diff options
233 files changed, 2024 insertions, 1467 deletions
diff --git a/bfdd/control.c b/bfdd/control.c index 4929bf1998..e772aadfc4 100644 --- a/bfdd/control.c +++ b/bfdd/control.c @@ -167,7 +167,6 @@ int control_accept(struct thread *t) control_new(csock); - bglobal.bg_csockev = NULL; thread_add_read(master, control_accept, NULL, sd, &bglobal.bg_csockev); return 0; diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 33e3db2c16..0e590a463c 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -720,7 +720,7 @@ bool lcommunity_list_exact_match(struct lcommunity *lcom, return entry->direct == COMMUNITY_PERMIT; if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) { - if (lcommunity_cmp(lcom, entry->u.com)) + if (lcommunity_cmp(lcom, entry->u.lcom)) return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) { if (lcommunity_regexp_match(lcom, entry->reg)) diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 299ee305be..2f0b87aa3a 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -165,13 +165,11 @@ static int bgp_dump_interval_add(struct bgp_dump *bgp_dump, int interval) interval = interval - secs_into_day % interval; /* always > 0 */ } - bgp_dump->t_interval = NULL; thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump, interval, &bgp_dump->t_interval); } else { /* One-off dump: execute immediately, don't affect any scheduled * dumps */ - bgp_dump->t_interval = NULL; thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump, 0, &bgp_dump->t_interval); } @@ -453,7 +451,6 @@ static int bgp_dump_interval_func(struct thread *t) { struct bgp_dump *bgp_dump; bgp_dump = THREAD_ARG(t); - bgp_dump->t_interval = NULL; /* Reschedule dump even if file couldn't be opened this time... */ if (bgp_dump_open_file(bgp_dump) != NULL) { diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 6248ad927b..ea54c14222 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -54,6 +54,7 @@ #include "bgpd/bgp_mac.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_nht.h" +#include "bgpd/bgp_trace.h" /* * Definitions and external declarations. @@ -653,6 +654,9 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, &p->prefix.macip_addr.mac, &p->prefix.macip_addr.ip, flags, seq, &remote_vtep_ip); + frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip, + esi); + return zclient_send_message(zclient); } @@ -703,6 +707,8 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, add ? "ADD" : "DEL", vpn->vni, &p->prefix.imet_addr.ip.ipaddr_v4); + frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p); + return zclient_send_message(zclient); } @@ -4335,6 +4341,54 @@ static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) } /* + * Handle autort change for L3VNI. + */ +static void update_autort_l3vni(struct bgp *bgp) +{ + if ((CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) + && (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD))) + return; + + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { + if (is_l3vni_live(bgp)) + uninstall_routes_for_vrf(bgp); + + /* Cleanup the RT to VRF mapping */ + bgp_evpn_unmap_vrf_from_its_rts(bgp); + + /* Remove auto generated RT */ + evpn_auto_rt_import_delete_for_vrf(bgp); + + list_delete_all_node(bgp->vrf_import_rtl); + + /* Map auto derive or configured RTs */ + evpn_auto_rt_import_add_for_vrf(bgp); + } + + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) { + list_delete_all_node(bgp->vrf_export_rtl); + + evpn_auto_rt_export_delete_for_vrf(bgp); + + evpn_auto_rt_export_add_for_vrf(bgp); + + if (is_l3vni_live(bgp)) + bgp_evpn_map_vrf_to_its_rts(bgp); + } + + if (!is_l3vni_live(bgp)) + return; + + /* advertise type-5 routes if needed */ + update_advertise_vrf_routes(bgp); + + /* install all remote routes belonging to this l3vni + * into corresponding vrf + */ + install_routes_for_vrf(bgp); +} + +/* * Public functions. */ @@ -4706,6 +4760,8 @@ void bgp_evpn_handle_autort_change(struct bgp *bgp) (void (*)(struct hash_bucket *, void*))update_autort_vni, bgp); + if (bgp->l3vni) + update_autort_l3vni(bgp); } /* diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 34094a0bde..9316d218a2 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -50,6 +50,7 @@ #include "bgpd/bgp_label.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_trace.h" static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es); @@ -1225,6 +1226,8 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_new(struct bgp_evpn_es *es, es_vtep->es = es; es_vtep->vtep_ip.s_addr = vtep_ip.s_addr; + inet_ntop(AF_INET, &es_vtep->vtep_ip, es_vtep->vtep_str, + sizeof(es_vtep->vtep_str)); listnode_init(&es_vtep->es_listnode, es_vtep); listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode); @@ -1301,6 +1304,8 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, zlog_debug("Tx %s Remote ESI %s VTEP %pI4", add ? "ADD" : "DEL", es->esi_str, &es_vtep->vtep_ip); + frrtrace(3, frr_bgp, evpn_mh_vtep_zsend, add, es, es_vtep); + return zclient_send_message(zclient); } @@ -2522,6 +2527,8 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, es_vrf->bgp_vrf->vrf_id, v4_nhg ? "v4_nhg" : "v6_nhg", nhg_id); + frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, true, v4_nhg, nhg_id, es_vrf); + /* only the gateway ip changes for each NH. rest of the params * are constant */ @@ -2558,6 +2565,8 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, zlog_debug("nhg %u vtep %pI4 l3-svi %d", api_nhg.id, &es_vtep->vtep_ip, es_vrf->bgp_vrf->l3vni_svi_ifindex); + + frrtrace(3, frr_bgp, evpn_mh_nh_zsend, nhg_id, es_vtep, es_vrf); } if (!api_nhg.nexthop_num) @@ -2603,6 +2612,10 @@ static void bgp_evpn_l3nhg_zebra_del_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id, v4_nhg ? "v4_nhg" : "v6_nhg", api_nhg.id); + + frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, false, v4_nhg, api_nhg.id, + es_vrf); + zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); } @@ -4202,6 +4215,8 @@ static void bgp_evpn_nh_zebra_update_send(struct bgp_evpn_nh *nh, bool add) nh->bgp_vrf->name, nh->nh_str); } + frrtrace(2, frr_bgp, evpn_mh_nh_rmac_zsend, add, nh); + zclient_send_message(zclient); } diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index 22a4215664..37a46c2f0e 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -145,6 +145,8 @@ struct bgp_evpn_es_vtep { struct bgp_evpn_es *es; /* parent ES */ struct in_addr vtep_ip; + char vtep_str[INET6_ADDRSTRLEN]; + uint32_t flags; /* Rxed a Type4 route from this PE */ #define BGP_EVPNES_VTEP_ESR (1 << 0) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index c77e240855..061fa6f087 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -664,7 +664,7 @@ void bgp_nht_interface_events(struct peer *peer) void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) { struct bgp_nexthop_cache_head *tree = NULL; - struct bgp_nexthop_cache *bnc; + struct bgp_nexthop_cache *bnc_nhc, *bnc_import; struct bgp *bgp; struct zapi_route nhr; afi_t afi; @@ -685,22 +685,38 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) } afi = family2afi(nhr.prefix.family); - if (command == ZEBRA_NEXTHOP_UPDATE) - tree = &bgp->nexthop_cache_table[afi]; - else if (command == ZEBRA_IMPORT_CHECK_UPDATE) - tree = &bgp->import_check_table[afi]; + tree = &bgp->nexthop_cache_table[afi]; - bnc = bnc_find(tree, &nhr.prefix, nhr.srte_color); - if (!bnc) { + bnc_nhc = bnc_find(tree, &nhr.prefix, nhr.srte_color); + if (!bnc_nhc) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache", + &nhr.prefix, nhr.srte_color, bgp->name_pretty); + } else + bgp_process_nexthop_update(bnc_nhc, &nhr); + + tree = &bgp->import_check_table[afi]; + + bnc_import = bnc_find(tree, &nhr.prefix, nhr.srte_color); + if (!bnc_import) { if (BGP_DEBUG(nht, NHT)) zlog_debug( - "parse nexthop update(%pFX(%u)(%s)): bnc info not found", + "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check", &nhr.prefix, nhr.srte_color, bgp->name_pretty); return; + } else { + if (nhr.type == ZEBRA_ROUTE_BGP + || !prefix_same(&bnc_import->prefix, &nhr.prefix)) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "%s: Import Check does not resolve to the same prefix for %pFX received %pFX", + __func__, &bnc_import->prefix, &nhr.prefix); + return; + } + bgp_process_nexthop_update(bnc_import, &nhr); } - bgp_process_nexthop_update(bnc, &nhr); - /* * HACK: if any BGP route is dependant on an SR-policy that doesn't * exist, zebra will never send NH updates relative to that policy. In @@ -712,12 +728,12 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) * which should provide a better infrastructure to solve this issue in * a more efficient and elegant way. */ - if (nhr.srte_color == 0) { + if (nhr.srte_color == 0 && bnc_nhc) { struct bgp_nexthop_cache *bnc_iter; frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi], bnc_iter) { - if (!prefix_same(&bnc->prefix, &bnc_iter->prefix) + if (!prefix_same(&bnc_import->prefix, &bnc_iter->prefix) || bnc_iter->srte_color == 0 || CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID)) continue; @@ -843,6 +859,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) { bool exact_match = false; + bool resolve_via_default = false; int ret; if (!zclient) @@ -863,11 +880,12 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) "%s: We have not connected yet, cannot send nexthops", __func__); } - if ((command == ZEBRA_NEXTHOP_REGISTER - || command == ZEBRA_IMPORT_ROUTE_REGISTER) - && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) - || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))) - exact_match = true; + if (command == ZEBRA_NEXTHOP_REGISTER) { + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) + exact_match = true; + if (CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) + resolve_via_default = true; + } if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__, @@ -875,17 +893,15 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) bnc->bgp->name_pretty); ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match, - bnc->bgp->vrf_id); + resolve_via_default, bnc->bgp->vrf_id); /* TBD: handle the failure */ if (ret == ZCLIENT_SEND_FAILURE) flog_warn(EC_BGP_ZEBRA_SEND, "sendmsg_nexthop: zclient_send_message() failed"); - if ((command == ZEBRA_NEXTHOP_REGISTER) - || (command == ZEBRA_IMPORT_ROUTE_REGISTER)) + if (command == ZEBRA_NEXTHOP_REGISTER) SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - else if ((command == ZEBRA_NEXTHOP_UNREGISTER) - || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER)) + else if (command == ZEBRA_NEXTHOP_UNREGISTER) UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); return; } @@ -910,10 +926,7 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, return; } - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); } /** @@ -935,10 +948,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, return; } - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); } /** diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index bb2dbc9427..de9a89523b 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1961,6 +1961,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) struct update_group *updgrp; struct peer *updgrp_peer; uint8_t subtype; + bool force_update = false; bgp_size_t msg_length = size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE); @@ -2222,7 +2223,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) /* Avoid supressing duplicate routes later * when processing in subgroup_announce_table(). */ - SET_FLAG(paf->subgroup->sflags, SUBGRP_STATUS_FORCE_UPDATES); + force_update = true; /* If the peer is configured for default-originate clear the * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will @@ -2354,7 +2355,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) } /* Perform route refreshment to the peer */ - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, force_update); /* No FSM action necessary */ return BGP_PACKET_NOOP; @@ -2457,7 +2458,8 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, peer->afc_recv[afi][safi] = 1; if (peer->afc[afi][safi]) { peer->afc_nego[afi][safi] = 1; - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, + false); } } else { peer->afc_recv[afi][safi] = 0; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fc97178450..0eb3cc61e3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4588,8 +4588,11 @@ static int bgp_announce_route_timer_expired(struct thread *t) * bgp_announce_route * * *Triggers* announcement of routes of a given AFI/SAFI to a peer. + * + * if force is true we will force an update even if the update + * limiting code is attempted to kick in. */ -void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) +void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force) { struct peer_af *paf; struct update_subgroup *subgrp; @@ -4606,6 +4609,9 @@ void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) if (!subgrp || paf->t_announce_route) return; + if (force) + SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES); + /* * Start a timer to stagger/delay the announce. This serves * two purposes - announcement can potentially be combined for @@ -4634,7 +4640,7 @@ void bgp_announce_route_all(struct peer *peer) safi_t safi; FOREACH_AFI_SAFI (afi, safi) - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Flag or unflag bgp_dest to determine whether it should be treated by @@ -4772,7 +4778,7 @@ static int bgp_soft_reconfig_table_task(struct thread *thread) table->soft_reconfig_peers, peer); bgp_announce_route(peer, table->afi, - table->safi); + table->safi, false); if (list_isempty( table->soft_reconfig_peers)) { list_delete( @@ -4800,7 +4806,7 @@ static int bgp_soft_reconfig_table_task(struct thread *thread) */ for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) { listnode_delete(table->soft_reconfig_peers, peer); - bgp_announce_route(peer, table->afi, table->safi); + bgp_announce_route(peer, table->afi, table->safi, false); } list_delete(&table->soft_reconfig_peers); @@ -13961,10 +13967,11 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route, DEFUN (show_ip_bgp_neighbor_received_prefix_filter, show_ip_bgp_neighbor_received_prefix_filter_cmd, - "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]", SHOW_STR IP_STR BGP_STR + BGP_INSTANCE_HELP_STR "Address Family\n" "Address Family\n" "Address Family modifier\n" @@ -13979,50 +13986,28 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; char *peerstr = NULL; - char name[BUFSIZ]; - union sockunion su; struct peer *peer; - int count, ret; - + int count; int idx = 0; + struct bgp *bgp = NULL; + bool uj = use_json(argc, argv); + + if (uj) + argc--; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp, uj); + if (!idx) + return CMD_WARNING; - /* show [ip] bgp */ - if (argv_find(argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [<ipv4|ipv6> [unicast]] */ - if (argv_find(argv, argc, "ipv4", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv6", &idx)) - afi = AFI_IP6; /* neighbors <A.B.C.D|X:X::X:X|WORD> */ argv_find(argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; - bool uj = use_json(argc, argv); - - ret = str2sockunion(peerstr, &su); - if (ret < 0) { - peer = peer_lookup_by_conf_if(NULL, peerstr); - if (!peer) { - if (uj) - vty_out(vty, "{}\n"); - else - vty_out(vty, - "%% Malformed address or name: %s\n", - peerstr); - return CMD_WARNING; - } - } else { - peer = peer_lookup(NULL, &su); - if (!peer) { - if (uj) - vty_out(vty, "{}\n"); - else - vty_out(vty, "No peer\n"); - return CMD_WARNING; - } - } + peer = peer_lookup_in_view(vty, bgp, peerstr, uj); + if (!peer) + return CMD_WARNING; snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi); count = prefix_bgp_show_prefix_list(NULL, afi, name, uj); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 7609f7196d..37bf675b67 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -608,7 +608,8 @@ extern void bgp_process_queue_init(struct bgp *bgp); extern void bgp_route_init(void); extern void bgp_route_finish(void); extern void bgp_cleanup_routes(struct bgp *); -extern void bgp_announce_route(struct peer *, afi_t, safi_t); +extern void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, + bool force); extern void bgp_stop_announce_route_timer(struct peer_af *paf); extern void bgp_announce_route_all(struct peer *); extern void bgp_default_originate(struct peer *, afi_t, safi_t, int); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 835576a079..2f37367a8f 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4576,13 +4576,11 @@ DEFUN_YANG (no_match_probability, DEFPY_YANG (match_ip_route_source, match_ip_route_source_cmd, - "match ip route-source <(1-199)|(1300-2699)|WORD>", + "match ip route-source WORD", MATCH_STR IP_STR "Match advertising source address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP standard access-list name\n") + "IP Access-list name\n") { const char *xpath = "./match-condition[condition='frr-bgp-route-map:ip-route-source']"; @@ -4602,14 +4600,12 @@ DEFPY_YANG (match_ip_route_source, DEFUN_YANG (no_match_ip_route_source, no_match_ip_route_source_cmd, - "no match ip route-source [<(1-199)|(1300-2699)|WORD>]", + "no match ip route-source [WORD]", NO_STR MATCH_STR IP_STR "Match advertising source address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP standard access-list name\n") + "IP Access-list name\n") { const char *xpath = "./match-condition[condition='frr-bgp-route-map:ip-route-source']"; diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 85676e6758..09a6be4010 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -1035,6 +1035,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish( char *argstr; const char *condition; route_map_event_t event; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -1072,8 +1073,14 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish( rhc->rhc_event = RMAP_EVENT_ECLIST_DELETED; } - bgp_route_match_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, event, - args->errmsg, args->errmsg_len); + ret = bgp_route_match_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, event, + args->errmsg, args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == RMAP_COMPILE_SUCCESS); if (argstr != value) XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); @@ -2440,6 +2447,7 @@ void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish( const char *asn; const char *addr; char *argstr; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -2456,8 +2464,15 @@ void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish( rhc->rhc_rule = "aggregator as"; rhc->rhc_event = RMAP_EVENT_SET_DELETED; - generic_set_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, - args->errmsg, args->errmsg_len); + ret = generic_set_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, args->errmsg, + args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == CMD_SUCCESS); + XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); } /* @@ -2604,6 +2619,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; uint16_t bandwidth; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -2629,9 +2645,14 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( if (yang_dnode_get_bool(args->dnode, "./two-octet-as-specific")) strlcat(str, " non-transitive", sizeof(str)); - generic_set_add(rhc->rhc_rmi, - "extcommunity bandwidth", str, - args->errmsg, args->errmsg_len); + ret = generic_set_add(rhc->rhc_rmi, "extcommunity bandwidth", str, + args->errmsg, args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == CMD_SUCCESS); } /* diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 376172a6f9..4ed8c7c59b 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -88,7 +88,7 @@ struct bgp_dest *bgp_dest_lock_node(struct bgp_dest *dest) const char *bgp_dest_get_prefix_str(struct bgp_dest *dest) { const struct prefix *p = NULL; - char str[PREFIX_STRLEN] = {0}; + static char str[PREFIX_STRLEN] = {0}; p = bgp_dest_get_prefix(dest); if (p) diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h index 303e06c9c9..91a190722b 100644 --- a/bgpd/bgp_trace.h +++ b/bgpd/bgp_trace.h @@ -34,7 +34,11 @@ #include <lttng/tracepoint.h> #include "bgpd/bgpd.h" +#include "bgpd/bgp_attr.h" #include "lib/stream.h" +#include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_evpn_mh.h" + /* clang-format off */ @@ -243,6 +247,93 @@ TRACEPOINT_EVENT( ) TRACEPOINT_LOGLEVEL(frr_bgp, bgp_dest_unlock, TRACE_INFO) +TRACEPOINT_EVENT( + frr_bgp, + evpn_mac_ip_zsend, + TP_ARGS(int, add, struct bgpevpn *, vpn, + const struct prefix_evpn *, pfx, + struct in_addr, vtep, esi_t *, esi), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(vni_t, vni, vpn->vni) + ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, &pfx->prefix.macip_addr.ip, + sizeof(struct ipaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mac_ip_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_bum_vtep_zsend, + TP_ARGS(int, add, struct bgpevpn *, vpn, + const struct prefix_evpn *, pfx), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(vni_t, vni, vpn->vni) + ctf_integer_network_hex(unsigned int, vtep, + pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_bum_vtep_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_vtep_zsend, + TP_ARGS(bool, add, struct bgp_evpn_es *, es, + struct bgp_evpn_es_vtep *, es_vtep), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_string(esi, es->esi_str) + ctf_string(vtep, es_vtep->vtep_str) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_vtep_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nhg_zsend, + TP_ARGS(bool, add, bool, type_v4, uint32_t, nhg_id, + struct bgp_evpn_es_vrf *, es_vrf), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_string(type, type_v4 ? "v4" : "v6") + ctf_integer(unsigned int, nhg, nhg_id) + ctf_string(esi, es_vrf->es->esi_str) + ctf_integer(int, vrf, es_vrf->bgp_vrf->vrf_id) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_nhg_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nh_zsend, + TP_ARGS(uint32_t, nhg_id, struct bgp_evpn_es_vtep *, vtep, + struct bgp_evpn_es_vrf *, es_vrf), + TP_FIELDS( + ctf_integer(unsigned int, nhg, nhg_id) + ctf_string(vtep, vtep->vtep_str) + ctf_integer(int, svi, es_vrf->bgp_vrf->l3vni_svi_ifindex) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_nh_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nh_rmac_zsend, + TP_ARGS(bool, add, struct bgp_evpn_nh *, nh), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(int, vrf, nh->bgp_vrf->vrf_id) + ctf_string(nh, nh->nh_str) + ctf_array(unsigned char, rmac, &nh->rmac, + sizeof(struct ethaddr)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_nh_rmac_zsend, TRACE_INFO) /* clang-format on */ #include <lttng/tracepoint-event.h> diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 14f4fb7310..26da38bd7a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7018,12 +7018,10 @@ DEFUN (no_neighbor_interface, DEFUN (neighbor_distribute_list, neighbor_distribute_list_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list <(1-199)|(1300-2699)|WORD> <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list WORD <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") @@ -7051,24 +7049,20 @@ DEFUN (neighbor_distribute_list, ALIAS_HIDDEN( neighbor_distribute_list, neighbor_distribute_list_hidden_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list <(1-199)|(1300-2699)|WORD> <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list WORD <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") DEFUN (no_neighbor_distribute_list, no_neighbor_distribute_list_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list <(1-199)|(1300-2699)|WORD> <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list WORD <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") @@ -7094,11 +7088,9 @@ DEFUN (no_neighbor_distribute_list, ALIAS_HIDDEN( no_neighbor_distribute_list, no_neighbor_distribute_list_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list <(1-199)|(1300-2699)|WORD> <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list WORD <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a67bb2f8c..0249d53f02 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -112,12 +112,6 @@ static int bgp_read_nexthop_update(ZAPI_CALLBACK_ARGS) return 0; } -static int bgp_read_import_check_update(ZAPI_CALLBACK_ARGS) -{ - bgp_parse_nexthop_update(cmd, vrf_id); - return 0; -} - /* Set or clear interface on which unnumbered neighbor is configured. This * would in turn cause BGP to initiate or turn off IPv6 RAs on this * interface. @@ -338,8 +332,11 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS) static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) { + struct listnode *node, *nnode; struct connected *ifc; + struct peer *peer; struct bgp *bgp; + struct prefix *addr; bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -356,6 +353,35 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) bgp_connected_delete(bgp, ifc); } + addr = ifc->address; + + if (bgp) { + /* + * When we are using the v6 global as part of the peering + * nexthops and we are removing it, then we need to + * clear the peer data saved for that nexthop and + * cause a re-announcement of the route. Since + * we do not want the peering to bounce. + */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + afi_t afi; + safi_t safi; + + if (addr->family == AF_INET) + continue; + + if (!IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) + && memcmp(&peer->nexthop.v6_global, + &addr->u.prefix6, 16) + == 0) { + memset(&peer->nexthop.v6_global, 0, 16); + FOREACH_AFI_SAFI (afi, safi) + bgp_announce_route(peer, afi, safi, + true); + } + } + } + connected_free(&ifc); return 0; @@ -3185,7 +3211,6 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient->redistribute_route_add = zebra_read_route; zclient->redistribute_route_del = zebra_read_route; zclient->nexthop_update = bgp_read_nexthop_update; - zclient->import_check_update = bgp_read_import_check_update; zclient->fec_update = bgp_read_fec_update; zclient->local_es_add = bgp_zebra_process_local_es_add; zclient->local_es_del = bgp_zebra_process_local_es_del; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ec91e7e229..b191029d2f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2156,7 +2156,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi) CAPABILITY_ACTION_SET); if (peer->afc_recv[afi][safi]) { peer->afc_nego[afi][safi] = 1; - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, + false); } } else { peer->last_reset = PEER_DOWN_AF_ACTIVATE; @@ -4142,7 +4143,7 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, SUBGRP_STATUS_FORCE_UPDATES); update_group_adjust_peer(paf); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } } @@ -5058,7 +5059,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, if (peer_established(peer) && peer->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); bgp_default_originate(peer, afi, safi, 0); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Skip peer-group mechanics for regular peers. */ @@ -5095,7 +5096,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, update_group_adjust_peer( peer_af_find(member, afi, safi)); bgp_default_originate(member, afi, safi, 0); - bgp_announce_route(member, afi, safi); + bgp_announce_route(member, afi, safi, false); } } @@ -5134,7 +5135,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) if (peer_established(peer) && peer->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); bgp_default_originate(peer, afi, safi, 1); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Skip peer-group mechanics for regular peers. */ @@ -5165,7 +5166,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) if (peer_established(member) && member->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(member, afi, safi)); bgp_default_originate(member, afi, safi, 1); - bgp_announce_route(member, afi, safi); + bgp_announce_route(member, afi, safi, false); } } @@ -5213,7 +5214,7 @@ static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi, if (outbound) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); if (peer_established(peer)) - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } else { if (!peer_established(peer)) return; @@ -6266,7 +6267,8 @@ static void peer_distribute_update(struct access_list *access) for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { if (access->name) - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + update_group_policy_update(bgp, + BGP_POLICY_DISTRIBUTE_LIST, access->name, 0, 0); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { FOREACH_AFI_SAFI (afi, safi) { @@ -7479,7 +7481,7 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi, UNSET_FLAG(paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { @@ -7882,8 +7884,7 @@ struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, json_no, JSON_C_TO_STRING_PRETTY)); json_object_free(json_no); } else - vty_out(vty, "No such neighbor in %s\n", - bgp->name_pretty); + vty_out(vty, "No such neighbor in this view/vrf\n"); return NULL; } diff --git a/configure.ac b/configure.ac index f792b1c652..c5e5d64aa0 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ([2.69]) -AC_INIT([frr], [8.1-dev], [https://github.com/frrouting/frr/issues]) +AC_INIT([frr], [8.2-dev], [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST([PACKAGE_URL]) PACKAGE_FULLNAME="FRRouting" @@ -797,6 +797,7 @@ fi # AS_IF([test "$host" = "$build"], [ + AM_PATH_PYTHON([3]) AC_CHECK_HEADER([gelf.h], [], [ AC_MSG_ERROR([libelf headers are required for building clippy. (Host only when cross-compiling.)]) ]) diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index c52d210ee5..b4f6ec521c 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -130,12 +130,42 @@ And create ``frr`` user and ``frrvty`` group as follows: Executing Tests --------------- +Configure your sudo environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topotests must be run as root. Normally this will be accomplished through the +use of the ``sudo`` command. In order for topotests to be able to open new +windows (either XTerm or byobu/screen/tmux windows) certain environment +variables must be passed through the sudo command. One way to do this is to +specify the :option:`-E` flag to ``sudo``. This will carry over most if not all +your environment variables include ``PATH``. For example: + +.. code:: shell + + sudo -E python3 -m pytest -s -v + +If you do not wish to use :option:`-E` (e.g., to avoid ``sudo`` inheriting +``PATH``) you can modify your `/etc/sudoers` config file to specifically pass +the environment variables required by topotests. Add the following commands to +your ``/etc/sudoers`` config file. + +.. code:: shell + + Defaults env_keep="TMUX" + Defaults env_keep+="TMUX_PANE" + Defaults env_keep+="STY" + Defaults env_keep+="DISPLAY" + +If there was already an ``env_keep`` configuration there be sure to use the +``+=`` rather than ``=`` on the first line above as well. + + Execute all tests in distributed test mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: shell - py.test -s -v -nauto --dist=loadfile + sudo -E pytest -s -v -nauto --dist=loadfile The above command must be executed from inside the topotests directory. @@ -167,7 +197,7 @@ the run. Here we see that 4 tests have failed. We an dig deeper by displaying the captured logs and errors. First let's redisplay the results enumerated by adding -the ``-E`` flag +the :option:`-E` flag .. code:: shell @@ -353,6 +383,12 @@ be run within ``tmux`` (or ``screen``)_, as ``gdb``, the shell or ``vtysh`` will be launched using that windowing program, otherwise ``xterm`` will be attempted to launch the given programs. +NOTE: you must run the topotest (pytest) such that your DISPLAY, STY or TMUX +environment variables are carried over. You can do this by passing the +:option:`-E` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to +automatically pass that environment variable through to the ``sudo`` +environment. + .. _screen: https://www.gnu.org/software/screen/ .. _tmux: https://github.com/tmux/tmux/wiki @@ -364,7 +400,7 @@ One can have a debugging CLI invoked on test failures by specifying the .. code:: shell - pytest --cli-on-error all-protocol-startup + sudo -E pytest --cli-on-error all-protocol-startup The debugging CLI can run shell or vtysh commands on any combination of routers It can also open shells or vtysh in their own windows for any combination of @@ -415,7 +451,7 @@ Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``. .. code:: shell - pytest --vtysh=rt1,rt2 all-protocol-startup + sudo -E pytest --vtysh=rt1,rt2 all-protocol-startup Debugging with GDB """""""""""""""""" @@ -436,7 +472,7 @@ Here's an example of launching ``zebra`` and ``bgpd`` inside ``gdb`` on router .. code:: shell - pytest --gdb-routers=r1 \ + sudo -E pytest --gdb-routers=r1 \ --gdb-daemons=bgpd,zebra \ --gdb-breakpoints=nb_config_diff \ all-protocol-startup @@ -453,7 +489,7 @@ memleak detection is enabled. .. code:: shell - pytest --valgrind-memleaks all-protocol-startup + sudo -E pytest --valgrind-memleaks all-protocol-startup .. _topotests_docker: @@ -555,21 +591,21 @@ top level directory of topotest: $ # Change to the top level directory of topotests. $ cd path/to/topotests $ # Tests must be run as root, since micronet requires it. - $ sudo pytest + $ sudo -E pytest In order to run a specific test, you can use the following command: .. code:: shell $ # running a specific topology - $ sudo pytest ospf-topo1/ + $ sudo -E pytest ospf-topo1/ $ # or inside the test folder $ cd ospf-topo1 - $ sudo pytest # to run all tests inside the directory - $ sudo pytest test_ospf_topo1.py # to run a specific test + $ sudo -E pytest # to run all tests inside the directory + $ sudo -E pytest test_ospf_topo1.py # to run a specific test $ # or outside the test folder $ cd .. - $ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one + $ sudo -E pytest ospf-topo1/test_ospf_topo1.py # to run a specific one The output of the tested daemons will be available at the temporary folder of your machine: @@ -588,7 +624,7 @@ You can also run memory leak tests to get reports: .. code:: shell $ # Set the environment variable to apply to a specific test... - $ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py + $ sudo -E env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py $ # ...or apply to all tests adding this line to the configuration file $ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini $ # You can also use your editor @@ -626,12 +662,12 @@ Some things to keep in mind: - Using sleep is almost never appropriate. As an example: if the test resets the peers in BGP, the test should look for the peers re-converging instead of just sleeping an arbitrary amount of time and continuing on. See - `verify_bgp_convergence` as a good example of this. In particular look at it's - use of the `@retry` decorator. If you are having troubles figuring out what to - look for, please do not be afraid to ask. + ``verify_bgp_convergence`` as a good example of this. In particular look at + it's use of the ``@retry`` decorator. If you are having troubles figuring out + what to look for, please do not be afraid to ask. - Don't duplicate effort. There exists many protocol utility functions that can - be found in their eponymous module under `tests/topotests/lib/` (e.g., - `ospf.py`) + be found in their eponymous module under ``tests/topotests/lib/`` (e.g., + ``ospf.py``) @@ -827,11 +863,11 @@ that using the following example commands: .. code:: shell $ # Running your bootstraped topology - $ sudo pytest -s --topology-only new-topo/test_new_topo.py + $ sudo -E pytest -s --topology-only new-topo/test_new_topo.py $ # Running the test_template.py topology - $ sudo pytest -s --topology-only example-test/test_template.py + $ sudo -E pytest -s --topology-only example-test/test_template.py $ # Running the ospf_topo1.py topology - $ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py + $ sudo -E pytest -s --topology-only ospf-topo1/test_ospf_topo1.py Parameters explanation: @@ -851,7 +887,7 @@ output: .. code:: shell - frr/tests/topotests# sudo pytest -s --topology-only ospf_topo1/test_ospf_topo1.py + frr/tests/topotests# sudo -E pytest -s --topology-only ospf_topo1/test_ospf_topo1.py ============================= test session starts ============================== platform linux -- Python 3.9.2, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 rootdir: /home/chopps/w/frr/tests/topotests, configfile: pytest.ini @@ -1011,8 +1047,8 @@ Example: # topology build code ... -- pytest setup/teardown fixture to start the topology and supply `tgen` argument - to tests. +- pytest setup/teardown fixture to start the topology and supply ``tgen`` + argument to tests. .. code:: py diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 04a56587ce..e52ec056ad 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -98,6 +98,16 @@ March/July/November. Walking backwards from this date: ``dev/MAJOR.MINOR`` at this point) and a ``rc1`` release candidate is tagged. Master is unfrozen and new features may again proceed. + Part of unfreezing master is editing the ``AC_INIT`` statement in + :file:`configure.ac` to reflect the new development version that master + now refers to. This is accompanied by a ``frr-X.Y-dev`` tag on master, + which should always be on the first commit on master *after* the stable + branch was forked (even if that is not the edit to ``AC_INIT``; it's more + important to have it on the very first commit on master after the fork.) + + (The :file:`configure.ac` edit and tag push are considered git housekeeping + and are pushed directly to ``master``, not through a PR.) + - 2 weeks earlier, a ``rc2`` release candidate is tagged. - on release date, the branch is renamed to ``stable/MAJOR.MINOR``. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 5c9d96e32b..5fcddafaaa 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2145,7 +2145,7 @@ Numbered Community Lists When number is used for BGP community list name, the number has special meanings. Community list number in the range from 1 and 99 is standard community list. Community list number in the range from 100 -to 199 is expanded community list. These community lists are called +to 500 is expanded community list. These community lists are called as numbered community lists. On the other hand normal community lists is called as named community lists. @@ -2154,10 +2154,10 @@ is called as named community lists. This command defines a new community list. The argument to (1-99) defines the list identifier. -.. clicmd:: bgp community-list (100-199) permit|deny COMMUNITY +.. clicmd:: bgp community-list (100-500) permit|deny COMMUNITY This command defines a new expanded community list. The argument to - (100-199) defines the list identifier. + (100-500) defines the list identifier. .. _bgp-community-alias: @@ -3540,6 +3540,10 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. The ``received-routes`` keyword displays all routes belonging to this address-family (prior to inbound policy) that were received by this peer. +.. clicmd:: show bgp [<view|vrf> VIEWVRFNAME] [afi] [safi] neighbors PEER received prefix-filter [json] + + Display Address Prefix ORFs received from this peer. + .. clicmd:: show bgp [afi] [safi] [all] dampening dampened-paths [wide|json] Display paths suppressed due to dampening of the selected afi and safi diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 66f8fd5678..4a711a8feb 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -394,10 +394,6 @@ Known limitations: clear the Node flag that is set by default for Prefix-SIDs associated to loopback addresses. This option is necessary to configure Anycast-SIDs. -.. clicmd:: show isis segment-routing prefix-sids - - Show detailed information about all learned Segment Routing Prefix-SIDs. - .. clicmd:: show isis segment-routing nodes Show detailed information about all learned Segment Routing Nodes. diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index d823c5d5b5..0b718fcdf2 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -85,6 +85,11 @@ OSPF6 router change to take effect, user can use this cli instead of restarting the ospf6d daemon. +.. clicmd:: clear ipv6 ospf6 [vrf NAME] interface [IFNAME] + + This command restarts the interface state machine for all interfaces in the + VRF or only for the specific interface if ``IFNAME`` is specified. + ASBR Summarisation Support in OSPFv3 ==================================== @@ -476,9 +481,10 @@ The following debug commands are supported: Toggle OSPFv3 ASBR debugging messages. -.. clicmd:: debug ospf6 border-routers +.. clicmd:: debug ospf6 border-routers {router-id [A.B.C.D] | area-id [A.B.C.D]} - Toggle OSPFv3 border router debugging messages. + Toggle OSPFv3 border router debugging messages. This can be specified for a + router with specific Router-ID/Area-ID. .. clicmd:: debug ospf6 flooding diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 0122e2ac75..26675c27fd 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -691,13 +691,12 @@ Redistribution the 'always' keyword is given then the default is always advertised, even when there is no default present in the routing table. -.. clicmd:: distribute-list NAME out (kernel|connected|static|rip|ospf - - .. _ospf-distribute-list: +.. clicmd:: distribute-list NAME out <kernel|connected|static|rip|isis|bgp|eigrp|nhrp|table|vnc|babel|openfabric> + Apply the access-list filter, NAME, to redistributed routes of the given - type before allowing the routes to redistributed into OSPF + type before allowing the routes to be redistributed into OSPF (:ref:`ospf redistribution <ospf-redistribute>`). .. clicmd:: default-metric (0-16777214) @@ -954,8 +953,6 @@ Router Information Show Router Capabilities PCE parameters. -.. _debugging-ospf: - Segment Routing =============== @@ -1042,6 +1039,8 @@ TI-LFA requires a proper Segment Routing configuration. Note that so far only P2P interfaces are supported. +.. _debugging-ospf: + Debugging OSPF ============== diff --git a/doc/user/static.rst b/doc/user/static.rst index 200d187370..05847ba394 100644 --- a/doc/user/static.rst +++ b/doc/user/static.rst @@ -33,25 +33,51 @@ Static Route Commands ===================== Static routing is a very fundamental feature of routing technology. It defines -a static prefix and gateway. +a static prefix and gateway, with several possible forms. -.. clicmd:: ip route NETWORK GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME +.. clicmd:: ip route NETWORK GATEWAY [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] -.. clicmd:: ipv6 route NETWORK from SRCPREFIX GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME +.. clicmd:: ip route NETWORK IFNAME [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ip route NETWORK GATEWAY IFNAME [DISTANCE] [onlink] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ip route NETWORK (Null0|blackhole|reject) [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] GATEWAY [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] IFNAME [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] GATEWAY IFNAME [DISTANCE] [onlink] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] (Null0|blackhole|reject) [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] NETWORK is destination prefix with a valid v4 or v6 network based upon - initial form of the command. GATEWAY is gateway for the prefix it currently - must match the v4 or v6 route type specified at the start of the command. - GATEWAY can also be treated as an interface name. If the interface name - is ``null0`` then zebra installs a blackhole route. TABLENO - is an optional parameter for namespaces that allows you to create the - route in a specified table associated with the vrf namespace. table will - be rejected if you are not using namespace based vrfs. ``nexthop-vrf`` - allows you to create a leaked route with a nexthop in the specified VRFNAME - vrf VRFNAME allows you to create the route in a specified vrf. - ``nexthop-vrf`` cannot be currently used with namespace based vrfs - currently as well. - The v6 variant allows the installation of a static source-specific route + initial form of the command. + + GATEWAY is the IP address to use as next-hop for the prefix. Currently, it must match + the v4 or v6 route type specified at the start of the command. + + IFNAME is the name of the interface to use as next-hop. If only IFNAME is specified + (without GATEWAY), a connected route will be created. + + When both IFNAME and GATEWAY are specified together, it binds the route to the specified + interface. In this case, it is also possible to specify ``onlink`` to force the kernel + to consider the next-hop as "on link" on the given interface. + + Alternatively, the gateway can be specified as ``Null0`` or ``blackhole`` to create a blackhole + route that drops all traffic. It can also be specified as ``reject`` to create an unreachable + route that rejects traffic with ICMP "Destination Unreachable" messages. + + TABLENO is an optional parameter for namespaces that allows you to create the + route in a specified table associated with the vrf namespace. ``table`` will + be rejected if you are not using namespace based vrfs. + + ``vrf`` VRFNAME allows you to create the route in a specified vrf. + + ``nexthop-vrf`` VRFNAME allows you to create a leaked route with a nexthop in the + specified VRFNAME. ``nexthop-vrf`` cannot be currently used with namespace based vrfs. + + The IPv6 variant allows the installation of a static source-specific route with the SRCPREFIX sub command. These routes are currently supported on Linux operating systems only, and perform AND matching on packet's destination and source addresses in the kernel's forwarding path. Note diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 3a9cd11055..5eb97ff06d 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -473,6 +473,21 @@ be updated with the new name. To illustrate, if you want to recompile with ./configure --with-defaultvrfname=global +.. _zebra-table-allocation: + +Table Allocation +================ + +Some services like BGP flowspec allocate routing tables to perform policy +routing based on netfilter criteria and IP rules. In order to avoid +conflicts between VRF allocated routing tables and those services, Zebra +proposes to define a chunk of routing tables to use by other services. + +Allocation configuration can be done like below, with the range of the +chunk of routing tables to be used by the given service. + +.. clicmd:: ip table range <STARTTABLENO> <ENDTABLENO> + .. _zebra-ecmp: ECMP diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile index 032db8b8ed..b9fe385c3a 100644 --- a/docker/ubuntu20-ci/Dockerfile +++ b/docker/ubuntu20-ci/Dockerfile @@ -11,7 +11,6 @@ RUN apt update && \ install-info build-essential libsnmp-dev perl \ libcap-dev python2 libelf-dev \ sudo gdb curl iputils-ping time \ - libgrpc++-dev libgrpc-dev protobuf-compiler-grpc \ lua5.3 liblua5.3-dev \ net-tools iproute2 && \ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output /tmp/get-pip.py && \ @@ -61,7 +60,6 @@ RUN cd ~/frr && \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ --enable-vtysh \ - --enable-grpc \ --enable-pimd \ --enable-sharpd \ --enable-multipath=64 \ diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c index 8f80b78d20..bb0cf51bd8 100644 --- a/eigrpd/eigrp_filter.c +++ b/eigrpd/eigrp_filter.c @@ -203,9 +203,8 @@ void eigrp_distribute_update(struct distribute_ctx *ctx, /* Cancel GR scheduled */ thread_cancel(&(ei->t_distribute)); /* schedule Graceful restart for interface in 10sec */ - e->t_distribute = NULL; thread_add_timer(master, eigrp_distribute_timer_interface, ei, 10, - &e->t_distribute); + &ei->t_distribute); } /* @@ -263,7 +262,6 @@ int eigrp_distribute_timer_process(struct thread *thread) struct eigrp *eigrp; eigrp = THREAD_ARG(thread); - eigrp->t_distribute = NULL; /* execute GR for whole process */ eigrp_update_send_process_GR(eigrp, EIGRP_GR_FILTER, NULL); diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index e3680b31a3..2ff8fc5f39 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -86,7 +86,6 @@ int eigrp_hello_timer(struct thread *thread) struct eigrp_interface *ei; ei = THREAD_ARG(thread); - ei->t_hello = NULL; if (IS_DEBUG_EIGRP(0, TIMERS)) zlog_debug("Start Hello Timer (%s) Expire [%u]", IF_NAME(ei), @@ -96,7 +95,6 @@ int eigrp_hello_timer(struct thread *thread) eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL); /* Hello timer set. */ - ei->t_hello = NULL; thread_add_timer(master, eigrp_hello_timer, ei, ei->params.v_hello, &ei->t_hello); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 02e943043f..28987b4af6 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -265,7 +265,7 @@ int eigrp_if_up(struct eigrp_interface *ei) /* Set multicast memberships appropriately for new state. */ eigrp_if_set_multicast(ei); - thread_add_event(master, eigrp_hello_timer, ei, (1), NULL); + thread_add_event(master, eigrp_hello_timer, ei, (1), &ei->t_hello); /*Prepare metrics*/ metric.bandwidth = eigrp_bandwidth_to_scaled(ei->params.bandwidth); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 39e384c121..529d94567d 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -340,8 +340,6 @@ int eigrp_write(struct thread *thread) #endif /* WANT_EIGRP_WRITE_FRAGMENT */ #define EIGRP_WRITE_IPHL_SHIFT 2 - eigrp->t_write = NULL; - node = listhead(eigrp->oi_write_q); assert(node); ei = listgetdata(node); @@ -470,7 +468,6 @@ out: /* If packets still remain in queue, call write thread. */ if (!list_isempty(eigrp->oi_write_q)) { - eigrp->t_write = NULL; thread_add_write(master, eigrp_write, eigrp, eigrp->fd, &eigrp->t_write); } @@ -497,7 +494,6 @@ int eigrp_read(struct thread *thread) eigrp = THREAD_ARG(thread); /* prepare for next packet. */ - eigrp->t_read = NULL; thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); stream_reset(eigrp->ibuf); @@ -1013,7 +1009,6 @@ int eigrp_unack_packet_retrans(struct thread *thread) return eigrp_retrans_count_exceeded(ep, nbr); /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; thread_add_timer(master, eigrp_unack_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); @@ -1049,7 +1044,6 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread) return eigrp_retrans_count_exceeded(ep, nbr); /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; thread_add_timer(master, eigrp_unack_multicast_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 90913a5b28..67fab89271 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -858,12 +858,10 @@ ALIAS(no_match_interface, no_match_interface_val_cmd, "no match interface WORD", DEFUN (match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop ((1-199)|(1300-2699)|WORD)", + "match ip next-hop WORD", MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { return eigrp_route_match_add(vty, vty->index, "ip next-hop", argv[0]); @@ -886,10 +884,8 @@ DEFUN (no_match_ip_next_hop, } ALIAS(no_match_ip_next_hop, no_match_ip_next_hop_val_cmd, - "no match ip next-hop ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR + "no match ip next-hop WORD", NO_STR MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") DEFUN (match_ip_next_hop_prefix_list, @@ -931,12 +927,10 @@ ALIAS(no_match_ip_next_hop_prefix_list, DEFUN (match_ip_address, match_ip_address_cmd, - "match ip address ((1-199)|(1300-2699)|WORD)", + "match ip address WORD", MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { return eigrp_route_match_add(vty, vty->index, "ip address", argv[0]); @@ -958,10 +952,8 @@ DEFUN (no_match_ip_address, } ALIAS(no_match_ip_address, no_match_ip_address_val_cmd, - "no match ip address ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR + "no match ip address WORD", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") DEFUN (match_ip_address_prefix_list, diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 0dc509706c..8a9eea8a79 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -917,12 +917,10 @@ int eigrp_update_send_GR_thread(struct thread *thread) /* get argument from thread */ nbr = THREAD_ARG(thread); /* remove this thread pointer */ - nbr->t_nbr_send_gr = NULL; /* if there is packet waiting in queue, * schedule this thread again with small delay */ if (nbr->retrans_queue->count > 0) { - nbr->t_nbr_send_gr = NULL; thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10, &nbr->t_nbr_send_gr); return 0; @@ -934,7 +932,6 @@ int eigrp_update_send_GR_thread(struct thread *thread) /* if it wasn't last chunk, schedule this thread again */ if (nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) { thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; } return 0; @@ -1003,7 +1000,6 @@ void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type, nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST; /* execute packet sending in thread */ thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; } /** diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 1030154907..84d4f6aeeb 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -171,7 +171,6 @@ static struct eigrp *eigrp_new(uint16_t as, vrf_id_t vrf_id) eigrp->ibuf = stream_new(EIGRP_PACKET_MAX_LEN + 1); - eigrp->t_read = NULL; thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); eigrp->oi_write_q = list_new(); diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 20651706d3..2937df992c 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -258,7 +258,6 @@ static int fabricd_initial_sync_timeout(struct thread *thread) f->initial_sync_circuit->interface->name); f->initial_sync_state = FABRICD_SYNC_PENDING; f->initial_sync_circuit = NULL; - f->initial_sync_timeout = NULL; return 0; } @@ -403,7 +402,6 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) static int fabricd_tier_set_timer(struct thread *thread) { struct fabricd *f = THREAD_ARG(thread); - f->tier_set_timer = NULL; fabricd_set_tier(f, f->tier_pending); return 0; @@ -413,7 +411,6 @@ static int fabricd_tier_calculation_cb(struct thread *thread) { struct fabricd *f = THREAD_ARG(thread); uint8_t tier = ISIS_TIER_UNDEFINED; - f->tier_calculation_timer = NULL; tier = fabricd_calculate_fabric_tier(f->area); if (tier == ISIS_TIER_UNDEFINED) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 70ec66fd7f..f48b142b1a 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -1330,11 +1330,14 @@ void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-isisd:isis/instance/redistribute */ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd, - "[no] redistribute <ipv4|ipv6>$ip " PROTO_REDIST_STR - "$proto <level-1|level-2>$level [{metric (0-16777215)|route-map WORD}]", + "[no] redistribute <ipv4$ip " PROTO_IP_REDIST_STR "$proto|ipv6$ip " + PROTO_IP6_REDIST_STR "$proto> <level-1|level-2>$level" + "[{metric (0-16777215)|route-map WORD}]", NO_STR REDIST_STR "Redistribute IPv4 routes\n" - "Redistribute IPv6 routes\n" PROTO_REDIST_HELP + PROTO_IP_REDIST_HELP + "Redistribute IPv6 routes\n" + PROTO_IP6_REDIST_HELP "Redistribute into level-1\n" "Redistribute into level-2\n" "Metric for redistributed routes\n" diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2f5e490da1..45d69bc352 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -543,12 +543,13 @@ void isis_redist_area_finish(struct isis_area *area) #ifdef FABRICD DEFUN (isis_redistribute, isis_redistribute_cmd, - "redistribute <ipv4|ipv6> " PROTO_REDIST_STR + "redistribute <ipv4 " PROTO_IP_REDIST_STR "|ipv6 " PROTO_IP6_REDIST_STR ">" " [{metric (0-16777215)|route-map WORD}]", REDIST_STR "Redistribute IPv4 routes\n" + PROTO_IP_REDIST_HELP "Redistribute IPv6 routes\n" - PROTO_REDIST_HELP + PROTO_IP6_REDIST_HELP "Metric for redistributed routes\n" "ISIS default metric\n" "Route map reference\n" @@ -599,12 +600,13 @@ DEFUN (isis_redistribute, DEFUN (no_isis_redistribute, no_isis_redistribute_cmd, - "no redistribute <ipv4|ipv6> " PROTO_REDIST_STR, + "no redistribute <ipv4 " PROTO_IP_REDIST_STR "|ipv6 " PROTO_IP6_REDIST_STR ">", NO_STR REDIST_STR "Redistribute IPv4 routes\n" + PROTO_IP_REDIST_HELP "Redistribute IPv6 routes\n" - PROTO_REDIST_HELP) + PROTO_IP6_REDIST_HELP) { int idx_afi = 2; int idx_protocol = 3; diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 45e89897ff..5718b48b9d 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1840,7 +1840,6 @@ static int isis_run_spf_cb(struct thread *thread) int have_run = 0; XFREE(MTYPE_ISIS_SPF_RUN, run); - area->spf_timer[level - 1] = NULL; if (!(area->is_type & level)) { if (IS_DEBUG_SPF_EVENTS) diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index c7266152b7..d3da5b9d39 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -119,7 +119,6 @@ static int tx_queue_send_event(struct thread *thread) struct isis_tx_queue_entry *e = THREAD_ARG(thread); struct isis_tx_queue *queue = e->queue; - e->retry = NULL; thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry); if (e->is_retry) diff --git a/isisd/isisd.h b/isisd/isisd.h index 64fbf78a07..3febda1d87 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -46,7 +46,11 @@ static const bool fabricd = true; #define PROTO_NAME "openfabric" #define PROTO_HELP "OpenFabric routing protocol\n" #define PROTO_REDIST_STR FRR_REDIST_STR_FABRICD +#define PROTO_IP_REDIST_STR FRR_IP_REDIST_STR_FABRICD +#define PROTO_IP6_REDIST_STR FRR_IP6_REDIST_STR_FABRICD #define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_FABRICD +#define PROTO_IP_REDIST_HELP FRR_IP_REDIST_HELP_STR_FABRICD +#define PROTO_IP6_REDIST_HELP FRR_IP6_REDIST_HELP_STR_FABRICD #define ROUTER_NODE OPENFABRIC_NODE #else static const bool fabricd = false; @@ -54,7 +58,11 @@ static const bool fabricd = false; #define PROTO_NAME "isis" #define PROTO_HELP "IS-IS routing protocol\n" #define PROTO_REDIST_STR FRR_REDIST_STR_ISISD +#define PROTO_IP_REDIST_STR FRR_IP_REDIST_STR_ISISD +#define PROTO_IP6_REDIST_STR FRR_IP6_REDIST_STR_ISISD #define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_ISISD +#define PROTO_IP_REDIST_HELP FRR_IP_REDIST_HELP_STR_ISISD +#define PROTO_IP6_REDIST_HELP FRR_IP6_REDIST_HELP_STR_ISISD #define ROUTER_NODE ISIS_NODE extern void isis_cli_init(void); #endif @@ -248,7 +256,6 @@ void isis_terminate(void); void isis_master_init(struct thread_master *master); void isis_vrf_link(struct isis *isis, struct vrf *vrf); void isis_vrf_unlink(struct isis *isis, struct vrf *vrf); -void isis_global_instance_create(const char *vrf_name); struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id); struct isis *isis_lookup_by_vrfname(const char *vrfname); struct isis *isis_lookup_by_sysid(const uint8_t *sysid); diff --git a/ldpd/accept.c b/ldpd/accept.c index 9bba0f5ddd..e8d3976ee9 100644 --- a/ldpd/accept.c +++ b/ldpd/accept.c @@ -58,7 +58,6 @@ accept_add(int fd, int (*cb)(struct thread *), void *arg) av->arg = arg; LIST_INSERT_HEAD(&accept_queue.queue, av, entry); - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); log_debug("%s: accepting on fd %d", __func__, fd); @@ -86,7 +85,6 @@ accept_pause(void) { log_debug(__func__); accept_unarm(); - accept_queue.evt = NULL; thread_add_timer(master, accept_timeout, NULL, 1, &accept_queue.evt); } @@ -105,7 +103,6 @@ accept_arm(void) { struct accept_ev *av; LIST_FOREACH(av, &accept_queue.queue, entry) { - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); } } @@ -122,7 +119,6 @@ static int accept_cb(struct thread *thread) { struct accept_ev *av = THREAD_ARG(thread); - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); av->accept_cb(thread); diff --git a/ldpd/interface.c b/ldpd/interface.c index 3e9f2fa991..5e04eab1b3 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -471,7 +471,6 @@ static void if_start_hello_timer(struct iface_af *ia) { thread_cancel(&ia->hello_timer); - ia->hello_timer = NULL; thread_add_timer(master, if_hello_timer, ia, if_get_hello_interval(ia), &ia->hello_timer); } diff --git a/ldpd/lde.c b/ldpd/lde.c index 2d35d097a1..babadc461f 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -145,7 +145,6 @@ lde(void) fatal(NULL); imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = lde_dispatch_parent; - iev_main->ev_read = NULL; thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd, &iev_main->ev_read); iev_main->handler_write = ldp_write_handler; @@ -555,7 +554,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); imsg_init(&iev_ldpe->ibuf, fd); iev_ldpe->handler_read = lde_dispatch_imsg; - iev_ldpe->ev_read = NULL; thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd, &iev_ldpe->ev_read); iev_ldpe->handler_write = ldp_write_handler; diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 0f91f49920..33bb6c0fc7 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -1072,7 +1072,6 @@ void lde_gc_start_timer(void) { thread_cancel(&gc_timer); - gc_timer = NULL; thread_add_timer(master, lde_gc_timer, NULL, LDE_GC_INTERVAL, &gc_timer); } diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index b65ebf6f55..9d3d1a606e 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -253,14 +253,12 @@ DEFPY (ldp_allow_broken_lsps, DEFPY (ldp_discovery_targeted_hello_accept, ldp_discovery_targeted_hello_accept_cmd, - "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]", + "[no] discovery targeted-hello accept [from WORD$from_acl]", NO_STR "Configure discovery parameters\n" "LDP Targeted Hellos\n" "Accept and respond to targeted hellos\n" "Access list to specify acceptable targeted hello source\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_targeted_hello_accept(vty, no, from_acl)); @@ -290,18 +288,14 @@ DEFPY (ldp_discovery_transport_address_ipv6, DEFPY (ldp_label_local_advertise, ldp_label_local_advertise_cmd, - "[no] label local advertise [{to <(1-199)|(1300-2699)|WORD>$to_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}]", + "[no] label local advertise [{to WORD$to_acl|for WORD$for_acl}]", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure outbound label advertisement control\n" "IP Access-list specifying controls on LDP Peers\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_advertise(vty, no, to_acl, for_acl)); @@ -309,15 +303,13 @@ DEFPY (ldp_label_local_advertise, DEFPY (ldp_label_local_advertise_explicit_null, ldp_label_local_advertise_explicit_null_cmd, - "[no] label local advertise explicit-null [for <(1-199)|(1300-2699)|WORD>$for_acl]", + "[no] label local advertise explicit-null [for WORD$for_acl]", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure outbound label advertisement control\n" "Configure explicit-null advertisement\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_expnull(vty, no, for_acl)); @@ -325,15 +317,13 @@ DEFPY (ldp_label_local_advertise_explicit_null, DEFPY (ldp_label_local_allocate, ldp_label_local_allocate_cmd, - "[no] label local allocate <host-routes$host_routes|for <(1-199)|(1300-2699)|WORD>$for_acl>", + "[no] label local allocate <host-routes$host_routes|for WORD$for_acl>", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure label allocation control\n" "allocate local label for host routes only\n" "IP access-list\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_allocate(vty, no, host_routes, for_acl)); @@ -341,18 +331,14 @@ DEFPY (ldp_label_local_allocate, DEFPY (ldp_label_remote_accept, ldp_label_remote_accept_cmd, - "[no] label remote accept {from <(1-199)|(1300-2699)|WORD>$from_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}", + "[no] label remote accept {from WORD$from_acl|for WORD$for_acl}", NO_STR "Configure label control and policies\n" "Configure remote/peer label control and policies\n" "Configure inbound label acceptance control\n" "Neighbor from whom to accept label advertisement\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_accept(vty, no, from_acl, for_acl)); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 000d1a3301..0ff3238ff9 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -94,10 +94,9 @@ static void ldp_load_module(const char *name) { const char *dir; dir = ldpd_di.module_path ? ldpd_di.module_path : frr_moduledir; - char moderr[256]; struct frrmod_runtime *module; - module = frrmod_load(name, dir, moderr, sizeof(moderr)); + module = frrmod_load(name, dir, NULL,NULL); if (!module) { fprintf(stderr, "%s: failed to load %s", __func__, name); log_warnx("%s: failed to load %s", __func__, name); @@ -244,7 +243,6 @@ main(int argc, char *argv[]) int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2]; int pipe_parent2lde[2], pipe_parent2lde_sync[2]; char *ctl_sock_name; - struct thread *thread = NULL; bool ctl_sock_used = false; snprintf(ctl_sock_path, sizeof(ctl_sock_path), LDPD_SOCKET, @@ -394,7 +392,7 @@ main(int argc, char *argv[]) frr_config_fork(); /* apply configuration */ - thread_add_event(master, ldp_config_fork_apply, NULL, 0, &thread); + thread_add_event(master, ldp_config_fork_apply, NULL, 0, NULL); /* setup pipes to children */ if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL || @@ -404,28 +402,24 @@ main(int argc, char *argv[]) fatal(NULL); imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]); iev_ldpe->handler_read = main_dispatch_ldpe; - iev_ldpe->ev_read = NULL; thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd, &iev_ldpe->ev_read); iev_ldpe->handler_write = ldp_write_handler; imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]); iev_ldpe_sync->handler_read = main_dispatch_ldpe; - iev_ldpe_sync->ev_read = NULL; thread_add_read(master, iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd, &iev_ldpe_sync->ev_read); iev_ldpe_sync->handler_write = ldp_write_handler; imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]); iev_lde->handler_read = main_dispatch_lde; - iev_lde->ev_read = NULL; thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd, &iev_lde->ev_read); iev_lde->handler_write = ldp_write_handler; imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]); iev_lde_sync->handler_read = main_dispatch_lde; - iev_lde_sync->ev_read = NULL; thread_add_read(master, iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd, &iev_lde_sync->ev_read); iev_lde_sync->handler_write = ldp_write_handler; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 428d2ab7b4..fff7ee7c67 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -122,7 +122,6 @@ ldpe(void) fatal(NULL); imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = ldpe_dispatch_main; - iev_main->ev_read = NULL; thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd, &iev_main->ev_read); iev_main->handler_write = ldp_write_handler; @@ -149,7 +148,6 @@ ldpe_init(struct ldpd_init *init) /* This socket must be open before dropping privileges. */ global.pfkeysock = pfkey_init(); if (sysdep.no_pfkey == 0) { - pfkey_ev = NULL; thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, &pfkey_ev); } @@ -377,7 +375,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); imsg_init(&iev_lde->ibuf, fd); iev_lde->handler_read = ldpe_dispatch_lde; - iev_lde->ev_read = NULL; thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd, &iev_lde->ev_read); iev_lde->handler_write = ldp_write_handler; @@ -784,7 +781,6 @@ ldpe_dispatch_pfkey(struct thread *thread) { int fd = THREAD_FD(thread); - pfkey_ev = NULL; thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, &pfkey_ev); @@ -805,13 +801,11 @@ ldpe_setup_sockets(int af, int disc_socket, int edisc_socket, /* discovery socket */ af_global->ldp_disc_socket = disc_socket; - af_global->disc_ev = NULL; thread_add_read(master, disc_recv_packet, &af_global->disc_ev, af_global->ldp_disc_socket, &af_global->disc_ev); /* extended discovery socket */ af_global->ldp_edisc_socket = edisc_socket; - af_global->edisc_ev = NULL; thread_add_read(master, disc_recv_packet, &af_global->edisc_ev, af_global->ldp_edisc_socket, &af_global->edisc_ev); diff --git a/ldpd/packet.c b/ldpd/packet.c index 8735faf3dd..56af16d280 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -141,7 +141,6 @@ disc_recv_packet(struct thread *thread) struct in_addr lsr_id; /* reschedule read */ - *threadp = NULL; thread_add_read(master, disc_recv_packet, threadp, fd, threadp); /* setup buffer */ @@ -425,7 +424,6 @@ session_read(struct thread *thread) uint16_t pdu_len, msg_len, msg_size, max_pdu_len; int ret; - tcp->rev = NULL; thread_add_read(master, session_read, nbr, fd, &tcp->rev); if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos, @@ -745,7 +743,6 @@ tcp_new(int fd, struct nbr *nbr) if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL) fatal(__func__); - tcp->rev = NULL; thread_add_read(master, session_read, nbr, tcp->fd, &tcp->rev); tcp->nbr = nbr; } diff --git a/lib/agentx.c b/lib/agentx.c index 6d4e68d651..5f865ca2b8 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -63,6 +63,8 @@ static int agentx_read(struct thread *t) int flags, new_flags = 0; int nonblock = false; struct listnode *ln = THREAD_ARG(t); + struct thread **thr = listgetdata(ln); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); /* fix for non blocking socket */ @@ -109,7 +111,7 @@ static void agentx_events_update(void) struct timeval timeout = {.tv_sec = 0, .tv_usec = 0}; fd_set fds; struct listnode *ln; - struct thread *thr; + struct thread **thr; int fd, thr_fd; thread_cancel(&timeout_thr); @@ -125,7 +127,7 @@ static void agentx_events_update(void) ln = listhead(events); thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; /* "two-pointer" / two-list simultaneous iteration * ln/thr/thr_fd point to the next existing event listener to hit while @@ -135,20 +137,21 @@ static void agentx_events_update(void) if (thr_fd == fd) { struct listnode *nextln = listnextnode(ln); if (!FD_ISSET(fd, &fds)) { - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); } ln = nextln; thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; } /* need listener, but haven't hit one where it would be */ else if (FD_ISSET(fd, &fds)) { struct listnode *newln; - thr = NULL; - thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); + thr = XCALLOC(MTYPE_TMP, sizeof(struct thread *)); + thread_add_read(agentx_tm, agentx_read, NULL, fd, thr); newln = listnode_add_before(events, ln, thr); - thr->arg = newln; + (*thr)->arg = newln; } } @@ -157,7 +160,8 @@ static void agentx_events_update(void) while (ln) { struct listnode *nextln = listnextnode(ln); thr = listgetdata(ln); - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); ln = nextln; } diff --git a/lib/atomlist.c b/lib/atomlist.c index 8169ba9eb4..3668b083d0 100644 --- a/lib/atomlist.c +++ b/lib/atomlist.c @@ -121,7 +121,7 @@ static void atomlist_del_core(struct atomlist_head *h, memory_order_consume); /* track the beginning of a chain of deleted items - * this is neccessary to make this lock-free; we can + * this is necessary to make this lock-free; we can * complete deletions started by other threads. */ if (!atomptr_l(prevval)) { diff --git a/lib/atomlist.h b/lib/atomlist.h index c795128a34..b0c4da4baa 100644 --- a/lib/atomlist.h +++ b/lib/atomlist.h @@ -100,7 +100,7 @@ static inline bool atomptr_u(atomptr_t val) /* single-linked list, unsorted/arbitrary. * can be used as queue with add_tail / pop * - * all operations are lock-free, but not neccessarily wait-free. this means + * all operations are lock-free, but not necessarily wait-free. this means * that there is no state where the system as a whole stops making process, * but it *is* possible that a *particular* thread is delayed by some time. * @@ -203,7 +203,7 @@ static void bfd_last_update(time_t last_update, char *buf, size_t len) struct tm tm; struct timeval tv; - /* If no BFD satatus update has ever been received, print `never'. */ + /* If no BFD status update has ever been received, print `never'. */ if (last_update == 0) { snprintf(buf, len, "never"); return; diff --git a/lib/buffer.c b/lib/buffer.c index 41b1adc9fc..e976fecc1f 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -59,7 +59,7 @@ struct buffer_data { /* It should always be true that: 0 <= sp <= cp <= size */ /* Default buffer size (used if none specified). It is rounded up to the - next page boundery. */ + next page boundary. */ #define BUFFER_SIZE_DEFAULT 4096 #define BUFFER_DATA_FREE(D) XFREE(MTYPE_BUFFER_DATA, (D)) diff --git a/lib/command.h b/lib/command.h index 8a7c9a2048..e2eec1aac6 100644 --- a/lib/command.h +++ b/lib/command.h @@ -234,7 +234,7 @@ struct cmd_node { /* Argc max counts. */ #define CMD_ARGC_MAX 256 -/* Turn off these macros when uisng cpp with extract.pl */ +/* Turn off these macros when using cpp with extract.pl */ #ifndef VTYSH_EXTRACT_PL /* helper defines for end-user DEFUN* macros */ diff --git a/lib/command_graph.h b/lib/command_graph.h index c20c9874c2..86157f872e 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -79,11 +79,11 @@ enum { CMD_ATTR_NORMAL, CMD_ATTR_YANG, }; -/* Comamand token struct. */ +/* Command token struct. */ struct cmd_token { enum cmd_token_type type; // token type uint8_t attr; // token attributes - bool allowrepeat; // matcher allowed to match token repetively? + bool allowrepeat; // matcher allowed to match token repetitively? uint32_t refcnt; char *text; // token text diff --git a/lib/command_match.h b/lib/command_match.h index fcb333120f..0488cc1a1f 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -68,7 +68,7 @@ enum match_type { * @param[in] vline vectorized input string * @param[out] argv pointer to argument list if successful match, NULL * otherwise. The elements of this list are pointers to struct cmd_token - * and represent the sequence of tokens matched by the inpu. The ->arg + * and represent the sequence of tokens matched by the input. The ->arg * field of each token points to a copy of the input matched on it. These * may be safely deleted or modified. * @param[out] element pointer to matched cmd_element if successful match, diff --git a/lib/command_parse.y b/lib/command_parse.y index 3e2cdc79af..dccd738f31 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -338,7 +338,7 @@ selector: '{' selector_seq_seq '}' varname_token * 1) this allows "at least 1 of" semantics, which are otherwise impossible * 2) this would add a start->end->start loop in the graph that the current * loop-avoidal fails to handle - * just use [{a|b}] if neccessary, that will work perfectly fine, and reason + * just use [{a|b}] if necessary, that will work perfectly fine, and reason * #1 is good enough to keep it this way. */ loopcheck(ctx, &$$); @@ -60,7 +60,7 @@ int db_init(const char *path_fmt, ...) (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE), NULL) != SQLITE_OK) { if (dbp == NULL) { - zlog_warn("%s: failed to open dabatase '%s'", __func__, + zlog_warn("%s: failed to open database '%s'", __func__, path); return -1; } diff --git a/lib/distribute.h b/lib/distribute.h index 83682dea6a..6b3226e8b4 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -29,7 +29,7 @@ extern "C" { #endif -/* Disctirubte list types. */ +/* Distribute list types. */ enum distribute_type { DISTRIBUTE_V4_IN, DISTRIBUTE_V6_IN, diff --git a/lib/ferr.h b/lib/ferr.h index 4e95431cea..c27601f66c 100644 --- a/lib/ferr.h +++ b/lib/ferr.h @@ -34,7 +34,7 @@ extern "C" { /* return type when this error indication stuff is used. * * guaranteed to have boolean evaluation to "false" when OK, "true" when error - * (i.e. can be changed to pointer in the future if neccessary) + * (i.e. can be changed to pointer in the future if necessary) * * For checking, always use "if (value)", nothing else. * Do _NOT_ use any integer constant (!= 0), or sign check (< 0). diff --git a/lib/filter.c b/lib/filter.c index 744ea9c480..3a86fbce93 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -192,7 +192,7 @@ void access_list_delete(struct access_list *access) access_list_free(access); } -/* Insert new access list to list of access_list. Each acceess_list +/* Insert new access list to list of access_list. Each access_list is sorted by the name. */ static struct access_list *access_list_insert(afi_t afi, const char *name) { @@ -387,7 +387,7 @@ void access_list_filter_add(struct access_list *access, struct filter *replace; struct filter *point; - /* Automatic asignment of seq no. */ + /* Automatic assignment of seq no. */ if (filter->seq == -1) filter->seq = filter_new_seq_get(access); @@ -635,15 +635,11 @@ DEFUN (show_ip_access_list, DEFUN (show_ip_access_list_name, show_ip_access_list_name_cmd, - "show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> [json]", + "show ip access-list WORD [json]", SHOW_STR IP_STR "List IP access lists\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" + "IP access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); @@ -669,7 +665,7 @@ DEFUN (show_ipv6_access_list_name, SHOW_STR IPV6_STR "List IPv6 access lists\n" - "IPv6 zebra access-list\n" + "IPv6 access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 45c7544a3b..e424fcf878 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -36,10 +36,7 @@ #endif /* VTYSH_EXTRACT_PL */ #define ACCESS_LIST_STR "Access list entry\n" -#define ACCESS_LIST_LEG_STR "IP standard access list\n" -#define ACCESS_LIST_ELEG_STR "IP extended access list\n" -#define ACCESS_LIST_ELEG_EXT_STR "IP extended access list (expanded range)\n" -#define ACCESS_LIST_ZEBRA_STR "Access list entry\n" +#define ACCESS_LIST_ZEBRA_STR "Access list name\n" #define ACCESS_LIST_SEQ_STR \ "Sequence number of an entry\n" \ "Sequence number\n" @@ -137,7 +134,7 @@ DEFPY_YANG( access_list_std, access_list_std_cmd, "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -214,7 +211,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", NO_STR ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -258,7 +255,7 @@ DEFPY_YANG( access_list_ext, access_list_ext_cmd, "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>", ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "IPv4 address\n" @@ -377,7 +374,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>", NO_STR ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "Any Internet Protocol\n" diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index ea9c828f7c..e572558de1 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -19,7 +19,7 @@ /* * IF YOU MODIFY THIS FILE PLEASE RUN `make check` and ensure that - * the test_zmq.c unit test is still working. There are dependancies + * the test_zmq.c unit test is still working. There are dependencies * between the two that are extremely fragile. My understanding * is that there is specialized ownership of the cb pointer based * upon what is happening. Those assumptions are supposed to be @@ -84,7 +84,10 @@ static int frrzmq_read_msg(struct thread *t) break; if (cb->read.cb_msg) { + cb->in_cb = true; cb->read.cb_msg(cb->read.arg, cb->zmqsock); + cb->in_cb = false; + read = 1; if (cb->read.cancelled) { @@ -92,7 +95,8 @@ static int frrzmq_read_msg(struct thread *t) ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; @@ -112,15 +116,19 @@ static int frrzmq_read_msg(struct thread *t) } read = 1; + cb->in_cb = true; cb->read.cb_part(cb->read.arg, cb->zmqsock, &msg, partno); + cb->in_cb = false; + if (cb->read.cancelled) { zmq_msg_close(&msg); frrzmq_check_events(cbp, &cb->write, ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } @@ -183,7 +191,6 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->write.cancelled = true; *cbp = cb; } @@ -195,6 +202,7 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb->read.cb_part = partfunc; cb->read.cb_error = errfunc; cb->read.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLIN) { thread_cancel(&cb->read.thread); @@ -232,14 +240,18 @@ static int frrzmq_write_msg(struct thread *t) break; if (cb->write.cb_msg) { + cb->in_cb = true; cb->write.cb_msg(cb->write.arg, cb->zmqsock); + cb->in_cb = false; + written = 1; if (cb->write.cancelled) { frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN); cb->write.thread = NULL; if (cb->read.cancelled && !cb->read.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; @@ -286,7 +298,6 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->read.cancelled = true; *cbp = cb; } @@ -298,6 +309,7 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb->write.cb_part = NULL; cb->write.cb_error = errfunc; cb->write.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLOUT) { thread_cancel(&cb->write.thread); @@ -317,22 +329,15 @@ void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core) core->cancelled = true; thread_cancel(&core->thread); - /* - * Looking at this code one would assume that FRR - * would want a `!(*cb)->write.thread. This was - * attempted in e08165def1c62beee0e87385 but this - * change caused `make check` to stop working - * which was not noticed because our CI system - * does not build with zeromq. Put this back - * to the code as written in 2017. e08165de.. - * was introduced in 2021. So someone was ok - * with frrzmq_thread_cancel for 4 years. This will - * allow those people doing `make check` to continue - * working. In the meantime if the people using - * this code see an issue they can fix it + /* If cancelled from within a callback, don't try to free memory + * in this path. */ + if ((*cb)->in_cb) + return; + + /* Ok to free the callback context if no more ... context. */ if ((*cb)->read.cancelled && !(*cb)->read.thread - && (*cb)->write.cancelled && (*cb)->write.thread) + && (*cb)->write.cancelled && ((*cb)->write.thread == NULL)) XFREE(MTYPE_ZEROMQ_CB, *cb); } diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h index d30cf8a841..b3be78cbea 100644 --- a/lib/frr_zmq.h +++ b/lib/frr_zmq.h @@ -49,10 +49,13 @@ struct cb_core { unsigned partnum); void (*cb_error)(void *arg, void *zmqsock); }; + struct frrzmq_cb { void *zmqsock; int fd; + bool in_cb; /* This context is in a read or write callback. */ + struct cb_core read; struct cb_core write; }; diff --git a/lib/frrscript.c b/lib/frrscript.c index 0e0d3c030c..b935b30cc2 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -226,7 +226,7 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, p = lua_to(lfs->L, 2); /* At the end, the Lua state should be same as it was at the start - * i.e. containing soley the returned table. + * i.e. containing solely the returned table. */ assert(lua_gettop(lfs->L) == 1); assert(lua_istable(lfs->L, -1) == 1); diff --git a/lib/graph.c b/lib/graph.c index 1cbe1b90f9..ba7314fb25 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -69,7 +69,7 @@ static void graph_vector_remove(vector v, unsigned int ix) * and v->active is > ix. */ v->active--; /* if ix == v->active--, we set the item to itself, then to NULL... - * still correct, no check neccessary. */ + * still correct, no check necessary. */ v->index[ix] = v->index[v->active]; v->index[v->active] = NULL; } diff --git a/lib/hash.h b/lib/hash.h index 47d951a34b..f3b24f051b 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -161,7 +161,7 @@ hash_create_size(unsigned int size, unsigned int (*hash_key)(const void *), * an element from its key, you must provide the data item itself, with the * portions used in the hash function set to the same values as the data item * to retrieve. To insert a data element, either provide the key as just - * described and provide alloc_func as descrbied below to allocate the full + * described and provide alloc_func as described below to allocate the full * data element, or provide the full data element and pass 'hash_alloc_intern' * to alloc_func. * diff --git a/lib/hook.h b/lib/hook.h index 3a0db6009b..d75e623edc 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -193,7 +193,7 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, * usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2)); * as above, "passlist" must use the same order and same names as "arglist" * - * theoretically passlist is not neccessary, but let's keep things simple and + * theoretically passlist is not necessary, but let's keep things simple and * use exact same args on DECLARE and DEFINE. */ #define DECLARE_HOOK(hookname, arglist, passlist) \ @@ -341,7 +341,7 @@ static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { switch (vrf_get_backend()) { @@ -354,7 +354,7 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) return NULL; } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id) { @@ -406,7 +406,7 @@ ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -/* Interface existance check by interface name. */ +/* Interface existence check by interface name. */ struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); @@ -251,8 +251,8 @@ struct interface { /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int - mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu - */ + mtu6; /* IPv6 MTU - probably, but not necessarily same as mtu + */ /* Link-layer information and hardware address */ enum zebra_link_type ll_type; diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 17695e6607..a139b9a14c 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -41,19 +41,19 @@ static struct log_ref ferr_lib_warn[] = { { .code = EC_LIB_LINUX_NS, .title = "The Linux namespace subsystem has encountered a parsing error", - .description = "During system startup an invalid parameter for the namesapce was give to FRR", + .description = "During system startup an invalid parameter for the namespace was give to FRR", .suggestion = "Gather log data and open an Issue. restart FRR", }, { .code = EC_LIB_SLOW_THREAD_CPU, .title = "The Event subsystem has detected a slow cpu time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination therof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination thereof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", .suggestion = "Gather log data and open an Issue", }, { .code = EC_LIB_SLOW_THREAD_WALL, .title = "The Event subsystem has detected a slow wall time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination therof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination thereof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", .suggestion = "Gather log data and open an Issue", }, { @@ -286,7 +286,7 @@ static struct log_ref ferr_lib_err[] = { }, { .code = EC_LIB_NB_CB_INVALID_PRIO, - .title = "Norhtbound callback has an invalid priority", + .title = "Northbound callback has an invalid priority", .description = "The northbound subsystem, during initialization, has detected a callback whose priority is invalid", .suggestion = "This is a bug; please report it" }, diff --git a/lib/libfrr.c b/lib/libfrr.c index d03437328b..9b05bb4fbf 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -674,13 +674,19 @@ static void frr_mkdir(const char *path, bool strip) strerror(errno)); } +static void _err_print(const void *cookie, const char *errstr) +{ + const char *prefix = (const char *)cookie; + + fprintf(stderr, "%s: %s\n", prefix, errstr); +} + static struct thread_master *master; struct thread_master *frr_init(void) { struct option_chain *oc; struct frrmod_runtime *module; struct zprivs_ids_t ids; - char moderr[256]; char p_instance[16] = "", p_pathspace[256] = ""; const char *dir; dir = di->module_path ? di->module_path : frr_moduledir; @@ -734,11 +740,9 @@ struct thread_master *frr_init(void) frrmod_init(di->module); while (modules) { modules = (oc = modules)->next; - module = frrmod_load(oc->arg, dir, moderr, sizeof(moderr)); - if (!module) { - fprintf(stderr, "%s\n", moderr); + module = frrmod_load(oc->arg, dir, _err_print, __func__); + if (!module) exit(1); - } XFREE(MTYPE_TMP, oc); } diff --git a/lib/libospf.h b/lib/libospf.h index d2bb29d80e..c8ada9d3c5 100644 --- a/lib/libospf.h +++ b/lib/libospf.h @@ -36,7 +36,7 @@ extern "C" { #define IPPROTO_OSPFIGP 89 #endif /* IPPROTO_OSPFIGP */ -/* Architectual Constants */ +/* Architectural Constants */ #ifdef DEBUG #define OSPF_LS_REFRESH_TIME 120 #else @@ -355,9 +355,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD), DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER), - DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), diff --git a/lib/module.c b/lib/module.c index 1d51a6396d..4037bfbeb0 100644 --- a/lib/module.c +++ b/lib/module.c @@ -26,9 +26,11 @@ #include "module.h" #include "memory.h" #include "lib/version.h" +#include "printfrr.h" DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name"); DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments"); +DEFINE_MTYPE_STATIC(LIB, MODULE_LOAD_ERR, "Module loading error"); static struct frrmod_info frrmod_default_info = { .name = "libfrr", @@ -67,14 +69,64 @@ void frrmod_init(struct frrmod_runtime *modinfo) execname = modinfo->info->name; } -struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, - size_t err_len) +/* + * If caller wants error strings, it should define non-NULL pFerrlog + * which will be called with 0-terminated error messages. These + * messages will NOT contain newlines, and the (*pFerrlog)() function + * could be called multiple times for a single call to frrmod_load(). + * + * The (*pFerrlog)() function may copy these strings if needed, but + * should expect them to be freed by frrmod_load() before frrmod_load() + * returns. + * + * frrmod_load() is coded such that (*pFerrlog)() will be called only + * in the case where frrmod_load() returns an error. + */ +struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, + void (*pFerrlog)(const void *, const char *), + const void *pErrlogCookie) { void *handle = NULL; char name[PATH_MAX], fullpath[PATH_MAX * 2], *args; struct frrmod_runtime *rtinfo, **rtinfop; const struct frrmod_info *info; +#define FRRMOD_LOAD_N_ERRSTR 10 + char *aErr[FRRMOD_LOAD_N_ERRSTR]; + unsigned int iErr = 0; + + memset(aErr, 0, sizeof(aErr)); + +#define ERR_RECORD(...) \ + do { \ + if (pFerrlog && (iErr < FRRMOD_LOAD_N_ERRSTR)) { \ + aErr[iErr++] = asprintfrr(MTYPE_MODULE_LOAD_ERR, \ + __VA_ARGS__); \ + } \ + } while (0) + +#define ERR_REPORT \ + do { \ + if (pFerrlog) { \ + unsigned int i; \ + \ + for (i = 0; i < iErr; ++i) { \ + (*pFerrlog)(pErrlogCookie, aErr[i]); \ + } \ + } \ + } while (0) + +#define ERR_FREE \ + do { \ + unsigned int i; \ + \ + for (i = 0; i < iErr; ++i) { \ + XFREE(MTYPE_MODULE_LOAD_ERR, aErr[i]); \ + aErr[i] = 0; \ + } \ + iErr = 0; \ + } while (0) + snprintf(name, sizeof(name), "%s", spec); args = strchr(name, ':'); if (args) @@ -85,32 +137,41 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir, execname, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", + fullpath, dlerror()); } if (!handle) { snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", + fullpath, dlerror()); } } if (!handle) { snprintf(fullpath, sizeof(fullpath), "%s", name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", fullpath, + dlerror()); } if (!handle) { - if (err) - snprintf(err, err_len, - "loading module \"%s\" failed: %s", name, - dlerror()); + ERR_REPORT; + ERR_FREE; return NULL; } + /* previous dlopen() errors are no longer relevant */ + ERR_FREE; + rtinfop = dlsym(handle, "frr_module"); if (!rtinfop) { dlclose(handle); - if (err) - snprintf(err, err_len, - "\"%s\" is not an FRR module: %s", name, - dlerror()); + ERR_RECORD("\"%s\" is not an FRR module: %s", name, dlerror()); + ERR_REPORT; + ERR_FREE; return NULL; } rtinfo = *rtinfop; @@ -122,17 +183,13 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, if (rtinfo->finished_loading) { dlclose(handle); - if (err) - snprintf(err, err_len, "module \"%s\" already loaded", - name); + ERR_RECORD("module \"%s\" already loaded", name); goto out_fail; } if (info->init && info->init()) { dlclose(handle); - if (err) - snprintf(err, err_len, - "module \"%s\" initialisation failed", name); + ERR_RECORD("module \"%s\" initialisation failed", name); goto out_fail; } @@ -140,11 +197,14 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, *frrmod_last = rtinfo; frrmod_last = &rtinfo->next; + ERR_FREE; return rtinfo; out_fail: XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args); XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name); + ERR_REPORT; + ERR_FREE; return NULL; } diff --git a/lib/module.h b/lib/module.h index 6275877cb3..ae1ca2f757 100644 --- a/lib/module.h +++ b/lib/module.h @@ -91,7 +91,9 @@ extern struct frrmod_runtime *frrmod_list; extern void frrmod_init(struct frrmod_runtime *modinfo); extern struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, - char *err, size_t err_len); + void (*pFerrlog)(const void *, + const char *), + const void *pErrlogCookie); #if 0 /* not implemented yet */ extern void frrmod_unload(struct frrmod_runtime *module); diff --git a/lib/netns_linux.c b/lib/netns_linux.c index cde842b88c..43c0d8c359 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -279,7 +279,7 @@ static void ns_disable_internal(struct ns *ns) } } -/* VRF list existance check by name. */ +/* VRF list existence check by name. */ static struct ns_map_nsid *ns_map_nsid_lookup_by_nsid(ns_id_t ns_id) { struct ns_map_nsid ns_map; diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 76af494e30..e62a83cee2 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -425,8 +425,7 @@ static int frr_confd_cdb_read_cb(struct thread *thread) int *subp = NULL; int reslen = 0; - thread = NULL; - thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &thread); + thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub); if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen) != CONFD_OK) { @@ -1164,15 +1163,10 @@ exit: } -static int frr_confd_dp_read(struct thread *thread) +static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd) { - struct confd_daemon_ctx *dctx = THREAD_ARG(thread); - int fd = THREAD_FD(thread); int ret; - thread = NULL; - thread_add_read(master, frr_confd_dp_read, dctx, fd, &thread); - ret = confd_fd_ready(dctx, fd); if (ret == CONFD_EOF) { flog_err_confd("confd_fd_ready"); @@ -1187,6 +1181,26 @@ static int frr_confd_dp_read(struct thread *thread) return 0; } +static int frr_confd_dp_ctl_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl); + + frr_confd_dp_read(dctx, fd); +} + +static int frr_confd_dp_worker_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_worker_read, dctx, fd, &t_dp_worker); + + frr_confd_dp_read(dctx, fd); +} + static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; @@ -1314,9 +1328,9 @@ static int frr_confd_init_dp(const char *program_name) goto error; } - thread_add_read(master, frr_confd_dp_read, dctx, dp_ctl_sock, + thread_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock, &t_dp_ctl); - thread_add_read(master, frr_confd_dp_read, dctx, dp_worker_sock, + thread_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock, &t_dp_worker); return 0; diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 71f07dfe86..e227d0385c 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -344,6 +344,10 @@ static struct lyd_node *get_dnode_config(const std::string &path) { struct lyd_node *dnode; + if (!yang_dnode_exists(running_config->dnode, + path.empty() ? NULL : path.c_str())) + return NULL; + dnode = yang_dnode_get(running_config->dnode, path.empty() ? NULL : path.c_str()); if (dnode) diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 7c463dd61f..86a159e507 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -528,19 +528,18 @@ static int frr_sr_notification_send(const char *xpath, struct list *arguments) static int frr_sr_read_cb(struct thread *thread) { - sr_subscription_ctx_t *sr_subscription = THREAD_ARG(thread); + struct yang_module *module = THREAD_ARG(thread); int fd = THREAD_FD(thread); int ret; - ret = sr_process_events(sr_subscription, session, NULL); + ret = sr_process_events(module->sr_subscription, session, NULL); if (ret != SR_ERR_OK) { flog_err(EC_LIB_LIBSYSREPO, "%s: sr_fd_event_process(): %s", __func__, sr_strerror(ret)); return -1; } - thread = NULL; - thread_add_read(master, frr_sr_read_cb, sr_subscription, fd, &thread); + thread_add_read(master, frr_sr_read_cb, module, fd, &module->sr_thread); return 0; } @@ -703,7 +702,7 @@ static int frr_sr_init(void) sr_strerror(ret)); goto cleanup; } - thread_add_read(master, frr_sr_read_cb, module->sr_subscription, + thread_add_read(master, frr_sr_read_cb, module, event_pipe, &module->sr_thread); } diff --git a/lib/prefix.c b/lib/prefix.c index ef7d2e59da..df753fe10b 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -113,7 +113,7 @@ const char *family2str(int family) return "?"; } -/* Address Famiy Identifier to Address Family converter. */ +/* Address Family Identifier to Address Family converter. */ int afi2family(afi_t afi) { if (afi == AFI_IP) diff --git a/lib/resolver.c b/lib/resolver.c index c2153e0a5e..4aba909f25 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -53,14 +53,14 @@ static int resolver_cb_socket_readable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->read_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, fd, ARES_SOCKET_BAD); if (vector_lookup(r->read_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, r, fd, - &t); - vector_set_index(r->read_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -71,14 +71,14 @@ static int resolver_cb_socket_writable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->write_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, ARES_SOCKET_BAD, fd); if (vector_lookup(r->write_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->write_threads, fd); thread_add_write(r->master, resolver_cb_socket_writable, r, fd, - &t); - vector_set_index(r->write_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -105,14 +105,15 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, int writable) { struct resolver_state *r = (struct resolver_state *)data; - struct thread *t; + struct thread *t, **t_ptr; if (readable) { - t = vector_lookup_ensure(r->read_threads, fd); + t = vector_lookup(r->read_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, - r, fd, &t); - vector_set_index(r->read_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->read_threads, fd); @@ -125,11 +126,12 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, } if (writable) { - t = vector_lookup_ensure(r->write_threads, fd); + t = vector_lookup(r->write_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->write_threads, fd); thread_add_read(r->master, resolver_cb_socket_writable, - r, fd, &t); - vector_set_index(r->write_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->write_threads, fd); diff --git a/lib/routemap.c b/lib/routemap.c index 5c60b7d1c6..6227ebf158 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2480,7 +2480,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name, do whatever the exit policy (EXIT, NEXT or GOTO) tells. on-match next - If this clause is matched, then the set statements are executed and then we drop through to the next clause - on-match goto n - If this clause is matched, then the set statments + on-match goto n - If this clause is matched, then the set statements are executed and then we goto the nth clause, or the first clause greater than this. In order to ensure route-maps *always* exit, you cannot jump backwards. diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index cadad15fa7..e2db511fc0 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -165,12 +165,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_address, match_ip_address_cmd, - "match ip address <(1-199)|(1300-2699)|WORD>$name", + "match ip address WORD$name", MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -187,13 +185,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_address, no_match_ip_address_cmd, - "no match ip address [<(1-199)|(1300-2699)|WORD>]", + "no match ip address [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -246,12 +242,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop <(1-199)|(1300-2699)|WORD>$name", + "match ip next-hop WORD$name", MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -268,13 +262,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_next_hop, no_match_ip_next_hop_cmd, - "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]", + "no match ip next-hop [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = diff --git a/lib/sbuf.h b/lib/sbuf.h index 9f0311006d..aaa2db0edb 100644 --- a/lib/sbuf.h +++ b/lib/sbuf.h @@ -35,7 +35,7 @@ extern "C" { * without any information about the previous parsing steps, is usually not very * helpful. * Using sbuf, the parser can log the whole parsing process into a buffer using - * a printf like API. When an error ocurrs, all the information about previous + * a printf like API. When an error occurs, all the information about previous * parsing steps is there in the log, without any need for backtracking, and can * be used to give a detailed and useful error description. * When parsing completes successfully without any error, the log can just be diff --git a/lib/sigevent.c b/lib/sigevent.c index be7297f264..6710527ae9 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -96,7 +96,7 @@ int quagga_sigevent_process(void) struct quagga_signal_t *sig; int i; #ifdef SIGEVENT_BLOCK_SIGNALS - /* shouldnt need to block signals, but potentially may be needed */ + /* shouldn't need to block signals, but potentially may be needed */ sigset_t newmask, oldmask; /* @@ -142,7 +142,7 @@ int quagga_sigevent_process(void) } #ifdef SIGEVENT_SCHEDULE_THREAD -/* timer thread to check signals. Shouldnt be needed */ +/* timer thread to check signals. shouldn't be needed */ int quagga_signal_timer(struct thread *t) { struct quagga_sigevent_master_t *sigm; diff --git a/lib/skiplist.c b/lib/skiplist.c index c5219f7381..81407826f2 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ * * Skip Lists are a probabilistic alternative to balanced trees, as diff --git a/lib/skiplist.h b/lib/skiplist.h index 00950e13bb..165607820a 100644 --- a/lib/skiplist.h +++ b/lib/skiplist.h @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ */ diff --git a/lib/vector.c b/lib/vector.c index 565c49fd59..4af564a82f 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -123,6 +123,17 @@ int vector_set_index(vector v, unsigned int i, void *val) return i; } +/* Make a specified index slot active and return its address. */ +void **vector_get_index(vector v, unsigned int i) +{ + vector_ensure(v, i); + + if (v->active <= i) + v->active = i + 1; + + return &v->index[i]; +} + /* Look up vector. */ void *vector_lookup(vector v, unsigned int i) { diff --git a/lib/vector.h b/lib/vector.h index d5857eb599..845c8d8b04 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -54,6 +54,7 @@ extern void vector_ensure(vector v, unsigned int num); extern int vector_empty_slot(vector v); extern int vector_set(vector v, void *val); extern int vector_set_index(vector v, unsigned int i, void *val); +extern void **vector_get_index(vector v, unsigned int i); extern void vector_unset(vector v, unsigned int i); extern void vector_unset_value(vector v, void *val); extern void vector_remove(vector v, unsigned int ix); diff --git a/lib/zclient.c b/lib/zclient.c index dde60a6c90..d639fa84b8 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -765,15 +765,17 @@ static int zclient_connect(struct thread *t) enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id) + bool connected, + bool resolve_via_def, vrf_id_t vrf_id) { struct stream *s; s = zclient->obuf; stream_reset(s); zclient_create_header(s, command, vrf_id); - stream_putc(s, (exact_match) ? 1 : 0); - + stream_putc(s, (connected) ? 1 : 0); + stream_putc(s, (resolve_via_def) ? 1 : 0); + stream_putw(s, SAFI_UNICAST); stream_putw(s, PREFIX_FAMILY(p)); stream_putc(s, p->prefixlen); switch (PREFIX_FAMILY(p)) { @@ -1925,6 +1927,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr) memset(nhr, 0, sizeof(*nhr)); STREAM_GETL(s, nhr->message); + STREAM_GETW(s, nhr->safi); STREAM_GETW(s, nhr->prefix.family); STREAM_GETC(s, nhr->prefix.prefixlen); switch (nhr->prefix.family) { @@ -4016,13 +4019,6 @@ static int zclient_read(struct thread *thread) (*zclient->nexthop_update)(command, zclient, length, vrf_id); break; - case ZEBRA_IMPORT_CHECK_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd import check update"); - if (zclient->import_check_update) - (*zclient->import_check_update)(command, zclient, - length, vrf_id); - break; case ZEBRA_BFD_DEST_REPLAY: if (zclient->bfd_dest_replay) (*zclient->bfd_dest_replay)(command, zclient, length, diff --git a/lib/zclient.h b/lib/zclient.h index f9438d5db7..c35753ca80 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -126,9 +126,6 @@ typedef enum { ZEBRA_INTERFACE_NBR_ADDRESS_ADD, ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, ZEBRA_INTERFACE_BFD_DEST_UPDATE, - ZEBRA_IMPORT_ROUTE_REGISTER, - ZEBRA_IMPORT_ROUTE_UNREGISTER, - ZEBRA_IMPORT_CHECK_UPDATE, ZEBRA_BFD_DEST_REGISTER, ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, @@ -362,7 +359,6 @@ struct zclient { int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS); int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS); int (*nexthop_update)(ZAPI_CALLBACK_ARGS); - int (*import_check_update)(ZAPI_CALLBACK_ARGS); int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS); @@ -1107,7 +1103,7 @@ extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id); + bool connected, bool resolve_via_default, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 5fcb311888..0a618056d5 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -107,7 +107,6 @@ static int netlink_log_recv(struct thread *t) struct zbuf payload, zb; struct nlmsghdr *n; - netlink_log_thread = NULL; zbuf_init(&zb, buf, sizeof(buf), 0); while (zbuf_recv(&zb, fd) > 0) { diff --git a/nhrpd/nhrp_event.c b/nhrpd/nhrp_event.c index f784ef22d6..206b2caccf 100644 --- a/nhrpd/nhrp_event.c +++ b/nhrpd/nhrp_event.c @@ -84,7 +84,6 @@ static int evmgr_read(struct thread *t) struct zbuf *ibuf = &evmgr->ibuf; struct zbuf msg; - evmgr->t_read = NULL; if (zbuf_read(ibuf, evmgr->fd, (size_t)-1) < 0) { evmgr_connection_error(evmgr); return 0; @@ -103,7 +102,6 @@ static int evmgr_write(struct thread *t) struct event_manager *evmgr = THREAD_ARG(t); int r; - evmgr->t_write = NULL; r = zbufq_write(&evmgr->obuf, evmgr->fd); if (r > 0) { thread_add_write(master, evmgr_write, evmgr, evmgr->fd, @@ -193,7 +191,6 @@ static int evmgr_reconnect(struct thread *t) struct event_manager *evmgr = THREAD_ARG(t); int fd; - evmgr->t_reconnect = NULL; if (evmgr->fd >= 0 || !nhrp_event_socket_path) return 0; diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c index b78afda2c4..339b6dfabe 100644 --- a/nhrpd/nhrp_multicast.c +++ b/nhrpd/nhrp_multicast.c @@ -149,7 +149,6 @@ static int netlink_mcast_log_recv(struct thread *t) struct zbuf payload, zb; struct nlmsghdr *n; - netlink_mcast_log_thread = NULL; zbuf_init(&zb, buf, sizeof(buf), 0); while (zbuf_recv(&zb, fd) > 0) { diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 9dfaf073d8..5179f15ebf 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -112,7 +112,6 @@ static int nhrp_reg_timeout(struct thread *t) struct nhrp_registration *r = THREAD_ARG(t); struct nhrp_cache *c; - r->t_register = NULL; if (r->timeout >= 16 && sockunion_family(&r->proto_addr) != AF_UNSPEC) { nhrp_reqid_free(&nhrp_packet_reqid, &r->reqid); @@ -176,7 +175,6 @@ static int nhrp_reg_send_req(struct thread *t) struct nhrp_extension_header *ext; struct nhrp_cie_header *cie; - r->t_register = NULL; if (!nhrp_peer_check(r->peer, 2)) { debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU", &r->peer->vc->remote.nbma); @@ -281,7 +279,6 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, struct nhrp_registration *reg, *regn; int i; - nhs->t_resolve = NULL; if (n < 0) { /* Failed, retry in a moment */ thread_add_timer(master, nhrp_nhs_resolve, nhs, 5, diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 5a7da703ac..030f4c0ff3 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -265,7 +265,6 @@ static int nhrp_peer_request_timeout(struct thread *t) struct interface *ifp = p->ifp; struct nhrp_interface *nifp = ifp->info; - p->t_fallback = NULL; if (p->online) return 0; diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 0905ceb72a..244273cd58 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -39,7 +39,6 @@ static int nhrp_shortcut_do_expire(struct thread *t) { struct nhrp_shortcut *s = THREAD_ARG(t); - s->t_timer = NULL; thread_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3, &s->t_timer); s->expiring = 1; diff --git a/nhrpd/vici.c b/nhrpd/vici.c index c21e01601c..8fce828663 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -361,7 +361,6 @@ static int vici_read(struct thread *t) struct zbuf *ibuf = &vici->ibuf; struct zbuf pktbuf; - vici->t_read = NULL; if (zbuf_read(ibuf, vici->fd, (size_t)-1) < 0) { vici_connection_error(vici); return 0; @@ -392,7 +391,6 @@ static int vici_write(struct thread *t) struct vici_conn *vici = THREAD_ARG(t); int r; - vici->t_write = NULL; r = zbufq_write(&vici->obuf, vici->fd); if (r > 0) { thread_add_write(master, vici_write, vici, vici->fd, @@ -509,7 +507,6 @@ static int vici_reconnect(struct thread *t) int fd; char *file_path; - vici->t_reconnect = NULL; if (vici->fd >= 0) return 0; diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 57165201bd..f3e8127a80 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -53,6 +53,16 @@ unsigned char conf_debug_ospf6_abr; +int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path) +{ + if (((o_path->origin.type == r_path->origin.type) + && (o_path->origin.id == r_path->origin.id) + && (o_path->origin.adv_router == r_path->origin.adv_router))) + return 1; + else + return 0; +} + bool ospf6_check_and_set_router_abr(struct ospf6 *o) { struct listnode *node; @@ -815,9 +825,8 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, struct ospf6_nexthop *nh, *rnh; for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) { - if (o_path->area_id != route->path.area_id || - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) != 0)) + if (o_path->area_id != route->path.area_id + || !ospf6_ls_origin_same(o_path, &route->path)) continue; if ((o_path->cost == route->path.cost) && @@ -1232,9 +1241,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if (o_path->area_id == route->path.area_id && - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) == 0)) + if (o_path->area_id == route->path.area_id + && ospf6_ls_origin_same(o_path, &route->path)) break; } diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 08521ecb0f..a4dc4ddc84 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -89,5 +89,7 @@ extern void ospf6_abr_init(void); extern void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6); extern void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6); +extern int ospf6_ls_origin_same(struct ospf6_path *o_path, + struct ospf6_path *r_path); #endif /*OSPF6_ABR_H*/ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index df40c608a1..cd2791fc48 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -204,7 +204,6 @@ int ospf6_orig_as_external_lsa(struct thread *thread) uint32_t type, adv_router; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_as_extern_lsa = NULL; if (oi->state == OSPF6_INTERFACE_DOWN) return 0; @@ -290,9 +289,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, * origin. */ if (o_path->area_id != route->path.area_id - || (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) - != 0)) + || !ospf6_ls_origin_same(o_path, &route->path)) continue; /* Cost is not same then delete current path */ @@ -411,10 +408,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { if (o_path->area_id == route->path.area_id - && (memcmp(&(o_path)->origin, - &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) - == 0)) + && ospf6_ls_origin_same(o_path, &route->path)) break; } /* If path is not found in old_route paths's list, @@ -1096,8 +1090,6 @@ static int ospf6_asbr_routemap_update_timer(struct thread *thread) struct ospf6_redist *red; int type; - ospf6->t_distribute_update = NULL; - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { red = ospf6_redist_lookup(ospf6, type, 0); @@ -1139,7 +1131,6 @@ void ospf6_asbr_distribute_list_update(struct ospf6 *ospf6, if (IS_OSPF6_DEBUG_ASBR) zlog_debug("%s: trigger redistribute reset thread", __func__); - ospf6->t_distribute_update = NULL; thread_add_timer_msec(master, ospf6_asbr_routemap_update_timer, ospf6, OSPF_MIN_LS_INTERVAL, &ospf6->t_distribute_update); @@ -3378,7 +3369,6 @@ static int ospf6_asbr_summary_process(struct thread *thread) struct ospf6 *ospf6 = THREAD_ARG(thread); int operation = 0; - ospf6->t_external_aggr = NULL; operation = ospf6->aggr_action; if (IS_OSPF6_DEBUG_AGGR) diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 186eac35a5..150903a56a 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -288,7 +288,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) monotime(&now); if (!OSPF6_LSA_IS_MAXAGE(lsa)) { - lsa->expire = NULL; thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, @@ -547,7 +546,6 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, /* reschedule retransmissions to all neighbors */ for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { THREAD_OFF(on->thread_send_lsupdate); - on->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate); } @@ -1028,15 +1026,8 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, if (old) ospf6_flood_clear(old); - /* (b) immediately flood and (c) remove from all retrans-list */ - /* Prevent self-originated LSA to be flooded. this is to make - reoriginated instance of the LSA not to be rejected by other - routers - due to MinLSArrival. */ self_originated = (new->header->adv_router == from->ospf6_if->area->ospf6->router_id); - if (!self_originated) - ospf6_flood(from, new); /* Received non-self-originated Grace LSA. */ if (IS_GRACE_LSA(new) && !self_originated) { @@ -1082,6 +1073,14 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, } } + /* (b) immediately flood and (c) remove from all retrans-list */ + /* Prevent self-originated LSA to be flooded. this is to make + * reoriginated instance of the LSA not to be rejected by other + * routers due to MinLSArrival. + */ + if (!self_originated) + ospf6_flood(from, new); + /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ ospf6_install_lsa(new); @@ -1113,7 +1112,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, "Newer instance of the self-originated LSA"); zlog_debug("Schedule reorigination"); } - new->refresh = NULL; thread_add_event(master, ospf6_lsa_refresh, new, 0, &new->refresh); } @@ -1239,7 +1237,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, ospf6_lsa_delete(new); return; } - return; } } diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index ad8998b1ed..78f842db6c 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -202,8 +202,6 @@ static int ospf6_handle_grace_timer_expiry(struct thread *thread) { struct ospf6_neighbor *nbr = THREAD_ARG(thread); - nbr->gr_helper_info.t_grace_timer = NULL; - ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_GRACE_TIMEOUT); return OSPF6_SUCCESS; } diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index b63a3c02db..9d73740819 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -819,7 +819,6 @@ int interface_up(struct thread *thread) /* Schedule Hello */ if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) && !if_is_loopback_or_vrf(oi->interface)) { - oi->thread_send_hello = NULL; thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); } @@ -2740,27 +2739,39 @@ void ospf6_interface_clear(struct interface *ifp) /* Clear interface */ DEFUN (clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd, - "clear ipv6 ospf6 interface [IFNAME]", + "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", CLEAR_STR IP6_STR OSPF6_STR + VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR ) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf; + int idx_vrf = 3; int idx_ifname = 4; struct interface *ifp; + const char *vrf_name; - if (argc == 4) /* Clear all the ospfv3 interfaces. */ - { + if (argv_find(argv, argc, "vrf", &idx_vrf)) + vrf_name = argv[idx_vrf + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(vrf_name); + if (!vrf) { + vty_out(vty, "%% VRF %s not found\n", vrf_name); + return CMD_WARNING; + } + + if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) { + /* Clear all the ospfv3 interfaces. */ FOR_ALL_INTERFACES (vrf, ifp) ospf6_interface_clear(ifp); - } else /* Interface name is specified. */ - { - if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT)) - == NULL) { + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf); + if (!ifp) { vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); return CMD_WARNING; diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 277af4b1c5..6abc1c7d09 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -248,7 +248,6 @@ int ospf6_router_lsa_originate(struct thread *thread) int count; oa = (struct ospf6_area *)THREAD_ARG(thread); - oa->thread_router_lsa = NULL; if (oa->ospf6->gr_info.restart_in_progress) { if (IS_DEBUG_OSPF6_GR) @@ -533,7 +532,6 @@ int ospf6_network_lsa_originate(struct thread *thread) uint16_t type; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_network_lsa = NULL; /* The interface must be enabled until here. A Network-LSA of a disabled interface (but was once enabled) should be flushed @@ -784,7 +782,6 @@ int ospf6_link_lsa_originate(struct thread *thread) struct ospf6_prefix *op; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_link_lsa = NULL; assert(oi->area); @@ -1030,7 +1027,6 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) int ls_id = 0; oa = (struct ospf6_area *)THREAD_ARG(thread); - oa->thread_intra_prefix_lsa = NULL; if (oa->ospf6->gr_info.restart_in_progress) { if (IS_DEBUG_OSPF6_GR) @@ -1269,7 +1265,6 @@ int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread) uint16_t type; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_intra_prefix_lsa = NULL; assert(oi->area); @@ -1524,9 +1519,8 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, /* Check old route path and route has same * origin. */ - if (o_path->area_id != route->path.area_id || - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) != 0)) + if (o_path->area_id != route->path.area_id + || !ospf6_ls_origin_same(o_path, &route->path)) continue; /* Cost is not same then delete current path */ @@ -1630,10 +1624,8 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, */ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if (o_path->area_id == route->path.area_id && - (memcmp(&(o_path)->origin, - &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) == 0)) + if (o_path->area_id == route->path.area_id + && ospf6_ls_origin_same(o_path, &route->path)) break; } /* If path is not found in old_route paths's list, @@ -2479,12 +2471,13 @@ DEFUN (debug_ospf6_brouter_router, DEFUN (no_debug_ospf6_brouter_router, no_debug_ospf6_brouter_router_cmd, - "no debug ospf6 border-routers router-id", + "no debug ospf6 border-routers router-id [A.B.C.D]", NO_STR DEBUG_STR OSPF6_STR "Debug border router\n" "Debug specific border router\n" + "Specify border-router's router-id\n" ) { OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF(); @@ -2510,12 +2503,13 @@ DEFUN (debug_ospf6_brouter_area, DEFUN (no_debug_ospf6_brouter_area, no_debug_ospf6_brouter_area_cmd, - "no debug ospf6 border-routers area-id", + "no debug ospf6 border-routers area-id [A.B.C.D]", NO_STR DEBUG_STR OSPF6_STR "Debug border router\n" "Debug border routers in specific Area\n" + "Specify Area-ID\n" ) { OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF(); diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index ac07704d2c..f406e828e1 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -891,7 +891,6 @@ int ospf6_lsa_refresh(struct thread *thread) new = ospf6_lsa_create(self->header); new->lsdb = old->lsdb; - new->refresh = NULL; thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME, &new->refresh); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 64de9bae41..a81c3e728f 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -726,7 +726,6 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL @@ -775,7 +774,6 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)) thread_add_event(master, exchange_done, on, 0, NULL); else { - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send_newone, on, 0, &on->thread_send_dbdesc); } @@ -856,7 +854,6 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, zlog_debug( "Duplicated dbdesc causes retransmit"); THREAD_OFF(on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); return; @@ -949,7 +946,6 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS @@ -1084,7 +1080,6 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst, if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) zlog_debug("Ignoring LSA of reserved scope"); continue; - break; } /* Find database copy */ @@ -1636,7 +1631,6 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) @@ -2399,7 +2393,6 @@ int ospf6_lsreq_send(struct thread *thread) /* set next thread */ if (on->request_list->count != 0) { - on->thread_send_lsreq = NULL; thread_add_timer(master, ospf6_lsreq_send, on, on->ospf6_if->rxmt_interval, &on->thread_send_lsreq); @@ -2585,11 +2578,9 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) ospf6_packet_free(op); if (on->lsupdate_list->count != 0) { - on->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate); } else if (on->retrans_list->count != 0) { - on->thread_send_lsupdate = NULL; thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval, &on->thread_send_lsupdate); @@ -2703,7 +2694,6 @@ int ospf6_lsupdate_send_interface(struct thread *thread) ospf6_packet_free(op); if (oi->lsupdate_list->count > 0) { - oi->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, &oi->thread_send_lsupdate); } diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 35fbd3991c..6f2795a56d 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -273,7 +273,6 @@ int hello_received(struct thread *thread) /* reset Inactivity Timer */ THREAD_OFF(on->inactivity_timer); - on->inactivity_timer = NULL; thread_add_timer(master, inactivity_timer, on, on->ospf6_if->dead_interval, &on->inactivity_timer); @@ -312,7 +311,6 @@ int twoway_received(struct thread *thread) SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); THREAD_OFF(on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); @@ -438,7 +436,6 @@ void ospf6_check_nbr_loading(struct ospf6_neighbor *on) else if (on->last_ls_req == NULL) { if (on->thread_send_lsreq != NULL) THREAD_OFF(on->thread_send_lsreq); - on->thread_send_lsreq = NULL; thread_add_event(master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq); } @@ -620,7 +617,6 @@ int inactivity_timer(struct thread *thread) if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) zlog_debug("Neighbor Event %s: *InactivityTimer*", on->name); - on->inactivity_timer = NULL; on->drouter = on->prev_drouter = 0; on->bdrouter = on->prev_bdrouter = 0; diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 2339d339f7..c2e9b7f28a 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -304,24 +304,16 @@ void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6) type = htons(OSPF6_LSTYPE_INTER_ROUTER); for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - lsa->header->age = htons(OSPF_LSA_MAXAGE); - THREAD_OFF(lsa->refresh); - thread_execute(master, ospf6_lsa_expire, lsa, - 0); - } + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) + ospf6_lsa_premature_aging(lsa); } /* Inter area prefix LSA */ type = htons(OSPF6_LSTYPE_INTER_PREFIX); for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - lsa->header->age = htons(OSPF_LSA_MAXAGE); - THREAD_OFF(lsa->refresh); - thread_execute(master, ospf6_lsa_expire, lsa, - 0); - } + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) + ospf6_lsa_premature_aging(lsa); } } @@ -1176,8 +1168,6 @@ static int ospf6_abr_task_timer(struct thread *thread) { struct ospf6 *ospf6 = THREAD_ARG(thread); - ospf6->t_abr_task = NULL; - if (IS_OSPF6_DEBUG_ABR) zlog_debug("Running ABR task on timer"); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 8bfd3b7124..4b87c4cf30 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -408,8 +408,6 @@ int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b) else return memcmp(&a->address, &b->address, sizeof(struct in6_addr)); - - return 0; } static int ospf6_path_cmp(struct ospf6_path *a, struct ospf6_path *b) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6fe7055202..9e3bb4895a 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -432,7 +432,6 @@ static struct ospf6 *ospf6_create(const char *name) o->rt_aggr_tbl = route_table_init(); o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY; - o->t_external_aggr = NULL; o->aggr_action = OSPF6_ROUTE_AGGR_NONE; o->fd = -1; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 1a0c5a9971..81573da3a6 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -145,16 +145,17 @@ void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg) prefix.prefixlen = 0; if (unreg) - command = ZEBRA_IMPORT_ROUTE_UNREGISTER; + command = ZEBRA_NEXTHOP_UNREGISTER; else - command = ZEBRA_IMPORT_ROUTE_REGISTER; + command = ZEBRA_NEXTHOP_REGISTER; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__, zserv_command_string(command), &prefix, ospf6->vrf_id); - if (zclient_send_rnh(zclient, command, &prefix, true, ospf6->vrf_id) + if (zclient_send_rnh(zclient, command, &prefix, false, true, + ospf6->vrf_id) == ZCLIENT_SEND_FAILURE) flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed", __func__); @@ -720,7 +721,7 @@ void ospf6_zebra_init(struct thread_master *master) ospf6_zebra_if_address_update_delete; zclient->redistribute_route_add = ospf6_zebra_read_route; zclient->redistribute_route_del = ospf6_zebra_read_route; - zclient->import_check_update = ospf6_zebra_import_check_update; + zclient->nexthop_update = ospf6_zebra_import_check_update; /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index cbd03441ef..a33ca95777 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -2059,7 +2059,8 @@ void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status) } } -void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa) +void ospf_apiserver_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct opaque_lsa { struct lsa_header header; @@ -2070,6 +2071,9 @@ void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa) struct opaque_lsa *olsa; int opaquelen; + if (json) + return; + olsa = (struct opaque_lsa *)lsa->data; if (VALID_OPAQUE_INFO_LEN(lsa->data)) diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h index 89a9474972..544a32a28c 100644 --- a/ospfd/ospf_apiserver.h +++ b/ospfd/ospf_apiserver.h @@ -182,7 +182,8 @@ extern void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, extern void ospf_apiserver_config_write_router(struct vty *vty); extern void ospf_apiserver_config_write_if(struct vty *vty, struct interface *ifp); -extern void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa); +extern void ospf_apiserver_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); extern int ospf_ospf_apiserver_lsa_originator(void *arg); extern struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa); extern void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv, diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index f11c84b092..b1aeefcd43 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -146,8 +146,7 @@ const char *ospf_if_name_string(struct ospf_interface *oi) return buf; } - -void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) +int ospf_nbr_ism_state(struct ospf_neighbor *nbr) { int state; struct ospf_interface *oi = nbr->oi; @@ -159,6 +158,13 @@ void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) else state = ISM_DROther; + return state; +} + +void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) +{ + int state = ospf_nbr_ism_state(nbr); + snprintf(buf, size, "%s/%s", lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), lookup_msg(ospf_ism_state_msg, state, NULL)); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index a1f55dd0af..031ec2f428 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -150,6 +150,7 @@ extern char *ospf_lsa_type_str[]; extern const char *ospf_area_name_string(struct ospf_area *); extern const char *ospf_area_desc_string(struct ospf_area *); extern const char *ospf_if_name_string(struct ospf_interface *); +extern int ospf_nbr_ism_state(struct ospf_neighbor *nbr); extern void ospf_nbr_state_message(struct ospf_neighbor *, char *, size_t); extern const char *ospf_timer_dump(struct thread *, char *, size_t); extern const char *ospf_timeval_dump(struct timeval *, char *, size_t); diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index 2d08eeece2..ea1506ea27 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -80,7 +80,8 @@ static struct ospf_ext_lp OspfEXT; */ /* Extended Prefix Opaque LSA related callback functions */ -static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_ext_pref_lsa_originate(void *arg); static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa); static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti, @@ -90,7 +91,8 @@ static int ospf_ext_link_new_if(struct interface *ifp); static int ospf_ext_link_del_if(struct interface *ifp); static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status); static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status); -static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_ext_link_lsa_originate(void *arg); static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa); static void ospf_ext_link_lsa_schedule(struct ext_itf *exti, @@ -1846,12 +1848,16 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext, } /* Extended Link TLVs */ -static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; @@ -1932,12 +1938,16 @@ static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext, } /* Extended Prefix TLVs */ -static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c index c108040303..6a5c0bae98 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -584,7 +584,7 @@ static void ospf_gr_nvm_update(struct ospf *ospf) json_object *json_instance; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) @@ -630,7 +630,7 @@ static void ospf_gr_nvm_delete(struct ospf *ospf) json_object *json_instances; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) @@ -663,7 +663,7 @@ void ospf_gr_nvm_read(struct ospf *ospf) time_t timestamp = 0; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index 11ad45d30f..a58a120b6b 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -75,7 +75,8 @@ static const char * const ospf_rejected_reason_desc[] = { "Router is in the process of graceful restart", }; -static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa); +static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr); static unsigned int ospf_enable_rtr_hash_key(const void *data) @@ -723,14 +724,10 @@ void ospf_gr_helper_exit(struct ospf_neighbor *nbr, /* check exit triggered due to successful completion * of graceful restart. - * If no, bring down the neighbour. */ if (reason != OSPF_GR_HELPER_COMPLETED) { if (IS_DEBUG_OSPF_GR) - zlog_debug( - "%s, Failed GR exit, so bringing down the neighbour", - __func__); - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_KillNbr); + zlog_debug("%s, Unsuccessful GR exit", __func__); } /*Recalculate the DR for the network segment */ @@ -1016,7 +1013,8 @@ void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf, * Returns: * Nothing. */ -static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) +static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = NULL; struct tlv_header *tlvh = NULL; @@ -1026,6 +1024,9 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t length = 0; int sum = 0; + if (json) + return; + lsah = (struct lsa_header *)lsa->data; if (lsa->size <= OSPF_LSA_HEADER_SIZE) { diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index eb7a8348e8..81cc346000 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -477,7 +477,7 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf, if (oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; - if (if_is_loopback(oi->ifp) || if_is_vrf(oi->ifp)) + if (if_is_loopback_or_vrf(oi->ifp)) continue; if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) @@ -719,7 +719,7 @@ static int ospf_if_delete_hook(struct interface *ifp) int ospf_if_is_enable(struct ospf_interface *oi) { - if (!(if_is_loopback(oi->ifp) || if_is_vrf(oi->ifp))) + if (!(if_is_loopback_or_vrf(oi->ifp))) if (if_is_up(oi->ifp)) return 1; @@ -1291,7 +1291,7 @@ uint8_t ospf_default_iftype(struct interface *ifp) { if (if_is_pointopoint(ifp)) return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback(ifp) || if_is_vrf(ifp)) + else if (if_is_loopback_or_vrf(ifp)) return OSPF_IFTYPE_LOOPBACK; else return OSPF_IFTYPE_BROADCAST; diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 268fb81e52..865e7d37a8 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -76,10 +76,13 @@ static int ospf_inactivity_timer(struct thread *thread) */ if (!OSPF_GR_IS_ACTIVE_HELPER(nbr)) OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); - else if (IS_DEBUG_OSPF_GR) + else if (IS_DEBUG_OSPF_GR) { zlog_debug( - "%s, Acting as HELPER for this neighbour, So inactivitytimer event will not be fired.", + "%s, Acting as HELPER for this neighbour, So restart the dead timer", __func__); + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); + } return 0; } @@ -173,7 +176,7 @@ int nsm_should_adj(struct ospf_neighbor *nbr) } /* OSPF NSM functions. */ -static int nsm_packet_received(struct ospf_neighbor *nbr) +static int nsm_hello_received(struct ospf_neighbor *nbr) { /* Start or Restart Inactivity Timer. */ OSPF_NSM_TIMER_OFF(nbr->t_inactivity); @@ -418,7 +421,7 @@ const struct { { /* DependUpon: dummy state. */ {NULL, NSM_DependUpon}, /* NoEvent */ - {NULL, NSM_DependUpon}, /* PacketReceived */ + {NULL, NSM_DependUpon}, /* HelloReceived */ {NULL, NSM_DependUpon}, /* Start */ {NULL, NSM_DependUpon}, /* 2-WayReceived */ {NULL, NSM_DependUpon}, /* NegotiationDone */ @@ -435,7 +438,7 @@ const struct { { /* Deleted: dummy state. */ {NULL, NSM_Deleted}, /* NoEvent */ - {NULL, NSM_Deleted}, /* PacketReceived */ + {NULL, NSM_Deleted}, /* HelloReceived */ {NULL, NSM_Deleted}, /* Start */ {NULL, NSM_Deleted}, /* 2-WayReceived */ {NULL, NSM_Deleted}, /* NegotiationDone */ @@ -452,8 +455,8 @@ const struct { { /* Down: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ - {nsm_start, NSM_Attempt}, /* Start */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ + {nsm_start, NSM_Attempt}, /* Start */ {NULL, NSM_Down}, /* 2-WayReceived */ {NULL, NSM_Down}, /* NegotiationDone */ {NULL, NSM_Down}, /* ExchangeDone */ @@ -469,7 +472,7 @@ const struct { { /* Attempt: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ {NULL, NSM_Attempt}, /* Start */ {NULL, NSM_Attempt}, /* 2-WayReceived */ {NULL, NSM_Attempt}, /* NegotiationDone */ @@ -486,7 +489,7 @@ const struct { { /* Init: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ {NULL, NSM_Init}, /* Start */ {nsm_twoway_received, NSM_DependUpon}, /* 2-WayReceived */ {NULL, NSM_Init}, /* NegotiationDone */ @@ -503,7 +506,7 @@ const struct { { /* 2-Way: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_TwoWay}, /* HelloReceived */ + {nsm_hello_received, NSM_TwoWay}, /* HelloReceived */ {NULL, NSM_TwoWay}, /* Start */ {NULL, NSM_TwoWay}, /* 2-WayReceived */ {NULL, NSM_TwoWay}, /* NegotiationDone */ @@ -520,7 +523,7 @@ const struct { { /* ExStart: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_ExStart}, /* PacaketReceived */ + {nsm_hello_received, NSM_ExStart}, /* HelloReceived */ {NULL, NSM_ExStart}, /* Start */ {NULL, NSM_ExStart}, /* 2-WayReceived */ {nsm_negotiation_done, NSM_Exchange}, /* NegotiationDone */ @@ -537,7 +540,7 @@ const struct { { /* Exchange: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Exchange}, /* PacketReceived */ + {nsm_hello_received, NSM_Exchange}, /* HelloReceived */ {NULL, NSM_Exchange}, /* Start */ {NULL, NSM_Exchange}, /* 2-WayReceived */ {NULL, NSM_Exchange}, /* NegotiationDone */ @@ -554,7 +557,7 @@ const struct { { /* Loading: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Loading}, /* PacketReceived */ + {nsm_hello_received, NSM_Loading}, /* HelloReceived */ {NULL, NSM_Loading}, /* Start */ {NULL, NSM_Loading}, /* 2-WayReceived */ {NULL, NSM_Loading}, /* NegotiationDone */ @@ -571,7 +574,7 @@ const struct { { /* Full: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Full}, /* PacketReceived */ + {nsm_hello_received, NSM_Full}, /* HelloReceived */ {NULL, NSM_Full}, /* Start */ {NULL, NSM_Full}, /* 2-WayReceived */ {NULL, NSM_Full}, /* NegotiationDone */ @@ -588,7 +591,7 @@ const struct { }; static const char *const ospf_nsm_event_str[] = { - "NoEvent", "PacketReceived", "Start", + "NoEvent", "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone", "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived", "KillNbr", @@ -756,10 +759,8 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s: Initializing [DD]: %pI4 with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name - : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); ospf_db_desc_send(nbr); } diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index e8573c6301..798325f790 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -40,7 +40,7 @@ /* OSPF Neighbor State Machine Event. */ #define NSM_NoEvent 0 -#define NSM_PacketReceived 1 /* HelloReceived in the protocol */ +#define NSM_HelloReceived 1 /* HelloReceived in the protocol */ #define NSM_Start 2 #define NSM_TwoWayReceived 3 #define NSM_NegotiationDone 4 diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 9ec2ed0aa8..4670316db4 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -274,7 +274,8 @@ struct ospf_opaque_functab { void (*config_write_router)(struct vty *vty); void (*config_write_if)(struct vty *vty, struct interface *ifp); void (*config_write_debug)(struct vty *vty); - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa); + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); int (*lsa_originator)(void *arg); struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa); int (*new_lsa_hook)(struct ospf_lsa *lsa); @@ -373,7 +374,8 @@ int ospf_register_opaque_functab( void (*config_write_router)(struct vty *vty), void (*config_write_if)(struct vty *vty, struct interface *ifp), void (*config_write_debug)(struct vty *vty), - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa), int (*lsa_originator)(void *arg), struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), int (*new_lsa_hook)(struct ospf_lsa *lsa), @@ -578,7 +580,6 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab, oipt->lsa_type = new->data->type; oipt->opaque_type = GET_OPAQUE_TYPE(ntohl(new->data->id.s_addr)); oipt->status = PROC_NORMAL; - oipt->t_opaque_lsa_self = NULL; oipt->functab = functab; functab->oipt = oipt; oipt->id_list = list_new(); @@ -703,7 +704,6 @@ register_opaque_info_per_id(struct opaque_info_per_type *oipt, sizeof(struct opaque_info_per_id)); oipi->opaque_id = GET_OPAQUE_ID(ntohl(new->data->id.s_addr)); - oipi->t_opaque_lsa_self = NULL; oipi->opqctl_type = oipt; oipi->lsa = ospf_lsa_lock(new); @@ -1182,6 +1182,16 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); + } else { + json_object_string_add( + json, "opaqueType", + ospf_opaque_type_name(opaque_type)); + json_object_int_add(json, "opaqueId", opaque_id); + json_object_int_add(json, "opaqueDataLength", + ntohs(lsah->length) + - OSPF_LSA_HEADER_SIZE); + json_object_boolean_add(json, "opaqueDataLengthValid", + VALID_OPAQUE_INFO_LEN(lsah)); } } else { zlog_debug(" Opaque-Type %u (%s)", opaque_type, @@ -1197,7 +1207,7 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, /* Call individual output functions. */ if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL) if (functab->show_opaque_info != NULL) - (*functab->show_opaque_info)(vty, lsa); + (*functab->show_opaque_info)(vty, json, lsa); return; } @@ -1845,7 +1855,6 @@ static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t) int rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -1897,7 +1906,6 @@ static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t) int n, rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -1951,7 +1959,6 @@ static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t) int rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -2067,7 +2074,6 @@ static int ospf_opaque_lsa_refresh_timer(struct thread *t) zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)"); oipi = THREAD_ARG(t); - oipi->t_opaque_lsa_self = NULL; if ((lsa = oipi->lsa) != NULL) if ((functab = oipi->opqctl_type->functab) != NULL) diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index 7d401c3dcc..bded32215b 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -136,7 +136,8 @@ extern int ospf_register_opaque_functab( void (*config_write_router)(struct vty *vty), void (*config_write_if)(struct vty *vty, struct interface *ifp), void (*config_write_debug)(struct vty *vty), - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa), int (*lsa_originator)(void *arg), struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), int (*new_lsa_hook)(struct ospf_lsa *lsa), diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1efdfee3b4..4294c255af 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1031,7 +1031,7 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, old_state = nbr->state; /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_HelloReceived); /* RFC2328 Section 9.5.1 If the router is not eligible to become Designated Router, @@ -1134,6 +1134,21 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router; + + /* + * RFC 3623 - Section 2: + * "If the restarting router determines that it was the Designated + * Router on a given segment prior to the restart, it elects + * itself as the Designated Router again. The restarting router + * knows that it was the Designated Router if, while the + * associated interface is in Waiting state, a Hello packet is + * received from a neighbor listing the router as the Designated + * Router". + */ + if (oi->area->ospf->gr_info.restart_in_progress + && oi->state == ISM_Waiting + && IPV4_ADDR_SAME(&hello->d_router, &oi->address->u.prefix4)) + DR(oi) = hello->d_router; } /* Save DD flags/options/Seqnum received. */ @@ -1375,14 +1390,10 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, UNSET_FLAG(dd->options, OSPF_OPTION_O); } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: Neighbor %pI4 state is %s, seq_num:0x%x, local:0x%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, + ospf_get_name(oi->ospf), &nbr->router_id, lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), ntohl(dd->dd_seqnum), nbr->dd_seqnum); @@ -1620,9 +1631,6 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - /* Neighbor State should be Exchange or later. */ if (nbr->state != NSM_Exchange && nbr->state != NSM_Loading && nbr->state != NSM_Full) { @@ -1867,9 +1875,6 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - /* Check neighbor state. */ if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) @@ -2256,9 +2261,6 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) zlog_debug( @@ -3891,9 +3893,8 @@ void ospf_db_desc_send(struct ospf_neighbor *nbr) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: %pI4 DB Desc send with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); } /* Re-send Database Description. */ @@ -3911,9 +3912,8 @@ void ospf_db_desc_resend(struct ospf_neighbor *nbr) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: %pI4 DB Desc resend with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); } /* Send Link State Request. */ diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 602f98d141..0efa6ca4d5 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -73,7 +73,9 @@ static struct ospf_router_info OspfRI; static void ospf_router_info_ism_change(struct ospf_interface *oi, int old_status); static void ospf_router_info_config_write_router(struct vty *vty); -static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_router_info_show_info(struct vty *vty, + struct json_object *json, + struct ospf_lsa *lsa); static int ospf_router_info_lsa_originate(void *arg); static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa); static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai, @@ -1552,12 +1554,17 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh) return TLV_SIZE(tlvh); } -static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_router_info_show_info(struct vty *vty, + struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index d95e677f6f..03fa572859 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -87,7 +87,8 @@ static int ospf_mpls_te_del_if(struct interface *ifp); static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status); static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status); static void ospf_mpls_te_config_write_router(struct vty *vty); -static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_mpls_te_lsa_originate_area(void *arg); static int ospf_mpls_te_lsa_inter_as_as(void *arg); static int ospf_mpls_te_lsa_inter_as_area(void *arg); @@ -3783,7 +3784,8 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, return sum; } -static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh, *next; @@ -3791,6 +3793,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh, uint16_t subtotal, uint16_t total) = NULL; + if (json) + return; + sum = 0; total = lsa->size - OSPF_LSA_HEADER_SIZE; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4109ada64a..9863a10115 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -178,19 +178,11 @@ static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty, { if (use_vrf) { if (json) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_string_add(json, "vrfName", - "default"); - else - json_object_string_add(json, "vrfName", - ospf->name); + json_object_string_add(json, "vrfName", + ospf_get_name(ospf)); json_object_int_add(json, "vrfId", ospf->vrf_id); - } else { - if (ospf->vrf_id == VRF_DEFAULT) - vty_out(vty, "VRF Name: %s\n", "default"); - else if (ospf->name) - vty_out(vty, "VRF Name: %s\n", ospf->name); - } + } else + vty_out(vty, "VRF Name: %s\n", ospf_get_name(ospf)); } } @@ -230,8 +222,8 @@ DEFUN_NOSH (router_ospf, if (IS_DEBUG_OSPF_EVENT) zlog_debug( "Config command 'router ospf %d' received, vrf %s id %u oi_running %u", - ospf->instance, ospf->name ? ospf->name : "NIL", - ospf->vrf_id, ospf->oi_running); + ospf->instance, ospf_get_name(ospf), ospf->vrf_id, + ospf->oi_running); VTY_PUSH_CONTEXT(OSPF_NODE, ospf); @@ -571,8 +563,7 @@ DEFUN (ospf_network_area, if (IS_DEBUG_OSPF_EVENT) zlog_debug( "%s ospf vrf %s num of %u ip ospf area x config", - __func__, ospf->name ? ospf->name : "NIL", - count); + __func__, ospf_get_name(ospf), count); return CMD_WARNING_CONFIG_FAILED; } @@ -3343,12 +3334,8 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, if (json) { if (use_vrf) { json_object_object_add(json_vrf, "areas", json_areas); - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else { json_object_object_add(json, "areas", json_areas); } @@ -3970,12 +3957,8 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, if (use_json) { if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } } else vty_out(vty, "\n"); @@ -4115,14 +4098,9 @@ static int show_ip_ospf_interface_traffic_common( } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -4419,6 +4397,16 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty, json_object_string_add(json_neighbor, "state", msgbuf); + json_object_string_add( + json_neighbor, "converged", + lookup_msg(ospf_nsm_state_msg, + nbr->state, NULL)); + json_object_string_add( + json_neighbor, "role", + lookup_msg(ospf_ism_state_msg, + ospf_nbr_ism_state(nbr), + NULL)); + if (nbr->t_inactivity) { long time_store; @@ -4519,14 +4507,9 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, if (use_json) { json_object_object_add(json_vrf, "neighbors", json_nbr_sub); - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -4748,14 +4731,9 @@ static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -5541,14 +5519,9 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty, if (use_json) { json_object_object_add(json_vrf, "neighbors", json_nbr_sub); - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -5732,14 +5705,9 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else { vty_out(vty, "\n"); } @@ -7049,14 +7017,9 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, if ((argc == arg_base + 4) || (uj && (argc == arg_base + 5))) { show_ip_ospf_database_summary(vty, ospf, 0, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } @@ -7077,27 +7040,17 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, else if (strncmp(argv[arg_base + idx_type]->text, "se", 2) == 0) { show_ip_ospf_database_summary(vty, ospf, 1, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "m", 1) == 0) { show_ip_ospf_database_maxage(vty, ospf, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) @@ -7137,14 +7090,9 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, } if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } return CMD_SUCCESS; @@ -7373,14 +7321,9 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } return CMD_SUCCESS; @@ -10187,14 +10130,9 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); if (uj) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -11183,12 +11121,8 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, if (use_vrf) { // json_object_object_add(json_vrf, "areas", // json_areas); - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } } else { vty_out(vty, "\n"); @@ -11358,10 +11292,7 @@ DEFUN (show_ip_ospf_vrfs, if (uj) json_vrf = json_object_new_object(); - if (ospf->vrf_id == VRF_DEFAULT) - name = VRF_DEFAULT_NAME; - else - name = ospf->name; + name = ospf_get_name(ospf); vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) ? -1 @@ -11623,14 +11554,9 @@ static int ospf_show_summary_address(struct vty *vty, struct ospf *ospf, } if (uj) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 28def509d5..643269e34e 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -478,7 +478,7 @@ void pbr_send_rnh(struct nexthop *nhop, bool reg) break; } - if (zclient_send_rnh(zclient, command, &p, false, nhop->vrf_id) + if (zclient_send_rnh(zclient, command, &p, false, false, nhop->vrf_id) == ZCLIENT_SEND_FAILURE) { zlog_warn("%s: Failure to send nexthop to zebra", __func__); } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 5fb2ddf732..4cd94e0df9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3842,7 +3842,7 @@ static void pim_cli_legacy_mesh_group_behavior(struct vty *vty, xpath_member_value)) { member_dnode = yang_dnode_get(vty->candidate_config->dnode, xpath_member_value); - if (!yang_is_last_list_dnode(member_dnode)) + if (!member_dnode || !yang_is_last_list_dnode(member_dnode)) return; } @@ -9761,7 +9761,7 @@ DEFPY(no_ip_msdp_mesh_group_member, return CMD_WARNING_CONFIG_FAILED; } - nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); + nb_cli_enqueue_change(vty, xpath_member_value, NB_OP_DESTROY, NULL); /* * If this is the last member, then we must remove the group altogether @@ -9795,7 +9795,7 @@ DEFPY(ip_msdp_mesh_group_source, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - /* Create mesh group member. */ + /* Create mesh group source. */ strlcat(xpath_value, "/source", sizeof(xpath_value)); nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, saddr_str); @@ -9826,7 +9826,7 @@ DEFPY(no_ip_msdp_mesh_group_source, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - /* Create mesh group member. */ + /* Create mesh group source. */ strlcat(xpath_value, "/source", sizeof(xpath_value)); nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 50de7124d2..795c96c838 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -671,7 +671,6 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) ifaddr_str, query_interval, startup_mode ? "startup" : "non-startup", igmp->fd); } - igmp->t_igmp_query_timer = NULL; thread_add_timer(router->master, pim_igmp_general_query, igmp, query_interval, &igmp->t_igmp_query_timer); } @@ -1052,7 +1051,6 @@ static void igmp_read_on(struct igmp_sock *igmp) zlog_debug("Scheduling READ event on IGMP socket fd=%d", igmp->fd); } - igmp->t_igmp_read = NULL; thread_add_read(router->master, pim_igmp_read, igmp, igmp->fd, &igmp->t_igmp_read); } diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 78a8265a1c..5fff9fca0e 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -205,7 +205,6 @@ int pim_msdp_sock_listen(struct pim_instance *pim) /* add accept thread */ listener->fd = sock; memcpy(&listener->su, &sin, socklen); - listener->thread = NULL; thread_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock, &listener->thread); diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index f4627cbcc2..b9da8ec068 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -1168,6 +1168,7 @@ int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args) { struct pim_msdp_mg_mbr *mbr; struct pim_msdp_mg *mg; + const struct lyd_node *mg_dnode; switch (args->event) { case NB_EV_VALIDATE: @@ -1176,9 +1177,11 @@ int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args) break; case NB_EV_APPLY: mbr = nb_running_get_entry(args->dnode, NULL, true); - mg = nb_running_get_entry(args->dnode, "../", true); - + mg_dnode = + yang_dnode_get_parent(args->dnode, "msdp-mesh-groups"); + mg = nb_running_get_entry(mg_dnode, NULL, true); pim_msdp_mg_mbr_del(mg, mbr); + nb_running_unset_entry(args->dnode); break; } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 23ba3498ae..50cfc297d4 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -54,7 +54,8 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, int ret; p = &(pnc->rpf.rpf_addr); - ret = zclient_send_rnh(zclient, command, p, false, pim->vrf->vrf_id); + ret = zclient_send_rnh(zclient, command, p, false, false, + pim->vrf->vrf_id); if (ret == ZCLIENT_SEND_FAILURE) zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 8c38cf6c4c..3df7dc41ce 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -415,7 +415,6 @@ static void pim_sock_read_on(struct interface *ifp) zlog_debug("Scheduling READ event on PIM socket fd=%d", pim_ifp->pim_sock_fd); } - pim_ifp->t_pim_sock_read = NULL; thread_add_read(router->master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, &pim_ifp->t_pim_sock_read); } diff --git a/python/clidef.py b/python/clidef.py index a47cee2d6b..ba7c9072c5 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -435,6 +435,8 @@ if __name__ == "__main__": macros.load(os.path.join(basepath, "bgpd/bgp_vty.h")) # sigh :( macros["PROTO_REDIST_STR"] = "FRR_REDIST_STR_ISISD" + macros["PROTO_IP_REDIST_STR"] = "FRR_IP_REDIST_STR_ISISD" + macros["PROTO_IP6_REDIST_STR"] = "FRR_IP6_REDIST_STR_ISISD" errors = process_file(args.cfile, ofd, dumpfd, args.all_defun, macros) if errors != 0: diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index a2c86e3b22..2eb7bb6da1 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -805,7 +805,6 @@ static int rip_interface_wakeup(struct thread *t) ifp = THREAD_ARG(t); ri = ifp->info; - ri->t_wakeup = NULL; /* Join to multicast group. */ if (rip_multicast_join(ifp, ri->rip->sock) < 0) { diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 63493e2539..12c4edd436 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -95,7 +95,6 @@ static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr) } /* Update timeout thread. */ - peer->t_timeout = NULL; thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, &peer->t_timeout); diff --git a/ripd/ripd.c b/ripd/ripd.c index 84fb67956e..145b4de0a0 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -142,7 +142,6 @@ static int rip_garbage_collect(struct thread *t) struct route_node *rp; rinfo = THREAD_ARG(t); - rinfo->t_garbage_collect = NULL; /* Off timeout timer. */ RIP_TIMER_OFF(rinfo->t_timeout); @@ -1744,7 +1743,6 @@ static int rip_read(struct thread *t) /* Fetch socket then register myself. */ sock = THREAD_FD(t); - rip->t_read = NULL; /* Add myself to tne next event */ rip_event(rip, RIP_READ, sock); @@ -2545,9 +2543,6 @@ static int rip_update(struct thread *t) { struct rip *rip = THREAD_ARG(t); - /* Clear timer pointer. */ - rip->t_update = NULL; - if (IS_RIP_DEBUG_EVENT) zlog_debug("update timer fire!"); @@ -2588,8 +2583,6 @@ static int rip_triggered_interval(struct thread *t) { struct rip *rip = THREAD_ARG(t); - rip->t_triggered_interval = NULL; - if (rip->trigger) { rip->trigger = 0; rip_triggered_update(t); @@ -2603,9 +2596,6 @@ static int rip_triggered_update(struct thread *t) struct rip *rip = THREAD_ARG(t); int interval; - /* Clear thred pointer. */ - rip->t_triggered_update = NULL; - /* Cancel interval timer. */ RIP_TIMER_OFF(rip->t_triggered_interval); rip->trigger = 0; @@ -2628,7 +2618,6 @@ static int rip_triggered_update(struct thread *t) update is triggered when the timer expires. */ interval = (frr_weak_random() % 5) + 1; - rip->t_triggered_interval = NULL; thread_add_timer(master, rip_triggered_interval, rip, interval, &rip->t_triggered_interval); @@ -2834,7 +2823,6 @@ void rip_event(struct rip *rip, enum rip_event event, int sock) switch (event) { case RIP_READ: - rip->t_read = NULL; thread_add_read(master, rip_read, rip, sock, &rip->t_read); break; case RIP_UPDATE_EVENT: diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index f374fcb839..7b5e7604d2 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -618,7 +618,6 @@ static int ripng_interface_wakeup(struct thread *t) ifp = THREAD_ARG(t); ri = ifp->info; - ri->t_wakeup = NULL; /* Join to multicast group. */ if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) { diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 4f5c8e7760..86abf1eead 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -429,7 +429,6 @@ static int ripng_garbage_collect(struct thread *t) struct agg_node *rp; rinfo = THREAD_ARG(t); - rinfo->t_garbage_collect = NULL; /* Off timeout timer. */ RIPNG_TIMER_OFF(rinfo->t_timeout); @@ -1320,7 +1319,6 @@ static int ripng_read(struct thread *thread) /* Fetch thread data and set read pointer to empty for event managing. `sock' sould be same as ripng->sock. */ sock = THREAD_FD(thread); - ripng->t_read = NULL; /* Add myself to the next event. */ ripng_event(ripng, RIPNG_READ, sock); @@ -1418,9 +1416,6 @@ static int ripng_update(struct thread *t) struct interface *ifp; struct ripng_interface *ri; - /* Clear update timer thread. */ - ripng->t_update = NULL; - /* Logging update event. */ if (IS_RIPNG_DEBUG_EVENT) zlog_debug("RIPng update timer expired!"); @@ -1469,8 +1464,6 @@ static int ripng_triggered_interval(struct thread *t) { struct ripng *ripng = THREAD_ARG(t); - ripng->t_triggered_interval = NULL; - if (ripng->trigger) { ripng->trigger = 0; ripng_triggered_update(t); @@ -1486,8 +1479,6 @@ int ripng_triggered_update(struct thread *t) struct ripng_interface *ri; int interval; - ripng->t_triggered_update = NULL; - /* Cancel interval timer. */ thread_cancel(&ripng->t_triggered_interval); ripng->trigger = 0; @@ -1525,7 +1516,6 @@ int ripng_triggered_update(struct thread *t) update is triggered when the timer expires. */ interval = (frr_weak_random() % 5) + 1; - ripng->t_triggered_interval = NULL; thread_add_timer(master, ripng_triggered_interval, ripng, interval, &ripng->t_triggered_interval); @@ -1942,7 +1932,6 @@ void ripng_event(struct ripng *ripng, enum ripng_event event, int sock) /* Update timer jitter. */ jitter = ripng_update_jitter(ripng->update_time); - ripng->t_update = NULL; thread_add_timer(master, ripng_update, ripng, sock ? 2 : ripng->update_time + jitter, &ripng->t_update); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 12e5a6d4ac..6bf687b02a 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -137,10 +137,7 @@ struct ripng { /* RIPng threads. */ struct thread *t_read; - struct thread *t_write; struct thread *t_update; - struct thread *t_garbage; - struct thread *t_zebra; /* Triggered update hack. */ int trigger; diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 2575475dd2..67cff378ee 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -626,19 +626,12 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, { int command; - if (!import) { - command = ZEBRA_NEXTHOP_REGISTER; + command = ZEBRA_NEXTHOP_REGISTER; - if (!watch) - command = ZEBRA_NEXTHOP_UNREGISTER; - } else { - command = ZEBRA_IMPORT_ROUTE_REGISTER; - - if (!watch) - command = ZEBRA_IMPORT_ROUTE_UNREGISTER; - } + if (!watch) + command = ZEBRA_NEXTHOP_UNREGISTER; - if (zclient_send_rnh(zclient, command, p, connected, vrf_id) + if (zclient_send_rnh(zclient, command, p, connected, false, vrf_id) == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } @@ -984,7 +977,6 @@ void sharp_zebra_init(void) zclient->interface_address_delete = interface_address_delete; zclient->route_notify_owner = route_notify_owner; zclient->nexthop_update = sharp_nexthop_update; - zclient->import_check_update = sharp_nexthop_update; zclient->nhg_notify_owner = nhg_notify_owner; zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; zclient->redistribute_route_add = sharp_redistribute_route; diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 452b5c42a4..a01ecad815 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -332,7 +332,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg) static_nht_hash_free(nhtd); } - if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) + if (zclient_send_rnh(zclient, cmd, &p, false, false, nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } diff --git a/tests/lib/cli/test_commands.refout b/tests/lib/cli/test_commands.refout index 9d4a6ef03e..2ec3e5504b 100644 --- a/tests/lib/cli/test_commands.refout +++ b/tests/lib/cli/test_commands.refout @@ -191,38 +191,38 @@ execute strict 'no ipv6 nd mtu 1'@11: rv==0, 'no ipv6 nd mtu <1-65535>': '1' complete 'no ipv6 nd mtu 1'@11: rv==2 describe 'no ipv6 nd mtu 1'@11: rv==0 '<1-65535>' 'MTU in bytes' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0 diff --git a/tests/lib/test_grpc.cpp b/tests/lib/test_grpc.cpp index 491796802a..0aa1bbb7e1 100644 --- a/tests/lib/test_grpc.cpp +++ b/tests/lib/test_grpc.cpp @@ -81,11 +81,16 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = { static int grpc_thread_stop(struct thread *thread); +static void _err_print(const void *cookie, const char *errstr) +{ + std::cout << "Failed to load grpc module:" << errstr << std::endl; +} + static void static_startup(void) { // struct frrmod_runtime module; // static struct option_chain *oc; - char moderr[256] = {}; + cmd_init(1); zlog_aux_init("NONE: ", LOG_DEBUG); @@ -94,17 +99,14 @@ static void static_startup(void) /* Load the server side module -- check libtool path first */ std::string modpath = std::string(binpath) + std::string("../../../lib/.libs"); - grpc_module = frrmod_load("grpc:50051", modpath.c_str(), moderr, sizeof(moderr)); + grpc_module = frrmod_load("grpc:50051", modpath.c_str(), 0, 0); if (!grpc_module) { modpath = std::string(binpath) + std::string("../../lib"); - grpc_module = frrmod_load("grpc:50051", modpath.c_str(), moderr, - sizeof(moderr)); + grpc_module = frrmod_load("grpc:50051", modpath.c_str(), + _err_print, 0); } - if (!grpc_module) { - std::cout << "Failed to load grpc module:" << moderr - << std::endl; + if (!grpc_module) exit(1); - } static_debug_init(); diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c index 416ea39772..1756d87a6f 100644 --- a/tests/lib/test_timer_correctness.c +++ b/tests/lib/test_timer_correctness.c @@ -134,7 +134,6 @@ int main(int argc, char **argv) /* Schedule timers to expire in 0..5 seconds */ interval_msec = prng_rand(prng) % 5000; arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1); - timers[i] = NULL; thread_add_timer_msec(master, timer_func, arg, interval_msec, &timers[i]); ret = snprintf(arg, TIMESTR_LEN + 1, "%lld.%06lld", @@ -154,7 +153,6 @@ int main(int argc, char **argv) XFREE(MTYPE_TMP, timers[index]->arg); thread_cancel(&timers[index]); - timers[index] = NULL; timers_pending--; } diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c index 45b29b92b1..f9d634b6a6 100644 --- a/tests/lib/test_timer_performance.c +++ b/tests/lib/test_timer_performance.c @@ -55,7 +55,6 @@ int main(int argc, char **argv) /* create thread structures so they won't be allocated during the * time measurement */ for (i = 0; i < SCHEDULE_TIMERS; i++) { - timers[i] = NULL; thread_add_timer_msec(master, dummy_func, NULL, 0, &timers[i]); } for (i = 0; i < SCHEDULE_TIMERS; i++) @@ -67,7 +66,6 @@ int main(int argc, char **argv) long interval_msec; interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS); - timers[i] = NULL; thread_add_timer_msec(master, dummy_func, NULL, interval_msec, &timers[i]); } @@ -79,7 +77,6 @@ int main(int argc, char **argv) index = prng_rand(prng) % SCHEDULE_TIMERS; thread_cancel(&timers[index]); - timers[index] = NULL; } monotime(&tv_stop); 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 1b99fcea1f..e8a793cfee 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -115,7 +115,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -127,7 +127,8 @@ def teardown_module(module): def test_router_running(): global fatal_error - net = get_topogen().net + tgen = get_topogen() + net = tgen.net # Skip if previous fatal error condition is raised if fatal_error != "": @@ -143,7 +144,7 @@ def test_router_running(): assert fatal_error == "", fatal_error # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def test_error_messages_vtysh(): @@ -198,9 +199,6 @@ def test_error_messages_vtysh(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_error_messages_daemons(): global fatal_error @@ -289,9 +287,6 @@ def test_error_messages_daemons(): assert error_logs == "", "Daemons report errors to StdErr" - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -325,7 +320,7 @@ def test_converge_protocols(): actual = ( net["r%s" % i] .cmd( - "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null" + "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null" ) .rstrip() ) @@ -358,7 +353,7 @@ def test_converge_protocols(): actual = ( net["r%s" % i] .cmd( - "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null" + "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null" ) .rstrip() ) @@ -379,9 +374,6 @@ def test_converge_protocols(): assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff) - # For debugging after starting FRR daemons, uncomment the next line - ## CLI(net) - def route_get_nhg_id(route_str): net = get_topogen().net @@ -567,8 +559,6 @@ def test_nexthop_groups(): % nhg_id ) - ##CLI(net) - ## Remove all NHG routes net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.1 1"') @@ -638,9 +628,6 @@ def test_rip_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_status(): global fatal_error @@ -705,9 +692,6 @@ def test_ripng_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ospfv2_interfaces(): global fatal_error @@ -790,9 +774,6 @@ def test_ospfv2_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_isis_interfaces(): global fatal_error @@ -856,9 +837,6 @@ def test_isis_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_summary(): global fatal_error @@ -966,7 +944,7 @@ def test_bgp_summary(): r"(192.168.7.(1|2)0|fc00:0:0:8::2000).+Active.+", "", expected ) elif "10.0.0.1" in arguments: - expected = "No such neighbor in VRF default" + expected = "No such neighbor in this view/vrf" if "terse" in arguments: expected = re.sub(r"BGP table version .+", "", expected) @@ -1037,9 +1015,6 @@ def test_bgp_summary(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_ipv6_summary(): global fatal_error @@ -1138,12 +1113,15 @@ def test_bgp_ipv6_summary(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_nht(): + global fatal_error net = get_topogen().net + + # Skip if previous fatal error condition is raised + if fatal_error != "": + pytest.skip(fatal_error) + print("\n\n**** Test that nexthop tracking is at least nominally working ****\n") thisDir = os.path.dirname(os.path.realpath(__file__)) @@ -1256,9 +1234,6 @@ def test_bgp_ipv4(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_ipv6(): global fatal_error @@ -1325,9 +1300,6 @@ def test_bgp_ipv6(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_route_map(): global fatal_error @@ -1567,9 +1539,6 @@ def test_mpls_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf index 18def599b4..98da8c2619 100644 --- a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf @@ -6,10 +6,14 @@ hostname rt1 password 1 ! interface eth-rt2 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt3 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf index 07b42f9885..9da8765005 100644 --- a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf @@ -10,13 +10,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt2 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt3 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! router ospf diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf index 2f35099564..34b0902094 100644 --- a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf @@ -5,10 +5,14 @@ hostname rt2 password 1 ! interface eth-rt1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt5 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf index a05d8b58c8..11be6a14b2 100644 --- a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf @@ -9,13 +9,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt1 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt5 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 2.2.2.2 diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf index 3e8777019e..8ab4eee1d3 100644 --- a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf @@ -5,10 +5,14 @@ hostname rt3 password 1 ! interface eth-rt1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt4 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf index 1196e6d189..acc54b3866 100644 --- a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf @@ -9,13 +9,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt1 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt4 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 3.3.3.3 diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf index bccd1e75bd..138b688140 100644 --- a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf @@ -5,9 +5,13 @@ hostname rt4 password 1 ! interface eth-rt3 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! interface eth-rt5 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf index 3a2568b4ab..670e56ccc8 100644 --- a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf @@ -9,12 +9,18 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt3 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt5 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 4.4.4.4 diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf index 766862276c..6eb4fe59a8 100644 --- a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf @@ -6,9 +6,13 @@ password 1 ! interface eth-rt2 ipv6 ospf6 network broadcast + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ! interface eth-rt4 ipv6 ospf6 network broadcast + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ! router ospf6 ospf6 router-id 5.5.5.5 diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf index a35de5f45f..286de51288 100644 --- a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf @@ -9,12 +9,18 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt2 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt4 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 5.5.5.5 diff --git a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py index 09b8631740..bef2c3f162 100755 --- a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py +++ b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py @@ -132,7 +132,7 @@ def print_cmd_result(rname, command): print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False)) -def router_compare_json_output(rname, command, reference, count=120, wait=0.5): +def router_compare_json_output(rname, command, reference, count=40, wait=2): "Compare router JSON output" logger.info('Comparing router "%s" "%s" output', rname, command) @@ -141,7 +141,7 @@ def router_compare_json_output(rname, command, reference, count=120, wait=0.5): filename = "{}/{}/{}".format(CWD, rname, reference) expected = json.loads(open(filename).read()) - # Run test function until we get an result. Wait at most 60 seconds. + # Run test function until we get an result. Wait at most 80 seconds. test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) _, diff = topotest.run_and_expect(test_func, None, count=count, wait=wait) assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) @@ -195,8 +195,8 @@ def test_bfd_ospf_interface_failure_rt2_step3(): # By default BFD provides a recovery time of 900ms plus jitter, so let's wait # initial 2 seconds to let the CI not suffer. - # TODO: add check for array size - sleep(2) + topotest.sleep(2, 'Wait for BFD down notification') + router_compare_json_output( "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 1, 0 ) @@ -234,8 +234,7 @@ def test_bfd_ospf_interface_failure_rt3_step3(): # By default BFD provides a recovery time of 900ms plus jitter, so let's wait # initial 2 seconds to let the CI not suffer. - # TODO: add check for array size - sleep(2) + topotest.sleep(2, 'Wait for BFD down notification') router_compare_json_output( "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 1, 0 ) diff --git a/tests/topotests/bgp_features/r1/ospf_neighbor.json b/tests/topotests/bgp_features/r1/ospf_neighbor.json index e742c119da..3b5f46d934 100644 --- a/tests/topotests/bgp_features/r1/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r1/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.2":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ], "192.168.0.3":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ] } diff --git a/tests/topotests/bgp_features/r2/ospf_neighbor.json b/tests/topotests/bgp_features/r2/ospf_neighbor.json index 2fd589ae25..47bb57cd00 100644 --- a/tests/topotests/bgp_features/r2/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r2/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.1":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ], "192.168.0.3":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ] } diff --git a/tests/topotests/bgp_features/r3/ospf_neighbor.json b/tests/topotests/bgp_features/r3/ospf_neighbor.json index 80fc92c3bc..b84974ccca 100644 --- a/tests/topotests/bgp_features/r3/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r3/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.1":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ], "192.168.0.2":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ] } diff --git a/tests/topotests/bgp_flowspec/r1/zebra.conf b/tests/topotests/bgp_flowspec/r1/zebra.conf index e4d5a21194..4b103cb398 100644 --- a/tests/topotests/bgp_flowspec/r1/zebra.conf +++ b/tests/topotests/bgp_flowspec/r1/zebra.conf @@ -1,6 +1,7 @@ ! hostname r1 password zebra +ip table range 500 600 interface r1-eth0 ip address 10.0.1.1/24 ipv6 address 1001::1/112 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py index 8fd344696e..fce8e708f2 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py @@ -206,7 +206,7 @@ def ltemplatePreRouterStartHook(): for cmd in cmds: cc.doCmd(tgen, rtr, cmd.format(rtr)) cc.doCmd(tgen, rtr, "ip link set dev {0}-eth0 master {0}-cust2".format(rtr)) - if cc.getOutput() != 4: + if cc.getOutput() != 0: InitSuccess = False logger.info( "Unexpected output seen ({} times, tests will be skipped".format( @@ -214,6 +214,11 @@ def ltemplatePreRouterStartHook(): ) ) else: + rtrs = ["r1", "r3", "r4", "ce4"] + for rtr in rtrs: + logger.info("{} configured".format(rtr)) + cc.doCmd(tgen, rtr, "ip -d link show type vrf") + cc.doCmd(tgen, rtr, "ip link show") InitSuccess = True logger.info("VRF config successful!") return InitSuccess diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py index a5f95f94bf..91a7adf997 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py @@ -4,7 +4,7 @@ from lib import topotest ret = luCommand( "r2", "ip -M route show", - "\d*(?= via inet 10.0.2.4 dev r2-eth1)", + r"\d*(?= via inet 10.0.2.4 dev r2-eth1)", "wait", "See mpls route to r4", ) @@ -16,7 +16,7 @@ if ret != False and found != None: ret = luCommand( "r2", "ip -M route show", - "\d*(?= via inet 10.0.1.1 dev r2-eth0)", + r"\d*(?= via inet 10.0.1.1 dev r2-eth0)", "wait", "See mpls route to r1", ) 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 9f100b7c30..eaa6aa4c30 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 @@ -21,7 +21,7 @@ for rtr in rtrs: ret = luCommand( rtr, 'vtysh -c "show memory"', - "zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", + r"zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", "none", "collect bgpd memory stats", ) @@ -188,7 +188,7 @@ else: ret = luCommand( rtr, 'vtysh -c "show memory"', - "zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", + r"zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", "none", "collect bgpd memory stats", ) diff --git a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py index 74d5edecab..a0cae0a40b 100644 --- a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py +++ b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py @@ -105,15 +105,21 @@ def setup_module(mod): "ip link add {0}-cust1 type vrf table 1001", "ip link add loop1 type dummy", "ip link set {0}-eth0 master {0}-cust1", - "ip link set {0}-eth1 master {0}-cust1", ] + eth1_cmds = ["ip link set {0}-eth1 master {0}-cust1"] + # For all registered routers, load the zebra configuration file for rname, router in tgen.routers().items(): # create VRF rx-cust1 and link rx-eth0 to rx-cust1 for cmd in cmds: output = tgen.net[rname].cmd(cmd.format(rname)) + # If router has an rX-eth1, link that to vrf also + if "{}-eth1".format(rname) in router.links.keys(): + for cmd in eth1_cmds: + output = output + tgen.net[rname].cmd(cmd.format(rname)) + for rname, router in tgen.routers().items(): router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) diff --git a/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json index aa3f74fc5f..63281e9be3 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"r1-eth0:10.0.1.1" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json index aa68198957..f361d605ce 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1":[ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth0:10.0.1.2" } @@ -11,7 +11,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r2-eth1:10.0.2.2" } @@ -19,7 +19,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r2-eth1:10.0.2.2" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json index 905774fc46..38794357ff 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r3-eth0:10.0.2.3" } @@ -11,7 +11,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r3-eth0:10.0.2.3" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json index 67593952ca..fccca693b9 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json @@ -4,7 +4,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r4-eth0:10.0.2.4" } @@ -12,7 +12,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r4-eth0:10.0.2.4" } diff --git a/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json index aa3f74fc5f..63281e9be3 100644 --- a/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"r1-eth0:10.0.1.1" } diff --git a/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json index aa68198957..f361d605ce 100644 --- a/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1":[ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth0:10.0.1.2" } @@ -11,7 +11,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r2-eth1:10.0.2.2" } @@ -19,7 +19,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r2-eth1:10.0.2.2" } diff --git a/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json index 905774fc46..38794357ff 100644 --- a/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r3-eth0:10.0.2.3" } @@ -11,7 +11,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r3-eth0:10.0.2.3" } diff --git a/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json index 67593952ca..fccca693b9 100644 --- a/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json @@ -4,7 +4,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r4-eth0:10.0.2.4" } @@ -12,7 +12,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r4-eth0:10.0.2.4" } diff --git a/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json index 3bfda39071..7efde22f3f 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json @@ -5,7 +5,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 1, - "state": "Full/DROther", + "converged": "Full", "address": "10.0.1.2", "ifaceName": "r1-eth1:10.0.1.1", "requestCounter": 0 @@ -16,7 +16,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 1, - "state": "Full/DROther", + "converged": "Full", "address": "10.0.2.3", "ifaceName": "r1-eth2:10.0.2.1", "requestCounter": 0 diff --git a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json index 5b7a5ebbb9..5bea193e01 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth1:10.0.1.2", "retransmitCounter":0, @@ -14,7 +14,7 @@ "3.3.3.3": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"r2-eth2:10.0.3.2", "retransmitCounter":0, diff --git a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json index 1b29b9f947..9966297d8a 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.2.1", "ifaceName":"r3-eth1:10.0.2.3", "retransmitCounter":0, @@ -14,7 +14,7 @@ "2.2.2.2": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.3.2", "ifaceName":"r3-eth2:10.0.3.3", "retransmitCounter":0, diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py index c21d6bf28e..834205f653 100644 --- a/tests/topotests/ldp_topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py @@ -126,7 +126,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -153,9 +153,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_interfaces(): global fatal_error @@ -219,9 +216,6 @@ def test_mpls_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_neighbor_establish(): global fatal_error @@ -356,9 +350,6 @@ def test_mpls_ldp_discovery(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_neighbor(): global fatal_error @@ -426,9 +417,6 @@ def test_mpls_ldp_neighbor(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_binding(): global fatal_error @@ -518,9 +506,6 @@ def test_mpls_ldp_binding(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv4_routingTable(): global fatal_error @@ -595,9 +580,6 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_table(): global fatal_error @@ -674,9 +656,6 @@ def test_mpls_table(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_linux_mpls_routes(): global fatal_error @@ -758,9 +737,6 @@ def test_linux_mpls_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json index 7e281abb5f..90c8195416 100644 --- a/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json @@ -5,7 +5,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 2, - "state": "Full\/DR", + "converged": "Full", "address": "10.0.1.2", "ifaceName": "r1-eth1:10.0.1.1", "requestCounter": 0 @@ -16,7 +16,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 2, - "state": "Full\/DR", + "converged": "Full", "address": "10.0.2.3", "ifaceName": "r1-eth2:10.0.2.1", "requestCounter": 0 diff --git a/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json index 22fd98f519..29dde53c6d 100644 --- a/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth1:10.0.1.2", "retransmitCounter":0, @@ -14,7 +14,7 @@ "3.3.3.3": [ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"r2-eth2:10.0.3.2", "retransmitCounter":0, diff --git a/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json index 970eb2fc1d..9966297d8a 100644 --- a/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.1", "ifaceName":"r3-eth1:10.0.2.3", "retransmitCounter":0, @@ -14,7 +14,7 @@ "2.2.2.2": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.3.2", "ifaceName":"r3-eth2:10.0.3.3", "retransmitCounter":0, diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index 910573c14c..18882285ed 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -217,6 +217,7 @@ class ltemplateRtrCmd: self.resetCounts() def doCmd(self, tgen, rtr, cmd, checkstr=None): + logger.info("doCmd: {} {}".format(rtr, cmd)) output = tgen.net[rtr].cmd(cmd).strip() if len(output): self.output += 1 @@ -227,9 +228,10 @@ class ltemplateRtrCmd: else: self.match += 1 return ret - logger.info("command: {} {}".format(rtr, cmd)) logger.info("output: " + output) - self.none += 1 + else: + logger.info("No output") + self.none += 1 return None def resetCounts(self): @@ -289,7 +291,7 @@ def ltemplateVersionCheck( # collect/log info on iproute2 cc = ltemplateRtrCmd() found = cc.doCmd( - tgen, rname, "apt-cache policy iproute2", "Installed: ([\d\.]*)" + tgen, rname, "apt-cache policy iproute2", r"Installed: ([\d\.]*)" ) if found != None: iproute2Ver = found.group(1) diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index 9d37088218..944981add4 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -1020,10 +1020,10 @@ def verify_ip_mroutes( if not isinstance(group_addresses, list): group_addresses = [group_addresses] - if not isinstance(iif, list) and iif is not "none": + if not isinstance(iif, list) and iif != "none": iif = [iif] - if not isinstance(oil, list) and oil is not "none": + if not isinstance(oil, list) and oil != "none": oil = [oil] for grp_addr in group_addresses: diff --git a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py index ccbcadb8b1..e59333ebd2 100755 --- a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py +++ b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py @@ -171,14 +171,60 @@ def router_compare_json_output(rname, command, reference, tries): assert diff is None, assertmsg +def expect_grace_lsa(restarting, helper): + """ + Check if the given helper neighbor has already received a Grace-LSA from + the router performing a graceful restart. + """ + tgen = get_topogen() + + logger.info( + "'{}': checking if a Grace-LSA was received from '{}'".format( + helper, restarting + ) + ) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[helper], + "show ipv6 ospf6 database json", + { + "interfaceScopedLinkStateDb": [ + { + "lsa": [ + { + "type": "GR", + "advRouter": restarting, + } + ] + } + ] + }, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting) + + assert result is None, assertmsg + + def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in # all routers of the routing domain. + # If we are not on initial convergence *but* we are checking + # after a restart. Looking in the zebra rib for installed + # is a recipe for test failure. Why? because if we are restarting + # then ospf is in the process of establishing neighbors and passing + # new routes to zebra. Zebra will not mark the route as installed + # when it receives a replacement from ospf until it has finished + # processing it. Let's give it a few seconds to allow this to happen + # under load. if initial_convergence == True: tries = 240 else: - tries = 1 + if restarting != None: + tries = 40 + else: + tries = 1 router_compare_json_output( rname, "show ipv6 route ospf json", "show_ipv6_route.json", tries ) @@ -212,6 +258,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): ) +def ensure_gr_is_in_zebra(rname): + retry = True + retry_times = 10 + tgen = get_topogen() + + while retry and retry_times > 0: + out = tgen.net[rname].cmd( + 'vtysh -c "show zebra client" | grep "Client: ospf6$" -A 40 | grep "Capabilities "' + ) + + if "Graceful Restart" not in out: + sleep(2) + retry_times -= 1 + else: + retry = False + + assertmsg = "%s does not appear to have Graceful Restart setup" % rname + assert not retry and retry_times > 0, assertmsg + + # # Test initial network convergence # @@ -238,10 +304,10 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="1.1.1.1", helper="rt2") + ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospf6d"], save_config=False) check_routers(exiting="rt1") - start_router_daemons(tgen, "rt1", ["ospf6d"]) check_routers(restarting="rt1") @@ -258,7 +324,9 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="2.2.2.2", helper="rt1") + expect_grace_lsa(restarting="2.2.2.2", helper="rt3") + ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospf6d"], save_config=False) check_routers(exiting="rt2") @@ -278,7 +346,10 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="3.3.3.3", helper="rt2") + expect_grace_lsa(restarting="3.3.3.3", helper="rt4") + expect_grace_lsa(restarting="3.3.3.3", helper="rt6") + ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospf6d"], save_config=False) check_routers(exiting="rt3") @@ -298,7 +369,9 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="4.4.4.4", helper="rt3") + expect_grace_lsa(restarting="4.4.4.4", helper="rt5") + ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospf6d"], save_config=False) check_routers(exiting="rt4") @@ -318,7 +391,8 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="5.5.5.5", helper="rt4") + ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospf6d"], save_config=False) check_routers(exiting="rt5") @@ -338,7 +412,9 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="6.6.6.6", helper="rt3") + expect_grace_lsa(restarting="6.6.6.6", helper="rt7") + ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospf6d"], save_config=False) check_routers(exiting="rt6") @@ -358,7 +434,8 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + expect_grace_lsa(restarting="6.6.6.6", helper="rt6") + ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospf6d"], save_config=False) check_routers(exiting="rt7") diff --git a/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json index ed290323a4..f82758101c 100644 --- a/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "2.2.2.2":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"eth-rt2:10.0.1.1" } diff --git a/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json index 4fe92b0b98..5a0b092702 100644 --- a/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "1.1.1.1":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"eth-rt1:10.0.1.2" } ], "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"eth-rt3:10.0.2.2" } diff --git a/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json index e3c36ab9a3..ab5e78414d 100644 --- a/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json @@ -2,21 +2,21 @@ "neighbors":{ "2.2.2.2":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"eth-rt2:10.0.2.3" } ], "4.4.4.4":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.3.4", "ifaceName":"eth-rt4:10.0.3.3" } ], "6.6.6.6":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.4.6", "ifaceName":"eth-rt6:10.0.4.3" } diff --git a/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json index 2123ecb8da..405679c10e 100644 --- a/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"eth-rt3:10.0.3.4" } ], "5.5.5.5":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.5.5", "ifaceName":"eth-rt5:10.0.5.4" } diff --git a/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json index 6440b67698..893d454368 100644 --- a/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "4.4.4.4":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.5.4", "ifaceName":"eth-rt4:10.0.5.5" } diff --git a/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json index d815c23927..564a513ac6 100644 --- a/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.4.3", "ifaceName":"eth-rt3:10.0.4.6" } ], "7.7.7.7":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.6.7", "ifaceName":"eth-rt7:10.0.6.6" } diff --git a/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json index 2254aea9a6..bc6b60697c 100644 --- a/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "6.6.6.6":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.6.6", "ifaceName":"eth-rt6:10.0.6.7" } diff --git a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py index 7d9cc68412..3e3bf5cb8c 100755 --- a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py +++ b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py @@ -180,14 +180,60 @@ def router_compare_json_output(rname, command, reference, tries): assert diff is None, assertmsg +def expect_grace_lsa(restarting, area, helper): + """ + Check if the given helper neighbor has already received a Grace-LSA from + the router performing a graceful restart. + """ + tgen = get_topogen() + + logger.info( + "'{}': checking if a Grace-LSA was received from '{}'".format( + helper, restarting + ) + ) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[helper], + "show ip ospf database opaque-link json", + { + "linkLocalOpaqueLsa": { + "areas": { + area: [ + { + "advertisingRouter": restarting, + "opaqueType": "Grace-LSA", + } + ] + } + } + }, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting) + + assert result is None, assertmsg + + def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in # all routers of the routing domain. + # If we are not on initial convergence *but* we are checking + # after a restart. Looking in the zebra rib for installed + # is a recipe for test failure. Why? because if we are restarting + # then ospf is in the process of establishing neighbors and passing + # new routes to zebra. Zebra will not mark the route as installed + # when it receives a replacement from ospf until it has finished + # processing it. Let's give it a few seconds to allow this to happen + # under load. if initial_convergence == True: tries = 240 else: - tries = 1 + if restarting != None: + tries = 40 + else: + tries = 1 router_compare_json_output( rname, "show ip route ospf json", "show_ip_route.json", tries ) @@ -215,6 +261,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): ) +def ensure_gr_is_in_zebra(rname): + retry = True + retry_times = 10 + tgen = get_topogen() + + while retry and retry_times > 0: + out = tgen.net[rname].cmd( + 'vtysh -c "show zebra client" | grep "Client: ospf$" -A 40 | grep "Capabilities "' + ) + + if "Graceful Restart" not in out: + sleep(2) + retry_times -= 1 + else: + retry = False + + assertmsg = "%s does not appear to have Graceful Restart setup" % rname + assert not retry and retry_times > 0, assertmsg + + # # Test initial network convergence # @@ -241,7 +307,8 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="1.1.1.1", area="0.0.0.1", helper="rt2") + ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False) check_routers(exiting="rt1") @@ -261,7 +328,9 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.1", helper="rt1") + expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.0", helper="rt3") + ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False) check_routers(exiting="rt2") @@ -281,7 +350,10 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt2") + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt4") + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt6") + ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False) check_routers(exiting="rt3") @@ -301,7 +373,9 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.0", helper="rt3") + expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.2", helper="rt5") + ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False) check_routers(exiting="rt4") @@ -321,7 +395,8 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="5.5.5.5", area="0.0.0.2", helper="rt4") + ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False) check_routers(exiting="rt5") @@ -341,7 +416,9 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.0", helper="rt3") + expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.3", helper="rt7") + ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False) check_routers(exiting="rt6") @@ -361,7 +438,8 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + expect_grace_lsa(restarting="7.7.7.7", area="0.0.0.3", helper="rt6") + ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False) check_routers(exiting="rt7") diff --git a/tests/topotests/ospf_topo1/test_ospf_topo1.py b/tests/topotests/ospf_topo1/test_ospf_topo1.py index d84c41bea3..710895cc6b 100644 --- a/tests/topotests/ospf_topo1/test_ospf_topo1.py +++ b/tests/topotests/ospf_topo1/test_ospf_topo1.py @@ -135,7 +135,7 @@ def test_wait_protocol_convergence(): ) if ( topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/DR"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) is None ): @@ -143,14 +143,14 @@ def test_wait_protocol_convergence(): if ( topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/DROther"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) is None ): return None return topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/Backup"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) _, result = topotest.run_and_expect( diff --git a/tests/topotests/pim_acl/r1/ospf_neighbor.json b/tests/topotests/pim_acl/r1/ospf_neighbor.json index a8fc093e90..af83d6bea3 100644 --- a/tests/topotests/pim_acl/r1/ospf_neighbor.json +++ b/tests/topotests/pim_acl/r1/ospf_neighbor.json @@ -3,7 +3,7 @@ "192.168.0.11":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.11", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -14,7 +14,7 @@ "192.168.0.12":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.12", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -25,7 +25,7 @@ "192.168.0.13":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.13", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -36,7 +36,7 @@ "192.168.0.14":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.14", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -47,7 +47,7 @@ "192.168.0.15":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.15", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json index 604d25fac1..1e70fcc36e 100644 --- a/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json +++ b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json @@ -5,7 +5,7 @@ "192.168.0.11":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.11", "ifaceName":"r1-eth1:192.168.101.1" } diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json b/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json index 456bb87520..7f2ab248cc 100644 --- a/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json +++ b/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json @@ -5,7 +5,7 @@ "192.168.0.12":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.12", "ifaceName":"r1-eth3:192.168.101.1" } diff --git a/tests/topotests/rip_topo1/test_rip_topo1.py b/tests/topotests/rip_topo1/test_rip_topo1.py index c5812f28cf..7d59e8422f 100644 --- a/tests/topotests/rip_topo1/test_rip_topo1.py +++ b/tests/topotests/rip_topo1/test_rip_topo1.py @@ -108,7 +108,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -134,9 +134,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -159,9 +156,6 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_rip_status(): global fatal_error @@ -220,9 +214,6 @@ def test_rip_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_rip_routes(): global fatal_error @@ -275,9 +266,6 @@ def test_rip_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv4_routingTable(): global fatal_error @@ -341,9 +329,6 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tests/topotests/ripng_topo1/test_ripng_topo1.py b/tests/topotests/ripng_topo1/test_ripng_topo1.py index df81ac08c4..563c4f7497 100644 --- a/tests/topotests/ripng_topo1/test_ripng_topo1.py +++ b/tests/topotests/ripng_topo1/test_ripng_topo1.py @@ -104,7 +104,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -130,9 +130,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -155,9 +152,6 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_status(): global fatal_error @@ -223,9 +217,6 @@ def test_ripng_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_routes(): global fatal_error @@ -290,9 +281,6 @@ def test_ripng_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv6_routingTable(): global fatal_error @@ -358,9 +346,6 @@ def test_zebra_ipv6_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tools/coccinelle/struct_thread_double_pointer.cocci b/tools/coccinelle/struct_thread_double_pointer.cocci new file mode 100644 index 0000000000..a08e6727cf --- /dev/null +++ b/tools/coccinelle/struct_thread_double_pointer.cocci @@ -0,0 +1,35 @@ +@r1@ +identifier fn, m, f, a, v, t; +identifier func =~ "thread_add_"; +type T1, T2; +position p; +@@ + +?static +T1 fn(T2 *t) +{ +... +func(m,f,a,v,&t)@p +... +} + +@r2@ +identifier m, f, a, v, t; +identifier func =~ "thread_add_"; +type T1; +position p; +@@ + +T1 *t; +... +func(m,f,a,v,&t)@p + +@script:python@ +p << r1.p; +@@ +coccilib.report.print_report(p[0],"Passed double 'struct thread' pointer") + +@script:python@ +p << r2.p; +@@ +coccilib.report.print_report(p[0],"Passed double 'struct thread' pointer") diff --git a/tools/coccinelle/struct_thread_null.cocci b/tools/coccinelle/struct_thread_null.cocci new file mode 100644 index 0000000000..4867b4454b --- /dev/null +++ b/tools/coccinelle/struct_thread_null.cocci @@ -0,0 +1,9 @@ +@@ +identifier I; +identifier func =~ "thread_add_"; +struct thread *thread; +@@ + +*thread = NULL; +... +func diff --git a/tools/coccinelle/zlog_no_newline.cocci b/tools/coccinelle/zlog_no_newline.cocci new file mode 100644 index 0000000000..20cf9d2c78 --- /dev/null +++ b/tools/coccinelle/zlog_no_newline.cocci @@ -0,0 +1,20 @@ +// zlog_* should not have \n or \r at the end usually. +// spatch --sp-file tools/coccinelle/zlog_no_newline.cocci --macro-file tools/cocci.h ./ 2>/dev/null + +@r@ +expression fmt; +identifier func =~ "zlog_"; +position p; +@@ +( + func(fmt)@p +| + func(fmt, ...)@p +) + +@script:python@ +fmt << r.fmt; +p << r.p; +@@ +if "\\n" in str(fmt) or "\\r" in str(fmt): + print("Newline in logging function detected %s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)) diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py new file mode 100755 index 0000000000..3058395758 --- /dev/null +++ b/tools/frr_babeltrace.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +''' +Usage: frr_babeltrace.py trace_path + +FRR pushes data into lttng tracepoints in the least overhead way possible +i.e. as binary-data/crf_arrays. These traces need to be converted into pretty +strings for easy greping etc. This script is a babeltrace python plugin for +that pretty printing. + +Copyright (C) 2021 NVIDIA Corporation +Anuradha Karuppiah + +This program 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 of the License, or (at your option) +any later version. + +This program 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 +''' + +import ipaddress +import socket +import sys + +import babeltrace + +########################### common parsers - start ############################ +def print_ip_addr(field_val): + ''' + pretty print "struct ipaddr" + ''' + if field_val[0] == socket.AF_INET: + addr = [str(fv) for fv in field_val[4:8]] + return str(ipaddress.IPv4Address('.'.join(addr))) + + if field_val[0] == socket.AF_INET6: + tmp = ''.join('%02x' % fb for fb in field_val[4:]) + addr = [] + while tmp: + addr.append(tmp[:4]) + tmp = tmp[4:] + addr = ':'.join(addr) + return str(ipaddress.IPv6Address(addr)) + + if not field_val[0]: + return '' + + return field_val + + +def print_mac(field_val): + ''' + pretty print "u8 mac[6]" + ''' + return ':'.join('%02x' % fb for fb in field_val) + +def print_net_ipv4_addr(field_val): + ''' + pretty print ctf_integer_network ipv4 + ''' + return str(ipaddress.IPv4Address(field_val)) + +def print_esi(field_val): + ''' + pretty print ethernet segment id, esi_t + ''' + return ':'.join('%02x' % fb for fb in field_val) + +def get_field_list(event): + ''' + only fetch fields added via the TP, skip metadata etc. + ''' + return event.field_list_with_scope(babeltrace.CTFScope.EVENT_FIELDS) + +def parse_event(event, field_parsers): + ''' + Wild card event parser; doesn't make things any prettier + ''' + field_list = get_field_list(event) + field_info = {} + for field in field_list: + if field in field_parsers: + field_parser = field_parsers.get(field) + field_info[field] = field_parser(event.get(field)) + else: + field_info[field] = event.get(field) + print(event.name, field_info) +############################ common parsers - end ############################# + +############################ evpn parsers - start ############################# +def parse_frr_bgp_evpn_mac_ip_zsend(event): + ''' + bgp evpn mac-ip parser; raw format - + ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, &pfx->prefix.macip_addr.ip, + sizeof(struct ipaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'ip': print_ip_addr, + 'mac': print_mac, + 'esi': print_esi, + 'vtep': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_bum_vtep_zsend(event): + ''' + bgp evpn bum-vtep parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, + pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr) + + ''' + field_parsers = {'vtep': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_nh_rmac_send(event): + ''' + bgp evpn nh-rmac parser; raw format - + ctf_array(unsigned char, rmac, &nh->rmac, sizeof(struct ethaddr)) + ''' + field_parsers = {'rmac': print_mac} + + parse_event(event, field_parsers) + +############################ evpn parsers - end ############################# + +def main(): + ''' + FRR lttng trace output parser; babel trace plugin + ''' + event_parsers = {'frr_bgp:evpn_mac_ip_zsend': + parse_frr_bgp_evpn_mac_ip_zsend, + 'frr_bgp:evpn_bum_vtep_zsend': + parse_frr_bgp_evpn_bum_vtep_zsend, + 'frr_bgp:evpn_mh_nh_rmac_zsend': + parse_frr_bgp_evpn_mh_nh_rmac_send} + + # get the trace path from the first command line argument + trace_path = sys.argv[1] + + # grab events + trace_collection = babeltrace.TraceCollection() + trace_collection.add_traces_recursive(trace_path, 'ctf') + + for event in trace_collection.events: + if event.name in event_parsers: + event_parser = event_parsers.get(event.name) + event_parser(event) + else: + parse_event(event, {}) + +if __name__ == '__main__': + main() diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index d0b4be81d4..b09d092458 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -68,6 +68,7 @@ DEFINE_MTYPE_STATIC(WATCHFRR, WATCHFRR_DAEMON, "watchfrr daemon entry"); struct thread_master *master; static bool watch_only = false; +const char *pathspace; typedef enum { PHASE_NONE = 0, @@ -361,7 +362,6 @@ static int restart_kill(struct thread *t_kill) (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM)); restart->kills++; - restart->t_kill = NULL; thread_add_timer(master, restart_kill, restart, gs.restart_timeout, &restart->t_kill); return 0; @@ -495,7 +495,6 @@ static int run_job(struct restart_info *restart, const char *cmdtype, char cmd[strlen(command) + strlen(restart->name) + 1]; snprintf(cmd, sizeof(cmd), command, restart->name); if ((restart->pid = run_background(cmd)) > 0) { - restart->t_kill = NULL; thread_add_timer(master, restart_kill, restart, gs.restart_timeout, &restart->t_kill); restart->what = cmdtype; @@ -833,10 +832,8 @@ static int try_connect(struct daemon *dmn) zlog_debug("%s: connection in progress", dmn->name); dmn->state = DAEMON_CONNECTING; dmn->fd = sock; - dmn->t_write = NULL; thread_add_write(master, check_connect, dmn, dmn->fd, &dmn->t_write); - dmn->t_wakeup = NULL; thread_add_timer(master, wakeup_connect_hanging, dmn, gs.timeout, &dmn->t_wakeup); SET_READ_HANDLER(dmn); @@ -1022,7 +1019,6 @@ static int wakeup_send_echo(struct thread *t_wakeup) daemon_down(dmn, why); } else { gettimeofday(&dmn->echo_sent, NULL); - dmn->t_wakeup = NULL; thread_add_timer(master, wakeup_no_answer, dmn, gs.timeout, &dmn->t_wakeup); } @@ -1269,7 +1265,6 @@ static void watchfrr_init(int argc, char **argv) gs.numdaemons++; gs.numdown++; dmn->fd = -1; - dmn->t_wakeup = NULL; thread_add_timer_msec(master, wakeup_init, dmn, 0, &dmn->t_wakeup); dmn->restart.interval = gs.min_restart_interval; @@ -1519,8 +1514,15 @@ int main(int argc, char **argv) else unsetenv("FRR_PATHSPACE"); + /* + * when watchfrr_di.pathspace is read, if it is not specified + * pathspace is NULL as expected + */ + pathspace = watchfrr_di.pathspace; + if (netns_en && !netns) netns = watchfrr_di.pathspace; + if (netns_en && netns && netns[0]) netns_setup(netns); diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index 4df1bf74af..4987a932c0 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -25,6 +25,12 @@ DECLARE_MGROUP(WATCHFRR); +/* + * This is the name of the pathspace we are in `-N XXX` + * If the default then this is NULL + */ +extern const char *pathspace; + extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index eda4f5d516..1492ee37b6 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -105,7 +105,10 @@ DEFUN(config_write_integrated, /* don't allow the user to pass parameters, we're root here! * should probably harden vtysh at some point too... */ - execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL); + if (pathspace) + execl(VTYSH_BIN_PATH, "vtysh", "-N", pathspace, "-w", NULL); + else + execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL); /* unbuffered write; we just messed with stdout... */ char msg[512]; diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang index 2df2e2958e..adcbacbfea 100644 --- a/yang/frr-nexthop.yang +++ b/yang/frr-nexthop.yang @@ -61,7 +61,7 @@ module frr-nexthop { type union { type inet:ip-address; type string { - pattern ""; + length "0"; } } } diff --git a/zebra/connected.c b/zebra/connected.c index 0511b35185..80d434bafc 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -73,8 +73,7 @@ static void connected_announce(struct interface *ifp, struct connected *ifc) if (!ifc) return; - if (!if_is_loopback(ifp) && ifc->address->family == AF_INET && - !IS_ZEBRA_IF_VRF(ifp)) { + if (!if_is_loopback_or_vrf(ifp) && ifc->address->family == AF_INET) { if (ifc->address->prefixlen == IPV4_MAX_BITLEN) SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); else diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 28a64407e5..fa3aabb195 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1089,7 +1089,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, - 1); + true); if (ret < 0) return ret; @@ -1099,7 +1099,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, - 0); + true); if (ret < 0) return ret; @@ -1128,7 +1128,7 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, - 0, 1); + 0, true); if (ret < 0) return ret; @@ -1137,7 +1137,7 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, - 0, 1); + 0, true); if (ret < 0) return ret; @@ -1168,7 +1168,7 @@ int kernel_interface_set_master(struct interface *master, nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, slave->ifindex); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } /* Interface address modification. */ @@ -1292,11 +1292,22 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); if (ifp == NULL) { - flog_err( - EC_LIB_INTERFACE, - "netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); - return -1; + if (startup) { + /* During startup, failure to lookup the referenced + * interface should not be an error, so we have + * downgraded this condition to warning, and we permit + * the startup interface state retrieval to continue. + */ + flog_warn(EC_LIB_INTERFACE, + "%s: can't find interface by index %d", + __func__, ifa->ifa_index); + return 0; + } else { + flog_err(EC_LIB_INTERFACE, + "%s: can't find interface by index %d", + __func__, ifa->ifa_index); + return -1; + } } /* Flags passed through */ @@ -1832,6 +1843,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Update link. */ zebra_if_update_link(ifp, link_ifindex, ns_id); + ifp->ll_type = + netlink_to_zebra_link_type(ifi->ifi_type); netlink_interface_update_hw_addr(tb, ifp); /* Inform clients, install any configured addresses. */ @@ -1899,6 +1912,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Update link. */ zebra_if_update_link(ifp, link_ifindex, ns_id); + ifp->ll_type = + netlink_to_zebra_link_type(ifi->ifi_type); netlink_interface_update_hw_addr(tb, ifp); if (if_is_no_ptm_operative(ifp)) { @@ -2054,7 +2069,7 @@ int netlink_protodown(struct interface *ifp, bool down) nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, ifp->ifindex); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } /* Interface information read by netlink. */ diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index 66a6bd0545..f141b72719 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -112,7 +112,6 @@ int irdp_sock_init(void) return ret; }; - t_irdp_raw = NULL; thread_add_read(zrouter.master, irdp_read_raw, NULL, sock, &t_irdp_raw); return sock; diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 7d67c42a79..5601b13a92 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -233,7 +233,6 @@ int irdp_read_raw(struct thread *r) int ret, ifindex = 0; int irdp_sock = THREAD_FD(r); - t_irdp_raw = NULL; thread_add_read(zrouter.master, irdp_read_raw, NULL, irdp_sock, &t_irdp_raw); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 602bdc1dc5..86e8f65b5f 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -419,7 +419,7 @@ static int kernel_read(struct thread *thread) zebra_dplane_info_from_zns(&dp_info, zns, false); netlink_parse_info(netlink_information_fetch, &zns->netlink, &dp_info, - 5, 0); + 5, false); thread_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock, &zns->t_netlink); @@ -433,7 +433,7 @@ static int kernel_read(struct thread *thread) int kernel_dplane_read(struct zebra_dplane_info *info) { netlink_parse_info(dplane_netlink_information_fetch, &info->nls, info, - 5, 0); + 5, false); return 0; } @@ -933,7 +933,7 @@ static int netlink_parse_error(const struct nlsock *nl, struct nlmsghdr *h, int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), const struct nlsock *nl, const struct zebra_dplane_info *zns, - int count, int startup) + int count, bool startup) { int status; int ret = 0; @@ -1036,7 +1036,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), static int netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, const struct zebra_dplane_info *dp_info, - int startup) + bool startup) { const struct nlsock *nl; @@ -1067,7 +1067,7 @@ netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), */ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, - int startup) + bool startup) { struct zebra_dplane_info dp_info; diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index d8e5671b72..37c76b9e59 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -94,11 +94,11 @@ extern const char *nl_rttype_to_str(uint8_t rttype); extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), const struct nlsock *nl, const struct zebra_dplane_info *dp_info, - int count, int startup); + int count, bool startup); extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup); extern int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, - struct zebra_ns *zns, int startup); + struct zebra_ns *zns, bool startup); extern int netlink_request(struct nlsock *nl, void *req); enum netlink_msg_status { diff --git a/zebra/rib.h b/zebra/rib.h index 8887053a4c..076608bb0f 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -46,24 +46,22 @@ DECLARE_MGROUP(ZEBRA); DECLARE_MTYPE(RE); -enum rnh_type { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE }; - PREDECL_LIST(rnh_list); /* Nexthop structure. */ struct rnh { uint8_t flags; -#define ZEBRA_NHT_CONNECTED 0x1 -#define ZEBRA_NHT_DELETED 0x2 -#define ZEBRA_NHT_EXACT_MATCH 0x4 +#define ZEBRA_NHT_CONNECTED 0x1 +#define ZEBRA_NHT_DELETED 0x2 +#define ZEBRA_NHT_EXACT_MATCH 0x4 +#define ZEBRA_NHT_RESOLVE_VIA_DEFAULT 0x8 /* VRF identifier. */ vrf_id_t vrf_id; afi_t afi; - - enum rnh_type type; + safi_t safi; uint32_t seqno; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e36f320ad9..780b601734 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1171,7 +1171,7 @@ int netlink_route_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_route_change_read_unicast, - &zns->netlink_cmd, &dp_info, 0, 1); + &zns->netlink_cmd, &dp_info, 0, true); if (ret < 0) return ret; @@ -1180,7 +1180,7 @@ int netlink_route_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_route_change_read_unicast, - &zns->netlink_cmd, &dp_info, 0, 1); + &zns->netlink_cmd, &dp_info, 0, true); if (ret < 0) return ret; @@ -1810,7 +1810,7 @@ static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla, nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static bool nexthop_set_src(const struct nexthop *nexthop, int family, @@ -2268,7 +2268,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) nl_attr_put32(&req.n, sizeof(req), RTA_TABLE, actual_table); suc = netlink_talk(netlink_route_change_read_multicast, &req.n, - &zns->netlink_cmd, zns, 0); + &zns->netlink_cmd, zns, false); mroute = NULL; return suc; @@ -3019,7 +3019,7 @@ int netlink_nexthop_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_nexthop_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); if (!ret) /* If we succesfully read in nexthop objects, @@ -3427,7 +3427,7 @@ int netlink_macfdb_read(struct zebra_ns *zns) /* We are reading entire table. */ filter_vlan = 0; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } @@ -3461,7 +3461,7 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, if (ret < 0) return ret; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 0, 0); + &dp_info, 0, false); /* Reset VLAN filter. */ filter_vlan = 0; @@ -3526,7 +3526,7 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, return ret; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 1, 0); + &dp_info, 1, false); return ret; } @@ -3744,7 +3744,6 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (tb[NDA_LLADDR]) { /* copy LLADDR information */ l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]); - memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), l2_len); } if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) { union sockunion link_layer_ipv4; @@ -3752,7 +3751,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (l2_len) { sockunion_family(&link_layer_ipv4) = AF_INET; memcpy((void *)sockunion_get_addr(&link_layer_ipv4), - &mac, l2_len); + RTA_DATA(tb[NDA_LLADDR]), l2_len); } else sockunion_family(&link_layer_ipv4) = AF_UNSPEC; zsend_nhrp_neighbor_notify( @@ -3930,7 +3929,7 @@ int netlink_neigh_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } @@ -3951,7 +3950,7 @@ int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) if (ret < 0) return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 0, 0); + &dp_info, 0, false); return ret; } @@ -4022,7 +4021,7 @@ int netlink_neigh_read_specific_ip(const struct ipaddr *ip, return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 1, 0); + &dp_info, 1, false); return ret; } @@ -4442,7 +4441,7 @@ static int netlink_fdb_nh_update(uint32_t nh_id, struct in_addr vtep_ip) } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nh_del(uint32_t nh_id) @@ -4477,7 +4476,7 @@ static int netlink_fdb_nh_del(uint32_t nh_id) } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nhg_update(uint32_t nhg_id, uint32_t nh_cnt, @@ -4537,7 +4536,7 @@ static int netlink_fdb_nhg_update(uint32_t nhg_id, uint32_t nh_cnt, } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nhg_del(uint32_t nhg_id) diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 976beefab0..9610f71d09 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -493,9 +493,7 @@ static int rtadv_timer(struct thread *thread) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) FOR_ALL_INTERFACES (vrf, ifp) { - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, - ZEBRA_INTERFACE_VRF_LOOPBACK) + if (if_is_loopback_or_vrf(ifp) || !if_is_operative(ifp)) continue; @@ -728,8 +726,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len, VRF_LOGNAME(vrf), ifp->ifindex, len, addr_str); } - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) + if (if_is_loopback_or_vrf(ifp)) return; /* Check interface configuration. */ @@ -1465,8 +1462,7 @@ DEFUN (ipv6_nd_ra_fast_retrans, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1488,8 +1484,7 @@ DEFUN (no_ipv6_nd_ra_fast_retrans, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1511,8 +1506,7 @@ DEFPY (ipv6_nd_ra_hop_limit, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1535,8 +1529,7 @@ DEFPY (no_ipv6_nd_ra_hop_limit, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1558,8 +1551,7 @@ DEFPY (ipv6_nd_ra_retrans_interval, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on loopback interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1582,8 +1574,7 @@ DEFPY (no_ipv6_nd_ra_retrans_interval, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot remove IPv6 Router Advertisements on loopback interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1604,8 +1595,7 @@ DEFUN (ipv6_nd_suppress_ra, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1629,8 +1619,7 @@ DEFUN (no_ipv6_nd_suppress_ra, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -2619,8 +2608,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp) zif = ifp->info; - if (!(if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) { + if (!if_is_loopback_or_vrf(ifp)) { if (zif->rtadv.AdvSendAdvertisements && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED)) vty_out(vty, " no ipv6 nd suppress-ra\n"); diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index b651edd8f9..fbf2620375 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -403,7 +403,7 @@ int netlink_rules_read(struct zebra_ns *zns) return ret; ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); if (ret < 0) return ret; @@ -412,7 +412,7 @@ int netlink_rules_read(struct zebra_ns *zns) return ret; ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } diff --git a/zebra/table_manager.c b/zebra/table_manager.c index bb060588d2..9f3b44f944 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -55,10 +55,9 @@ #define RT_TABLE_ID_UNRESERVED_MIN 1 #define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff -struct table_manager tbl_mgr; - DEFINE_MGROUP(TABLE_MGR, "Table Manager"); DEFINE_MTYPE_STATIC(TABLE_MGR, TM_CHUNK, "Table Manager Chunk"); +DEFINE_MTYPE_STATIC(TABLE_MGR, TM_TABLE, "Table Manager Context"); static void delete_table_chunk(void *val) { @@ -68,12 +67,21 @@ static void delete_table_chunk(void *val) /** * Init table manager */ -void table_manager_enable(ns_id_t ns_id) +void table_manager_enable(struct zebra_vrf *zvrf) { - if (ns_id != NS_DEFAULT) + + if (zvrf->tbl_mgr) return; - tbl_mgr.lc_list = list_new(); - tbl_mgr.lc_list->del = delete_table_chunk; + if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) { + struct zebra_vrf *def = zebra_vrf_lookup_by_id(VRF_DEFAULT); + + if (def) + zvrf->tbl_mgr = def->tbl_mgr; + return; + } + zvrf->tbl_mgr = XCALLOC(MTYPE_TM_TABLE, sizeof(struct table_manager)); + zvrf->tbl_mgr->lc_list = list_new(); + zvrf->tbl_mgr->lc_list->del = delete_table_chunk; hook_register(zserv_client_close, release_daemon_table_chunks); } @@ -89,14 +97,19 @@ void table_manager_enable(ns_id_t ns_id) * @return Pointer to the assigned table chunk */ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, - uint32_t size) + uint32_t size, + struct zebra_vrf *zvrf) { struct table_manager_chunk *tmc; struct listnode *node; uint32_t start; + bool manual_conf = false; + + if (!zvrf) + return NULL; /* first check if there's one available */ - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { + for (ALL_LIST_ELEMENTS_RO(zvrf->tbl_mgr->lc_list, node, tmc)) { if (tmc->proto == NO_PROTO && tmc->end - tmc->start + 1 == size) { tmc->proto = proto; @@ -109,17 +122,26 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, if (!tmc) return NULL; + if (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end) + manual_conf = true; /* table RT IDs range are [1;252] and [256;0xffffffff] * - check if the requested range can be within the first range, * otherwise elect second one * - TODO : vrf-lites have their own table identifier. * In that case, table_id should be removed from the table range. */ - if (list_isempty(tbl_mgr.lc_list)) - start = RT_TABLE_ID_UNRESERVED_MIN; - else + if (list_isempty(zvrf->tbl_mgr->lc_list)) { + if (!manual_conf) + start = RT_TABLE_ID_UNRESERVED_MIN; + else + start = zvrf->tbl_mgr->start; + } else start = ((struct table_manager_chunk *)listgetdata( - listtail(tbl_mgr.lc_list)))->end + 1; + listtail(zvrf->tbl_mgr->lc_list))) + ->end + + 1; + + if (!manual_conf) { #if !defined(GNU_LINUX) /* BSD systems @@ -127,25 +149,35 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, #else /* Linux Systems */ - /* if not enough room space between MIN and COMPAT, - * then begin after LOCAL - */ - if (start < RT_TABLE_ID_COMPAT && (size > - RT_TABLE_ID_COMPAT - - RT_TABLE_ID_UNRESERVED_MIN)) - start = RT_TABLE_ID_LOCAL + 1; + /* if not enough room space between MIN and COMPAT, + * then begin after LOCAL + */ + if (start < RT_TABLE_ID_COMPAT + && (size > RT_TABLE_ID_COMPAT - RT_TABLE_ID_UNRESERVED_MIN)) + start = RT_TABLE_ID_LOCAL + 1; #endif /* !def(GNU_LINUX) */ - tmc->start = start; - if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) { - flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, - "Reached max table id. Start/Size %u/%u", start, size); - XFREE(MTYPE_TM_CHUNK, tmc); - return NULL; + tmc->start = start; + if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) { + flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, + "Reached max table id. Start/Size %u/%u", + start, size); + XFREE(MTYPE_TM_CHUNK, tmc); + return NULL; + } + } else { + tmc->start = start; + if (zvrf->tbl_mgr->end - size + 1 < start) { + flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, + "Reached max table id. Start/Size %u/%u", + start, size); + XFREE(MTYPE_TM_CHUNK, tmc); + return NULL; + } } tmc->end = tmc->start + size - 1; tmc->proto = proto; tmc->instance = instance; - listnode_add(tbl_mgr.lc_list, tmc); + listnode_add(zvrf->tbl_mgr->lc_list, tmc); return tmc; } @@ -160,16 +192,23 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, * @return 0 on success, -1 otherwise */ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, - uint32_t end) + uint32_t end, struct zebra_vrf *zvrf) { struct listnode *node; struct table_manager_chunk *tmc; int ret = -1; + struct table_manager *tbl_mgr; + + if (!zvrf) + return -1; + tbl_mgr = zvrf->tbl_mgr; + if (!tbl_mgr) + return ret; /* check that size matches */ zlog_debug("Releasing table chunk: %u - %u", start, end); /* find chunk and disown */ - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { + for (ALL_LIST_ELEMENTS_RO(tbl_mgr->lc_list, node, tmc)) { if (tmc->start != start) continue; if (tmc->end != end) @@ -208,24 +247,99 @@ int release_daemon_table_chunks(struct zserv *client) struct table_manager_chunk *tmc; int count = 0; int ret; + struct vrf *vrf; + struct zebra_vrf *zvrf; - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { - if (tmc->proto == proto && tmc->instance == instance) { - ret = release_table_chunk(tmc->proto, tmc->instance, - tmc->start, tmc->end); - if (ret == 0) - count++; + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = vrf->info; + + if (!zvrf) + continue; + if (!vrf_is_backend_netns() && vrf->vrf_id != VRF_DEFAULT) + continue; + for (ALL_LIST_ELEMENTS_RO(zvrf->tbl_mgr->lc_list, node, tmc)) { + if (tmc->proto == proto && tmc->instance == instance) { + ret = release_table_chunk( + tmc->proto, tmc->instance, tmc->start, + tmc->end, zvrf); + if (ret == 0) + count++; + } } } - zlog_debug("%s: Released %d table chunks", __func__, count); return count; } -void table_manager_disable(ns_id_t ns_id) +static void table_range_add(struct zebra_vrf *zvrf, uint32_t start, + uint32_t end) +{ + if (!zvrf->tbl_mgr) + return; + zvrf->tbl_mgr->start = start; + zvrf->tbl_mgr->end = end; +} + +void table_manager_disable(struct zebra_vrf *zvrf) { - if (ns_id != NS_DEFAULT) + if (!zvrf->tbl_mgr) + return; + if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) { + zvrf->tbl_mgr = NULL; return; - list_delete(&tbl_mgr.lc_list); + } + list_delete(&zvrf->tbl_mgr->lc_list); + XFREE(MTYPE_TM_TABLE, zvrf->tbl_mgr); + zvrf->tbl_mgr = NULL; +} + +int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf, + const char *start_table_str, const char *end_table_str) +{ + uint32_t start; + uint32_t end; + + if (add) { + if (!start_table_str || !end_table_str) { + vty_out(vty, "%% Labels not specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + start = atoi(start_table_str); + end = atoi(end_table_str); + if (end < start) { + vty_out(vty, "%% End table is less than Start table\n"); + return CMD_WARNING_CONFIG_FAILED; + } + +#if !defined(GNU_LINUX) +/* BSD systems + */ +#else + /* Linux Systems + */ + if ((start >= RT_TABLE_ID_COMPAT && start <= RT_TABLE_ID_LOCAL) + || (end >= RT_TABLE_ID_COMPAT + && end <= RT_TABLE_ID_LOCAL)) { + vty_out(vty, "%% Values forbidden in range [%u;%u]\n", + RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL); + return CMD_WARNING_CONFIG_FAILED; + } + if (start < RT_TABLE_ID_COMPAT && end > RT_TABLE_ID_LOCAL) { + vty_out(vty, + "%% Range overlaps range [%u;%u] forbidden\n", + RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL); + return CMD_WARNING_CONFIG_FAILED; + } +#endif + if (zvrf->tbl_mgr + && ((zvrf->tbl_mgr->start && zvrf->tbl_mgr->start != start) + || (zvrf->tbl_mgr->end && zvrf->tbl_mgr->end != end))) { + vty_out(vty, + "%% New range will be taken into account at restart\n"); + } + table_range_add(zvrf, start, end); + } else + table_range_add(zvrf, 0, 0); + return CMD_SUCCESS; } diff --git a/zebra/table_manager.h b/zebra/table_manager.h index 4f78f5097e..fa1366842e 100644 --- a/zebra/table_manager.h +++ b/zebra/table_manager.h @@ -57,15 +57,20 @@ struct table_manager_chunk { */ struct table_manager { struct list *lc_list; + uint32_t start; + uint32_t end; }; -void table_manager_enable(ns_id_t ns_id); +void table_manager_enable(struct zebra_vrf *zvrf); struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, - uint32_t size); + uint32_t size, + struct zebra_vrf *zvrf); int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, - uint32_t end); + uint32_t end, struct zebra_vrf *zvrf); int release_daemon_table_chunks(struct zserv *client); -void table_manager_disable(ns_id_t ns_id); +void table_manager_disable(struct zebra_vrf *zvrf); +int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf, + const char *min, const char *max); #ifdef __cplusplus } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 496849251a..2e9b0b6ea2 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1164,13 +1164,6 @@ int zsend_zebra_srv6_locator_delete(struct zserv *client, /* Inbound message handling ------------------------------------------------ */ -const int cmd2type[] = { - [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, -}; - /* Nexthop register */ static void zread_rnh_register(ZAPI_HANDLER_ARGS) { @@ -1178,17 +1171,17 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) struct stream *s; struct prefix p; unsigned short l = 0; - uint8_t flags = 0; - uint16_t type = cmd2type[hdr->command]; + uint8_t connected = 0; + uint8_t resolve_via_default; bool exist; bool flag_changed = false; uint8_t orig_flags; + safi_t safi; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( - "rnh_register msg from client %s: hdr->length=%d, type=%s vrf=%u", + "rnh_register msg from client %s: hdr->length=%d vrf=%u", zebra_route_string(client->proto), hdr->length, - (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route", zvrf->vrf->vrf_id); s = msg; @@ -1197,10 +1190,12 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) client->nh_reg_time = monotime(NULL); while (l < hdr->length) { - STREAM_GETC(s, flags); + STREAM_GETC(s, connected); + STREAM_GETC(s, resolve_via_default); + STREAM_GETW(s, safi); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 4; + l += 7; if (p.family == AF_INET) { client->v4_nh_watch_add_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { @@ -1228,37 +1223,29 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist); + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), &exist); if (!rnh) return; orig_flags = rnh->flags; - if (type == RNH_NEXTHOP_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags - && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - } else if (type == RNH_IMPORT_CHECK_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - else if (!flags - && CHECK_FLAG(rnh->flags, - ZEBRA_NHT_EXACT_MATCH)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - } + if (connected && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + else if (!connected + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + + if (resolve_via_default) + SET_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT); if (orig_flags != rnh->flags) flag_changed = true; /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist || flag_changed) - zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type, - &p); + zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p, + safi); - zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); + zebra_add_rnh_client(rnh, client, zvrf_id(zvrf)); } stream_failure: @@ -1272,7 +1259,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) struct stream *s; struct prefix p; unsigned short l = 0; - uint16_t type = cmd2type[hdr->command]; + safi_t safi; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1283,15 +1270,19 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) s = msg; while (l < hdr->length) { - uint8_t flags; + uint8_t ignore; - STREAM_GETC(s, flags); - if (flags != 0) + STREAM_GETC(s, ignore); + if (ignore != 0) + goto stream_failure; + STREAM_GETC(s, ignore); + if (ignore != 0) goto stream_failure; + STREAM_GETW(s, safi); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 4; + l += 7; if (p.family == AF_INET) { client->v4_nh_watch_rem_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { @@ -1319,10 +1310,10 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), safi); if (rnh) { client->nh_dereg_time = monotime(NULL); - zebra_remove_rnh_client(rnh, client, type); + zebra_remove_rnh_client(rnh, client); } } stream_failure: @@ -2853,7 +2844,7 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS) } static void zread_get_table_chunk(struct zserv *client, struct stream *msg, - vrf_id_t vrf_id) + struct zebra_vrf *zvrf) { struct stream *s; uint32_t size; @@ -2865,7 +2856,7 @@ static void zread_get_table_chunk(struct zserv *client, struct stream *msg, /* Get data. */ STREAM_GETL(s, size); - tmc = assign_table_chunk(client->proto, client->instance, size); + tmc = assign_table_chunk(client->proto, client->instance, size, zvrf); if (!tmc) flog_err(EC_ZEBRA_TM_CANNOT_ASSIGN_CHUNK, "%s: Unable to assign Table Chunk of size %u", @@ -2874,13 +2865,14 @@ static void zread_get_table_chunk(struct zserv *client, struct stream *msg, zlog_debug("Assigned Table Chunk %u - %u", tmc->start, tmc->end); /* send response back */ - zsend_assign_table_chunk_response(client, vrf_id, tmc); + zsend_assign_table_chunk_response(client, zvrf_id(zvrf), tmc); stream_failure: return; } -static void zread_release_table_chunk(struct zserv *client, struct stream *msg) +static void zread_release_table_chunk(struct zserv *client, struct stream *msg, + struct zebra_vrf *zvrf) { struct stream *s; uint32_t start, end; @@ -2892,7 +2884,7 @@ static void zread_release_table_chunk(struct zserv *client, struct stream *msg) STREAM_GETL(s, start); STREAM_GETL(s, end); - release_table_chunk(client->proto, client->instance, start, end); + release_table_chunk(client->proto, client->instance, start, end, zvrf); stream_failure: return; @@ -2912,9 +2904,9 @@ static void zread_table_manager_request(ZAPI_HANDLER_ARGS) return; } if (hdr->command == ZEBRA_GET_TABLE_CHUNK) - zread_get_table_chunk(client, msg, zvrf_id(zvrf)); + zread_get_table_chunk(client, msg, zvrf); else if (hdr->command == ZEBRA_RELEASE_TABLE_CHUNK) - zread_release_table_chunk(client, msg); + zread_release_table_chunk(client, msg, zvrf); } } @@ -3682,8 +3674,6 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_HELLO] = zread_hello, [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register, [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister, - [ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister, [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister, diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 054015846f..61f97ce6a9 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -346,7 +346,6 @@ void zebra_ns_notify_init(void) { int fd_monitor; - zebra_netns_notify_current = NULL; fd_monitor = inotify_init(); if (fd_monitor < 0) { flog_err_sys( diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 8ae677fb22..50e1d0f389 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -128,9 +128,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) route_read(zns); kernel_read_pbr_rules(zns); - /* Initiate Table Manager per ZNS */ - table_manager_enable(ns_id); - return 0; } @@ -145,8 +142,6 @@ static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) kernel_terminate(zns, complete); - table_manager_disable(zns->ns_id); - zns->ns_id = NS_DEFAULT; return 0; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 24c51e485f..12e82dde94 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -730,10 +730,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - "%s(%u):%pRN has Nexthop(%pFX) Type: %s depending on it, evaluating %u:%u", - zvrf_name(zvrf), zvrf_id(zvrf), - rn, p, rnh_type2str(rnh->type), seq, - rnh->seqno); + "%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u", + zvrf_name(zvrf), zvrf_id(zvrf), rn, p, + seq, rnh->seqno); /* * If we have evaluated this node on this pass @@ -755,8 +754,8 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) } rnh->seqno = seq; - zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, - rnh->type, p); + zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p, + rnh->safi); } rn = rn->parent; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 017a4aae7f..f5faaab71b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -71,21 +71,18 @@ void zebra_rnh_init(void) } static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, - enum rnh_type type) + safi_t safi) { struct zebra_vrf *zvrf; struct route_table *t = NULL; zvrf = zebra_vrf_lookup_by_id(vrfid); - if (zvrf) - switch (type) { - case RNH_NEXTHOP_TYPE: + if (zvrf) { + if (safi == SAFI_UNICAST) t = zvrf->rnh_table[afi]; - break; - case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[afi]; - break; - } + else if (safi == SAFI_MULTICAST) + t = zvrf->rnh_table_multicast[afi]; + } return t; } @@ -93,7 +90,7 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, static void zebra_rnh_remove_from_routing_table(struct rnh *rnh) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_table *table = zvrf->table[rnh->afi][rnh->safi]; struct route_node *rn; rib_dest_t *dest; @@ -117,7 +114,7 @@ static void zebra_rnh_remove_from_routing_table(struct rnh *rnh) static void zebra_rnh_store_in_routing_table(struct rnh *rnh) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_table *table = zvrf->table[rnh->afi][rnh->safi]; struct route_node *rn; rib_dest_t *dest; @@ -135,27 +132,28 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh) route_unlock_node(rn); } -struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, - bool *exists) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists) { struct route_table *table; struct route_node *rn; struct rnh *rnh = NULL; afi_t afi = family2afi(p->family); + safi_t safi = SAFI_UNICAST; if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrfid); - zlog_debug("%s(%u): Add RNH %pFX type %s", VRF_LOGNAME(vrf), - vrfid, p, rnh_type2str(type)); + zlog_debug("%s(%u): Add RNH %pFX for safi: %u", + VRF_LOGNAME(vrf), vrfid, p, safi); } - table = get_rnh_table(vrfid, afi, type); + + table = get_rnh_table(vrfid, afi, safi); if (!table) { struct vrf *vrf = vrf_lookup_by_id(vrfid); flog_warn(EC_ZEBRA_RNH_NO_TABLE, - "%s(%u): Add RNH %pFX type %s - table not found", - VRF_LOGNAME(vrf), vrfid, p, rnh_type2str(type)); + "%s(%u): Add RNH %pFX - table not found", + VRF_LOGNAME(vrf), vrfid, p); *exists = false; return NULL; } @@ -178,9 +176,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, rnh->resolved_route.family = p->family; rnh->client_list = list_new(); rnh->vrf_id = vrfid; - rnh->type = type; rnh->seqno = 0; rnh->afi = afi; + rnh->safi = safi; rnh->zebra_pseudowire_list = list_new(); route_lock_node(rn); rn->info = rnh; @@ -195,13 +193,12 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, return (rn->info); } -struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, safi_t safi) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), safi); if (!table) return NULL; @@ -228,7 +225,7 @@ void zebra_free_rnh(struct rnh *rnh) list_delete(&rnh->zebra_pseudowire_list); zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - table = zvrf->table[family2afi(rnh->resolved_route.family)][SAFI_UNICAST]; + table = zvrf->table[family2afi(rnh->resolved_route.family)][rnh->safi]; if (table) { struct route_node *rern; @@ -247,7 +244,7 @@ void zebra_free_rnh(struct rnh *rnh) XFREE(MTYPE_RNH, rnh); } -static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) +static void zebra_delete_rnh(struct rnh *rnh) { struct route_node *rn; @@ -261,8 +258,8 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id); - zlog_debug("%s(%u): Del RNH %pRN type %s", VRF_LOGNAME(vrf), - rnh->vrf_id, rnh->node, rnh_type2str(type)); + zlog_debug("%s(%u): Del RNH %pRN", VRF_LOGNAME(vrf), + rnh->vrf_id, rnh->node); } zebra_free_rnh(rnh); @@ -279,15 +276,14 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) * and as such it will have a resolved rnh. */ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id) + vrf_id_t vrf_id) { if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); - zlog_debug("%s(%u): Client %s registers for RNH %pRN type %s", + zlog_debug("%s(%u): Client %s registers for RNH %pRN", VRF_LOGNAME(vrf), vrf_id, - zebra_route_string(client->proto), rnh->node, - rnh_type2str(type)); + zebra_route_string(client->proto), rnh->node); } if (!listnode_lookup(rnh->client_list, client)) listnode_add(rnh->client_list, client); @@ -296,21 +292,20 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, * We always need to respond with known information, * currently multiple daemons expect this behavior */ - zebra_send_rnh_update(rnh, client, type, vrf_id, 0); + zebra_send_rnh_update(rnh, client, vrf_id, 0); } -void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type) +void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client) { if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id); - zlog_debug("Client %s unregisters for RNH %s(%u)%pRN type %s", + zlog_debug("Client %s unregisters for RNH %s(%u)%pRN", zebra_route_string(client->proto), VRF_LOGNAME(vrf), - vrf->vrf_id, rnh->node, rnh_type2str(type)); + vrf->vrf_id, rnh->node); } listnode_delete(rnh->client_list, client); - zebra_delete_rnh(rnh, type); + zebra_delete_rnh(rnh); } /* XXX move this utility function elsewhere? */ @@ -350,15 +345,15 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw, return; addr2hostprefix(pw->af, &pw->nexthop, &nh); - rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists); + rnh = zebra_add_rnh(&nh, vrf_id, &exists); if (!rnh) return; if (!listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, - RNH_NEXTHOP_TYPE, &nh); + zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, &nh, + SAFI_UNICAST); } else *nht_exists = true; } @@ -374,7 +369,7 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) listnode_delete(rnh->zebra_pseudowire_list, pw); pw->rnh = NULL; - zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); + zebra_delete_rnh(rnh); } /* Clear the NEXTHOP_FLAG_RNH_FILTERED flags on all nexthops @@ -419,111 +414,6 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, } /* - * Determine appropriate route (RE entry) resolving a tracked BGP route - * for BGP route for import. - */ -static struct route_entry * -zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, - struct route_node *nrn, struct rnh *rnh, - struct route_node **prn) -{ - struct route_table *route_table; - struct route_node *rn; - struct route_entry *re; - - *prn = NULL; - - route_table = zvrf->table[afi][SAFI_UNICAST]; - if (!route_table) // unexpected - return NULL; - - rn = route_node_match(route_table, &nrn->p); - if (!rn) - return NULL; - - /* Unlock route node - we don't need to lock when walking the tree. */ - route_unlock_node(rn); - - if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) - && !prefix_same(&nrn->p, &rn->p)) - return NULL; - - if (IS_ZEBRA_DEBUG_NHT_DETAILED) { - zlog_debug("%s: %s(%u):%pRN Resolved Import Entry to %pRN", - __func__, VRF_LOGNAME(zvrf->vrf), rnh->vrf_id, - rnh->node, rn); - } - - /* Identify appropriate route entry. */ - RNODE_FOREACH_RE (rn, re) { - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) - && CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) - && !CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) - && (re->type != ZEBRA_ROUTE_BGP)) - break; - } - - if (re) - *prn = rn; - - if (!re && IS_ZEBRA_DEBUG_NHT_DETAILED) - zlog_debug(" Rejected due to removed or is a bgp route"); - - return re; -} - -/* - * See if a tracked route entry for import (by BGP) has undergone any - * change, and if so, notify the client. - */ -static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi, - int force, struct route_node *nrn, - struct rnh *rnh, - struct route_node *prn, - struct route_entry *re) -{ - int state_changed = 0; - struct zserv *client; - struct listnode *node; - - zebra_rnh_remove_from_routing_table(rnh); - if (prn) { - prefix_copy(&rnh->resolved_route, &prn->p); - } else { - int family = rnh->resolved_route.family; - - memset(&rnh->resolved_route.family, 0, sizeof(struct prefix)); - rnh->resolved_route.family = family; - } - zebra_rnh_store_in_routing_table(rnh); - - if (re && (rnh->state == NULL)) { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) - state_changed = 1; - } else if (!re && (rnh->state != NULL)) - state_changed = 1; - - if (compare_state(re, rnh->state)) { - copy_state(rnh, re, nrn); - state_changed = 1; - } - - if (state_changed || force) { - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%s(%u):%pRN: Route import check %s %s", - VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id, - nrn, rnh->state ? "passed" : "failed", - state_changed ? "(state changed)" : ""); - /* state changed, notify clients */ - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { - zebra_send_rnh_update(rnh, client, - RNH_IMPORT_CHECK_TYPE, - zvrf->vrf->vrf_id, 0); - } - } -} - -/* * Notify clients registered for this nexthop about a change. */ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, @@ -580,8 +470,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, zebra_route_string(client->proto)); } - zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE, - zvrf->vrf->vrf_id, 0); + zebra_send_rnh_update(rnh, client, zvrf->vrf->vrf_id, 0); } if (re) @@ -676,7 +565,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, *prn = NULL; - route_table = zvrf->table[afi][SAFI_UNICAST]; + route_table = zvrf->table[afi][rnh->safi]; if (!route_table) return NULL; @@ -700,10 +589,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, * match route to be exact if so specified */ if (is_default_prefix(&rn->p) - && !rnh_resolve_via_default(zvrf, rn->p.family)) { + && (!CHECK_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT) + && !rnh_resolve_via_default(zvrf, rn->p.family))) { if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - " Not allowed to resolve through default prefix"); + " Not allowed to resolve through default prefix: rnh->resolve_via_default: %u", + CHECK_FLAG( + rnh->flags, + ZEBRA_NHT_RESOLVE_VIA_DEFAULT)); return NULL; } @@ -823,26 +716,22 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, /* Evaluate one tracked entry */ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, - int force, enum rnh_type type, - struct route_node *nrn) + int force, struct route_node *nrn) { struct rnh *rnh; struct route_entry *re; struct route_node *prn; if (IS_ZEBRA_DEBUG_NHT) { - zlog_debug("%s(%u):%pRN: Evaluate RNH, type %s %s", + zlog_debug("%s(%u):%pRN: Evaluate RNH, %s", VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id, nrn, - rnh_type2str(type), force ? "(force)" : ""); + force ? "(force)" : ""); } rnh = nrn->info; /* Identify route entry (RE) resolving this tracked entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); - else - re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); /* If the entry cannot be resolved and that is also the existing state, * there is nothing further to do. @@ -851,12 +740,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, return; /* Process based on type of entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(zvrf, afi, force, nrn, rnh, - prn, re); - else - zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, - re); + zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re); } /* @@ -869,7 +753,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, * covers multiple nexthops we are interested in. */ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, - enum rnh_type type, struct route_node *nrn) + struct route_node *nrn) { struct rnh *rnh; struct route_entry *re; @@ -878,12 +762,7 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, rnh = nrn->info; /* Identify route entry (RIB) resolving this tracked entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, - &prn); - else - re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, - &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); if (re) UNSET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); @@ -893,12 +772,12 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, * of a particular VRF and address-family or a specific prefix. */ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - enum rnh_type type, struct prefix *p) + struct prefix *p, safi_t safi) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, type); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, safi); if (!rnh_table) // unexpected return; @@ -906,7 +785,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, /* Evaluating a specific entry, make sure it exists. */ nrn = route_node_lookup(rnh_table, p); if (nrn && nrn->info) - zebra_rnh_evaluate_entry(zvrf, afi, force, type, nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, nrn); if (nrn) route_unlock_node(nrn); @@ -915,26 +794,25 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_evaluate_entry(zvrf, afi, force, type, - nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_clear_nhc_flag(zvrf, afi, type, nrn); + zebra_rnh_clear_nhc_flag(zvrf, afi, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } } } void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, - enum rnh_type type, struct prefix *p) + struct prefix *p) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, afi, type); + table = get_rnh_table(vrfid, afi, SAFI_UNICAST); if (!table) { if (IS_ZEBRA_DEBUG_NHT) zlog_debug("print_rnhs: rnh table not found"); @@ -1271,8 +1149,7 @@ static bool compare_state(struct route_entry *r1, } int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id, - uint32_t srte_color) + vrf_id_t vrf_id, uint32_t srte_color) { struct stream *s = NULL; struct route_entry *re; @@ -1282,8 +1159,6 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, struct route_node *rn; int ret; uint32_t message = 0; - int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE - : ZEBRA_NEXTHOP_UPDATE; rn = rnh->node; re = rnh->state; @@ -1291,13 +1166,14 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, /* Get output stream. */ s = stream_new(ZEBRA_MAX_PACKET_SIZ); - zclient_create_header(s, cmd, vrf_id); + zclient_create_header(s, ZEBRA_NEXTHOP_UPDATE, vrf_id); /* Message flags. */ if (srte_color) SET_FLAG(message, ZAPI_MESSAGE_SRTE); stream_putl(s, message); + stream_putw(s, rnh->safi); stream_putw(s, rn->p.family); switch (rn->p.family) { case AF_INET: @@ -1444,7 +1320,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty) } static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, - struct zserv *client, enum rnh_type type) + struct zserv *client) { struct route_table *ntable; struct route_node *nrn; @@ -1453,14 +1329,12 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); - zlog_debug( - "%s(%u): Client %s RNH cleanup for family %s type %s", - VRF_LOGNAME(vrf), vrf_id, - zebra_route_string(client->proto), afi2str(afi), - rnh_type2str(type)); + zlog_debug("%s(%u): Client %s RNH cleanup for family %s", + VRF_LOGNAME(vrf), vrf_id, + zebra_route_string(client->proto), afi2str(afi)); } - ntable = get_rnh_table(vrf_id, afi, type); + ntable = get_rnh_table(vrf_id, afi, SAFI_UNICAST); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found"); return -1; @@ -1471,7 +1345,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, continue; rnh = nrn->info; - zebra_remove_rnh_client(rnh, client, type); + zebra_remove_rnh_client(rnh, client); } return 1; } @@ -1485,14 +1359,9 @@ static int zebra_client_cleanup_rnh(struct zserv *client) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { zvrf = vrf->info; if (zvrf) { - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, - RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, - RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, - RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, - RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, + client); } } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 24ee6d0bd9..27c016ebe6 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -31,36 +31,22 @@ extern "C" { extern void zebra_rnh_init(void); -static inline const char *rnh_type2str(enum rnh_type type) -{ - switch (type) { - case RNH_NEXTHOP_TYPE: - return "Nexthop"; - case RNH_IMPORT_CHECK_TYPE: - return "Import"; - } - - return "ERROR"; -} - extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type, bool *exists); + bool *exists); extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type); + safi_t safi); extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrfid); + vrf_id_t vrfid); extern int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id, - uint32_t srte_color); + vrf_id_t vrf_id, uint32_t srte_color); extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); -extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type); +extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client); extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - enum rnh_type type, struct prefix *p); + struct prefix *p, safi_t safi); extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, - enum rnh_type type, struct prefix *p); + struct prefix *p); extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index d07a49fb6e..908c13f3df 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -319,7 +319,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype)); if (NHT_RM_MAP(zvrf, afi, rtype)) - zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -340,8 +340,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, zvrf->vrf->vrf_id, rtype); NHT_RM_MAP(zvrf, afi, rtype) = NULL; - zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, - NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST); } XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); } @@ -1589,8 +1588,8 @@ static void zebra_nht_rm_update(const char *rmap) afi_ip = 1; zebra_evaluate_rnh( - zvrf, AFI_IP, 1, - RNH_NEXTHOP_TYPE, NULL); + zvrf, AFI_IP, 1, NULL, + SAFI_UNICAST); } } } @@ -1620,8 +1619,8 @@ static void zebra_nht_rm_update(const char *rmap) afi_ipv6 = 1; zebra_evaluate_rnh( - zvrf, AFI_IP, 1, - RNH_NEXTHOP_TYPE, NULL); + zvrf, AFI_IP, 1, NULL, + SAFI_UNICAST); } } } diff --git a/zebra/zebra_srte.c b/zebra/zebra_srte.c index ba3727371c..7933ef66b1 100644 --- a/zebra/zebra_srte.c +++ b/zebra/zebra_srte.c @@ -116,6 +116,7 @@ static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy, SET_FLAG(message, ZAPI_MESSAGE_SRTE); stream_putl(s, message); + stream_putw(s, SAFI_UNICAST); switch (policy->endpoint.ipa_type) { case IPADDR_V4: stream_putw(s, AF_INET); @@ -196,7 +197,7 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy) exit(1); } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), RNH_NEXTHOP_TYPE); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), SAFI_UNICAST); if (!rnh) return; @@ -205,8 +206,8 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy) zebra_sr_policy_notify_update_client(policy, client); else /* Fallback to the IGP shortest path. */ - zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE, - zvrf_id(zvrf), policy->color); + zebra_send_rnh_update(rnh, client, zvrf_id(zvrf), + policy->color); } } diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 4fbcc6f596..4b00f3415c 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -44,6 +44,7 @@ #ifndef VTYSH_EXTRACT_PL #include "zebra/zebra_vrf_clippy.c" #endif +#include "zebra/table_manager.h" static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, safi_t safi); @@ -113,6 +114,10 @@ static int zebra_vrf_new(struct vrf *vrf) otable_init(&zvrf->other_tables); router_id_init(zvrf); + + /* Initiate Table Manager per ZNS */ + table_manager_enable(zvrf); + return 0; } @@ -153,7 +158,7 @@ static int zebra_vrf_enable(struct vrf *vrf) table = route_table_init(); table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->import_check_table[afi] = table; + zvrf->rnh_table_multicast[afi] = table; } /* Kick off any VxLAN-EVPN processing. */ @@ -176,6 +181,8 @@ static int zebra_vrf_disable(struct vrf *vrf) zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf), zvrf_id(zvrf)); + table_manager_disable(zvrf); + /* Stop any VxLAN-EVPN processing. */ zebra_vxlan_vrf_disable(zvrf); @@ -196,8 +203,8 @@ static int zebra_vrf_disable(struct vrf *vrf) for (afi = AFI_IP; afi <= AFI_IP6; afi++) { route_table_finish(zvrf->rnh_table[afi]); zvrf->rnh_table[afi] = NULL; - route_table_finish(zvrf->import_check_table[afi]); - zvrf->import_check_table[afi] = NULL; + route_table_finish(zvrf->rnh_table_multicast[afi]); + zvrf->rnh_table_multicast[afi] = NULL; for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) rib_close_table(zvrf->table[afi][safi]); @@ -298,8 +305,8 @@ static int zebra_vrf_delete(struct vrf *vrf) if (zvrf->rnh_table[afi]) route_table_finish(zvrf->rnh_table[afi]); - if (zvrf->import_check_table[afi]) - route_table_finish(zvrf->import_check_table[afi]); + if (zvrf->rnh_table_multicast[afi]) + route_table_finish(zvrf->rnh_table[afi]); } otable = otable_pop(&zvrf->other_tables); @@ -503,6 +510,12 @@ static int vrf_config_write(struct vty *vty) if (zvrf->zebra_rnh_ipv6_default_route) vty_out(vty, "ipv6 nht resolve-via-default\n"); + + if (zvrf->tbl_mgr + && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end)) + vty_out(vty, "ip table range %u %u\n", + zvrf->tbl_mgr->start, + zvrf->tbl_mgr->end); } else { vty_frame(vty, "vrf %s\n", zvrf_name(zvrf)); if (zvrf->l3vni) @@ -517,6 +530,12 @@ static int vrf_config_write(struct vty *vty) if (zvrf->zebra_rnh_ipv6_default_route) vty_out(vty, " ipv6 nht resolve-via-default\n"); + + if (zvrf->tbl_mgr && vrf_is_backend_netns() + && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end)) + vty_out(vty, " ip table range %u %u\n", + zvrf->tbl_mgr->start, + zvrf->tbl_mgr->end); } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index f32f09850b..3def27b79e 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -78,9 +78,7 @@ struct zebra_vrf { /* Recursive Nexthop table */ struct route_table *rnh_table[AFI_MAX]; - - /* Import check table (used mostly by BGP */ - struct route_table *import_check_table[AFI_MAX]; + struct route_table *rnh_table_multicast[AFI_MAX]; struct otable_head other_tables; @@ -177,12 +175,14 @@ struct zebra_vrf { uint64_t lsp_installs; uint64_t lsp_removals; + struct table_manager *tbl_mgr; + #if defined(HAVE_RTADV) struct rtadv rtadv; #endif /* HAVE_RTADV */ - int zebra_rnh_ip_default_route; - int zebra_rnh_ipv6_default_route; + bool zebra_rnh_ip_default_route; + bool zebra_rnh_ipv6_default_route; }; #define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name #define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 79087c5849..06528d3dbe 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -59,6 +59,7 @@ #include "northbound_cli.h" #include "zebra/zebra_nb.h" #include "zebra/kernel_netlink.h" +#include "zebra/table_manager.h" extern int allow_delete; @@ -965,6 +966,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "internalNextHopActiveNum", nexthop_group_active_nexthop_num( &(re->nhe->nhg))); + json_object_int_add(json_route, "nexthopGroupId", re->nhe_id); json_object_string_add(json_route, "uptime", up_str); @@ -1330,12 +1332,6 @@ DEFPY (show_ip_nht, afi_t afi = ipv4 ? AFI_IP : AFI_IP6; vrf_id_t vrf_id = VRF_DEFAULT; struct prefix prefix, *p = NULL; - enum rnh_type rtype; - - if (strcmp(type, "nht") == 0) - rtype = RNH_NEXTHOP_TYPE; - else - rtype = RNH_IMPORT_CHECK_TYPE; if (vrf_all) { struct vrf *vrf; @@ -1345,7 +1341,7 @@ DEFPY (show_ip_nht, if ((zvrf = vrf->info) != NULL) { vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, - rtype, NULL); + NULL); } return CMD_SUCCESS; } @@ -1359,7 +1355,7 @@ DEFPY (show_ip_nht, return CMD_WARNING; } - zebra_print_rnh_table(vrf_id, afi, vty, rtype, p); + zebra_print_rnh_table(vrf_id, afi, vty, p); return CMD_SUCCESS; } @@ -1378,9 +1374,9 @@ DEFUN (ip_nht_default_route, if (zvrf->zebra_rnh_ip_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ip_default_route = 1; + zvrf->zebra_rnh_ip_default_route = true; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1717,8 +1713,8 @@ DEFUN (no_ip_nht_default_route, if (!zvrf->zebra_rnh_ip_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zvrf->zebra_rnh_ip_default_route = false; + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1737,8 +1733,8 @@ DEFUN (ipv6_nht_default_route, if (zvrf->zebra_rnh_ipv6_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zvrf->zebra_rnh_ipv6_default_route = true; + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1758,8 +1754,8 @@ DEFUN (no_ipv6_nht_default_route, if (!zvrf->zebra_rnh_ipv6_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zvrf->zebra_rnh_ipv6_default_route = false; + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -4290,6 +4286,31 @@ DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf, #endif /* HAVE_NETLINK */ +DEFUN(ip_table_range, ip_table_range_cmd, + "[no] ip table range (1-4294967295) (1-4294967295)", + NO_STR IP_STR + "table configuration\n" + "Configure table range\n" + "Start Routing Table\n" + "End Routing Table\n") +{ + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + + if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) { + vty_out(vty, + "VRF subcommand does not make any sense in l3mdev based vrf's\n"); + return CMD_WARNING; + } + + if (strmatch(argv[0]->text, "no")) + return table_manager_range(vty, false, zvrf, NULL, NULL); + + return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg); +} + /* IP node for static routes. */ static int zebra_ip_config(struct vty *vty); static struct cmd_node ip_node = { @@ -4438,6 +4459,9 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd); install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd); + install_element(CONFIG_NODE, &ip_table_range_cmd); + install_element(VRF_NODE, &ip_table_range_cmd); + #ifdef HAVE_NETLINK install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd); install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd); diff --git a/zebra/zserv.c b/zebra/zserv.c index e4a48093f7..abb9c5ca5d 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1007,7 +1007,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; time_t connect_time, last_read_time, last_write_time; uint32_t last_read_cmd, last_write_cmd; - struct client_gr_info *info = NULL; vty_out(vty, "Client: %s", zebra_route_string(client->proto)); if (client->instance) @@ -1100,22 +1099,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt); vty_out(vty, "Errors: %u\n", client->error_cnt); - TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { - vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id)); - vty_out(vty, "Capabilities : "); - switch (info->capabilities) { - case ZEBRA_CLIENT_GR_CAPABILITIES: - vty_out(vty, "Graceful Restart\n"); - break; - case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: - case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: - case ZEBRA_CLIENT_GR_DISABLE: - case ZEBRA_CLIENT_RIB_STALE_TIME: - vty_out(vty, "None\n"); - break; - } - } - #if defined DEV_BUILD vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n", client->ibuf_fifo->count, client->ibuf_fifo->max_count, @@ -1151,7 +1134,8 @@ static void zebra_show_stale_client_detail(struct vty *vty, vty_out(vty, "Capabilities : "); switch (info->capabilities) { case ZEBRA_CLIENT_GR_CAPABILITIES: - vty_out(vty, "Graceful Restart\n"); + vty_out(vty, "Graceful Restart(%u seconds)\n", + info->stale_removal_time); break; case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: |
