diff options
60 files changed, 1289 insertions, 328 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index 9784943b4c..461e60dbfc 100644 --- a/bgpd/bgp_addpath.c +++ b/bgpd/bgp_addpath.c @@ -406,9 +406,9 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi, } } - zlog_info("Resetting peer %s%s due to change in addpath config", + zlog_info("Resetting peer %s%pBP due to change in addpath config", CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) ? "group " : "", - peer->host); + peer); if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { group = peer->group; diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 17687e6252..3d93e8a1ac 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3889,7 +3889,10 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, stream_putc(s, attr->mp_nexthop_len); stream_put_ipv4(s, attr->nexthop.s_addr); } - default: + break; + case SAFI_UNSPEC: + case SAFI_MAX: + assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE"); break; } break; @@ -3940,17 +3943,24 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, break; case SAFI_FLOWSPEC: stream_putc(s, 0); /* no nexthop for flowspec */ - default: + break; + case SAFI_UNSPEC: + case SAFI_MAX: + assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE"); break; } break; - default: + case AFI_L2VPN: if (safi != SAFI_FLOWSPEC) flog_err( EC_BGP_ATTR_NH_SEND_LEN, "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d", peer->host, afi, safi, attr->mp_nexthop_len); break; + case AFI_UNSPEC: + case AFI_MAX: + assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here"); + break; } /* SNPA */ @@ -3964,7 +3974,12 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, uint32_t num_labels, bool addpath_capable, uint32_t addpath_tx_id, struct attr *attr) { - if (safi == SAFI_MPLS_VPN) { + switch (safi) { + case SAFI_UNSPEC: + case SAFI_MAX: + assert(!"Dev escape usage of SAFI_UNSPEC or MAX"); + break; + case SAFI_MPLS_VPN: if (addpath_capable) stream_putl(s, addpath_tx_id); /* Label, RD, Prefix write. */ @@ -3972,35 +3987,74 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, stream_put(s, label, BGP_LABEL_BYTES); stream_put(s, prd->val, 8); stream_put(s, &p->u.prefix, PSIZE(p->prefixlen)); - } else if (afi == AFI_L2VPN && safi == SAFI_EVPN) { - /* EVPN prefix - contents depend on type */ - bgp_evpn_encode_prefix(s, p, prd, label, num_labels, attr, - addpath_capable, addpath_tx_id); - } else if (safi == SAFI_LABELED_UNICAST) { + break; + case SAFI_EVPN: + if (afi == AFI_L2VPN) + /* EVPN prefix - contents depend on type */ + bgp_evpn_encode_prefix(s, p, prd, label, num_labels, + attr, addpath_capable, + addpath_tx_id); + else + assert(!"Add encoding bits here for other AFI's"); + break; + case SAFI_LABELED_UNICAST: /* Prefix write with label. */ stream_put_labeled_prefix(s, p, label, addpath_capable, addpath_tx_id); - } else if (safi == SAFI_FLOWSPEC) { + break; + case SAFI_FLOWSPEC: stream_putc(s, p->u.prefix_flowspec.prefixlen); stream_put(s, (const void *)p->u.prefix_flowspec.ptr, p->u.prefix_flowspec.prefixlen); - } else + break; + + case SAFI_UNICAST: + case SAFI_MULTICAST: stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id); + break; + case SAFI_ENCAP: + assert(!"Please add proper encoding of SAFI_ENCAP"); + break; + } } size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi, const struct prefix *p) { int size = PSIZE(p->prefixlen); - if (safi == SAFI_MPLS_VPN) + + switch (safi) { + case SAFI_UNSPEC: + case SAFI_MAX: + assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE"); + break; + case SAFI_UNICAST: + case SAFI_MULTICAST: + break; + case SAFI_MPLS_VPN: size += 88; - else if (safi == SAFI_LABELED_UNICAST) + break; + case SAFI_ENCAP: + /* This has to be wrong, but I don't know what to put here */ + assert(!"Do we try to use this?"); + break; + case SAFI_LABELED_UNICAST: size += BGP_LABEL_BYTES; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - size += 232; // TODO: Maximum possible for type-2, type-3 and - // type-5 - else if (safi == SAFI_FLOWSPEC) + break; + case SAFI_EVPN: + /* + * TODO: Maximum possible for type-2, type-3 and type-5 + */ + if (afi == AFI_L2VPN) + size += 232; + else + assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values"); + break; + case SAFI_FLOWSPEC: size = ((struct prefix_fs *)p)->prefix.prefixlen; + break; + } + return size; } @@ -4641,7 +4695,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* AIGP */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) && + if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) && (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) || peer->sort != BGP_PEER_EBGP)) { /* At the moment only AIGP Metric TLV exists for AIGP diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index bfde1c127e..9e540b63cb 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -51,6 +51,8 @@ #include "bgpd/bgp_flowspec.h" #include "bgpd/bgp_packet.h" +#include "bgpd/bgp_debug_clippy.c" + unsigned long conf_bgp_debug_as4; unsigned long conf_bgp_debug_neighbor_events; unsigned long conf_bgp_debug_events; @@ -324,7 +326,7 @@ static void bgp_debug_list_add_entry(struct list *list, const char *host, } static bool bgp_debug_list_remove_entry(struct list *list, const char *host, - struct prefix *p) + const struct prefix *p) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; @@ -630,17 +632,14 @@ static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, } static int bgp_debug_parse_evpn_prefix(struct vty *vty, struct cmd_token **argv, - int argc, struct prefix **argv_pp) + int argc, struct prefix *argv_p) { - struct prefix *argv_p; struct ethaddr mac = {}; struct ipaddr ip = {}; int evpn_type = 0; int mac_idx = 0; int ip_idx = 0; - argv_p = *argv_pp; - if (bgp_evpn_cli_parse_type(&evpn_type, argv, argc) < 0) return CMD_WARNING; @@ -1023,49 +1022,42 @@ DEFUN (no_debug_bgp_keepalive_peer, } /* debug bgp bestpath */ -DEFUN (debug_bgp_bestpath_prefix, +DEFPY (debug_bgp_bestpath_prefix, debug_bgp_bestpath_prefix_cmd, - "debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>", + "debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>$prefix", DEBUG_STR BGP_STR "BGP bestpath\n" "IPv4 prefix\n" "IPv6 prefix\n") { - struct prefix *argv_p; - int idx_ipv4_ipv6_prefixlen = 3; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); - if (!bgp_debug_bestpath_prefixes) bgp_debug_bestpath_prefixes = list_new(); if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, - argv_p)) { + prefix)) { vty_out(vty, "BGP bestpath debugging is already enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, argv_p); + bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, prefix); if (vty->node == CONFIG_NODE) { DEBUG_ON(bestpath, BESTPATH); } else { TERM_DEBUG_ON(bestpath, BESTPATH); vty_out(vty, "BGP bestpath debugging is on for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); } return CMD_SUCCESS; } -DEFUN (no_debug_bgp_bestpath_prefix, +DEFPY (no_debug_bgp_bestpath_prefix, no_debug_bgp_bestpath_prefix_cmd, - "no debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>", + "no debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>$prefix", NO_STR DEBUG_STR BGP_STR @@ -1073,18 +1065,12 @@ DEFUN (no_debug_bgp_bestpath_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - int found_prefix = 0; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); + bool found_prefix = false; if (bgp_debug_bestpath_prefixes && !list_isempty(bgp_debug_bestpath_prefixes)) { found_prefix = bgp_debug_list_remove_entry( - bgp_debug_bestpath_prefixes, NULL, argv_p); + bgp_debug_bestpath_prefixes, NULL, prefix); if (list_isempty(bgp_debug_bestpath_prefixes)) { if (vty->node == CONFIG_NODE) { @@ -1099,10 +1085,10 @@ DEFUN (no_debug_bgp_bestpath_prefix, if (found_prefix) vty_out(vty, "BGP bestpath debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); else vty_out(vty, "BGP bestpath debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } @@ -1410,8 +1396,6 @@ DEFUN (no_debug_bgp_update_direct_peer, return CMD_SUCCESS; } -#include "bgpd/bgp_debug_clippy.c" - DEFPY (debug_bgp_update_prefix_afi_safi, debug_bgp_update_prefix_afi_safi_cmd, "debug bgp updates prefix l2vpn$afi evpn$safi type <<macip|2> mac <X:X:X:X:X:X|X:X:X:X:X:X/M> [ip <A.B.C.D|X:X::X:X>]|<multicast|3> ip <A.B.C.D|X:X::X:X>|<prefix|5> ip <A.B.C.D/M|X:X::X:X/M>>", @@ -1439,39 +1423,33 @@ DEFPY (debug_bgp_update_prefix_afi_safi, "IPv4 prefix\n" "IPv6 prefix\n") { - struct prefix *argv_p; + struct prefix argv_p; int ret = CMD_SUCCESS; - argv_p = prefix_new(); - ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); - if (ret != CMD_SUCCESS) { - prefix_free(&argv_p); + if (ret != CMD_SUCCESS) return ret; - } if (!bgp_debug_update_prefixes) bgp_debug_update_prefixes = list_new(); - if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) { + if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, + &argv_p)) { vty_out(vty, "BGP updates debugging is already enabled for %pFX\n", - argv_p); - prefix_free(&argv_p); + &argv_p); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); + bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, &argv_p); if (vty->node == CONFIG_NODE) { DEBUG_ON(update, UPDATE_PREFIX); } else { TERM_DEBUG_ON(update, UPDATE_PREFIX); - vty_out(vty, "BGP updates debugging is on for %pFX\n", argv_p); + vty_out(vty, "BGP updates debugging is on for %pFX\n", &argv_p); } - prefix_free(&argv_p); - return CMD_SUCCESS; } @@ -1503,22 +1481,18 @@ DEFPY (no_debug_bgp_update_prefix_afi_safi, "IPv4 prefix\n" "IPv6 prefix\n") { - struct prefix *argv_p; + struct prefix argv_p; bool found_prefix = false; int ret = CMD_SUCCESS; - argv_p = prefix_new(); - ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p); - if (ret != CMD_SUCCESS) { - prefix_free(&argv_p); + if (ret != CMD_SUCCESS) return ret; - } if (bgp_debug_update_prefixes && !list_isempty(bgp_debug_update_prefixes)) { found_prefix = bgp_debug_list_remove_entry( - bgp_debug_update_prefixes, NULL, argv_p); + bgp_debug_update_prefixes, NULL, &argv_p); if (list_isempty(bgp_debug_update_prefixes)) { if (vty->node == CONFIG_NODE) { @@ -1532,20 +1506,19 @@ DEFPY (no_debug_bgp_update_prefix_afi_safi, } if (found_prefix) - vty_out(vty, "BGP updates debugging is off for %pFX\n", argv_p); + vty_out(vty, "BGP updates debugging is off for %pFX\n", + &argv_p); else vty_out(vty, "BGP updates debugging was not enabled for %pFX\n", - argv_p); - - prefix_free(&argv_p); + &argv_p); return ret; } -DEFUN (debug_bgp_update_prefix, +DEFPY (debug_bgp_update_prefix, debug_bgp_update_prefix_cmd, - "debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>", + "debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>$prefix", DEBUG_STR BGP_STR "BGP updates\n" @@ -1553,39 +1526,32 @@ DEFUN (debug_bgp_update_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); - if (!bgp_debug_update_prefixes) bgp_debug_update_prefixes = list_new(); - if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) { + if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, prefix)) { vty_out(vty, "BGP updates debugging is already enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); + bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, prefix); if (vty->node == CONFIG_NODE) { DEBUG_ON(update, UPDATE_PREFIX); } else { TERM_DEBUG_ON(update, UPDATE_PREFIX); vty_out(vty, "BGP updates debugging is on for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); } return CMD_SUCCESS; } -DEFUN (no_debug_bgp_update_prefix, +DEFPY (no_debug_bgp_update_prefix, no_debug_bgp_update_prefix_cmd, - "no debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>", + "no debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>$prefix", NO_STR DEBUG_STR BGP_STR @@ -1594,18 +1560,12 @@ DEFUN (no_debug_bgp_update_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 5; - struct prefix *argv_p; - int found_prefix = 0; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); + bool found_prefix = false; if (bgp_debug_update_prefixes && !list_isempty(bgp_debug_update_prefixes)) { found_prefix = bgp_debug_list_remove_entry( - bgp_debug_update_prefixes, NULL, argv_p); + bgp_debug_update_prefixes, NULL, prefix); if (list_isempty(bgp_debug_update_prefixes)) { if (vty->node == CONFIG_NODE) { @@ -1620,10 +1580,10 @@ DEFUN (no_debug_bgp_update_prefix, if (found_prefix) vty_out(vty, "BGP updates debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); else vty_out(vty, "BGP updates debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } @@ -1693,9 +1653,9 @@ DEFUN (debug_bgp_graceful_restart, } -DEFUN (debug_bgp_zebra_prefix, +DEFPY (debug_bgp_zebra_prefix, debug_bgp_zebra_prefix_cmd, - "debug bgp zebra prefix <A.B.C.D/M|X:X::X:X/M>", + "debug bgp zebra prefix <A.B.C.D/M|X:X::X:X/M>$prefix", DEBUG_STR BGP_STR "BGP Zebra messages\n" @@ -1703,30 +1663,22 @@ DEFUN (debug_bgp_zebra_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); - if (!bgp_debug_zebra_prefixes) bgp_debug_zebra_prefixes = list_new(); - if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p)) { + if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, prefix)) { vty_out(vty, "BGP zebra debugging is already enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p); + bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, prefix); if (vty->node == CONFIG_NODE) DEBUG_ON(zebra, ZEBRA); else { TERM_DEBUG_ON(zebra, ZEBRA); - vty_out(vty, "BGP zebra debugging is on for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + vty_out(vty, "BGP zebra debugging is on for %s\n", prefix_str); } return CMD_SUCCESS; @@ -1768,9 +1720,9 @@ DEFUN (no_debug_bgp_graceful_restart, return CMD_SUCCESS; } -DEFUN (no_debug_bgp_zebra_prefix, +DEFPY (no_debug_bgp_zebra_prefix, no_debug_bgp_zebra_prefix_cmd, - "no debug bgp zebra prefix <A.B.C.D/M|X:X::X:X/M>", + "no debug bgp zebra prefix <A.B.C.D/M|X:X::X:X/M>$prefix", NO_STR DEBUG_STR BGP_STR @@ -1779,18 +1731,12 @@ DEFUN (no_debug_bgp_zebra_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 5; - struct prefix *argv_p; - int found_prefix = 0; - - argv_p = prefix_new(); - (void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - apply_mask(argv_p); + bool found_prefix = false; if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes)) { found_prefix = bgp_debug_list_remove_entry( - bgp_debug_zebra_prefixes, NULL, argv_p); + bgp_debug_zebra_prefixes, NULL, prefix); if (list_isempty(bgp_debug_zebra_prefixes)) { if (vty->node == CONFIG_NODE) @@ -1803,11 +1749,10 @@ DEFUN (no_debug_bgp_zebra_prefix, } if (found_prefix) - vty_out(vty, "BGP zebra debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + vty_out(vty, "BGP zebra debugging is off for %s\n", prefix_str); else vty_out(vty, "BGP zebra debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); + prefix_str); return CMD_SUCCESS; } diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 65de35cbdb..923586f633 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1245,7 +1245,7 @@ static void bgp_update_delay_process_status_change(struct peer *peer) /* Called after event occurred, this function change status and reset read/write and timer thread. */ -void bgp_fsm_change_status(struct peer *peer, int status) +void bgp_fsm_change_status(struct peer *peer, enum bgp_fsm_status status) { struct bgp *bgp; uint32_t peer_count; diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 368c2c5001..6418e15b9a 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -125,7 +125,8 @@ extern int bgp_event_update(struct peer *, enum bgp_fsm_events event); extern int bgp_stop(struct peer *peer); extern void bgp_timer_set(struct peer *); extern void bgp_routeadv_timer(struct thread *); -extern void bgp_fsm_change_status(struct peer *peer, int status); +extern void bgp_fsm_change_status(struct peer *peer, + enum bgp_fsm_status status); extern const char *const peer_down_str[]; extern void bgp_update_delay_end(struct bgp *); extern void bgp_maxmed_update(struct bgp *); diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c index 467a33694a..fe0c33251e 100644 --- a/bgpd/bgp_snmp_bgp4v2.c +++ b/bgpd/bgp_snmp_bgp4v2.c @@ -145,10 +145,24 @@ static struct peer *bgpv2PeerTable_lookup(struct variable *v, oid name[], size_t namelen = v ? v->namelen : BGP4V2_PEER_ENTRY_OFFSET; oid *offset = name + namelen; sa_family_t family = name[namelen - 1] == 4 ? AF_INET : AF_INET6; + int afi_len = IN_ADDR_SIZE; + size_t offsetlen = *length - namelen; + + if (family == AF_INET6) + afi_len = IN6_ADDR_SIZE; + + /* Somehow with net-snmp 5.7.3, every OID item in an array + * is uninitialized and has a max random value, let's zero it. + * With 5.8, 5.9, it works fine even without this hack. + */ + if (!offsetlen) { + for (int i = 0; i < afi_len; i++) + *(offset + i) = 0; + } if (exact) { if (family == AF_INET) { - oid2in_addr(offset, IN_ADDR_SIZE, &addr->ip._v4_addr); + oid2in_addr(offset, afi_len, &addr->ip._v4_addr); peer = peer_lookup_all_vrf(addr); return peer; } else if (family == AF_INET6) { @@ -163,11 +177,11 @@ static struct peer *bgpv2PeerTable_lookup(struct variable *v, oid name[], switch (sockunion_family(&peer->su)) { case AF_INET: oid_copy_in_addr(offset, &peer->su.sin.sin_addr); - *length = IN_ADDR_SIZE + namelen; + *length = afi_len + namelen; return peer; case AF_INET6: oid_copy_in6_addr(offset, &peer->su.sin6.sin6_addr); - *length = IN6_ADDR_SIZE + namelen; + *length = afi_len + namelen; return peer; default: break; @@ -367,9 +381,10 @@ static uint8_t *bgpv2PeerErrorsTable(struct variable *v, oid name[], } return SNMP_STRING(""); case BGP4V2_PEER_LAST_ERROR_SENT_DATA: - if (peer->last_reset == PEER_DOWN_NOTIFY_SEND || - peer->last_reset == PEER_DOWN_RTT_SHUTDOWN || - peer->last_reset == PEER_DOWN_USER_SHUTDOWN) + if ((peer->last_reset == PEER_DOWN_NOTIFY_SEND || + peer->last_reset == PEER_DOWN_RTT_SHUTDOWN || + peer->last_reset == PEER_DOWN_USER_SHUTDOWN) && + peer->notify.data) return SNMP_STRING(peer->notify.data); else return SNMP_STRING(""); @@ -420,7 +435,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, { oid *offset; int offsetlen; - struct bgp_path_info *path; + struct bgp_path_info *path, *min; struct bgp_dest *dest; union sockunion su; unsigned int len; @@ -500,6 +515,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, else addr->prefixlen = len * 8; + addr->family = family; + dest = bgp_node_get(bgp->rib[afi][SAFI_UNICAST], addr); offset++; @@ -525,8 +542,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, if (!dest) return NULL; - while ((dest = bgp_route_next(dest))) { - struct bgp_path_info *min = NULL; + do { + min = NULL; for (path = bgp_dest_get_bgp_path_info(dest); path; path = path->next) { @@ -564,6 +581,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, offset = name + namelen; + /* Encode prefix into OID */ if (family == AF_INET) oid_copy_in_addr(offset, &rn_p->u.prefix4); else @@ -573,6 +591,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, *offset = rn_p->prefixlen; offset++; + /* Encode peer's IP into OID */ if (family == AF_INET) { oid_copy_in_addr(offset, &min->peer->su.sin.sin_addr); @@ -584,6 +603,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, } addr->prefixlen = rn_p->prefixlen; + addr->family = rn_p->family; bgp_dest_unlock_node(dest); @@ -594,7 +614,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, memset(&paddr.ip._v4_addr, 0, afi_len); else memset(&paddr.ip._v6_addr, 0, afi_len); - } + } while ((dest = bgp_route_next(dest))); return NULL; } @@ -735,7 +755,7 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[], case BGP4V2_NLRI_MED: if (CHECK_FLAG(path->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) - return SNMP_INTEGER(path->attr->local_pref); + return SNMP_INTEGER(path->attr->med); else return SNMP_INTEGER(0); case BGP4V2_NLRI_ATOMIC_AGGREGATE: diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 219362cd04..8ea9c1996b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -14693,7 +14693,7 @@ static int bgp_show_neighbor_graceful_restart(struct vty *vty, struct bgp *bgp, { struct listnode *node, *nnode; struct peer *peer; - int find = 0; + bool found = false; safi_t safi = SAFI_UNICAST; json_object *json_neighbor = NULL; @@ -14721,27 +14721,31 @@ static int bgp_show_neighbor_graceful_restart(struct vty *vty, struct bgp *bgp, && !strcmp(peer->conf_if, conf_if)) || (peer->hostname && !strcmp(peer->hostname, conf_if))) { - find = 1; + found = true; bgp_show_peer_gr_status(vty, peer, json_neighbor); } } else { if (sockunion_same(&peer->su, su)) { - find = 1; + found = true; bgp_show_peer_gr_status(vty, peer, json_neighbor); } } - if (json && find) - json_object_object_add(json, peer->host, - json_neighbor); + if (json) { + if (found) + json_object_object_add(json, peer->host, + json_neighbor); + else + json_object_free(json_neighbor); + } } - if (find) + if (found) break; } - if (type == show_peer && !find) { + if (type == show_peer && !found) { if (json) json_object_boolean_true_add(json, "bgpNoSuchNeighbor"); else diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 952b8fcc56..f6e7b444c6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1589,7 +1589,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api_nh->weight = nh_weight; - if (mpinfo->extra && !sid_zero(&mpinfo->extra->sid[0].sid) && + if (mpinfo->extra && + bgp_is_valid_label(&mpinfo->extra->label[0]) && + !sid_zero(&mpinfo->extra->sid[0].sid) && !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { sid_info = &mpinfo->extra->sid[0]; @@ -1597,12 +1599,16 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, sizeof(api_nh->seg6_segs)); if (sid_info->transposition_len != 0) { - if (!bgp_is_valid_label( - &mpinfo->extra->label[0])) - continue; - mpls_lse_decode(mpinfo->extra->label[0], &label, &ttl, &exp, &bos); + + if (label < MPLS_LABEL_UNRESERVED_MIN) { + if (bgp_debug_zebra(&api.prefix)) + zlog_debug( + "skip invalid SRv6 routes: transposition scheme is used, but label is too small"); + continue; + } + transpose_sid(&api_nh->seg6_segs, label, sid_info->transposition_offset, sid_info->transposition_len); @@ -1683,9 +1689,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, zlog_debug( "Tx route %s VRF %u %pFX metric %u tag %" ROUTE_TAG_PRI " count %d nhg %d", - valid_nh_count ? "add" : "delete", bgp->vrf_id, - &api.prefix, api.metric, api.tag, api.nexthop_num, - nhg_id); + is_add ? "add" : "delete", bgp->vrf_id, &api.prefix, + api.metric, api.tag, api.nexthop_num, nhg_id); for (i = 0; i < api.nexthop_num; i++) { api_nh = &api.nexthops[i]; diff --git a/debian/changelog b/debian/changelog index ad43f13e33..e3b6634594 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,11 +4,11 @@ frr (8.5~dev-1) UNRELEASED; urgency=medium -- Donatas Abraitis <donatas@opensourcerouting.org> Tue, 04 Oct 2022 16:00:00 +0500 -frr (8.4~dev-1) UNRELEASED; urgency=medium +frr (8.4-0) unstable; urgency=medium - * FRR Dev 8.4 + * New upstream release FRR 8.4 - -- Jafar Al-Gharaibeh <jafar@atcorp.com> Wed, 20 Jul 2022 10:00:00 +0500 + -- Jafar Al-Gharaibeh <jafar@atcorp.com> Tue, 01 Nov 2022 10:00:00 +0500 frr (8.3-0) unstable; urgency=medium diff --git a/doc/user/evpn.rst b/doc/user/evpn.rst index 0737ab6f07..c8052803cc 100644 --- a/doc/user/evpn.rst +++ b/doc/user/evpn.rst @@ -441,7 +441,7 @@ Here a traditional ``vxlan`` interface is created with the name "vni100" which uses a VTEP-IP of 100.64.0.1, carries VNI 100, and has Dynamic VTEP learning disabled. IPv6 address autoconfiguration is disabled for "vni100", then the interface is enslaved to "br100", ARP/ND suppression is enabled, and Dynamic -VTEP Learning is disabled. +MAC Learning is disabled. .. code-block:: shell diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 69c1c18d3c..0dff2ea448 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -831,6 +831,13 @@ Showing Information Show the OSPF routing table, as determined by the most recent SPF calculation. +.. clicmd:: show ip ospf [vrf <NAME|all>] border-routers [json] + + Show the list of ABR and ASBR border routers summary learnt via + OSPFv2 Type-3 (Summary LSA) and Type-4 (Summary ASBR LSA). + User can get that information as JSON format when ``json`` keyword + at the end of cli is presented. + .. clicmd:: show ip ospf (1-65535) route orr [NAME] .. clicmd:: show ip ospf [vrf <NAME|all>] route orr [NAME] diff --git a/doc/user/snmp.rst b/doc/user/snmp.rst index b9058cc0d3..0bf3565b2e 100644 --- a/doc/user/snmp.rst +++ b/doc/user/snmp.rst @@ -115,6 +115,65 @@ Then, you can use the following command to check everything works as expected: OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109 [...] +An example below is how to query SNMP for BGP: + + .. code-block:: shell + + $ # BGP4-MIB (https://www.circitor.fr/Mibs/Mib/B/BGP4-MIB.mib) + $ snmpwalk -c public -v2c -On -Ln localhost .1.3.6.1.2.1.15 + + $ # BGP4V2-MIB (http://www.circitor.fr/Mibs/Mib/B/BGP4V2-MIB.mib) + $ # Information about the peers (bgp4V2PeerTable): + $ snmpwalk -c public -v2c -On -Ln localhost .1.3.6.1.3.5.1.1.2 + ... + .1.3.6.1.3.5.1.1.2.1.1.1.4.192.168.10.124 = Gauge32: 0 + .1.3.6.1.3.5.1.1.2.1.1.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 0 + .1.3.6.1.3.5.1.1.2.1.2.1.4.192.168.10.124 = INTEGER: 1 + .1.3.6.1.3.5.1.1.2.1.2.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.3.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.3.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 01 + .1.3.6.1.3.5.1.1.2.1.4.1.4.192.168.10.124 = INTEGER: 1 + .1.3.6.1.3.5.1.1.2.1.4.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.5.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 7C + .1.3.6.1.3.5.1.1.2.1.5.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 02 + .1.3.6.1.3.5.1.1.2.1.6.1.4.192.168.10.124 = Gauge32: 179 + .1.3.6.1.3.5.1.1.2.1.6.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 179 + .1.3.6.1.3.5.1.1.2.1.7.1.4.192.168.10.124 = Gauge32: 65002 + .1.3.6.1.3.5.1.1.2.1.7.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65002 + .1.3.6.1.3.5.1.1.2.1.8.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.8.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.9.1.4.192.168.10.124 = Gauge32: 41894 + .1.3.6.1.3.5.1.1.2.1.9.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 39960 + .1.3.6.1.3.5.1.1.2.1.10.1.4.192.168.10.124 = Gauge32: 65001 + .1.3.6.1.3.5.1.1.2.1.10.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65001 + .1.3.6.1.3.5.1.1.2.1.11.1.4.192.168.10.124 = Hex-STRING: C8 C8 C8 CA + .1.3.6.1.3.5.1.1.2.1.11.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C8 C8 C8 CA + .1.3.6.1.3.5.1.1.2.1.12.1.4.192.168.10.124 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.12.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.13.1.4.192.168.10.124 = INTEGER: 6 + .1.3.6.1.3.5.1.1.2.1.13.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 6 + + $ # Information about the BGP table (bgp4V2NlriTable): + $ snmpwalk -c public -v2c -On -Ln localhost .1.3.6.1.3.5.1.1.9 + ... + .1.3.6.1.3.5.1.1.9.1.22.1.4.10.0.2.0.24.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.10.10.100.0.24.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.1.32.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.2.32.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.3.32.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.0.0.24.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.1.0.24.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.10.0.24.192.168.10.124 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.0.64.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.24.1.4.10.0.2.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.10.10.100.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.1.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.2.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.3.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.0.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.1.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.10.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.0.64.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 02 01 FD E9 The AgentX protocol can be transported over a Unix socket or using TCP or UDP. It usually defaults to a Unix socket and depends on how NetSNMP was built. If @@ -132,5 +191,7 @@ Here is the syntax for using AgentX: .. clicmd:: agentx + Once enabled, it can't be unconfigured. Only removing from the daemons file + the keyword ``agentx`` takes an effect. .. include:: snmptrap.rst diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 3608f828e8..c05a29af4e 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -309,6 +309,15 @@ the default route. User can get that information as JSON string when ``json`` key word at the end of cli is presented. +.. clicmd:: show ip nht route-map [vrf <NAME|all>] [json] + + This command displays route-map attach point to nexthop tracking and + displays list of protocol with its applied route-map. + When zebra considers sending NHT resoultion, the nofification only + sent to appropriate client protocol only after applying route-map filter. + User can get that information as JSON format when ``json`` keyword + at the end of cli is presented. + PBR dataplane programming ========================= diff --git a/lib/agentx.c b/lib/agentx.c index 6c2923fcf8..5f62459805 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -32,13 +32,15 @@ #include "linklist.h" #include "lib/version.h" #include "lib_errors.h" +#include "hook.h" +#include "libfrr.h" #include "xref.h" XREF_SETUP(); DEFINE_HOOK(agentx_enabled, (), ()); -static int agentx_enabled = 0; +static bool agentx_enabled = false; static struct thread_master *agentx_tm; static struct thread *timeout_thr = NULL; @@ -226,7 +228,7 @@ DEFUN (agentx_enable, init_snmp(FRR_SMUX_NAME); events = list_new(); agentx_events_update(); - agentx_enabled = 1; + agentx_enabled = true; hook_call(agentx_enabled); } @@ -245,7 +247,14 @@ DEFUN (no_agentx, return CMD_WARNING_CONFIG_FAILED; } -int smux_enabled(void) +static int smux_disable(void) +{ + agentx_enabled = false; + + return 0; +} + +bool smux_enabled(void) { return agentx_enabled; } @@ -264,6 +273,8 @@ void smux_init(struct thread_master *tm) install_node(&agentx_node); install_element(CONFIG_NODE, &agentx_enable_cmd); install_element(CONFIG_NODE, &no_agentx_cmd); + + hook_register(frr_early_fini, smux_disable); } void smux_agentx_enable(void) @@ -272,7 +283,7 @@ void smux_agentx_enable(void) init_snmp(FRR_SMUX_NAME); events = list_new(); agentx_events_update(); - agentx_enabled = 1; + agentx_enabled = true; } } diff --git a/lib/smux.h b/lib/smux.h index 48c3374236..1d73406a28 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -109,7 +109,10 @@ struct index_oid { #define SNMP_IP6ADDRESS(V) (*var_len = sizeof(struct in6_addr), (uint8_t *)&V) -extern int smux_enabled(void); +/* + * Check to see if snmp is enabled or not + */ +extern bool smux_enabled(void); extern void smux_init(struct thread_master *tm); extern void smux_agentx_enable(void); diff --git a/lib/srv6.c b/lib/srv6.c index 5cd82080f5..f4077a86d2 100644 --- a/lib/srv6.c +++ b/lib/srv6.c @@ -121,6 +121,13 @@ const char *seg6local_context2str(char *str, size_t size, } } +static void srv6_locator_chunk_list_free(void *data) +{ + struct srv6_locator_chunk *chunk = data; + + srv6_locator_chunk_free(&chunk); +} + struct srv6_locator *srv6_locator_alloc(const char *name) { struct srv6_locator *locator = NULL; @@ -128,7 +135,7 @@ struct srv6_locator *srv6_locator_alloc(const char *name) locator = XCALLOC(MTYPE_SRV6_LOCATOR, sizeof(struct srv6_locator)); strlcpy(locator->name, name, sizeof(locator->name)); locator->chunks = list_new(); - locator->chunks->del = (void (*)(void *))srv6_locator_chunk_free; + locator->chunks->del = srv6_locator_chunk_list_free; QOBJ_REG(locator, srv6_locator); return locator; diff --git a/lib/workqueue.c b/lib/workqueue.c index c703de90b3..a5338ba78b 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -272,9 +272,6 @@ void work_queue_run(struct thread *thread) /* dont run items which are past their allowed retries */ if (item->ran > wq->spec.max_retries) { - /* run error handler, if any */ - if (wq->spec.errorfunc) - wq->spec.errorfunc(wq, item); work_queue_item_remove(wq, item); continue; } @@ -317,10 +314,6 @@ void work_queue_run(struct thread *thread) case WQ_RETRY_NOW: /* a RETRY_NOW that gets here has exceeded max_tries, same as * ERROR */ - case WQ_ERROR: { - if (wq->spec.errorfunc) - wq->spec.errorfunc(wq, item); - } /* fallthru */ case WQ_SUCCESS: default: { diff --git a/lib/workqueue.h b/lib/workqueue.h index 27fb1383eb..7866032fc0 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -41,7 +41,6 @@ DECLARE_MTYPE(WORK_QUEUE); /* action value, for use by item processor and item error handlers */ typedef enum { WQ_SUCCESS = 0, - WQ_ERROR, /* Error, run error handler if provided */ WQ_RETRY_NOW, /* retry immediately */ WQ_RETRY_LATER, /* retry later, cease processing work queue */ WQ_REQUEUE, /* requeue item, continue processing work queue */ @@ -80,10 +79,6 @@ struct work_queue { */ wq_item_status (*workfunc)(struct work_queue *, void *); - /* error handling function, optional */ - void (*errorfunc)(struct work_queue *, - struct work_queue_item *); - /* callback to delete user specific item data */ void (*del_item_data)(struct work_queue *, void *); diff --git a/lib/zlog_targets.c b/lib/zlog_targets.c index 31bd8e16eb..f7ea48bf9d 100644 --- a/lib/zlog_targets.c +++ b/lib/zlog_targets.c @@ -257,6 +257,7 @@ bool zlog_file_set_filename(struct zlog_cfg_file *zcf, const char *filename) return zlog_file_cycle(zcf); } assert(0); + return false; } bool zlog_file_set_fd(struct zlog_cfg_file *zcf, int fd) @@ -271,6 +272,7 @@ bool zlog_file_set_fd(struct zlog_cfg_file *zcf, int fd) return zlog_file_cycle(zcf); } assert(0); + return false; } struct rcu_close_rotate { @@ -544,6 +546,7 @@ int zlog_syslog_get_facility(void) return syslog_facility; } assert(0); + return 0; } void zlog_syslog_set_prio_min(int prio_min) @@ -581,4 +584,5 @@ int zlog_syslog_get_prio_min(void) return syslog_prio_min; } assert(0); + return 0; } diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 07061b6f57..0fd6e15ed6 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1585,7 +1585,11 @@ ospf6_asbr_summary_remove_lsa_and_route(struct ospf6 *ospf6, zlog_debug( "%s: Remove the blackhole route", __func__); + ospf6_zebra_route_update_remove(aggr->route, ospf6); + if (aggr->route->route_option) + XFREE(MTYPE_OSPF6_EXTERNAL_INFO, + aggr->route->route_option); ospf6_route_delete(aggr->route); aggr->route = NULL; } @@ -2736,8 +2740,13 @@ ospf6_summary_add_aggr_route_and_blackhole(struct ospf6 *ospf6, struct ospf6_external_aggr_rt *aggr) { struct ospf6_route *rt_aggr; + struct ospf6_route *old_rt = NULL; struct ospf6_external_info *info; + /* Check if a route is already present. */ + if (aggr->route) + old_rt = aggr->route; + /* Create summary route and save it. */ rt_aggr = ospf6_route_create(ospf6); rt_aggr->type = OSPF6_DEST_TYPE_NETWORK; @@ -2756,6 +2765,16 @@ ospf6_summary_add_aggr_route_and_blackhole(struct ospf6 *ospf6, /* Add next-hop to Null interface. */ ospf6_add_route_nexthop_blackhole(rt_aggr); + /* Free the old route, if any. */ + if (old_rt) { + ospf6_zebra_route_update_remove(old_rt, ospf6); + + if (old_rt->route_option) + XFREE(MTYPE_OSPF6_EXTERNAL_INFO, old_rt->route_option); + + ospf6_route_delete(old_rt); + } + ospf6_zebra_route_update_add(rt_aggr, ospf6); } @@ -3024,8 +3043,8 @@ static void ospf6_aggr_handle_external_info(void *data) (void)ospf6_originate_type5_type7_lsas(rt, ospf6); } -static void -ospf6_asbr_summary_config_delete(struct ospf6 *ospf6, struct route_node *rn) +void ospf6_asbr_summary_config_delete(struct ospf6 *ospf6, + struct route_node *rn) { struct ospf6_external_aggr_rt *aggr = rn->info; @@ -3167,14 +3186,6 @@ void ospf6_external_aggregator_free(struct ospf6_external_aggr_rt *aggr) hash_clean(aggr->match_extnl_hash, ospf6_aggr_unlink_external_info); - if (aggr->route) { - if (aggr->route->route_option) - XFREE(MTYPE_OSPF6_EXTERNAL_INFO, - aggr->route->route_option); - - ospf6_route_delete(aggr->route); - } - if (IS_OSPF6_DEBUG_AGGR) zlog_debug("%s: Release the aggregator Address(%pFX)", __func__, diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index 0487bb14c3..0d2a98aeba 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -182,4 +182,6 @@ void ospf6_external_aggregator_free(struct ospf6_external_aggr_rt *aggr); void ospf6_unset_all_aggr_flag(struct ospf6 *ospf6); void ospf6_fill_aggr_route_details(struct ospf6 *ospf6, struct ospf6_external_aggr_rt *aggr); +void ospf6_asbr_summary_config_delete(struct ospf6 *ospf6, + struct route_node *rn); #endif /* OSPF6_ASBR_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 1c045cba07..d3dd5501a4 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -303,6 +303,9 @@ void ospf6_interface_delete(struct ospf6_interface *oi) /* disable from area list if possible */ ospf6_area_interface_delete(oi); + if (oi->at_data.auth_key) + XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key); + /* Free BFD allocated data. */ XFREE(MTYPE_TMP, oi->bfd_config.profile); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 360a9db0d6..fb54ebab15 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -2015,6 +2015,9 @@ static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface *oi) * these values */ oi->at_data.hash_algo = key->hash_algo; + if (oi->at_data.auth_key) + XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, + oi->at_data.auth_key); oi->at_data.auth_key = XSTRDUP( MTYPE_OSPF6_AUTH_MANUAL_KEY, key->string); oi->at_data.key_id = key->index; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 439b94c9af..a4ba1fb569 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -106,6 +106,23 @@ struct ospf6_neighbor *ospf6_area_neighbor_lookup(struct ospf6_area *area, return NULL; } +static void ospf6_neighbor_clear_ls_lists(struct ospf6_neighbor *on) +{ + struct ospf6_lsa *lsa; + struct ospf6_lsa *lsanext; + + ospf6_lsdb_remove_all(on->summary_list); + if (on->last_ls_req) { + ospf6_lsa_unlock(on->last_ls_req); + on->last_ls_req = NULL; + } + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } +} + /* create ospf6_neighbor */ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, struct ospf6_interface *oi) @@ -147,14 +164,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, void ospf6_neighbor_delete(struct ospf6_neighbor *on) { - struct ospf6_lsa *lsa, *lsanext; - - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); ospf6_lsdb_remove_all(on->dbdesc_list); ospf6_lsdb_remove_all(on->lsupdate_list); @@ -339,12 +349,7 @@ void negotiation_done(struct thread *thread) zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name); /* clear ls-list */ - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); /* Interface scoped LSAs */ for (ALL_LSDB(on->ospf6_if->lsdb, lsa, lsanext)) { @@ -464,7 +469,6 @@ void loading_done(struct thread *thread) void adj_ok(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa, *lsanext; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -486,19 +490,13 @@ void adj_ok(struct thread *thread) } else if (on->state >= OSPF6_NEIGHBOR_EXSTART && !need_adjacency(on)) { ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on, OSPF6_NEIGHBOR_EVENT_ADJ_OK); - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); } } void seqnumber_mismatch(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa, *lsanext; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -515,12 +513,7 @@ void seqnumber_mismatch(struct thread *thread) SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); THREAD_OFF(on->thread_send_dbdesc); on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ @@ -532,7 +525,6 @@ void seqnumber_mismatch(struct thread *thread) void bad_lsreq(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa, *lsanext; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -549,12 +541,7 @@ void bad_lsreq(struct thread *thread) SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); THREAD_OFF(on->thread_send_dbdesc); on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ @@ -567,7 +554,6 @@ void bad_lsreq(struct thread *thread) void oneway_received(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa, *lsanext; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -582,12 +568,7 @@ void oneway_received(struct thread *thread) OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD); thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); - ospf6_lsdb_remove_all(on->summary_list); - ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) { - ospf6_decrement_retrans_count(lsa); - ospf6_lsdb_remove(lsa, on->retrans_list); - } + ospf6_neighbor_clear_ls_lists(on); THREAD_OFF(on->thread_send_dbdesc); THREAD_OFF(on->thread_send_lsreq); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index eb89a14cd3..db45fa5f5c 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -498,6 +498,7 @@ void ospf6_delete(struct ospf6 *o) struct route_node *rn = NULL; struct ospf6_area *oa; struct vrf *vrf; + struct ospf6_external_aggr_rt *aggr; QOBJ_UNREG(o); @@ -536,8 +537,11 @@ void ospf6_delete(struct ospf6 *o) } for (rn = route_top(o->rt_aggr_tbl); rn; rn = route_next(rn)) - if (rn->info) - ospf6_external_aggregator_free(rn->info); + if (rn->info) { + aggr = rn->info; + ospf6_asbr_summary_config_delete(o, rn); + ospf6_external_aggregator_free(aggr); + } route_table_finish(o->rt_aggr_tbl); XFREE(MTYPE_OSPF6_TOP, o->name); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 4f60ce22a9..58fcbfa4a9 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -1956,9 +1956,10 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread) rt_time = monotime_since(&start_time, NULL); /* Free old all routers routing table */ - if (ospf->oall_rtrs) - /* ospf_route_delete (ospf->old_rtrs); */ + if (ospf->oall_rtrs) { ospf_rtrs_free(ospf->oall_rtrs); + ospf->oall_rtrs = NULL; + } /* Update all routers routing table */ ospf->oall_rtrs = ospf->all_rtrs; @@ -1967,9 +1968,10 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread) ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs); #endif /* Free old ABR/ASBR routing table */ - if (ospf->old_rtrs) - /* ospf_route_delete (ospf->old_rtrs); */ + if (ospf->old_rtrs) { ospf_rtrs_free(ospf->old_rtrs); + ospf->old_rtrs = NULL; + } /* Update ABR/ASBR routing table */ ospf->old_rtrs = ospf->new_rtrs; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 0bab045ef4..43b7de552a 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -6614,14 +6614,17 @@ static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, route_lock_node(start); for (rn = start; rn; rn = route_next_until(rn, start)) if ((lsa = rn->info)) { - if (json) { - json_lsa = json_object_new_object(); - json_object_array_add(json, json_lsa); - } + if (show_function[lsa->data->type] != NULL) { + if (json) { + json_lsa = + json_object_new_object(); + json_object_array_add(json, + json_lsa); + } - if (show_function[lsa->data->type] != NULL) show_function[lsa->data->type]( vty, lsa, json_lsa); + } } route_unlock_node(start); } @@ -6640,9 +6643,6 @@ static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, json_object *json_areas = NULL; json_object *json_lsa_array = NULL; - if (json) - json_lsa_type = json_object_new_object(); - switch (type) { case OSPF_AS_EXTERNAL_LSA: case OSPF_OPAQUE_AS_LSA: @@ -6685,6 +6685,7 @@ static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, } if (json) { + json_lsa_type = json_object_new_object(); json_object_object_add(json_lsa_type, "areas", json_areas); json_object_object_add(json, @@ -7158,6 +7159,9 @@ DEFUN (show_ip_ospf_database_max, vty_out(vty, "%% OSPF is not enabled in vrf %s\n", vrf_name); + if (uj) + json_object_free(json); + return CMD_SUCCESS; } ret = (show_ip_ospf_database_common( @@ -7169,6 +7173,9 @@ DEFUN (show_ip_ospf_database_max, ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { vty_out(vty, "%% OSPF is not enabled in vrf default\n"); + if (uj) + json_object_free(json); + return CMD_SUCCESS; } @@ -11209,15 +11216,37 @@ DEFUN (show_ip_ospf_instance_reachable_routers, static int show_ip_ospf_border_routers_common(struct vty *vty, struct ospf *ospf, - uint8_t use_vrf) + uint8_t use_vrf, + json_object *json) { - if (ospf->instance) - vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + json_object *json_vrf = NULL; + json_object *json_router = NULL; - ospf_show_vrf_name(ospf, vty, NULL, use_vrf); + if (json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + json_router = json_object_new_object(); + } + + if (ospf->instance) { + if (!json) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + else + json_object_int_add(json_vrf, "ospfInstance", + ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); if (ospf->new_table == NULL) { - vty_out(vty, "No OSPF routing information exist\n"); + if (!json) + vty_out(vty, "No OSPF routing information exist\n"); + else { + json_object_free(json_router); + json_object_free(json_vrf); + } return CMD_SUCCESS; } @@ -11225,22 +11254,35 @@ static int show_ip_ospf_border_routers_common(struct vty *vty, show_ip_ospf_route_network (vty, ospf->new_table); */ /* Show Router routes. */ - show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, NULL); + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, json_router); - vty_out(vty, "\n"); + if (json) { + json_object_object_add(json_vrf, "routers", json_router); + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } else { + vty_out(vty, "\n"); + } return CMD_SUCCESS; } -DEFUN (show_ip_ospf_border_routers, +DEFPY (show_ip_ospf_border_routers, show_ip_ospf_border_routers_cmd, - "show ip ospf [vrf <NAME|all>] border-routers", + "show ip ospf [vrf <NAME|all>] border-routers [json]", SHOW_STR IP_STR "OSPF information\n" VRF_CMD_HELP_STR "All VRFs\n" - "Show all the ABR's and ASBR's\n") + "Show all the ABR's and ASBR's\n" + JSON_STR) { struct ospf *ospf = NULL; struct listnode *node = NULL; @@ -11250,6 +11292,11 @@ DEFUN (show_ip_ospf_border_routers, int inst = 0; int idx_vrf = 0; uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); @@ -11265,32 +11312,47 @@ DEFUN (show_ip_ospf_border_routers, ospf_output = true; ret = show_ip_ospf_border_routers_common( - vty, ospf, use_vrf); + vty, ospf, use_vrf, json); } - if (!ospf_output) + if (uj) + vty_json(vty, json); + else if (!ospf_output) vty_out(vty, "%% OSPF is not enabled\n"); + + return ret; } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); if (ospf == NULL || !ospf->oi_running) { - vty_out(vty, - "%% OSPF is not enabled in vrf %s\n", - vrf_name); + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + return CMD_SUCCESS; } - - ret = show_ip_ospf_border_routers_common(vty, ospf, - use_vrf); } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { - vty_out(vty, "%% OSPF is not enabled in vrf default\n"); + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + return CMD_SUCCESS; } + } - ret = show_ip_ospf_border_routers_common(vty, ospf, use_vrf); + if (ospf) { + ret = show_ip_ospf_border_routers_common(vty, ospf, use_vrf, + json); + if (uj) + vty_json(vty, json); } return ret; @@ -11317,7 +11379,7 @@ DEFUN (show_ip_ospf_instance_border_routers, if (!ospf || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_border_routers_common(vty, ospf, 0); + return show_ip_ospf_border_routers_common(vty, ospf, 0, NULL); } static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 2403b567a5..a5d40ad176 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -852,6 +852,10 @@ static void ospf_finish_final(struct ospf *ospf) ospf_route_delete(ospf, ospf->new_table); ospf_route_table_free(ospf->new_table); } + if (ospf->oall_rtrs) + ospf_rtrs_free(ospf->oall_rtrs); + if (ospf->all_rtrs) + ospf_rtrs_free(ospf->all_rtrs); if (ospf->old_rtrs) ospf_rtrs_free(ospf->old_rtrs); if (ospf->new_rtrs) diff --git a/pathd/path_pcep_config.c b/pathd/path_pcep_config.c index 99b1c349a9..873b0ccd37 100644 --- a/pathd/path_pcep_config.c +++ b/pathd/path_pcep_config.c @@ -453,8 +453,7 @@ int path_pcep_config_update_path(struct path *path) } if (number_of_sid_clashed) - SET_FLAG(segment->segment_list->flags, - F_SEGMENT_LIST_SID_CONFLICT); + SET_FLAG(segment_list->flags, F_SEGMENT_LIST_SID_CONFLICT); else srte_apply_changes(); diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 3bfb31e0c6..dff1b4fed4 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -166,8 +166,8 @@ struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil, const char *name) { if (PIM_DEBUG_MROUTE) { - pim_sgaddr sg = {.src = *oil_mcastgrp(c_oil), - .grp = *oil_origin(c_oil)}; + pim_sgaddr sg = {.src = *oil_origin(c_oil), + .grp = *oil_mcastgrp(c_oil)}; zlog_debug( "%s(%s): Del oil for %pSG, Ref Count: %d (Predecrement)", diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 71e62bf769..a3f5f6b0cd 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -793,9 +793,18 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons %changelog -* Wed Jul 20 2022 Martin Winter <mwinter@opensourcerouting.org> - %{version} - -* Tue Oct 04 2022 Donatas Abraitis <donatas@opensourcerouting.org> - 8.4 +* Tue Nov 01 2022 Martin Winter <mwinter@opensourcerouting.org> - %{version} + +* Tue Nov 01 2022 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.4 +- New BGP command (neighbor PEER soo) to configure SoO to prevent routing loops and suboptimal routing on dual-homed sites. +- Command debug bgp allow-martian replaced to bgp allow-martian-nexthop because previously we allowed using martian next-hops when debug is turned on. +- Implement BGP Prefix Origin Validation State Extended Community rfc8097 +- Implement Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages rfc9234 +- BMP L3VPN support +- PIMv6 support +- MLD support +- New command to enable using reserved IPv4 ranges as normal addresses for BGP next-hops, interface addresses, etc. +- For a full list of bug fixes, please refer to https://frrouting.org/release/ * Wed Jul 13 2022 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.3 - General: diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index de07ad8ef3..cb36304473 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -313,6 +313,7 @@ static bool static_zebra_nht_get_prefix(const struct static_nexthop *nh, } assertf(0, "BUG: someone forgot to add nexthop type %u", nh->type); + return false; } void static_zebra_nht_register(struct static_nexthop *nh, bool reg) diff --git a/tests/lib/test_heavy_wq.c b/tests/lib/test_heavy_wq.c index 00aa7b80dd..be47ef4bbc 100644 --- a/tests/lib/test_heavy_wq.c +++ b/tests/lib/test_heavy_wq.c @@ -70,11 +70,6 @@ static void heavy_wq_add(struct vty *vty, const char *str, int i) return; } -static void slow_func_err(struct work_queue *wq, struct work_queue_item *item) -{ - printf("%s: running error function\n", __func__); -} - static void slow_func_del(struct work_queue *wq, void *data) { struct heavy_wq_node *hn = data; @@ -143,7 +138,6 @@ static int heavy_wq_init(void) heavy_wq = work_queue_new(master, "heavy_work_queue"); heavy_wq->spec.workfunc = &slow_func; - heavy_wq->spec.errorfunc = &slow_func_err; heavy_wq->spec.del_item_data = &slow_func_del; heavy_wq->spec.max_retries = 3; heavy_wq->spec.hold = 1000; diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf new file mode 100644 index 0000000000..d82a21e1f9 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf @@ -0,0 +1,31 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + no bgp default ipv4-unicast + neighbor 192.168.12.2 remote-as external + neighbor 192.168.12.2 timers 1 3 + neighbor 192.168.12.2 timers connect 1 + neighbor 2001:db8::12:2 remote-as external + neighbor 2001:db8::12:2 timers 1 3 + neighbor 2001:db8::12:2 timers connect 1 + ! + address-family ipv4 unicast + network 10.0.0.0/31 route-map p1 + network 10.0.0.2/32 route-map p2 + neighbor 192.168.12.2 activate + exit-address-family + address-family ipv6 unicast + network 2001:db8::1/128 route-map p1 + network 2001:db8:1::/56 route-map p2 + neighbor 2001:db8::12:2 activate + exit-address-family +! +route-map p1 permit 10 + set metric 1 +exit +route-map p2 permit 10 + set metric 2 + set origin incomplete +exit +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r1/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r1/zebra.conf new file mode 100644 index 0000000000..0807e89d08 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r1/zebra.conf @@ -0,0 +1,5 @@ +! +interface r1-eth0 + ip address 192.168.12.1/24 + ipv6 address 2001:db8::12:1/64 +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf new file mode 100644 index 0000000000..3512e66cec --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf @@ -0,0 +1,23 @@ +! +debug bgp updates +! +router bgp 65002 + no bgp ebgp-requires-policy + no bgp network import-check + no bgp default ipv4-unicast + neighbor 192.168.12.1 remote-as external + neighbor 192.168.12.1 timers 1 3 + neighbor 192.168.12.1 timers connect 1 + neighbor 2001:db8::12:1 remote-as external + neighbor 2001:db8::12:1 timers 1 3 + neighbor 2001:db8::12:1 timers connect 1 + ! + address-family ipv4 unicast + neighbor 192.168.12.1 activate + exit-address-family + address-family ipv6 unicast + neighbor 2001:db8::12:1 activate + exit-address-family +! +agentx +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/snmpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/snmpd.conf new file mode 100644 index 0000000000..032b93b676 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/snmpd.conf @@ -0,0 +1,17 @@ +agentAddress 127.0.0.1,[::1] + +group public_group v1 public +group public_group v2c public +access public_group "" any noauth prefix all all none + +rocommunity public default + +view all included .1 + +iquerySecName frr +rouser frr + +master agentx + +agentXSocket /etc/frr/agentx +agentXPerms 777 755 root frr diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/zebra.conf new file mode 100644 index 0000000000..db6d7005a0 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/zebra.conf @@ -0,0 +1,5 @@ +! +interface r2-eth0 + ip address 192.168.12.2/24 + ipv6 address 2001:db8::12:2/64 +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py new file mode 100755 index 0000000000..53ca10930b --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2022 Donatas Abraitis <donatas@opensourcerouting.org> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Test some of the BGP4V2-MIB entries. +""" + +import os +import sys +import json +from time import sleep +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.snmptest import SnmpTester +from lib import topotest + +pytestmark = [pytest.mark.bgpd, pytest.mark.snmp] + + +def build_topo(tgen): + tgen.add_router("r1") + tgen.add_router("r2") + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + snmpd = os.system("which snmpd") + if snmpd: + error_msg = "SNMP not installed - skipping" + pytest.skip(error_msg) + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + for rname, router in tgen.routers().items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, + os.path.join(CWD, "{}/bgpd.conf".format(rname)), + "-M snmp", + ) + router.load_config( + TopoRouter.RD_SNMP, + os.path.join(CWD, "{}/snmpd.conf".format(rname)), + "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX", + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_snmp_bgp4v2(): + tgen = get_topogen() + + r2 = tgen.gears["r2"] + + def _bgp_converge_summary(): + output = json.loads(r2.vtysh_cmd("show bgp summary json")) + expected = { + "ipv4Unicast": { + "peers": { + "192.168.12.1": { + "state": "Established", + "pfxRcd": 2, + } + } + }, + "ipv6Unicast": { + "peers": { + "2001:db8::12:1": { + "state": "Established", + "pfxRcd": 2, + } + } + }, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge_summary) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see connections established" + + def _bgp_converge_prefixes(): + output = json.loads(r2.vtysh_cmd("show bgp all json")) + expected = { + "ipv4Unicast": { + "routes": { + "10.0.0.0/31": [ + { + "metric": 1, + "origin": "IGP", + } + ], + "10.0.0.2/32": [ + { + "metric": 2, + "origin": "incomplete", + } + ], + } + }, + "ipv6Unicast": { + "routes": { + "2001:db8::1/128": [ + { + "metric": 1, + "origin": "IGP", + } + ], + "2001:db8:1::/56": [ + { + "metric": 2, + "origin": "incomplete", + } + ], + } + }, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge_prefixes) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see prefixes from R1" + + snmp = SnmpTester(r2, "localhost", "public", "2c", "-Ln -On") + + def _snmpwalk_remote_addr(): + expected = { + "1.3.6.1.3.5.1.1.2.1.5.1.4.192.168.12.1": "C0 A8 0C 01", + "1.3.6.1.3.5.1.1.2.1.5.2.16.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "20 01 0D B8 00 00 00 00 00 00 00 00 00 12 00 01", + } + + # bgp4V2PeerRemoteAddr + output, _ = snmp.walk(".1.3.6.1.3.5.1.1.2.1.5") + return output == expected + + _, result = topotest.run_and_expect(_snmpwalk_remote_addr, True, count=10, wait=1) + assertmsg = "Can't fetch SNMP for bgp4V2PeerRemoteAddr" + assert result, assertmsg + + def _snmpwalk_peer_state(): + expected = { + "1.3.6.1.3.5.1.1.2.1.13.1.4.192.168.12.1": "6", + "1.3.6.1.3.5.1.1.2.1.13.2.16.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "6", + } + + # bgp4V2PeerState + output, _ = snmp.walk(".1.3.6.1.3.5.1.1.2.1.13") + return output == expected + + _, result = topotest.run_and_expect(_snmpwalk_peer_state, True, count=10, wait=1) + assertmsg = "Can't fetch SNMP for bgp4V2PeerState" + assert result, assertmsg + + def _snmpwalk_peer_last_error_code_received(): + expected = { + "1.3.6.1.3.5.1.1.3.1.1.1.4.192.168.12.1": "0", + "1.3.6.1.3.5.1.1.3.1.1.2.16.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "0", + } + + # bgp4V2PeerLastErrorCodeReceived + output, _ = snmp.walk(".1.3.6.1.3.5.1.1.3.1.1") + return output == expected + + _, result = topotest.run_and_expect( + _snmpwalk_peer_last_error_code_received, True, count=10, wait=1 + ) + assertmsg = "Can't fetch SNMP for bgp4V2PeerLastErrorCodeReceived" + assert result, assertmsg + + def _snmpwalk_origin(): + expected = { + "1.3.6.1.3.5.1.1.9.1.9.1.4.10.0.0.0.31.192.168.12.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.4.10.0.0.2.32.192.168.12.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.2.16.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.2.16.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "3", + } + + # bgp4V2NlriOrigin + output, _ = snmp.walk(".1.3.6.1.3.5.1.1.9.1.9") + return output == expected + + _, result = topotest.run_and_expect(_snmpwalk_origin, True, count=10, wait=1) + assertmsg = "Can't fetch SNMP for bgp4V2NlriOrigin" + assert result, assertmsg + + def _snmpwalk_med(): + expected = { + "1.3.6.1.3.5.1.1.9.1.17.1.4.10.0.0.0.31.192.168.12.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.1.4.10.0.0.2.32.192.168.12.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.2.16.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.2.16.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "2", + } + + # bgp4V2NlriMed + output, _ = snmp.walk(".1.3.6.1.3.5.1.1.9.1.17") + return output == expected + + _, result = topotest.run_and_expect(_snmpwalk_med, True, count=10, wait=1) + assertmsg = "Can't fetch SNMP for bgp4V2NlriMed" + assert result, assertmsg + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/bgpd.conf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/bgpd.conf diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/zebra.conf new file mode 100644 index 0000000000..823a56d53f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/ce1/zebra.conf @@ -0,0 +1,9 @@ +log file zebra.log +! +hostname ce1 +! +interface eth0 + ip address 172.16.0.1/24 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/bgpd.conf new file mode 100644 index 0000000000..15779aa0d5 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/bgpd.conf @@ -0,0 +1,41 @@ +frr defaults traditional +! +hostname pe1 +password zebra +! +log stdout notifications +log monitor notifications +log commands +! +router bgp 65001 + bgp router-id 192.0.2.1 + ! + segment-routing srv6 + locator default + exit + ! +! +router bgp 65001 vrf vrf10 + bgp router-id 192.0.2.1 + ! + address-family ipv4 unicast + redistribute connected + sid vpn export auto + rd vpn export 65001:10 + rt vpn both 0:10 + import vpn + export vpn + exit-address-family + ! +! +router bgp 65001 vrf vrf20 + bgp router-id 192.0.2.1 + ! + address-family ipv4 unicast + rd vpn export 65001:20 + rt vpn both 0:10 + import vpn + export vpn + exit-address-family + ! +! diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/default_ipv4_vpn.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/default_ipv4_vpn.json new file mode 100644 index 0000000000..dc86d7c978 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/default_ipv4_vpn.json @@ -0,0 +1,31 @@ +{ + "vrfName": "default", + "routerId": "192.0.2.1", + "localAS": 65001, + "routes": { + "routeDistinguishers": { + "65001:10": { + "172.16.0.0/24": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "172.16.0.0", + "prefixLen": 24, + "network": "172.16.0.0\/24", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf10", + "nexthops": [ + { + "hostname": "pe1", + "afi": "ipv4", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf10_ipv4_unicast.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf10_ipv4_unicast.json new file mode 100644 index 0000000000..ce2d5c19c3 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf10_ipv4_unicast.json @@ -0,0 +1,25 @@ +{ + "vrfName": "vrf10", + "routerId": "192.0.2.1", + "localAS": 65001, + "routes": { + "172.16.0.0/24": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "172.16.0.0", + "prefixLen": 24, + "network": "172.16.0.0\/24", + "origin": "incomplete", + "nexthops": [ + { + "hostname": "pe1", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json new file mode 100644 index 0000000000..9f78447255 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json @@ -0,0 +1,22 @@ +{ + "172.16.0.0\/24": [ + { + "prefix": "172.16.0.0\/24", + "prefixLen": 24, + "protocol": "bgp", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "installed": true, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "vrf": "vrf10", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4_unicast.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4_unicast.json new file mode 100644 index 0000000000..6a88d39a8c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4_unicast.json @@ -0,0 +1,27 @@ +{ + "vrfName": "vrf20", + "routerId": "192.0.2.1", + "localAS": 65001, + "routes": { + "172.16.0.0/24": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "172.16.0.0", + "prefixLen": 24, + "network": "172.16.0.0\/24", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf10", + "nexthops": [ + { + "hostname": "pe1", + "afi": "ipv4", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/zebra.conf new file mode 100644 index 0000000000..52341fc4fc --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/zebra.conf @@ -0,0 +1,27 @@ +log file zebra.log +! +hostname pe1 +! +interface lo + ip address 10.0.0.1/32 +! +interface eth0 vrf vrf10 + ip address 172.16.0.254/24 +! +line vty +! +segment-routing + srv6 + locators + locator default + prefix 2001:db8:2::/64 block-len 40 node-len 24 func-bits 16 + exit + ! + exit + ! + exit + ! +exit +! +end +! diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py new file mode 100755 index 0000000000..16f8adb3c5 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +# Copyright (c) 2022, LINE Corporation +# Authored by Ryoga Saito <ryoga.saito@linecorp.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +import os +import re +import sys +import json +import functools +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import required_linux_kernel_version + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + tgen.add_router("pe1") + tgen.add_router("ce1") + + tgen.add_link(tgen.gears["pe1"], tgen.gears["ce1"], "eth0", "eth0") + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + for rname, router in tgen.routers().items(): + router.load_config(TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname))) + router.load_config(TopoRouter.RD_BGP, + os.path.join(CWD, '{}/bgpd.conf'.format(rname))) + + tgen.gears["pe1"].run("ip link add vrf10 type vrf table 10") + tgen.gears["pe1"].run("ip link set vrf10 up") + tgen.gears["pe1"].run("ip link add vrf20 type vrf table 20") + tgen.gears["pe1"].run("ip link set vrf20 up") + tgen.gears["pe1"].run("ip link set eth0 master vrf10") + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def open_json_file(path): + try: + with open(path, "r") as f: + return json.load(f) + except IOError: + assert False, "Could not read file {}".format(path) + + +def check(name, command, checker): + tgen = get_topogen() + router = tgen.gears[name] + + def _check(): + try: + return checker(router.vtysh_cmd(command)) + except: + return False + + logger.info('[+] check {} "{}"'.format(name, command)) + _, result = topotest.run_and_expect(_check, None, count=10, wait=0.5) + assert result is None, "Failed" + + +def check_vrf10_bgp_rib(output): + expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD) + actual = json.loads(output) + return topotest.json_cmp(actual, expected) + + +def check_default_bgp_vpn_rib(output): + expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD) + actual = json.loads(output) + return topotest.json_cmp(actual, expected) + + +def check_vrf20_bgp_rib(output): + expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD) + actual = json.loads(output) + return topotest.json_cmp(actual, expected) + + +def check_vrf20_rib(output): + expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD) + actual = json.loads(output) + return topotest.json_cmp(actual, expected) + + +def test_rib(): + check("pe1", "show bgp vrf vrf10 ipv4 unicast json", check_vrf10_bgp_rib) + check("pe1", "show bgp ipv4 vpn json", check_default_bgp_vpn_rib) + check("pe1", "show bgp vrf vrf20 ipv4 unicast json", check_vrf20_bgp_rib) + check("pe1", "show ip route vrf vrf20 json", check_vrf20_rib) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/config_timing/test_config_timing.py b/tests/topotests/config_timing/test_config_timing.py index 7ab8619b01..0e5508b56d 100644 --- a/tests/topotests/config_timing/test_config_timing.py +++ b/tests/topotests/config_timing/test_config_timing.py @@ -161,8 +161,17 @@ def test_static_timing(): return tot_delta + # Number of static routes - prefix_count = 10000 + router = tgen.gears["r1"] + output = router.run("vtysh -h | grep address-sanitizer") + if output == "": + logger.info("No Address Sanitizer, generating 10000 routes") + prefix_count = 10000 + else: + logger.info("Address Sanitizer build, only testing 50 routes") + prefix_count = 50 + prefix_base = [ [u"10.0.0.0/8", u"11.0.0.0/8"], [u"2100:1111:2220::/44", u"2100:3333:4440::/44"], diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py index fe5ff28979..d695443906 100644 --- a/tests/topotests/lib/snmptest.py +++ b/tests/topotests/lib/snmptest.py @@ -36,11 +36,12 @@ from lib.topolog import logger class SnmpTester(object): "A helper class for testing SNMP" - def __init__(self, router, iface, community, version): + def __init__(self, router, iface, community, version, options=""): self.community = community self.version = version self.router = router self.iface = iface + self.options = options logger.info( "created SNMP tester: SNMPv{0} community:{1}".format( self.version, self.community @@ -52,7 +53,9 @@ class SnmpTester(object): Helper function to build a string with SNMP configuration for commands. """ - return "-v {0} -c {1} {2}".format(self.version, self.community, self.iface) + return "-v {0} -c {1} {2} {3}".format( + self.version, self.community, self.options, self.iface + ) @staticmethod def _get_snmp_value(snmp_output): diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 7c5d91d4dc..bf402e1bef 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -1514,6 +1514,7 @@ def ignore_unconfigurable_lines(lines_to_add, lines_to_del): [ ctx_keys[0].startswith(x) for x in [ + "agentx", "frr version", "frr defaults", "username", diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index a72cb6e809..be7eb3ecdf 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -354,6 +354,7 @@ int main(int argc, char **argv, char **env) const char *pathspace_arg = NULL; char pathspace[MAXPATHLEN] = ""; const char *histfile = NULL; + const char *histfile_env = getenv("VTYSH_HISTFILE"); /* SUID: drop down to calling user & go back up when needed */ elevuid = geteuid(); @@ -611,10 +612,8 @@ int main(int argc, char **argv, char **env) * VTYSH_HISTFILE is preferred over command line * argument (-H/--histfile). */ - if (getenv("VTYSH_HISTFILE")) { - const char *file = getenv("VTYSH_HISTFILE"); - - strlcpy(history_file, file, sizeof(history_file)); + if (histfile_env) { + strlcpy(history_file, histfile_env, sizeof(history_file)); } else if (histfile) { strlcpy(history_file, histfile, sizeof(history_file)); } else { diff --git a/zebra/main.c b/zebra/main.c index 3de97943fd..e38f9a85e3 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -221,12 +221,12 @@ void zebra_finalize(struct thread *dummy) { zlog_info("Zebra final shutdown"); - /* Final shutdown of ns resources */ - ns_walk_func(zebra_ns_final_shutdown, NULL, NULL); - /* Stop dplane thread and finish any cleanup */ zebra_dplane_shutdown(); + /* Final shutdown of ns resources */ + ns_walk_func(zebra_ns_final_shutdown, NULL, NULL); + zebra_router_terminate(); ns_terminate(); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 96ec90e549..33fe8db99e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -987,10 +987,12 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, } } } - if (nhe_id || ng) + if (nhe_id || ng) { dplane_rib_add_multipath(afi, SAFI_UNICAST, &p, &src_p, re, ng, startup, ctx); - else { + if (ng) + nexthop_group_delete(&ng); + } else { /* * I really don't see how this is possible * but since we are testing for it let's diff --git a/zebra/rtadv.c b/zebra/rtadv.c index a8ec60844c..2b9246515d 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -585,6 +585,28 @@ static void rtadv_process_solicit(struct interface *ifp) zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS; } +static const char *rtadv_optionalhdr2str(uint8_t opt_type) +{ + switch (opt_type) { + case ND_OPT_SOURCE_LINKADDR: + return "Optional Source Link Address"; + case ND_OPT_TARGET_LINKADDR: + return "Optional Target Link Address"; + case ND_OPT_PREFIX_INFORMATION: + return "Optional Prefix Information"; + case ND_OPT_REDIRECTED_HEADER: + return "Optional Redirected Header"; + case ND_OPT_MTU: + return "Optional MTU"; + case ND_OPT_RTR_ADV_INTERVAL: + return "Optional Advertisement Interval"; + case ND_OPT_HOME_AGENT_INFO: + return "Optional Home Agent Information"; + } + + return "Unknown Optional Type"; +} + /* * This function processes optional attributes off of * end of a RA packet received. At this point in @@ -609,6 +631,13 @@ static void rtadv_process_optional(uint8_t *optional, unsigned int len, &addr->sin6_addr, 1); break; default: + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug( + "%s:Received Packet with optional Header type %s(%u) that is being ignored", + __func__, + rtadv_optionalhdr2str( + opt_hdr->nd_opt_type), + opt_hdr->nd_opt_type); break; } diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 26c7823747..2304af19d1 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -308,6 +308,7 @@ struct rtadv_prefix { #define ND_OPT_HA_INFORMATION 8 /* HA Information Option */ #endif + #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL struct nd_opt_adv_interval { /* Advertisement interval option */ uint8_t nd_opt_ai_type; @@ -324,6 +325,12 @@ struct nd_opt_adv_interval { /* Advertisement interval option */ #define nd_opt_ai_interval nd_opt_adv_interval_ival #endif #endif +#ifndef ND_OPT_RTR_ADV_INTERVAL +#define ND_OPT_RTR_ADV_INTERVAL 7 +#endif +#ifndef ND_OPT_HOME_AGENT_INFO +#define ND_OPT_HOME_AGENT_INFO 8 +#endif #ifndef HAVE_STRUCT_ND_OPT_HOMEAGENT_INFO struct nd_opt_homeagent_info { /* Home Agent info */ diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index ca897251e2..5cefa16cdd 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -539,10 +539,15 @@ static void zfpm_log_route_info(struct netlink_route_info *ri, for (i = 0; i < ri->num_nhs; i++) { nhi = &ri->nhs[i]; - if (ri->af == AF_INET) - inet_ntop(AF_INET, &nhi->gateway, buf, sizeof(buf)); - else - inet_ntop(AF_INET6, &nhi->gateway, buf, sizeof(buf)); + if (nhi->gateway) { + if (ri->af == AF_INET) + inet_ntop(AF_INET, nhi->gateway, buf, + sizeof(buf)); + else + inet_ntop(AF_INET6, nhi->gateway, buf, + sizeof(buf)); + } else + strlcpy(buf, "none", sizeof(buf)); zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s, Encap type: %s", nhi->if_index, buf, nhi->recursive ? "yes" : "no", diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 9756d9ba08..fe3f77f3c7 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -1754,7 +1754,6 @@ static void mpls_processq_init(void) zrouter.lsp_process_q->spec.workfunc = &lsp_process; zrouter.lsp_process_q->spec.del_item_data = &lsp_processq_del; - zrouter.lsp_process_q->spec.errorfunc = NULL; zrouter.lsp_process_q->spec.completion_func = &lsp_processq_complete; zrouter.lsp_process_q->spec.max_retries = 0; zrouter.lsp_process_q->spec.hold = 10; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b86780276b..9551f26d80 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3681,14 +3681,14 @@ static void rib_meta_queue_free(struct meta_queue *mq, struct list *l, static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l, struct zebra_vrf *zvrf) { - struct zebra_early_route *zer; + struct zebra_early_route *ere; struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(l, node, nnode, zer)) { - if (zvrf && zer->re->vrf_id != zvrf->vrf->vrf_id) + for (ALL_LIST_ELEMENTS(l, node, nnode, ere)) { + if (zvrf && ere->re->vrf_id != zvrf->vrf->vrf_id) continue; - XFREE(MTYPE_RE, zer); + early_route_memory_free(ere); node->data = NULL; list_delete_node(l, node); mq->size--; @@ -3743,7 +3743,6 @@ static void rib_queue_init(void) /* fill in the work queue spec */ zrouter.ribq->spec.workfunc = &meta_queue_process; - zrouter.ribq->spec.errorfunc = NULL; zrouter.ribq->spec.completion_func = NULL; /* XXX: TODO: These should be runtime configurable via vty */ zrouter.ribq->spec.max_retries = 3; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 066ef8a8d0..4f43cea493 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -143,26 +143,48 @@ static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf, } static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf, - int af_type) + int af_type, json_object *json) { int i; - vty_out(vty, "Protocol : route-map\n"); - vty_out(vty, "-------------------------------------\n"); + if (!json) { + vty_out(vty, "Protocol : route-map\n"); + vty_out(vty, "-------------------------------------\n"); + } for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (json) { + if (NHT_RM_NAME(zvrf, af_type, i)) + json_object_string_add( + json, zebra_route_string(i), + NHT_RM_NAME(zvrf, af_type, i)); + else + json_object_string_add( + json, zebra_route_string(i), "none"); + } else { + if (NHT_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-24s : %-10s\n", + zebra_route_string(i), + NHT_RM_NAME(zvrf, af_type, i)); + else + vty_out(vty, "%-24s : none\n", + zebra_route_string(i)); + } + } + + if (json) { if (NHT_RM_NAME(zvrf, af_type, i)) - vty_out(vty, "%-24s : %-10s\n", zebra_route_string(i), + json_object_string_add(json, "any", + NHT_RM_NAME(zvrf, af_type, i)); + else + json_object_string_add(json, "any", "none"); + } else { + if (NHT_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-24s : %-10s\n", "any", NHT_RM_NAME(zvrf, af_type, i)); else - vty_out(vty, "%-24s : none\n", zebra_route_string(i)); + vty_out(vty, "%-24s : none\n", "any"); } - - if (NHT_RM_NAME(zvrf, af_type, i)) - vty_out(vty, "%-24s : %-10s\n", "any", - NHT_RM_NAME(zvrf, af_type, i)); - else - vty_out(vty, "%-24s : none\n", "any"); } static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all, @@ -198,35 +220,78 @@ static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all, } static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all, - const char *vrf_name) + const char *vrf_name, bool use_json) { struct zebra_vrf *zvrf; + json_object *json = NULL; + json_object *json_vrfs = NULL; + + if (use_json) { + json = json_object_new_object(); + json_vrfs = json_object_new_object(); + json_object_string_add(json, "afi", + (af_type == AFI_IP) ? "ipv4" : "ipv6"); + } if (vrf_all) { struct vrf *vrf; + if (use_json) + json_object_object_add(json, "vrfs", json_vrfs); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { zvrf = (struct zebra_vrf *)vrf->info; if (zvrf == NULL) continue; - vty_out(vty, "VRF: %s\n", zvrf->vrf->name); - show_vrf_nht_rm(vty, zvrf, af_type); + if (use_json) { + json_object *json_proto = NULL; + json_object *json_vrf = NULL; + json_vrf = json_object_new_object(); + json_object_object_add( + json_vrfs, zvrf->vrf->name, json_vrf); + json_proto = json_object_new_object(); + json_object_object_add(json_vrf, "protocols", + json_proto); + show_vrf_nht_rm(vty, zvrf, af_type, json_proto); + } else { + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_nht_rm(vty, zvrf, af_type, NULL); + } } } else { + json_object *json_proto = NULL; + json_object *json_vrf = NULL; vrf_id_t vrf_id = VRF_DEFAULT; if (vrf_name) VRF_GET_ID(vrf_id, vrf_name, false); zvrf = zebra_vrf_lookup_by_id(vrf_id); - if (!zvrf) + if (!zvrf) { + json_object_free(json); + json_object_free(json_vrfs); return CMD_SUCCESS; + } - vty_out(vty, "VRF: %s\n", zvrf->vrf->name); - show_vrf_nht_rm(vty, zvrf, af_type); + if (use_json) { + json_object_object_add(json, "vrfs", json_vrfs); + json_vrf = json_object_new_object(); + json_object_object_add(json_vrfs, zvrf->vrf->name, + json_vrf); + json_proto = json_object_new_object(); + json_object_object_add(json_vrf, "protocols", + json_proto); + show_vrf_nht_rm(vty, zvrf, af_type, json_proto); + } else { + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_nht_rm(vty, zvrf, af_type, NULL); + } } + if (use_json) + vty_json(vty, json); + return CMD_SUCCESS; } @@ -854,14 +919,19 @@ DEFPY_YANG (no_ip_protocol_nht_rmap, DEFPY_YANG (show_ip_protocol_nht, show_ip_protocol_nht_cmd, - "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]", + "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]", SHOW_STR IP_STR - "IP nexthop tracking table\n" - "IP Next Hop tracking filtering status\n" - VRF_FULL_CMD_HELP_STR) + "IPv4 nexthop tracking table\n" + "IPv4 Next Hop tracking filtering status\n" + VRF_CMD_HELP_STR + "All VRFs\n" + JSON_STR) { - int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name); + int ret; + bool uj = use_json(argc, argv); + + ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name, uj); return ret; } @@ -936,14 +1006,19 @@ DEFPY_YANG (no_ipv6_protocol_nht_rmap, DEFPY_YANG (show_ipv6_protocol_nht, show_ipv6_protocol_nht_cmd, - "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]", + "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]", SHOW_STR IP6_STR - "Next Hop filtering status\n" - "Route-map\n" - VRF_FULL_CMD_HELP_STR) + "IPv6 nexthop tracking table\n" + "IPv6 Next Hop tracking filtering status\n" + VRF_CMD_HELP_STR + "All VRFs\n" + JSON_STR) { - int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name); + int ret; + bool uj = use_json(argc, argv); + + ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name, uj); return ret; } |
