diff options
233 files changed, 10846 insertions, 2108 deletions
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index fef7a61ccc..fd3c02f47e 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -18,7 +18,8 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre2 perl pkgconf python3 python3-dev readline readline-dev sqlite-libs pcre2-dev squashfs-tools sudo tar texinfo xorriso xz-libs py-pip rtrlib rtrlib-dev - py3-sphinx elfutils elfutils-dev libyang-dev" + py3-sphinx elfutils elfutils-dev libyang-dev protobuf-c-compiler protobuf-c-dev + lua5.3-dev lua5.3" checkdepends="pytest py-setuptools" install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall" subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg" @@ -47,7 +48,8 @@ build() { --enable-vty-group=frrvty \ --enable-user=$_user \ --enable-group=$_user \ - --enable-pcre2posix + --enable-pcre2posix \ + --enable-scripting make -j $(nproc) } diff --git a/babeld/babeld.c b/babeld/babeld.c index 4ce92c5204..f4c932971e 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -444,37 +444,39 @@ babel_fill_with_next_timeout(struct timeval *tv) #if (defined NO_DEBUG) #define printIfMin(a,b,c,d) #else -#define printIfMin(a,b,c,d) \ - if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);} - - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct interface *ifp = NULL; +#define printIfMin(a, b, c, d) \ + if (unlikely(debug & BABEL_DEBUG_TIMEOUT)) { \ + printIfMin(a, b, c, d); \ + } - *tv = check_neighbours_timeout; - printIfMin(tv, 0, "check_neighbours_timeout", NULL); - timeval_min_sec(tv, expiry_time); - printIfMin(tv, 1, "expiry_time", NULL); - timeval_min_sec(tv, source_expiry_time); - printIfMin(tv, 1, "source_expiry_time", NULL); - timeval_min(tv, &resend_time); - printIfMin(tv, 1, "resend_time", NULL); - FOR_ALL_INTERFACES(vrf, ifp) { - babel_interface_nfo *babel_ifp = NULL; - if(!if_up(ifp)) - continue; - babel_ifp = babel_get_if_nfo(ifp); - timeval_min(tv, &babel_ifp->flush_timeout); - printIfMin(tv, 1, "flush_timeout", ifp->name); - timeval_min(tv, &babel_ifp->hello_timeout); - printIfMin(tv, 1, "hello_timeout", ifp->name); - timeval_min(tv, &babel_ifp->update_timeout); - printIfMin(tv, 1, "update_timeout", ifp->name); - timeval_min(tv, &babel_ifp->update_flush_timeout); - printIfMin(tv, 1, "update_flush_timeout",ifp->name); - } - timeval_min(tv, &unicast_flush_timeout); - printIfMin(tv, 1, "unicast_flush_timeout", NULL); - printIfMin(tv, 2, NULL, NULL); + struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct interface *ifp = NULL; + + *tv = check_neighbours_timeout; + printIfMin(tv, 0, "check_neighbours_timeout", NULL); + timeval_min_sec(tv, expiry_time); + printIfMin(tv, 1, "expiry_time", NULL); + timeval_min_sec(tv, source_expiry_time); + printIfMin(tv, 1, "source_expiry_time", NULL); + timeval_min(tv, &resend_time); + printIfMin(tv, 1, "resend_time", NULL); + FOR_ALL_INTERFACES (vrf, ifp) { + babel_interface_nfo *babel_ifp = NULL; + if (!if_up(ifp)) + continue; + babel_ifp = babel_get_if_nfo(ifp); + timeval_min(tv, &babel_ifp->flush_timeout); + printIfMin(tv, 1, "flush_timeout", ifp->name); + timeval_min(tv, &babel_ifp->hello_timeout); + printIfMin(tv, 1, "hello_timeout", ifp->name); + timeval_min(tv, &babel_ifp->update_timeout); + printIfMin(tv, 1, "update_timeout", ifp->name); + timeval_min(tv, &babel_ifp->update_flush_timeout); + printIfMin(tv, 1, "update_flush_timeout", ifp->name); + } + timeval_min(tv, &unicast_flush_timeout); + printIfMin(tv, 1, "unicast_flush_timeout", NULL); + printIfMin(tv, 2, NULL, NULL); #undef printIfMin #endif } diff --git a/babeld/babeld.h b/babeld/babeld.h index 6c51af48a8..619550f651 100644 --- a/babeld/babeld.h +++ b/babeld/babeld.h @@ -26,12 +26,8 @@ Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek #if defined(__GNUC__) && (__GNUC__ >= 3) #define ATTRIBUTE(x) __attribute__ (x) -#define LIKELY(_x) __builtin_expect(!!(_x), 1) -#define UNLIKELY(_x) __builtin_expect(!!(_x), 0) #else #define ATTRIBUTE(x) /**/ -#define LIKELY(_x) !!(_x) -#define UNLIKELY(_x) !!(_x) #endif #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) diff --git a/babeld/util.h b/babeld/util.h index 5e5843543a..8535d4dd6a 100644 --- a/babeld/util.h +++ b/babeld/util.h @@ -122,10 +122,11 @@ extern const unsigned char v4prefix[16]; #define BABEL_DEBUG_ROUTE (1 << 5) #define BABEL_DEBUG_ALL (0xFFFF) -#define debugf(level, ...) \ -do { \ -if(UNLIKELY(debug & level)) zlog_debug(__VA_ARGS__); \ -} while(0) +#define debugf(level, ...) \ + do { \ + if (unlikely(debug & level)) \ + zlog_debug(__VA_ARGS__); \ + } while (0) #endif /* NO_DEBUG */ diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index a51bcb1a1a..d1ddfd0460 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -55,7 +55,7 @@ static void bfd_session_status_update(struct bfd_session_params *bsp, } peer->last_reset = PEER_DOWN_BFD_DOWN; - /* draft-ietf-idr-bfd-subcode */ + /* rfc9384 */ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send(peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_BFD_DOWN); diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 73dbf4ab2b..baf164679c 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -389,13 +389,13 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) /* Local Port, Remote Port */ if (peer->su_local->sa.sa_family == AF_INET6) - stream_putw(s, peer->su_local->sin6.sin6_port); + stream_putw(s, htons(peer->su_local->sin6.sin6_port)); else if (peer->su_local->sa.sa_family == AF_INET) - stream_putw(s, peer->su_local->sin.sin_port); + stream_putw(s, htons(peer->su_local->sin.sin_port)); if (peer->su_remote->sa.sa_family == AF_INET6) - stream_putw(s, peer->su_remote->sin6.sin6_port); + stream_putw(s, htons(peer->su_remote->sin6.sin6_port)); else if (peer->su_remote->sa.sa_family == AF_INET) - stream_putw(s, peer->su_remote->sin.sin_port); + stream_putw(s, htons(peer->su_remote->sin.sin_port)); static const uint8_t dummy_open[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 541da9ecd6..dc1905868b 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -503,6 +503,8 @@ static const char *ecommunity_gettoken(const char *str, uint8_t ecomm_type; char buf[INET_ADDRSTRLEN + 1]; struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr; + uint64_t tmp_as = 0; + /* Skip white space. */ while (isspace((unsigned char)*p)) { p++; @@ -581,9 +583,18 @@ static const char *ecommunity_gettoken(const char *str, goto error; endptr++; - as = strtoul(endptr, &endptr, 10); - if (*endptr != '\0' || as == BGP_AS4_MAX) + errno = 0; + tmp_as = strtoul(endptr, &endptr, 10); + /* 'unsigned long' is a uint64 on 64-bit + * systems, and uint32 on 32-bit systems. So for + * 64-bit we can just directly check the value + * against BGP_AS4_MAX/UINT32_MAX, and for + * 32-bit we can check for errno (set to ERANGE + * upon overflow). + */ + if (*endptr != '\0' || tmp_as == BGP_AS4_MAX || errno) goto error; + as = (as_t)tmp_as; memcpy(buf, p, (limit - p)); buf[limit - p] = '\0'; @@ -625,9 +636,19 @@ static const char *ecommunity_gettoken(const char *str, goto error; } else { /* ASN */ - as = strtoul(buf, &endptr, 10); - if (*endptr != '\0' || as == BGP_AS4_MAX) + errno = 0; + tmp_as = strtoul(buf, &endptr, 10); + /* 'unsigned long' is a uint64 on 64-bit + * systems, and uint32 on 32-bit systems. So for + * 64-bit we can just directly check the value + * against BGP_AS4_MAX/UINT32_MAX, and for + * 32-bit we can check for errno (set to ERANGE + * upon overflow). + */ + if (*endptr != '\0' || tmp_as > BGP_AS4_MAX || + errno) goto error; + as = (as_t)tmp_as; } } else if (*p == '.') { if (separator) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 78e96d130c..81117e94ef 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -5679,7 +5679,7 @@ void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p, } int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int withdraw) + struct bgp_nlri *packet, bool withdraw) { uint8_t *pnt; uint8_t *lim; @@ -6235,6 +6235,14 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, l3vni); return -1; } + + if (CHECK_FLAG(bgp_evpn->flags, BGP_FLAG_DELETE_IN_PROGRESS)) { + flog_err(EC_BGP_NO_DFLT, + "Cannot process L3VNI %u ADD - EVPN BGP instance is shutting down", + l3vni); + return -1; + } + as = bgp_evpn->as; /* if the BGP vrf instance doesn't exist - create one */ @@ -6377,6 +6385,13 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) return -1; } + if (CHECK_FLAG(bgp_evpn->flags, BGP_FLAG_DELETE_IN_PROGRESS)) { + flog_err(EC_BGP_NO_DFLT, + "Cannot process L3VNI %u ADD - EVPN BGP instance is shutting down", + l3vni); + return -1; + } + /* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured, * bgp_delete would not remove/decrement bgp_path_info of the ip_prefix * routes. This will uninstalling the routes from zebra and decremnt the diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 1dce4820d6..a034bfbd7e 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -150,7 +150,7 @@ extern void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p, struct attr *attr, bool addpath_capable, uint32_t addpath_tx_id); extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int withdraw); + struct bgp_nlri *packet, bool withdraw); extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p, struct bgp_path_info *ri); diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index d821d4d582..4aff93514f 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -1071,7 +1071,8 @@ void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn) continue; /* Update EAD-ES */ - bgp_evpn_ead_es_route_update(bgp, es); + if (bgp_evpn_local_es_is_active(es)) + bgp_evpn_ead_es_route_update(bgp, es); /* Update EAD-EVI */ if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) { @@ -2608,6 +2609,9 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty, listcount(es->macip_global_path_list)); json_object_int_add(json, "inconsistentVniVtepCount", es->incons_evi_vtep_cnt); + if (es->flags & BGP_EVPNES_LOCAL) + json_object_int_add(json, "localEsDfPreference", + es->df_pref); if (listcount(es->es_vtep_list)) { json_vteps = json_object_new_array(); for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index f9debe43cd..70bdbaf035 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -82,7 +82,7 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len, } int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int withdraw) + struct bgp_nlri *packet, bool withdraw) { uint8_t *pnt; uint8_t *lim; @@ -98,6 +98,13 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, afi = packet->afi; safi = packet->safi; + /* + * All other AFI/SAFI's treat no attribute as a implicit + * withdraw. Flowspec should as well. + */ + if (!attr) + withdraw = true; + if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT_EXTENDED) { flog_err(EC_BGP_FLOWSPEC_PACKET, "BGP flowspec nlri length maximum reached (%u)", diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index 58fc1775ab..bc2f00511e 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -15,7 +15,7 @@ #define BGP_FLOWSPEC_NLRI_STRING_MAX 512 extern int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int withdraw); + struct bgp_nlri *packet, bool withdraw); extern void bgp_flowspec_vty_init(void); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index c08f95cdf4..63168f1e7a 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1103,7 +1103,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, struct bgp_path_info *new; struct bgp_path_info_extra *extra; uint32_t num_sids = 0; - void *parent = source_bpi; + struct bgp_path_info *parent = source_bpi; if (new_attr->srv6_l3vpn || new_attr->srv6_vpn) num_sids = 1; @@ -1311,7 +1311,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, new->extra->parent = bgp_path_info_lock(parent); bgp_dest_lock_node( - (struct bgp_dest *)((struct bgp_path_info *)parent)->net); + (struct bgp_dest *)parent->net); if (bgp_orig) new->extra->bgp_orig = bgp_lock(bgp_orig); if (nexthop_orig) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 1c76828a2f..9469a0778f 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -331,7 +331,7 @@ static void bgp_update_explicit_eors(struct peer *peer) * calling safi function and for evpn, passed as parameter */ int bgp_nlri_parse(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int mp_withdraw) + struct bgp_nlri *packet, bool mp_withdraw) { switch (packet->safi) { case SAFI_UNICAST: diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index c072bbc235..04bdb81849 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -42,26 +42,28 @@ DECLARE_HOOK(bgp_packet_send, } while (0) /* Packet send and receive function prototypes. */ -extern void bgp_keepalive_send(struct peer *); -extern void bgp_open_send(struct peer *); -extern void bgp_notify_send(struct peer *, uint8_t, uint8_t); -extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t, - uint8_t *, size_t); +extern void bgp_keepalive_send(struct peer *peer); +extern void bgp_open_send(struct peer *peer); +extern void bgp_notify_send(struct peer *peer, uint8_t code, uint8_t sub_code); +extern void bgp_notify_send_with_data(struct peer *peer, uint8_t code, + uint8_t sub_code, uint8_t *data, + size_t datalen); void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code, uint8_t *data, size_t datalen); extern void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi, uint8_t orf_type, uint8_t when_to_refresh, int remove, uint8_t subtype); -extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int); +extern void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi, + int capabilty_code, int action); -extern int bgp_capability_receive(struct peer *, bgp_size_t); +extern int bgp_capability_receive(struct peer *peer, bgp_size_t length); -extern int bgp_nlri_parse(struct peer *, struct attr *, struct bgp_nlri *, - int mp_withdraw); +extern int bgp_nlri_parse(struct peer *peer, struct attr *attr, + struct bgp_nlri *nlri, bool mp_withdraw); -extern void bgp_update_restarted_peers(struct peer *); -extern void bgp_update_implicit_eors(struct peer *); -extern void bgp_check_update_delay(struct bgp *); +extern void bgp_update_restarted_peers(struct peer *peer); +extern void bgp_update_implicit_eors(struct peer *peer); +extern void bgp_check_update_delay(struct bgp *peer); extern int bgp_packet_set_marker(struct stream *s, uint8_t type); extern void bgp_packet_set_size(struct stream *s); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a23bffd4ae..b49206adce 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3070,7 +3070,9 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, * the IMPLICIT_NULL label. This is pretty specialized: it's only called * in a path where we basically _know_ this is a BGP-LU route. */ -static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) +static bool bgp_lu_need_null_label(struct bgp *bgp, + const struct bgp_path_info *new_select, + afi_t afi, mpls_label_t *label) { /* Certain types get imp null; so do paths where the nexthop is * not labeled. @@ -3079,12 +3081,20 @@ static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) || new_select->sub_type == BGP_ROUTE_AGGREGATE || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE) return true; - else if (new_select->extra == NULL || - !bgp_is_valid_label(&new_select->extra->label[0])) - /* TODO -- should be configurable? */ + else if (new_select->extra && + bgp_is_valid_label(&new_select->extra->label[0])) + return false; + if (label == NULL) return true; + if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL)) + /* Disable PHP : explicit-null */ + *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL + : MPLS_LABEL_IPV6_EXPLICIT_NULL; else - return false; + /* Enforced PHP popping: implicit-null */ + *label = MPLS_LABEL_IMPLICIT_NULL; + + return true; } /* @@ -3113,6 +3123,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *old_select; struct bgp_path_info_pair old_and_new; int debug = 0; + mpls_label_t mpls_label_null; if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) { if (dest) @@ -3167,7 +3178,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, * Right now, since we only deal with per-prefix labels, it is not * necessary to do this upon changes to best path. Exceptions: * - label index has changed -> recalculate resulting label - * - path_info sub_type changed -> switch to/from implicit-null + * - path_info sub_type changed -> switch to/from null label value * - no valid label (due to removed static label binding) -> get new one */ if (bgp->allocate_mpls_labels[afi][safi]) { @@ -3176,11 +3187,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || bgp_label_index_differs(new_select, old_select) || new_select->sub_type != old_select->sub_type || !bgp_is_valid_label(&dest->local_label)) { - /* Enforced penultimate hop popping: - * implicit-null for local routes, aggregate - * and redistributed routes + /* control label imposition for local routes, + * aggregate and redistributed routes */ - if (bgp_lu_need_imp_null(new_select)) { + mpls_label_null = MPLS_LABEL_IMPLICIT_NULL; + if (bgp_lu_need_null_label(bgp, new_select, afi, + &mpls_label_null)) { if (CHECK_FLAG( dest->flags, BGP_NODE_REGISTERED_FOR_LABEL) @@ -3189,8 +3201,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, BGP_NODE_LABEL_REQUESTED)) bgp_unregister_for_label(dest); dest->local_label = mpls_lse_encode( - MPLS_LABEL_IMPLICIT_NULL, 0, 0, - 1); + mpls_label_null, 0, 0, 1); bgp_set_valid_label(&dest->local_label); } else bgp_register_for_label(dest, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 4faf4a9f15..32ecb083be 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -461,7 +461,8 @@ route_match_ip_address(void *rule, const struct prefix *prefix, void *object) if (prefix->family == AF_INET) { alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -521,7 +522,8 @@ route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object) alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -581,7 +583,8 @@ route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object) alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -676,7 +679,7 @@ route_match_address_prefix_list(void *rule, afi_t afi, plist = prefix_list_lookup(afi, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -737,7 +740,8 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(AFI_IP, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -786,7 +790,8 @@ route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(AFI_IP6, (char *)rule); if (!plist) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -891,7 +896,8 @@ route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(AFI_IP, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -956,7 +962,7 @@ route_match_mac_address(void *rule, const struct prefix *prefix, void *object) alist = access_list_lookup(AFI_L2VPN, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -964,7 +970,7 @@ route_match_mac_address(void *rule, const struct prefix *prefix, void *object) return RMAP_NOMATCH; } if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix %pFX is not a EVPN MAC IP ROUTE defaulting to NO_MATCH", __func__, prefix); @@ -3242,7 +3248,8 @@ route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object) if (prefix->family == AF_INET6) { alist = access_list_lookup(AFI_IP6, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -3299,7 +3306,8 @@ route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object) alist = access_list_lookup(AFI_IP6, (char *)rule); if (!alist) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index a436490ba1..de781d6b1e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1675,28 +1675,46 @@ DEFUN (no_router_bgp, for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) { if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF) continue; - if (CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST], - BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST], - BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST], - BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST], - BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST], + if (CHECK_FLAG( + tmp_bgp->af_flags[AFI_IP] + [SAFI_UNICAST], + BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_IP6] + [SAFI_UNICAST], + BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_IP] + [SAFI_UNICAST], + BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_IP6] + [SAFI_UNICAST], + BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) || + CHECK_FLAG(tmp_bgp->af_flags[AFI_IP] + [SAFI_UNICAST], BGP_CONFIG_VRF_TO_VRF_EXPORT) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST], + CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6] + [SAFI_UNICAST], BGP_CONFIG_VRF_TO_VRF_EXPORT) || (bgp == bgp_get_evpn() && - (CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN], - BGP_L2VPN_EVPN_ADV_IPV4_UNICAST) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN], - BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN], - BGP_L2VPN_EVPN_ADV_IPV6_UNICAST) || - CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN], - BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) || - (hashcount(tmp_bgp->vnihash))) { + (CHECK_FLAG( + tmp_bgp->af_flags[AFI_L2VPN] + [SAFI_EVPN], + BGP_L2VPN_EVPN_ADV_IPV4_UNICAST) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_L2VPN] + [SAFI_EVPN], + BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_L2VPN] + [SAFI_EVPN], + BGP_L2VPN_EVPN_ADV_IPV6_UNICAST) || + CHECK_FLAG( + tmp_bgp->af_flags[AFI_L2VPN] + [SAFI_EVPN], + BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) || + (tmp_bgp->l3vni)) { vty_out(vty, "%% Cannot delete default BGP instance. Dependent VRF instances exist\n"); return CMD_WARNING_CONFIG_FAILED; @@ -2802,6 +2820,21 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd, return CMD_SUCCESS; } +DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd, + "[no] bgp labeled-unicast explicit-null", + NO_STR BGP_STR + "BGP Labeled-unicast options\n" + "Use explicit-null label values for local prefixes\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (no) + UNSET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL); + else + SET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL); + return CMD_SUCCESS; +} + DEFUN(bgp_suppress_duplicates, bgp_suppress_duplicates_cmd, "bgp suppress-duplicates", BGP_STR @@ -18217,6 +18250,9 @@ int bgp_config_write(struct vty *vty) ? "" : "no "); + if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL)) + vty_out(vty, " bgp labeled-unicast explicit-null\n"); + /* draft-ietf-idr-deprecate-as-set-confed-set */ if (bgp->reject_as_sets) vty_out(vty, " bgp reject-as-sets\n"); @@ -19136,6 +19172,9 @@ void bgp_vty_init(void) install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd); install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd); + /* bgp labeled-unicast explicit-null */ + install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd); + /* bgp suppress-duplicates */ install_element(BGP_NODE, &bgp_suppress_duplicates_cmd); install_element(BGP_NODE, &no_bgp_suppress_duplicates_cmd); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index a08a2870ee..b6491bf799 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -500,6 +500,8 @@ struct bgp { #define BGP_FLAG_HARD_ADMIN_RESET (1ULL << 31) /* Evaluate the AIGP attribute during the best path selection process */ #define BGP_FLAG_COMPARE_AIGP (1ULL << 32) +/* For BGP-LU, force local prefixes to use explicit-null label */ +#define BGP_FLAG_LU_EXPLICIT_NULL (1ULL << 33) /* BGP default address-families. * New peers inherit enabled afi/safis from bgp instance. diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 8d6db9d775..67c70431bd 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -51,6 +51,8 @@ #include <execinfo.h> #endif /* HAVE_GLIBC_BACKTRACE */ +#define DEBUG_CLEANUP 0 + struct ethaddr rfapi_ethaddr0 = {{0}}; #define DEBUG_RFAPI_STR "RF API debugging/testing command\n" @@ -3677,11 +3679,36 @@ void rfapi_delete(struct bgp *bgp) { extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */ +#if DEBUG_CLEANUP + zlog_debug("%s: bgp %p", __func__, bgp); +#endif + /* * This clears queries and registered routes, and closes nves */ if (bgp->rfapi) rfp_clear_vnc_nve_all(); + + /* + * close any remaining descriptors + */ + struct rfapi *h = bgp->rfapi; + + if (h && h->descriptors.count) { + struct listnode *node, *nnode; + struct rfapi_descriptor *rfd; +#if DEBUG_CLEANUP + zlog_debug("%s: descriptor count %u", __func__, + h->descriptors.count); +#endif + for (ALL_LIST_ELEMENTS(&h->descriptors, node, nnode, rfd)) { +#if DEBUG_CLEANUP + zlog_debug("%s: closing rfd %p", __func__, rfd); +#endif + (void)rfapi_close(rfd); + } + } + bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg); bgp->rfapi_cfg = NULL; bgp_rfapi_destroy(bgp, bgp->rfapi); diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index be9d30768c..5784f95b27 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -40,6 +40,7 @@ #define DEBUG_PENDING_DELETE_ROUTE 0 #define DEBUG_NHL 0 #define DEBUG_RIB_SL_RD 0 +#define DEBUG_CLEANUP 0 /* forward decl */ #if DEBUG_NHL @@ -327,6 +328,11 @@ static void rfapiRibStartTimer(struct rfapi_descriptor *rfd, tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE, sizeof(struct rfapi_rib_tcb)); } +#if DEBUG_CLEANUP + zlog_debug("%s: rfd %p, rn %p, ri %p, tcb %p", __func__, rfd, rn, ri, + tcb); +#endif + tcb->rfd = rfd; tcb->ri = ri; tcb->rn = rn; @@ -506,6 +512,16 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) NULL, (void **)&ri)) { + if (ri->timer) { + struct rfapi_rib_tcb + *tcb; + + tcb = EVENT_ARG( + ri->timer); + EVENT_OFF(ri->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, + tcb); + } rfapi_info_free(ri); skiplist_delete_first( (struct skiplist *) @@ -555,6 +571,9 @@ void rfapiRibFree(struct rfapi_descriptor *rfd) { afi_t afi; +#if DEBUG_CLEANUP + zlog_debug("%s: rfd %p", __func__, rfd); +#endif /* * NB rfd is typically detached from master list, so is not included diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 2877c29c20..29698846c3 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4888,6 +4888,7 @@ static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf, clear_vnc_prefix(&cda); vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count, start_count); + print_cleared_stats(&cda); /* frees lists in cda */ return CMD_SUCCESS; } diff --git a/configure.ac b/configure.ac index f3968df2aa..79288c67e9 100644 --- a/configure.ac +++ b/configure.ac @@ -299,14 +299,20 @@ if test "$enable_scripting" = "yes"; then AX_LUA_HEADERS([], [ AC_MSG_ERROR([Lua 5.3 headers are required to build with Lua support. No other version is supported.]) ]) - AX_LUA_LIBS([ + PKG_CHECK_MODULES([LUA], [lua5.3], [ AC_DEFINE([HAVE_SCRIPTING], [1], [Have support for scripting]) - LIBS="$LIBS $LUA_LIB" + LIBS="$LIBS $LUA_LIBS" SCRIPTING=true ], [ - SCRIPTING=false - AC_MSG_ERROR([Lua 5.3 libraries are required to build with Lua support. No other version is supported.]) - ]) + AX_LUA_LIBS([ + AC_DEFINE([HAVE_SCRIPTING], [1], [Have support for scripting]) + LIBS="$LIBS $LUA_LIB" + SCRIPTING=true + ], [ + SCRIPTING=false + AC_MSG_ERROR([Lua 5.3 libraries are required to build with Lua support. No other version is supported.]) + ]) + ]) fi dnl the following flags go in CFLAGS rather than AC_CFLAGS since they make diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst index b7021b69a1..2fe0a5989b 100644 --- a/doc/developer/logging.rst +++ b/doc/developer/logging.rst @@ -502,6 +502,51 @@ General utility formats representation for a hexdump. Non-printable characters are replaced with a dot. +.. frrfmt:: %pIS (struct iso_address *) + + ([IS]o Network address) - Format ISO Network Address + + ``%pIS``: :frrfmtout:`01.0203.04O5` + ISO Network address is printed as separated byte. The number of byte of the + address is embeded in the `iso_net` structure. + + ``%pISl``: :frrfmtout:`01.0203.04O5.0607.0809.1011.1213.14` - long format to + print the long version of the ISO Network address which include the System + ID and the PSEUDO-ID of the IS-IS system + + Note that the `ISO_ADDR_STRLEN` define gives the total size of the string + that could be used in conjunction to snprintfrr. Use like:: + + char buf[ISO_ADDR_STRLEN]; + struct iso_net addr = {.len = 4, .addr = {1, 2, 3, 4}}; + snprintfrr(buf, ISO_ADDR_STRLEN, "%pIS", &addr); + +.. frrfmt:: %pSY (uint8_t *) + + (IS-IS [SY]stem ID) - Format IS-IS System ID + + ``%pSY``: :frrfmtout:`0102.0304.0506` + +.. frrfmt:: %pPN (uint8_t *) + + (IS-IS [P]seudo [N]ode System ID) - Format IS-IS Pseudo Node System ID + + ``%pPN``: :frrfmtout:`0102.0304.0506.07` + +.. frrfmt:: %pLS (uint8_t *) + + (IS-IS [L]sp fragment [S]ystem ID) - Format IS-IS Pseudo System ID + + ``%pLS``: :frrfmtout:`0102.0304.0506.07-08` + + Note that the `ISO_SYSID_STRLEN` define gives the total size of the string + that could be used in conjunction to snprintfrr. Use like:: + + char buf[ISO_SYSID_STRLEN]; + uint8_t id[8] = {1, 2, 3, 4 , 5 , 6 , 7, 8}; + snprintfrr(buf, SYS_ID_SIZE, "%pSY", id); + + Integer formats ^^^^^^^^^^^^^^^ diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 946f0699f2..97d7ce6b75 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2767,6 +2767,17 @@ happened automatically if local-role is set. value of his role (by setting local-role on his side). Otherwise, a Role Mismatch Notification will be sent. +Labeled unicast +--------------- + +*bgpd* supports labeled information, as per :rfc:`3107`. + +.. clicmd:: bgp labeled-unicast explicit-null + +By default, locally advertised prefixes use the `implicit-null` label to +encode in the outgoing NLRI. The following command uses the `explicit-null` +label value for all the BGP instances. + .. _bgp-l3vpn-vrfs: L3VPN VRFs diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 90c13d4f93..88fa78ddfa 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -68,6 +68,10 @@ writing, *isisd* does not support multiple ISIS processes. Log changes in adjacency state. +.. clicmd:: log-pdu-drops + + Log any dropped PDUs. + .. clicmd:: metric-style [narrow | transition | wide] Set old-style (ISO 10589) or new-style packet formats: diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst index 6ea7e7891a..6614a568f8 100644 --- a/doc/user/mgmtd.rst +++ b/doc/user/mgmtd.rst @@ -70,14 +70,6 @@ Frontend Interface and MGMTd: database. - Data can be retrieved anytime using GET_CONFIG/GET_DATA API. - - Startup Database: - - - Consists of configuration data items only. - - This is a copy of Running database that is stored in persistent - storage and is used to load configurations on Running database during - MGMT daemon startup. - - Data cannot be edited/retrieved directly via Frontend interface. - - Operational Database: - Consists of non-configurational data items. @@ -313,8 +305,7 @@ MGMT Configuration commands .. clicmd:: mgmt commit apply This command commits any uncommited changes in the Candidate DB to the - Running DB. It also dumps a copy of the tree in JSON format into - frr_startup.json. + Running DB. .. clicmd:: mgmt commit check diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 30d55f34a7..5171832604 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -310,6 +310,18 @@ To start OSPF process you have to specify the OSPF router. of packets to process before returning. The defult value of this parameter is 20. +.. clicmd:: socket buffer <send | recv | all> (1-4000000000) + + This command controls the ospf instance's socket buffer sizes. The + 'no' form resets one or both values to the default. + +.. clicmd:: no socket-per-interface + + Ordinarily, ospfd uses a socket per interface for sending + packets. This command disables those per-interface sockets, and + causes ospfd to use a single socket per ospf instance for sending + and receiving packets. + .. _ospf-area: Areas @@ -325,7 +337,6 @@ Areas announced to other areas. This command can be used only in ABR and ONLY router-LSAs (Type-1) and network-LSAs (Type-2) (i.e. LSAs with scope area) can be summarized. Type-5 AS-external-LSAs can't be summarized - their scope is AS. - Summarizing Type-7 AS-external-LSAs isn't supported yet by FRR. .. code-block:: frr @@ -431,6 +442,31 @@ Areas configured not to advertise forwarding addresses into the backbone to direct forwarded traffic to the NSSA ABR translator. +.. clicmd:: area A.B.C.D nssa default-information-originate [metric-type (1-2)] [metric (0-16777214)] + +.. clicmd:: area (0-4294967295) nssa default-information-originate [metric-type (1-2)] [metric (0-16777214)] + + NSSA ABRs and ASBRs can be configured with the `default-information-originate` + option to originate a Type-7 default route into the NSSA area. In the case + of NSSA ASBRs, the origination of the default route is conditioned to the + existence of a default route in the RIB that wasn't learned via the OSPF + protocol. + +.. clicmd:: area A.B.C.D nssa range A.B.C.D/M [<not-advertise|cost (0-16777215)>] + +.. clicmd:: area (0-4294967295) nssa range A.B.C.D/M [<not-advertise|cost (0-16777215)>] + + Summarize a group of external subnets into a single Type-7 LSA, which is + then translated to a Type-5 LSA and avertised to the backbone. + This command can only be used at the area boundary (NSSA ABR router). + + By default, the metric of the summary route is calculated as the highest + metric among the summarized routes. The `cost` option, however, can be used + to set an explicit metric. + + The `not-advertise` option, when present, prevents the summary route from + being advertised, effectively filtering the summarized routes. + .. clicmd:: area A.B.C.D default-cost (0-16777215) diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 4a24fa52be..5ea33d62c9 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -424,6 +424,8 @@ BGP :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021.` - :rfc:`9234` :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022.` +- :rfc:`9384` + :t:`A BGP Cease NOTIFICATION Subcode for Bidirectional Forwarding Detection (BFD). J. Haas. March 2023.` OSPF ---- diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 72471d7af0..d70c3c0e64 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -387,9 +387,14 @@ cause great confusion. .. clicmd:: show ip igmp [vrf NAME] join [json] Display IGMP static join information for a specific vrf. - If "vrf all" is provided, it displays information for all the vrfs present. + +.. index:: show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail] [json$json] +.. clicmd:: show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail] [json$json] -.. clicmd:: show ip igmp groups + Display IGMP static join information for all the vrfs present. + +.. index:: show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json] +.. clicmd:: show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json] Display IGMP groups information. diff --git a/docker/ubi-8/Dockerfile b/docker/ubi-8/Dockerfile deleted file mode 100644 index 1d1e8bdc6e..0000000000 --- a/docker/ubi-8/Dockerfile +++ /dev/null @@ -1,83 +0,0 @@ -# This stage builds an rpm from the source -FROM registry.access.redhat.com/ubi8/ubi:8.5 as ubi-8-builder - -RUN dnf -y update-minimal --security --sec-severity=Important --sec-severity=Critical - -RUN rpm --import https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official \ - && dnf config-manager --disableplugin subscription-manager --add-repo http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os \ - && dnf config-manager --disableplugin subscription-manager --add-repo http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os \ - && dnf config-manager --disableplugin subscription-manager --add-repo http://mirror.centos.org/centos/8-stream/PowerTools/x86_64/os - -RUN dnf install -qy https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \ - && dnf install --enablerepo=* -qy rpm-build git autoconf pcre-devel \ - systemd-devel automake libtool make readline-devel texinfo \ - net-snmp-devel pkgconfig groff pkgconfig json-c-devel pam-devel \ - bison flex python3-pytest c-ares-devel python3-devel python3-sphinx \ - libcap-devel platform-python-devel \ - https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \ - https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \ - https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm \ - https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-devel-0.8.0-1.el7.x86_64.rpm - - -COPY . /src - -ARG PKGVER - -RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >> /root/.rpmmacros \ - && cd /src \ - && ./bootstrap.sh \ - && ./configure \ - --enable-rpki \ - --enable-snmp=agentx \ - --enable-numeric-version \ - --with-pkg-extra-version="_palmetto_git$PKGVER" \ - && make dist \ - && cd / \ - && mkdir -p /rpmbuild/{SOURCES,SPECS} \ - && cp /src/frr*.tar.gz /rpmbuild/SOURCES \ - && cp /src/redhat/frr.spec /rpmbuild/SPECS \ - && rpmbuild \ - --define "_topdir /rpmbuild" \ - -ba /rpmbuild/SPECS/frr.spec - -# This stage installs frr from the rpm -FROM registry.access.redhat.com/ubi8/ubi:8.5 -RUN dnf -y update-minimal --security --sec-severity=Important --sec-severity=Critical -ARG FRR_IMAGE_TAG -ARG FRR_RELEASE -ARG FRR_NAME -ARG FRR_VENDOR -LABEL name=$FRR_NAME \ - vendor=$FRR_VENDOR \ - version=$FRR_IMAGE_TAG \ - release=$FRR_RELEASE - -RUN rpm --import https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official \ - && dnf config-manager --disableplugin subscription-manager --add-repo http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os \ - && dnf config-manager --disableplugin subscription-manager --add-repo http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os - -RUN dnf install -qy https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \ - && mkdir -p /pkgs/rpm \ - && dnf install --enablerepo=* -qy https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \ - https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm - -COPY --from=ubi-8-builder /rpmbuild/RPMS/ /pkgs/rpm/ - -RUN dnf install -qy /pkgs/rpm/*/*.rpm \ - && rm -rf /pkgs \ -# Own the config / PID files - && mkdir -p /var/run/frr \ - && chown -R frr:frr /etc/frr /var/run/frr - -# Add tini because no CentOS8 package -ENV TINI_VERSION v0.19.0 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /sbin/tini -RUN chmod +x /sbin/tini - -# Simple init manager for reaping processes and forwarding signals -ENTRYPOINT ["/sbin/tini", "--"] - -# Default CMD starts watchfrr -COPY docker/ubi-8/docker-start /usr/lib/frr/docker-start -CMD ["/usr/lib/frr/docker-start"] diff --git a/docker/ubi8-minimal/Dockerfile b/docker/ubi8-minimal/Dockerfile new file mode 100644 index 0000000000..adb04219be --- /dev/null +++ b/docker/ubi8-minimal/Dockerfile @@ -0,0 +1,132 @@ +# This stage builds an rpm from the source +ARG UBI8_MINIMAL_VERSION +FROM registry.access.redhat.com/ubi8/ubi-minimal:${UBI8_MINIMAL_VERSION} as ubi8-minimal-builder + +RUN rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-8 + +ADD docker/ubi8-minimal/almalinux.repo /etc/yum.repos.d/almalinux.repo + +# ubi8-minimal comes with broken tzdata package installed, so we need to remove them +# and later reinstall it again: https://bugzilla.redhat.com/show_bug.cgi?id=1668185 +RUN rpm --quiet -e --nodeps tzdata >/dev/null 2>&1 + +RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 install \ + autoconf \ + automake \ + bison \ + c-ares-devel \ + flex \ + git \ + groff \ + json-c-devel \ + libcap-devel \ + libssh-devel \ + libtool \ + make \ + net-snmp-devel \ + openssl \ + pam-devel \ + pcre-devel \ + pkgconfig \ + platform-python-devel \ + python3-devel \ + python3-pytest \ + python3-sphinx \ + readline-devel \ + rpm-build \ + systemd-devel \ + texinfo \ + tzdata \ + && microdnf --disableplugin=subscription-manager clean all + +RUN curl -sSL -o /tmp/libyang2.rpm https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-12/RedHat-8-x86_64-Packages/libyang2-2.0.7-1.el8.x86_64.rpm \ + && rpm -i /tmp/libyang2.rpm \ + && rm -f /tmp/libyang2.rpm + +RUN curl -sSL -o /tmp/libyang2-devel.rpm https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-12/RedHat-8-x86_64-Packages/libyang2-devel-2.0.7-1.el8.x86_64.rpm \ + && rpm -i /tmp/libyang2-devel.rpm \ + && rm -f /tmp/libyang2-devel.rpm + +RUN curl -sSL -o /tmp/librtr.rpm https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-149/RedHat-8-x86_64-Packages/librtr-0.8.0-1.el8.x86_64.rpm \ + && rpm -i /tmp/librtr.rpm \ + && rm -f /tmp/librtr.rpm + +RUN curl -sSL -o /tmp/librtr-devel.rpm https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-149/RedHat-8-x86_64-Packages/librtr-devel-0.8.0-1.el8.x86_64.rpm \ + && rpm -i /tmp/librtr-devel.rpm \ + && rm -f /tmp/librtr-devel.rpm + +COPY . /src + +ARG PKGVER + +RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >> /root/.rpmmacros \ + && cd /src \ + && ./bootstrap.sh \ + && ./configure \ + --enable-rpki \ + --enable-snmp=agentx \ + --enable-numeric-version \ + --with-pkg-extra-version="_git$PKGVER" \ + && make dist \ + && cd / \ + && mkdir -p /rpmbuild/{SOURCES,SPECS} \ + && cp /src/frr*.tar.gz /rpmbuild/SOURCES \ + && cp /src/redhat/frr.spec /rpmbuild/SPECS \ + && rpmbuild \ + --define "_topdir /rpmbuild" \ + -ba /rpmbuild/SPECS/frr.spec + +# This stage installs frr from the rpm +FROM registry.access.redhat.com/ubi8/ubi-minimal:${UBI8_MINIMAL_VERSION} +ARG FRR_IMAGE_TAG +ARG FRR_RELEASE +ARG FRR_NAME +ARG FRR_VENDOR +LABEL name=$FRR_NAME \ + vendor=$FRR_VENDOR \ + version=$FRR_IMAGE_TAG \ + release=$FRR_RELEASE + +ADD docker/ubi8-minimal/almalinux.repo /etc/yum.repos.d/almalinux.repo + +RUN rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-8 + +RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 install \ + c-ares \ + initscripts \ + net-snmp-agent-libs \ + net-snmp-libs \ + openssl \ + python3 \ + shadow-utils \ + systemd \ + && microdnf --disableplugin=subscription-manager clean all + +RUN curl -sSL -o /tmp/libyang2.rpm https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-12/RedHat-8-x86_64-Packages/libyang2-2.0.7-1.el8.x86_64.rpm \ + && rpm -i /tmp/libyang2.rpm \ + && rm -f /tmp/libyang2.rpm + +RUN curl -sSL -o /tmp/librtr.rpm https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-149/RedHat-8-x86_64-Packages/librtr-0.8.0-1.el8.x86_64.rpm \ + && rpm -i /tmp/librtr.rpm \ + && rm -f /tmp/librtr.rpm + +COPY --from=ubi8-minimal-builder /rpmbuild/RPMS/ /pkgs/rpm/ + +# Install packages and create FRR files and folders. Be sure to own the config / PID files +RUN rpm -i /pkgs/rpm/x86_64/*.rpm \ + && rm -rf /pkgs \ + && rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* \ + && mkdir -p /var/run/frr \ + && chown -R frr:frr /etc/frr /var/run/frr + +# There is no package for tini, add it manually +ENV TINI_VERSION v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /sbin/tini +RUN chmod +x /sbin/tini + +# Simple init manager for reaping processes and forwarding signals +ENTRYPOINT ["/sbin/tini", "--"] + +# Default CMD starts watchfrr +COPY docker/ubi8-minimal/docker-start /usr/lib/frr/docker-start +CMD ["/usr/lib/frr/docker-start"] diff --git a/docker/ubi8-minimal/almalinux.repo b/docker/ubi8-minimal/almalinux.repo new file mode 100644 index 0000000000..9b9877b180 --- /dev/null +++ b/docker/ubi8-minimal/almalinux.repo @@ -0,0 +1,23 @@ +[AlmaLinux - baseos] +name=AlmaLinux $releasever - BaseOS +mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/baseos +# baseurl=https://repo.almalinux.org/almalinux/$releasever/BaseOS/$basearch/os/ +enabled=1 +gpgcheck=1 +countme=1 + +[AlmaLinux - appstream] +name=AlmaLinux $releasever - AppStream +mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/appstream +# baseurl=https://repo.almalinux.org/almalinux/$releasever/AppStream/$basearch/os/ +enabled=1 +gpgcheck=1 +countme=1 + +[AlmaLinux - powertools] +name=AlmaLinux $releasever - PowerTools +mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/powertools +# baseurl=https://repo.almalinux.org/almalinux/$releasever/PowerTools/$basearch/os/ +enabled=1 +gpgcheck=1 +countme=1 diff --git a/docker/ubi-8/build.sh b/docker/ubi8-minimal/build.sh index 0216636893..2aa45c9bf5 100755 --- a/docker/ubi-8/build.sh +++ b/docker/ubi8-minimal/build.sh @@ -5,37 +5,45 @@ set -e ## # Package version needs to be decimal ## -DISTRO=ubi-8 +DISTRO=ubi8-minimal + +UBI8_MINIMAL_VERSION=$1 +if [ -z "$UBI8_MINIMAL_VERSION" ]; then + UBI8_MINIMAL_VERSION="latest" +fi GITREV="$2" if [ -z "$GITREV" ];then GITREV="$(git rev-parse --short=10 HEAD)" fi -FRR_IMAGE_TAG="$1" +FRR_IMAGE_TAG="$3" if [ -z $FRR_IMAGE_TAG ];then - FRR_IMAGE_TAG="frr:ubi-8-$GITREV" + FRR_IMAGE_TAG="frr:ubi8-minimal-$GITREV" fi PKGVER="$(printf '%u\n' 0x$GITREV)" -FRR_RELEASE="$3" +FRR_RELEASE="$4" if [ -z $FRR_RELEASE ];then FRR_RELEASE=$(git describe --tags --abbrev=0) fi -FRR_NAME=$4 +FRR_NAME=$5 if [ -z $FRR_NAME ];then FRR_NAME=frr fi -FRR_VENDOR=$5 +FRR_VENDOR=$6 if [ -z $FRR_VENDOR ];then FRR_VENDOR=frr fi +DOCKERFILE_PATH="$(dirname $(realpath $0))/Dockerfile" + docker build \ --cache-from="frr:$DISTRO-builder-$GITREV" \ - --file=docker/$DISTRO/Dockerfile \ + --file="$DOCKERFILE_PATH" \ + --build-arg="UBI8_MINIMAL_VERSION=$UBI8_MINIMAL_VERSION" \ --build-arg="PKGVER=$PKGVER" \ --build-arg="FRR_IMAGE_TAG=$FRR_IMAGE_TAG" \ --build-arg="FRR_RELEASE=$FRR_RELEASE" \ diff --git a/docker/ubi-8/docker-start b/docker/ubi8-minimal/docker-start index d954142ab9..d954142ab9 100755 --- a/docker/ubi-8/docker-start +++ b/docker/ubi8-minimal/docker-start diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 4fd39498a0..0be36e175a 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -273,8 +273,8 @@ void fabricd_initial_sync_hello(struct isis_circuit *circuit) if (IS_DEBUG_ADJ_PACKETS) zlog_debug( - "OpenFabric: Started initial synchronization with %s on %s", - sysid_print(circuit->u.p2p.neighbor->sysid), + "OpenFabric: Started initial synchronization with %pSY on %s", + circuit->u.p2p.neighbor->sysid, circuit->interface->name); } @@ -359,7 +359,9 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) return ISIS_TIER_UNDEFINED; } - zlog_info("OpenFabric: Found %s as furthest t0 from local system, dist == %u", rawlspid_print(furthest_t0->N.id), furthest_t0->d_N); + zlog_info( + "OpenFabric: Found %pLS as furthest t0 from local system, dist == %u", + furthest_t0->N.id, furthest_t0->d_N); struct isis_spftree *remote_tree = isis_run_hopcount_spf(area, furthest_t0->N.id, NULL); @@ -372,8 +374,9 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) isis_spftree_del(remote_tree); return ISIS_TIER_UNDEFINED; } else { - zlog_info("OpenFabric: Found %s as furthest from remote dist == %u", rawlspid_print(furthest_from_remote->N.id), - furthest_from_remote->d_N); + zlog_info( + "OpenFabric: Found %pLS as furthest from remote dist == %u", + furthest_from_remote->N.id, furthest_from_remote->d_N); } int64_t tier = furthest_from_remote->d_N - furthest_t0->d_N; diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 1871078cc1..30b71537e0 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -283,6 +283,8 @@ void isis_adj_process_threeway(struct isis_adjacency *adj, } const char *isis_adj_name(const struct isis_adjacency *adj) { + static char buf[ISO_SYSID_STRLEN]; + if (!adj) return "NONE"; @@ -291,8 +293,9 @@ const char *isis_adj_name(const struct isis_adjacency *adj) dyn = dynhn_find_by_id(adj->circuit->isis, adj->sysid); if (dyn) return dyn->hostname; - else - return sysid_print(adj->sysid); + + snprintfrr(buf, sizeof(buf), "%pSY", adj->sysid); + return buf; } void isis_log_adj_change(struct isis_adjacency *adj, enum isis_adj_state old_state, @@ -439,9 +442,8 @@ void isis_adj_print(struct isis_adjacency *adj) if (dyn) zlog_debug("%s", dyn->hostname); - zlog_debug("SystemId %20s SNPA %s, level %d; Holding Time %d", - sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level, - adj->hold_time); + zlog_debug("SystemId %20pSY SNPA %pSY, level %d; Holding Time %d", + adj->sysid, adj->snpa, adj->level, adj->hold_time); if (adj->ipv4_address_count) { zlog_debug("IPv4 Address(es):"); for (unsigned int i = 0; i < adj->ipv4_address_count; i++) @@ -530,7 +532,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json, time2string(adj->last_upd + adj->hold_time - now)); } - json_object_string_add(json, "snpa", snpa_print(adj->snpa)); + json_object_string_addf(json, "snpa", "%pSY", adj->snpa); } if (detail == ISIS_UI_LEVEL_DETAIL) { @@ -581,8 +583,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json, isis_mtid2str(adj->mt_set[i])); } } - json_object_string_add(iface_json, "snpa", - snpa_print(adj->snpa)); + json_object_string_addf(iface_json, "snpa", "%pSY", adj->snpa); if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid); @@ -593,11 +594,8 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json, json_object_string_add(iface_json, "lan-id", buf); } else { - snprintfrr(buf, sizeof(buf), "%s-%02x", - sysid_print(adj->lanid), - adj->lanid[ISIS_SYS_ID_LEN]); - json_object_string_add(iface_json, "lan-id", - buf); + json_object_string_addf(iface_json, "lan-id", + "%pSY", adj->lanid); } json_object_int_add(iface_json, "lan-prio", @@ -626,12 +624,9 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json, area_addr_json); for (unsigned int i = 0; i < adj->area_address_count; i++) { - json_object_string_add( - area_addr_json, "isonet", - isonet_print(adj->area_addresses[i] - .area_addr, - adj->area_addresses[i] - .addr_len)); + json_object_string_addf( + area_addr_json, "isonet", "%pIS", + &adj->area_addresses[i]); } } if (adj->ipv4_address_count) { @@ -736,7 +731,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, + adj->hold_time - now); } else vty_out(vty, "- "); - vty_out(vty, "%-10s", snpa_print(adj->snpa)); + vty_out(vty, "%-10pSY", adj->snpa); vty_out(vty, "\n"); } @@ -780,7 +775,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, vty_out(vty, " %s\n", isis_mtid2str(adj->mt_set[i])); } - vty_out(vty, " SNPA: %s", snpa_print(adj->snpa)); + vty_out(vty, " SNPA: %pSY", adj->snpa); if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid); @@ -788,9 +783,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, vty_out(vty, ", LAN id: %s.%02x", dyn->hostname, adj->lanid[ISIS_SYS_ID_LEN]); else - vty_out(vty, ", LAN id: %s.%02x", - sysid_print(adj->lanid), - adj->lanid[ISIS_SYS_ID_LEN]); + vty_out(vty, ", LAN id: %pPN", adj->lanid); vty_out(vty, "\n"); vty_out(vty, " LAN Priority: %u", @@ -811,11 +804,8 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, vty_out(vty, " Area Address(es):\n"); for (unsigned int i = 0; i < adj->area_address_count; i++) { - vty_out(vty, " %s\n", - isonet_print(adj->area_addresses[i] - .area_addr, - adj->area_addresses[i] - .addr_len)); + vty_out(vty, " %pIS\n", + &adj->area_addresses[i]); } } if (adj->ipv4_address_count) { diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h index f02f7a68ea..c0c8e68145 100644 --- a/isisd/isis_adjacency.h +++ b/isisd/isis_adjacency.h @@ -69,7 +69,7 @@ struct isis_adjacency { struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS]; enum isis_adj_state adj_state; /* adjacencyState */ enum isis_adj_usage adj_usage; /* adjacencyUsage */ - struct area_addr *area_addresses; /* areaAdressesOfNeighbour */ + struct iso_address *area_addresses; /* areaAdressesOfNeighbour */ unsigned int area_address_count; struct nlpids nlpids; /* protocols spoken ... */ struct in_addr *ipv4_addresses; diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 124dcdd86d..feab451233 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -286,8 +286,7 @@ void isis_circuit_add_addr(struct isis_circuit *circuit, if (connected->address->family == AF_INET) { uint32_t addr = connected->address->u.prefix4.s_addr; addr = ntohl(addr); - if (IPV4_NET0(addr) || IPV4_NET127(addr) || IN_CLASSD(addr) - || IPV4_LINKLOCAL(addr)) + if (IPV4_NET0(addr) || IPV4_NET127(addr) || IN_CLASSD(addr)) return; for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ipv4)) @@ -696,10 +695,9 @@ int isis_circuit_up(struct isis_circuit *circuit) } #ifdef EXTREME_DEGUG if (IS_DEBUG_EVENTS) - zlog_debug("%s: if_id %d, isomtu %d snpa %s", __func__, - circuit->interface->ifindex, - ISO_MTU(circuit), - snpa_print(circuit->u.bc.snpa)); + zlog_debug("%s: if_id %d, isomtu %d snpa %pSY", + __func__, circuit->interface->ifindex, + ISO_MTU(circuit), circuit->u.bc.snpa); #endif /* EXTREME_DEBUG */ circuit->u.bc.adjdb[0] = list_new(); @@ -996,8 +994,8 @@ void isis_circuit_print_json(struct isis_circuit *circuit, json_object_string_add(iface_json, "level", circuit_t2string(circuit->is_type)); if (circuit->circ_type == CIRCUIT_T_BROADCAST) - json_object_string_add(iface_json, "snpa", - snpa_print(circuit->u.bc.snpa)); + json_object_string_addf(iface_json, "snpa", "%pSY", + circuit->u.bc.snpa); levels_json = json_object_new_array(); @@ -1123,8 +1121,7 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, circuit_type2string(circuit->circ_type)); vty_out(vty, ", Level: %s", circuit_t2string(circuit->is_type)); if (circuit->circ_type == CIRCUIT_T_BROADCAST) - vty_out(vty, ", SNPA: %-10s", - snpa_print(circuit->u.bc.snpa)); + vty_out(vty, ", SNPA: %-10pSY", circuit->u.bc.snpa); vty_out(vty, "\n"); if (circuit->is_type & IS_LEVEL_1) { vty_out(vty, " Level-1 Information:\n"); diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 7e1bb9255c..ee51e46858 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -3026,6 +3026,26 @@ void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode, } /* + * XPath: /frr-isisd:isis/instance/log-pdu-drops + */ +DEFPY_YANG(log_pdu_drops, log_pdu_drops_cmd, "[no] log-pdu-drops", + NO_STR "Log any dropped PDUs\n") +{ + nb_cli_enqueue_change(vty, "./log-pdu-drops", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_log_pdu_drops(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " log-pdu-drops\n"); +} + +/* * XPath: /frr-isisd:isis/instance/mpls/ldp-sync */ DEFPY(isis_mpls_ldp_sync, isis_mpls_ldp_sync_cmd, "mpls ldp-sync", @@ -3290,6 +3310,7 @@ void isis_cli_init(void) install_element(INTERFACE_NODE, &isis_ti_lfa_cmd); install_element(ISIS_NODE, &log_adj_changes_cmd); + install_element(ISIS_NODE, &log_pdu_drops_cmd); install_element(ISIS_NODE, &isis_mpls_ldp_sync_cmd); install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_cmd); diff --git a/isisd/isis_common.h b/isisd/isis_common.h index c908dc2e24..2ded68f84d 100644 --- a/isisd/isis_common.h +++ b/isisd/isis_common.h @@ -11,14 +11,6 @@ #ifndef ISIS_COMMON_H #define ISIS_COMMON_H -/* - * Area Address - */ -struct area_addr { - uint8_t addr_len; - uint8_t area_addr[20]; -}; - struct isis_passwd { uint8_t len; #define ISIS_PASSWD_TYPE_UNUSED 0 diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index 446e522019..61c49d08a7 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -145,12 +145,10 @@ void dynhn_print_all(struct vty *vty, struct isis *isis) vty_out(vty, "Level System ID Dynamic Hostname\n"); for (ALL_LIST_ELEMENTS_RO(isis->dyn_cache, node, dyn)) { vty_out(vty, "%-7d", dyn->level); - vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id), - dyn->hostname); + vty_out(vty, "%pSY %-15s\n", dyn->id, dyn->hostname); } - vty_out(vty, " * %s %s\n", sysid_print(isis->sysid), - cmd_hostname_get()); + vty_out(vty, " * %pSY %s\n", isis->sysid, cmd_hostname_get()); return; } diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 8a2a2ab971..32231a079f 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -217,8 +217,8 @@ void isis_event_auth_failure(char *area_tag, const char *error_string, uint8_t *sysid) { if (IS_DEBUG_EVENTS) - zlog_debug("ISIS-Evt (%s) Authentication failure %s from %s", - area_tag, error_string, sysid_print(sysid)); + zlog_debug("ISIS-Evt (%s) Authentication failure %s from %pSY", + area_tag, error_string, sysid); return; } diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c index 7a25a92535..abb6168393 100644 --- a/isisd/isis_lfa.c +++ b/isisd/isis_lfa.c @@ -1466,8 +1466,8 @@ int isis_rlfa_activate(struct isis_spftree *spftree, struct rlfa *rlfa, if (ldp_label == MPLS_INVALID_LABEL) { if (IS_DEBUG_LFA) zlog_debug( - "ISIS-LFA: failed to activate RLFA: missing LDP label to reach PQ node through %s", - sysid_print(vadj->sadj->id)); + "ISIS-LFA: failed to activate RLFA: missing LDP label to reach PQ node through %pSY", + vadj->sadj->id); return -1; } diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index d569f6bd5b..fb69448d04 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -193,10 +193,9 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, || (lsp->hdr.rem_lifetime != 0 && rem_lifetime != 0))) { if (IS_DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", - areatag, rawlspid_print(lsp->hdr.lsp_id), - lsp->hdr.seqno, lsp->hdr.checksum, - lsp->hdr.rem_lifetime); + "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus", + areatag, lsp->hdr.lsp_id, lsp->hdr.seqno, + lsp->hdr.checksum, lsp->hdr.rem_lifetime); zlog_debug( "ISIS-Snp (%s): is equal to ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, seqno, checksum, rem_lifetime); @@ -223,9 +222,9 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, && lsp->hdr.rem_lifetime)))) { if (IS_DEBUG_SNP_PACKETS) { zlog_debug( - "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", - areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, - checksum, rem_lifetime); + "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus", + areatag, lsp->hdr.lsp_id, seqno, checksum, + rem_lifetime); zlog_debug( "ISIS-Snp (%s): is newer than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, lsp->hdr.seqno, lsp->hdr.checksum, @@ -234,9 +233,10 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno, return LSP_NEWER; } if (IS_DEBUG_SNP_PACKETS) { - zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus", - areatag, rawlspid_print(lsp->hdr.lsp_id), seqno, - checksum, rem_lifetime); + zlog_debug( + "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus", + areatag, lsp->hdr.lsp_id, seqno, checksum, + rem_lifetime); zlog_debug( "ISIS-Snp (%s): is older than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus", areatag, lsp->hdr.seqno, lsp->hdr.checksum, @@ -554,8 +554,8 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, if (lsp->own_lsp) { flog_err( EC_LIB_DEVELOPMENT, - "ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP", - area->area_tag, rawlspid_print(lsp->hdr.lsp_id)); + "ISIS-Upd (%s): BUG updating LSP %pLS still marked as own LSP", + area->area_tag, lsp->hdr.lsp_id); lsp_clear_data(lsp); lsp->own_lsp = 0; } @@ -634,10 +634,8 @@ struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, put_lsp_hdr(lsp, NULL, false); if (IS_DEBUG_EVENTS) - zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x", - sysid_print(lsp_id), LSP_PSEUDO_ID(lsp->hdr.lsp_id), - LSP_FRAGMENT(lsp->hdr.lsp_id), lsp->hdr.pdu_len, - lsp->hdr.seqno); + zlog_debug("New LSP with ID %pLS len %d seqnum %08x", lsp_id, + lsp->hdr.pdu_len, lsp->hdr.seqno); return lsp; } @@ -704,7 +702,7 @@ void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost, else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost) snprintf(id, sizeof(id), "%.14s", cmd_hostname_get()); else - memcpy(id, sysid_print(lsp_id), 15); + snprintf(id, sizeof(id), "%pSY", lsp_id); if (frag) snprintf(dest, dest_len, "%s.%02x-%02x", id, @@ -1250,10 +1248,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) if (LSP_PSEUDO_ID(ne_id)) { if (area->oldmetric) { lsp_debug( - "ISIS (%s): Adding DIS %s.%02x as old-style neighbor", - area->area_tag, - sysid_print(ne_id), - LSP_PSEUDO_ID(ne_id)); + "ISIS (%s): Adding DIS %pPN as old-style neighbor", + area->area_tag, ne_id); isis_tlvs_add_oldstyle_reach( lsp->tlvs, ne_id, metric); @@ -1279,9 +1275,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) if (area->oldmetric) { lsp_debug( - "ISIS (%s): Adding old-style is reach for %s", - area->area_tag, - sysid_print(ne_id)); + "ISIS (%s): Adding old-style is reach for %pSY", + area->area_tag, ne_id); isis_tlvs_add_oldstyle_reach( lsp->tlvs, ne_id, metric); } @@ -1424,12 +1419,12 @@ int lsp_generate(struct isis_area *area, int level) refresh_time, &area->t_lsp_refresh[level - 1]); if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", - area->area_tag, level, - rawlspid_print(newlsp->hdr.lsp_id), - newlsp->hdr.pdu_len, newlsp->hdr.seqno, - newlsp->hdr.checksum, newlsp->hdr.rem_lifetime, - refresh_time); + zlog_debug( + "ISIS-Upd (%s): Building L%d LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", + area->area_tag, level, newlsp->hdr.lsp_id, + newlsp->hdr.pdu_len, newlsp->hdr.seqno, + newlsp->hdr.checksum, newlsp->hdr.rem_lifetime, + refresh_time); } sched_debug( "ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.", @@ -1506,8 +1501,8 @@ static int lsp_regenerate(struct isis_area *area, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", - area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id), + "ISIS-Upd (%s): Refreshed our L%d LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus", + area->area_tag, level, lsp->hdr.lsp_id, lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, refresh_time); } @@ -1698,9 +1693,9 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, lsp_clear_data(lsp); lsp->tlvs = isis_alloc_tlvs(); lsp_debug( - "ISIS (%s): Constructing pseudo LSP %s for interface %s level %d", - area->area_tag, rawlspid_print(lsp->hdr.lsp_id), - circuit->interface->name, level); + "ISIS (%s): Constructing pseudo LSP %pLS for interface %s level %d", + area->area_tag, lsp->hdr.lsp_id, circuit->interface->name, + level); lsp->level = level; /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ @@ -1717,10 +1712,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, if (circuit->area->oldmetric) { isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0); - lsp_debug( - "ISIS (%s): Adding %s.%02x as old-style neighbor (self)", - area->area_tag, sysid_print(ne_id), - LSP_PSEUDO_ID(ne_id)); + lsp_debug("ISIS (%s): Adding %pPN as old-style neighbor (self)", + area->area_tag, ne_id); } if (circuit->area->newmetric) { if (area_is_mt(circuit->area)) @@ -1728,10 +1721,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, else mtid = ISIS_MT_DISABLE; isis_tlvs_add_extended_reach(lsp->tlvs, mtid, ne_id, 0, NULL); - lsp_debug( - "ISIS (%s): Adding %s.%02x as te-style neighbor (self)", - area->area_tag, sysid_print(ne_id), - LSP_PSEUDO_ID(ne_id)); + lsp_debug("ISIS (%s): Adding %pPN as te-style neighbor (self)", + area->area_tag, ne_id); } adj_list = list_new(); @@ -1740,8 +1731,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) { if (!(adj->level & level)) { lsp_debug( - "ISIS (%s): Ignoring neighbor %s, level does not intersect", - area->area_tag, sysid_print(adj->sysid)); + "ISIS (%s): Ignoring neighbor %pSY, level does not intersect", + area->area_tag, adj->sysid); continue; } @@ -1753,8 +1744,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, && !(level == IS_LEVEL_2 && adj->sys_type == ISIS_SYSTYPE_L2_IS)) { lsp_debug( - "ISIS (%s): Ignoring neighbor %s, level does not match", - area->area_tag, sysid_print(adj->sysid)); + "ISIS (%s): Ignoring neighbor %pSY, level does not match", + area->area_tag, adj->sysid); continue; } @@ -1762,18 +1753,16 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, if (circuit->area->oldmetric) { isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0); lsp_debug( - "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", - area->area_tag, sysid_print(ne_id), - LSP_PSEUDO_ID(ne_id)); + "ISIS (%s): Adding %pPN as old-style neighbor (peer)", + area->area_tag, ne_id); } if (circuit->area->newmetric) { isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST, ne_id, 0, NULL); lsp_debug( - "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", - area->area_tag, sysid_print(ne_id), - LSP_PSEUDO_ID(ne_id)); + "ISIS (%s): Adding %pPN as te-style neighbor (peer)", + area->area_tag, ne_id); } } list_delete(&adj_list); @@ -1832,10 +1821,9 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", - circuit->area->area_tag, level, - rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, - lsp->hdr.seqno, lsp->hdr.checksum, + "ISIS-Upd (%s): Built L%d Pseudo LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", + circuit->area->area_tag, level, lsp->hdr.lsp_id, + lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, refresh_time); } @@ -1863,8 +1851,8 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) if (!lsp) { flog_err(EC_LIB_DEVELOPMENT, - "lsp_regenerate_pseudo: no l%d LSP %s found!", level, - rawlspid_print(lsp_id)); + "lsp_regenerate_pseudo: no l%d LSP %pLS found!", level, + lsp_id); return ISIS_ERROR; } @@ -1887,10 +1875,9 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", - circuit->area->area_tag, level, - rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len, - lsp->hdr.seqno, lsp->hdr.checksum, + "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus", + circuit->area->area_tag, level, lsp->hdr.lsp_id, + lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, refresh_time); } @@ -2101,10 +2088,9 @@ void lsp_tick(struct event *thread) if (lsp->age_out == 0) { zlog_debug( - "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out", + "ISIS-Upd (%s): L%u LSP %pLS seq 0x%08x aged out", area->area_tag, lsp->level, - rawlspid_print(lsp->hdr.lsp_id), - lsp->hdr.seqno); + lsp->hdr.lsp_id, lsp->hdr.seqno); /* if we're aging out fragment 0, lsp_destroy() * below will delete all other fragments too, @@ -2207,11 +2193,10 @@ void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit, const char *func, const char *file, int line) { if (IS_DEBUG_FLOODING) { - zlog_debug("Flooding LSP %s%s%s (From %s %s:%d)", - rawlspid_print(lsp->hdr.lsp_id), - circuit ? " except on " : "", - circuit ? circuit->interface->name : "", - func, file, line); + zlog_debug("Flooding LSP %pLS%s%s (From %s %s:%d)", + lsp->hdr.lsp_id, circuit ? " except on " : "", + circuit ? circuit->interface->name : "", func, file, + line); } if (!fabricd) diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 95d24036ec..09ffa3479a 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -32,48 +32,13 @@ #include "isisd/isis_dynhn.h" /* staticly assigned vars for printing purposes */ +static char sys_hostname[ISO_SYSID_STRLEN]; struct in_addr new_prefix; -/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */ -/* + place for #0 termination */ -char isonet[51]; /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */ char datestring[20]; char nlpidstring[30]; /* - * This converts the isonet to its printable format - */ -const char *isonet_print(const uint8_t *from, int len) -{ - int i = 0; - char tbuf[4]; - isonet[0] = '\0'; - - if (!from) - return "unknown"; - - while (i < len) { - if (i & 1) { - snprintf(tbuf, sizeof(tbuf), "%02x", *(from + i)); - strlcat(isonet, tbuf, sizeof(isonet)); - } else { - if (i == (len - 1)) { /* No dot at the end of address */ - snprintf(tbuf, sizeof(tbuf), "%02x", - *(from + i)); - strlcat(isonet, tbuf, sizeof(isonet)); - } else { - snprintf(tbuf, sizeof(tbuf), "%02x.", - *(from + i)); - strlcat(isonet, tbuf, sizeof(isonet)); - } - } - i++; - } - - return isonet; -} - -/* * Returns 0 on error, length of buff on ok * extract dot from the dotted str, and insert all the number in a buff */ @@ -307,60 +272,6 @@ const char *isis_hello_padding2string(int hello_padding_type) return NULL; /* not reached */ } -/* - * Print functions - we print to static vars - */ -const char *snpa_print(const uint8_t *from) -{ - return isis_format_id(from, ISIS_SYS_ID_LEN); -} - -const char *sysid_print(const uint8_t *from) -{ - return isis_format_id(from, ISIS_SYS_ID_LEN); -} - -const char *rawlspid_print(const uint8_t *from) -{ - return isis_format_id(from, 8); -} - -#define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00") -const char *isis_format_id(const uint8_t *id, size_t len) -{ -#define FORMAT_BUF_COUNT 4 - static char buf_ring[FORMAT_BUF_COUNT][FORMAT_ID_SIZE]; - static size_t cur_buf = 0; - - char *rv; - - cur_buf++; - if (cur_buf >= FORMAT_BUF_COUNT) - cur_buf = 0; - - rv = buf_ring[cur_buf]; - - if (!id) { - snprintf(rv, FORMAT_ID_SIZE, "unknown"); - return rv; - } - - if (len < 6) { - snprintf(rv, FORMAT_ID_SIZE, "Short ID"); - return rv; - } - - snprintf(rv, FORMAT_ID_SIZE, "%02x%02x.%02x%02x.%02x%02x", id[0], id[1], - id[2], id[3], id[4], id[5]); - - if (len > 6) - snprintf(rv + 14, FORMAT_ID_SIZE - 14, ".%02x", id[6]); - if (len > 7) - snprintf(rv + 17, FORMAT_ID_SIZE - 17, "-%02x", id[7]); - - return rv; -} - const char *time2string(uint32_t time) { uint32_t rest; @@ -474,7 +385,8 @@ const char *print_sys_hostname(const uint8_t *sysid) return dyn->hostname; } - return sysid_print(sysid); + snprintfrr(sys_hostname, ISO_SYSID_STRLEN, "%pSY", sysid); + return sys_hostname; } /* @@ -508,11 +420,11 @@ void zlog_dump_data(void *data, int len) /* store hex str (for left side) */ snprintf(bytestr, sizeof(bytestr), "%02X ", *p); - strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1); + strlcat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1); /* store char str (for right side) */ snprintf(bytestr, sizeof(bytestr), "%c", c); - strncat(charstr, bytestr, + strlcat(charstr, bytestr, sizeof(charstr) - strlen(charstr) - 1); if ((i % 16) == 0) { @@ -523,9 +435,9 @@ void zlog_dump_data(void *data, int len) charstr[0] = 0; } else if ((i % 8) == 0) { /* half line: add whitespaces */ - strncat(hexstr, " ", + strlcat(hexstr, " ", sizeof(hexstr) - strlen(hexstr) - 1); - strncat(charstr, " ", + strlcat(charstr, " ", sizeof(charstr) - strlen(charstr) - 1); } p++; /* next byte */ diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index 01d9abe869..3a1d136b1d 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -28,11 +28,6 @@ int sysid2buff(uint8_t *, const char *); /* * Printing functions */ -const char *isonet_print(const uint8_t *, int len); -const char *sysid_print(const uint8_t *); -const char *snpa_print(const uint8_t *); -const char *rawlspid_print(const uint8_t *); -const char *isis_format_id(const uint8_t *id, size_t len); const char *time2string(uint32_t); const char *nlpid2str(uint8_t nlpid); /* typedef struct nlpids nlpids; */ diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index fcc0f53815..d04a24dc46 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -507,8 +507,8 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs, /* Check if MT is enable for this area */ if (!area_is_mt(area)) { lsp_debug( - "ISIS (%s): Adding %s.%02x as te-style neighbor (MT disable)", - area->area_tag, sysid_print(id), LSP_PSEUDO_ID(id)); + "ISIS (%s): Adding %pPN as te-style neighbor (MT disable)", + area->area_tag, id); isis_tlvs_add_extended_reach(tlvs, ISIS_MT_DISABLE, id, metric, ext); return; @@ -518,15 +518,12 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs, for (unsigned int i = 0; i < mt_count; i++) { uint16_t mtid = mt_set[i]; if (mt_set[i] == ISIS_MT_IPV4_UNICAST) { - lsp_debug( - "ISIS (%s): Adding %s.%02x as te-style neighbor", - area->area_tag, sysid_print(id), - LSP_PSEUDO_ID(id)); + lsp_debug("ISIS (%s): Adding %pPN as te-style neighbor", + area->area_tag, id); } else { lsp_debug( - "ISIS (%s): Adding %s.%02x as mt-style neighbor for %s", - area->area_tag, sysid_print(id), - LSP_PSEUDO_ID(id), isis_mtid2str(mtid)); + "ISIS (%s): Adding %pPN as mt-style neighbor for %s", + area->area_tag, id, isis_mtid2str(mtid)); } isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, ext); } diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 7dc3a0eb3d..9141bfc46c 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -559,6 +559,13 @@ const struct frr_yang_module_info frr_isisd_info = { }, }, { + .xpath = "/frr-isisd:isis/instance/log-pdu-drops", + .cbs = { + .cli_show = cli_show_isis_log_pdu_drops, + .modify = isis_instance_log_pdu_drops_modify, + }, + }, + { .xpath = "/frr-isisd:isis/instance/mpls-te", .cbs = { .cli_show = cli_show_isis_mpls_te, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index 480b2ce041..9a1f1f786f 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -196,6 +196,7 @@ int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_modify( int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_destroy( struct nb_cb_destroy_args *args); int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args); +int isis_instance_log_pdu_drops_modify(struct nb_cb_modify_args *args); int isis_instance_mpls_te_create(struct nb_cb_create_args *args); int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args); int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args); @@ -609,6 +610,8 @@ void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_log_pdu_drops(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults); void cli_show_isis_mpls_ldp_sync(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty, diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 3817465a64..022bfbed6e 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -103,14 +103,14 @@ int isis_instance_is_type_modify(struct nb_cb_modify_args *args) } struct sysid_iter { - struct area_addr *addr; + struct iso_address *addr; bool same; }; static int sysid_iter_cb(const struct lyd_node *dnode, void *arg) { struct sysid_iter *iter = arg; - struct area_addr addr; + struct iso_address addr; const char *net; net = yang_dnode_get_string(dnode, NULL); @@ -130,7 +130,7 @@ static int sysid_iter_cb(const struct lyd_node *dnode, void *arg) int isis_instance_area_address_create(struct nb_cb_create_args *args) { struct isis_area *area; - struct area_addr addr, *addrr = NULL, *addrp = NULL; + struct iso_address addr, *addrr = NULL, *addrp = NULL; struct listnode *node; struct sysid_iter iter; uint8_t buff[255]; @@ -161,7 +161,8 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args) } break; case NB_EV_PREPARE: - addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); + addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, + sizeof(struct iso_address)); addrr->addr_len = dotformat2buff(buff, net_title); memcpy(addrr->area_addr, buff, addrr->addr_len); args->resource->ptr = addrr; @@ -217,7 +218,7 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args) int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args) { - struct area_addr addr, *addrp = NULL; + struct iso_address addr, *addrp = NULL; struct listnode *node; uint8_t buff[255]; struct isis_area *area; @@ -1830,6 +1831,23 @@ int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args) } /* + * XPath: /frr-isisd:isis/instance/log-pdu-drops + */ +int isis_instance_log_pdu_drops_modify(struct nb_cb_modify_args *args) +{ + struct isis_area *area; + bool log = yang_dnode_get_bool(args->dnode, NULL); + + if (args->event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(args->dnode, NULL, true); + area->log_pdu_drops = log ? 1 : 0; + + return NB_OK; +} + +/* * XPath: /frr-isisd:isis/instance/mpls-te */ int isis_instance_mpls_te_create(struct nb_cb_create_args *args) diff --git a/isisd/isis_nb_notifications.c b/isisd/isis_nb_notifications.c index 94b1c47d3e..5a1e312b4d 100644 --- a/isisd/isis_nb_notifications.c +++ b/isisd/isis_nb_notifications.c @@ -134,6 +134,7 @@ void isis_notif_lsp_too_large(const struct isis_circuit *circuit, const char *xpath = "/frr-isisd:lsp-too-large"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_area *area = circuit->area; @@ -143,7 +144,8 @@ void isis_notif_lsp_too_large(const struct isis_circuit *circuit, data = yang_data_new_uint32(xpath_arg, pdu_size); listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); hook_call(isis_hook_lsp_too_large, circuit, pdu_size, lsp_id); @@ -180,11 +182,13 @@ void isis_notif_corrupted_lsp(const struct isis_area *area, const char *xpath = "/frr-isisd:corrupted-lsp-detected"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; notif_prep_instance_hdr(xpath, area, "default", arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); hook_call(isis_hook_corrupted_lsp, area); @@ -201,11 +205,13 @@ void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *xpath = "/frr-isisd:attempt-to-exceed-max-sequence"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; notif_prep_instance_hdr(xpath, area, "default", arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); hook_call(isis_hook_lsp_exceed_max, area, lsp_id); @@ -299,6 +305,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj, const char *xpath = "/frr-isisd:adjacency-state-change"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_circuit *circuit = adj->circuit; struct isis_area *area = circuit->area; @@ -312,7 +319,8 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj, listnode_add(arguments, data); } snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath); - data = yang_data_new_string(xpath_arg, sysid_print(adj->sysid)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); @@ -389,13 +397,15 @@ void isis_notif_lsp_received(const struct isis_circuit *circuit, const char *xpath = "/frr-isisd:lsp-received"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_area *area = circuit->area; notif_prep_instance_hdr(xpath, area, "default", arguments); notif_prepr_iface_hdr(xpath, circuit, arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); data = yang_data_new_uint32(xpath_arg, seqno); @@ -419,11 +429,13 @@ void isis_notif_lsp_gen(const struct isis_area *area, const uint8_t *lsp_id, const char *xpath = "/frr-isisd:lsp-generation"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; notif_prep_instance_hdr(xpath, area, "default", arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); data = yang_data_new_uint32(xpath_arg, seqno); @@ -503,13 +515,15 @@ void isis_notif_lsp_error(const struct isis_circuit *circuit, const char *xpath = "/frr-isisd:lsp-error-detected"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_area *area = circuit->area; notif_prep_instance_hdr(xpath, area, "default", arguments); notif_prepr_iface_hdr(xpath, circuit, arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); data = yang_data_new_binary(xpath_arg, raw_pdu, raw_pdu_len); @@ -530,13 +544,15 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit, const char *xpath = "/frr-isisd:sequence-number-skipped"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_area *area = circuit->area; notif_prep_instance_hdr(xpath, area, "default", arguments); notif_prepr_iface_hdr(xpath, circuit, arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); hook_call(isis_hook_seqno_skipped, circuit, lsp_id); @@ -553,13 +569,15 @@ void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, const char *xpath = "/frr-isisd:own-lsp-purge"; struct list *arguments = yang_data_list_new(); char xpath_arg[XPATH_MAXLEN]; + char xpath_value[ISO_SYSID_STRLEN]; struct yang_data *data; struct isis_area *area = circuit->area; notif_prep_instance_hdr(xpath, area, "default", arguments); notif_prepr_iface_hdr(xpath, circuit, arguments); snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id); + data = yang_data_new_string(xpath_arg, xpath_value); listnode_add(arguments, data); hook_call(isis_hook_own_lsp_purge, circuit, lsp_id); diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c index 13fdddf555..b7c33ed27b 100644 --- a/isisd/isis_nb_state.c +++ b/isisd/isis_nb_state.c @@ -132,8 +132,11 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_sysid_get_elem( struct nb_cb_get_elem_args *args) { const struct isis_adjacency *adj = args->list_entry; + char xpath_value[ISO_SYSID_STRLEN]; - return yang_data_new_string(args->xpath, sysid_print(adj->sysid)); + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid); + + return yang_data_new_string(args->xpath, xpath_value); } /* @@ -158,8 +161,11 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_snpa_get_elem( struct nb_cb_get_elem_args *args) { const struct isis_adjacency *adj = args->list_entry; + char xpath_value[ISO_SYSID_STRLEN]; + + snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->snpa); - return yang_data_new_string(args->xpath, snpa_print(adj->snpa)); + return yang_data_new_string(args->xpath, xpath_value); } /* diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index d53d43ad0e..0cd43a7abc 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -514,9 +514,9 @@ static int process_lan_hello(struct iih_info *iih) if (IS_DEBUG_ADJ_PACKETS) { zlog_debug( - "ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, cirID %u, length %zd", - iih->circuit->area->area_tag, iih->level, - snpa_print(iih->ssnpa), iih->circuit->interface->name, + "ISIS-Adj (%s): Rcvd L%d LAN IIH from %pSY on %s, cirType %s, cirID %u, length %zd", + iih->circuit->area->area_tag, iih->level, iih->ssnpa, + iih->circuit->interface->name, circuit_t2string(iih->circuit->is_type), iih->circuit->circuit_id, stream_get_endp(iih->circuit->rcv_stream)); @@ -862,31 +862,32 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, #ifndef FABRICD /* send northbound notification */ + char buf[ISO_SYSID_STRLEN]; + + snprintfrr(buf, ISO_SYSID_STRLEN, "%pSY", hdr.lsp_id); isis_notif_lsp_received(circuit, hdr.lsp_id, hdr.seqno, time(NULL), - sysid_print(hdr.lsp_id)); + buf); #endif /* ifndef FABRICD */ if (pdu_len_validate(hdr.pdu_len, circuit)) { - zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %hu", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - hdr.pdu_len); + zlog_debug("ISIS-Upd (%s): LSP %pLS invalid LSP length %hu", + circuit->area->area_tag, hdr.lsp_id, hdr.pdu_len); return ISIS_WARNING; } if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus, len %hu, on %s", - circuit->area->area_tag, level, - rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum, - hdr.rem_lifetime, hdr.pdu_len, - circuit->interface->name); + zlog_debug( + "ISIS-Upd (%s): Rcvd L%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus, len %hu, on %s", + circuit->area->area_tag, level, hdr.lsp_id, hdr.seqno, + hdr.checksum, hdr.rem_lifetime, hdr.pdu_len, + circuit->interface->name); } /* lsp is_type check */ if ((hdr.lsp_bits & IS_LEVEL_1) != IS_LEVEL_1) { - zlog_debug( - "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%x", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - hdr.lsp_bits & IS_LEVEL_1_AND_2); + zlog_debug("ISIS-Upd (%s): LSP %pLS invalid LSP is type 0x%x", + circuit->area->area_tag, hdr.lsp_id, + hdr.lsp_bits & IS_LEVEL_1_AND_2); /* continue as per RFC1122 Be liberal in what you accept, and * conservative in what you send */ } @@ -896,27 +897,25 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, if (iso_csum_verify(STREAM_DATA(circuit->rcv_stream) + 12, hdr.pdu_len - 12, hdr.checksum, 12)) { zlog_debug( - "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04hx", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - hdr.checksum); + "ISIS-Upd (%s): LSP %pLS invalid LSP checksum 0x%04hx", + circuit->area->area_tag, hdr.lsp_id, hdr.checksum); return ISIS_WARNING; } /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ if (circuit->ext_domain) { zlog_debug( - "ISIS-Upd (%s): LSP %s received at level %d over circuit with externalDomain = true", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - level); + "ISIS-Upd (%s): LSP %pLS received at level %d over circuit with externalDomain = true", + circuit->area->area_tag, hdr.lsp_id, level); return ISIS_WARNING; } /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ if (!(circuit->is_type & level)) { zlog_debug( - "ISIS-Upd (%s): LSP %s received at level %d over circuit of type %s", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - level, circuit_t2string(circuit->is_type)); + "ISIS-Upd (%s): LSP %pLS received at level %d over circuit of type %s", + circuit->area->area_tag, hdr.lsp_id, level, + circuit_t2string(circuit->is_type)); return ISIS_WARNING; } @@ -1016,11 +1015,11 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, if (circuit->circ_type == CIRCUIT_T_BROADCAST) { if (!isis_adj_lookup_snpa(ssnpa, circuit->u.bc.adjdb[level - 1])) { - zlog_debug("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", - circuit->area->area_tag, - rawlspid_print(hdr.lsp_id), hdr.seqno, - hdr.checksum, hdr.rem_lifetime, - circuit->interface->name); + zlog_debug( + "(%s): DS ======= LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", + circuit->area->area_tag, hdr.lsp_id, hdr.seqno, + hdr.checksum, hdr.rem_lifetime, + circuit->interface->name); goto out; /* Silently discard */ } } @@ -1057,9 +1056,9 @@ dontcheckadj: if (lsp && (lsp->hdr.seqno == hdr.seqno) && (lsp->hdr.checksum != hdr.checksum) && hdr.rem_lifetime) { - zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", - circuit->area->area_tag, rawlspid_print(hdr.lsp_id), - hdr.seqno); + zlog_warn( + "ISIS-Upd (%s): LSP %pLS seq 0x%08x with confused checksum received.", + circuit->area->area_tag, hdr.lsp_id, hdr.seqno); hdr.rem_lifetime = 0; lsp_confusion = true; } else @@ -1153,10 +1152,9 @@ dontcheckadj: } if (IS_DEBUG_UPDATE_PACKETS) zlog_debug( - "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08x", + "ISIS-Upd (%s): (1) re-originating LSP %pLS new seq 0x%08x", circuit->area->area_tag, - rawlspid_print(hdr.lsp_id), - lsp->hdr.seqno); + hdr.lsp_id, lsp->hdr.seqno); } else { /* our own LSP with 0 remaining life time */ #ifndef FABRICD @@ -1194,9 +1192,8 @@ dontcheckadj: #endif /* ifndef FABRICD */ if (IS_DEBUG_UPDATE_PACKETS) { zlog_debug( - "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08x", - circuit->area->area_tag, - rawlspid_print(hdr.lsp_id), + "ISIS-Upd (%s): (2) re-originating LSP %pLS new seq 0x%08x", + circuit->area->area_tag, hdr.lsp_id, lsp->hdr.seqno); } lsp_flood(lsp, NULL); @@ -1361,9 +1358,9 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, if (!is_csnp && (circuit->circ_type == CIRCUIT_T_BROADCAST) && !circuit->u.bc.is_dr[level - 1]) { zlog_debug( - "ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, skipping: we are not the DIS", - circuit->area->area_tag, level, typechar, - snpa_print(ssnpa), circuit->interface->name); + "ISIS-Snp (%s): Rcvd L%d %cSNP from %pSY on %s, skipping: we are not the DIS", + circuit->area->area_tag, level, typechar, ssnpa, + circuit->interface->name); return ISIS_OK; } @@ -1452,16 +1449,16 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, /* debug isis snp-packets */ if (IS_DEBUG_SNP_PACKETS) { - zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", - circuit->area->area_tag, level, typechar, - snpa_print(ssnpa), circuit->interface->name); + zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %pSY on %s", + circuit->area->area_tag, level, typechar, ssnpa, + circuit->interface->name); for (struct isis_lsp_entry *entry = entry_head; entry; entry = entry->next) { zlog_debug( - "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus", - circuit->area->area_tag, typechar, - rawlspid_print(entry->id), entry->seqno, - entry->checksum, entry->rem_lifetime); + "ISIS-Snp (%s): %cSNP entry %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus", + circuit->area->area_tag, typechar, entry->id, + entry->seqno, entry->checksum, + entry->rem_lifetime); } } @@ -1654,14 +1651,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) if (idrp == ISO9542_ESIS) { flog_err(EC_LIB_DEVELOPMENT, "No support for ES-IS packet IDRP=%hhx", idrp); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } if (idrp != ISO10589_ISIS) { flog_err(EC_ISIS_PACKET, "Not an IS-IS packet IDRP=%hhx", idrp); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1672,7 +1669,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) isis_notif_version_skew(circuit, version1, raw_pdu, sizeof(raw_pdu)); #endif /* ifndef FABRICD */ - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_WARNING; } @@ -1696,14 +1693,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) isis_notif_id_len_mismatch(circuit, id_len, raw_pdu, sizeof(raw_pdu)); #endif /* ifndef FABRICD */ - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } uint8_t expected_length; if (pdu_size(pdu_type, &expected_length)) { zlog_warn("Unsupported ISIS PDU %hhu", pdu_type); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_WARNING; } @@ -1711,7 +1708,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) flog_err(EC_ISIS_PACKET, "Expected fixed header length = %hhu but got %hhu", expected_length, length); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1719,7 +1716,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) flog_err( EC_ISIS_PACKET, "PDU is too short to contain fixed header of given PDU type."); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1730,14 +1727,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) isis_notif_version_skew(circuit, version2, raw_pdu, sizeof(raw_pdu)); #endif /* ifndef FABRICD */ - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_WARNING; } if (circuit->is_passive) { zlog_warn("Received ISIS PDU on passive circuit %s", circuit->interface->name); - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_WARNING; } @@ -1756,7 +1753,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) isis_notif_max_area_addr_mismatch(circuit, max_area_addrs, raw_pdu, sizeof(raw_pdu)); #endif /* ifndef FABRICD */ - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1765,8 +1762,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) case L2_LAN_HELLO: case P2P_HELLO: if (fabricd && pdu_type != P2P_HELLO) { - pdu_counter_count(circuit->area->pdu_drop_counters, - pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1777,8 +1773,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) case FS_LINK_STATE: if (fabricd && pdu_type != L2_LINK_STATE && pdu_type != FS_LINK_STATE) { - pdu_counter_count(circuit->area->pdu_drop_counters, - pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } @@ -1791,12 +1786,12 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) retval = process_snp(pdu_type, circuit, ssnpa); break; default: - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return ISIS_ERROR; } if (retval != ISIS_OK) - pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type); + pdu_counter_count_drop(circuit->area, pdu_type); return retval; } @@ -2481,11 +2476,11 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp, if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) { flog_err( EC_ISIS_PACKET, - "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s. LSP Size is %zu while interface stream size is %zu.", - circuit->area->area_tag, lsp->level, - rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, - lsp->hdr.checksum, lsp->hdr.rem_lifetime, - circuit->interface->name, stream_get_endp(lsp->pdu), + "ISIS-Upd (%s): Can't send L%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s. LSP Size is %zu while interface stream size is %zu.", + circuit->area->area_tag, lsp->level, lsp->hdr.lsp_id, + lsp->hdr.seqno, lsp->hdr.checksum, + lsp->hdr.rem_lifetime, circuit->interface->name, + stream_get_endp(lsp->pdu), stream_get_size(circuit->snd_stream)); #ifndef FABRICD /* send a northbound notification */ @@ -2509,14 +2504,14 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp, } if (IS_DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Sending %sL%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", - circuit->area->area_tag, - (tx_type == TX_LSP_CIRCUIT_SCOPED) - ? "Circuit scoped " : "", - lsp->level, - rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, - lsp->hdr.checksum, lsp->hdr.rem_lifetime, - circuit->interface->name); + zlog_debug( + "ISIS-Upd (%s): Sending %sL%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s", + circuit->area->area_tag, + (tx_type == TX_LSP_CIRCUIT_SCOPED) ? "Circuit scoped " + : "", + lsp->level, lsp->hdr.lsp_id, lsp->hdr.seqno, + lsp->hdr.checksum, lsp->hdr.rem_lifetime, + circuit->interface->name); if (IS_DEBUG_PACKET_DUMP) zlog_dump_data(STREAM_DATA(circuit->snd_stream), stream_get_endp(circuit->snd_stream)); @@ -2554,3 +2549,37 @@ out: isis_tx_queue_del(circuit->tx_queue, lsp); } } + +void isis_log_pdu_drops(struct isis_area *area, const char *pdu_type) +{ + uint64_t total_drops = 0; + + for (int i = 0; i < PDU_COUNTER_SIZE; i++) { + if (!area->pdu_drop_counters[i]) + continue; + total_drops += area->pdu_drop_counters[i]; + } + + zlog_info("PDU drop detected of type: %s. %" PRIu64 + " Total Drops; %" PRIu64 " L1 IIH drops; %" PRIu64 + " L2 IIH drops; %" PRIu64 " P2P IIH drops; %" PRIu64 + " L1 LSP drops; %" PRIu64 " L2 LSP drops; %" PRIu64 + " FS LSP drops; %" PRIu64 " L1 CSNP drops; %" PRIu64 + " L2 CSNP drops; %" PRIu64 " L1 PSNP drops; %" PRIu64 + " L2 PSNP drops.", + pdu_type, total_drops, + pdu_counter_get_count(area->pdu_drop_counters, L1_LAN_HELLO), + pdu_counter_get_count(area->pdu_drop_counters, L2_LAN_HELLO), + pdu_counter_get_count(area->pdu_drop_counters, P2P_HELLO), + pdu_counter_get_count(area->pdu_drop_counters, L1_LINK_STATE), + pdu_counter_get_count(area->pdu_drop_counters, L2_LINK_STATE), + pdu_counter_get_count(area->pdu_drop_counters, FS_LINK_STATE), + pdu_counter_get_count(area->pdu_drop_counters, + L1_COMPLETE_SEQ_NUM), + pdu_counter_get_count(area->pdu_drop_counters, + L2_COMPLETE_SEQ_NUM), + pdu_counter_get_count(area->pdu_drop_counters, + L1_PARTIAL_SEQ_NUM), + pdu_counter_get_count(area->pdu_drop_counters, + L2_PARTIAL_SEQ_NUM)); +} diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index ccd89a70f1..5303c61d38 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -206,4 +206,6 @@ void send_lsp(struct isis_circuit *circuit, void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream); int send_hello(struct isis_circuit *circuit, int level); int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa); +void isis_log_pdu_drops(struct isis_area *area, const char *pdu_type); + #endif /* _ZEBRA_ISIS_PDU_H */ diff --git a/isisd/isis_pdu_counter.c b/isisd/isis_pdu_counter.c index 9d07b5e598..a3605a32a1 100644 --- a/isisd/isis_pdu_counter.c +++ b/isisd/isis_pdu_counter.c @@ -8,10 +8,10 @@ #include "vty.h" -#include "isisd/isis_pdu_counter.h" #include "isisd/isisd.h" #include "isisd/isis_circuit.h" #include "isisd/isis_pdu.h" +#include "isisd/isis_pdu_counter.h" static int pdu_type_to_counter_index(uint8_t pdu_type) { @@ -91,3 +91,23 @@ void pdu_counter_print(struct vty *vty, const char *prefix, pdu_counter_index_to_name(i), counter[i]); } } + +void pdu_counter_count_drop(struct isis_area *area, uint8_t pdu_type) +{ + pdu_counter_count(area->pdu_drop_counters, pdu_type); + + if (area->log_pdu_drops) { + isis_log_pdu_drops( + area, pdu_counter_index_to_name( + pdu_type_to_counter_index(pdu_type))); + } +} + +uint64_t pdu_counter_get_count(pdu_counter_t counter, uint8_t pdu_type) +{ + int index = pdu_type_to_counter_index(pdu_type); + + if (index < 0) + return -1; + return counter[index]; +} diff --git a/isisd/isis_pdu_counter.h b/isisd/isis_pdu_counter.h index c53c47368f..5c35b4fb51 100644 --- a/isisd/isis_pdu_counter.h +++ b/isisd/isis_pdu_counter.h @@ -24,5 +24,7 @@ typedef uint64_t pdu_counter_t[PDU_COUNTER_SIZE]; void pdu_counter_print(struct vty *vty, const char *prefix, pdu_counter_t counter); void pdu_counter_count(pdu_counter_t counter, uint8_t pdu_type); +void pdu_counter_count_drop(struct isis_area *area, uint8_t pdu_type); +uint64_t pdu_counter_get_count(pdu_counter_t counter, uint8_t pdu_type); #endif diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c index 6d9974fe9f..f9e3780e29 100644 --- a/isisd/isis_snmp.c +++ b/isisd/isis_snmp.c @@ -833,12 +833,12 @@ static int isis_snmp_conv_next(uint8_t *buf, size_t max_len, size_t *out_len, */ static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len, struct isis_area **ret_area, - struct area_addr **ret_addr) + struct iso_address **ret_addr) { uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX]; size_t addr_len; struct isis_area *area = NULL; - struct area_addr *addr = NULL; + struct iso_address *addr = NULL; struct listnode *addr_node; struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); @@ -880,15 +880,15 @@ static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len, static int isis_snmp_area_addr_lookup_next(oid *oid_idx, size_t oid_idx_len, struct isis_area **ret_area, - struct area_addr **ret_addr) + struct iso_address **ret_addr) { uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX]; size_t addr_len; int try_exact = 0; struct isis_area *found_area = NULL; struct isis_area *area = NULL; - struct area_addr *found_addr = NULL; - struct area_addr *addr = NULL; + struct iso_address *found_addr = NULL; + struct iso_address *addr = NULL; struct listnode *addr_node; struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); @@ -1501,7 +1501,7 @@ static uint8_t *isis_snmp_find_man_area(struct variable *v, oid *name, WriteMethod **write_method) { int res; - struct area_addr *area_addr = NULL; + struct iso_address *area_addr = NULL; oid *oid_idx; size_t oid_idx_len; size_t off = 0; @@ -2485,6 +2485,11 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, uint32_t delta_ticks; time_t now_time; + /* Ring buffer to print SNPA */ +#define FORMAT_BUF_COUNT 4 + static char snpa[FORMAT_BUF_COUNT][ISO_SYSID_STRLEN]; + static size_t cur_buf = 0; + *write_method = NULL; if (*length <= v->namelen) { @@ -2531,9 +2536,10 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, return SNMP_INTEGER(adj->threeway_state); case ISIS_ISADJ_NEIGHSNPAADDRESS: { - const char *snpa = (char *)snpa_print(adj->snpa); - *var_len = strlen(snpa); - return (uint8_t *)snpa; + cur_buf = (cur_buf + 1) % FORMAT_BUF_COUNT; + snprintfrr(snpa[cur_buf], ISO_SYSID_STRLEN, "%pSY", adj->snpa); + *var_len = strlen(snpa[cur_buf]); + return (uint8_t *)snpa[cur_buf]; } case ISIS_ISADJ_NEIGHSYSTYPE: diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index bfe3758cd8..8597049ac0 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1067,8 +1067,8 @@ end: && !isis_level2_adj_up(spftree->area)) { struct prefix_pair ip_info = { {0} }; if (IS_DEBUG_RTE_EVENTS) - zlog_debug("ISIS-Spf (%s): add default %s route", - rawlspid_print(lsp->hdr.lsp_id), + zlog_debug("ISIS-Spf (%pLS): add default %s route", + lsp->hdr.lsp_id, spftree->family == AF_INET ? "ipv4" : "ipv6"); @@ -1207,9 +1207,8 @@ static void isis_spf_preload_tent(struct isis_spftree *spftree, if (isis_lfa_excise_adj_check(spftree, adj_id)) { if (IS_DEBUG_LFA) - zlog_debug("ISIS-SPF: excising adjacency %s", - isis_format_id(sadj->id, - ISIS_SYS_ID_LEN + 1)); + zlog_debug("ISIS-SPF: excising adjacency %pPN", + sadj->id); continue; } @@ -1324,8 +1323,8 @@ static void spf_adj_list_parse_tlv(struct isis_spftree *spftree, LSP_FRAGMENT(lspid) = 0; lsp = lsp_search(spftree->lspdb, lspid); if (lsp == NULL || lsp->hdr.rem_lifetime == 0) { - zlog_warn("ISIS-SPF: No LSP found from root to L%d %s", - spftree->level, rawlspid_print(lspid)); + zlog_warn("ISIS-SPF: No LSP found from root to L%d %pLS", + spftree->level, lspid); return; } @@ -1663,9 +1662,8 @@ static void isis_spf_loop(struct isis_spftree *spftree, lsp = lsp_for_vertex(spftree, vertex); if (!lsp) { - zlog_warn("ISIS-SPF: No LSP found for %s", - isis_format_id(vertex->N.id, - sizeof(vertex->N.id))); + zlog_warn("ISIS-SPF: No LSP found for %pPN", + vertex->N.id); continue; } diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c index cb330603e4..e43b84ab2e 100644 --- a/isisd/isis_sr.c +++ b/isisd/isis_sr.c @@ -1022,14 +1022,14 @@ static void show_node(struct vty *vty, struct isis_area *area, int level) if (!cap) continue; - ttable_add_row( - tt, "%s|%u - %u|%u - %u|%s|%u", - sysid_print(lsp->hdr.lsp_id), cap->srgb.lower_bound, - cap->srgb.lower_bound + cap->srgb.range_size - 1, - cap->srlb.lower_bound, - cap->srlb.lower_bound + cap->srlb.range_size - 1, - cap->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF", - cap->msd); + ttable_add_row(tt, "%pSY|%u - %u|%u - %u|%s|%u", + lsp->hdr.lsp_id, cap->srgb.lower_bound, + cap->srgb.lower_bound + cap->srgb.range_size - 1, + cap->srlb.lower_bound, + cap->srlb.lower_bound + cap->srlb.range_size - 1, + cap->algo[0] == SR_ALGORITHM_SPF ? "SPF" + : "S-SPF", + cap->msd); } /* Dump the generated table. */ diff --git a/isisd/isis_te.c b/isisd/isis_te.c index c0b5f35f47..4e180ead61 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -903,7 +903,7 @@ static int lsp_to_edge_cb(const uint8_t *id, uint32_t metric, bool old_metric, struct ls_edge *edge, *dst; struct ls_attributes *attr; - te_debug(" |- Process Extended IS for %s", sysid_print(id)); + te_debug(" |- Process Extended IS for %pSY", id); /* Check parameters */ if (old_metric || !args || !tlvs) @@ -1077,7 +1077,7 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric, prefix_copy(&p, prefix); else { /* Remove old subnet if any before prefix adjustment */ - subnet = ls_find_subnet(args->ted, *prefix); + subnet = ls_find_subnet(args->ted, prefix); if (subnet) { if (args->export) { subnet->status = DELETE; @@ -1092,10 +1092,10 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric, } /* Search existing Subnet in TED ... */ - subnet = ls_find_subnet(args->ted, p); + subnet = ls_find_subnet(args->ted, &p); /* ... and create a new Subnet if not found */ if (!subnet) { - ls_pref = ls_prefix_new(vertex->node->adv, p); + ls_pref = ls_prefix_new(vertex->node->adv, &p); subnet = ls_subnet_add(args->ted, ls_pref); /* Stop processing if we are unable to create a new subnet */ if (!subnet) @@ -1180,14 +1180,14 @@ static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp) ted = mta->ted; - te_debug("ISIS-TE(%s): Parse LSP %s", lsp->area->area_tag, - sysid_print(lsp->hdr.lsp_id)); + te_debug("ISIS-TE(%s): Parse LSP %pSY", lsp->area->area_tag, + lsp->hdr.lsp_id); /* First parse LSP to obtain the corresponding Vertex */ vertex = lsp_to_vertex(ted, lsp); if (!vertex) { - zlog_warn("Unable to build Vertex from LSP %s. Abort!", - sysid_print(lsp->hdr.lsp_id)); + zlog_warn("Unable to build Vertex from LSP %pSY. Abort!", + lsp->hdr.lsp_id); return; } @@ -1251,8 +1251,8 @@ static void isis_te_delete_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp) if (!IS_MPLS_TE(mta) || !mta->ted || !lsp) return; - te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %s", - lsp->area->area_tag, sysid_print(lsp->hdr.lsp_id)); + te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %pSY", + lsp->area->area_tag, lsp->hdr.lsp_id); /* Compute Link State Node ID from IS-IS sysID ... */ if (lsp->level == ISIS_LEVEL1) @@ -1835,7 +1835,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc, return CMD_WARNING_CONFIG_FAILED; } /* Get the Subnet from the Link State Database */ - subnet = ls_find_subnet(ted, pref); + subnet = ls_find_subnet(ted, &pref); if (!subnet) { vty_out(vty, "No subnet found for ID %pFX\n", &pref); @@ -1848,7 +1848,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc, return CMD_WARNING_CONFIG_FAILED; } /* Get the Subnet from the Link State Database */ - subnet = ls_find_subnet(ted, pref); + subnet = ls_find_subnet(ted, &pref); if (!subnet) { vty_out(vty, "No subnet found for ID %pFX\n", &pref); diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index b52a38be7f..3b6db0ee17 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -661,7 +661,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, sbuf_push( buf, indent, "Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n" - " Neighbor-ID: %s\n", + " Neighbor-ID: %pSY\n", lan->sid, lan->weight, lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? '1' @@ -681,7 +681,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG ? '1' : '0', - isis_format_id(lan->neighbor_id, 6)); + lan->neighbor_id); } } } @@ -1590,14 +1590,14 @@ static void format_item_area_address(uint16_t mtid, struct isis_item *i, int indent) { struct isis_area_address *addr = (struct isis_area_address *)i; + struct iso_address iso_addr; - if (json) { - json_object_string_add(json, "area-addr", - isonet_print(addr->addr, addr->len)); - } else { - sbuf_push(buf, indent, "Area Address: %s\n", - isonet_print(addr->addr, addr->len)); - } + memcpy(iso_addr.area_addr, addr->addr, ISO_ADDR_SIZE); + iso_addr.addr_len = addr->len; + if (json) + json_object_string_addf(json, "area-addr", "%pIS", &iso_addr); + else + sbuf_push(buf, indent, "Area Address: %pIS\n", &iso_addr); } static void free_item_area_address(struct isis_item *i) @@ -1678,17 +1678,18 @@ static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i, struct json_object *json, int indent) { struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i; + char sys_id[ISO_SYSID_STRLEN]; + snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id); if (json) { struct json_object *old_json; old_json = json_object_new_object(); json_object_object_add(json, "old-reach-style", old_json); - json_object_string_add(old_json, "is-reach", - isis_format_id(r->id, 7)); + json_object_string_add(old_json, "is-reach", sys_id); json_object_int_add(old_json, "metric", r->metric); } else sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n", - isis_format_id(r->id, 7), r->metric); + sys_id, r->metric); } static void free_item_oldstyle_reach(struct isis_item *i) @@ -1760,13 +1761,13 @@ static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i, int indent) { struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i; + char sys_id[ISO_SYSID_STRLEN]; - if (json) { - json_object_string_add(json, "lan-neighbor", - isis_format_id(n->mac, 6)); - } else - sbuf_push(buf, indent, "LAN Neighbor: %s\n", - isis_format_id(n->mac, 6)); + snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", n->mac); + if (json) + json_object_string_add(json, "lan-neighbor", sys_id); + else + sbuf_push(buf, indent, "LAN Neighbor: %s\n", sys_id); } static void free_item_lan_neighbor(struct isis_item *i) @@ -1831,23 +1832,25 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i, int indent) { struct isis_lsp_entry *e = (struct isis_lsp_entry *)i; + char sys_id[ISO_SYSID_STRLEN]; + snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pLS", e->id); if (json) { char buf[255]; struct json_object *lsp_json; lsp_json = json_object_new_object(); json_object_object_add(json, "lsp-entry", lsp_json); - json_object_string_add(lsp_json, "id", isis_format_id(e->id, 8)); + json_object_string_add(lsp_json, "id", sys_id); snprintfrr(buf,sizeof(buf),"0x%08x",e->seqno); json_object_string_add(lsp_json, "seq", buf); snprintfrr(buf,sizeof(buf),"0x%04hx",e->checksum); json_object_string_add(lsp_json, "chksum", buf); json_object_int_add(lsp_json, "lifetime", e->checksum); } else - sbuf_push(buf, indent, - "LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n", - isis_format_id(e->id, 8), e->seqno, e->checksum, - e->rem_lifetime); + sbuf_push( + buf, indent, + "LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n", + sys_id, e->seqno, e->checksum, e->rem_lifetime); } static void free_item_lsp_entry(struct isis_item *i) @@ -1919,7 +1922,9 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i, struct json_object *json, int indent) { struct isis_extended_reach *r = (struct isis_extended_reach *)i; + char sys_id[ISO_SYSID_STRLEN]; + snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id); if (json) { struct json_object *reach_json; reach_json = json_object_new_object(); @@ -1927,8 +1932,7 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i, json_object_string_add( reach_json, "mt-id", (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT"); - json_object_string_add(reach_json, "id", - isis_format_id(r->id, 7)); + json_object_string_add(reach_json, "id", sys_id); json_object_int_add(reach_json, "metric", r->metric); if (mtid != ISIS_MT_IPV4_UNICAST) json_object_string_add(reach_json, "mt-name", @@ -1940,7 +1944,7 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i, } else { sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)", (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT", - isis_format_id(r->id, 7), r->metric); + sys_id, r->metric); if (mtid != ISIS_MT_IPV4_UNICAST) sbuf_push(buf, 0, " %s", isis_mtid2str(mtid)); sbuf_push(buf, 0, "\n"); @@ -3125,9 +3129,12 @@ static void format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj, struct sbuf *buf, struct json_object *json, int indent) { + char sys_id[ISO_SYSID_STRLEN]; + if (!threeway_adj) return; + snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", threeway_adj->neighbor_id); if (json) { struct json_object *three_json; three_json = json_object_new_object(); @@ -3140,9 +3147,7 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj, threeway_adj->local_circuit_id); if (!threeway_adj->neighbor_set) return; - json_object_string_add( - three_json, "neigh-system-id", - isis_format_id(threeway_adj->neighbor_id, 6)); + json_object_string_add(three_json, "neigh-system-id", sys_id); json_object_int_add(three_json, "neigh-ext-circuit-id", threeway_adj->neighbor_circuit_id); } else { @@ -3155,8 +3160,7 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj, if (!threeway_adj->neighbor_set) return; - sbuf_push(buf, indent, " Neighbor System ID: %s\n", - isis_format_id(threeway_adj->neighbor_id, 6)); + sbuf_push(buf, indent, " Neighbor System ID: %s\n", sys_id); sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %u\n", threeway_adj->neighbor_circuit_id); } @@ -3988,33 +3992,29 @@ static void format_tlv_purge_originator(struct isis_purge_originator *poi, struct sbuf *buf, struct json_object *json, int indent) { + char sen_id[ISO_SYSID_STRLEN]; + char gen_id[ISO_SYSID_STRLEN]; + if (!poi) return; + snprintfrr(gen_id, ISO_SYSID_STRLEN, "%pSY", poi->generator); + if (poi->sender_set) + snprintfrr(sen_id, ISO_SYSID_STRLEN, "%pSY", poi->sender); + if (json) { struct json_object *purge_json; purge_json = json_object_new_object(); json_object_object_add(json, "purge_originator", purge_json); - json_object_string_add( - purge_json, "id", - isis_format_id(poi->generator, sizeof(poi->generator))); - if (poi->sender_set) { - json_object_string_add( - purge_json, "rec-from", - isis_format_id(poi->sender, - sizeof(poi->sender))); - } + json_object_string_add(purge_json, "id", gen_id); + if (poi->sender_set) + json_object_string_add(purge_json, "rec-from", sen_id); } else { sbuf_push(buf, indent, "Purge Originator Identification:\n"); - sbuf_push( - buf, indent, " Generator: %s\n", - isis_format_id(poi->generator, sizeof(poi->generator))); - if (poi->sender_set) { - sbuf_push(buf, indent, " Received-From: %s\n", - isis_format_id(poi->sender, - sizeof(poi->sender))); - } + sbuf_push(buf, indent, " Generator: %s\n", gen_id); + if (poi->sender_set) + sbuf_push(buf, indent, " Received-From: %s\n", sen_id); } } @@ -5271,14 +5271,14 @@ void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs, struct list *addresses) { struct listnode *node; - struct area_addr *area_addr; + struct iso_address *area_addr; for (ALL_LIST_ELEMENTS_RO(addresses, node, area_addr)) { struct isis_area_address *a = XCALLOC(MTYPE_ISIS_TLV, sizeof(*a)); a->len = area_addr->addr_len; - memcpy(a->addr, area_addr->area_addr, 20); + memcpy(a->addr, area_addr->area_addr, ISO_ADDR_SIZE); append_item(&tlvs->area_addresses, (struct isis_item *)a); } } @@ -5475,7 +5475,7 @@ bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs, for (struct isis_area_address *addr = addr_head; addr; addr = addr->next) { struct listnode *node; - struct area_addr *a; + struct iso_address *a; for (ALL_LIST_ELEMENTS_RO(addresses, node, a)) { if (a->addr_len == addr->len diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index ec2d50d60a..caf97f1174 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -126,12 +126,12 @@ void _isis_tx_queue_add(struct isis_tx_queue *queue, return; if (IS_DEBUG_TX_QUEUE) { - zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)", - rawlspid_print(lsp->hdr.lsp_id), - queue->circuit->interface->name, - (type == TX_LSP_CIRCUIT_SCOPED) ? - "circuit scoped" : "regular", - func, file, line); + zlog_debug( + "Add LSP %pLS to %s queue as %s LSP. (From %s %s:%d)", + lsp->hdr.lsp_id, queue->circuit->interface->name, + (type == TX_LSP_CIRCUIT_SCOPED) ? "circuit scoped" + : "regular", + func, file, line); } struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp); @@ -164,9 +164,8 @@ void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp, return; if (IS_DEBUG_TX_QUEUE) { - zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)", - rawlspid_print(lsp->hdr.lsp_id), - queue->circuit->interface->name, + zlog_debug("Remove LSP %pLS from %s queue. (From %s %s:%d)", + lsp->hdr.lsp_id, queue->circuit->interface->name, func, file, line); } diff --git a/isisd/isisd.c b/isisd/isisd.c index c6369a884e..fd6b91b42e 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -272,7 +272,7 @@ void isis_area_del_circuit(struct isis_area *area, struct isis_circuit *circuit) static void delete_area_addr(void *arg) { - struct area_addr *addr = (struct area_addr *)arg; + struct iso_address *addr = (struct iso_address *)arg; XFREE(MTYPE_ISIS_AREA_ADDR, addr); } @@ -809,8 +809,8 @@ static void area_set_mt_overload(struct isis_area *area, uint16_t mtid, int area_net_title(struct vty *vty, const char *net_title) { VTY_DECLVAR_CONTEXT(isis_area, area); - struct area_addr *addr; - struct area_addr *addrp; + struct iso_address *addr; + struct iso_address *addrp; struct listnode *node; uint8_t buff[255]; @@ -823,14 +823,14 @@ int area_net_title(struct vty *vty, const char *net_title) return CMD_ERR_NOTHING_TODO; } - addr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); + addr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct iso_address)); addr->addr_len = dotformat2buff(buff, net_title); memcpy(addr->area_addr, buff, addr->addr_len); #ifdef EXTREME_DEBUG zlog_debug("added area address %s for area %s (address length %d)", net_title, area->area_tag, addr->addr_len); #endif /* EXTREME_DEBUG */ - if (addr->addr_len < 8 || addr->addr_len > 20) { + if (addr->addr_len < ISO_ADDR_MIN || addr->addr_len > ISO_ADDR_SIZE) { vty_out(vty, "area address must be at least 8..20 octets long (%d)\n", addr->addr_len); @@ -852,8 +852,8 @@ int area_net_title(struct vty *vty, const char *net_title) memcpy(area->isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN); area->isis->sysid_set = 1; if (IS_DEBUG_EVENTS) - zlog_debug("Router has SystemID %s", - sysid_print(area->isis->sysid)); + zlog_debug("Router has SystemID %pSY", + area->isis->sysid); } else { /* * Check that the SystemID portions match @@ -899,12 +899,12 @@ int area_net_title(struct vty *vty, const char *net_title) int area_clear_net_title(struct vty *vty, const char *net_title) { VTY_DECLVAR_CONTEXT(isis_area, area); - struct area_addr addr, *addrp = NULL; + struct iso_address addr, *addrp = NULL; struct listnode *node; uint8_t buff[255]; addr.addr_len = dotformat2buff(buff, net_title); - if (addr.addr_len < 8 || addr.addr_len > 20) { + if (addr.addr_len < ISO_ADDR_MIN || addr.addr_len > ISO_ADDR_SIZE) { vty_out(vty, "Unsupported area address length %d, should be 8...20 \n", addr.addr_len); @@ -2348,11 +2348,11 @@ static void common_isis_summary_json(struct json_object *json, time_t cur; char uptime[MONOTIME_STRLEN]; char stier[5]; + json_object_string_add(json, "vrf", isis->name); json_object_int_add(json, "process-id", isis->process_id); if (isis->sysid_set) - json_object_string_add(json, "system-id", - sysid_print(isis->sysid)); + json_object_string_addf(json, "system-id", "%pSY", isis->sysid); cur = time(NULL); cur -= isis->uptime; @@ -2380,16 +2380,11 @@ static void common_isis_summary_json(struct json_object *json, } if (listcount(area->area_addrs) > 0) { - struct area_addr *area_addr; + struct iso_address *area_addr; for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2, - area_addr)) { - json_object_string_add( - area_json, "net", - isonet_print(area_addr->area_addr, - area_addr->addr_len + - ISIS_SYS_ID_LEN + - 1)); - } + area_addr)) + json_object_string_addf(area_json, "net", + "%pISl", area_addr); } tx_pdu_json = json_object_new_object(); @@ -2462,8 +2457,7 @@ static void common_isis_summary_vty(struct vty *vty, struct isis *isis) vty_out(vty, "vrf : %s\n", isis->name); vty_out(vty, "Process Id : %ld\n", isis->process_id); if (isis->sysid_set) - vty_out(vty, "System Id : %s\n", - sysid_print(isis->sysid)); + vty_out(vty, "System Id : %pSY\n", isis->sysid); vty_out(vty, "Up time : "); vty_out_timestr(vty, isis->uptime); @@ -2485,15 +2479,10 @@ static void common_isis_summary_vty(struct vty *vty, struct isis *isis) } if (listcount(area->area_addrs) > 0) { - struct area_addr *area_addr; + struct iso_address *area_addr; for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2, - area_addr)) { - vty_out(vty, " Net: %s\n", - isonet_print(area_addr->area_addr, - area_addr->addr_len - + ISIS_SYS_ID_LEN - + 1)); - } + area_addr)) + vty_out(vty, " Net: %pISl\n", area_addr); } vty_out(vty, " TX counters per PDU type:\n"); @@ -3497,15 +3486,10 @@ static int isis_config_write(struct vty *vty) write++; /* ISIS - Net */ if (listcount(area->area_addrs) > 0) { - struct area_addr *area_addr; + struct iso_address *area_addr; for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2, area_addr)) { - vty_out(vty, " net %s\n", - isonet_print( - area_addr->area_addr, - area_addr->addr_len - + ISIS_SYS_ID_LEN - + 1)); + vty_out(vty, " net %pISl\n", area_addr); write++; } } diff --git a/isisd/isisd.h b/isisd/isisd.h index 0b1f1cb620..12d9cd36c4 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -24,6 +24,7 @@ #include "isis_lfa.h" #include "qobj.h" #include "ldp_sync.h" +#include "iso.h" DECLARE_MGROUP(ISISD); @@ -87,7 +88,7 @@ struct isis { uint32_t router_id; /* Router ID from zebra */ struct list *area_list; /* list of IS-IS areas */ uint8_t max_area_addrs; /* maximumAreaAdresses */ - struct area_addr *man_area_addrs; /* manualAreaAddresses */ + struct iso_address *man_area_addrs; /* manualAreaAddresses */ time_t uptime; /* when did we start */ struct event *t_dync_clean; /* dynamic hostname cache cleanup thread */ uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 1 through 255 */ @@ -195,6 +196,8 @@ struct isis_area { int ip_circuits; /* logging adjacency changes? */ uint8_t log_adj_changes; + /* logging pdu drops? */ + uint8_t log_pdu_drops; /* multi topology settings */ struct list *mt_settings; /* MPLS-TE settings */ diff --git a/lib/compiler.h b/lib/compiler.h index d12e282832..29fcfbefbf 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -439,6 +439,14 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, #pragma diag_suppress 167 #endif /* __INTELISENSE__ */ +#if defined(__GNUC__) && (__GNUC__ >= 3) +#define likely(_x) __builtin_expect(!!(_x), 1) +#define unlikely(_x) __builtin_expect(!!(_x), 0) +#else +#define likely(_x) !!(_x) +#define unlikely(_x) !!(_x) +#endif + #ifdef __cplusplus } #endif diff --git a/lib/cspf.c b/lib/cspf.c index b92c9cb395..6a0fb7f63c 100644 --- a/lib/cspf.c +++ b/lib/cspf.c @@ -88,7 +88,7 @@ static struct c_path *cpath_copy(struct c_path *dest, const struct c_path *src) * * @param path Constrained Path structure to be deleted */ -static void cpath_del(struct c_path *path) +void cpath_del(struct c_path *path) { if (!path) return; diff --git a/lib/cspf.h b/lib/cspf.h index 3eceaa04af..bba685a617 100644 --- a/lib/cspf.h +++ b/lib/cspf.h @@ -191,6 +191,8 @@ extern void cspf_del(struct cspf *algo); */ extern struct c_path *compute_p2p_path(struct cspf *algo, struct ls_ted *ted); +extern void cpath_del(struct c_path *path); + #ifdef __cplusplus } #endif diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 27c41aaa27..5895924a5e 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* route-map for interface. * Copyright (C) 1999 Kunihiro Ishiguro + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -10,6 +11,9 @@ #include "memory.h" #include "if.h" #include "if_rmap.h" +#include "northbound_cli.h" + +#include "lib/if_rmap_clippy.c" DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, @@ -17,8 +21,6 @@ DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name"); -static struct list *if_rmap_ctx_list; - static struct if_rmap *if_rmap_new(void) { struct if_rmap *new; @@ -30,7 +32,9 @@ static struct if_rmap *if_rmap_new(void) static void if_rmap_free(struct if_rmap *if_rmap) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); + char *no_const_ifname = (char *)if_rmap->ifname; + + XFREE(MTYPE_IF_RMAP_NAME, no_const_ifname); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); @@ -40,22 +44,16 @@ static void if_rmap_free(struct if_rmap *if_rmap) struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *if_rmap; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - if_rmap = hash_lookup(ctx->ifrmaphash, &key); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return if_rmap; } void if_rmap_hook_add(struct if_rmap_ctx *ctx, - void (*func)(struct if_rmap_ctx *ctx, - struct if_rmap *)) + void (*func)(struct if_rmap_ctx *ctx, struct if_rmap *)) { ctx->if_rmap_add_hook = func; } @@ -80,16 +78,11 @@ static void *if_rmap_hash_alloc(void *arg) static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *ret; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return ret; } @@ -108,142 +101,171 @@ static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; } -static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_set(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type, const char *routemap_name) { - struct if_rmap *if_rmap; - - if_rmap = if_rmap_get(ctx, ifname); + struct if_rmap *if_rmap = if_rmap_get(ctx, ifname); - if (type == IF_RMAP_IN) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if_rmap->routemap[IF_RMAP_IN] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } - if (type == IF_RMAP_OUT) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - if_rmap->routemap[IF_RMAP_OUT] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); + if_rmap->routemap[type] = XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); if (ctx->if_rmap_add_hook) (ctx->if_rmap_add_hook)(ctx, if_rmap); - - return if_rmap; } -static int if_rmap_unset(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_unset(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap = if_rmap_lookup(ctx, ifname); - if_rmap = if_rmap_lookup(ctx, ifname); if (!if_rmap) - return 0; - - if (type == IF_RMAP_IN) { - if (!if_rmap->routemap[IF_RMAP_IN]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) - return 0; - - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - } + return; - if (type == IF_RMAP_OUT) { - if (!if_rmap->routemap[IF_RMAP_OUT]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) - return 0; + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + if (!if_rmap->routemap[type]) + return; - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - } + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); if (ctx->if_rmap_delete_hook) ctx->if_rmap_delete_hook(ctx, if_rmap); - if (if_rmap->routemap[IF_RMAP_IN] == NULL - && if_rmap->routemap[IF_RMAP_OUT] == NULL) { + if (if_rmap->routemap[IF_RMAP_IN] == NULL && + if_rmap->routemap[IF_RMAP_OUT] == NULL) { hash_release(ctx->ifrmaphash, if_rmap); if_rmap_free(if_rmap); } - - return 1; } -DEFUN (if_rmap, - if_rmap_cmd, - "route-map RMAP_NAME <in|out> IFNAME", - "Route map set\n" - "Route map name\n" - "Route map set for input filtering\n" - "Route map set for output filtering\n" - "Route map interface name\n") +static int if_route_map_handler(struct vty *vty, bool no, const char *dir, + const char *other_dir, const char *ifname, + const char *route_map) { - int idx_rmap_name = 1; - int idx_in_out = 2; - int idx_ifname = 3; - enum if_rmap_type type; - struct if_rmap_ctx *ctx = - (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); - - if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; + enum nb_operation op = no ? NB_OP_DESTROY : NB_OP_MODIFY; + const struct lyd_node *dnode; + char xpath[XPATH_MAXLEN]; + + if (!no) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* + * If we are deleting the last policy for this interface, + * (i.e., no `in` or `out` policy). delete the interface list + * node instead. + */ + dnode = yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (yang_dnode_existsf( + dnode, + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, other_dir)) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* both dir will be empty so delete the list node */ + snprintf(xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']", + ifname); + } } + nb_cli_enqueue_change(vty, xpath, op, route_map); + + return nb_cli_apply_changes(vty, NULL); +} - if_rmap_set(ctx, argv[idx_ifname]->arg, - type, argv[idx_rmap_name]->arg); +DEFPY_YANG(if_ipv4_route_map, if_ipv4_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; - return CMD_SUCCESS; + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); } -DEFUN (no_if_rmap, - no_if_rmap_cmd, - "no route-map ROUTEMAP_NAME <in|out> IFNAME", - NO_STR - "Route map unset\n" - "Route map name\n" - "Route map for input filtering\n" - "Route map for output filtering\n" - "Route map interface name\n") +DEFPY_YANG(no_if_ipv4_route_map, no_if_ipv4_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) { - int idx_routemap_name = 2; - int idx_in_out = 3; - int idx_ifname = 4; - int ret; - enum if_rmap_type type; - struct if_rmap_ctx *ctx = - (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); - - if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->arg, "o", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; - } + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; - ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type, - argv[idx_routemap_name]->arg); - if (!ret) { - vty_out(vty, "route-map doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + +/* + * CLI infra requires new handlers for ripngd + */ +DEFPY_YANG(if_ipv6_route_map, if_ipv6_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); +} + +DEFPY_YANG(no_if_ipv6_route_map, no_if_ipv6_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + + +void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del) +{ + + const char *mapname = yang_dnode_get_string(dnode, NULL); + const char *ifname = yang_dnode_get_string(dnode, "../interface"); + + if (del) + if_rmap_unset(ctx, ifname, type); + else + if_rmap_set(ctx, ifname, type, mapname); +} + +void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode) +{ + const char *ifname = yang_dnode_get_string(dnode, "interface"); + if_rmap_unset(ctx, ifname, IF_RMAP_IN); + if_rmap_unset(ctx, ifname, IF_RMAP_OUT); } /* Configuration write function. */ -int config_write_if_rmap(struct vty *vty, - struct if_rmap_ctx *ctx) +int config_write_if_rmap(struct vty *vty, struct if_rmap_ctx *ctx) { unsigned int i; struct hash_bucket *mp; @@ -275,10 +297,8 @@ int config_write_if_rmap(struct vty *vty, void if_rmap_ctx_delete(struct if_rmap_ctx *ctx) { - listnode_delete(if_rmap_ctx_list, ctx); hash_clean_and_free(&ctx->ifrmaphash, (void (*)(void *))if_rmap_free); - if (ctx->name) - XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx); + XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx->name); XFREE(MTYPE_IF_RMAP_CTX, ctx); } @@ -289,29 +309,24 @@ struct if_rmap_ctx *if_rmap_ctx_create(const char *name) ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx)); - if (ctx->name) - ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); - ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, - "Interface Route-Map Hash"); - if (!if_rmap_ctx_list) - if_rmap_ctx_list = list_new(); - listnode_add(if_rmap_ctx_list, ctx); + ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); + ctx->ifrmaphash = + hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, + "Interface Route-Map Hash"); return ctx; } void if_rmap_init(int node) { - if (node == RIPNG_NODE) { - } else if (node == RIP_NODE) { - install_element(RIP_NODE, &if_rmap_cmd); - install_element(RIP_NODE, &no_if_rmap_cmd); + if (node == RIP_NODE) { + install_element(RIP_NODE, &if_ipv4_route_map_cmd); + install_element(RIP_NODE, &no_if_ipv4_route_map_cmd); + } else if (node == RIPNG_NODE) { + install_element(RIPNG_NODE, &if_ipv6_route_map_cmd); + install_element(RIPNG_NODE, &no_if_ipv6_route_map_cmd); } - if_rmap_ctx_list = list_new(); } void if_rmap_terminate(void) { - if (!if_rmap_ctx_list) - return; - list_delete(&if_rmap_ctx_list); } diff --git a/lib/if_rmap.h b/lib/if_rmap.h index 3bdbc2a3b2..6f5fb578f0 100644 --- a/lib/if_rmap.h +++ b/lib/if_rmap.h @@ -6,15 +6,20 @@ #ifndef _ZEBRA_IF_RMAP_H #define _ZEBRA_IF_RMAP_H +#include "typesafe.h" + #ifdef __cplusplus extern "C" { #endif +struct lyd_node; +struct vty; + enum if_rmap_type { IF_RMAP_IN, IF_RMAP_OUT, IF_RMAP_MAX }; struct if_rmap { /* Name of the interface. */ - char *ifname; + const char *ifname; char *routemap[IF_RMAP_MAX]; }; @@ -45,6 +50,11 @@ void if_rmap_hook_delete(struct if_rmap_ctx *ctx, struct if_rmap *)); extern struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname); +extern void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del); +extern void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode); extern int config_write_if_rmap(struct vty *, struct if_rmap_ctx *ctx); #ifdef __cplusplus diff --git a/lib/iso.c b/lib/iso.c new file mode 100644 index 0000000000..fe97776ade --- /dev/null +++ b/lib/iso.c @@ -0,0 +1,144 @@ +/* + * ISO Network functions - iso_net.c + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2023 Orange http://www.orange.com + * + * This file is part of Free Range Routing (FRR). + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "compiler.h" + +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "printfrr.h" +#include "iso.h" + +/** + * Print ISO System ID as 0000.0000.0000 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("SY", printfrr_iso_sysid); +static ssize_t printfrr_iso_sysid(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x", + id[0], id[1], id[2], id[3], id[4], id[5]); +} + +/** + * Print ISO Pseudo Node system ID as 0000.0000.0000.00 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("PN", printfrr_iso_pseudo); +static ssize_t printfrr_iso_pseudo(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x", + id[0], id[1], id[2], id[3], id[4], id[5], id[6]); +} + +/** + * Print ISO LSP Fragment System ID as 0000.0000.0000.00-00 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("LS", printfrr_iso_frag_id); +static ssize_t printfrr_iso_frag_id(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x-%02x", + id[0], id[1], id[2], id[3], id[4], id[5], id[6], + id[7]); +} + +/** + * Print ISO Network address as 00.0000.0000.0000 ... with the System ID + * as 0000.0000.0000.00 when long 'l' option is added to '%pIS' + * + * @param Print buffer + * @param Print argument + * @param Pointer to the ISO Network address + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("IS", printfrr_iso_addr); +static ssize_t printfrr_iso_addr(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const struct iso_address *ia = vptr; + uint8_t len = 0; + int i = 0; + ssize_t ret = 0; + + if (ea->fmt[0] == 'l') { + len = 7; /* ISO SYSTEM ID + 1 */ + ea->fmt++; + } + + if (!ia) + return bputs(buf, "(null)"); + + len += ia->addr_len; + while (i < len) { + /* No dot for odd index and at the end of address */ + if ((i & 1) || (i == (len - 1))) + ret += bprintfrr(buf, "%02x", ia->area_addr[i]); + else + ret += bprintfrr(buf, "%02x.", ia->area_addr[i]); + i++; + } + + return ret; +} + diff --git a/lib/iso.h b/lib/iso.h new file mode 100644 index 0000000000..975d3c154b --- /dev/null +++ b/lib/iso.h @@ -0,0 +1,49 @@ +/* + * ISO Network definition - iso_net.h + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2023 Orange http://www.orange.com + * + * This file is part of Free Range Routing (FRR). + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIB_ISO_H_ +#define LIB_ISO_H_ + +#include "compiler.h" + +/* len of "xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx" + '\0' */ +#define ISO_ADDR_STRLEN 51 +#define ISO_ADDR_MIN 8 +#define ISO_ADDR_SIZE 20 +struct iso_address { + uint8_t addr_len; + uint8_t area_addr[ISO_ADDR_SIZE]; +}; + +/* len of "xxxx.xxxx.xxxx.xx-xx" + '\0' */ +#define ISO_SYSID_STRLEN 21 + +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#pragma FRR printfrr_ext "%pSY" (uint8_t *) +#pragma FRR printfrr_ext "%pPN" (uint8_t *) +#pragma FRR printfrr_ext "%pLS" (uint8_t *) +#pragma FRR printfrr_ext "%pIS" (struct iso_address *) +#endif + +#endif /* LIB_ISO_H_ */ diff --git a/lib/link_state.c b/lib/link_state.c index b501018be7..7f20cdcf5e 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -26,6 +26,7 @@ #include "printfrr.h" #include <lib/json.h> #include "link_state.h" +#include "iso.h" /* Link State Memory allocation */ DEFINE_MTYPE_STATIC(LIB, LS_DB, "Link State Database"); @@ -333,7 +334,7 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2) /** * Link State prefix management functions */ -struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p) +struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p) { struct ls_prefix *new; @@ -342,7 +343,7 @@ struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p) new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix)); new->adv = adv; - new->pref = p; + new->pref = *p; return new; } @@ -889,7 +890,7 @@ struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref) if (pref == NULL) return NULL; - old = ls_find_subnet(ted, pref->pref); + old = ls_find_subnet(ted, &pref->pref); if (old) { if (!ls_prefix_same(old->ls_pref, pref)) { ls_prefix_del(old->ls_pref); @@ -942,11 +943,12 @@ void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet) ls_subnet_del(ted, subnet); } -struct ls_subnet *ls_find_subnet(struct ls_ted *ted, const struct prefix prefix) +struct ls_subnet *ls_find_subnet(struct ls_ted *ted, + const struct prefix *prefix) { struct ls_subnet subnet = {}; - subnet.key = prefix; + subnet.key = *prefix; return subnets_find(&ted->subnets, &subnet); } @@ -1846,7 +1848,7 @@ struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg, subnet->status = UPDATE; break; case LS_MSG_EVENT_DELETE: - subnet = ls_find_subnet(ted, pref->pref); + subnet = ls_find_subnet(ted, &pref->pref); if (subnet) { if (delete) ls_subnet_del_all(ted, subnet); @@ -1979,13 +1981,9 @@ static const char *const status2txt[] = { static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str, size_t size) { - if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) { - uint8_t *id; - - id = lnid.id.iso.sys_id; - snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0], - id[1], id[2], id[3], id[4], id[5]); - } else + if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) + snprintfrr(str, size, "%pSY", lnid.id.iso.sys_id); + else snprintfrr(str, size, "%pI4", &lnid.id.ip.addr); return str; diff --git a/lib/link_state.h b/lib/link_state.h index e6a6388ba4..b75f035431 100644 --- a/lib/link_state.h +++ b/lib/link_state.h @@ -314,7 +314,7 @@ extern int ls_attributes_same(struct ls_attributes *a1, * * @return New Link State Prefix */ -extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p); +extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p); /** * Remove Link State Prefix. Data Structure is freed. @@ -709,7 +709,7 @@ extern void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet); * @return Subnet if found, NULL otherwise */ extern struct ls_subnet *ls_find_subnet(struct ls_ted *ted, - const struct prefix prefix); + const struct prefix *prefix); /** * Create a new Link State Data Base. diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index 36c78052bc..7437eedfc7 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -16,17 +16,17 @@ #include "sockopt.h" #ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ +#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ +#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) #else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ +#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ do { \ - if (mgmt_debug_be_client) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ + if (mgmt_debug_be_client) \ + zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) -#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ +#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) #endif /* REDIRECT_DEBUG_TO_STDERR */ @@ -597,7 +597,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) MGMTD_BE_CLIENT_DBG( "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u", client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm, - client_ctx->avg_prep_nb_cfg_tm, (uint32_t)num_processed); + client_ctx->avg_prep_nb_cfg_tm, + (uint32_t)num_processed); if (error) mgmt_be_txn_cfg_abort(txn); diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index a2c4fd6572..7cb9aa3def 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -109,8 +109,8 @@ mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx *client_ctx, FOREACH_SESSION_IN_LIST (client_ctx, session) { if (session->session_id == session_id) { MGMTD_FE_CLIENT_DBG( - "Found session %p for session-id %llu.", session, - (unsigned long long)session_id); + "Found session %p for session-id %llu.", + session, (unsigned long long)session_id); return session; } } @@ -274,7 +274,8 @@ mgmt_fe_send_lockds_req(struct mgmt_fe_client_ctx *client_ctx, MGMTD_FE_CLIENT_DBG( "Sending %sLOCK_REQ message for Ds:%d session %llu to MGMTD Frontend server", - lock ? "" : "UN", ds_id, (unsigned long long)session->client_id); + lock ? "" : "UN", ds_id, + (unsigned long long)session->client_id); return mgmt_fe_client_send_msg(client_ctx, &fe_msg); } @@ -310,12 +311,12 @@ mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx *client_ctx, return mgmt_fe_client_send_msg(client_ctx, &fe_msg); } -static int -mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx, - struct mgmt_fe_client_session *session, - uint64_t req_id, Mgmtd__DatastoreId src_ds_id, - Mgmtd__DatastoreId dest_ds_id, bool validate_only, - bool abort) +static int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx, + struct mgmt_fe_client_session *session, + uint64_t req_id, + Mgmtd__DatastoreId src_ds_id, + Mgmtd__DatastoreId dest_ds_id, + bool validate_only, bool abort) { (void)req_id; Mgmtd__FeMessage fe_msg; @@ -450,15 +451,17 @@ mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx *client_ctx, if (session && fe_msg->session_reply->success) { MGMTD_FE_CLIENT_DBG( "Session Create for client-id %llu successful.", - (unsigned long long)fe_msg - ->session_reply->client_conn_id); + (unsigned long long) + fe_msg->session_reply + ->client_conn_id); session->session_id = fe_msg->session_reply->session_id; } else { MGMTD_FE_CLIENT_ERR( "Session Create for client-id %llu failed.", - (unsigned long long)fe_msg - ->session_reply->client_conn_id); + (unsigned long long) + fe_msg->session_reply + ->client_conn_id); } } else if (!fe_msg->session_reply->create) { MGMTD_FE_CLIENT_DBG( diff --git a/lib/routemap.c b/lib/routemap.c index 16da81fa74..20dcd2a53d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -669,7 +669,7 @@ static struct route_map *route_map_add(const char *name) if (!map->ipv6_prefix_table) map->ipv6_prefix_table = route_table_init(); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Add route-map %s", name); return map; } @@ -689,7 +689,7 @@ static void route_map_free_map(struct route_map *map) while ((index = map->head) != NULL) route_map_index_delete(index, 0); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting route-map %s", map->name); list = &route_map_master; @@ -706,6 +706,9 @@ static void route_map_free_map(struct route_map *map) else list->head = map->next; + route_table_finish(map->ipv4_prefix_table); + route_table_finish(map->ipv6_prefix_table); + hash_release(route_map_master_hash, map); XFREE(MTYPE_ROUTE_MAP_NAME, map->name); XFREE(MTYPE_ROUTE_MAP, map); @@ -1120,7 +1123,7 @@ void route_map_index_delete(struct route_map_index *index, int notify) QOBJ_UNREG(index); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting route-map %s sequence %d", index->map->name, index->pref); @@ -1231,7 +1234,7 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref) route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED); } - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Route-map %s add sequence %d, type: %s", map->name, pref, route_map_type_str(type)); @@ -1811,10 +1814,8 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, * must be AF_INET or AF_INET6 in order for the lookup to succeed. So if * the AF doesn't line up with the LPM trees, skip the optimization. */ - if (map->optimization_disabled || - (prefix->family == AF_INET && !map->ipv4_prefix_table) || - (prefix->family == AF_INET6 && !map->ipv6_prefix_table)) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (map->optimization_disabled) { + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Skipping route-map optimization for route-map: %s, pfx: %pFX, family: %d", map->name, prefix, prefix->family); @@ -1826,9 +1827,6 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, else table = map->ipv6_prefix_table; - if (!table) - return NULL; - do { candidate_rmap_list = route_map_get_index_list(&rn, prefix, table); @@ -1914,19 +1912,10 @@ static void route_map_pfx_table_add_default(afi_t afi, p.family = afi2family(afi); p.prefixlen = 0; - if (p.family == AF_INET) { - table = index->map->ipv4_prefix_table; - if (!table) - index->map->ipv4_prefix_table = route_table_init(); - + if (p.family == AF_INET) table = index->map->ipv4_prefix_table; - } else { - table = index->map->ipv6_prefix_table; - if (!table) - index->map->ipv6_prefix_table = route_table_init(); - + else table = index->map->ipv6_prefix_table; - } /* Add default route to table */ rn = route_node_get(table, &p); @@ -2317,8 +2306,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event, struct route_map_index *index, afi_t afi, const char *plist_name) { - struct route_map *rmap = NULL; - if (!index) return; @@ -2332,19 +2319,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event, route_map_pfx_table_del_default(AFI_IP, index); route_map_pfx_table_del_default(AFI_IP6, index); - if ((index->map->head == NULL) && (index->map->tail == NULL)) { - rmap = index->map; - - if (rmap->ipv4_prefix_table) { - route_table_finish(rmap->ipv4_prefix_table); - rmap->ipv4_prefix_table = NULL; - } - - if (rmap->ipv6_prefix_table) { - route_table_finish(rmap->ipv6_prefix_table); - rmap->ipv6_prefix_table = NULL; - } - } return; } @@ -2569,12 +2543,14 @@ route_map_result_t route_map_apply_ext(struct route_map *map, */ if (prefix->family == AF_EVPN) { if (evpn_prefix2prefix(prefix, &conv) != 0) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Unable to convert EVPN prefix %pFX into IPv4/IPv6 prefix. Falling back to non-optimized route-map lookup", prefix); } else { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Converted EVPN prefix %pFX into %pFX for optimized route-map lookup", prefix, &conv); @@ -2586,13 +2562,13 @@ route_map_result_t route_map_apply_ext(struct route_map *map, index = route_map_get_index(map, prefix, match_object, &match_ret); if (index) { index->applied++; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug( "Best match route-map: %s, sequence: %d for pfx: %pFX, result: %s", map->name, index->pref, prefix, route_map_cmd_result_str(match_ret)); } else { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug( "No best match sequence for pfx: %pFX in route-map: %s, result: %s", prefix, map->name, @@ -2615,7 +2591,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map, /* Apply this index. */ match_ret = route_map_apply_match(&index->match_list, prefix, match_object); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) { + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) { zlog_debug( "Route-map: %s, sequence: %d, prefix: %pFX, result: %s", map->name, index->pref, prefix, @@ -2728,7 +2704,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map, } route_map_apply_end: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Route-map: %s, prefix: %pFX, result: %s", (map ? map->name : "null"), prefix, route_map_result_str(ret)); @@ -2783,7 +2759,7 @@ static void route_map_clear_reference(struct hash_bucket *bucket, void *arg) tmp_dep_data.rname = arg; dep_data = hash_release(dep->dep_rmap_hash, &tmp_dep_data); if (dep_data) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Clearing reference for %s to %s count: %d", dep->dep_name, tmp_dep_data.rname, dep_data->refcnt); @@ -2803,7 +2779,7 @@ static void route_map_clear_all_references(char *rmap_name) { int i; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Clearing references for %s", rmap_name); for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { @@ -2879,7 +2855,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_LLIST_ADDED: case RMAP_EVENT_CALL_ADDED: case RMAP_EVENT_FILTER_ADDED: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Adding dependency for filter %s in route-map %s", dep_name, rmap_name); dep = (struct route_map_dep *)hash_get( @@ -2908,7 +2884,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_LLIST_DELETED: case RMAP_EVENT_CALL_DELETED: case RMAP_EVENT_FILTER_DELETED: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting dependency for filter %s in route-map %s", dep_name, rmap_name); dep = (struct route_map_dep *)hash_get(dephash, dname, NULL); @@ -3034,7 +3010,7 @@ static void route_map_process_dependency(struct hash_bucket *bucket, void *data) dep_data = bucket->data; rmap_name = dep_data->rname; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Notifying %s of dependency", rmap_name); if (route_map_master.event_hook) (*route_map_master.event_hook)(rmap_name); @@ -3082,7 +3058,7 @@ void route_map_notify_dependencies(const char *affected_name, if (!dep->this_hash) dep->this_hash = upd8_hash; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Filter %s updated", dep->dep_name); hash_iterate(dep->dep_rmap_hash, route_map_process_dependency, (void *)event); diff --git a/lib/subdir.am b/lib/subdir.am index 0f5bbef0b2..dcc58b31ae 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -47,6 +47,7 @@ lib_libfrr_la_SOURCES = \ lib/if_rmap.c \ lib/imsg-buffer.c \ lib/imsg.c \ + lib/iso.c \ lib/jhash.c \ lib/json.c \ lib/keychain.c \ @@ -173,6 +174,7 @@ clippy_scan += \ lib/affinitymap_cli.c \ lib/if.c \ lib/filter_cli.c \ + lib/if_rmap.c \ lib/log_vty.c \ lib/nexthop_group.c \ lib/northbound_cli.c \ @@ -224,6 +226,7 @@ pkginclude_HEADERS += \ lib/if_rmap.h \ lib/imsg.h \ lib/ipaddr.h \ + lib/iso.h \ lib/jhash.h \ lib/json.h \ lib/keychain.h \ @@ -2400,7 +2400,7 @@ static void vty_timeout(struct event *thread) } /* Read up configuration file from file_name. */ -static void vty_read_file(struct nb_config *config, FILE *confp) +void vty_read_file(struct nb_config *config, FILE *confp) { int ret; struct vty *vty; @@ -369,6 +369,7 @@ extern void vty_pass_fd(struct vty *vty, int fd); extern bool vty_read_config(struct nb_config *config, const char *config_file, char *config_default_dir); +extern void vty_read_file(struct nb_config *config, FILE *confp); extern void vty_time_print(struct vty *, int); extern void vty_serv_sock(const char *, unsigned short, const char *); extern void vty_close(struct vty *); diff --git a/lib/zclient.c b/lib/zclient.c index 95093a56f5..d42cb20191 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4294,6 +4294,8 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api) memset(api, 0, sizeof(*api)); + api->safi = SAFI_UNICAST; + STREAM_GETL(s, api->cap); switch (api->cap) { case ZEBRA_CLIENT_GR_CAPABILITIES: diff --git a/mgmtd/mgmt.h b/mgmtd/mgmt.h index 4d186c176b..9579b02230 100644 --- a/mgmtd/mgmt.h +++ b/mgmtd/mgmt.h @@ -62,6 +62,8 @@ struct mgmt_master { }; extern struct mgmt_master *mm; +extern char const *const mgmt_daemons[]; +extern uint mgmt_daemons_count; /* Inline functions */ static inline unsigned long timeval_elapsed(struct timeval a, struct timeval b) diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index af43cf3eae..cf7d705943 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -80,23 +80,23 @@ static const struct mgmt_be_xpath_map_reg xpath_static_map_reg[] = { .be_clients = (enum mgmt_be_client_id[]){ #if HAVE_STATICD - MGMTD_BE_CLIENT_ID_STATICD, + MGMTD_BE_CLIENT_ID_STATICD, #endif MGMTD_BE_CLIENT_ID_MAX}}, {.xpath_regexp = "/frr-interface:lib/*", .be_clients = (enum mgmt_be_client_id[]){ #if HAVE_STATICD - MGMTD_BE_CLIENT_ID_STATICD, + MGMTD_BE_CLIENT_ID_STATICD, #endif MGMTD_BE_CLIENT_ID_MAX}}, {.xpath_regexp = - "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/*", + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/*", .be_clients = (enum mgmt_be_client_id[]){ #if HAVE_STATICD - MGMTD_BE_CLIENT_ID_STATICD, + MGMTD_BE_CLIENT_ID_STATICD, #endif MGMTD_BE_CLIENT_ID_MAX}}, }; @@ -347,8 +347,8 @@ mgmt_be_adapter_cleanup_old_conn(struct mgmt_be_client_adapter *adapter) struct mgmt_be_client_adapter *old; FOREACH_ADAPTER_IN_LIST (old) { - if (old != adapter - && !strncmp(adapter->name, old->name, sizeof(adapter->name))) { + if (old != adapter && + !strncmp(adapter->name, old->name, sizeof(adapter->name))) { /* * We have a Zombie lingering around */ diff --git a/mgmtd/mgmt_be_server.c b/mgmtd/mgmt_be_server.c index 0fa7ddd6d6..aa77464524 100644 --- a/mgmtd/mgmt_be_server.c +++ b/mgmtd/mgmt_be_server.c @@ -119,7 +119,7 @@ static void mgmt_be_server_start(const char *hostname) return; mgmt_be_server_start_failed: - if (sock) + if (sock > 0) close(sock); mgmt_be_listen_fd = -1; diff --git a/mgmtd/mgmt_ds.c b/mgmtd/mgmt_ds.c index 1724afb182..58c49b8789 100644 --- a/mgmtd/mgmt_ds.c +++ b/mgmtd/mgmt_ds.c @@ -87,7 +87,6 @@ static int mgmt_ds_replace_dst_with_src_ds(struct mgmt_ds_ctx *src, struct mgmt_ds_ctx *dst) { struct lyd_node *dst_dnode, *src_dnode; - struct ly_out *out; if (!src || !dst) return -1; @@ -117,13 +116,6 @@ static int mgmt_ds_replace_dst_with_src_ds(struct mgmt_ds_ctx *src, nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs); } - if (dst->ds_id == MGMTD_DS_RUNNING) { - if (ly_out_new_filepath(MGMTD_STARTUP_DS_FILE_PATH, &out) - == LY_SUCCESS) - mgmt_ds_dump_in_memory(dst, "", LYD_JSON, out); - ly_out_free(out, NULL, 0); - } - /* TODO: Update the versions if nb_config present */ return 0; @@ -134,7 +126,6 @@ static int mgmt_ds_merge_src_with_dst_ds(struct mgmt_ds_ctx *src, { int ret; struct lyd_node **dst_dnode, *src_dnode; - struct ly_out *out; if (!src || !dst) return -1; @@ -159,13 +150,6 @@ static int mgmt_ds_merge_src_with_dst_ds(struct mgmt_ds_ctx *src, nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs); } - if (dst->ds_id == MGMTD_DS_RUNNING) { - if (ly_out_new_filepath(MGMTD_STARTUP_DS_FILE_PATH, &out) - == LY_SUCCESS) - mgmt_ds_dump_in_memory(dst, "", LYD_JSON, out); - ly_out_free(out, NULL, 0); - } - return 0; } @@ -190,6 +174,7 @@ static int mgmt_ds_load_cfg_from_file(const char *filepath, void mgmt_ds_reset_candidate(void) { struct lyd_node *dnode = mm->candidate_ds->root.cfg_root->dnode; + if (dnode) yang_dnode_free(dnode); @@ -200,8 +185,6 @@ void mgmt_ds_reset_candidate(void) int mgmt_ds_init(struct mgmt_master *mm) { - struct lyd_node *root; - if (mgmt_ds_mm || mm->running_ds || mm->candidate_ds || mm->oper_ds) assert(!"MGMTD: Call ds_init only once!"); @@ -209,12 +192,6 @@ int mgmt_ds_init(struct mgmt_master *mm) if (!running_config) assert(!"MGMTD: Call ds_init after frr_init only!"); - if (mgmt_ds_load_cfg_from_file(MGMTD_STARTUP_DS_FILE_PATH, &root) - == 0) { - nb_config_free(running_config); - running_config = nb_config_new(root); - } - running.root.cfg_root = running_config; running.config_ds = true; running.ds_id = MGMTD_DS_RUNNING; @@ -523,12 +500,12 @@ int mgmt_ds_delete_data_nodes(struct mgmt_ds_ctx *ds_ctx, const char *xpath) */ return NB_ERR_NOT_FOUND; /* destroy dependant */ - if (nb_node->dep_cbs.get_dependant_xpath) { + if (nb_node && nb_node->dep_cbs.get_dependant_xpath) { nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath); dep_dnode = yang_dnode_get( ds_ctx->config_ds ? ds_ctx->root.cfg_root->dnode - : ds_ctx->root.dnode_root, + : ds_ctx->root.dnode_root, dep_xpath); if (dep_dnode) lyd_free_tree(dep_dnode); diff --git a/mgmtd/mgmt_ds.h b/mgmtd/mgmt_ds.h index 89a2ea9425..8d01f3d5b1 100644 --- a/mgmtd/mgmt_ds.h +++ b/mgmtd/mgmt_ds.h @@ -24,8 +24,6 @@ #define MGMTD_DS_NAME_CANDIDATE "candidate" #define MGMTD_DS_NAME_OPERATIONAL "operational" -#define MGMTD_STARTUP_DS_FILE_PATH DAEMON_DB_DIR "/frr_startup.json" - #define FOREACH_MGMTD_DS_ID(id) \ for ((id) = MGMTD_DS_NONE; (id) < MGMTD_DS_MAX_ID; (id)++) diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index 5826b17de7..90e6870fd4 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -495,7 +495,8 @@ static int mgmt_fe_send_setcfg_reply(struct mgmt_fe_session_ctx *session, if (implicit_commit) { if (mm->perf_stats_en) - gettimeofday(&session->adapter->cmt_stats.last_end, NULL); + gettimeofday(&session->adapter->cmt_stats.last_end, + NULL); mgmt_fe_session_compute_commit_timers( &session->adapter->cmt_stats); } @@ -715,8 +716,8 @@ mgmt_fe_adapter_cleanup_old_conn(struct mgmt_fe_client_adapter *adapter) struct mgmt_fe_client_adapter *old; FOREACH_ADAPTER_IN_LIST (old) { - if (old != adapter - && !strncmp(adapter->name, old->name, sizeof(adapter->name))) { + if (old != adapter && + !strncmp(adapter->name, old->name, sizeof(adapter->name))) { /* * We have a Zombie lingering around */ @@ -1109,8 +1110,8 @@ mgmt_fe_session_handle_getdata_req_msg(struct mgmt_fe_session_ctx *session, MGMTD_TXN_TYPE_SHOW); if (session->txn_id == MGMTD_SESSION_ID_NONE) { mgmt_fe_send_getdata_reply( - session, getdata_req->ds_id, getdata_req->req_id, - false, NULL, + session, getdata_req->ds_id, + getdata_req->req_id, false, NULL, "Failed to create a Show transaction!"); goto mgmt_fe_sess_handle_getdata_req_failed; } @@ -1780,8 +1781,8 @@ mgmt_fe_adapter_cmt_stats_write(struct vty *vty, sizeof(buf))); vty_out(vty, " Apply-Config Start: \t\t%s\n", mgmt_realtime_to_string( - &adapter->cmt_stats.apply_cfg_start, buf, - sizeof(buf))); + &adapter->cmt_stats.apply_cfg_start, + buf, sizeof(buf))); vty_out(vty, " Apply-Config End: \t\t%s\n", mgmt_realtime_to_string( &adapter->cmt_stats.apply_cfg_end, buf, @@ -1818,8 +1819,9 @@ mgmt_fe_adapter_setcfg_stats_write(struct vty *vty, adapter->setcfg_stats.avg_tm); vty_out(vty, " Last-Set-Cfg-Details:\n"); vty_out(vty, " Set-Cfg Start: \t\t\t%s\n", - mgmt_realtime_to_string(&adapter->setcfg_stats.last_start, - buf, sizeof(buf))); + mgmt_realtime_to_string( + &adapter->setcfg_stats.last_start, buf, + sizeof(buf))); vty_out(vty, " Set-Cfg End: \t\t\t%s\n", mgmt_realtime_to_string(&adapter->setcfg_stats.last_end, buf, sizeof(buf))); @@ -1894,9 +1896,11 @@ void mgmt_fe_adapter_reset_perf_stats(struct vty *vty) struct mgmt_fe_session_ctx *session; FOREACH_ADAPTER_IN_LIST (adapter) { - memset(&adapter->setcfg_stats, 0, sizeof(adapter->setcfg_stats)); + memset(&adapter->setcfg_stats, 0, + sizeof(adapter->setcfg_stats)); FOREACH_SESSION_IN_LIST (adapter, session) { - memset(&adapter->cmt_stats, 0, sizeof(adapter->cmt_stats)); + memset(&adapter->cmt_stats, 0, + sizeof(adapter->cmt_stats)); } } } diff --git a/mgmtd/mgmt_fe_server.c b/mgmtd/mgmt_fe_server.c index 6097c23aac..e8bbe139bb 100644 --- a/mgmtd/mgmt_fe_server.c +++ b/mgmtd/mgmt_fe_server.c @@ -119,7 +119,7 @@ static void mgmt_fe_server_start(const char *hostname) return; mgmt_fe_server_start_failed: - if (sock) + if (sock > 0) close(sock); mgmt_fe_listen_fd = -1; diff --git a/mgmtd/mgmt_history.c b/mgmtd/mgmt_history.c index 6f9f2dd63f..2251c49f1c 100644 --- a/mgmtd/mgmt_history.c +++ b/mgmtd/mgmt_history.c @@ -33,7 +33,7 @@ DECLARE_DLIST(mgmt_cmt_infos, struct mgmt_cmt_info_t, cmts); * The only instance of VTY session that has triggered an ongoing * config rollback operation. */ -static struct vty *rollback_vty = NULL; +static struct vty *rollback_vty; static bool mgmt_history_record_exists(char *file_path) { @@ -82,7 +82,7 @@ static struct mgmt_cmt_info_t *mgmt_history_create_cmt_rec(void) mgmt_realtime_to_string(&cmt_recd_tv, new->time_str, sizeof(new->time_str)); mgmt_history_hash(new->time_str, new->cmtid_str); - snprintf(new->cmt_json_file, sizeof(new->cmt_json_file), + snprintf(new->cmt_json_file, sizeof(new->cmt_json_file) - 1, MGMTD_COMMIT_FILE_PATH, new->cmtid_str); if (mgmt_cmt_infos_count(&mm->cmts) == MGMTD_MAX_COMMIT_LIST) { @@ -100,7 +100,8 @@ static struct mgmt_cmt_info_t *mgmt_history_create_cmt_rec(void) return new; } -static struct mgmt_cmt_info_t *mgmt_history_find_cmt_record(const char *cmtid_str) +static struct mgmt_cmt_info_t * +mgmt_history_find_cmt_record(const char *cmtid_str) { struct mgmt_cmt_info_t *cmt_info; @@ -129,7 +130,8 @@ static bool mgmt_history_read_cmt_record_index(void) while ((fread(&cmt_info, sizeof(cmt_info), 1, fp)) > 0) { if (cnt < MGMTD_MAX_COMMIT_LIST) { - if (!mgmt_history_record_exists(cmt_info.cmt_json_file)) { + if (!mgmt_history_record_exists( + cmt_info.cmt_json_file)) { zlog_err( "Commit record present in index_file, but commit file %s missing", cmt_info.cmt_json_file); @@ -282,7 +284,8 @@ int mgmt_history_rollback_by_id(struct vty *vty, const char *cmtid_str) FOREACH_CMT_REC (mm, cmt_info) { if (strncmp(cmt_info->cmtid_str, cmtid_str, MGMTD_MD5_HASH_STR_HEX_LEN) == 0) { - ret = mgmt_history_rollback_to_cmt(vty, cmt_info, false); + ret = mgmt_history_rollback_to_cmt(vty, cmt_info, + false); return ret; } @@ -321,7 +324,8 @@ int mgmt_history_rollback_n(struct vty *vty, int num_cmts) FOREACH_CMT_REC (mm, cmt_info) { if (cnt == num_cmts) { - ret = mgmt_history_rollback_to_cmt(vty, cmt_info, false); + ret = mgmt_history_rollback_to_cmt(vty, cmt_info, + false); return ret; } @@ -356,6 +360,7 @@ void show_mgmt_cmt_history(struct vty *vty) void mgmt_history_new_record(struct mgmt_ds_ctx *ds_ctx) { struct mgmt_cmt_info_t *cmt_info = mgmt_history_create_cmt_rec(); + mgmt_ds_dump_ds_to_file(cmt_info->cmt_json_file, ds_ctx); mgmt_history_dump_cmt_record_index(); } diff --git a/mgmtd/mgmt_history.h b/mgmtd/mgmt_history.h index 29a1d7738e..5f96cf90e1 100644 --- a/mgmtd/mgmt_history.h +++ b/mgmtd/mgmt_history.h @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2021 Vmware, Inc. - * Pushpasis Sarkar <spushpasis@vmware.com> - * Copyright (c) 2023, LabN Consulting, L.L.C. - * - */ + * Copyright (C) 2021 Vmware, Inc. + * Pushpasis Sarkar <spushpasis@vmware.com> + * Copyright (c) 2023, LabN Consulting, L.L.C. + * + */ #ifndef _FRR_MGMTD_HISTORY_H_ #define _FRR_MGMTD_HISTORY_H_ diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c index 7d176059f5..08c999260d 100644 --- a/mgmtd/mgmt_main.c +++ b/mgmtd/mgmt_main.c @@ -17,6 +17,13 @@ #include "routing_nb.h" +char const *const mgmt_daemons[] = { +#ifdef HAVE_STATICD + "staticd", +#endif +}; +uint mgmt_daemons_count = array_size(mgmt_daemons); + /* mgmt options, we use GNU getopt library. */ static const struct option longopts[] = { {"skip_runas", no_argument, NULL, 'S'}, diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 5fa8aabfd6..2ba0cb413a 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -1258,6 +1258,7 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn) char err_buf[1024] = {0}; nb_ctx.client = NB_CLIENT_MGMTD_SERVER; nb_ctx.user = (void *)txn; + ret = nb_candidate_validate_yang(nb_config, false, err_buf, sizeof(err_buf) - 1); if (ret != NB_OK) { @@ -1787,27 +1788,10 @@ static int mgmt_txn_get_config(struct mgmt_txn_ctx *txn, struct mgmt_txn_req *txn_req, struct mgmt_ds_ctx *ds_ctx) { - struct mgmt_txn_reqs_head *req_list = NULL; - struct mgmt_txn_reqs_head *pending_list = NULL; int indx; struct mgmt_get_data_req *get_data; struct mgmt_get_data_reply *get_reply; - switch (txn_req->req_event) { - case MGMTD_TXN_PROC_GETCFG: - req_list = &txn->get_cfg_reqs; - break; - case MGMTD_TXN_PROC_GETDATA: - req_list = &txn->get_data_reqs; - break; - case MGMTD_TXN_PROC_SETCFG: - case MGMTD_TXN_PROC_COMMITCFG: - case MGMTD_TXN_COMMITCFG_TIMEOUT: - case MGMTD_TXN_CLEANUP: - assert(!"Wrong txn request type!"); - break; - } - get_data = txn_req->req.get_data; if (!get_data->reply) { @@ -1852,24 +1836,11 @@ static int mgmt_txn_get_config(struct mgmt_txn_ctx *txn, mgmt_txn_get_config_failed: - if (pending_list) { - /* - * Move the transaction to corresponding pending list. - */ - if (req_list) - mgmt_txn_reqs_del(req_list, txn_req); - txn_req->pending_be_proc = true; - mgmt_txn_reqs_add_tail(pending_list, txn_req); - MGMTD_TXN_DBG( - "Moved Req: %p for Txn: %p from Req-List to Pending-List", - txn_req, txn_req->txn); - } else { - /* - * Delete the txn request. It will also remove it from request - * list. - */ - mgmt_txn_req_free(&txn_req); - } + /* + * Delete the txn request. It will also remove it from request + * list. + */ + mgmt_txn_req_free(&txn_req); return 0; } diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 898eb43915..fa34d90c75 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -10,6 +10,8 @@ #include "command.h" #include "json.h" +#include "northbound_cli.h" + #include "mgmtd/mgmt.h" #include "mgmtd/mgmt_be_server.h" #include "mgmtd/mgmt_be_adapter.h" @@ -389,6 +391,7 @@ static struct cmd_node debug_node = { static int config_write_mgmt_debug_helper(struct vty *vty, bool config) { int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn; + if (!n) return 0; @@ -440,6 +443,7 @@ DEFPY(debug_mgmt, debug_mgmt_cmd, "Transaction debug\n") { bool set = !no; + if (all) be = fe = ds = txn = set ? all : NULL; @@ -455,6 +459,33 @@ DEFPY(debug_mgmt, debug_mgmt_cmd, return CMD_SUCCESS; } +/* + * Analog of `frr_config_read_in()`, instead of our config file though we loop + * over all daemons that have transitioned to mgmtd, loading their configs + */ +static int mgmt_config_pre_hook(struct event_loop *loop) +{ + FILE *confp; + char *p; + + for (uint i = 0; i < mgmt_daemons_count; i++) { + p = asprintfrr(MTYPE_TMP, "%s/%s.conf", frr_sysconfdir, + mgmt_daemons[i]); + confp = fopen(p, "r"); + if (confp == NULL) { + if (errno != ENOENT) + zlog_err("%s: couldn't read config file %s: %s", + __func__, p, safe_strerror(errno)); + } else { + zlog_info("mgmtd: reading daemon config from %s", p); + vty_read_file(vty_shared_candidate_config, confp); + fclose(confp); + } + XFREE(MTYPE_TMP, p); + } + return 0; +} + void mgmt_vty_init(void) { /* @@ -468,6 +499,8 @@ void mgmt_vty_init(void) static_vty_init(); #endif + hook_register(frr_config_pre, mgmt_config_pre_hook); + install_node(&debug_node); install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd); diff --git a/nhrpd/debug.h b/nhrpd/debug.h index e9428fa90a..f2c7022ad4 100644 --- a/nhrpd/debug.h +++ b/nhrpd/debug.h @@ -1,13 +1,5 @@ #include "log.h" -#if defined(__GNUC__) && (__GNUC__ >= 3) -#define likely(_x) __builtin_expect(!!(_x), 1) -#define unlikely(_x) __builtin_expect(!!(_x), 0) -#else -#define likely(_x) !!(_x) -#define unlikely(_x) !!(_x) -#endif - #define NHRP_DEBUG_COMMON (1 << 0) #define NHRP_DEBUG_KERNEL (1 << 1) #define NHRP_DEBUG_IF (1 << 2) diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index e14586c5ee..ded520889f 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -54,6 +54,7 @@ static void ospf_area_range_free(struct ospf_area_range *range) } static void ospf_area_range_add(struct ospf_area *area, + struct route_table *ranges, struct ospf_area_range *range) { struct route_node *rn; @@ -64,7 +65,7 @@ static void ospf_area_range_add(struct ospf_area *area, p.prefix = range->addr; apply_mask_ipv4(&p); - rn = route_node_get(area->ranges, (struct prefix *)&p); + rn = route_node_get(ranges, (struct prefix *)&p); if (rn->info) route_unlock_node(rn); else @@ -75,10 +76,12 @@ static void ospf_area_range_delete(struct ospf_area *area, struct route_node *rn) { struct ospf_area_range *range = rn->info; + bool nssa = CHECK_FLAG(range->flags, OSPF_AREA_RANGE_NSSA); - if (range->specifics != 0) + if (ospf_area_range_active(range) && + CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE)) ospf_delete_discard_route(area->ospf, area->ospf->new_table, - (struct prefix_ipv4 *)&rn->p); + (struct prefix_ipv4 *)&rn->p, nssa); ospf_area_range_free(range); rn->info = NULL; @@ -87,11 +90,12 @@ static void ospf_area_range_delete(struct ospf_area *area, } struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *area, + struct route_table *ranges, struct prefix_ipv4 *p) { struct route_node *rn; - rn = route_node_lookup(area->ranges, (struct prefix *)p); + rn = route_node_lookup(ranges, (struct prefix *)p); if (rn) { route_unlock_node(rn); return rn->info; @@ -133,11 +137,12 @@ struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area, } static struct ospf_area_range *ospf_area_range_match(struct ospf_area *area, + struct route_table *ranges, struct prefix_ipv4 *p) { struct route_node *node; - node = route_node_match(area->ranges, (struct prefix *)p); + node = route_node_match(ranges, (struct prefix *)p); if (node) { route_unlock_node(node); return node->info; @@ -153,7 +158,7 @@ struct ospf_area_range *ospf_area_range_match_any(struct ospf *ospf, struct listnode *node; for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) - if ((range = ospf_area_range_match(area, p))) + if ((range = ospf_area_range_match(area, area->ranges, p))) return range; return NULL; @@ -169,17 +174,13 @@ static int ospf_area_actively_attached(struct ospf_area *area) return area->act_ints; } -int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p, int advertise) +int ospf_area_range_set(struct ospf *ospf, struct ospf_area *area, + struct route_table *ranges, struct prefix_ipv4 *p, + int advertise, bool nssa) { - struct ospf_area *area; struct ospf_area_range *range; - area = ospf_area_get(ospf, area_id); - if (area == NULL) - return 0; - - range = ospf_area_range_lookup(area, p); + range = ospf_area_range_lookup(area, ranges, p); if (range != NULL) { if (!CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; @@ -190,7 +191,7 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id, ospf_schedule_abr_task(ospf); } else { range = ospf_area_range_new(p); - ospf_area_range_add(area, range); + ospf_area_range_add(area, ranges, range); ospf_schedule_abr_task(ospf); } @@ -201,20 +202,19 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id, range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; } + if (nssa) + SET_FLAG(range->flags, OSPF_AREA_RANGE_NSSA); + return 1; } -int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p, uint32_t cost) +int ospf_area_range_cost_set(struct ospf *ospf, struct ospf_area *area, + struct route_table *ranges, struct prefix_ipv4 *p, + uint32_t cost) { - struct ospf_area *area; struct ospf_area_range *range; - area = ospf_area_get(ospf, area_id); - if (area == NULL) - return 0; - - range = ospf_area_range_lookup(area, p); + range = ospf_area_range_lookup(area, ranges, p); if (range == NULL) return 0; @@ -227,17 +227,12 @@ int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id, return 1; } -int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p) +int ospf_area_range_unset(struct ospf *ospf, struct ospf_area *area, + struct route_table *ranges, struct prefix_ipv4 *p) { - struct ospf_area *area; struct route_node *rn; - area = ospf_area_lookup_by_area_id(ospf, area_id); - if (area == NULL) - return 0; - - rn = route_node_lookup(area->ranges, (struct prefix *)p); + rn = route_node_lookup(ranges, (struct prefix *)p); if (rn == NULL) return 0; @@ -249,14 +244,12 @@ int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id, return 1; } -int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id, +int ospf_area_range_substitute_set(struct ospf *ospf, struct ospf_area *area, struct prefix_ipv4 *p, struct prefix_ipv4 *s) { - struct ospf_area *area; struct ospf_area_range *range; - area = ospf_area_get(ospf, area_id); - range = ospf_area_range_lookup(area, p); + range = ospf_area_range_lookup(area, area->ranges, p); if (range != NULL) { if (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) @@ -264,7 +257,7 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id, ospf_schedule_abr_task(ospf); } else { range = ospf_area_range_new(p); - ospf_area_range_add(area, range); + ospf_area_range_add(area, area->ranges, range); ospf_schedule_abr_task(ospf); } @@ -276,17 +269,12 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id, return 1; } -int ospf_area_range_substitute_unset(struct ospf *ospf, struct in_addr area_id, +int ospf_area_range_substitute_unset(struct ospf *ospf, struct ospf_area *area, struct prefix_ipv4 *p) { - struct ospf_area *area; struct ospf_area_range *range; - area = ospf_area_lookup_by_area_id(ospf, area_id); - if (area == NULL) - return 0; - - range = ospf_area_range_lookup(area, p); + range = ospf_area_range_lookup(area, area->ranges, p); if (range == NULL) return 0; @@ -538,8 +526,7 @@ void ospf_check_abr_status(struct ospf *ospf) } static void ospf_abr_update_aggregate(struct ospf_area_range *range, - struct ospf_route * or, - struct ospf_area *area) + uint32_t cost, struct ospf_area *area) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: Start", __func__); @@ -557,20 +544,18 @@ static void ospf_abr_update_aggregate(struct ospf_area_range *range, range->cost = range->cost_config; } else { - if (range->specifics == 0) { + if (!ospf_area_range_active(range)) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug("%s: use or->cost %d", __func__, - or->cost); + zlog_debug("%s: use cost %d", __func__, cost); - range->cost = or->cost; /* 1st time get 1st cost */ + range->cost = cost; /* 1st time get 1st cost */ } - if (or->cost > range->cost) { + if (cost > range->cost) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug("%s: update to %d", __func__, - or->cost); + zlog_debug("%s: update to %d", __func__, cost); - range->cost = or->cost; + range->cost = cost; } } @@ -605,6 +590,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) struct ospf_lsa *old = NULL, *new = NULL; struct as_external_lsa *ext7; struct prefix_ipv4 p; + struct ospf_area_range *range; if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) { if (IS_DEBUG_OSPF_NSSA) @@ -646,6 +632,18 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) return 1; } + range = ospf_area_range_match(area, area->nssa_ranges, &p); + if (range) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("Suppressed by range %pI4/%u of area %pI4", + &range->addr, range->masklen, + &area->area_id); + + ospf_abr_update_aggregate(range, GET_METRIC(ext7->e[0].metric), + area); + return 1; + } + if (old && CHECK_FLAG(old->flags, OSPF_LSA_APPROVED)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( @@ -675,17 +673,27 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) } } - /* Area where Aggregate testing will be inserted, just like summary - advertisements */ - /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */ - return 0; } -static void ospf_abr_translate_nssa_range(struct prefix_ipv4 *p, uint32_t cost) +static void ospf_abr_translate_nssa_range(struct ospf *ospf, + struct prefix_ipv4 *p, uint32_t cost) { - /* The Type-7 is created from the aggregated prefix and forwarded - for lsa installation and flooding... to be added... */ + struct external_info ei = {}; + struct ospf_lsa *lsa; + + prefix_copy(&ei.p, p); + ei.type = ZEBRA_ROUTE_OSPF; + ei.route_map_set.metric = cost; + ei.route_map_set.metric_type = -1; + + lsa = ospf_external_info_find_lsa(ospf, p); + if (lsa) + lsa = ospf_external_lsa_refresh(ospf, lsa, &ei, + LSA_REFRESH_FORCE, true); + else + lsa = ospf_external_lsa_originate(ospf, &ei); + SET_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT); } void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, @@ -892,9 +900,11 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, zlog_debug( "%s: this is intra-area route to %pFX", __func__, p); - if ((range = ospf_area_range_match(or_area, p)) - && !ospf_area_is_transit(area)) - ospf_abr_update_aggregate(range, or, area); + if ((range = ospf_area_range_match( + or_area, or_area->ranges, p)) && + !ospf_area_is_transit(area)) + ospf_abr_update_aggregate(range, or->cost, + area); else ospf_abr_announce_network_to_area(p, or->cost, area); @@ -1345,7 +1355,7 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf) zlog_debug("%s: Stop", __func__); } -static void ospf_abr_prepare_aggregates(struct ospf *ospf) +static void ospf_abr_prepare_aggregates(struct ospf *ospf, bool nssa) { struct listnode *node; struct route_node *rn; @@ -1356,7 +1366,14 @@ static void ospf_abr_prepare_aggregates(struct ospf *ospf) zlog_debug("%s: Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - for (rn = route_top(area->ranges); rn; rn = route_next(rn)) + struct route_table *ranges; + + if (nssa) + ranges = area->nssa_ranges; + else + ranges = area->ranges; + + for (rn = route_top(ranges); rn; rn = route_next(rn)) if ((range = rn->info) != NULL) { range->cost = 0; range->specifics = 0; @@ -1409,7 +1426,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf) p.prefixlen = range->subst_masklen; } - if (range->specifics) { + if (ospf_area_range_active(range)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: active range", __func__); @@ -1452,13 +1469,11 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf) zlog_debug("%s: Stop", __func__); } -static void -ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ +static void ospf_abr_send_nssa_aggregates(struct ospf *ospf) { - struct listnode *node; /*, n; */ - struct ospf_area *area; /*, *ar; */ + struct listnode *node; + struct ospf_area *area; struct route_node *rn; - struct ospf_area_range *range; struct prefix_ipv4 p; if (IS_DEBUG_OSPF_NSSA) @@ -1472,20 +1487,13 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ zlog_debug("%s: looking at area %pI4", __func__, &area->area_id); - for (rn = route_top(area->ranges); rn; rn = route_next(rn)) { - if (rn->info == NULL) - continue; + for (rn = route_top(area->nssa_ranges); rn; + rn = route_next(rn)) { + struct ospf_area_range *range; range = rn->info; - - if (!CHECK_FLAG(range->flags, - OSPF_AREA_RANGE_ADVERTISE)) { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug( - "%s: discarding suppress-ranges", - __func__); + if (!range) continue; - } p.family = AF_INET; p.prefix = range->addr; @@ -1495,14 +1503,9 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ zlog_debug("%s: this is range: %pFX", __func__, &p); - if (CHECK_FLAG(range->flags, - OSPF_AREA_RANGE_SUBSTITUTE)) { - p.family = AF_INET; - p.prefix = range->subst_addr; - p.prefixlen = range->subst_masklen; - } - - if (range->specifics) { + if (ospf_area_range_active(range) + && CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) { if (IS_DEBUG_OSPF_NSSA) zlog_debug("%s: active range", __func__); @@ -1512,7 +1515,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ * translate, Install (as Type-5), Approve, and * Flood */ - ospf_abr_translate_nssa_range(&p, range->cost); + ospf_abr_translate_nssa_range(ospf, &p, + range->cost); } } /* all area ranges*/ } /* all areas */ @@ -1807,6 +1811,82 @@ static void ospf_abr_announce_non_dna_routers(struct event *thread) OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Stop", __func__); } +static void ospf_abr_nssa_type7_default_create(struct ospf *ospf, + struct ospf_area *area, + struct ospf_lsa *lsa) +{ + struct external_info ei; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "Announcing Type-7 default route into NSSA area %pI4", + &area->area_id); + + /* Prepare the extrenal_info for aggregator */ + memset(&ei, 0, sizeof(struct external_info)); + ei.p.family = AF_INET; + ei.p.prefixlen = 0; + ei.tag = 0; + ei.type = 0; + ei.instance = ospf->instance; + + /* Compute default route type and metric. */ + if (area->nssa_default_originate.metric_value != -1) + ei.route_map_set.metric = + area->nssa_default_originate.metric_value; + else + ei.route_map_set.metric = DEFAULT_DEFAULT_ALWAYS_METRIC; + if (area->nssa_default_originate.metric_type != -1) + ei.route_map_set.metric_type = + area->nssa_default_originate.metric_type; + else + ei.route_map_set.metric_type = DEFAULT_METRIC_TYPE; + + if (!lsa) + ospf_nssa_lsa_originate(area, &ei); + else + ospf_nssa_lsa_refresh(area, lsa, &ei); +} + +static void ospf_abr_nssa_type7_default_delete(struct ospf *ospf, + struct ospf_area *area, + struct ospf_lsa *lsa) +{ + if (lsa && !CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "Withdrawing Type-7 default route from area %pI4", + &area->area_id); + + ospf_ls_retransmit_delete_nbr_area(area, lsa); + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush_area(lsa, area); + } +} + +/* NSSA Type-7 default route. */ +void ospf_abr_nssa_type7_defaults(struct ospf *ospf) +{ + struct ospf_area *area; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + struct in_addr id = {}; + struct ospf_lsa *lsa; + + lsa = ospf_lsdb_lookup_by_id(area->lsdb, OSPF_AS_NSSA_LSA, id, + area->ospf->router_id); + if (area->external_routing == OSPF_AREA_NSSA + && area->nssa_default_originate.enabled + && (IS_OSPF_ABR(ospf) + || (IS_OSPF_ASBR(ospf) + && ospf->nssa_default_import_check.status))) + ospf_abr_nssa_type7_default_create(ospf, area, lsa); + else + ospf_abr_nssa_type7_default_delete(ospf, area, lsa); + } +} + static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf, struct ospf_lsa *lsa) { @@ -1874,30 +1954,39 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf) zlog_debug("%s: Stop", __func__); } -static void ospf_abr_manage_discard_routes(struct ospf *ospf) +static void ospf_abr_manage_discard_routes(struct ospf *ospf, bool nssa) { struct listnode *node, *nnode; struct route_node *rn; struct ospf_area *area; - struct ospf_area_range *range; - for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) - for (rn = route_top(area->ranges); rn; rn = route_next(rn)) - if ((range = rn->info) != NULL) - if (CHECK_FLAG(range->flags, - OSPF_AREA_RANGE_ADVERTISE)) { - if (range->specifics) - ospf_add_discard_route( - ospf, ospf->new_table, - area, - (struct prefix_ipv4 - *)&rn->p); - else - ospf_delete_discard_route( - ospf, ospf->new_table, - (struct prefix_ipv4 - *)&rn->p); - } + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + struct route_table *ranges; + + if (nssa) + ranges = area->nssa_ranges; + else + ranges = area->ranges; + + for (rn = route_top(ranges); rn; rn = route_next(rn)) { + struct ospf_area_range *range; + + range = rn->info; + if (!range) + continue; + + if (ospf_area_range_active(range) + && CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) + ospf_add_discard_route( + ospf, ospf->new_table, area, + (struct prefix_ipv4 *)&rn->p, nssa); + else + ospf_delete_discard_route( + ospf, ospf->new_table, + (struct prefix_ipv4 *)&rn->p, nssa); + } + } } /* This is the function taking care about ABR NSSA, i.e. NSSA @@ -1925,7 +2014,7 @@ static void ospf_abr_manage_discard_routes(struct ospf *ospf) For External Calculations, any NSSA areas use the Type-7 AREA-LSDB, any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */ -static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ +void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ { if (ospf->gr_info.restart_in_progress) return; @@ -1952,7 +2041,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ /* RESET all Ranges in every Area, same as summaries */ if (IS_DEBUG_OSPF_NSSA) zlog_debug("%s: NSSA initialize aggregates", __func__); - ospf_abr_prepare_aggregates(ospf); /*TURNED OFF just for now */ + ospf_abr_prepare_aggregates(ospf, true); /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or * Aggregate as Type-7 @@ -1983,7 +2072,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ zlog_debug("%s: remove unapproved translates", __func__); ospf_abr_remove_unapproved_translates(ospf); - ospf_abr_manage_discard_routes(ospf); /* same as normal...discard */ + ospf_abr_manage_discard_routes(ospf, true); if (IS_DEBUG_OSPF_NSSA) zlog_debug("%s: Stop", __func__); @@ -2012,7 +2101,7 @@ void ospf_abr_task(struct ospf *ospf) if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: prepare aggregates", __func__); - ospf_abr_prepare_aggregates(ospf); + ospf_abr_prepare_aggregates(ospf, false); if (IS_OSPF_ABR(ospf)) { if (IS_DEBUG_OSPF_EVENT) @@ -2031,6 +2120,11 @@ void ospf_abr_task(struct ospf *ospf) zlog_debug("%s: announce stub defaults", __func__); ospf_abr_announce_stub_defaults(ospf); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: announce NSSA Type-7 defaults", + __func__); + ospf_abr_nssa_type7_defaults(ospf); + if (ospf->fr_configured) { OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): announce non-DNArouters", @@ -2050,7 +2144,7 @@ void ospf_abr_task(struct ospf *ospf) zlog_debug("%s: remove unapproved summaries", __func__); ospf_abr_remove_unapproved_summaries(ospf); - ospf_abr_manage_discard_routes(ospf); + ospf_abr_manage_discard_routes(ospf, false); if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: Stop", __func__); diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h index 19d444b125..cc2b2b0548 100644 --- a/ospfd/ospf_abr.h +++ b/ospfd/ospf_abr.h @@ -16,6 +16,7 @@ #define OSPF_AREA_RANGE_ADVERTISE (1 << 0) #define OSPF_AREA_RANGE_SUBSTITUTE (1 << 1) +#define OSPF_AREA_RANGE_NSSA (1 << 2) /* Area range. */ struct ospf_area_range { @@ -44,23 +45,23 @@ struct ospf_area_range { /* Prototypes. */ extern struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *, + struct route_table *, struct prefix_ipv4 *); - -extern struct ospf_area_range *ospf_some_area_range_match(struct prefix_ipv4 *); - extern struct ospf_area_range * ospf_area_range_lookup_next(struct ospf_area *, struct in_addr *, int); -extern int ospf_area_range_set(struct ospf *, struct in_addr, - struct prefix_ipv4 *, int); -extern int ospf_area_range_cost_set(struct ospf *, struct in_addr, - struct prefix_ipv4 *, uint32_t); -extern int ospf_area_range_unset(struct ospf *, struct in_addr, - struct prefix_ipv4 *); -extern int ospf_area_range_substitute_set(struct ospf *, struct in_addr, +extern int ospf_area_range_set(struct ospf *, struct ospf_area *, + struct route_table *, struct prefix_ipv4 *, int, + bool); +extern int ospf_area_range_cost_set(struct ospf *, struct ospf_area *, + struct route_table *, struct prefix_ipv4 *, + uint32_t); +extern int ospf_area_range_unset(struct ospf *, struct ospf_area *, + struct route_table *, struct prefix_ipv4 *); +extern int ospf_area_range_substitute_set(struct ospf *, struct ospf_area *, struct prefix_ipv4 *, struct prefix_ipv4 *); -extern int ospf_area_range_substitute_unset(struct ospf *, struct in_addr, +extern int ospf_area_range_substitute_unset(struct ospf *, struct ospf_area *, struct prefix_ipv4 *); extern struct ospf_area_range *ospf_area_range_match_any(struct ospf *, struct prefix_ipv4 *); @@ -69,10 +70,12 @@ extern int ospf_act_bb_connection(struct ospf *); extern void ospf_check_abr_status(struct ospf *); extern void ospf_abr_task(struct ospf *); +extern void ospf_abr_nssa_task(struct ospf *ospf); extern void ospf_schedule_abr_task(struct ospf *); extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, uint32_t, struct ospf_area *); +extern void ospf_abr_nssa_type7_defaults(struct ospf *ospf); extern void ospf_abr_nssa_check_status(struct ospf *ospf); extern void ospf_abr_generate_indication_lsa(struct ospf *ospf, const struct ospf_area *area); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 649ba70e02..5742ece1f7 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -651,6 +651,8 @@ int ospf_if_new_hook(struct interface *ifp) ifp->info = XCALLOC(MTYPE_OSPF_IF_INFO, sizeof(struct ospf_if_info)); + IF_OSPF_IF_INFO(ifp)->oii_fd = -1; + IF_OIFS(ifp) = route_table_init(); IF_OIFS_PARAMS(ifp) = route_table_init(); @@ -691,6 +693,8 @@ static int ospf_if_delete_hook(struct interface *ifp) { int rc = 0; struct route_node *rn; + struct ospf_if_info *oii; + rc = ospf_opaque_del_if(ifp); /* @@ -707,6 +711,13 @@ static int ospf_if_delete_hook(struct interface *ifp) route_table_finish(IF_OIFS(ifp)); route_table_finish(IF_OIFS_PARAMS(ifp)); + /* Close per-interface socket */ + oii = ifp->info; + if (oii && oii->oii_fd > 0) { + close(oii->oii_fd); + oii->oii_fd = -1; + } + XFREE(MTYPE_OSPF_IF_INFO, ifp->info); return rc; @@ -1367,6 +1378,16 @@ static int ospf_ifp_up(struct interface *ifp) struct ospf_interface *oi; struct route_node *rn; struct ospf_if_info *oii = ifp->info; + struct ospf *ospf; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state change to up.", + ifp->name); + + /* Open per-intf write socket if configured */ + ospf = ifp->vrf->info; + if (ospf && ospf->intf_socket_enabled) + ospf_ifp_sock_init(ifp); ospf_if_recalculate_output_cost(ifp); @@ -1384,10 +1405,6 @@ static int ospf_ifp_up(struct interface *ifp) return 0; } - if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) - zlog_debug("Zebra: Interface[%s] state change to up.", - ifp->name); - for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { if ((oi = rn->info) == NULL) continue; @@ -1416,6 +1433,9 @@ static int ospf_ifp_down(struct interface *ifp) ospf_if_down(oi); } + /* Close per-interface write socket if configured */ + ospf_ifp_sock_close(ifp); + return 0; } diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 8625a72ac1..649df437a4 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -121,6 +121,9 @@ struct ospf_if_info { membership_counts[MEMBER_MAX]; /* multicast group refcnts */ uint32_t curr_mtu; + + /* Per-interface write socket, configured via 'ospf' object */ + int oii_fd; }; struct ospf_interface; diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 82f7b96fd5..9e2dd7a457 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -1654,9 +1654,6 @@ struct in_addr ospf_get_nssa_ip(struct ospf_area *area) if (best_default.s_addr != INADDR_ANY) return best_default; - if (best_default.s_addr != INADDR_ANY) - return best_default; - return fwd; } @@ -1868,8 +1865,7 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, } /* As Type-7 */ -static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa, - struct external_info *ei) +static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa) { struct ospf_lsa *new; struct as_external_lsa *extlsa; @@ -2017,7 +2013,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, struct ospf_lsa *type7, struct ospf_lsa *type5) { - struct ospf_lsa *new; + struct ospf_lsa *new, *translated_lsa; struct as_external_lsa *extnew; if (ospf->gr_info.restart_in_progress) { @@ -2031,7 +2027,8 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, * the OSPF_LSA_LOCAL_XLT flag, must originate by hand */ - if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) == + NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( "%s: Could not translate Type-7, Id %pI4, to Type-5", @@ -2039,16 +2036,17 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, return NULL; } - extnew = (struct as_external_lsa *)new->data; + extnew = (struct as_external_lsa *)translated_lsa->data; /* Update LSA sequence number from translated Type-5 LSA */ if (type5) - new->data->ls_seqnum = lsa_seqnum_increment(type5); + translated_lsa->data->ls_seqnum = lsa_seqnum_increment(type5); - if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) { + if ((new = ospf_lsa_install(ospf, NULL, translated_lsa)) == NULL) { flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, "%s: Could not install LSA id %pI4", __func__, &type7->data->id); + ospf_lsa_free(translated_lsa); return NULL; } @@ -2071,7 +2069,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, struct ospf_lsa *type7, struct ospf_lsa *type5) { - struct ospf_lsa *new = NULL; + struct ospf_lsa *new = NULL, *translated_lsa = NULL; struct as_external_lsa *extold = NULL; uint32_t ls_seqnum = 0; @@ -2147,7 +2145,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, ospf_ls_retransmit_delete_nbr_as(ospf, type5); /* create new translated LSA */ - if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) == + NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( "%s: Could not translate Type-7 for %pI4 to Type-5", @@ -2157,13 +2156,14 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, if (type7->area->suppress_fa == 1) { if (extold->e[0].fwd_addr.s_addr == 0) - new->data->ls_seqnum = htonl(ls_seqnum + 1); + translated_lsa->data->ls_seqnum = htonl(ls_seqnum + 1); } - if (!(new = ospf_lsa_install(ospf, NULL, new))) { + if (!(new = ospf_lsa_install(ospf, NULL, translated_lsa))) { flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, "%s: Could not install translated LSA, Id %pI4", __func__, &type7->data->id); + ospf_lsa_free(translated_lsa); return NULL; } @@ -2253,7 +2253,7 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, /* stay away from translated LSAs! */ !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) ospf_install_flood_nssa( - ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ + ospf, new); /* Install/Flood Type-7 to all NSSAs */ /* Debug logging. */ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { @@ -2266,6 +2266,100 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, return new; } +/* Originate an NSSA-LSA, install and flood. */ +struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area, + struct external_info *ei) +{ + struct ospf *ospf = area->ospf; + struct ospf_lsa *new; + + if (ospf->gr_info.restart_in_progress) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type7]: Graceful Restart in progress, don't originate"); + return NULL; + } + + if (ospf->router_id.s_addr == INADDR_ANY) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type7:%pI4]: deferring NSSA-LSA origination, router ID is zero", + &ei->p.prefix); + return NULL; + } + + /* Create new NSSA-LSA instance. */ + if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type7:%pI4]: Could not originate NSSA-LSA", + &ei->p.prefix); + return NULL; + } + new->data->type = OSPF_AS_NSSA_LSA; + new->area = area; + + /* Install newly created LSA into Type-7 LSDB. */ + ospf_lsa_install(ospf, NULL, new); + + /* Update LSA origination count. */ + ospf->lsa_originate_count++; + + /* Flooding new LSA */ + ospf_flood_through_area(area, NULL, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%pI4]: Originate NSSA-LSA %p", + new->data->type, &new->data->id, (void *)new); + ospf_lsa_header_dump(new->data); + } + + return new; +} + +/* Refresh NSSA-LSA. */ +struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area, + struct ospf_lsa *lsa, + struct external_info *ei) +{ + struct ospf *ospf = area->ospf; + struct ospf_lsa *new; + + /* Delete LSA from neighbor retransmit-list. */ + ospf_ls_retransmit_delete_nbr_as(ospf, lsa); + + /* Unregister AS-external-LSA from refresh-list. */ + ospf_refresher_unregister_lsa(ospf, lsa); + + /* Create new NSSA-LSA instance. */ + if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type7:%pI4]: Could not originate NSSA-LSA", + &ei->p.prefix); + return NULL; + } + new->data->type = OSPF_AS_NSSA_LSA; + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + new->area = area; + + /* Install newly created LSA into Type-7 LSDB. */ + ospf_lsa_install(ospf, NULL, new); + + /* Flooding new LSA */ + ospf_flood_through_area(area, NULL, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%pI4]: NSSA-LSA refresh", + new->data->type, &new->data->id); + ospf_lsa_header_dump(new->data); + } + + return new; +} + static struct external_info *ospf_default_external_info(struct ospf *ospf) { int type; @@ -2611,8 +2705,8 @@ struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) - ospf_install_flood_nssa(ospf, new, - ei); /* Install/Flood per new rules */ + ospf_install_flood_nssa(ospf, + new); /* Install/Flood per new rules */ /* Register self-originated LSA to refresh queue. * Translated LSAs should not be registered, but refreshed upon diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 8ab293f4db..d5ca0694cc 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -278,6 +278,11 @@ extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *); extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *, struct external_info *); +extern struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area, + struct external_info *ei); +extern struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area, + struct ospf_lsa *lsa, + struct external_info *ei); extern void ospf_external_lsa_rid_change(struct ospf *ospf); extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *, uint32_t, struct in_addr, diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index d3f30ce1ee..aff8ed05c7 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -15,6 +15,7 @@ #include "sockopt.h" #include "privs.h" #include "lib_errors.h" +#include "lib/table.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -111,7 +112,7 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p, "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s", top->fd, &p->u.prefix4, ifindex, safe_strerror(errno)); - else + else if (IS_DEBUG_OSPF_EVENT) zlog_debug( "interface %pI4 [%u] leave AllDRouters Multicast group.", &p->u.prefix4, ifindex); @@ -119,62 +120,60 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p, return ret; } -int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) +int ospf_if_ipmulticast(int fd, struct prefix *p, ifindex_t ifindex) { uint8_t val; int ret, len; /* Prevent receiving self-origined multicast packets. */ - ret = setsockopt_ipv4_multicast_loop(top->fd, 0); + ret = setsockopt_ipv4_multicast_loop(fd, 0); if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", - top->fd, safe_strerror(errno)); + fd, safe_strerror(errno)); /* Explicitly set multicast ttl to 1 -- endo. */ val = 1; len = sizeof(val); - ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, - len); + ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", - top->fd, safe_strerror(errno)); + fd, safe_strerror(errno)); #ifndef GNU_LINUX /* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send * packet out of ifindex. Below would be used Non Linux system. */ - ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); + ret = setsockopt_ipv4_multicast_if(fd, p->u.prefix4, ifindex); if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IP_MULTICAST_IF(fd %d, addr %pI4, ifindex %u): %s", - top->fd, &p->u.prefix4, ifindex, + fd, &p->u.prefix4, ifindex, safe_strerror(errno)); #endif return ret; } -int ospf_sock_init(struct ospf *ospf) +/* + * Helper to open and set up a socket; returns the new fd on success, + * -1 on error. + */ +static int sock_init_common(vrf_id_t vrf_id, const char *name, int *pfd) { int ospf_sock; int ret, hincl = 1; - int bufsize = (8 * 1024 * 1024); - - /* silently ignore. already done */ - if (ospf->fd > 0) - return -1; - if (ospf->vrf_id == VRF_UNKNOWN) { + if (vrf_id == VRF_UNKNOWN) { /* silently return since VRF is not ready */ return -1; } + frr_with_privs(&ospfd_privs) { ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP, - ospf->vrf_id, ospf->name); + vrf_id, name); if (ospf_sock < 0) { - flog_err(EC_LIB_SOCKET, - "ospf_read_sock_init: socket: %s", + flog_err(EC_LIB_SOCKET, "%s: socket: %s", __func__, safe_strerror(errno)); return -1; } @@ -213,9 +212,102 @@ int ospf_sock_init(struct ospf *ospf) ospf_sock); } - setsockopt_so_sendbuf(ospf_sock, bufsize); - setsockopt_so_recvbuf(ospf_sock, bufsize); + *pfd = ospf_sock; - ospf->fd = ospf_sock; return ret; } + +/* + * Update a socket bufsize(s), based on its ospf instance + */ +void ospf_sock_bufsize_update(const struct ospf *ospf, int sock, + enum ospf_sock_type_e type) +{ + int bufsize; + + if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_RECV) { + bufsize = ospf->recv_sock_bufsize; + setsockopt_so_recvbuf(sock, bufsize); + } + + if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_SEND) { + bufsize = ospf->send_sock_bufsize; + setsockopt_so_sendbuf(sock, bufsize); + } +} + +int ospf_sock_init(struct ospf *ospf) +{ + int ret; + + /* silently ignore. already done */ + if (ospf->fd > 0) + return -1; + + ret = sock_init_common(ospf->vrf_id, ospf->name, &(ospf->fd)); + + if (ret >= 0) /* Update socket buffer sizes */ + ospf_sock_bufsize_update(ospf, ospf->fd, OSPF_SOCK_BOTH); + + return ret; +} + +/* + * Open per-interface write socket + */ +int ospf_ifp_sock_init(struct interface *ifp) +{ + struct ospf_if_info *oii; + struct ospf_interface *oi; + struct ospf *ospf; + struct route_node *rn; + int ret; + + oii = IF_OSPF_IF_INFO(ifp); + if (oii == NULL) + return -1; + + if (oii->oii_fd > 0) + return 0; + + rn = route_top(IF_OIFS(ifp)); + if (rn && rn->info) { + oi = rn->info; + ospf = oi->ospf; + } else + return -1; + + ret = sock_init_common(ifp->vrf->vrf_id, ifp->name, &oii->oii_fd); + + if (ret >= 0) /* Update socket buffer sizes */ + ospf_sock_bufsize_update(ospf, oii->oii_fd, OSPF_SOCK_BOTH); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, ifp->name, + oii, oii->oii_fd); + + return ret; +} + +/* + * Close per-interface write socket + */ +int ospf_ifp_sock_close(struct interface *ifp) +{ + struct ospf_if_info *oii; + + oii = IF_OSPF_IF_INFO(ifp); + if (oii == NULL) + return 0; + + if (oii->oii_fd > 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, + ifp->name, oii, oii->oii_fd); + + close(oii->oii_fd); + oii->oii_fd = -1; + } + + return 0; +} diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index 33fd8980bf..b810bad50b 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -13,7 +13,20 @@ extern int ospf_if_drop_allspfrouters(struct ospf *, struct prefix *, ifindex_t); extern int ospf_if_add_alldrouters(struct ospf *, struct prefix *, ifindex_t); extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t); -extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t); +extern int ospf_if_ipmulticast(int fd, struct prefix *, ifindex_t); extern int ospf_sock_init(struct ospf *ospf); +/* Open, close per-interface write socket */ +int ospf_ifp_sock_init(struct interface *ifp); +int ospf_ifp_sock_close(struct interface *ifp); + +enum ospf_sock_type_e { + OSPF_SOCK_NONE = 0, + OSPF_SOCK_RECV, + OSPF_SOCK_SEND, + OSPF_SOCK_BOTH +}; + +void ospf_sock_bufsize_update(const struct ospf *ospf, int sock, + enum ospf_sock_type_e type); #endif /* _ZEBRA_OSPF_NETWORK_H */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 5f7d49e0bb..552acfd6d3 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -618,7 +618,7 @@ static void ospf_write(struct event *thread) struct msghdr msg; struct iovec iov[2]; uint8_t type; - int ret; + int ret, fd; int flags = 0; struct listnode *node; #ifdef WANT_OSPF_WRITE_FRAGMENT @@ -633,11 +633,12 @@ static void ospf_write(struct event *thread) struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf; struct in_pktinfo *pi; #endif + fd = ospf->fd; - if (ospf->fd < 0 || ospf->oi_running == 0) { + if (fd < 0 || ospf->oi_running == 0) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s failed to send, fd %d, instance %u", - __func__, ospf->fd, ospf->oi_running); + __func__, fd, ospf->oi_running); return; } @@ -657,6 +658,15 @@ static void ospf_write(struct event *thread) /* convenience - max OSPF data per packet */ maxdatasize = oi->ifp->mtu - sizeof(struct ip); #endif /* WANT_OSPF_WRITE_FRAGMENT */ + + /* Reset socket fd to use. */ + fd = ospf->fd; + + /* Check for per-interface socket */ + if (ospf->intf_socket_enabled && + (IF_OSPF_IF_INFO(oi->ifp))->oii_fd > 0) + fd = (IF_OSPF_IF_INFO(oi->ifp))->oii_fd; + /* Get one packet from queue. */ op = ospf_fifo_head(oi->obuf); assert(op); @@ -664,8 +674,7 @@ static void ospf_write(struct event *thread) if (op->dst.s_addr == htonl(OSPF_ALLSPFROUTERS) || op->dst.s_addr == htonl(OSPF_ALLDROUTERS)) - ospf_if_ipmulticast(ospf, oi->address, - oi->ifp->ifindex); + ospf_if_ipmulticast(fd, oi->address, oi->ifp->ifindex); /* Rewrite the md5 signature & update the seq */ ospf_make_md5_digest(oi, op); @@ -760,13 +769,13 @@ static void ospf_write(struct event *thread) #ifdef WANT_OSPF_WRITE_FRAGMENT if (op->length > maxdatasize) - ospf_write_frags(ospf->fd, op, &iph, &msg, maxdatasize, + ospf_write_frags(fd, op, &iph, &msg, maxdatasize, oi->ifp->mtu, flags, type); #endif /* WANT_OSPF_WRITE_FRAGMENT */ /* send final fragment (could be first) */ sockopt_iphdrincl_swab_htosys(&iph); - ret = sendmsg(ospf->fd, &msg, flags); + ret = sendmsg(fd, &msg, flags); sockopt_iphdrincl_swab_systoh(&iph); if (IS_DEBUG_OSPF_EVENT) zlog_debug( diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 5f18bff1cf..75868056ad 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -1008,7 +1008,8 @@ void ospf_prune_unreachable_routers(struct route_table *rtrs) } int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, - struct ospf_area *area, struct prefix_ipv4 *p) + struct ospf_area *area, struct prefix_ipv4 *p, + bool nssa) { struct route_node *rn; struct ospf_route * or, *new_or; @@ -1027,7 +1028,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, or = rn->info; - if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: an intra-area route exists", __func__); @@ -1054,7 +1055,10 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, new_or->cost = 0; new_or->u.std.area_id = area->area_id; new_or->u.std.external_routing = area->external_routing; - new_or->path_type = OSPF_PATH_INTER_AREA; + if (nssa) + new_or->path_type = OSPF_PATH_TYPE2_EXTERNAL; + else + new_or->path_type = OSPF_PATH_INTER_AREA; rn->info = new_or; ospf_zebra_add_discard(ospf, p); @@ -1063,7 +1067,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, } void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt, - struct prefix_ipv4 *p) + struct prefix_ipv4 *p, bool nssa) { struct route_node *rn; struct ospf_route * or ; @@ -1081,7 +1085,7 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt, or = rn->info; - if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) { if (IS_DEBUG_OSPF_EVENT) zlog_debug("%s: an intra-area route exists", __func__); return; diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 2582067aec..7639a0049e 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -152,9 +152,10 @@ extern void ospf_route_subst_nexthops(struct ospf_route *, struct list *); extern void ospf_prune_unreachable_networks(struct route_table *); extern void ospf_prune_unreachable_routers(struct route_table *); extern int ospf_add_discard_route(struct ospf *, struct route_table *, - struct ospf_area *, struct prefix_ipv4 *); + struct ospf_area *, struct prefix_ipv4 *, + bool); extern void ospf_delete_discard_route(struct ospf *, struct route_table *, - struct prefix_ipv4 *); + struct prefix_ipv4 *, bool); extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *, struct ospf_route *); diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 3087008819..3d5c5aa2d5 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -120,7 +120,7 @@ route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object) alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -168,7 +168,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(AFI_IP, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -245,7 +245,7 @@ route_match_ip_address(void *rule, const struct prefix *prefix, void *object) alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -286,7 +286,7 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(AFI_IP, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 2982cc7d6f..fcc43e7311 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -1112,7 +1112,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, oid2in_addr(offset, IN_ADDR_SIZE, range_net); p.prefix = *range_net; - return ospf_area_range_lookup(area, &p); + return ospf_area_range_lookup(area, area->ranges, &p); } else { /* Set OID offset for Area ID. */ offset = name + v->namelen; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index dc9dd34303..b140027147 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1781,7 +1781,7 @@ static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex, * @param metric Standard metric attached to this Edge */ static void ospf_te_update_subnet(struct ls_ted *ted, struct ls_vertex *vertex, - struct prefix p, uint8_t metric) + struct prefix *p, uint8_t metric) { struct ls_subnet *subnet; struct ls_prefix *ls_pref; @@ -1840,7 +1840,7 @@ static void ospf_te_delete_subnet(struct ls_ted *ted, struct in_addr addr) p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = addr; - subnet = ls_find_subnet(ted, p); + subnet = ls_find_subnet(ted, &p); /* Remove subnet if found */ if (subnet) { @@ -1933,7 +1933,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa) p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = rl->link[i].link_data; metric = ntohs(rl->link[i].metric); - ospf_te_update_subnet(ted, vertex, p, metric); + ospf_te_update_subnet(ted, vertex, &p, metric); break; case LSA_LINK_TYPE_STUB: /* Keep only /32 prefix */ @@ -1942,7 +1942,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa) p.family = AF_INET; p.u.prefix4 = rl->link[i].link_id; metric = ntohs(rl->link[i].metric); - ospf_te_update_subnet(ted, vertex, p, metric); + ospf_te_update_subnet(ted, vertex, &p, metric); } break; default: @@ -2074,12 +2074,12 @@ static void ospf_te_update_remote_asbr(struct ls_ted *ted, struct ls_edge *edge) p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = attr->standard.local; - ospf_te_update_subnet(ted, edge->source, p, attr->standard.te_metric); + ospf_te_update_subnet(ted, edge->source, &p, attr->standard.te_metric); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = attr->standard.remote_addr; - ospf_te_update_subnet(ted, vertex, p, attr->standard.te_metric); + ospf_te_update_subnet(ted, vertex, &p, attr->standard.te_metric); /* Connect Edge to the remote Vertex */ if (edge->destination == NULL) { @@ -2625,14 +2625,14 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa) pref.family = AF_INET; pref.prefixlen = ext->pref_length; pref.u.prefix4 = ext->address; - subnet = ls_find_subnet(ted, pref); + subnet = ls_find_subnet(ted, &pref); /* Create new Link State Prefix if not found */ if (!subnet) { lnid.origin = OSPFv2; lnid.id.ip.addr = lsa->data->adv_router; lnid.id.ip.area_id = lsa->area->area_id; - ls_pref = ls_prefix_new(lnid, pref); + ls_pref = ls_prefix_new(lnid, &pref); /* and add it to the TED */ subnet = ls_subnet_add(ted, ls_pref); } @@ -2698,7 +2698,7 @@ static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa) pref.family = AF_INET; pref.prefixlen = ext->pref_length; pref.u.prefix4 = ext->address; - subnet = ls_find_subnet(ted, pref); + subnet = ls_find_subnet(ted, &pref); /* Check if there is a corresponding subnet */ if (!subnet) @@ -4398,7 +4398,7 @@ DEFUN (show_ip_ospf_mpls_te_db, return CMD_WARNING_CONFIG_FAILED; } /* Get the Subnet from the Link State Database */ - subnet = ls_find_subnet(OspfMplsTE.ted, pref); + subnet = ls_find_subnet(OspfMplsTE.ted, &pref); if (!subnet) { vty_out(vty, "No subnet found for ID %pFX\n", &pref); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 8c0afd8527..3c0e0fcb63 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -35,12 +35,11 @@ #include "ospfd/ospf_spf.h" #include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" -/*#include "ospfd/ospf_routemap.h" */ #include "ospfd/ospf_vty.h" #include "ospfd/ospf_dump.h" #include "ospfd/ospf_bfd.h" #include "ospfd/ospf_ldp_sync.h" - +#include "ospfd/ospf_network.h" FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES, { .val_bool = true, .match_profile = "datacenter", }, @@ -611,6 +610,7 @@ DEFUN (ospf_area_range, "Advertised metric for this range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; int idx_ipv4_number = 1; int idx_ipv4_prefixlen = 3; int idx_cost = 6; @@ -622,12 +622,14 @@ DEFUN (ospf_area_range, VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_set(ospf, area, area->ranges, &p, + OSPF_AREA_RANGE_ADVERTISE, false); if (argc > 5) { cost = strtoul(argv[idx_cost]->arg, NULL, 10); - ospf_area_range_cost_set(ospf, area_id, &p, cost); + ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost); } return CMD_SUCCESS; @@ -647,6 +649,7 @@ DEFUN (ospf_area_range_cost, "Network prefix to be announced instead of range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; int idx_ipv4_number = 1; int idx_ipv4_prefixlen = 3; int idx = 4; @@ -658,19 +661,20 @@ DEFUN (ospf_area_range_cost, VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + ospf_area_range_set(ospf, area, area->ranges, &p, + OSPF_AREA_RANGE_ADVERTISE, false); if (argv_find(argv, argc, "cost", &idx)) { cost = strtoul(argv[idx + 1]->arg, NULL, 10); - ospf_area_range_cost_set(ospf, area_id, &p, cost); + ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost); } idx = 4; if (argv_find(argv, argc, "substitute", &idx)) { str2prefix_ipv4(argv[idx + 1]->arg, &s); - ospf_area_range_substitute_set(ospf, area_id, &p, &s); + ospf_area_range_substitute_set(ospf, area, &p, &s); } return CMD_SUCCESS; @@ -687,6 +691,7 @@ DEFUN (ospf_area_range_not_advertise, "DoNotAdvertise this range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; int idx_ipv4_number = 1; int idx_ipv4_prefixlen = 3; struct prefix_ipv4 p; @@ -696,10 +701,11 @@ DEFUN (ospf_area_range_not_advertise, VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_set(ospf, area_id, &p, 0); - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); - ospf_area_range_substitute_unset(ospf, area_id, &p); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_set(ospf, area, area->ranges, &p, 0, false); + ospf_area_range_substitute_unset(ospf, area, &p); return CMD_SUCCESS; } @@ -721,6 +727,7 @@ DEFUN (no_ospf_area_range, "DoNotAdvertise this range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; int idx_ipv4_number = 2; int idx_ipv4_prefixlen = 4; struct prefix_ipv4 p; @@ -730,7 +737,10 @@ DEFUN (no_ospf_area_range, VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_unset(ospf, area_id, &p); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_unset(ospf, area, area->ranges, &p); return CMD_SUCCESS; } @@ -748,6 +758,7 @@ DEFUN (no_ospf_area_range_substitute, "Network prefix to be announced instead of range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; int idx_ipv4_number = 2; int idx_ipv4_prefixlen = 4; int idx_ipv4_prefixlen_2 = 6; @@ -759,7 +770,10 @@ DEFUN (no_ospf_area_range_substitute, str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); - ospf_area_range_substitute_unset(ospf, area_id, &p); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_substitute_unset(ospf, area, &p); return CMD_SUCCESS; } @@ -1433,15 +1447,35 @@ DEFUN (no_ospf_area_stub_no_summary, return CMD_SUCCESS; } -static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc, - struct cmd_token **argv, int cfg_nosum, - int nosum) +DEFPY (ospf_area_nssa, + ospf_area_nssa_cmd, + "area <A.B.C.D|(0-4294967295)>$area_str nssa\ + [{\ + <translate-candidate|translate-never|translate-always>$translator_role\ + |default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\ + |no-summary$no_summary\ + |suppress-fa$suppress_fa\ + }]", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as nssa\n" + "Configure NSSA-ABR for translate election (default)\n" + "Configure NSSA-ABR to never translate\n" + "Configure NSSA-ABR to always translate\n" + "Originate Type 7 default into NSSA area\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Do not inject inter-area routes into nssa\n" + "Suppress forwarding address\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); struct in_addr area_id; int ret, format; - VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, argv[1]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str); ret = ospf_area_nssa_set(ospf, area_id); ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), @@ -1452,14 +1486,14 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc, return CMD_WARNING_CONFIG_FAILED; } - if (argc > 3) { - if (strncmp(argv[3]->text, "translate-c", 11) == 0) + if (translator_role) { + if (strncmp(translator_role, "translate-c", 11) == 0) ospf_area_nssa_translator_role_set( ospf, area_id, OSPF_NSSA_ROLE_CANDIDATE); - else if (strncmp(argv[3]->text, "translate-n", 11) == 0) + else if (strncmp(translator_role, "translate-n", 11) == 0) ospf_area_nssa_translator_role_set( ospf, area_id, OSPF_NSSA_ROLE_NEVER); - else if (strncmp(argv[3]->text, "translate-a", 11) == 0) + else if (strncmp(translator_role, "translate-a", 11) == 0) ospf_area_nssa_translator_role_set( ospf, area_id, OSPF_NSSA_ROLE_ALWAYS); } else { @@ -1467,12 +1501,27 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc, OSPF_NSSA_ROLE_CANDIDATE); } - if (cfg_nosum) { - if (nosum) - ospf_area_no_summary_set(ospf, area_id); - else - ospf_area_no_summary_unset(ospf, area_id); - } + if (dflt_originate) { + int metric_type = DEFAULT_METRIC_TYPE; + + if (mval_str == NULL) + mval = -1; + if (mtype_str) + (void)str2metric_type(mtype_str, &metric_type); + ospf_area_nssa_default_originate_set(ospf, area_id, mval, + metric_type); + } else + ospf_area_nssa_default_originate_unset(ospf, area_id); + + if (no_summary) + ospf_area_nssa_no_summary_set(ospf, area_id); + else + ospf_area_no_summary_unset(ospf, area_id); + + if (suppress_fa) + ospf_area_nssa_suppress_fa_set(ospf, area_id); + else + ospf_area_nssa_suppress_fa_unset(ospf, area_id); /* Flush the external LSA for the specified area */ ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA); @@ -1482,168 +1531,125 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc, return CMD_SUCCESS; } - -DEFUN (ospf_area_nssa_translate, - ospf_area_nssa_translate_cmd, - "area <A.B.C.D|(0-4294967295)> nssa <translate-candidate|translate-never|translate-always>", +DEFPY (no_ospf_area_nssa, + no_ospf_area_nssa_cmd, + "no area <A.B.C.D|(0-4294967295)>$area_str nssa\ + [{\ + <translate-candidate|translate-never|translate-always>\ + |default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\ + |no-summary\ + |suppress-fa\ + }]", + NO_STR "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" "Configure OSPF area as nssa\n" "Configure NSSA-ABR for translate election (default)\n" "Configure NSSA-ABR to never translate\n" - "Configure NSSA-ABR to always translate\n") -{ - return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0); -} - -DEFUN (ospf_area_nssa, - ospf_area_nssa_cmd, - "area <A.B.C.D|(0-4294967295)> nssa", - "OSPF area parameters\n" - "OSPF area ID in IP address format\n" - "OSPF area ID as a decimal value\n" - "Configure OSPF area as nssa\n") -{ - return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0); -} - -DEFUN(ospf_area_nssa_suppress_fa, ospf_area_nssa_suppress_fa_cmd, - "area <A.B.C.D|(0-4294967295)> nssa suppress-fa", - "OSPF area parameters\n" - "OSPF area ID in IP address format\n" - "OSPF area ID as a decimal value\n" - "Configure OSPF area as nssa\n" - "Suppress forwarding address\n") + "Configure NSSA-ABR to always translate\n" + "Originate Type 7 default into NSSA area\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Do not inject inter-area routes into nssa\n" + "Suppress forwarding address\n") { - int idx_ipv4_number = 1; - struct in_addr area_id; - int format; - VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, - argv[idx_ipv4_number]->arg); - - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); - ospf_area_nssa_suppress_fa_set(ospf, area_id); - - ospf_schedule_abr_task(ospf); - - return CMD_SUCCESS; -} - -DEFUN(no_ospf_area_nssa_suppress_fa, no_ospf_area_nssa_suppress_fa_cmd, - "no area <A.B.C.D|(0-4294967295)> nssa suppress-fa", - NO_STR - "OSPF area parameters\n" - "OSPF area ID in IP address format\n" - "OSPF area ID as a decimal value\n" - "Configure OSPF area as nssa\n" - "Suppress forwarding address\n") -{ - int idx_ipv4_number = 2; struct in_addr area_id; int format; - VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - - VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format, - argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str); - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); + /* Flush the NSSA LSA for the specified area */ + ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA); + ospf_area_no_summary_unset(ospf, area_id); + ospf_area_nssa_default_originate_unset(ospf, area_id); ospf_area_nssa_suppress_fa_unset(ospf, area_id); + ospf_area_nssa_unset(ospf, area_id); ospf_schedule_abr_task(ospf); return CMD_SUCCESS; } -DEFUN (ospf_area_nssa_no_summary, - ospf_area_nssa_no_summary_cmd, - "area <A.B.C.D|(0-4294967295)> nssa no-summary", +DEFPY (ospf_area_nssa_range, + ospf_area_nssa_range_cmd, + "area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]", "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" "Configure OSPF area as nssa\n" - "Do not inject inter-area routes into nssa\n") + "Configured address range\n" + "Specify IPv4 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") { - int idx_ipv4_number = 1; - struct in_addr area_id; - int format; - VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, - argv[idx_ipv4_number]->arg); - - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); - ospf_area_nssa_no_summary_set(ospf, area_id); - - ospf_schedule_abr_task(ospf); - - return CMD_SUCCESS; -} - -DEFUN (no_ospf_area_nssa_no_summary, - no_ospf_area_nssa_no_summary_cmd, - "no area <A.B.C.D|(0-4294967295)> nssa no-summary", - NO_STR - "OSPF area parameters\n" - "OSPF area ID in IP address format\n" - "OSPF area ID as a decimal value\n" - "Configure OSPF area as nssa\n" - "Do not inject inter-area routes into nssa\n") -{ - int idx_ipv4_number = 2; + struct ospf_area *area; struct in_addr area_id; int format; + int advertise = 0; - VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + VTY_GET_OSPF_AREA_ID(area_id, format, area_str); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); - VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format, - argv[idx_ipv4_number]->arg); + if (area->external_routing != OSPF_AREA_NSSA) { + vty_out(vty, "%% First configure %s as an NSSA area\n", + area_str); + return CMD_WARNING; + } - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); - ospf_area_no_summary_unset(ospf, area_id); + if (!not_adv) + advertise = OSPF_AREA_RANGE_ADVERTISE; - ospf_schedule_abr_task(ospf); + ospf_area_range_set(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix, advertise, true); + if (cost_str) + ospf_area_range_cost_set(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix, cost); return CMD_SUCCESS; } -DEFUN (no_ospf_area_nssa, - no_ospf_area_nssa_cmd, - "no area <A.B.C.D|(0-4294967295)> nssa [<translate-candidate|translate-never|translate-always>]", +DEFPY (no_ospf_area_nssa_range, + no_ospf_area_nssa_range_cmd, + "no area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise|cost (0-16777215)>]", NO_STR "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" "Configure OSPF area as nssa\n" - "Configure NSSA-ABR for translate election (default)\n" - "Configure NSSA-ABR to never translate\n" - "Configure NSSA-ABR to always translate\n") + "Configured address range\n" + "Specify IPv4 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; + struct ospf_area *area; struct in_addr area_id; int format; - VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, - argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, area_str); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); - /* Flush the NSSA LSA for the specified area */ - ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA); - ospf_area_nssa_unset(ospf, area_id, argc); + if (area->external_routing != OSPF_AREA_NSSA) { + vty_out(vty, "%% First configure %s as an NSSA area\n", + area_str); + return CMD_WARNING; + } - ospf_schedule_abr_task(ospf); + ospf_area_range_unset(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix); return CMD_SUCCESS; } - DEFUN (ospf_area_default_cost, ospf_area_default_cost_cmd, "area <A.B.C.D|(0-4294967295)> default-cost (0-16777215)", @@ -3396,6 +3402,23 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, /* show LDP-Sync status */ ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0); + /* Socket buffer sizes */ + if (json) { + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + json_object_int_add(json_vrf, "recvSockBufsize", + ospf->recv_sock_bufsize); + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + json_object_int_add(json_vrf, "sendSockBufsize", + ospf->send_sock_bufsize); + } else { + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + vty_out(vty, " Receive socket bufsize: %u\n", + ospf->recv_sock_bufsize); + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + vty_out(vty, " Send socket bufsize: %u\n", + ospf->send_sock_bufsize); + } + /* Show each area status. */ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0); @@ -5065,6 +5088,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, json_object *json_neigh = NULL, *json_neigh_array = NULL; char neigh_str[INET_ADDRSTRLEN] = {0}; char neigh_state[16] = {0}; + struct ospf_neighbor *nbr_dr, *nbr_bdr; if (use_json) { if (prev_nbr && @@ -5192,19 +5216,38 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, } } - /* Show Designated Rotuer ID. */ - if (use_json) - json_object_string_addf(json_neigh, "routerDesignatedId", - "%pI4", &nbr->d_router); - else - vty_out(vty, " DR is %pI4,", &nbr->d_router); + /* Show Designated Router ID. */ + if (DR(oi).s_addr == INADDR_ANY) { + if (!use_json) + vty_out(vty, + " No designated router on this network\n"); + } else { + nbr_dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); + if (nbr_dr) { + if (use_json) + json_object_string_addf( + json_neigh, "routerDesignatedId", + "%pI4", &nbr_dr->router_id); + else + vty_out(vty, " DR is %pI4,", + &nbr_dr->router_id); + } + } - /* Show Backup Designated Rotuer ID. */ - if (use_json) - json_object_string_addf(json_neigh, "routerDesignatedBackupId", - "%pI4", &nbr->bd_router); - else - vty_out(vty, " BDR is %pI4\n", &nbr->bd_router); + /* Show Backup Designated Router ID. */ + nbr_bdr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi)); + if (nbr_bdr == NULL) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + if (use_json) + json_object_string_addf(json_neigh, + "routerDesignatedBackupId", + "%pI4", &nbr_bdr->router_id); + else + vty_out(vty, " BDR is %pI4\n", &nbr_bdr->router_id); + } /* Show options. */ if (use_json) { @@ -11981,29 +12024,62 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf) vty_out(vty, " no-summary\n"); vty_out(vty, "\n"); } else if (area->external_routing == OSPF_AREA_NSSA) { + vty_out(vty, " area %s nssa", buf); + switch (area->NSSATranslatorRole) { case OSPF_NSSA_ROLE_NEVER: - vty_out(vty, - " area %s nssa translate-never\n", - buf); + vty_out(vty, " translate-never"); break; case OSPF_NSSA_ROLE_ALWAYS: - vty_out(vty, - " area %s nssa translate-always\n", - buf); + vty_out(vty, " translate-always"); break; case OSPF_NSSA_ROLE_CANDIDATE: - vty_out(vty, " area %s nssa \n", buf); break; } - if (area->no_summary) + + if (area->nssa_default_originate.enabled) { vty_out(vty, - " area %s nssa no-summary\n", - buf); + " default-information-originate"); + if (area->nssa_default_originate + .metric_value != -1) + vty_out(vty, " metric %d", + area->nssa_default_originate + .metric_value); + if (area->nssa_default_originate + .metric_type != + DEFAULT_METRIC_TYPE) + vty_out(vty, " metric-type 1"); + } + + if (area->no_summary) + vty_out(vty, " no-summary"); if (area->suppress_fa) - vty_out(vty, - " area %s nssa suppress-fa\n", - buf); + vty_out(vty, " suppress-fa"); + vty_out(vty, "\n"); + + for (rn1 = route_top(area->nssa_ranges); rn1; + rn1 = route_next(rn1)) { + struct ospf_area_range *range; + + range = rn1->info; + if (!range) + continue; + + vty_out(vty, " area %s nssa range %pFX", + buf, &rn1->p); + + if (range->cost_config != + OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %u", + range->cost_config); + + if (!CHECK_FLAG( + range->flags, + OSPF_AREA_RANGE_ADVERTISE)) + vty_out(vty, " not-advertise"); + + vty_out(vty, "\n"); + } } if (area->default_cost != 1) @@ -12434,6 +12510,9 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) if (ospf->fr_configured) vty_out(vty, " flood-reduction\n"); + if (!ospf->intf_socket_enabled) + vty_out(vty, " no socket-per-interface\n"); + /* Redistribute information print. */ config_write_ospf_redistribute(vty, ospf); @@ -12490,6 +12569,22 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) /* LDP-Sync print */ ospf_ldp_sync_write_config(vty, ospf); + /* Socket buffer sizes */ + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) { + if (ospf->send_sock_bufsize == ospf->recv_sock_bufsize) + vty_out(vty, " socket buffer all %u\n", + ospf->recv_sock_bufsize); + else + vty_out(vty, " socket buffer recv %u\n", + ospf->recv_sock_bufsize); + } + + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE && + ospf->send_sock_bufsize != ospf->recv_sock_bufsize) + vty_out(vty, " socket buffer send %u\n", + ospf->send_sock_bufsize); + + vty_out(vty, "exit\n"); write++; @@ -12946,6 +13041,71 @@ DEFPY(no_flood_reduction_area, no_flood_reduction_area_cmd, return CMD_SUCCESS; } +DEFPY(ospf_socket_bufsizes, + ospf_socket_bufsizes_cmd, + "[no] socket buffer <send$send_val | recv$recv_val | all$all_val> \ + ![(1-4000000000)$bufsize]", + NO_STR + "Socket parameters\n" + "Buffer size configuration\n" + "Send buffer size\n" + "Receive buffer size\n" + "Both send and receive buffer sizes\n" + "Buffer size, in bytes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + uint32_t recvsz, sendsz; + + if (no) + bufsize = OSPF_DEFAULT_SOCK_BUFSIZE; + + if (all_val) { + recvsz = bufsize; + sendsz = bufsize; + } else if (send_val) { + sendsz = bufsize; + recvsz = ospf->recv_sock_bufsize; + } else if (recv_val) { + recvsz = bufsize; + sendsz = ospf->send_sock_bufsize; + } else + return CMD_SUCCESS; + + /* React to a change by modifying existing sockets */ + ospf_update_bufsize(ospf, recvsz, sendsz); + + return CMD_SUCCESS; +} + +DEFPY (per_intf_socket, + per_intf_socket_cmd, + "[no] socket-per-interface", + NO_STR + "Use write socket per interface\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *node; + struct ospf_interface *oi; + + if (no) { + if (ospf->intf_socket_enabled) { + ospf->intf_socket_enabled = false; + + /* Iterate and close any sockets */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + ospf_ifp_sock_close(oi->ifp); + } + } else if (!ospf->intf_socket_enabled) { + ospf->intf_socket_enabled = true; + + /* Iterate and open sockets */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + ospf_ifp_sock_init(oi->ifp); + } + + return CMD_SUCCESS; +} + void ospf_vty_clear_init(void) { install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd); @@ -13029,12 +13189,9 @@ void ospf_vty_init(void) /* "area nssa" commands. */ install_element(OSPF_NODE, &ospf_area_nssa_cmd); - install_element(OSPF_NODE, &ospf_area_nssa_translate_cmd); - install_element(OSPF_NODE, &ospf_area_nssa_no_summary_cmd); - install_element(OSPF_NODE, &no_ospf_area_nssa_no_summary_cmd); - install_element(OSPF_NODE, &ospf_area_nssa_suppress_fa_cmd); - install_element(OSPF_NODE, &no_ospf_area_nssa_suppress_fa_cmd); install_element(OSPF_NODE, &no_ospf_area_nssa_cmd); + install_element(OSPF_NODE, &ospf_area_nssa_range_cmd); + install_element(OSPF_NODE, &no_ospf_area_nssa_range_cmd); install_element(OSPF_NODE, &ospf_area_default_cost_cmd); install_element(OSPF_NODE, &no_ospf_area_default_cost_cmd); @@ -13112,6 +13269,9 @@ void ospf_vty_init(void) install_element(OSPF_NODE, &flood_reduction_area_cmd); install_element(OSPF_NODE, &no_flood_reduction_area_cmd); + install_element(OSPF_NODE, &ospf_socket_bufsizes_cmd); + install_element(OSPF_NODE, &per_intf_socket_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init(); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 3e02d3c33e..3f967e41e4 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -20,6 +20,7 @@ #include "log.h" #include "route_opaque.h" #include "lib/bfd.h" +#include "lib/lib_errors.h" #include "nexthop.h" #include "ospfd/ospfd.h" @@ -1470,6 +1471,61 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) return 0; } +void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg) +{ + struct prefix prefix = {}; + int command; + + if (zclient->sock < 0) { + if (IS_DEBUG_OSPF(zebra, ZEBRA)) + zlog_debug(" Not connected to Zebra"); + return; + } + + prefix.family = AF_INET; + prefix.prefixlen = 0; + + if (unreg) + command = ZEBRA_NEXTHOP_UNREGISTER; + else + command = ZEBRA_NEXTHOP_REGISTER; + + if (IS_DEBUG_OSPF(zebra, ZEBRA)) + zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__, + zserv_command_string(command), &prefix, + ospf->vrf_id); + + if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false, + true, ospf->vrf_id) == ZCLIENT_SEND_FAILURE) + flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed", + __func__); +} + +static int ospf_zebra_import_check_update(ZAPI_CALLBACK_ARGS) +{ + struct ospf *ospf; + struct zapi_route nhr; + struct prefix matched; + + ospf = ospf_lookup_by_vrf_id(vrf_id); + if (ospf == NULL || !IS_OSPF_ASBR(ospf)) + return 0; + + if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { + zlog_err("%s[%u]: Failure to decode route", __func__, + ospf->vrf_id); + return -1; + } + + if (matched.family != AF_INET || matched.prefixlen != 0 || + nhr.type == ZEBRA_ROUTE_OSPF) + return 0; + + ospf->nssa_default_import_check.status = !!nhr.nexthop_num; + ospf_abr_nssa_type7_defaults(ospf); + + return 0; +} int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name) { @@ -2132,6 +2188,7 @@ static zclient_handler *const ospf_handlers[] = { [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route, [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route, + [ZEBRA_NEXTHOP_UPDATE] = ospf_zebra_import_check_update, [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler, diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 711b1e7a61..86a5678fc4 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -69,6 +69,7 @@ extern int ospf_redistribute_set(struct ospf *, struct ospf_redist *, int, unsigned short, int, int); extern int ospf_redistribute_unset(struct ospf *, int, unsigned short); extern int ospf_redistribute_default_set(struct ospf *, int, int, int); +extern void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg); extern int ospf_distribute_list_out_set(struct ospf *, int, const char *); extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *); extern void ospf_routemap_set(struct ospf_redist *, const char *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 112ddfedb7..7e83714c0a 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -419,6 +419,10 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name) QOBJ_REG(new, ospf); new->fd = -1; + new->intf_socket_enabled = true; + + new->recv_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE; + new->send_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE; return new; } @@ -963,6 +967,7 @@ struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id) new->oiflist = list_new(); new->ranges = route_table_init(); + new->nssa_ranges = route_table_init(); if (area_id.s_addr == OSPF_AREA_BACKBONE) ospf->backbone = new; @@ -1006,6 +1011,7 @@ static void ospf_area_free(struct ospf_area *area) ospf_lsa_unlock(&area->router_lsa_self); route_table_finish(area->ranges); + route_table_finish(area->nssa_ranges); list_delete(&area->oiflist); if (EXPORT_NAME(area)) @@ -1029,13 +1035,14 @@ void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id) struct ospf_area *area; area = ospf_area_lookup_by_area_id(ospf, area_id); - if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL - && !ospf_vl_count(ospf, area) - && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT - && area->external_routing == OSPF_AREA_DEFAULT - && area->no_summary == 0 && area->default_cost == 1 - && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL - && area->auth_type == OSPF_AUTH_NULL) { + if (area && listcount(area->oiflist) == 0 && + area->ranges->top == NULL && area->nssa_ranges->top == NULL && + !ospf_vl_count(ospf, area) && + area->shortcut_configured == OSPF_SHORTCUT_DEFAULT && + area->external_routing == OSPF_AREA_DEFAULT && + area->no_summary == 0 && area->default_cost == 1 && + EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL && + area->auth_type == OSPF_AUTH_NULL) { listnode_delete(ospf->areas, area); ospf_area_free(area); } @@ -1701,7 +1708,7 @@ int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id) return 1; } -int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc) +int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id) { struct ospf_area *area; @@ -1709,22 +1716,14 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc) if (area == NULL) return 0; - /* argc < 5 -> 'no area x nssa' */ - if (argc < 5 && area->external_routing == OSPF_AREA_NSSA) { - ospf->anyNSSA--; - /* set NSSA area defaults */ - area->no_summary = 0; - area->suppress_fa = 0; - area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; - area->NSSATranslatorStabilityInterval = - OSPF_NSSA_TRANS_STABLE_DEFAULT; - ospf_area_type_set(area, OSPF_AREA_DEFAULT); - } else { - ospf_area_nssa_translator_role_set(ospf, area_id, - OSPF_NSSA_ROLE_CANDIDATE); - } - + ospf->anyNSSA--; + /* set NSSA area defaults */ + area->no_summary = 0; + area->suppress_fa = 0; + area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; + area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; + area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT; + ospf_area_type_set(area, OSPF_AREA_DEFAULT); ospf_area_check_free(ospf, area_id); return 1; @@ -1782,6 +1781,51 @@ int ospf_area_nssa_translator_role_set(struct ospf *ospf, return 1; } +void ospf_area_nssa_default_originate_set(struct ospf *ospf, + struct in_addr area_id, int metric, + int metric_type) +{ + struct ospf_area *area; + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return; + + if (!area->nssa_default_originate.enabled) { + area->nssa_default_originate.enabled = true; + if (++ospf->nssa_default_import_check.refcnt == 1) { + ospf->nssa_default_import_check.status = false; + ospf_zebra_import_default_route(ospf, false); + } + } + + area->nssa_default_originate.metric_value = metric; + area->nssa_default_originate.metric_type = metric_type; +} + +void ospf_area_nssa_default_originate_unset(struct ospf *ospf, + struct in_addr area_id) +{ + struct ospf_area *area; + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return; + + if (area->nssa_default_originate.enabled) { + area->nssa_default_originate.enabled = false; + if (--ospf->nssa_default_import_check.refcnt == 0) { + ospf->nssa_default_import_check.status = false; + ospf_zebra_import_default_route(ospf, true); + } + area->nssa_default_originate.metric_value = -1; + area->nssa_default_originate.metric_type = -1; + + if (!IS_OSPF_ABR(ospf)) + ospf_abr_nssa_type7_defaults(ospf); + } +} + int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area, const char *list_name) { @@ -2140,6 +2184,32 @@ int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr) return 1; } +/* + * Update socket bufsize(s), usually after config change + */ +void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize, + uint32_t sendsize) +{ + enum ospf_sock_type_e type = OSPF_SOCK_NONE; + + /* Figure out whether there's been a change */ + if (recvsize != ospf->recv_sock_bufsize) { + type = OSPF_SOCK_RECV; + ospf->recv_sock_bufsize = recvsize; + + if (sendsize != ospf->send_sock_bufsize) { + type = OSPF_SOCK_BOTH; + ospf->send_sock_bufsize = sendsize; + } + } else if (sendsize != ospf->send_sock_bufsize) { + type = OSPF_SOCK_SEND; + ospf->send_sock_bufsize = sendsize; + } + + if (type != OSPF_SOCK_NONE) + ospf_sock_bufsize_update(ospf, ospf->fd, type); +} + void ospf_master_init(struct event_loop *master) { memset(&ospf_master, 0, sizeof(ospf_master)); diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 6727d802a6..1f8d1a32e6 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -67,6 +67,9 @@ #define OSPF_LS_REFRESH_SHIFT (60 * 15) #define OSPF_LS_REFRESH_JITTER 60 +/* Default socket buffer size */ +#define OSPF_DEFAULT_SOCK_BUFSIZE (8 * 1024 * 1024) + struct ospf_external { unsigned short instance; struct route_table *external_info; @@ -302,6 +305,18 @@ struct ospf { int default_metric; /* Default metric for redistribute. */ + /* NSSA default-information-originate */ + struct { + /* # of NSSA areas requesting default information */ + uint16_t refcnt; + + /* + * Whether a default route known through non-OSPF protocol is + * present in the RIB. + */ + bool status; + } nssa_default_import_check; + #define OSPF_LSA_REFRESHER_GRANULARITY 10 #define OSPF_LSA_REFRESHER_SLOTS \ ((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \ @@ -412,6 +427,13 @@ struct ospf { /* Flood Reduction configuration state */ bool fr_configured; + /* Socket buffer sizes */ + uint32_t recv_sock_bufsize; + uint32_t send_sock_bufsize; + + /* Per-interface write socket */ + bool intf_socket_enabled; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(ospf); @@ -517,6 +539,7 @@ struct ospf_area { #define OSPF_TRANSIT_FALSE 0 #define OSPF_TRANSIT_TRUE 1 struct route_table *ranges; /* Configured Area Ranges. */ + struct route_table *nssa_ranges; /* Configured NSSA Area Ranges. */ /* RFC3137 stub router state flags for area */ uint8_t stub_router_state; @@ -561,6 +584,13 @@ struct ospf_area { #define PREFIX_LIST_OUT(A) (A)->plist_out.list #define PREFIX_NAME_OUT(A) (A)->plist_out.name + /* NSSA default-information-originate */ + struct { + bool enabled; + int metric_type; + int metric_value; + } nssa_default_originate; + /* Shortest Path Tree. */ struct vertex *spf; struct list *spf_vertex_list; @@ -697,14 +727,18 @@ extern int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id); extern int ospf_area_no_summary_unset(struct ospf *ospf, struct in_addr area_id); extern int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id); -extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, - int argc); +extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id); extern int ospf_area_nssa_suppress_fa_set(struct ospf *ospf, struct in_addr area_id); extern int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf, struct in_addr area_id); extern int ospf_area_nssa_translator_role_set(struct ospf *ospf, struct in_addr area_id, int role); +extern void ospf_area_nssa_default_originate_set(struct ospf *ospf, + struct in_addr area_id, + int metric, int metric_type); +extern void ospf_area_nssa_default_originate_unset(struct ospf *ospf, + struct in_addr area_id); extern int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area_id, const char *list_name); @@ -769,6 +803,9 @@ int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id); const char *ospf_get_name(const struct ospf *ospf); extern struct ospf_interface *add_ospf_interface(struct connected *co, struct ospf_area *area); +/* Update socket bufsize(s), after config change */ +void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize, + uint32_t sendsize); extern int p_spaces_compare_func(const struct p_space *a, const struct p_space *b); diff --git a/pathd/path_ted.c b/pathd/path_ted.c index d8ddd8cdc8..fd5c342d84 100644 --- a/pathd/path_ted.c +++ b/pathd/path_ted.c @@ -268,7 +268,7 @@ uint32_t path_ted_query_type_c(struct prefix *prefix, uint8_t algo) switch (prefix->family) { case AF_INET: case AF_INET6: - subnet = ls_find_subnet(ted_state_g.ted, *prefix); + subnet = ls_find_subnet(ted_state_g.ted, prefix); if (subnet) { if ((CHECK_FLAG(subnet->ls_pref->flags, LS_PREF_SR)) && (subnet->ls_pref->sr.algo == algo)) @@ -298,7 +298,7 @@ uint32_t path_ted_query_type_e(struct prefix *prefix, uint32_t iface_id) switch (prefix->family) { case AF_INET: case AF_INET6: - subnet = ls_find_subnet(ted_state_g.ted, *prefix); + subnet = ls_find_subnet(ted_state_g.ted, prefix); if (subnet && subnet->vertex && subnet->vertex->outgoing_edges) { /* from the vertex linked in subnet */ diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 8c75b0a5b5..2e90cf9053 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -67,7 +67,7 @@ static struct cmd_node debug_node = { }; static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[], - const int argc, int *idx) + const int argc, int *idx, bool uj) { struct vrf *vrf; @@ -76,9 +76,13 @@ static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[], else vrf = vrf_lookup_by_id(VRF_DEFAULT); - if (!vrf) - vty_out(vty, "Specified VRF: %s does not exist\n", - argv[*idx]->arg); + if (!vrf) { + if (uj) + vty_json_empty(vty); + else + vty_out(vty, "Specified VRF: %s does not exist\n", + argv[*idx]->arg); + } return vrf; } @@ -822,19 +826,172 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty, } } -static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) +static void igmp_source_json_helper(struct gm_source *src, + json_object *json_sources, char *source_str, + char *mmss, char *uptime) +{ + json_object *json_source = NULL; + + json_source = json_object_new_object(); + if (!json_source) + return; + + json_object_string_add(json_source, "source", source_str); + json_object_string_add(json_source, "timer", mmss); + json_object_boolean_add(json_source, "forwarded", + IGMP_SOURCE_TEST_FORWARDING(src->source_flags)); + json_object_string_add(json_source, "uptime", uptime); + json_object_array_add(json_sources, json_source); +} + +static void igmp_group_print(struct interface *ifp, struct vty *vty, bool uj, + json_object *json, struct gm_group *grp, + time_t now, bool detail) { - struct interface *ifp; - time_t now; - json_object *json = NULL; json_object *json_iface = NULL; json_object *json_group = NULL; json_object *json_groups = NULL; + char group_str[INET_ADDRSTRLEN]; + char hhmmss[PIM_TIME_STRLEN]; + char uptime[PIM_TIME_STRLEN]; + + pim_inet4_dump("<group?>", grp->group_addr, group_str, + sizeof(group_str)); + pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer); + pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation); + + if (uj) { + json_object_object_get_ex(json, ifp->name, &json_iface); + if (!json_iface) { + json_iface = json_object_new_object(); + if (!json_iface) + return; + json_object_pim_ifp_add(json_iface, ifp); + json_object_object_add(json, ifp->name, json_iface); + json_groups = json_object_new_array(); + if (!json_groups) + return; + json_object_object_add(json_iface, "groups", + json_groups); + } + + json_object_object_get_ex(json_iface, "groups", &json_groups); + if (json_groups) { + json_group = json_object_new_object(); + if (!json_group) + return; + + json_object_string_add(json_group, "group", group_str); + if (grp->igmp_version == IGMP_DEFAULT_VERSION) + json_object_string_add( + json_group, "mode", + grp->group_filtermode_isexcl + ? "EXCLUDE" + : "INCLUDE"); + + json_object_string_add(json_group, "timer", hhmmss); + json_object_int_add( + json_group, "sourcesCount", + grp->group_source_list + ? listcount(grp->group_source_list) + : 0); + json_object_int_add(json_group, "version", + grp->igmp_version); + json_object_string_add(json_group, "uptime", uptime); + json_object_array_add(json_groups, json_group); + + if (detail) { + struct listnode *srcnode; + struct gm_source *src; + json_object *json_sources = NULL; + + json_sources = json_object_new_array(); + if (!json_sources) + return; + + json_object_object_add(json_group, "sources", + json_sources); + + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + char source_str[INET_ADDRSTRLEN]; + char mmss[PIM_TIME_STRLEN]; + char src_uptime[PIM_TIME_STRLEN]; + + pim_inet4_dump( + "<source?>", src->source_addr, + source_str, sizeof(source_str)); + pim_time_timer_to_mmss( + mmss, sizeof(mmss), + src->t_source_timer); + pim_time_uptime( + src_uptime, sizeof(src_uptime), + now - src->source_creation); + + igmp_source_json_helper( + src, json_sources, source_str, + mmss, src_uptime); + } + } + } + } else { + if (detail) { + struct listnode *srcnode; + struct gm_source *src; + + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + srcnode, src)) { + char source_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<source?>", src->source_addr, + source_str, sizeof(source_str)); + + vty_out(vty, + "%-16s %-15s %4s %8s %-15s %d %8s\n", + ifp->name, group_str, + grp->igmp_version == 3 + ? (grp->group_filtermode_isexcl + ? "EXCL" + : "INCL") + : "----", + hhmmss, source_str, grp->igmp_version, + uptime); + } + return; + } + + vty_out(vty, "%-16s %-15s %4s %8s %4d %d %8s\n", ifp->name, + group_str, + grp->igmp_version == 3 + ? (grp->group_filtermode_isexcl ? "EXCL" + : "INCL") + : "----", + hhmmss, + grp->group_source_list + ? listcount(grp->group_source_list) + : 0, + grp->igmp_version, uptime); + } +} + +static void igmp_show_groups_interface_single(struct pim_instance *pim, + struct vty *vty, bool uj, + const char *ifname, + const char *grp_str, bool detail) +{ + struct interface *ifp; + time_t now; + json_object *json = NULL; + struct pim_interface *pim_ifp = NULL; + struct gm_group *grp; now = pim_time_monotonic_sec(); if (uj) { json = json_object_new_object(); + if (!json) + return; json_object_int_add(json, "totalGroups", pim->gm_group_count); json_object_int_add(json, "watermarkLimit", pim->gm_watermark_limit); @@ -843,8 +1000,87 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) vty_out(vty, "Watermark warn limit(%s): %u\n", pim->gm_watermark_limit ? "Set" : "Not Set", pim->gm_watermark_limit); - vty_out(vty, - "Interface Group Mode Timer Srcs V Uptime \n"); + + if (!detail) + vty_out(vty, + "Interface Group Mode Timer Srcs V Uptime\n"); + else + vty_out(vty, + "Interface Group Mode Timer Source V Uptime\n"); + } + + ifp = if_lookup_by_name(ifname, pim->vrf->vrf_id); + if (!ifp) { + if (uj) + vty_json(vty, json); + return; + } + + pim_ifp = ifp->info; + if (!pim_ifp) { + if (uj) + vty_json(vty, json); + return; + } + + if (grp_str) { + struct in_addr group_addr; + struct gm_sock *igmp; + + if (inet_pton(AF_INET, grp_str, &group_addr) == 1) { + igmp = pim_igmp_sock_lookup_ifaddr( + pim_ifp->gm_socket_list, + pim_ifp->primary_address); + if (igmp) { + grp = find_group_by_addr(igmp, group_addr); + if (grp) + igmp_group_print(ifp, vty, uj, json, + grp, now, detail); + } + } + } else { + struct listnode *grpnode; + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, grp)) + igmp_group_print(ifp, vty, uj, json, grp, now, detail); + } + + if (uj) { + if (detail) + vty_json_no_pretty(vty, json); + else + vty_json(vty, json); + } +} + +static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj, + const char *grp_str, bool detail) +{ + struct interface *ifp; + time_t now; + json_object *json = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + if (!json) + return; + json_object_int_add(json, "totalGroups", pim->gm_group_count); + json_object_int_add(json, "watermarkLimit", + pim->gm_watermark_limit); + } else { + vty_out(vty, "Total IGMP groups: %u\n", pim->gm_group_count); + vty_out(vty, "Watermark warn limit(%s): %u\n", + pim->gm_watermark_limit ? "Set" : "Not Set", + pim->gm_watermark_limit); + if (!detail) + vty_out(vty, + "Interface Group Mode Timer Srcs V Uptime\n"); + else + vty_out(vty, + "Interface Group Mode Timer Source V Uptime\n"); } /* scan interfaces */ @@ -856,78 +1092,38 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) if (!pim_ifp) continue; - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, - grp)) { - char group_str[INET_ADDRSTRLEN]; - char hhmmss[10]; - char uptime[10]; - - pim_inet4_dump("<group?>", grp->group_addr, group_str, - sizeof(group_str)); - pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), - grp->t_group_timer); - pim_time_uptime(uptime, sizeof(uptime), - now - grp->group_creation); - - if (uj) { - json_object_object_get_ex(json, ifp->name, - &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, - ifp); - json_object_object_add(json, ifp->name, - json_iface); - json_groups = json_object_new_array(); - json_object_object_add(json_iface, - "groups", - json_groups); + if (grp_str) { + struct in_addr group_addr; + struct gm_sock *igmp; + + if (inet_pton(AF_INET, grp_str, &group_addr) == 1) { + igmp = pim_igmp_sock_lookup_ifaddr( + pim_ifp->gm_socket_list, + pim_ifp->primary_address); + if (igmp) { + grp = find_group_by_addr(igmp, + group_addr); + if (grp) + igmp_group_print(ifp, vty, uj, + json, grp, now, + detail); } - - json_group = json_object_new_object(); - json_object_string_add(json_group, "group", - group_str); - - if (grp->igmp_version == 3) - json_object_string_add( - json_group, "mode", - grp->group_filtermode_isexcl - ? "EXCLUDE" - : "INCLUDE"); - - json_object_string_add(json_group, "timer", - hhmmss); - json_object_int_add( - json_group, "sourcesCount", - grp->group_source_list ? listcount( - grp->group_source_list) - : 0); - json_object_int_add(json_group, "version", - grp->igmp_version); - json_object_string_add(json_group, "uptime", - uptime); - json_object_array_add(json_groups, json_group); - } else { - vty_out(vty, "%-16s %-15s %4s %8s %4d %d %8s\n", - ifp->name, group_str, - grp->igmp_version == 3 - ? (grp->group_filtermode_isexcl - ? "EXCL" - : "INCL") - : "----", - hhmmss, - grp->group_source_list ? listcount( - grp->group_source_list) - : 0, - grp->igmp_version, uptime); } - } /* scan igmp groups */ - } /* scan interfaces */ + } else { + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, + grpnode, grp)) + igmp_group_print(ifp, vty, uj, json, grp, now, + detail); + } + } /* scan interfaces */ - if (uj) - vty_json(vty, json); + if (uj) { + if (detail) + vty_json_no_pretty(vty, json); + else + vty_json(vty, json); + } } static void igmp_show_group_retransmission(struct pim_instance *pim, @@ -981,24 +1177,175 @@ static void igmp_show_group_retransmission(struct pim_instance *pim, } /* scan interfaces */ } +static void igmp_sources_print(struct interface *ifp, char *group_str, + struct gm_source *src, time_t now, + json_object *json, struct vty *vty, bool uj) +{ + json_object *json_iface = NULL; + json_object *json_group = NULL; + json_object *json_sources = NULL; + char source_str[INET_ADDRSTRLEN]; + char mmss[PIM_TIME_STRLEN]; + char uptime[PIM_TIME_STRLEN]; + + pim_inet4_dump("<source?>", src->source_addr, source_str, + sizeof(source_str)); + pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer); + pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation); + + if (uj) { + json_object_object_get_ex(json, ifp->name, &json_iface); + if (!json_iface) { + json_iface = json_object_new_object(); + if (!json_iface) + return; + json_object_string_add(json_iface, "name", ifp->name); + json_object_object_add(json, ifp->name, json_iface); + } + + json_object_object_get_ex(json_iface, group_str, &json_group); + if (!json_group) { + json_group = json_object_new_object(); + if (!json_group) + return; + json_object_string_add(json_group, "group", group_str); + json_object_object_add(json_iface, group_str, + json_group); + json_sources = json_object_new_array(); + if (!json_sources) + return; + json_object_object_add(json_group, "sources", + json_sources); + } + + json_object_object_get_ex(json_group, "sources", &json_sources); + if (json_sources) + igmp_source_json_helper(src, json_sources, source_str, + mmss, uptime); + } else { + vty_out(vty, "%-16s %-15s %-15s %5s %3s %8s\n", ifp->name, + group_str, source_str, mmss, + IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" + : "N", + uptime); + } +} + +static void igmp_show_sources_interface_single(struct pim_instance *pim, + struct vty *vty, bool uj, + const char *ifname, + const char *grp_str) +{ + struct interface *ifp; + time_t now; + json_object *json = NULL; + struct pim_interface *pim_ifp; + struct gm_group *grp; + + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + if (!json) + return; + } else { + vty_out(vty, + "Interface Group Source Timer Fwd Uptime \n"); + } + + ifp = if_lookup_by_name(ifname, pim->vrf->vrf_id); + if (!ifp) { + if (uj) + vty_json(vty, json); + return; + } + + pim_ifp = ifp->info; + if (!pim_ifp) { + if (uj) + vty_json(vty, json); + return; + } + + if (grp_str) { + struct in_addr group_addr; + struct gm_sock *igmp; + struct listnode *srcnode; + struct gm_source *src; + char group_str[INET_ADDRSTRLEN]; + int res; + + res = inet_pton(AF_INET, grp_str, &group_addr); + if (res <= 0) { + if (uj) + vty_json(vty, json); + return; + } + + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, + pim_ifp->primary_address); + if (!igmp) { + if (uj) + vty_json(vty, json); + return; + } + + grp = find_group_by_addr(igmp, group_addr); + if (!grp) { + if (uj) + vty_json(vty, json); + return; + } + pim_inet4_dump("<group?>", grp->group_addr, group_str, + sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) + igmp_sources_print(ifp, group_str, src, now, json, vty, + uj); + } else { + struct listnode *grpnode; + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, + grp)) { + char group_str[INET_ADDRSTRLEN]; + struct listnode *srcnode; + struct gm_source *src; + + pim_inet4_dump("<group?>", grp->group_addr, group_str, + sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + srcnode, src)) + igmp_sources_print(ifp, group_str, src, now, + json, vty, uj); + + } /* scan igmp groups */ + } + + if (uj) + vty_json(vty, json); +} + static void igmp_show_sources(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; time_t now; json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_group = NULL; - json_object *json_source = NULL; - json_object *json_sources = NULL; now = pim_time_monotonic_sec(); - if (uj) + if (uj) { json = json_object_new_object(); - else + if (!json) + return; + } else { vty_out(vty, - "Interface Group Source Timer Fwd Uptime \n"); + "Interface Group Source Timer Fwd Uptime\n"); + } /* scan interfaces */ FOR_ALL_INTERFACES (pim->vrf, ifp) { @@ -1021,82 +1368,12 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty, /* scan group sources */ for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, - srcnode, src)) { - char source_str[INET_ADDRSTRLEN]; - char mmss[10]; - char uptime[10]; - - pim_inet4_dump("<source?>", src->source_addr, - source_str, sizeof(source_str)); - - pim_time_timer_to_mmss(mmss, sizeof(mmss), - src->t_source_timer); - - pim_time_uptime(uptime, sizeof(uptime), - now - src->source_creation); - - if (uj) { - json_object_object_get_ex( - json, ifp->name, &json_iface); - if (!json_iface) { - json_iface = - json_object_new_object(); - json_object_string_add( - json_iface, "name", - ifp->name); - json_object_object_add( - json, ifp->name, - json_iface); - } - json_object_object_get_ex(json_iface, - group_str, - &json_group); - - if (!json_group) { - json_group = - json_object_new_object(); - json_object_string_add( - json_group, "group", - group_str); - json_object_object_add( - json_iface, group_str, - json_group); - json_sources = - json_object_new_array(); - json_object_object_add( - json_group, "sources", - json_sources); - } - json_source = json_object_new_object(); - json_object_string_add(json_source, - "source", - source_str); - json_object_string_add(json_source, - "timer", mmss); - json_object_boolean_add( - json_source, "forwarded", - IGMP_SOURCE_TEST_FORWARDING( - src->source_flags)); - json_object_string_add( - json_source, "uptime", uptime); - json_object_array_add(json_sources, - json_source); - - } else { - vty_out(vty, - "%-16s %-15s %-15s %5s %3s %8s\n", - ifp->name, group_str, - source_str, mmss, - IGMP_SOURCE_TEST_FORWARDING( - src->source_flags) - ? "Y" - : "N", - uptime); - } - - } /* scan group sources */ + srcnode, src)) + igmp_sources_print(ifp, group_str, src, now, + json, vty, uj); } /* scan igmp groups */ } /* scan interfaces */ + if (uj) vty_json(vty, json); } @@ -1227,7 +1504,7 @@ DEFUN (clear_ip_interfaces, VRF_CMD_HELP_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1247,7 +1524,7 @@ DEFUN (clear_ip_igmp_interfaces, "Reset IGMP interfaces\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1355,7 +1632,7 @@ DEFUN (clear_ip_pim_bsr_db, "Reset pim bsr data\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1378,8 +1655,8 @@ DEFUN (show_ip_igmp_interface, JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -1444,8 +1721,8 @@ DEFUN (show_ip_igmp_join, JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -1487,39 +1764,47 @@ DEFUN (show_ip_igmp_join_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_igmp_groups, - show_ip_igmp_groups_cmd, - "show ip igmp [vrf NAME] groups [json]", - SHOW_STR - IP_STR - IGMP_STR - VRF_CMD_HELP_STR - IGMP_GROUP_STR - JSON_STR) +DEFPY(show_ip_igmp_groups, + show_ip_igmp_groups_cmd, + "show ip igmp [vrf NAME$vrf_name] groups [INTERFACE$ifname [GROUP$grp_str]] [detail$detail] [json$json]", + SHOW_STR + IP_STR + IGMP_STR + VRF_CMD_HELP_STR + IGMP_GROUP_STR + "Interface name\n" + "Group address\n" + "Detailed Information\n" + JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, !!json); if (!vrf) return CMD_WARNING; - igmp_show_groups(vrf->info, vty, uj); + if (ifname) + igmp_show_groups_interface_single(vrf->info, vty, !!json, + ifname, grp_str, !!detail); + else + igmp_show_groups(vrf->info, vty, !!json, NULL, !!detail); return CMD_SUCCESS; } -DEFUN (show_ip_igmp_groups_vrf_all, - show_ip_igmp_groups_vrf_all_cmd, - "show ip igmp vrf all groups [json]", - SHOW_STR - IP_STR - IGMP_STR - VRF_CMD_HELP_STR - IGMP_GROUP_STR - JSON_STR) +DEFPY(show_ip_igmp_groups_vrf_all, + show_ip_igmp_groups_vrf_all_cmd, + "show ip igmp vrf all groups [GROUP$grp_str] [detail$detail] [json$json]", + SHOW_STR + IP_STR + IGMP_STR + VRF_CMD_HELP_STR + IGMP_GROUP_STR + "Group address\n" + "Detailed Information\n" + JSON_STR) { - bool uj = use_json(argc, argv); + bool uj = !!json; struct vrf *vrf; bool first = true; @@ -1533,7 +1818,7 @@ DEFUN (show_ip_igmp_groups_vrf_all, first = false; } else vty_out(vty, "VRF: %s\n", vrf->name); - igmp_show_groups(vrf->info, vty, uj); + igmp_show_groups(vrf->info, vty, uj, grp_str, !!detail); } if (uj) vty_out(vty, "}\n"); @@ -1552,7 +1837,7 @@ DEFUN (show_ip_igmp_groups_retransmissions, "IGMP group retransmissions\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1562,23 +1847,29 @@ DEFUN (show_ip_igmp_groups_retransmissions, return CMD_SUCCESS; } -DEFUN (show_ip_igmp_sources, - show_ip_igmp_sources_cmd, - "show ip igmp [vrf NAME] sources [json]", - SHOW_STR - IP_STR - IGMP_STR - VRF_CMD_HELP_STR - IGMP_SOURCE_STR - JSON_STR) +DEFPY(show_ip_igmp_sources, + show_ip_igmp_sources_cmd, + "show ip igmp [vrf NAME$vrf_name] sources [INTERFACE$ifname [GROUP$grp_str]] [json$json]", + SHOW_STR + IP_STR + IGMP_STR + VRF_CMD_HELP_STR + IGMP_SOURCE_STR + "Interface name\n" + "Group address\n" + JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, !!json); if (!vrf) return CMD_WARNING; - igmp_show_sources(vrf->info, vty, use_json(argc, argv)); + if (ifname) + igmp_show_sources_interface_single(vrf->info, vty, !!json, + ifname, grp_str); + else + igmp_show_sources(vrf->info, vty, !!json); return CMD_SUCCESS; } @@ -1594,7 +1885,7 @@ DEFUN (show_ip_igmp_sources_retransmissions, "IGMP source retransmissions\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1617,8 +1908,8 @@ DEFUN (show_ip_igmp_statistics, JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -1746,7 +2037,7 @@ DEFUN (show_ip_pim_assert, "PIM interface assert\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1766,7 +2057,7 @@ DEFUN (show_ip_pim_assert_internal, "PIM interface internal assert state\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1786,7 +2077,7 @@ DEFUN (show_ip_pim_assert_metric, "PIM interface assert metric\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -1806,7 +2097,7 @@ DEFUN (show_ip_pim_assert_winner_metric, "PIM interface assert winner metric\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -2125,8 +2416,8 @@ DEFUN(show_ip_pim_mlag_up, show_ip_pim_mlag_up_cmd, const char *src_or_group = NULL; const char *group = NULL; int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf || !vrf->info) { vty_out(vty, "%s: VRF or Info missing\n", __func__); @@ -2598,7 +2889,7 @@ DEFUN (show_ip_rib, "Unicast address\n") { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); struct in_addr addr; const char *addr_str; struct pim_nexthop nexthop; @@ -2686,7 +2977,7 @@ DEFUN (show_ip_ssmpingd, VRF_CMD_HELP_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, false); if (!vrf) return CMD_WARNING; @@ -3141,8 +3432,8 @@ DEFUN (show_ip_pim_ssm_range, JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -3192,8 +3483,8 @@ DEFUN (show_ip_pim_group_type, JSON_STR) { int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); bool uj = use_json(argc, argv); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -5086,7 +5377,7 @@ DEFUN (show_ip_msdp_mesh_group, bool uj = use_json(argc, argv); int idx = 2; struct pim_msdp_mg *mg; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); struct pim_instance *pim; struct json_object *json = NULL; @@ -5322,7 +5613,7 @@ DEFUN (show_ip_msdp_peer_detail, { bool uj = use_json(argc, argv); int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -5562,7 +5853,7 @@ DEFUN (show_ip_msdp_sa_detail, { bool uj = use_json(argc, argv); int idx = 2; - struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -5677,7 +5968,7 @@ DEFUN (show_ip_msdp_sa_sg, struct vrf *vrf; int idx = 2; - vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -5947,7 +6238,7 @@ DEFUN (show_ip_pim_vxlan_sg, struct vrf *vrf; int idx = 2; - vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; @@ -6007,7 +6298,7 @@ DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work, struct vrf *vrf; int idx = 2; - vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj); if (!vrf) return CMD_WARNING; diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index fb6693491b..d39d77cd2f 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -60,4 +60,5 @@ void pim_cmd_init(void); +#define PIM_TIME_STRLEN 10 #endif /* PIM_CMD_H */ diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c index 9947c01af5..1a7b34adde 100644 --- a/ripd/rip_nb.c +++ b/ripd/rip_nb.c @@ -166,6 +166,27 @@ const struct frr_yang_module_info frr_ripd_info = { }, }, { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map", + .cbs = { + .create = ripd_instance_if_route_maps_if_route_map_create, + .destroy = ripd_instance_if_route_maps_if_route_map_destroy, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map/in-route-map", + .cbs = { + .modify = ripd_instance_if_route_maps_if_route_map_in_route_map_modify, + .destroy = ripd_instance_if_route_maps_if_route_map_in_route_map_destroy, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map/out-route-map", + .cbs = { + .modify = ripd_instance_if_route_maps_if_route_map_out_route_map_modify, + .destroy = ripd_instance_if_route_maps_if_route_map_out_route_map_destroy, + } + }, + { .xpath = "/frr-ripd:ripd/instance/static-route", .cbs = { .cli_show = cli_show_rip_route, @@ -338,6 +359,66 @@ const struct frr_yang_module_info frr_ripd_info = { }, }, { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop", + .cbs = { + .get_next = ripd_instance_state_routes_route_nexthops_nexthop_get_next, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/nh-type", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/protocol", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/rip-type", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/gateway", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/interface", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/from", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/tag", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/external-metric", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/expire-time", + .cbs = { + .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem, + } + }, + { .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric", .cbs = { .get_elem = ripd_instance_state_routes_route_metric_get_elem, diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h index 99114c9928..ebc60fefb4 100644 --- a/ripd/rip_nb.h +++ b/ripd/rip_nb.h @@ -52,6 +52,18 @@ int ripd_instance_redistribute_route_map_destroy( struct nb_cb_destroy_args *args); int ripd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args); int ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args); +int ripd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args); +int ripd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args); +int ripd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args); int ripd_instance_static_route_create(struct nb_cb_create_args *args); int ripd_instance_static_route_destroy(struct nb_cb_destroy_args *args); int ripd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args); @@ -89,6 +101,37 @@ struct yang_data *ripd_instance_state_routes_route_interface_get_elem( struct nb_cb_get_elem_args *args); struct yang_data *ripd_instance_state_routes_route_metric_get_elem( struct nb_cb_get_elem_args *args); +const void *ripd_instance_state_routes_route_nexthops_nexthop_get_next( + struct nb_cb_get_next_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data *ripd_instance_state_routes_route_metric_get_elem( + struct nb_cb_get_elem_args *args); int clear_rip_route_rpc(struct nb_cb_rpc_args *args); int lib_interface_rip_split_horizon_modify(struct nb_cb_modify_args *args); int lib_interface_rip_v2_broadcast_modify(struct nb_cb_modify_args *args); diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c index 2277ddc204..343bb9bb57 100644 --- a/ripd/rip_nb_config.c +++ b/ripd/rip_nb_config.c @@ -3,6 +3,7 @@ * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> * Copyright (C) 2018 NetDEF, Inc. * Renato Westphal + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -13,6 +14,7 @@ #include "prefix.h" #include "table.h" #include "command.h" +#include "if_rmap.h" #include "routemap.h" #include "northbound.h" #include "libfrr.h" @@ -681,6 +683,94 @@ int ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args) } /* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map + */ +int ripd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args) +{ + /* if_rmap is created when first routemap is added */ + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + struct rip *rip; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* + * YANG will prune edit deletes up to the most general deleted node so + * we need to handle deleting any existing state underneath and not + * count on those more specific callbacks being called individually. + */ + + rip = nb_running_get_entry(args->dnode, NULL, true); + if_rmap_yang_destroy_cb(rip->if_rmap_ctx, args->dnode); + + return NB_OK; +} + +static void if_route_map_modify(const struct lyd_node *dnode, + enum if_rmap_type type, bool delete) +{ + struct rip *rip = nb_running_get_entry(dnode, NULL, true); + + if_rmap_yang_modify_cb(rip->if_rmap_ctx, dnode, type, delete); +} + +/* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map/in-route-map + */ +int ripd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, false); + + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, true); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map/out-route-map + */ +int ripd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, false); + + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, true); + + return NB_OK; +} + +/* * XPath: /frr-ripd:ripd/instance/static-route */ int ripd_instance_static_route_create(struct nb_cb_create_args *args) diff --git a/ripd/rip_nb_state.c b/ripd/rip_nb_state.c index 0e2931b464..fa0d382a0e 100644 --- a/ripd/rip_nb_state.c +++ b/ripd/rip_nb_state.c @@ -207,10 +207,171 @@ struct yang_data *ripd_instance_state_routes_route_prefix_get_elem( const struct route_node *rn = args->list_entry; const struct rip_info *rinfo = listnode_head(rn->info); + assert(rinfo); return yang_data_new_ipv4p(args->xpath, &rinfo->rp->p); } /* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop + */ +const void *ripd_instance_state_routes_route_nexthops_nexthop_get_next( + struct nb_cb_get_next_args *args) +{ + const struct route_node *rn = args->parent_list_entry; + const struct listnode *node = args->list_entry; + + assert(rn); + if (node) + return listnextnode(node); + assert(rn->info); + return listhead((struct list *)rn->info); +} + +static inline const struct rip_info *get_rip_info(const void *info) +{ + return (const struct rip_info *)listgetdata( + (const struct listnode *)info); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/nh-type + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + assert(rinfo); + return yang_data_new_enum(args->xpath, rinfo->nh.type); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/protocol + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + assert(rinfo); + return yang_data_new_enum(args->xpath, rinfo->type); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/rip-type + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + assert(rinfo); + return yang_data_new_enum(args->xpath, rinfo->sub_type); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/gateway + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + if (rinfo->nh.type != NEXTHOP_TYPE_IPV4 && + rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX) + return NULL; + + return yang_data_new_ipv4(args->xpath, &rinfo->nh.gate.ipv4); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/interface + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + const struct rip *rip = rip_info_get_instance(rinfo); + + if (rinfo->nh.type != NEXTHOP_TYPE_IFINDEX && + rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX) + return NULL; + + return yang_data_new_string( + args->xpath, + ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id)); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/from + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + if (rinfo->type != ZEBRA_ROUTE_RIP || rinfo->sub_type != RIP_ROUTE_RTE) + return NULL; + + return yang_data_new_ipv4(args->xpath, &rinfo->from); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/tag + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + return yang_data_new_uint32(args->xpath, rinfo->tag); +} + +/* + * XPath: + * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/external-metric + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + + if ((rinfo->type == ZEBRA_ROUTE_RIP && + rinfo->sub_type == RIP_ROUTE_RTE) || + rinfo->metric == RIP_METRIC_INFINITY || rinfo->external_metric == 0) + return NULL; + return yang_data_new_uint32(args->xpath, rinfo->external_metric); +} + +/* + * XPath: + * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/expire-time + */ +struct yang_data * +ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct rip_info *rinfo = get_rip_info(args->list_entry); + struct event *event; + + if ((event = rinfo->t_timeout) == NULL) + event = rinfo->t_garbage_collect; + if (!event) + return NULL; + + return yang_data_new_uint32(args->xpath, + event_timer_remain_second(event)); +} + +/* * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop */ struct yang_data *ripd_instance_state_routes_route_next_hop_get_elem( diff --git a/ripd/ripd.c b/ripd/ripd.c index ae4d93b4f5..7dbe2bbccf 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1500,7 +1500,7 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to, ret = sendmsg(rip->sock, &msg, 0); if (IS_RIP_DEBUG_EVENT) - zlog_debug("SEND to %pI4%d", &sin.sin_addr, + zlog_debug("SEND to %pI4 port %d", &sin.sin_addr, ntohs(sin.sin_port)); if (ret < 0) @@ -2836,16 +2836,11 @@ uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo) if (access_list_apply(alist, &rinfo->rp->p) == FILTER_DENY) return 0; - - return rdistance->distance; - } else - return rdistance->distance; + } + return rdistance->distance; } - if (rip->distance) - return rip->distance; - - return 0; + return rip->distance; } static void rip_distance_show(struct vty *vty, struct rip *rip) diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c index 63144d866b..2f412e5197 100644 --- a/ripngd/ripng_nb.c +++ b/ripngd/ripng_nb.c @@ -115,6 +115,27 @@ const struct frr_yang_module_info frr_ripngd_info = { }, }, { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map", + .cbs = { + .create = ripngd_instance_if_route_maps_if_route_map_create, + .destroy = ripngd_instance_if_route_maps_if_route_map_destroy, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map/in-route-map", + .cbs = { + .modify = ripngd_instance_if_route_maps_if_route_map_in_route_map_modify, + .destroy = ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map", + .cbs = { + .modify = ripngd_instance_if_route_maps_if_route_map_out_route_map_modify, + .destroy = ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy, + } + }, + { .xpath = "/frr-ripngd:ripngd/instance/static-route", .cbs = { .cli_show = cli_show_ripng_route, diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h index 675cef7c92..1c0e63c241 100644 --- a/ripngd/ripng_nb.h +++ b/ripngd/ripng_nb.h @@ -39,6 +39,18 @@ int ripngd_instance_redistribute_route_map_destroy( int ripngd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args); int ripngd_instance_redistribute_metric_destroy( struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args); +int ripngd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args); +int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args); +int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args); int ripngd_instance_static_route_create(struct nb_cb_create_args *args); int ripngd_instance_static_route_destroy(struct nb_cb_destroy_args *args); int ripngd_instance_aggregate_address_create(struct nb_cb_create_args *args); diff --git a/ripngd/ripng_nb_config.c b/ripngd/ripng_nb_config.c index 006bf79ce8..30f707e061 100644 --- a/ripngd/ripng_nb_config.c +++ b/ripngd/ripng_nb_config.c @@ -3,6 +3,7 @@ * Copyright (C) 1998 Kunihiro Ishiguro * Copyright (C) 2018 NetDEF, Inc. * Renato Westphal + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -13,6 +14,7 @@ #include "prefix.h" #include "table.h" #include "command.h" +#include "if_rmap.h" #include "routemap.h" #include "agg_table.h" #include "northbound.h" @@ -503,6 +505,93 @@ int ripngd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args) } /* + * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args) +{ + /* if_rmap is created when first routemap is added */ + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + struct ripng *ripng; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* + * YANG will prune edit deletes up to the most general deleted node so + * we need to handle deleting any existing state underneath and not + * count on those more specific callbacks being called individually. + */ + + ripng = nb_running_get_entry(args->dnode, NULL, true); + if_rmap_yang_destroy_cb(ripng->if_rmap_ctx, args->dnode); + + return NB_OK; +} + +static void if_route_map_modify(const struct lyd_node *dnode, + enum if_rmap_type type, bool delete) +{ + struct ripng *ripng = nb_running_get_entry(dnode, NULL, true); + + if_rmap_yang_modify_cb(ripng->if_rmap_ctx, dnode, type, delete); +} +/* + * XPath: /frr-ripng:ripng/instance/if-route-maps/if-route-map/in-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, false); + + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, true); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, false); + + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, true); + + return NB_OK; +} + +/* * XPath: /frr-ripngd:ripngd/instance/static-route */ int ripngd_instance_static_route_create(struct nb_cb_create_args *args) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 77b562d6a6..0d7ba34530 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -1059,7 +1059,7 @@ DEFUN (show_sharp_ted, return CMD_WARNING_CONFIG_FAILED; } /* Get the Subnet from the Link State Database */ - subnet = ls_find_subnet(sg.ted, pref); + subnet = ls_find_subnet(sg.ted, &pref); if (!subnet) { vty_out(vty, "No subnet found for ID %pFX\n", &pref); @@ -1245,6 +1245,7 @@ DEFPY (show_sharp_cspf, } if (path->status != SUCCESS) { vty_out(vty, "Path computation failed: %d\n", path->status); + cpath_del(path); return CMD_SUCCESS; } @@ -1260,7 +1261,7 @@ DEFPY (show_sharp_cspf, &edge->attributes->standard.remote6); } vty_out(vty, "\n"); - + cpath_del(path); return CMD_SUCCESS; } diff --git a/staticd/static_main.c b/staticd/static_main.c index 09f22318ff..9809d9751a 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -161,6 +161,10 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = { #define STATIC_VTY_PORT 2616 +/* + * NOTE: .flags == FRR_NO_SPLIT_CONFIG to avoid reading split config, mgmtd will + * do this for us now + */ FRR_DAEMON_INFO(staticd, STATIC, .vty_port = STATIC_VTY_PORT, .proghelp = "Implementation of STATIC.", @@ -170,7 +174,8 @@ FRR_DAEMON_INFO(staticd, STATIC, .vty_port = STATIC_VTY_PORT, .privs = &static_privs, .yang_modules = staticd_yang_modules, .n_yang_modules = array_size(staticd_yang_modules), -); + + .flags = FRR_NO_SPLIT_CONFIG); int main(int argc, char **argv, char **envp) { @@ -210,9 +215,12 @@ int main(int argc, char **argv, char **envp) routing_control_plane_protocols_register_vrf_dependency(); - snprintf(backup_config_file, sizeof(backup_config_file), - "%s/zebra.conf", frr_sysconfdir); - staticd_di.backup_config_file = backup_config_file; + /* + * We set FRR_NO_SPLIT_CONFIG flag to avoid reading our config, but we + * still need to write one if vtysh tells us to. Setting the host + * config filename does this. + */ + host_config_set(config_default); frr_config_fork(); frr_run(master); diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index 54596dbdfb..ae7903e0cc 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -1042,9 +1042,9 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type) if (!parse_ret) { if (type == BGP_ATTR_MP_REACH_NLRI) - nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0); + nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, false); else if (type == BGP_ATTR_MP_UNREACH_NLRI) - nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1); + nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, true); } handle_result(peer, t, parse_ret, nlri_ret); } diff --git a/tests/lib/subdir.am b/tests/lib/subdir.am index 1bc092a49e..e950d0120d 100644 --- a/tests/lib/subdir.am +++ b/tests/lib/subdir.am @@ -15,7 +15,7 @@ tests_lib_test_frrscript_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_frrscript_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_frrscript_LDADD = $(ALL_TESTS_LDADD) tests_lib_test_frrscript_SOURCES = tests/lib/test_frrscript.c -EXTRA_DIST += tests/lib/test_frrscript.py +EXTRA_DIST += tests/lib/test_frrscript.py tests/lib/script1.lua ############################################################################## diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index f7c3a4c19d..92bb99c8f2 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -288,6 +288,17 @@ def test_converge_protocols(): thisDir = os.path.dirname(os.path.realpath(__file__)) + # We need loopback to have a link local so it always is the + # "selected" router for fe80::/64 when we static compare below. + print("Adding link-local to loopback for stable results") + cmd = ( + "mac=`cat /sys/class/net/lo/address`; echo lo: $mac;" + " [ -z \"$mac\" ] && continue; IFS=':'; set $mac; unset IFS;" + " ip address add dev lo scope link" + " fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64" + ) + net["r1"].cmd_raises(cmd) + print("\n\n** Waiting for protocols convergence") print("******************************************\n") diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py index 8b9631175a..65c0c3532a 100755 --- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py +++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py @@ -83,6 +83,7 @@ def build_topo(tgen): switch.add_link(tgen.gears["PE2"]) switch.add_link(tgen.gears["host2"]) + def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf): pe = tgen.gears[pe_name] @@ -100,7 +101,9 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf): # setup single vxlan device pe.run( - "ip link add dev vxlan0 type vxlan dstport 4789 local {0} nolearning external".format(tunnel_local_ip) + "ip link add dev vxlan0 type vxlan dstport 4789 local {0} nolearning external".format( + tunnel_local_ip + ) ) pe.run("ip link set dev vxlan0 master bridge") pe.run("bridge link set dev vxlan0 vlan_tunnel on") @@ -136,10 +139,12 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf): pe.run("bridge vlan add dev vxlan0 vid 300") pe.run("bridge vlan add dev vxlan0 vid 300 tunnel_info id 300") + def setup_p_router(tgen, p_name): p1 = tgen.gears[p_name] p1.run("sysctl -w net.ipv4.ip_forward=1") + def setup_module(mod): "Sets up the pytest environment" @@ -180,7 +185,7 @@ def teardown_module(mod): "Teardown the pytest environment" tgen = get_topogen() - #tgen.mininet_cli() + # tgen.mininet_cli() # This function tears down the whole topology. tgen.stop_topology() @@ -204,17 +209,21 @@ def check_vni_macs_present(tgen, router, vni, maclist): ) return None + def check_flood_entry_present(pe, vni, vtep): if not topotest.iproute2_is_fdb_get_capable(): return None - output = pe.run("bridge fdb get 00:00:00:00:00:00 dev vxlan0 vni {} self".format(vni)) + output = pe.run( + "bridge fdb get 00:00:00:00:00:00 dev vxlan0 vni {} self".format(vni) + ) if str(vtep) not in output: return output return None + def test_pe1_converge_evpn(): "Wait for protocol convergence" @@ -231,6 +240,15 @@ def test_pe1_converge_evpn(): _, result = topotest.run_and_expect(test_func, None, count=45, wait=1) assertmsg = '"{}" JSON output mismatches'.format(pe1.name) + # Let's ensure that the hosts have actually tried talking to + # each other. Otherwise under certain startup conditions + # they may not actually do any l2 arp'ing and as such + # the bridges won't know about the hosts on their networks + host1 = tgen.gears["host1"] + host1.run("ping -c 1 10.10.1.56") + host2 = tgen.gears["host2"] + host2.run("ping -c 1 10.10.1.55") + test_func = partial( check_vni_macs_present, tgen, @@ -249,11 +267,12 @@ def test_pe1_converge_evpn(): assertmsg = '"{}" Flood FDB Entry for VTEP {} not found'.format(pe1.name, vtep) assert result is None, assertmsg + def test_pe2_converge_evpn(): "Wait for protocol convergence" tgen = get_topogen() -#Don't run this test if we have any failure. + # Don't run this test if we have any failure. if tgen.routers_have_failure(): pytest.skip(tgen.errors) @@ -284,6 +303,7 @@ def test_pe2_converge_evpn(): assertmsg = '"{}" Flood FDB Entry for VTEP {} not found'.format(pe2.name, vtep) assert result is None, assertmsg + def mac_learn_test(host, local): "check the host MAC gets learned by the VNI" @@ -389,11 +409,11 @@ def ip_learn_test(tgen, host, local, remote, ip_addr): if "HWaddr" in line_items[0]: mac = line_items[1] break - #print(host_output) + # print(host_output) # check we have a local association between the MAC and IP local_output = local.vtysh_cmd("show evpn mac vni 101 mac {} json".format(mac)) - #print(local_output) + # print(local_output) local_output_json = json.loads(local_output) mac_type = local_output_json[mac]["type"] assertmsg = "Failed to learn local IP address on host {}".format(host.name) @@ -417,7 +437,7 @@ def ip_learn_test(tgen, host, local, remote, ip_addr): remote_output = remote.vtysh_cmd( "show evpn mac vni 101 mac {} json".format(mac) ) - #print(remote_output) + # print(remote_output) remote_output_json = json.loads(remote_output) type = remote_output_json[mac]["type"] if not remote_output_json[mac]["neighbors"] == "none": @@ -431,12 +451,12 @@ def ip_learn_test(tgen, host, local, remote, ip_addr): count += 1 sleep(1) - #print("tries: {}".format(count)) + # print("tries: {}".format(count)) assertmsg = "{} remote learned mac no address: {} ".format(host.name, mac) # some debug for this failure if not converged == True: log_output = remote.run("cat zebra.log") - #print(log_output) + # print(log_output) assert converged == True, assertmsg if remote_output_json[mac]["neighbors"]["active"]: @@ -463,8 +483,8 @@ def test_ip_pe1_learn(): host1 = tgen.gears["host1"] pe1 = tgen.gears["PE1"] pe2 = tgen.gears["PE2"] - #pe2.vtysh_cmd("debug zebra vxlan") - #pe2.vtysh_cmd("debug zebra kernel") + # pe2.vtysh_cmd("debug zebra vxlan") + # pe2.vtysh_cmd("debug zebra kernel") # lets populate that arp cache host1.run("ping -c1 10.10.1.1") ip_learn_test(tgen, host1, pe1, pe2, "10.10.1.55") @@ -482,13 +502,14 @@ def test_ip_pe2_learn(): host2 = tgen.gears["host2"] pe1 = tgen.gears["PE1"] pe2 = tgen.gears["PE2"] - #pe1.vtysh_cmd("debug zebra vxlan") - #pe1.vtysh_cmd("debug zebra kernel") + # pe1.vtysh_cmd("debug zebra vxlan") + # pe1.vtysh_cmd("debug zebra kernel") # lets populate that arp cache host2.run("ping -c1 10.10.1.3") ip_learn_test(tgen, host2, pe2, pe1, "10.10.1.56") # tgen.mininet_cli() + def show_dvni_route(pe, vni, prefix, vrf): output = pe.vtysh_cmd("show ip route vrf {} {}".format(vrf, prefix)) @@ -502,6 +523,7 @@ def show_dvni_route(pe, vni, prefix, vrf): return None + def test_dvni(): "test Downstream VNI works as expected importing into PE1" @@ -517,7 +539,7 @@ def test_dvni(): _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assertmsg = '"{}" DVNI route {} not found'.format(pe1.name, prefix) assert result is None, assertmsg - #tgen.mininet_cli() + # tgen.mininet_cli() def test_memory_leak(): diff --git a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py index 6561833d6e..2884043012 100755 --- a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py +++ b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py @@ -164,6 +164,15 @@ def test_pe1_converge_evpn(): _, result = topotest.run_and_expect(test_func, None, count=45, wait=1) assertmsg = '"{}" JSON output mismatches'.format(pe1.name) + # Let's ensure that the hosts have actually tried talking to + # each other. Otherwise under certain startup conditions + # they may not actually do any l2 arp'ing and as such + # the bridges won't know about the hosts on their networks + host1 = tgen.gears["host1"] + host1.run("ping -c 1 10.10.1.56") + host2 = tgen.gears["host2"] + host2.run("ping -c 1 10.10.1.55") + test_func = partial( check_vni_macs_present, tgen, @@ -171,6 +180,7 @@ def test_pe1_converge_evpn(): 101, (("host1", "host1-eth0"), ("host2", "host2-eth0")), ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) if result: logger.warning("%s", result) @@ -385,8 +395,8 @@ def test_ip_pe1_learn(): host1 = tgen.gears["host1"] pe1 = tgen.gears["PE1"] pe2 = tgen.gears["PE2"] - #pe2.vtysh_cmd("debug zebra vxlan") - #pe2.vtysh_cmd("debug zebra kernel") + # pe2.vtysh_cmd("debug zebra vxlan") + # pe2.vtysh_cmd("debug zebra kernel") # lets populate that arp cache host1.run("ping -c1 10.10.1.1") ip_learn_test(tgen, host1, pe1, pe2, "10.10.1.55") @@ -404,8 +414,8 @@ def test_ip_pe2_learn(): host2 = tgen.gears["host2"] pe1 = tgen.gears["PE1"] pe2 = tgen.gears["PE2"] - #pe1.vtysh_cmd("debug zebra vxlan") - #pe1.vtysh_cmd("debug zebra kernel") + # pe1.vtysh_cmd("debug zebra vxlan") + # pe1.vtysh_cmd("debug zebra kernel") # lets populate that arp cache host2.run("ping -c1 10.10.1.3") ip_learn_test(tgen, host2, pe2, pe1, "10.10.1.56") diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py index eaa6aa4c30..46993c7d9a 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py @@ -62,6 +62,25 @@ else: "pass", "Adding {} routes".format(num), ) + luCommand( + "ce1", + 'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33', + str(num), + "wait", + "See all sharp routes in rib on ce1", + wait, + wait_time=10, + ) + luCommand( + "ce2", + 'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33', + str(num), + "wait", + "See all sharp routes in rib on ce2", + wait, + wait_time=10, + ) + rtrs = ["ce1", "ce2", "ce3"] for rtr in rtrs: luCommand( diff --git a/tests/topotests/bgp_lu_explicitnull/r1/bgpd.conf b/tests/topotests/bgp_lu_explicitnull/r1/bgpd.conf new file mode 100644 index 0000000000..a31439c984 --- /dev/null +++ b/tests/topotests/bgp_lu_explicitnull/r1/bgpd.conf @@ -0,0 +1,15 @@ +router bgp 65500 + bgp router-id 192.0.2.1 + no bgp ebgp-requires-policy + bgp labeled-unicast explicit-null + neighbor 192.0.2.2 remote-as 65501 +! + address-family ipv4 unicast + no neighbor 192.0.2.2 activate + network 192.168.2.1/32 + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 192.0.2.2 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_explicitnull/r1/zebra.conf b/tests/topotests/bgp_lu_explicitnull/r1/zebra.conf new file mode 100644 index 0000000000..b84574891e --- /dev/null +++ b/tests/topotests/bgp_lu_explicitnull/r1/zebra.conf @@ -0,0 +1,6 @@ +interface r1-eth0 + ip address 192.0.2.1/24 +! +interface r1-eth1 + ip address 192.168.2.1/32 +!
\ No newline at end of file diff --git a/tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf b/tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf new file mode 100644 index 0000000000..41c2b9b6fa --- /dev/null +++ b/tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf @@ -0,0 +1,15 @@ +router bgp 65501 + bgp router-id 192.0.2.2 + no bgp ebgp-requires-policy + bgp labeled-unicast explicit-null + neighbor 192.0.2.1 remote-as 65500 +! + address-family ipv4 unicast + no neighbor 192.0.2.1 activate + network 192.168.2.2/32 + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 192.0.2.1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_explicitnull/r2/zebra.conf b/tests/topotests/bgp_lu_explicitnull/r2/zebra.conf new file mode 100644 index 0000000000..9a639610c1 --- /dev/null +++ b/tests/topotests/bgp_lu_explicitnull/r2/zebra.conf @@ -0,0 +1,6 @@ +interface r2-eth0 + ip address 192.0.2.2/24 +! +interface r2-eth1 + ip address 192.168.2.2/32 +! diff --git a/tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py b/tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py new file mode 100644 index 0000000000..d53ac68e84 --- /dev/null +++ b/tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC +# +# test_bgp_explicitnull.py +# +# Part of NetDEF Topology Tests +# +# Copyright 2023 by 6WIND S.A. +# + +""" +test_bgp_lu_explicitnull.py: Test BGP LU label allocation +""" + +import os +import sys +import json +import functools +import pytest + +# Save the Current Working Directory to find configuration files. +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 + + +pytestmark = [pytest.mark.bgpd] + + +# Basic scenario for BGP-LU. Nodes are directly connected. +# The 192.168.2.2/32 prefix is advertised from r2 to r1 +# The explicit-null label should be used +# The 192.168.2.1/32 prefix is advertised from r1 to r2 +# The explicit-null label should be used +# Traffic from 192.168.2.1 to 192.168.2.2 should use explicit-null label +# +# AS65500 BGP-LU AS65501 +# +-----+ +-----+ +# | |.1 .2| | +# | 1 +----------------+ 2 + 192.168.0.2/32 +# | | 192.0.2.0/24 | | +# +-----+ +-----+ + + +def build_topo(tgen): + "Build function" + + # Create routers + tgen.add_router("r1") + tgen.add_router("r2") + + # r1-r2 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + # r1 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"]) + + # r2 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + "Sets up the pytest environment" + # This function initiates the topology build with Topogen... + tgen = Topogen(build_topo, mod.__name__) + + # Skip if no mpls support + if not tgen.hasmpls: + logger.info("MPLS is not available, skipping test") + pytest.skip("MPLS is not available, skipping") + return + + # ... and here it calls Mininet initialization functions. + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + + # Enable mpls input for routers, so we can ping + sval = "net.mpls.conf.{}.input" + topotest.sysctl_assure(router_list["r2"], sval.format("r2-eth0"), 1) + topotest.sysctl_assure(router_list["r1"], sval.format("r1-eth0"), 1) + + # For all registred routers, load the zebra configuration file + for rname, router in router_list.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)) + ) + + # After loading the configurations, this function loads configured daemons. + tgen.start_router() + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def check_show_ip_label_prefix_found(router, ipversion, prefix, label): + output = json.loads( + router.vtysh_cmd("show {} route {} json".format(ipversion, prefix)) + ) + expected = {prefix: [{"prefix": prefix, "nexthops": [{"fib": True, "labels": [label]}]}]} + ret = topotest.json_cmp(output, expected) + if ret is None: + return "not good" + return None + +def test_converge_bgplu(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # tgen.mininet_cli(); + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + # Check r1 gets prefix 192.168.2.2/32 + test_func = functools.partial( + check_show_ip_label_prefix_found, + tgen.gears["r1"], + "ip", + "192.168.2.2/32", + "0", + ) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert ( + success + ), "r1, prefix 192.168.2.2/32 from r2 not present" + + # Check r2 gets prefix 192.168.2.1/32 + test_func = functools.partial( + check_show_ip_label_prefix_found, + tgen.gears["r2"], + "ip", + "192.168.2.1/32", + "0", + ) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert ( + success + ), "r2, prefix 192.168.2.1/32 from r1 not present" + +def test_traffic_connectivity(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + def _check_ping(name, dest_addr, src_addr): + tgen = get_topogen() + output = tgen.gears[name].run("ping {} -c 1 -w 1 -I {}".format(dest_addr, src_addr)) + logger.info(output) + if " 0% packet loss" not in output: + return True + + logger.info("r1, check ping 192.168.2.2 from 192.168.2.1 is OK") + tgen = get_topogen() + func = functools.partial(_check_ping, "r1", "192.168.2.2", "192.168.2.1") + # tgen.mininet_cli() + success, result = topotest.run_and_expect(func, None, count=10, wait=0.5) + assert result is None, "r1, ping to 192.168.2.2 from 192.168.2.1 fails" + +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_route_origin_parser/pe1/bgpd.conf b/tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf new file mode 100644 index 0000000000..1929dfa69b --- /dev/null +++ b/tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf @@ -0,0 +1,2 @@ +router bgp 65001 + neighbor 192.168.2.1 remote-as external diff --git a/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py b/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py new file mode 100644 index 0000000000..673efc2c73 --- /dev/null +++ b/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0-or-later +# +# April 03 2023, Trey Aspelund <taspelund@nvidia.com> +# +# Copyright (C) 2023 NVIDIA Corporation +# +# Test if the CLI parser for RT/SoO ecoms correctly +# constrain user input to valid 4-byte ASN values. +# + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.common_config import step + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + tgen.add_router("pe1") + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + pe1 = tgen.gears["pe1"] + pe1.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "pe1/bgpd.conf")) + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_route_origin_parser(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + pe1 = tgen.gears["pe1"] + + def _invalid_soo_accepted(): + pe1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + address-family ipv4 unicast + neighbor 192.168.2.1 soo 4294967296:65 + """ + ) + run_cfg = pe1.vtysh_cmd("show run") + return "soo" in run_cfg + + def _max_soo_accepted(): + pe1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + address-family ipv4 unicast + neighbor 192.168.2.1 soo 4294967295:65 + """ + ) + run_cfg = pe1.vtysh_cmd("show run") + return "soo 4294967295:65" in run_cfg + + def _invalid_rt_accepted(): + pe1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + address-family ipv4 unicast + rt vpn both 4294967296:65 + """ + ) + run_cfg = pe1.vtysh_cmd("show run") + return "rt vpn" in run_cfg + + def _max_rt_accepted(): + pe1.vtysh_cmd( + """ + configure terminal + router bgp 65001 + address-family ipv4 unicast + rt vpn both 4294967295:65 + """ + ) + run_cfg = pe1.vtysh_cmd("show run") + return "rt vpn both 4294967295:65" in run_cfg + + step( + "Configure invalid 4-byte value SoO (4294967296:65), this should not be accepted" + ) + test_func = functools.partial(_invalid_soo_accepted) + _, result = topotest.run_and_expect(test_func, False, count=30, wait=0.5) + assert result is False, "invalid 4-byte value of SoO accepted" + + step("Configure max 4-byte value SoO (4294967295:65), this should be accepted") + test_func = functools.partial(_max_soo_accepted) + _, result = topotest.run_and_expect(test_func, True, count=30, wait=0.5) + assert result is True, "max 4-byte value of SoO not accepted" + + step( + "Configure invalid 4-byte value RT (4294967296:65), this should not be accepted" + ) + test_func = functools.partial(_invalid_rt_accepted) + _, result = topotest.run_and_expect(test_func, False, count=30, wait=0.5) + assert result is False, "invalid 4-byte value of RT accepted" + + step("Configure max 4-byte value RT (4294967295:65), this should be accepted") + test_func = functools.partial(_max_rt_accepted) + _, result = topotest.run_and_expect(test_func, True, count=30, wait=0.5) + assert result is True, "max 4-byte value of RT not accepted" + + +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 8de6f9bf70..5c1b97262c 100644 --- a/tests/topotests/config_timing/test_config_timing.py +++ b/tests/topotests/config_timing/test_config_timing.py @@ -133,7 +133,7 @@ def test_static_timing(): delta = (datetime.datetime.now() - tstamp).total_seconds() tot_delta += delta - router.logger.info( + router.logger.debug( "\nvtysh command => {}\nvtysh output <= {}\nin {}s".format( load_command, output, delta ) @@ -152,7 +152,7 @@ def test_static_timing(): # Number of static routes router = tgen.gears["r1"] - output = router.run("vtysh -h | grep address-sanitizer") + output = router.net.cmd_legacy("vtysh -h | grep address-sanitizer", warn=False) if output == "": logger.info("No Address Sanitizer, generating 10000 routes") prefix_count = 10000 diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index e5a1e75837..d19d8db75c 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -492,7 +492,7 @@ def save_initial_config_on_routers(tgen): # Get all running configs in parallel procs = {} for rname in router_list: - logger.info("Fetching running config for router %s", rname) + logger.debug("Fetching running config for router %s", rname) procs[rname] = router_list[rname].popen( ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"], stdin=None, @@ -548,7 +548,7 @@ def reset_config_on_routers(tgen, routerName=None): # procs = {} for rname in router_list: - logger.info("Fetching running config for router %s", rname) + logger.debug("Fetching running config for router %s", rname) procs[rname] = router_list[rname].popen( ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"], stdin=None, @@ -570,7 +570,7 @@ def reset_config_on_routers(tgen, routerName=None): # procs = {} for rname in router_list: - logger.info( + logger.debug( "Generating delta for router %s to new configuration (gen %d)", rname, gen ) procs[rname] = tgen.net.popen( @@ -599,7 +599,7 @@ def reset_config_on_routers(tgen, routerName=None): # procs = {} for rname in router_list: - logger.info("Applying delta config on router %s", rname) + logger.debug("Applying delta config on router %s", rname) procs[rname] = router_list[rname].popen( ["/usr/bin/env", "vtysh", "-f", delta_fmt.format(rname, gen)], @@ -611,7 +611,7 @@ def reset_config_on_routers(tgen, routerName=None): output, _ = p.communicate() vtysh_command = "vtysh -f {}".format(delta_fmt.format(rname, gen)) if not p.returncode: - router_list[rname].logger.info( + router_list[rname].logger.debug( '\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format( vtysh_command, output ) @@ -640,7 +640,7 @@ def reset_config_on_routers(tgen, routerName=None): if show_router_config: procs = {} for rname in router_list: - logger.info("Fetching running config for router %s", rname) + logger.debug("Fetching running config for router %s", rname) procs[rname] = router_list[rname].popen( ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"], stdin=None, @@ -657,7 +657,7 @@ def reset_config_on_routers(tgen, routerName=None): output, ) else: - logger.info( + logger.debug( "Configuration on router %s after reset:\n%s", rname, output ) @@ -742,7 +742,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False): frr_cfg_bkup = frr_cfg_bkup_fmt.format(rname) with open(frr_cfg_file, "r+") as cfg: data = cfg.read() - logger.info( + logger.debug( "Applying following configuration on router %s (gen: %d):\n%s", rname, gen, @@ -775,7 +775,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False): frr_cfg_file = frr_cfg_file_fmt.format(rname) vtysh_command = "vtysh -f " + frr_cfg_file if not p.returncode: - router_list[rname].logger.info( + router_list[rname].logger.debug( '\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format( vtysh_command, output ) @@ -821,7 +821,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False): output, ) else: - logger.info("New configuration for router %s:\n%s", rname, output) + logger.debug("New configuration for router %s:\n%s", rname, output) logger.debug("Exiting API: load_config_to_routers") return not errors @@ -957,10 +957,10 @@ def generate_support_bundle(): bundle_procs[rname] = tgen.net[rname].popen(gen_sup_cmd, stdin=None) for rname, rnode in router_list.items(): - logger.info("Waiting on support bundle for %s", rname) + logger.debug("Waiting on support bundle for %s", rname) output, error = bundle_procs[rname].communicate() if output: - logger.info( + logger.debug( "Output from collecting support bundle for %s:\n%s", rname, output ) if error: @@ -1234,15 +1234,15 @@ def add_interfaces_to_vlan(tgen, input_dict): cmd = "ip link add link {} name {} type vlan id {}".format( interface, vlan_intf, vlan ) - logger.info("[DUT: %s]: Running command: %s", dut, cmd) + logger.debug("[DUT: %s]: Running command: %s", dut, cmd) result = rnode.run(cmd) - logger.info("result %s", result) + logger.debug("result %s", result) # Bringing interface up cmd = "ip link set {} up".format(vlan_intf) - logger.info("[DUT: %s]: Running command: %s", dut, cmd) + logger.debug("[DUT: %s]: Running command: %s", dut, cmd) result = rnode.run(cmd) - logger.info("result %s", result) + logger.debug("result %s", result) # Assigning IP address ifaddr = ipaddress.ip_interface( @@ -1254,9 +1254,9 @@ def add_interfaces_to_vlan(tgen, input_dict): cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format( ifaddr.version, vlan_intf, ifaddr ) - logger.info("[DUT: %s]: Running command: %s", dut, cmd) + logger.debug("[DUT: %s]: Running command: %s", dut, cmd) result = rnode.run(cmd) - logger.info("result %s", result) + logger.debug("result %s", result) def tcpdump_capture_start( @@ -1567,12 +1567,16 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False): vrf["name"], vrf["id"] ) - logger.info("[DUT: %s]: Running kernel cmd [%s]", c_router, cmd) + logger.debug( + "[DUT: %s]: Running kernel cmd [%s]", c_router, cmd + ) rnode.run(cmd) # Kernel cmd - Bring down VRF cmd = "ip link set dev {} down".format(name) - logger.info("[DUT: %s]: Running kernel cmd [%s]", c_router, cmd) + logger.debug( + "[DUT: %s]: Running kernel cmd [%s]", c_router, cmd + ) rnode.run(cmd) else: @@ -1581,14 +1585,14 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False): cmd = "ip link add {} type vrf table {}".format( name, table_id ) - logger.info( + logger.debug( "[DUT: %s]: Running kernel cmd " "[%s]", c_router, cmd ) rnode.run(cmd) # Kernel cmd - Bring up VRF cmd = "ip link set dev {} up".format(name) - logger.info( + logger.debug( "[DUT: %s]: Running kernel " "cmd [%s]", c_router, cmd ) rnode.run(cmd) @@ -1616,7 +1620,7 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False): interface_name, _vrf ) - logger.info( + logger.debug( "[DUT: %s]: Running" " kernel cmd [%s]", c_router, cmd, @@ -1683,7 +1687,7 @@ def create_interface_in_kernel( cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format( ifaddr.version, name, ifaddr ) - logger.info("[DUT: %s]: Running command: %s", dut, cmd) + logger.debug("[DUT: %s]: Running command: %s", dut, cmd) rnode.run(cmd) if vrf: @@ -1715,7 +1719,7 @@ def shutdown_bringup_interface_in_kernel(tgen, dut, intf_name, ifaceaction=False action = "down" cmd = "{} {} {}".format(cmd, intf_name, action) - logger.info("[DUT: %s]: Running command: %s", dut, cmd) + logger.debug("[DUT: %s]: Running command: %s", dut, cmd) rnode.run(cmd) @@ -1968,7 +1972,7 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75): ) if initial_wait > 0: - logger.info("Waiting for [%s]s as initial delay", initial_wait) + logger.debug("Waiting for [%s]s as initial delay", initial_wait) sleep(initial_wait) invert_logic = not _expected @@ -2027,13 +2031,13 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75): return saved_failure if saved_failure: - logger.info( + logger.debug( "RETRY DIAG: [failure] Sleeping %ds until next retry with %.1f retry time left - too see if timeout was too short", retry_sleep, seconds_left, ) else: - logger.info( + logger.debug( "Sleeping %ds until next retry with %.1f retry time left", retry_sleep, seconds_left, @@ -3357,7 +3361,19 @@ def socat_send_mld_join( # Run socat command to send IGMP join logger.info("[DUT: {}]: Running command: [{}]".format(server, socat_cmd)) - output = rnode.run("set +m; {} sleep 0.5".format(socat_cmd)) + output = rnode.run("set +m; {} echo $!".format(socat_cmd)) + + # Check if socat join process is running + if output: + pid = output.split()[0] + rnode.run("touch /var/run/frr/socat_join.pid") + rnode.run("echo %s >> /var/run/frr/socat_join.pid" % pid) + else: + errormsg = "Socat join is not sent for {}. Error {}".format( + mld_group, output + ) + logger.error(output) + return errormsg logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return True @@ -3415,7 +3431,7 @@ def socat_send_pim6_traffic( if multicast_hops: socat_cmd += "multicast-hops=255'" - socat_cmd += " &>{}/socat.logs &".format(tgen.logdir) + socat_cmd += " >{}/socat.logs &".format(tgen.logdir) # Run socat command to send pim6 traffic logger.info( @@ -3435,7 +3451,20 @@ def socat_send_pim6_traffic( ) rnode.run("chmod 755 {}".format(traffic_shell_script)) - output = rnode.run("{} &> /dev/null".format(traffic_shell_script)) + output = rnode.run("{} &>/dev/null & echo $!".format(traffic_shell_script)) + + # Check if socat traffic process is running + if output: + pid = output.split()[0] + rnode.run("touch /var/run/frr/socat_traffic.pid") + rnode.run("echo %s >> /var/run/frr/socat_traffic.pid" % pid) + + else: + errormsg = "Socat traffic is not sent for {}. Error {}".format( + mld_group, output + ) + logger.error(output) + return errormsg logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return True @@ -3465,18 +3494,30 @@ def kill_socat(tgen, dut=None, action=None): if dut is not None and router != dut: continue + traffic_shell_script = "{}/{}/traffic.sh".format(tgen.logdir, router) + pid_socat_join = rnode.run("cat /var/run/frr/socat_join.pid") + pid_socat_traffic = rnode.run("cat /var/run/frr/socat_traffic.pid") if action == "remove_mld_join": - cmd = "ps -ef | grep socat | grep UDP6-RECV | grep {}".format(router) + pids = pid_socat_join elif action == "remove_mld_traffic": - cmd = "ps -ef | grep socat | grep UDP6-SEND | grep {}".format(router) + pids = pid_socat_traffic else: - cmd = "ps -ef | grep socat".format(router) - - awk_cmd = "awk -F' ' '{print $2}' | xargs kill -9 &>/dev/null &" - cmd = "{} | {}".format(cmd, awk_cmd) + pids = "\n".join([pid_socat_join, pid_socat_traffic]) - logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd)) - rnode.run(cmd) + if os.path.exists(traffic_shell_script): + cmd = ( + "ps -ef | grep %s | awk -F' ' '{print $2}' | xargs kill -9" + % traffic_shell_script + ) + logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd)) + rnode.run(cmd) + + for pid in pids.split("\n"): + pid = pid.strip() + if pid.isdigit(): + cmd = "set +m; kill -9 %s &> /dev/null" % pid + logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd)) + rnode.run(cmd) logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) diff --git a/tests/topotests/lib/micronet_compat.py b/tests/topotests/lib/micronet_compat.py index 5a69c56d8d..edbd360084 100644 --- a/tests/topotests/lib/micronet_compat.py +++ b/tests/topotests/lib/micronet_compat.py @@ -161,12 +161,10 @@ class Mininet(Micronet): g_mnet_inst = None - def __init__(self, controller=None): + def __init__(self): """ Create a Micronet. """ - assert not controller - if Mininet.g_mnet_inst is not None: Mininet.g_mnet_inst.stop() Mininet.g_mnet_inst = self diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 41da660b7d..f5b3ad06d9 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -212,7 +212,10 @@ class Topogen(object): # Mininet(Micronet) to build the actual topology. assert not inspect.isclass(topodef) - self.net = Mininet(controller=None) + self.net = Mininet() + + # Adjust the parent namespace + topotest.fix_netns_limits(self.net) # New direct way: Either a dictionary defines the topology or a build function # is supplied, or a json filename all of which build the topology by calling @@ -504,7 +507,7 @@ class Topogen(object): def set_error(self, message, code=None): "Sets an error message and signal other tests to skip." - logger.info(message) + logger.info("setting error msg: %s", message) # If no code is defined use a sequential number if code is None: @@ -799,7 +802,7 @@ class TopoRouter(TopoGear): grep_cmd = "grep 'ip {}' {}".format(daemonstr, source) else: grep_cmd = "grep 'router {}' {}".format(daemonstr, source) - result = self.run(grep_cmd).strip() + result = self.run(grep_cmd, warn=False).strip() if result: self.load_config(daemon) else: @@ -822,7 +825,7 @@ class TopoRouter(TopoGear): all routers. """ daemonstr = self.RD.get(daemon) - self.logger.info('loading "{}" configuration: {}'.format(daemonstr, source)) + self.logger.debug('loading "{}" configuration: {}'.format(daemonstr, source)) self.net.loadConf(daemonstr, source, param) def check_router_running(self): @@ -945,16 +948,16 @@ class TopoRouter(TopoGear): vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command) - self.logger.info('vtysh command => "{}"'.format(command)) + self.logger.debug('vtysh command => "{}"'.format(command)) output = self.run(vtysh_command) dbgout = output.strip() if dbgout: if "\n" in dbgout: dbgout = dbgout.replace("\n", "\n\t") - self.logger.info("vtysh result:\n\t{}".format(dbgout)) + self.logger.debug("vtysh result:\n\t{}".format(dbgout)) else: - self.logger.info('vtysh result: "{}"'.format(dbgout)) + self.logger.debug('vtysh result: "{}"'.format(dbgout)) if isjson is False: return output @@ -994,7 +997,7 @@ class TopoRouter(TopoGear): dbgcmds = commands if is_string(commands) else "\n".join(commands) dbgcmds = "\t" + dbgcmds.replace("\n", "\n\t") - self.logger.info("vtysh command => FILE:\n{}".format(dbgcmds)) + self.logger.debug("vtysh command => FILE:\n{}".format(dbgcmds)) res = self.run(vtysh_command) os.unlink(fname) @@ -1003,9 +1006,9 @@ class TopoRouter(TopoGear): if dbgres: if "\n" in dbgres: dbgres = dbgres.replace("\n", "\n\t") - self.logger.info("vtysh result:\n\t{}".format(dbgres)) + self.logger.debug("vtysh result:\n\t{}".format(dbgres)) else: - self.logger.info('vtysh result: "{}"'.format(dbgres)) + self.logger.debug('vtysh result: "{}"'.format(dbgres)) return res def report_memory_leaks(self, testname): diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index d35b908e12..86a7f2000f 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -352,7 +352,7 @@ def run_and_expect(func, what, count=20, wait=3): count, wait ) - logger.info( + logger.debug( "'{}' polling started (interval {} secs, maximum {} tries)".format( func_name, wait, count ) @@ -366,7 +366,7 @@ def run_and_expect(func, what, count=20, wait=3): continue end_time = time.time() - logger.info( + logger.debug( "'{}' succeeded after {:.2f} seconds".format( func_name, end_time - start_time ) @@ -409,7 +409,7 @@ def run_and_expect_type(func, etype, count=20, wait=3, avalue=None): count, wait ) - logger.info( + logger.debug( "'{}' polling started (interval {} secs, maximum wait {} secs)".format( func_name, wait, int(wait * count) ) @@ -432,7 +432,7 @@ def run_and_expect_type(func, etype, count=20, wait=3, avalue=None): continue end_time = time.time() - logger.info( + logger.debug( "'{}' succeeded after {:.2f} seconds".format( func_name, end_time - start_time ) @@ -1130,7 +1130,7 @@ def _sysctl_atleast(commander, variable, min_value): valstr = " ".join([str(x) for x in min_value]) else: valstr = str(min_value) - logger.info("Increasing sysctl %s from %s to %s", variable, cur_val, valstr) + logger.debug("Increasing sysctl %s from %s to %s", variable, cur_val, valstr) commander.cmd_raises('sysctl -w {}="{}"\n'.format(variable, valstr)) @@ -1161,7 +1161,7 @@ def _sysctl_assure(commander, variable, value): valstr = " ".join([str(x) for x in value]) else: valstr = str(value) - logger.info("Changing sysctl %s from %s to %s", variable, cur_val, valstr) + logger.debug("Changing sysctl %s from %s to %s", variable, cur_val, valstr) commander.cmd_raises('sysctl -w {}="{}"\n'.format(variable, valstr)) @@ -1204,7 +1204,7 @@ def rlimit_atleast(rname, min_value, raises=False): soft, hard = cval if soft < min_value: nval = (min_value, hard if min_value < hard else min_value) - logger.info("Increasing rlimit %s from %s to %s", rname, cval, nval) + logger.debug("Increasing rlimit %s from %s to %s", rname, cval, nval) resource.setrlimit(rname, nval) except subprocess.CalledProcessError as error: logger.warning( @@ -1478,11 +1478,11 @@ class Router(Node): logger.info("%s: stopping %s", self.name, ", ".join([x[0] for x in running])) for name, pid in running: - logger.info("{}: sending SIGTERM to {}".format(self.name, name)) + logger.debug("{}: sending SIGTERM to {}".format(self.name, name)) try: os.kill(pid, signal.SIGTERM) except OSError as err: - logger.info( + logger.debug( "%s: could not kill %s (%s): %s", self.name, name, pid, str(err) ) @@ -1526,7 +1526,10 @@ class Router(Node): def removeIPs(self): for interface in self.intfNames(): try: - self.intf_ip_cmd(interface, "ip address flush " + interface) + self.intf_ip_cmd(interface, "ip -4 address flush " + interface) + self.intf_ip_cmd( + interface, "ip -6 address flush " + interface + " scope global" + ) except Exception as ex: logger.error("%s can't remove IPs %s", self, str(ex)) # pdb.set_trace() @@ -1560,7 +1563,7 @@ class Router(Node): router_relative = os.path.join(script_dir, self.name, tail) if self.path_exists(router_relative): source = router_relative - self.logger.info( + self.logger.debug( "using router relative configuration: {}".format(source) ) @@ -1617,7 +1620,7 @@ class Router(Node): # Auto-Started staticd has no config, so it will read from zebra config else: - logger.info("No daemon {} known".format(daemon)) + logger.warning("No daemon {} known".format(daemon)) # print "Daemons after:", self.daemons def runInWindow(self, cmd, title=None): @@ -1859,7 +1862,7 @@ class Router(Node): else "", ) else: - logger.info("%s: %s %s started", self, self.routertype, daemon) + logger.debug("%s: %s %s started", self, self.routertype, daemon) # Start mgmtd first if "mgmtd" in daemons_list: @@ -1888,15 +1891,6 @@ class Router(Node): while "snmpd" in daemons_list: daemons_list.remove("snmpd") - if daemons is None: - # Fix Link-Local Addresses on initial startup - # Somehow (on Mininet only), Zebra removes the IPv6 Link-Local addresses on start. Fix this - _, output, _ = self.cmd_status( - "for i in `ls /sys/class/net/` ; do mac=`cat /sys/class/net/$i/address`; echo $i: $mac; [ -z \"$mac\" ] && continue; IFS=':'; set $mac; unset IFS; ip address add dev $i scope link fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64; done", - stderr=subprocess.STDOUT, - ) - logger.debug("Set MACs:\n%s", output) - # Now start all the other daemons for daemon in daemons_list: if self.daemons[daemon] == 0: @@ -1934,7 +1928,7 @@ class Router(Node): daemonpidfile = d.rstrip() daemonpid = self.cmd("cat %s" % daemonpidfile).rstrip() if daemonpid.isdigit() and pid_exists(int(daemonpid)): - logger.info( + logger.debug( "{}: killing {}".format( self.name, os.path.basename(daemonpidfile.rsplit(".", 1)[0]), @@ -2198,7 +2192,7 @@ class Router(Node): log = self.getStdErr(daemon) if "memstats" in log: # Found memory leak - logger.info( + logger.warning( "\nRouter {} {} StdErr Log:\n{}".format(self.name, daemon, log) ) if not leakfound: diff --git a/tests/topotests/mgmt_tests/test_yang_mgmt.py b/tests/topotests/mgmt_tests/test_yang_mgmt.py index 06c18d7dfa..921b4e622c 100644 --- a/tests/topotests/mgmt_tests/test_yang_mgmt.py +++ b/tests/topotests/mgmt_tests/test_yang_mgmt.py @@ -217,7 +217,9 @@ def test_mgmt_commit_check(request): ] } } - result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol) + result = verify_rib( + tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False + ) assert ( result is not True ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name) @@ -319,7 +321,9 @@ def test_mgmt_commit_abort(request): ] } } - result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol) + result = verify_rib( + tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False + ) assert ( result is not True ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name) @@ -372,7 +376,7 @@ def test_mgmt_delete_config(request): assert ( result is True ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name) - + step("Mgmt delete config") raw_config = { "r1": { @@ -387,7 +391,9 @@ def test_mgmt_delete_config(request): assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) step("Verify that the route is deleted from RIB") - result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol) + result = verify_rib( + tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False + ) assert ( result is not True ), "Testcase {} : Failed" "Error: Routes is still present in RIB".format(tc_name) @@ -461,7 +467,9 @@ def test_mgmt_chaos_stop_start_frr(request): dut = "r1" protocol = "static" input_dict_4 = {"r1": {"static_routes": [{"network": "192.1.11.200/32"}]}} - result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol) + result = verify_rib( + tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False + ) assert ( result is not True ), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name) diff --git a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py index a76ff2dd9c..87b04b41be 100644 --- a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py +++ b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py @@ -62,6 +62,7 @@ from lib.common_config import ( socat_send_mld_join, socat_send_pim6_traffic, get_frr_ipv6_linklocal, + kill_socat, ) from lib.bgp import create_router_bgp from lib.pim import ( @@ -158,10 +159,6 @@ def setup_module(mod): # Creating configuration from JSON build_config_from_json(tgen, tgen.json_topo) - # XXX Replace this using "with McastTesterHelper()... " in each test if possible. - global app_helper - app_helper = McastTesterHelper(tgen) - logger.info("Running setup_module() done") @@ -172,7 +169,8 @@ def teardown_module(): tgen = get_topogen() - app_helper.cleanup() + # Clean up socat + kill_socat(tgen) # Stop toplogy and Remove tmp files tgen.stop_topology() diff --git a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py index ceef68fece..788a839918 100644 --- a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py +++ b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py @@ -53,6 +53,7 @@ from lib.common_config import ( socat_send_mld_join, socat_send_pim6_traffic, get_frr_ipv6_linklocal, + kill_socat, ) from lib.bgp import create_router_bgp from lib.pim import ( @@ -149,10 +150,6 @@ def setup_module(mod): # Creating configuration from JSON build_config_from_json(tgen, tgen.json_topo) - # XXX Replace this using "with McastTesterHelper()... " in each test if possible. - global app_helper - app_helper = McastTesterHelper(tgen) - logger.info("Running setup_module() done") @@ -163,7 +160,8 @@ def teardown_module(): tgen = get_topogen() - app_helper.cleanup() + # Clean up socat + kill_socat(tgen) # Stop toplogy and Remove tmp files tgen.stop_topology() diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py index 95b4004e14..977cd477c8 100755 --- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py +++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py @@ -172,6 +172,9 @@ def teardown_module(): logger.info("Running teardown_module to delete topology") tgen = get_topogen() + # Clean up socat + kill_socat(tgen) + # Stop toplogy and Remove tmp files tgen.stop_topology() diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py index 2fedb6e517..a61164baa2 100755 --- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py +++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py @@ -176,6 +176,9 @@ def teardown_module(): logger.info("Running teardown_module to delete topology") tgen = get_topogen() + # Clean up socat + kill_socat(tgen) + # Stop toplogy and Remove tmp files tgen.stop_topology() diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json new file mode 100644 index 0000000000..715aa1de72 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_group_all_detail.json @@ -0,0 +1 @@ +{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}} diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json new file mode 100644 index 0000000000..3bbcce1370 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_brief.json @@ -0,0 +1,51 @@ +{ + "totalGroups":5, + "watermarkLimit":0, + "l1-i1-eth1":{ + "name":"l1-i1-eth1", + "state":"up", + "address":"10.0.8.2", + "index":"*", + "flagMulticast":true, + "flagBroadcast":true, + "lanDelayEnabled":true, + "groups":[ + { + "group":"225.1.1.1", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + }, + { + "group":"225.1.1.2", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + }, + { + "group":"225.1.1.3", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + }, + { + "group":"225.1.1.4", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + }, + { + "group":"225.1.1.5", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + } + ] + } +} + diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json new file mode 100644 index 0000000000..876befa1b8 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_group_all_detail.json @@ -0,0 +1 @@ +{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}} diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json new file mode 100644 index 0000000000..a3fb496d25 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_brief.json @@ -0,0 +1,22 @@ +{ + "totalGroups":5, + "watermarkLimit":0, + "l1-i1-eth1":{ + "name":"l1-i1-eth1", + "state":"up", + "address":"10.0.8.2", + "index":"*", + "flagMulticast":true, + "flagBroadcast":true, + "lanDelayEnabled":true, + "groups":[ + { + "group":"225.1.1.5", + "timer":"*", + "sourcesCount":1, + "version":2, + "uptime":"*" + } + ] + } +} diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json new file mode 100644 index 0000000000..11ac5a01e7 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_single_if_single_group_detail.json @@ -0,0 +1 @@ +{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}} diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json new file mode 100644 index 0000000000..10ae1afc90 --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_group_all.json @@ -0,0 +1,61 @@ +{ + "l1-i1-eth1":{ + "name":"l1-i1-eth1", + "225.1.1.1":{ + "group":"225.1.1.1", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + }, + "225.1.1.2":{ + "group":"225.1.1.2", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + }, + "225.1.1.3":{ + "group":"225.1.1.3", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + }, + "225.1.1.4":{ + "group":"225.1.1.4", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + }, + "225.1.1.5":{ + "group":"225.1.1.5", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + } + } +} + diff --git a/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json new file mode 100644 index 0000000000..7a19975bee --- /dev/null +++ b/tests/topotests/multicast_pim_sm_topo3/igmp_source_single_if_single_group.json @@ -0,0 +1,16 @@ +{ + "l1-i1-eth1":{ + "name":"l1-i1-eth1", + "225.1.1.4":{ + "group":"225.1.1.4", + "sources":[ + { + "source":"*", + "timer":"*", + "forwarded":true, + "uptime":"*" + } + ] + } + } +} diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py index 2ffd3a3ac0..2c1241c0cc 100755 --- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py +++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py @@ -42,6 +42,8 @@ import time import datetime import pytest from time import sleep +import json +import functools pytestmark = pytest.mark.pimd @@ -54,8 +56,8 @@ sys.path.append(os.path.join(CWD, "../lib/")) # pylint: disable=C0413 # Import topogen and topotest helpers -from lib.topogen import Topogen, get_topogen - +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import ( start_topology, write_test_header, @@ -1510,6 +1512,108 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request): ) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + # IGMP JSON verification + step("Verify IGMP group and source JSON for single interface and group") + router = tgen.gears["l1"] + + reffile = os.path.join(CWD, "igmp_group_all_detail.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp vrf default groups detail json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP group detailed output on l1 for all interfaces and all groups is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_single_if_group_all_brief.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp vrf default groups l1-i1-eth1 json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP group output on l1 for all groups in interface l1-i1-eth1 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_single_if_group_all_detail.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp vrf default groups l1-i1-eth1 detail json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP group detailed output on l1 for all groups in interface l1-i1-eth1 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_single_if_single_group_brief.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp vrf default groups l1-i1-eth1 225.1.1.5 json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP group output on l1 for interface l1-i1-eth1 and group 225.1.1.5 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_single_if_single_group_detail.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp vrf default groups l1-i1-eth1 225.1.1.5 detail json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP group detailed output on l1 for interface l1-i1-eth1 and group 225.1.1.5 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_source_single_if_group_all.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp sources l1-i1-eth1 json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP source output on l1 for interface l1-i1-eth1 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + + reffile = os.path.join(CWD, "igmp_source_single_if_single_group.json") + expected = json.loads(open(reffile).read()) + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show ip igmp sources l1-i1-eth1 225.1.1.4 json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = "IGMP source output on l1 for interface l1-i1-eth1 and group 225.1.1.4 is not as expected. Expected: {}".format( + expected + ) + assert res is None, assertmsg + step( "Remove igmp 'no ip igmp' and 'no ip igmp version 2' from" " receiver interface of FRR1" diff --git a/tests/topotests/ospf_nssa_topo1/__init__.py b/tests/topotests/ospf_nssa_topo1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/__init__.py diff --git a/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf new file mode 100644 index 0000000000..6d23c84806 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf @@ -0,0 +1,22 @@ +password 1 +hostname rt1 +log file ospfd.log +! +! debug ospf sr +! debug ospf te +! debug ospf event +! debug ospf lsa +! debug ospf zebra +! +interface lo + ip ospf area 0 +! +interface eth-rt2 + ip ospf network point-to-point + ip ospf area 0 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +router ospf + router-id 1.1.1.1 +! diff --git a/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf new file mode 100644 index 0000000000..7ba3dc7591 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf @@ -0,0 +1,6 @@ +log file staticd.log +! +hostname rt1 +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref new file mode 100644 index 0000000000..ac34417bda --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref @@ -0,0 +1,115 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref new file mode 100644 index 0000000000..ac34417bda --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref @@ -0,0 +1,115 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref new file mode 100644 index 0000000000..ac34417bda --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref @@ -0,0 +1,115 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref new file mode 100644 index 0000000000..ac34417bda --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref @@ -0,0 +1,115 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref new file mode 100644 index 0000000000..6a05555eec --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref @@ -0,0 +1,103 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref new file mode 100644 index 0000000000..6a05555eec --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref @@ -0,0 +1,103 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref new file mode 100644 index 0000000000..2d3c8c485f --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref @@ -0,0 +1,91 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref new file mode 100644 index 0000000000..6a05555eec --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref @@ -0,0 +1,103 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref new file mode 100644 index 0000000000..f41ee3b698 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref @@ -0,0 +1,103 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref new file mode 100644 index 0000000000..2d3c8c485f --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref @@ -0,0 +1,91 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.0", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.1.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf new file mode 100644 index 0000000000..1df100564e --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf @@ -0,0 +1,18 @@ +log file zebra.log +! +hostname rt1 +! +! debug zebra kernel +! debug zebra packet +! debug zebra mpls +! +interface lo + ip address 1.1.1.1/32 +! +interface eth-rt2 + ip address 10.0.1.1/24 +! +ip forwarding +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf new file mode 100644 index 0000000000..12884d2ea9 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf @@ -0,0 +1,35 @@ +password 1 +hostname rt2 +log file ospfd.log +! +! debug ospf sr +! debug ospf te +! debug ospf event +! debug ospf lsa +! debug ospf zebra +! +interface lo + ip ospf area 0 +! +interface eth-rt1 + ip ospf network point-to-point + ip ospf area 0 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +interface eth-rt3 + ip ospf network point-to-point + ip ospf area 1 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +interface eth-rt4 + ip ospf network point-to-point + ip ospf area 1 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +router ospf + router-id 2.2.2.2 + area 1 nssa +! diff --git a/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf new file mode 100644 index 0000000000..b6d4233a4f --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf @@ -0,0 +1,6 @@ +log file staticd.log +! +hostname rt2 +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c09411741a --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref @@ -0,0 +1,127 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c09411741a --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref @@ -0,0 +1,127 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref new file mode 100644 index 0000000000..a67dfb4685 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref @@ -0,0 +1,139 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "0.0.0.0\/0":{ + "routeType":"N E2", + "cost":10, + "type2cost":1, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c09411741a --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref @@ -0,0 +1,127 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c7dd93c6e9 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref @@ -0,0 +1,129 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "172.16.1.0\/24":{ + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref new file mode 100644 index 0000000000..9c3cfff6c0 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref @@ -0,0 +1,117 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "172.16.1.0\/24":{ + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref new file mode 100644 index 0000000000..f6bbdfa594 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref @@ -0,0 +1,103 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c7dd93c6e9 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref @@ -0,0 +1,129 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "172.16.1.0\/24":{ + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c7dd93c6e9 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref @@ -0,0 +1,129 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "172.16.1.0\/24":{ + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref new file mode 100644 index 0000000000..c09411741a --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref @@ -0,0 +1,127 @@ +{ + "1.1.1.1\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":"10.0.1.1", + "via":"eth-rt1" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.0", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt1" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt3" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt4" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.3", + "via":"eth-rt3" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.4", + "via":"eth-rt4" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf new file mode 100644 index 0000000000..fa274ebade --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf @@ -0,0 +1,24 @@ +log file zebra.log +! +hostname rt2 +! +! debug zebra kernel +! debug zebra packet +! debug zebra mpls +! +interface lo + ip address 2.2.2.2/32 +! +interface eth-rt1 + ip address 10.0.1.2/24 +! +interface eth-rt3 + ip address 10.0.2.2/24 +! +interface eth-rt4 + ip address 10.0.3.2/24 +! +ip forwarding +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf new file mode 100644 index 0000000000..9691a7c512 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf @@ -0,0 +1,24 @@ +password 1 +hostname rt3 +log file ospfd.log +! +! debug ospf sr +! debug ospf te +! debug ospf event +! debug ospf lsa +! debug ospf zebra +! +interface lo + ip ospf area 1 +! +interface eth-rt2 + ip ospf network point-to-point + ip ospf area 1 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +router ospf + router-id 3.3.3.3 + area 1 nssa + redistribute connected +! diff --git a/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf new file mode 100644 index 0000000000..f0edd6c9ca --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf @@ -0,0 +1,8 @@ +log file staticd.log +! +hostname rt3 +! +ip route 0.0.0.0/0 Null0 +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref new file mode 100644 index 0000000000..a2d078ab13 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref @@ -0,0 +1,138 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref new file mode 100644 index 0000000000..4619067abd --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref @@ -0,0 +1,150 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref new file mode 100644 index 0000000000..a2d078ab13 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref @@ -0,0 +1,138 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref new file mode 100644 index 0000000000..a2d078ab13 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref @@ -0,0 +1,138 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref new file mode 100644 index 0000000000..10387215b2 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref @@ -0,0 +1,150 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref new file mode 100644 index 0000000000..4f8eaf1eaa --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref @@ -0,0 +1,138 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref new file mode 100644 index 0000000000..41e9f6718a --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref new file mode 100644 index 0000000000..10387215b2 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref @@ -0,0 +1,150 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref new file mode 100644 index 0000000000..4619067abd --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref @@ -0,0 +1,150 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref new file mode 100644 index 0000000000..4619067abd --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref @@ -0,0 +1,150 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.1\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.2\/32":{ + "routeType":"N E2", + "cost":20, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.2.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf new file mode 100644 index 0000000000..d943540f3b --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf @@ -0,0 +1,18 @@ +log file zebra.log +! +hostname rt3 +! +! debug zebra kernel +! debug zebra packet +! debug zebra mpls +! +interface lo + ip address 3.3.3.3/32 +! +interface eth-rt2 + ip address 10.0.2.3/24 +! +ip forwarding +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf new file mode 100644 index 0000000000..cba7cf71ed --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf @@ -0,0 +1,24 @@ +password 1 +hostname rt4 +log file ospfd.log +! +! debug ospf sr +! debug ospf te +! debug ospf event +! debug ospf lsa +! debug ospf zebra +! +interface lo + ip ospf area 1 +! +interface eth-rt2 + ip ospf network point-to-point + ip ospf area 1 + ip ospf hello-interval 3 + ip ospf dead-interval 12 +! +router ospf + router-id 4.4.4.4 + area 1 nssa + redistribute static +! diff --git a/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf new file mode 100644 index 0000000000..e00ee5dfea --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf @@ -0,0 +1,9 @@ +log file staticd.log +! +hostname rt4 +! +ip route 172.16.1.1/32 Null0 +ip route 172.16.1.2/32 Null0 +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref new file mode 100644 index 0000000000..e57f542f1c --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref @@ -0,0 +1,114 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref new file mode 100644 index 0000000000..82a0e1a9b4 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref new file mode 100644 index 0000000000..e57f542f1c --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref @@ -0,0 +1,114 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref new file mode 100644 index 0000000000..e57f542f1c --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref @@ -0,0 +1,114 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref new file mode 100644 index 0000000000..5f51b3b3b8 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref new file mode 100644 index 0000000000..5f51b3b3b8 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref new file mode 100644 index 0000000000..5f51b3b3b8 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref new file mode 100644 index 0000000000..5f51b3b3b8 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":20, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref new file mode 100644 index 0000000000..82a0e1a9b4 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref new file mode 100644 index 0000000000..82a0e1a9b4 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref @@ -0,0 +1,126 @@ +{ + "0.0.0.0\/0":{ + "routeType":"N IA", + "cost":11, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "1.1.1.1\/32":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "2.2.2.2\/32":{ + "routeType":"N IA", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3\/32":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "4.4.4.4\/32":{ + "routeType":"N", + "cost":0, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"lo" + } + ] + }, + "10.0.1.0\/24":{ + "routeType":"N IA", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.2.0\/24":{ + "routeType":"N", + "cost":20, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "10.0.3.0\/24":{ + "routeType":"N", + "cost":10, + "area":"0.0.0.1", + "nexthops":[ + { + "ip":" ", + "directlyAttachedTo":"eth-rt2" + } + ] + }, + "2.2.2.2":{ + "routeType":"R ", + "cost":10, + "area":"0.0.0.1", + "routerType":"abr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "3.3.3.3":{ + "routeType":"R ", + "cost":20, + "area":"0.0.0.1", + "routerType":"asbr", + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + }, + "172.16.1.0\/24":{ + "routeType":"N E2", + "cost":10, + "type2cost":1000, + "tag":0, + "nexthops":[ + { + "ip":"10.0.3.2", + "via":"eth-rt2" + } + ] + } +} diff --git a/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf new file mode 100644 index 0000000000..588febe70b --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf @@ -0,0 +1,18 @@ +log file zebra.log +! +hostname rt4 +! +! debug zebra kernel +! debug zebra packet +! debug zebra mpls +! +interface lo + ip address 4.4.4.4/32 +! +interface eth-rt2 + ip address 10.0.3.4/24 +! +ip forwarding +! +line vty +! diff --git a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py new file mode 100644 index 0000000000..432ddf0986 --- /dev/null +++ b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_ospf_nssa_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2023 by +# Network Device Education Foundation, Inc. ("NetDEF") +# + +""" +test_ospf_nssa_topo1.py: + + +---------+ + | RT1 | + | 1.1.1.1 | + +---------+ + |eth-rt2 + | + |10.0.1.0/24 + | + |eth-rt1 + +---------+ + | RT2 | + | 2.2.2.2 | + +---------+ + eth-rt3| |eth-rt4 + | | + 10.0.2.0/24 | | 10.0.3.0/24 + +---------+ +--------+ + | | + |eth-rt2 |eth-rt2 + +---------+ +---------+ + | RT3 | | RT4 | + | 3.3.3.3 | | 4.4.4.4 | + +---------+ +---------+ + +""" + +import os +import sys +import pytest +import json +from functools import partial + +# Save the Current Working Directory to find configuration files. +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 + +# Required to instantiate the topology builder class. + +pytestmark = [pytest.mark.ospfd] + + +def build_topo(tgen): + "Build function" + + # + # Define FRR Routers + # + for router in ["rt1", "rt2", "rt3", "rt4"]: + tgen.add_router(router) + + # + # Define connections + # + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["rt1"], nodeif="eth-rt2") + switch.add_link(tgen.gears["rt2"], nodeif="eth-rt1") + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["rt2"], nodeif="eth-rt3") + switch.add_link(tgen.gears["rt3"], nodeif="eth-rt2") + + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4") + switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2") + + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def print_cmd_result(rname, command): + print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False)) + + +def router_compare_json_output(rname, command, reference): + "Compare router JSON output" + + logger.info('Comparing router "%s" "%s" output', rname, command) + + tgen = get_topogen() + filename = "{}/{}/{}".format(CWD, rname, reference) + expected = json.loads(open(filename).read()) + + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) + _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5) + assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) + assert diff is None, assertmsg + + +# +# Step 1 +# +# Test initial network convergence +# +def test_rib_step1(): + logger.info("Test (step 1): test initial network convergence") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step1/show_ip_ospf_route.ref" + ) + + +# +# Step 2 +# +# Action(s): +# -rt3: configure an NSSA default route +# +# Expected changes: +# -rt2: add NSSA default route pointing to rt3 +# +def test_rib_step2(): + logger.info("Test (step 2): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Adding NSSA default on rt4") + tgen.net["rt3"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa default-information-originate"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step2/show_ip_ospf_route.ref" + ) + + +# +# Step 3 +# +# Action(s): +# -rt3: remove NSSA default route +# +# Expected changes: +# -rt2: remove NSSA default route +# +def test_rib_step3(): + logger.info("Test (step 3): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Removing NSSA default on rt4") + tgen.net["rt3"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step3/show_ip_ospf_route.ref" + ) + + +# +# Step 4 +# +# Action(s): +# -rt2: configure an NSSA range for 172.16.1.0/24 +# +# Expected changes: +# -rt1: the 172.16.1.1/32 and 172.16.1.2/32 routes should be removed +# -rt1: the 172.16.1.0/24 route should be added +# +def test_rib_step4(): + logger.info("Test (step 4): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Configuring NSSA range on rt2") + tgen.net["rt2"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step4/show_ip_ospf_route.ref" + ) + + +# +# Step 5 +# +# Action(s): +# -rt4: remove the 172.16.1.1/32 static route +# +# Expected changes: +# -None (the 172.16.1.0/24 range is still active because of 172.16.1.2/32) +# +def test_rib_step5(): + logger.info("Test (step 5): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Removing first static route in rt4") + tgen.net["rt4"].cmd('vtysh -c "conf t" -c "no ip route 172.16.1.1/32 Null0"') + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step5/show_ip_ospf_route.ref" + ) + + +# +# Step 6 +# +# Action(s): +# -rt4: remove the 172.16.1.2/32 static route +# +# Expected changes: +# -rt1: remove the 172.16.1.0/24 route since the NSSA range is no longer active +# +def test_rib_step6(): + logger.info("Test (step 6): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Removing second static route in rt4") + tgen.net["rt4"].cmd('vtysh -c "conf t" -c "no ip route 172.16.1.2/32 Null0"') + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step6/show_ip_ospf_route.ref" + ) + + +# +# Step 7 +# +# Action(s): +# -rt4: readd the 172.16.1.1/32 and 172.16.1.2/32 static routes +# +# Expected changes: +# -rt1: readd the 172.16.1.0/24 route since the NSSA range is active again +# +def test_rib_step7(): + logger.info("Test (step 7): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Readding static routes in rt4") + tgen.net["rt4"].cmd('vtysh -c "conf t" -c "ip route 172.16.1.1/32 Null0"') + tgen.net["rt4"].cmd('vtysh -c "conf t" -c "ip route 172.16.1.2/32 Null0"') + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step7/show_ip_ospf_route.ref" + ) + + +# +# Step 8 +# +# Action(s): +# -rt2: update the NSSA range with a static cost +# +# Expected changes: +# -rt1: update the metric of the 172.16.1.0/24 route from 20 to 1000 +# +def test_rib_step8(): + logger.info("Test (step 8): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Updating the NSSA range cost on rt2") + tgen.net["rt2"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24 cost 1000"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step8/show_ip_ospf_route.ref" + ) + + +# +# Step 9 +# +# Action(s): +# -rt2: update the NSSA range to not advertise itself +# +# Expected changes: +# -rt1: the 172.16.1.0/24 route should be removed +# +def test_rib_step9(): + logger.info("Test (step 9): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Updating the NSSA range to not advertise itself") + tgen.net["rt2"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24 not-advertise"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step9/show_ip_ospf_route.ref" + ) + + +# +# Step 10 +# +# Action(s): +# -rt2: remove the NSSA range +# +# Expected changes: +# -rt1: the 172.16.1.1/32 and 172.16.1.2/32 routes should be added +# +def test_rib_step10(): + logger.info("Test (step 10): verify OSPF routes") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Removing NSSA range on rt2") + tgen.net["rt2"].cmd( + 'vtysh -c "conf t" -c "router ospf" -c "no area 1 nssa range 172.16.1.0/24"' + ) + + for rname in ["rt1", "rt2", "rt3", "rt4"]: + router_compare_json_output( + rname, "show ip ospf route json", "step10/show_ip_ospf_route.ref" + ) + + +# Memory leak test template +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/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py index 5b1a53b895..d5583ac06a 100644 --- a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py +++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py @@ -111,9 +111,7 @@ def ospf_unconfigure_suppress_fa(router_name, area): tgen = get_topogen() router = tgen.gears[router_name] - router.vtysh_cmd( - "conf t\nrouter ospf\nno area {} nssa suppress-fa\nexit\n".format(area) - ) + router.vtysh_cmd("conf t\nrouter ospf\narea {} nssa\nexit\n".format(area)) def ospf_get_lsa_type5(router_name): diff --git a/tests/topotests/rip_allow_ecmp/__init__.py b/tests/topotests/rip_allow_ecmp/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/rip_allow_ecmp/__init__.py diff --git a/tests/topotests/rip_allow_ecmp/r1/frr.conf b/tests/topotests/rip_allow_ecmp/r1/frr.conf new file mode 100644 index 0000000000..d8eb9a31d3 --- /dev/null +++ b/tests/topotests/rip_allow_ecmp/r1/frr.conf @@ -0,0 +1,9 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +router rip + allow-ecmp + network 192.168.1.0/24 + timers basic 5 15 10 +exit diff --git a/tests/topotests/rip_allow_ecmp/r2/frr.conf b/tests/topotests/rip_allow_ecmp/r2/frr.conf new file mode 100644 index 0000000000..d7ea6f3102 --- /dev/null +++ b/tests/topotests/rip_allow_ecmp/r2/frr.conf @@ -0,0 +1,13 @@ +! +int lo + ip address 10.10.10.1/32 +! +int r2-eth0 + ip address 192.168.1.2/24 +! +router rip + network 192.168.1.0/24 + network 10.10.10.1/32 + timers basic 5 15 10 +exit + diff --git a/tests/topotests/rip_allow_ecmp/r3/frr.conf b/tests/topotests/rip_allow_ecmp/r3/frr.conf new file mode 100644 index 0000000000..2362c47b84 --- /dev/null +++ b/tests/topotests/rip_allow_ecmp/r3/frr.conf @@ -0,0 +1,13 @@ +! +int lo + ip address 10.10.10.1/32 +! +int r3-eth0 + ip address 192.168.1.3/24 +! +router rip + network 192.168.1.0/24 + network 10.10.10.1/32 + timers basic 5 15 10 +exit + diff --git a/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py new file mode 100644 index 0000000000..b0ba146984 --- /dev/null +++ b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2023 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +""" +Test if RIP `allow-ecmp` command works correctly. +""" + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.ripd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2", "r3")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_rip_allow_ecmp(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + + def _show_rip_routes(): + output = json.loads( + r1.vtysh_cmd("show yang operational-data /frr-ripd:ripd ripd") + ) + try: + output = output["frr-ripd:ripd"]["instance"][0]["state"]["routes"] + except KeyError: + return False + + expected = { + "route": [ + { + "prefix": "10.10.10.1/32", + "nexthops": { + "nexthop": [ + { + "nh-type": "ip4", + "protocol": "rip", + "rip-type": "normal", + "gateway": "192.168.1.2", + "from": "192.168.1.2", + "tag": 0, + }, + { + "nh-type": "ip4", + "protocol": "rip", + "rip-type": "normal", + "gateway": "192.168.1.3", + "from": "192.168.1.3", + "tag": 0, + }, + ] + }, + "metric": 2, + }, + ] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_show_rip_routes) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assert result is None, "Can't see 10.10.10.1/32 as multipath in `show ip rip`" + + def _show_routes(): + output = json.loads(r1.vtysh_cmd("show ip route json")) + expected = { + "10.10.10.1/32": [ + { + "nexthops": [ + { + "ip": "192.168.1.2", + "active": True, + }, + { + "ip": "192.168.1.3", + "active": True, + }, + ] + } + ] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_show_routes) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assert result is None, "Can't see 10.10.10.1/32 as multipath in `show ip route`" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py index 6137471ea6..e2863218b0 100644 --- a/tests/topotests/zebra_rib/test_zebra_rib.py +++ b/tests/topotests/zebra_rib/test_zebra_rib.py @@ -51,7 +51,8 @@ def config_macvlan(tgen, r_str, device, macvlan): def setup_module(mod): "Sets up the pytest environment" - topodef = {"s1": ("r1", "r1", "r1", "r1", "r1", "r1", "r1", "r1")} + # 8 links to 8 switches on r1 + topodef = {"s{}".format(x): ("r1",) for x in range(1, 9)} tgen = Topogen(topodef, mod.__name__) tgen.start_topology() diff --git a/yang/frr-if-rmap.yang b/yang/frr-if-rmap.yang new file mode 100644 index 0000000000..0fa2c5eddf --- /dev/null +++ b/yang/frr-if-rmap.yang @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause +module frr-if-rmap { + yang-version 1.1; + namespace "http://frrouting.org/yang/frr-if-rmap"; + prefix frr-if-map; + + import frr-interface { + prefix frr-interface; + } + + import frr-route-map { + prefix frr-route-map; + } + + organization + "FRRouting"; + contact + "FRR Users List: <mailto:frog@lists.frrouting.org> + FRR Development List: <mailto:dev@lists.frrouting.org>"; + description + "This module defines route map settings + + Copyright 2023 LabN Consulting L.L.C + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2023-04-09 { + description + "Initial revision"; + reference "FRRouting"; + } + + grouping if-route-maps-group { + description "Grouping for interface route maps"; + + container if-route-maps { + description "Collection of interface route-maps"; + + list if-route-map { + must "in-route-map or out-route-map"; + key "interface"; + description "Collection of route-maps for an interface"; + + leaf "interface" { + type frr-interface:interface-ref; + description "The interface the route maps are associated with"; + } + leaf "in-route-map" { + type frr-route-map:route-map-name; + description "Name of the ingress route map"; + } + leaf "out-route-map" { + type frr-route-map:route-map-name; + description "Name of the egress route map"; + } + } + } + } +} diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 66ec6a410d..de925b4823 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -1594,6 +1594,13 @@ module frr-isisd { "Log changes to the IS-IS adjacencies in this area."; } + leaf log-pdu-drops { + type boolean; + default "false"; + description + "Log any dropped PDUs in this area."; + } + container mpls-te { presence "Present if MPLS-TE is enabled."; description diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 746bf35d28..d2088e589e 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -10,9 +10,15 @@ module frr-ripd { import ietf-yang-types { prefix yang; } + import frr-if-rmap { + prefix frr-if-rmap; + } import frr-interface { prefix frr-interface; } + import frr-nexthop { + prefix frr-nexthop; + } import frr-vrf { prefix frr-vrf; } @@ -60,6 +66,7 @@ module frr-ripd { description "Changed interface references to use frr-interface:interface-ref typedef"; + reference "FRRouting"; } revision 2017-12-06 { description @@ -69,10 +76,35 @@ module frr-ripd { RFC 2453: RIP Version 2."; } + typedef rip-route-type { + type enumeration { + enum normal { + value 0; + description "Normal RIP route type."; + } + enum static { + value 1; + description "Static RIP route type."; + } + enum default { + value 2; + description "Default RIP route type."; + } + enum redistribute { + value 3; + description "Redistribute RIP route type."; + } + enum interface { + value 4; + description "Interface RIP route type."; + } + } + description + "Types of RIP routes."; + } + container ripd { - /* - * Routing instance configuration. - */ + description "rip routing instance data"; list instance { key "vrf"; description @@ -229,9 +261,9 @@ module frr-ripd { "Redistributes routes learned from other routing protocols."; leaf protocol { type frr-route-types:frr-route-types-v4; + must '. != "rip"'; description "Routing protocol."; - must '. != "rip"'; } leaf route-map { type frr-route-map:route-map-ref; @@ -253,6 +285,9 @@ module frr-ripd { is 0."; } } + + uses frr-if-rmap:if-route-maps-group; + leaf-list static-route { type inet:ipv4-prefix; description @@ -291,11 +326,8 @@ module frr-ripd { } } container version { + description "version of rip"; leaf receive { - must - '(. = "1" and ../send = "1") or ' + - '(. = "2" and ../send = "2") or ' + - '(. = "1-2" and ../send = "2")'; type enumeration { enum "1" { value 1; @@ -313,15 +345,15 @@ module frr-ripd { "Accept both RIPv1 and RIPv2 updates."; } } + must + '(. = "1" and ../send = "1") or ' + + '(. = "2" and ../send = "2") or ' + + '(. = "1-2" and ../send = "2")'; default "1-2"; description "Advertisement reception - Version control."; } leaf send { - must - '(../receive = "1" and . = "1") or ' + - '(../receive = "2" and . = "2") or ' + - '(../receive = "1-2" and . = "2")'; type enumeration { enum "1" { value 1; @@ -334,6 +366,10 @@ module frr-ripd { "Send RIPv2 updates only."; } } + must + '(../receive = "1" and . = "1") or ' + + '(../receive = "2" and . = "2") or ' + + '(../receive = "1-2" and . = "2")'; default "2"; description "Advertisement transmission - Version control."; @@ -399,23 +435,81 @@ module frr-ripd { separated by the slash (/) character. The range of values for the prefix-length is 0 to 32."; } + container nexthops { + description "container of nexthops"; + list nexthop { + description "A list of nexthop objects."; + leaf nh-type { + type frr-nexthop:nexthop-type; + mandatory true; + description + "The nexthop type."; + } + leaf protocol { + type frr-route-types:frr-route-types-v4; + description + "The protocol originating this route."; + } + leaf rip-type { + type rip-route-type; + description + "The RIP type of route."; + } + leaf gateway { + type inet:ipv4-address; + description + "The nexthop gateway address."; + } + leaf interface { + type frr-interface:interface-ref; + description + "The nexthop egress interface."; + } + leaf from { + type inet:ipv4-address; + description + "The nexthop gateway address."; + } + leaf tag { + type uint32; + default "0"; + description + "Route tag"; + } + leaf external-metric { + type uint32; + description + "External metric if learned from external protocol."; + } + leaf expire-time { + type uint32; + description + "Seconds before route expires."; + } + } + } + leaf metric { + type uint8 { + range "0..16"; + } + description + "Route metric."; + } + /* + * Replaced by container `nexthops` above. + */ leaf next-hop { type inet:ipv4-address; + status deprecated; description "Next hop IPv4 address."; } leaf interface { type frr-interface:interface-ref; + status deprecated; description "The interface that the route uses."; } - leaf metric { - type uint8 { - range "0..16"; - } - description - "Route metric."; - } } } } @@ -426,6 +520,7 @@ module frr-ripd { * Per-interface configuration data */ augment "/frr-interface:lib/frr-interface:interface" { + description "rip interface data"; container rip { description "RIP interface parameters."; diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index d7de4c398a..7b2b135fb5 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -10,6 +10,9 @@ module frr-ripngd { import ietf-yang-types { prefix yang; } + import frr-if-rmap { + prefix frr-if-rmap; + } import frr-interface { prefix frr-interface; } @@ -196,6 +199,9 @@ module frr-ripngd { is 0."; } } + + uses frr-if-rmap:if-route-maps-group; + leaf-list static-route { type inet:ipv6-prefix; description diff --git a/yang/subdir.am b/yang/subdir.am index 82a6a01474..eb17c38dbc 100644 --- a/yang/subdir.am +++ b/yang/subdir.am @@ -24,6 +24,7 @@ dist_yangmodels_DATA += yang/frr-filter.yang dist_yangmodels_DATA += yang/frr-module-translator.yang dist_yangmodels_DATA += yang/frr-nexthop.yang dist_yangmodels_DATA += yang/frr-test-module.yang +dist_yangmodels_DATA += yang/frr-if-rmap.yang dist_yangmodels_DATA += yang/frr-interface.yang dist_yangmodels_DATA += yang/frr-route-map.yang dist_yangmodels_DATA += yang/frr-zebra-route-map.yang diff --git a/zebra/interface.c b/zebra/interface.c index 03376afc09..496a85e676 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -137,6 +137,8 @@ static int if_zebra_new_hook(struct interface *ifp) zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC; zebra_if->shutdown = IF_ZEBRA_DATA_OFF; + zebra_if->link_nsid = NS_UNKNOWN; + zebra_if_nhg_dependents_init(zebra_if); zebra_ptm_if_init(zebra_if); @@ -305,6 +307,14 @@ struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns, return NULL; } +struct interface *if_lookup_by_index_per_nsid(ns_id_t ns_id, uint32_t ifindex) +{ + struct zebra_ns *zns; + + zns = zebra_ns_lookup(ns_id); + return zns ? if_lookup_by_index_per_ns(zns, ifindex) : NULL; +} + const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex) { struct interface *ifp; @@ -991,7 +1001,6 @@ void if_up(struct interface *ifp, bool install_connected) { struct zebra_if *zif; struct interface *link_if; - struct zebra_vrf *zvrf = ifp->vrf->info; zif = ifp->info; zif->up_count++; @@ -1024,8 +1033,7 @@ void if_up(struct interface *ifp, bool install_connected) link_if = ifp; zebra_vxlan_svi_up(ifp, link_if); } else if (IS_ZEBRA_IF_VLAN(ifp)) { - link_if = if_lookup_by_index_per_ns(zvrf->zns, - zif->link_ifindex); + link_if = zif->link; if (link_if) zebra_vxlan_svi_up(ifp, link_if); } else if (IS_ZEBRA_IF_MACVLAN(ifp)) { @@ -1049,7 +1057,6 @@ void if_down(struct interface *ifp) { struct zebra_if *zif; struct interface *link_if; - struct zebra_vrf *zvrf = ifp->vrf->info; zif = ifp->info; zif->down_count++; @@ -1068,8 +1075,7 @@ void if_down(struct interface *ifp) link_if = ifp; zebra_vxlan_svi_down(ifp, link_if); } else if (IS_ZEBRA_IF_VLAN(ifp)) { - link_if = if_lookup_by_index_per_ns(zvrf->zns, - zif->link_ifindex); + link_if = zif->link; if (link_if) zebra_vxlan_svi_down(ifp, link_if); } else if (IS_ZEBRA_IF_MACVLAN(ifp)) { @@ -1109,6 +1115,7 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, if (IS_ZEBRA_IF_VETH(ifp)) return; zif = (struct zebra_if *)ifp->info; + zif->link_nsid = ns_id; zif->link_ifindex = link_ifindex; zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), link_ifindex); @@ -1145,8 +1152,8 @@ void zebra_if_update_all_links(struct zebra_ns *zns) /* update SVI linkages */ if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) { - zif->link = if_lookup_by_index_per_ns( - zns, zif->link_ifindex); + zif->link = if_lookup_by_index_per_nsid( + zif->link_nsid, zif->link_ifindex); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("interface %s/%d's lower fixup to %s/%d", ifp->name, ifp->ifindex, diff --git a/zebra/interface.h b/zebra/interface.h index 4c6ebaa11d..e5545d6ba0 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -195,6 +195,7 @@ struct zebra_if { struct list *mac_list; /* Link fields - for sub-interfaces. */ + ns_id_t link_nsid; ifindex_t link_ifindex; struct interface *link; @@ -259,6 +260,8 @@ extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t); extern struct interface *if_lookup_by_name_per_ns(struct zebra_ns *, const char *); extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *); +extern struct interface *if_lookup_by_index_per_nsid(ns_id_t nsid, + uint32_t ifindex); extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int); extern void if_unlink_per_ns(struct interface *); diff --git a/zebra/rib.h b/zebra/rib.h index 26425a331f..a56bb05d68 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -180,7 +180,7 @@ struct route_entry { * sub-queue 9: any other origin (if any) typically those that * don't generate routes */ -#define MQ_SIZE 10 +#define MQ_SIZE 11 struct meta_queue { struct list *subq[MQ_SIZE]; uint32_t size; /* sum of lengths of all subqueues */ @@ -602,6 +602,12 @@ static inline struct nexthop_group *rib_get_fib_backup_nhg( return &(re->fib_backup_ng); } +extern void zebra_gr_process_client(afi_t afi, vrf_id_t vrf_id, uint8_t proto, + uint8_t instance); + +extern int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto, + uint8_t instance); + extern void zebra_vty_init(void); extern pid_t pid; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index fb1ebc6827..e821572c5d 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3745,6 +3745,11 @@ dplane_route_update_internal(struct route_node *rn, NEXTHOP_FLAG_FIB); } + if ((op == DPLANE_OP_ROUTE_UPDATE) && old_re && re && + (old_re != re) && + !CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) + SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + dplane_ctx_free(&ctx); return ZEBRA_DPLANE_REQUEST_SUCCESS; } @@ -6853,10 +6858,6 @@ void zebra_dplane_shutdown(void) zdplane_info.dg_run = false; - if (zdplane_info.dg_t_update) - event_cancel_async(zdplane_info.dg_t_update->master, - &zdplane_info.dg_t_update, NULL); - frr_pthread_stop(zdplane_info.dg_pthread, NULL); /* Destroy pthread */ diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c index 96d598f7c4..cf2056b7ac 100644 --- a/zebra/zebra_gr.c +++ b/zebra/zebra_gr.c @@ -42,8 +42,8 @@ static struct zserv *zebra_gr_find_stale_client(struct zserv *client); static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread); static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info); static void zebra_gr_process_client_stale_routes(struct zserv *client, - vrf_id_t vrf_id); - + struct client_gr_info *info); +static void zebra_gr_delete_stale_route_table_afi(struct event *event); /* * Debug macros. */ @@ -53,7 +53,6 @@ static void zebra_gr_process_client_stale_routes(struct zserv *client, zlog_debug(msg, ##__VA_ARGS__); \ } while (0) - /* * Client connection functions */ @@ -82,11 +81,12 @@ void zebra_gr_stale_client_cleanup(struct list *client_list) if (info->t_stale_removal != NULL) { EVENT_OFF(info->t_stale_removal); info->t_stale_removal = NULL; + info->do_delete = true; /* Process the stale routes */ event_execute( zrouter.master, zebra_gr_route_stale_delete_timer_expiry, - info, 1); + info, 0); } } } @@ -101,6 +101,8 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client) info = XCALLOC(MTYPE_ZEBRA_GR, sizeof(struct client_gr_info)); + info->stale_client_ptr = client; + TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info); return info; } @@ -108,8 +110,8 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client) /* * A helper function to delete and destroy client info. */ -static void zebra_gr_client_info_delte(struct zserv *client, - struct client_gr_info *info) +static void zebra_gr_client_info_delete(struct zserv *client, + struct client_gr_info *info) { struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); @@ -117,8 +119,6 @@ static void zebra_gr_client_info_delte(struct zserv *client, EVENT_OFF(info->t_stale_removal); - XFREE(MTYPE_ZEBRA_GR, info->current_prefix); - LOG_GR("%s: Instance info is being deleted for client %s vrf %s(%u)", __func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf), info->vrf_id); @@ -164,7 +164,6 @@ int32_t zebra_gr_client_disconnect(struct zserv *client) zebra_gr_route_stale_delete_timer_expiry, info, info->stale_removal_time, &info->t_stale_removal); - info->current_afi = AFI_IP; info->stale_client_ptr = client; info->stale_client = true; LOG_GR("%s: Client %s vrf %s(%u) Stale timer update to %d", @@ -287,31 +286,65 @@ void zebra_gr_client_reconnect(struct zserv *client) zserv_client_delete(old_client); } +struct zebra_gr_afi_clean { + struct client_gr_info *info; + afi_t afi; + uint8_t proto; + uint8_t instance; + + struct event *t_gac; +}; + /* * Functions to deal with capabilities */ /* - * Update the graceful restart information - * for the client instance. - * This function handles all the capabilities that are received. + * Function to decode and call appropriate functions + * to handle client capabilities. */ -static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api) +void zread_client_capabilities(ZAPI_HANDLER_ARGS) { + struct zapi_cap api; struct client_gr_info *info = NULL; + struct stream *s; + struct vrf *vrf; + + s = msg; + + if (zapi_capabilities_decode(s, &api)) { + LOG_GR("%s: Error in reading capabilities for client %s", + __func__, zebra_route_string(client->proto)); + return; + } + + vrf = vrf_lookup_by_id(api.vrf_id); + + /* + * If this ever matters uncomment and add safi to the + * arrays as needed to track + */ + if (api.safi != SAFI_UNICAST) + return; + + /* GR only for dynamic clients */ + if (client->proto <= ZEBRA_ROUTE_CONNECT) { + LOG_GR("%s: GR capabilities for client %s not supported", + __func__, zebra_route_string(client->proto)); + return; + } /* Find the bgp information for the specified vrf id */ TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { - if (info->vrf_id == api->vrf_id) + if (info->vrf_id == api.vrf_id) break; } - /* * If the command is delete, then cancel the stale timer and * delete the bgp info */ - switch (api->cap) { + switch (api.cap) { case ZEBRA_CLIENT_GR_DISABLE: if (!info) return; @@ -323,7 +356,7 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api) if ((info->gr_enable) && (client->gr_instance_count > 0)) client->gr_instance_count--; - zebra_gr_client_info_delte(client, info); + zebra_gr_client_info_delete(client, info); break; case ZEBRA_CLIENT_GR_CAPABILITIES: /* Allocate bgp info */ @@ -332,18 +365,16 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api) /* Update other parameters */ if (!info->gr_enable) { - struct vrf *vrf = vrf_lookup_by_id(api->vrf_id); - client->gr_instance_count++; LOG_GR("%s: Cient %s vrf %s(%u) GR enabled count %d", __func__, zebra_route_string(client->proto), - VRF_LOGNAME(vrf), api->vrf_id, + VRF_LOGNAME(vrf), api.vrf_id, client->gr_instance_count); - info->capabilities = api->cap; - info->stale_removal_time = api->stale_removal_time; - info->vrf_id = api->vrf_id; + info->capabilities = api.cap; + info->stale_removal_time = api.stale_removal_time; + info->vrf_id = api.vrf_id; info->gr_enable = true; } break; @@ -353,107 +384,54 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api) /* Update the stale removal timer */ if (info && info->t_stale_removal == NULL) { - struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); LOG_GR("%s: vrf %s(%u) Stale time: %d is now update to: %d", __func__, VRF_LOGNAME(vrf), info->vrf_id, info->stale_removal_time, - api->stale_removal_time); + api.stale_removal_time); - info->stale_removal_time = api->stale_removal_time; + info->stale_removal_time = api.stale_removal_time; } break; case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: if (!info) { - LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d", - __func__, zebra_route_string(client->proto), - api->afi, api->safi); - } else { - struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); - - LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d", + LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d, no Graceful Restart communication, returning", __func__, zebra_route_string(client->proto), - VRF_LOGNAME(vrf), info->vrf_id, api->afi, - api->safi); - info->route_sync[api->afi][api->safi] = true; + api.afi, api.safi); + return; } + + LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d", + __func__, zebra_route_string(client->proto), + VRF_LOGNAME(vrf), info->vrf_id, api.afi, api.safi); + info->route_sync[api.afi] = true; + + /* + * Schedule for after anything already in the meta Q + */ + rib_add_gr_run(api.afi, api.vrf_id, client->proto, + client->instance); + zebra_gr_process_client_stale_routes(client, info); break; case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: if (!info) { LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d", __func__, zebra_route_string(client->proto), - api->afi, api->safi); + api.afi, api.safi); } else { - struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); - LOG_GR("%s: Client %s vrf %s(%u) route update pending for AFI %d, SAFI %d", __func__, zebra_route_string(client->proto), - VRF_LOGNAME(vrf), info->vrf_id, api->afi, - api->safi); + VRF_LOGNAME(vrf), info->vrf_id, api.afi, + api.safi); - info->af_enabled[api->afi][api->safi] = true; + info->af_enabled[api.afi] = true; } break; } } /* - * Handler for capabilities that are received from client. - */ -static void zebra_client_capabilities_handler(struct zserv *client, - struct zapi_cap *api) -{ - switch (api->cap) { - case ZEBRA_CLIENT_GR_CAPABILITIES: - case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: - case ZEBRA_CLIENT_GR_DISABLE: - case ZEBRA_CLIENT_RIB_STALE_TIME: - /* - * For all the cases we need to update the client info. - */ - zebra_client_update_info(client, api); - break; - case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: - /* - * After client info has been updated delete all - * stale routes - */ - zebra_client_update_info(client, api); - zebra_gr_process_client_stale_routes(client, api->vrf_id); - break; - } -} - -/* - * Function to decode and call appropriate functions - * to handle client capabilities. - */ -void zread_client_capabilities(ZAPI_HANDLER_ARGS) -{ - struct zapi_cap api; - struct stream *s; - - s = msg; - - if (zapi_capabilities_decode(s, &api)) { - LOG_GR("%s: Error in reading capabilities for client %s", - __func__, zebra_route_string(client->proto)); - return; - } - - /* GR only for dynamic clients */ - if (client->proto <= ZEBRA_ROUTE_CONNECT) { - LOG_GR("%s: GR capabilities for client %s not supported", - __func__, zebra_route_string(client->proto)); - return; - } - /* Call the capabilities handler */ - zebra_client_capabilities_handler(client, &api); -} - - -/* * Stale route handling */ @@ -470,10 +448,6 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread) client = (struct zserv *)info->stale_client_ptr; - /* Set the flag to indicate all stale route deletion */ - if (thread->u.val == 1) - info->do_delete = true; - cnt = zebra_gr_delete_stale_routes(info); /* Restart the timer */ @@ -492,8 +466,6 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread) __func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf), info->vrf_id); - XFREE(MTYPE_ZEBRA_GR, info->current_prefix); - info->current_afi = 0; zebra_gr_delete_stale_client(info); } } @@ -502,14 +474,13 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread) /* * Function to process to check if route entry is stale * or has been updated. + * + * Returns true when a node is deleted else false */ -static void zebra_gr_process_route_entry(struct zserv *client, +static bool zebra_gr_process_route_entry(struct zserv *client, struct route_node *rn, struct route_entry *re) { - if ((client == NULL) || (rn == NULL) || (re == NULL)) - return; - /* If the route is not refreshed after restart, delete the entry */ if (re->uptime < client->restart_time) { if (IS_ZEBRA_DEBUG_RIB) @@ -517,7 +488,62 @@ static void zebra_gr_process_route_entry(struct zserv *client, __func__, zebra_route_string(client->proto), &rn->p); rib_delnode(rn, re); + + return true; } + + return false; +} + +static void zebra_gr_delete_stale_route_table_afi(struct event *event) +{ + struct zebra_gr_afi_clean *gac = EVENT_ARG(event); + struct route_table *table; + struct route_node *rn; + struct route_entry *re, *next; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(gac->info->vrf_id); + int32_t n = 0; + + if (!zvrf) + goto done; + + table = zvrf->table[gac->afi][SAFI_UNICAST]; + if (!table) + goto done; + + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + RNODE_FOREACH_RE_SAFE (rn, re, next) { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + /* If the route refresh is received + * after restart then do not delete + * the route + */ + + if (re->type == gac->proto && + re->instance == gac->instance && + zebra_gr_process_route_entry( + gac->info->stale_client_ptr, rn, re)) + n++; + + /* If the max route count is reached + * then timer thread will be restarted + * Store the current prefix and afi + */ + if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT) && + (gac->info->do_delete == false)) { + event_add_timer( + zrouter.master, + zebra_gr_delete_stale_route_table_afi, + gac, ZEBRA_DEFAULT_STALE_UPDATE_DELAY, + &gac->t_gac); + } + } + } + +done: + XFREE(MTYPE_ZEBRA_GR, gac); } /* @@ -528,19 +554,11 @@ static void zebra_gr_process_route_entry(struct zserv *client, static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info, struct zebra_vrf *zvrf) { - struct route_node *rn, *curr; - struct route_entry *re; - struct route_entry *next; - struct route_table *table; - int32_t n = 0; - afi_t afi, curr_afi; + afi_t afi; uint8_t proto; uint16_t instance; struct zserv *s_client; - if ((info == NULL) || (zvrf == NULL)) - return -1; - s_client = info->stale_client_ptr; if (s_client == NULL) { LOG_GR("%s: Stale client %s(%u) not present", __func__, @@ -550,69 +568,18 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info, proto = s_client->proto; instance = s_client->instance; - curr_afi = info->current_afi; LOG_GR("%s: Client %s %s(%u) stale routes are being deleted", __func__, zebra_route_string(proto), zvrf->vrf->name, zvrf->vrf->vrf_id); /* Process routes for all AFI */ - for (afi = curr_afi; afi < AFI_MAX; afi++) { - table = zvrf->table[afi][SAFI_UNICAST]; + for (afi = AFI_IP; afi < AFI_MAX; afi++) { - if (table) { - /* - * If the current prefix is NULL then get the first - * route entry in the table - */ - if (info->current_prefix == NULL) { - rn = route_top(table); - if (rn == NULL) - continue; - curr = rn; - } else - /* Get the next route entry */ - curr = route_table_get_next( - table, info->current_prefix); - - for (rn = curr; rn; rn = srcdest_route_next(rn)) { - RNODE_FOREACH_RE_SAFE (rn, re, next) { - if (CHECK_FLAG(re->status, - ROUTE_ENTRY_REMOVED)) - continue; - /* If the route refresh is received - * after restart then do not delete - * the route - */ - if (re->type == proto - && re->instance == instance) { - zebra_gr_process_route_entry( - s_client, rn, re); - n++; - } - - /* If the max route count is reached - * then timer thread will be restarted - * Store the current prefix and afi - */ - if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT) - && (info->do_delete == false)) { - info->current_afi = afi; - info->current_prefix = XCALLOC( - MTYPE_ZEBRA_GR, - sizeof(struct prefix)); - prefix_copy( - info->current_prefix, - &rn->p); - return n; - } - } - } - } /* - * Reset the current prefix to indicate processing completion - * of the current AFI + * Schedule for immediately after anything in the + * meta-Q */ - XFREE(MTYPE_ZEBRA_GR, info->current_prefix); + rib_add_gr_run(afi, info->vrf_id, proto, instance); } return 0; } @@ -623,21 +590,13 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info, */ static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info) { - struct vrf *vrf; struct zebra_vrf *zvrf; uint64_t cnt = 0; if (info == NULL) return -1; - /* Get the current VRF */ - vrf = vrf_lookup_by_id(info->vrf_id); - if (vrf == NULL) { - LOG_GR("%s: Invalid VRF specified %u", __func__, info->vrf_id); - return -1; - } - - zvrf = vrf->info; + zvrf = zebra_vrf_lookup_by_id(info->vrf_id); if (zvrf == NULL) { LOG_GR("%s: Invalid VRF entry %u", __func__, info->vrf_id); return -1; @@ -652,49 +611,63 @@ static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info) * and cancels the stale timer */ static void zebra_gr_process_client_stale_routes(struct zserv *client, - vrf_id_t vrf_id) + struct client_gr_info *info) { - struct client_gr_info *info = NULL; afi_t afi; - safi_t safi; - - TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { - if (info->vrf_id == vrf_id) - break; - } if (info == NULL) return; /* Check if route update completed for all AFI, SAFI */ - FOREACH_AFI_SAFI_NSF (afi, safi) { - if (info->af_enabled[afi][safi]) { - if (!info->route_sync[afi][safi]) { - struct vrf *vrf = vrf_lookup_by_id(vrf_id); - - LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d, SAFI %d", - __func__, - zebra_route_string(client->proto), - VRF_LOGNAME(vrf), info->vrf_id, afi, - safi); - return; - } + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + if (info->af_enabled[afi] && !info->route_sync[afi]) { + struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); + + LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d", + __func__, zebra_route_string(client->proto), + VRF_LOGNAME(vrf), info->vrf_id, afi); + return; } } /* * Route update completed for all AFI, SAFI - * Cancel the stale timer and process the routes + * Cancel the stale timer, routes are already being processed */ if (info->t_stale_removal) { - struct vrf *vrf = vrf_lookup_by_id(vrf_id); + struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); LOG_GR("%s: Client %s canceled stale delete timer vrf %s(%d)", __func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf), info->vrf_id); EVENT_OFF(info->t_stale_removal); - event_execute(zrouter.master, - zebra_gr_route_stale_delete_timer_expiry, info, - 0); } } + +void zebra_gr_process_client(afi_t afi, vrf_id_t vrf_id, uint8_t proto, + uint8_t instance) +{ + struct zserv *client = zserv_find_client(proto, instance); + struct client_gr_info *info = NULL; + struct zebra_gr_afi_clean *gac; + + if (client == NULL) + return; + + TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { + if (info->vrf_id == vrf_id) + break; + } + + if (info == NULL) + return; + + gac = XCALLOC(MTYPE_ZEBRA_GR, sizeof(*gac)); + gac->info = info; + gac->afi = afi; + gac->proto = proto; + gac->instance = instance; + + event_add_event(zrouter.master, zebra_gr_delete_stale_route_table_afi, + gac, 0, &gac->t_gac); +} diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ceb0640553..32cfa4d04c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -64,7 +64,12 @@ DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn)); -/* Meta Q's specific names */ +/* + * Meta Q's specific names + * + * If you add something here ensure that you + * change MQ_SIZE as well over in rib.h + */ enum meta_queue_indexes { META_QUEUE_NHG, META_QUEUE_EVPN, @@ -76,6 +81,7 @@ enum meta_queue_indexes { META_QUEUE_NOTBGP, META_QUEUE_BGP, META_QUEUE_OTHER, + META_QUEUE_GR_RUN, }; /* Each route type's string and default distance value. */ @@ -250,6 +256,8 @@ static const char *subqueue2str(enum meta_queue_indexes index) return "BGP Routes"; case META_QUEUE_OTHER: return "Other Routes"; + case META_QUEUE_GR_RUN: + return "Graceful Restart"; } return "Unknown"; @@ -3089,6 +3097,23 @@ static void process_subq_early_route(struct listnode *lnode) process_subq_early_route_add(ere); } +struct meta_q_gr_run { + afi_t afi; + vrf_id_t vrf_id; + uint8_t proto; + uint8_t instance; +}; + +static void process_subq_gr_run(struct listnode *lnode) +{ + struct meta_q_gr_run *gr_run = listgetdata(lnode); + + zebra_gr_process_client(gr_run->afi, gr_run->vrf_id, gr_run->proto, + gr_run->instance); + + XFREE(MTYPE_WQ_WRAPPER, gr_run); +} + /* * Examine the specified subqueue; process one entry and return 1 if * there is a node, return 0 otherwise. @@ -3122,6 +3147,9 @@ static unsigned int process_subq(struct list *subq, case META_QUEUE_OTHER: process_subq_route(lnode, qindex); break; + case META_QUEUE_GR_RUN: + process_subq_gr_run(lnode); + break; } list_delete_node(subq, lnode); @@ -3727,6 +3755,20 @@ static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l, } } +static void rib_meta_queue_gr_run_free(struct meta_queue *mq, struct list *l, + struct zebra_vrf *zvrf) +{ + struct meta_q_gr_run *gr_run; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(l, node, nnode, gr_run)) { + if (zvrf && zvrf->vrf->vrf_id != gr_run->vrf_id) + continue; + + XFREE(MTYPE_WQ_WRAPPER, gr_run); + } +} + void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf) { enum meta_queue_indexes i; @@ -3754,6 +3796,9 @@ void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf) case META_QUEUE_OTHER: rib_meta_queue_free(mq, mq->subq[i], zvrf); break; + case META_QUEUE_GR_RUN: + rib_meta_queue_gr_run_free(mq, mq->subq[i], zvrf); + break; } if (!zvrf) list_delete(&mq->subq[i]); @@ -4094,6 +4139,17 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, zlog_debug("%s: dump complete", straddr); } +static int rib_meta_queue_gr_run_add(struct meta_queue *mq, void *data) +{ + listnode_add(mq->subq[META_QUEUE_GR_RUN], data); + mq->size++; + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("Graceful Run adding"); + + return 0; +} + static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data) { struct zebra_early_route *ere = data; @@ -4110,6 +4166,20 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data) return 0; } +int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto, uint8_t instance) +{ + struct meta_q_gr_run *gr_run; + + gr_run = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*gr_run)); + + gr_run->afi = afi; + gr_run->proto = proto; + gr_run->vrf_id = vrf_id; + gr_run->instance = instance; + + return mq_add_handler(gr_run, rib_meta_queue_gr_run_add); +} + struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, uint8_t instance, uint32_t flags, uint32_t nhe_id, diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index d9a7ee465a..142501b149 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1041,7 +1041,7 @@ route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object) } alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -1104,7 +1104,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, } plist = prefix_list_lookup(AFI_IP, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -1145,7 +1145,7 @@ route_match_address(afi_t afi, void *rule, const struct prefix *prefix, alist = access_list_lookup(afi, (char *)rule); if (alist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", __func__, (char *)rule); @@ -1207,7 +1207,7 @@ route_match_address_prefix_list(void *rule, const struct prefix *prefix, plist = prefix_list_lookup(afi, (char *)rule); if (plist == NULL) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "%s: Prefix List %s specified does not exist defaulting to NO_MATCH", __func__, (char *)rule); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index c370ad9169..36290f99e0 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -2582,19 +2582,18 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, struct zebra_mac *zrmac = NULL; json_object *json = NULL; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); - zl3vni = zl3vni_lookup(l3vni); if (!zl3vni) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni); return; @@ -2603,7 +2602,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, zrmac = zl3vni_rmac_lookup(zl3vni, rmac); if (!zrmac) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% Requested RMAC doesn't exist in L3-VNI %u\n", @@ -2624,13 +2623,18 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json) struct rmac_walk_ctx wctx; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } zl3vni = zl3vni_lookup(l3vni); if (!zl3vni) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni); return; @@ -2639,9 +2643,6 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json) if (!num_rmacs) return; - if (use_json) - json = json_object_new_object(); - memset(&wctx, 0, sizeof(wctx)); wctx.vty = vty; wctx.json = json; @@ -2663,15 +2664,14 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json) json_object *json = NULL; void *args[2]; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); - args[0] = vty; args[1] = json; hash_iterate(zrouter.l3vni_table, @@ -2690,15 +2690,14 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni, struct zebra_neigh *n = NULL; json_object *json = NULL; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); - /* If vni=0 passed, assume svd lookup */ if (!l3vni) n = svd_nh_lookup(ip); @@ -2799,15 +2798,14 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json) json_object *json = NULL; void *args[2]; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); - args[0] = vty; args[1] = json; hash_iterate(zrouter.l3vni_table, @@ -2828,24 +2826,23 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json) json_object *json = NULL; struct zebra_l3vni *zl3vni = NULL; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } zl3vni = zl3vni_lookup(vni); if (!zl3vni) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - if (use_json) - json = json_object_new_object(); - args[0] = vty; args[1] = json; zl3vni_print(zl3vni, (void *)args); @@ -2900,12 +2897,18 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, struct neigh_walk_ctx wctx; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } + zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; @@ -2914,9 +2917,6 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, if (!num_neigh) return; - if (use_json) - json = json_object_new_object(); - /* Since we have IPv6 addresses to deal with which can vary widely in * size, we try to be a bit more elegant in display by first computing * the maximum width. @@ -2951,12 +2951,14 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, json_object *json = NULL; void *args[3]; - if (!is_evpn_enabled()) - return; - if (use_json) json = json_object_new_object(); + if (!is_evpn_enabled()) { + vty_json(vty, json); + return; + } + args[0] = vty; args[1] = json; args[2] = (void *)(ptrdiff_t)print_dup; @@ -2979,12 +2981,14 @@ void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty, json_object *json = NULL; void *args[3]; - if (!is_evpn_enabled()) - return; - if (use_json) json = json_object_new_object(); + if (!is_evpn_enabled()) { + vty_json(vty, json); + return; + } + args[0] = vty; args[1] = json; args[2] = (void *)(ptrdiff_t)print_dup; @@ -3008,12 +3012,18 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, struct zebra_neigh *n; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } + zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; @@ -3026,8 +3036,6 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, vni); return; } - if (use_json) - json = json_object_new_object(); zebra_evpn_print_neigh(n, vty, json); @@ -3048,12 +3056,18 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, struct neigh_walk_ctx wctx; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } + zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; @@ -3062,9 +3076,6 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, if (!num_neigh) return; - if (use_json) - json = json_object_new_object(); - memset(&wctx, 0, sizeof(wctx)); wctx.zevpn = zevpn; wctx.vty = vty; @@ -3094,12 +3105,20 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, struct neigh_walk_ctx wctx; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } zevpn = zebra_evpn_lookup(vni); if (!zevpn) { - vty_out(vty, "%% VNI %u does not exist\n", vni); + if (use_json) + vty_json(vty, json); + else + vty_out(vty, "%% VNI %u does not exist\n", vni); return; } @@ -3111,9 +3130,6 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, if (!num_neigh) return; - if (use_json) - json = json_object_new_object(); - /* Since we have IPv6 addresses to deal with which can vary widely in * size, we try to be a bit more elegant in display by first computing * the maximum width. @@ -3155,8 +3171,12 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, json_object *json = NULL; json_object *json_mac = NULL; - if (!is_evpn_enabled()) + if (!is_evpn_enabled()) { + if (use_json) + vty_out(vty, "{}\n"); return; + } + zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) @@ -3218,13 +3238,13 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, struct mac_walk_ctx wctx; json_object *json = NULL; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); memset(&wctx, 0, sizeof(wctx)); wctx.vty = vty; @@ -3246,13 +3266,13 @@ void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty, struct mac_walk_ctx wctx; json_object *json = NULL; + if (use_json) + json = json_object_new_object(); + if (!is_evpn_enabled()) { - if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); return; } - if (use_json) - json = json_object_new_object(); memset(&wctx, 0, sizeof(wctx)); wctx.vty = vty; @@ -3275,12 +3295,14 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, struct mac_walk_ctx wctx; json_object *json = NULL; - if (!is_evpn_enabled()) - return; - if (use_json) json = json_object_new_object(); + if (!is_evpn_enabled()) { + vty_json(vty, json); + return; + } + memset(&wctx, 0, sizeof(wctx)); wctx.vty = vty; wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; @@ -3303,13 +3325,18 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, struct zebra_mac *mac; json_object *json = NULL; - if (!is_evpn_enabled()) + if (use_json) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; @@ -3317,7 +3344,7 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) { if (use_json) - vty_out(vty, "{}\n"); + vty_json(vty, json); else vty_out(vty, "%% Requested MAC does not exist in VNI %u\n", @@ -3325,10 +3352,8 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, return; } - if (use_json) - json = json_object_new_object(); - zebra_evpn_print_mac(mac, vty, json); + if (use_json) vty_json(vty, json); } @@ -3693,8 +3718,11 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, json_object *json = NULL; json_object *json_mac = NULL; - if (!is_evpn_enabled()) + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } + zevpn = zebra_evpn_lookup(vni); if (!zevpn) { if (use_json) @@ -3745,12 +3773,14 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct zebra_l3vni *zl3vni = NULL; struct zebra_evpn *zevpn = NULL; - if (!is_evpn_enabled()) - return; - if (use_json) json = json_object_new_object(); + if (!is_evpn_enabled()) { + vty_json(vty, json); + return; + } + args[0] = vty; args[1] = json; @@ -3787,8 +3817,13 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj) json_object *json = NULL; struct zebra_vrf *zvrf = NULL; - if (!is_evpn_enabled()) + if (uj) + json = json_object_new_object(); + + if (!is_evpn_enabled()) { + vty_json(vty, json); return; + } zvrf = zebra_vrf_get_evpn(); @@ -3797,7 +3832,6 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj) num_vnis = num_l2vnis + num_l3vnis; if (uj) { - json = json_object_new_object(); json_object_string_add(json, "advertiseGatewayMacip", zvrf->advertise_gw_macip ? "Yes" : "No"); json_object_string_add(json, "advertiseSviMacip", @@ -3860,12 +3894,15 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, json_object *json = NULL; void *args[2]; - if (!is_evpn_enabled()) - return; - if (use_json) json = json_object_new_object(); - else + + if (!is_evpn_enabled()) { + vty_json(vty, json); + return; + } + + if (!use_json) vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI", "Type", "VxLAN IF", "# MACs", "# ARPs", "# Remote VTEPs", "Tenant VRF"); @@ -3943,8 +3980,11 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf, struct zebra_ns *zns = NULL; struct zebra_evpn_show zes; - if (!is_evpn_enabled()) + if (!is_evpn_enabled()) { + if (use_json) + vty_out(vty, "{}\n"); return; + } zns = zebra_ns_lookup(NS_DEFAULT); if (!zns) diff --git a/zebra/zserv.c b/zebra/zserv.c index 70707866ee..6abd49310c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1152,10 +1152,6 @@ static void zebra_show_stale_client_detail(struct vty *vty, info->t_stale_removal)); } } - vty_out(vty, "Current AFI : %d\n", info->current_afi); - if (info->current_prefix) - vty_out(vty, "Current prefix : %pFX\n", - info->current_prefix); } } vty_out(vty, "\n"); diff --git a/zebra/zserv.h b/zebra/zserv.h index aa58a3a299..90aa4d53f4 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -51,9 +51,6 @@ struct client_gr_info { /* VRF for which GR enabled */ vrf_id_t vrf_id; - /* AFI */ - afi_t current_afi; - /* Stale time and GR cap */ uint32_t stale_removal_time; enum zserv_client_capabilities capabilities; @@ -64,11 +61,10 @@ struct client_gr_info { bool stale_client; /* Route sync and enable flags for AFI/SAFI */ - bool af_enabled[AFI_MAX][SAFI_MAX]; - bool route_sync[AFI_MAX][SAFI_MAX]; + bool af_enabled[AFI_MAX]; + bool route_sync[AFI_MAX]; /* Book keeping */ - struct prefix *current_prefix; void *stale_client_ptr; struct event *t_stale_removal; |
