diff options
311 files changed, 4226 insertions, 2883 deletions
diff --git a/babeld/route.c b/babeld/route.c index dfd0bfab89..8dd1e40431 100644 --- a/babeld/route.c +++ b/babeld/route.c @@ -166,7 +166,7 @@ resize_route_table(int new_slots) static struct babel_route * insert_route(struct babel_route *route) { - int i, n; + int i, n = 0; assert(!route->installed); 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/bfdd/dplane.c b/bfdd/dplane.c index 4b7f9ba7ac..9dee2a5589 100644 --- a/bfdd/dplane.c +++ b/bfdd/dplane.c @@ -157,8 +157,8 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg) case ECHO_REPLY: case ECHO_REQUEST: zlog_debug(" [dp_time=%" PRIu64 " bfdd_time=%" PRIu64 "]", - (uint64_t)be64toh(msg->data.echo.dp_time), - (uint64_t)be64toh(msg->data.echo.bfdd_time)); + be64toh(msg->data.echo.dp_time), + be64toh(msg->data.echo.bfdd_time)); break; case DP_ADD_SESSION: @@ -245,21 +245,18 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg) " packets), " "out %" PRIu64 " bytes (%" PRIu64 " packets)}]", ntohl(msg->data.session_counters.lid), - (uint64_t)be64toh( - msg->data.session_counters.control_input_bytes), - (uint64_t)be64toh(msg->data.session_counters - .control_input_packets), - (uint64_t)be64toh(msg->data.session_counters - .control_output_bytes), - (uint64_t)be64toh(msg->data.session_counters - .control_output_packets), - (uint64_t)be64toh(msg->data.session_counters.echo_input_bytes), - (uint64_t)be64toh( - msg->data.session_counters.echo_input_packets), - (uint64_t)be64toh( - msg->data.session_counters.echo_output_bytes), - (uint64_t)be64toh(msg->data.session_counters - .echo_output_packets)); + be64toh(msg->data.session_counters.control_input_bytes), + be64toh(msg->data.session_counters + .control_input_packets), + be64toh(msg->data.session_counters + .control_output_bytes), + be64toh(msg->data.session_counters + .control_output_packets), + be64toh(msg->data.session_counters.echo_input_bytes), + be64toh(msg->data.session_counters.echo_input_packets), + be64toh(msg->data.session_counters.echo_output_bytes), + be64toh(msg->data.session_counters + .echo_output_packets)); break; } } 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 3219ae13b5..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); } 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_filter.c b/bgpd/bgp_filter.c index 641cc7605f..7dda4f0180 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -440,7 +440,7 @@ bool config_bgp_aspath_validate(const char *regstr) } DEFUN(as_path, bgp_as_path_cmd, - "bgp as-path access-list WORD [seq (0-4294967295)] <deny|permit> LINE...", + "bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...", BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" @@ -460,7 +460,7 @@ DEFUN(as_path, bgp_as_path_cmd, int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO; /* Retrieve access list name */ - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx); char *alname = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -509,7 +509,7 @@ DEFUN(as_path, bgp_as_path_cmd, } DEFUN(no_as_path, no_bgp_as_path_cmd, - "no bgp as-path access-list WORD [seq (0-4294967295)] <deny|permit> LINE...", + "no bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -529,7 +529,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, regex_t *regex; char *aslistname = - argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx) ? argv[idx]->arg : NULL; /* Lookup AS list from AS path list. */ aslist = as_list_lookup(aslistname); @@ -586,7 +586,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, DEFUN (no_as_path_all, no_bgp_as_path_all_cmd, - "no bgp as-path access-list WORD", + "no bgp as-path access-list AS_PATH_FILTER_NAME", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -653,7 +653,7 @@ static void as_list_show_all(struct vty *vty, json_object *json) DEFUN (show_as_path_access_list, show_bgp_as_path_access_list_cmd, - "show bgp as-path-access-list WORD [json]", + "show bgp as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR BGP_STR "List AS path access lists\n" @@ -684,7 +684,7 @@ DEFUN (show_as_path_access_list, ALIAS (show_as_path_access_list, show_ip_as_path_access_list_cmd, - "show ip as-path-access-list WORD [json]", + "show ip as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR IP_STR "List AS path access lists\n" @@ -753,6 +753,20 @@ static struct cmd_node as_list_node = { .config_write = config_write_as_list, }; +static void bgp_aspath_filter_cmd_completion(vector comps, + struct cmd_token *token) +{ + struct as_list *aslist; + + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, aslist->name)); +} + +static const struct cmd_variable_handler aspath_filter_handlers[] = { + {.tokenname = "AS_PATH_FILTER_NAME", + .completions = bgp_aspath_filter_cmd_completion}, + {.completions = NULL}}; + /* Register functions. */ void bgp_filter_init(void) { @@ -766,6 +780,8 @@ void bgp_filter_init(void) install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd); install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); + + cmd_variable_handler_register(aspath_filter_handlers); } void bgp_filter_reset(void) diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 3c8f2f3668..fa2a445165 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -244,6 +244,10 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi, p = bgp_dest_get_prefix(dest); + if (BGP_DEBUG(labelpool, LABELPOOL)) + zlog_debug("%s: %pFX: %s ", __func__, p, + (reg ? "reg" : "dereg")); + if (reg) { assert(pi); /* 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..2a84f548f8 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2712,6 +2712,28 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, } /* + * Utility to determine whether a particular path_info should use + * the IMPLICIT_NULL label. This is pretty specialized: it's only called + * in a path where we basically _know_ this is a BGP-LU route. + */ +static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) +{ + /* Certain types get imp null; so do paths where the nexthop is + * not labeled. + */ + if (new_select->sub_type == BGP_ROUTE_STATIC + || new_select->sub_type == BGP_ROUTE_AGGREGATE + || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE) + return true; + else if (new_select->extra == NULL || + !bgp_is_valid_label(&new_select->extra->label[0])) + /* TODO -- should be configurable? */ + return true; + else + return false; +} + +/* * old_select = The old best path * new_select = the new best path * @@ -2802,11 +2824,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, * implicit-null for local routes, aggregate * and redistributed routes */ - if (new_select->sub_type == BGP_ROUTE_STATIC - || new_select->sub_type - == BGP_ROUTE_AGGREGATE - || new_select->sub_type - == BGP_ROUTE_REDISTRIBUTE) { + if (bgp_lu_need_imp_null(new_select)) { if (CHECK_FLAG( dest->flags, BGP_NODE_REGISTERED_FOR_LABEL) @@ -4588,8 +4606,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 +4627,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 +4658,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 +4796,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 +4824,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); @@ -12001,7 +12025,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, <[all$all] dampening <parameters>\ |route-map WORD\ |prefix-list WORD\ - |filter-list WORD\ + |filter-list AS_PATH_FILTER_NAME\ |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ @@ -13961,10 +13985,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 +14004,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..72a620aa6c 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']"; @@ -4765,7 +4761,7 @@ DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]", DEFPY_YANG (match_community, match_community_cmd, - "match community <(1-99)|(100-500)|WORD> [exact-match]", + "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]", MATCH_STR "Match BGP community list\n" "Community-list number (standard)\n" @@ -4808,7 +4804,7 @@ DEFPY_YANG (match_community, DEFUN_YANG (no_match_community, no_match_community_cmd, - "no match community [<(1-99)|(100-500)|WORD> [exact-match]]", + "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]", NO_STR MATCH_STR "Match BGP community list\n" @@ -4826,7 +4822,7 @@ DEFUN_YANG (no_match_community, DEFPY_YANG (match_lcommunity, match_lcommunity_cmd, - "match large-community <(1-99)|(100-500)|WORD> [exact-match]", + "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]", MATCH_STR "Match BGP large community list\n" "Large Community-list number (standard)\n" @@ -4869,7 +4865,7 @@ DEFPY_YANG (match_lcommunity, DEFUN_YANG (no_match_lcommunity, no_match_lcommunity_cmd, - "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]", + "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]", NO_STR MATCH_STR "Match BGP large community list\n" @@ -4887,7 +4883,7 @@ DEFUN_YANG (no_match_lcommunity, DEFPY_YANG (match_ecommunity, match_ecommunity_cmd, - "match extcommunity <(1-99)|(100-500)|WORD>", + "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>", MATCH_STR "Match BGP/VPN extended community list\n" "Extended community-list number (standard)\n" @@ -4913,7 +4909,7 @@ DEFPY_YANG (match_ecommunity, DEFUN_YANG (no_match_ecommunity, no_match_ecommunity_cmd, - "no match extcommunity [<(1-99)|(100-500)|WORD>]", + "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]", NO_STR MATCH_STR "Match BGP/VPN extended community list\n" @@ -4931,7 +4927,7 @@ DEFUN_YANG (no_match_ecommunity, DEFUN_YANG (match_aspath, match_aspath_cmd, - "match as-path WORD", + "match as-path AS_PATH_FILTER_NAME", MATCH_STR "Match BGP AS path list\n" "AS path access-list name\n") @@ -4954,7 +4950,7 @@ DEFUN_YANG (match_aspath, DEFUN_YANG (no_match_aspath, no_match_aspath_cmd, - "no match as-path [WORD]", + "no match as-path [AS_PATH_FILTER_NAME]", NO_STR MATCH_STR "Match BGP AS path list\n" @@ -5526,7 +5522,7 @@ ALIAS_YANG (no_set_community, DEFPY_YANG (set_community_delete, set_community_delete_cmd, - "set comm-list <(1-99)|(100-500)|WORD> delete", + "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete", SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" @@ -5553,7 +5549,7 @@ DEFPY_YANG (set_community_delete, DEFUN_YANG (no_set_community_delete, no_set_community_delete_cmd, - "no set comm-list [<(1-99)|(100-500)|WORD> delete]", + "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]", NO_STR SET_STR "set BGP community list (for deletion)\n" @@ -5653,7 +5649,7 @@ ALIAS_YANG (no_set_lcommunity1, DEFPY_YANG (set_lcommunity_delete, set_lcommunity_delete_cmd, - "set large-comm-list <(1-99)|(100-500)|WORD> delete", + "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete", SET_STR "set BGP large community list (for deletion)\n" "Large Community-list number (standard)\n" @@ -5679,7 +5675,7 @@ DEFPY_YANG (set_lcommunity_delete, DEFUN_YANG (no_set_lcommunity_delete, no_set_lcommunity_delete_cmd, - "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]", + "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]", NO_STR SET_STR "set BGP large community list (for deletion)\n" 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..14149b5139 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,234 @@ 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) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_add_zrecv, + TP_ARGS(esi_t *, esi, struct in_addr, vtep, + uint8_t, active, uint8_t, bypass, uint16_t, df_pref), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer(uint8_t, active, active) + ctf_integer(uint8_t, bypass, bypass) + ctf_integer(uint16_t, df_pref, df_pref) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_del_zrecv, + TP_ARGS(esi_t *, esi), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_evi_add_zrecv, + TP_ARGS(esi_t *, esi, vni_t, vni), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_evi_del_zrecv, + TP_ARGS(esi_t *, esi, vni_t, vni), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_vni_add_zrecv, + TP_ARGS(vni_t, vni, struct in_addr, vtep, vrf_id_t, vrf, + struct in_addr, mc_grp), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer_network_hex(unsigned int, mc_grp, + mc_grp.s_addr) + ctf_integer(int, vrf, vrf) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_vni_del_zrecv, + TP_ARGS(vni_t, vni), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_macip_add_zrecv, + TP_ARGS(vni_t, vni, struct ethaddr *, mac, + struct ipaddr *, ip, uint32_t, flags, + uint32_t, seqnum, esi_t *, esi), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_array(unsigned char, mac, mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, ip, + sizeof(struct ipaddr)) + ctf_integer(uint32_t, flags, flags) + ctf_integer(uint32_t, seq, seqnum) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_macip_del_zrecv, + TP_ARGS(vni_t, vni, struct ethaddr *, mac, struct ipaddr *, ip, + int, state), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_array(unsigned char, mac, mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, ip, + sizeof(struct ipaddr)) + ctf_integer(int, state, state) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_l3vni_add_zrecv, + TP_ARGS(vni_t, vni, vrf_id_t, vrf, + struct ethaddr *, svi_rmac, + struct ethaddr *, vrr_rmac, int, filter, + struct in_addr, vtep, int, svi_ifindex, + bool, anycast_mac), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer(int, vrf, vrf) + ctf_array(unsigned char, svi_rmac, svi_rmac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, vrr_rmac, vrr_rmac, + sizeof(struct ethaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer(int, filter, filter) + ctf_integer(int, svi_ifindex, svi_ifindex) + ctf_string(anycast_mac, anycast_mac ? "y" : "n") + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_l3vni_del_zrecv, + TP_ARGS(vni_t, vni, vrf_id_t, vrf), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer(int, vrf, vrf) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_del_zrecv, TRACE_INFO) /* clang-format on */ #include <lttng/tracepoint-event.h> diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 14f4fb7310..158a5f30b7 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") @@ -7250,7 +7242,7 @@ static int peer_aslist_unset_vty(struct vty *vty, const char *ip_str, afi_t afi, DEFUN (neighbor_filter_list, neighbor_filter_list_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" @@ -7267,7 +7259,7 @@ DEFUN (neighbor_filter_list, } ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" @@ -7276,7 +7268,7 @@ ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, DEFUN (no_neighbor_filter_list, no_neighbor_filter_list_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -7293,7 +7285,7 @@ DEFUN (no_neighbor_filter_list, } ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list WORD <in|out>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" @@ -19069,7 +19061,7 @@ static void community_list_perror(struct vty *vty, int ret) /*community-list standard */ DEFUN (community_list_standard, bgp_community_list_standard_cmd, - "bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" @@ -19093,7 +19085,7 @@ DEFUN (community_list_standard, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -19116,7 +19108,7 @@ DEFUN (community_list_standard, DEFUN (no_community_list_standard_all, no_bgp_community_list_standard_all_cmd, - "no bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR @@ -19156,7 +19148,7 @@ DEFUN (no_community_list_standard_all, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, @@ -19173,7 +19165,7 @@ DEFUN (no_community_list_standard_all, } ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd, - "no bgp community-list <(1-99)|standard WORD>", + "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME>", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" "Add an standard community-list entry\n" @@ -19182,7 +19174,7 @@ ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cm /*community-list expanded */ DEFUN (community_list_expanded_all, bgp_community_list_expanded_all_cmd, - "bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" @@ -19207,7 +19199,7 @@ DEFUN (community_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -19230,7 +19222,7 @@ DEFUN (community_list_expanded_all, DEFUN (no_community_list_expanded_all, no_bgp_community_list_expanded_all_cmd, - "no bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR @@ -19270,7 +19262,7 @@ DEFUN (no_community_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, @@ -19288,7 +19280,7 @@ DEFUN (no_community_list_expanded_all, ALIAS(no_community_list_expanded_all, no_bgp_community_list_expanded_all_list_cmd, - "no bgp community-list <(100-500)|expanded WORD>", + "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME>", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" "Add an expanded community-list entry\n" @@ -19366,7 +19358,7 @@ DEFUN (show_community_list, DEFUN (show_community_list_arg, show_bgp_community_list_arg_cmd, - "show bgp community-list <(1-500)|WORD> detail", + "show bgp community-list <(1-500)|COMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List community-list\n" @@ -19412,7 +19404,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, /* All digit name check. */ idx = 0; - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx); argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "(100-500)", &idx); cl_name = argv[idx]->arg; @@ -19476,7 +19468,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, idx = 0; argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx); /* Unset community list. */ ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct, @@ -19532,7 +19524,7 @@ DEFUN (lcommunity_list_expanded, DEFUN (lcommunity_list_name_standard, bgp_lcommunity_list_name_standard_cmd, - "bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:BB:CC...", + "bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" @@ -19549,7 +19541,7 @@ DEFUN (lcommunity_list_name_standard, DEFUN (lcommunity_list_name_expanded, bgp_lcommunity_list_name_expanded_cmd, - "bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...", + "bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...", BGP_STR LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" @@ -19566,7 +19558,7 @@ DEFUN (lcommunity_list_name_expanded, DEFUN (no_lcommunity_list_all, no_bgp_lcommunity_list_all_cmd, - "no bgp large-community-list <(1-99)|(100-500)|WORD>", + "no bgp large-community-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME>", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19580,7 +19572,7 @@ DEFUN (no_lcommunity_list_all, DEFUN (no_lcommunity_list_name_standard_all, no_bgp_lcommunity_list_name_standard_all_cmd, - "no bgp large-community-list standard WORD", + "no bgp large-community-list standard LCOMMUNITY_LIST_NAME", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19593,7 +19585,7 @@ DEFUN (no_lcommunity_list_name_standard_all, DEFUN (no_lcommunity_list_name_expanded_all, no_bgp_lcommunity_list_name_expanded_all_cmd, - "no bgp large-community-list expanded WORD", + "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19640,7 +19632,7 @@ DEFUN (no_lcommunity_list_expanded, DEFUN (no_lcommunity_list_name_standard, no_bgp_lcommunity_list_name_standard_cmd, - "no bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:AA:NN...", + "no bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:AA:NN...", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19658,7 +19650,7 @@ DEFUN (no_lcommunity_list_name_standard, DEFUN (no_lcommunity_list_name_expanded, no_bgp_lcommunity_list_name_expanded_cmd, - "no bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...", + "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19732,7 +19724,7 @@ DEFUN (show_lcommunity_list, DEFUN (show_lcommunity_list_arg, show_bgp_lcommunity_list_arg_cmd, - "show bgp large-community-list <(1-500)|WORD> detail", + "show bgp large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List large-community list\n" @@ -19760,7 +19752,7 @@ DEFUN (show_lcommunity_list_arg, DEFUN (extcommunity_list_standard, bgp_extcommunity_list_standard_cmd, - "bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" @@ -19780,7 +19772,7 @@ DEFUN (extcommunity_list_standard, int idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -19806,7 +19798,7 @@ DEFUN (extcommunity_list_standard, DEFUN (extcommunity_list_name_expanded, bgp_extcommunity_list_name_expanded_cmd, - "bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...", + "bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" @@ -19825,7 +19817,7 @@ DEFUN (extcommunity_list_name_expanded, int idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -19851,7 +19843,7 @@ DEFUN (extcommunity_list_name_expanded, DEFUN (no_extcommunity_list_standard_all, no_bgp_extcommunity_list_standard_all_cmd, - "no bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...", + "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR @@ -19889,7 +19881,7 @@ DEFUN (no_extcommunity_list_standard_all, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, @@ -19907,7 +19899,7 @@ DEFUN (no_extcommunity_list_standard_all, ALIAS(no_extcommunity_list_standard_all, no_bgp_extcommunity_list_standard_all_list_cmd, - "no bgp extcommunity-list <(1-99)|standard WORD>", + "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME>", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" "Specify standard extcommunity-list\n" @@ -19915,7 +19907,7 @@ ALIAS(no_extcommunity_list_standard_all, DEFUN (no_extcommunity_list_expanded_all, no_bgp_extcommunity_list_expanded_all_cmd, - "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...", + "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR @@ -19954,7 +19946,7 @@ DEFUN (no_extcommunity_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, @@ -19972,7 +19964,7 @@ DEFUN (no_extcommunity_list_expanded_all, ALIAS(no_extcommunity_list_expanded_all, no_bgp_extcommunity_list_expanded_all_list_cmd, - "no bgp extcommunity-list <(100-500)|expanded WORD>", + "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME>", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" @@ -20033,7 +20025,7 @@ DEFUN (show_extcommunity_list, DEFUN (show_extcommunity_list_arg, show_bgp_extcommunity_list_arg_cmd, - "show bgp extcommunity-list <(1-500)|WORD> detail", + "show bgp extcommunity-list <(1-500)|EXTCOMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List extended-community list\n" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a67bb2f8c..6161f56fe6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -64,6 +64,7 @@ #include "bgpd/bgp_evpn_private.h" #include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_mac.h" +#include "bgpd/bgp_trace.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -112,12 +113,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 +333,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 +354,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; @@ -2747,6 +2774,9 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS) esi_to_str(&esi, buf, sizeof(buf)), &originator_ip, active, df_pref, bypass ? "bypass" : ""); + frrtrace(5, frr_bgp, evpn_mh_local_es_add_zrecv, &esi, originator_ip, + active, bypass, df_pref); + bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref, !!bypass); @@ -2772,6 +2802,8 @@ static int bgp_zebra_process_local_es_del(ZAPI_CALLBACK_ARGS) zlog_debug("Rx del ESI %s", esi_to_str(&esi, buf, sizeof(buf))); + frrtrace(1, frr_bgp, evpn_mh_local_es_del_zrecv, &esi); + bgp_evpn_local_es_del(bgp, &esi); return 0; @@ -2798,10 +2830,15 @@ static int bgp_zebra_process_local_es_evi(ZAPI_CALLBACK_ARGS) ZEBRA_VNI_ADD ? "add" : "del", esi_to_str(&esi, buf, sizeof(buf)), vni); - if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) + if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) { + frrtrace(2, frr_bgp, evpn_mh_local_es_evi_add_zrecv, &esi, vni); + bgp_evpn_local_es_evi_add(bgp, &esi, vni); - else + } else { + frrtrace(2, frr_bgp, evpn_mh_local_es_evi_del_zrecv, &esi, vni); + bgp_evpn_local_es_evi_del(bgp, &esi, vni); + } return 0; } @@ -2836,6 +2873,10 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS) filter ? "prefix-routes-only" : "none", svi_ifindex); + frrtrace(8, frr_bgp, evpn_local_l3vni_add_zrecv, l3vni, vrf_id, + &svi_rmac, &vrr_rmac, filter, originator_ip, + svi_ifindex, is_anycast_mac); + bgp_evpn_local_l3vni_add(l3vni, vrf_id, &svi_rmac, &vrr_rmac, originator_ip, filter, svi_ifindex, is_anycast_mac); @@ -2844,6 +2885,8 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS) zlog_debug("Rx L3-VNI DEL VRF %s VNI %u", vrf_id_to_name(vrf_id), l3vni); + frrtrace(2, frr_bgp, evpn_local_l3vni_del_zrecv, l3vni, vrf_id); + bgp_evpn_local_l3vni_del(l3vni, vrf_id); } @@ -2880,13 +2923,19 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS) vrf_id_to_name(vrf_id), vni, vrf_id_to_name(tenant_vrf_id), svi_ifindex); - if (cmd == ZEBRA_VNI_ADD) + if (cmd == ZEBRA_VNI_ADD) { + frrtrace(4, frr_bgp, evpn_local_vni_add_zrecv, vni, vtep_ip, + tenant_vrf_id, mcast_grp); + return bgp_evpn_local_vni_add( bgp, vni, vtep_ip.s_addr != INADDR_ANY ? vtep_ip : bgp->router_id, tenant_vrf_id, mcast_grp, svi_ifindex); - else + } else { + frrtrace(1, frr_bgp, evpn_local_vni_del_zrecv, vni); + return bgp_evpn_local_vni_del(bgp, vni); + } } static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) @@ -2942,11 +2991,18 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) &mac, &ip, vni, seqnum, state, esi_to_str(&esi, buf2, sizeof(buf2))); - if (cmd == ZEBRA_MACIP_ADD) + if (cmd == ZEBRA_MACIP_ADD) { + frrtrace(6, frr_bgp, evpn_local_macip_add_zrecv, vni, &mac, &ip, + flags, seqnum, &esi); + return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags, seqnum, &esi); - else + } else { + frrtrace(4, frr_bgp, evpn_local_macip_del_zrecv, vni, &mac, &ip, + state); + return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state); + } } static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS) @@ -3185,7 +3241,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/debian/frr-pythontools.install b/debian/frr-pythontools.install index 5f7eaebed5..820895ce68 100644 --- a/debian/frr-pythontools.install +++ b/debian/frr-pythontools.install @@ -1,2 +1,3 @@ usr/lib/frr/frr-reload.py usr/lib/frr/generate_support_bundle.py +usr/lib/frr/frr_babeltrace.py diff --git a/doc/developer/conf.py b/doc/developer/conf.py index 8f282c0790..61df6e0e60 100644 --- a/doc/developer/conf.py +++ b/doc/developer/conf.py @@ -138,6 +138,7 @@ exclude_patterns = [ "_build", "building-libyang.rst", "topotests-snippets.rst", + "topotests-markers.rst", "include-compile.rst", ] diff --git a/doc/developer/link-state.rst b/doc/developer/link-state.rst index 1cbaf27ffe..2072595e36 100644 --- a/doc/developer/link-state.rst +++ b/doc/developer/link-state.rst @@ -53,15 +53,15 @@ Data structures 3 types of Link State structure have been defined: -.. c:type:: struct ls_node +.. c:struct:: ls_node that groups all information related to a node -.. c:type:: struct ls_attributes +.. c:struct:: ls_attributes that groups all information related to a link -.. c:type:: struct ls_prefix +.. c:struct:: ls_prefix that groups all information related to a prefix @@ -73,7 +73,7 @@ identifier which advertises the Link State and a bit mask as flags to indicates which parameters are valid i.e. for which the value is valid and corresponds to a Link State information conveyed by the routing protocol. -.. c:type:: struct ls_node_id +.. c:struct:: ls_node_id defines the Node identifier as router ID IPv4 address plus the area ID for OSPF or the ISO System ID plus the IS-IS level for IS-IS. @@ -159,10 +159,11 @@ A unique Key is used to identify both Vertices and Edges within the Graph. 4 data structures have been defined to implement the Graph model: -.. c:type:: struct ls_vertex -.. c:type:: struct ls_edge -.. c:type:: struct ls_prefix -.. c:type:: struct ls_ted +.. c:struct:: ls_vertex +.. c:struct:: ls_edge +.. c:struct:: ls_ted + + - :c:struct:`ls_prefix` TED stores Vertex, Edge and Subnet elements with a RB Tree structure. The Vertex key corresponds to the Router ID for OSPF and ISO System ID for @@ -412,7 +413,7 @@ Data Structures The Link State Message is defined to convey Link State parameters from the routing protocol (OSPF or IS-IS) to other daemons e.g. BGP. -.. c:type:: struct ls_message +.. c:struct:: ls_message The structure is composed of: diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst index 553bd1f596..dc8f236927 100644 --- a/doc/developer/lists.rst +++ b/doc/developer/lists.rst @@ -106,19 +106,25 @@ Functions provided: | _init, _fini | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ | _first, _next, _next_safe, | yes | yes | yes | yes | yes | +| | | | | | | | _const_first, _const_next | | | | | | +------------------------------------+------+------+------+---------+------------+ | _swap_all | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ +| _anywhere | yes | -- | -- | -- | -- | ++------------------------------------+------+------+------+---------+------------+ | _add_head, _add_tail, _add_after | yes | -- | -- | -- | -- | +------------------------------------+------+------+------+---------+------------+ | _add | -- | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ +| _member | yes | yes | yes | yes | yes | ++------------------------------------+------+------+------+---------+------------+ | _del, _pop | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ | _find, _const_find | -- | -- | yes | yes | -- | +------------------------------------+------+------+------+---------+------------+ | _find_lt, _find_gteq, | -- | -- | -- | yes | yes | +| | | | | | | | _const_find_lt, _const_find_gteq | | | | | | +------------------------------------+------+------+------+---------+------------+ | use with frr_each() macros | yes | yes | yes | yes | yes | @@ -182,7 +188,7 @@ Common iteration macros The following iteration macros work across all data structures: -.. c:function:: frr_each(Z, &head, item) +.. c:macro:: frr_each(Z, head, item) Equivalent to: @@ -193,7 +199,7 @@ The following iteration macros work across all data structures: Note that this will fail if the list is modified while being iterated over. -.. c:function:: frr_each_safe(Z, &head, item) +.. c:macro:: frr_each_safe(Z, head, item) Same as the previous, but the next element is pre-loaded into a "hidden" variable (named ``Z_safe``.) Equivalent to: @@ -212,7 +218,7 @@ The following iteration macros work across all data structures: tables is resized while iterating. This will cause items to be skipped or iterated over twice. -.. c:function:: frr_each_from(Z, &head, item, from) +.. c:macro:: frr_each_from(Z, head, item, from) Iterates over the list, starting at item ``from``. This variant is "safe" as in the previous macro. Equivalent to: @@ -268,6 +274,16 @@ The following documentation assumes that a list has been defined using outdated by the time this function returns and can therefore only be used as an estimate. +.. c:function:: bool Z_member(const struct Z_head *, const itemtype *) + + Determines whether some item is a member of the given container. The + item must either be valid on some container, or set to all zeroes. + + On some containers, if no faster way to determine membership is possible, + this is simply ``item == Z_find(head, item)``. + + Not currently available for atomic containers. + .. c:function:: const itemtype *Z_const_first(const struct Z_head *) .. c:function:: itemtype *Z_first(struct Z_head *) @@ -297,7 +313,7 @@ The following documentation assumes that a list has been defined using affected by the "modification while iterating" problem. To remove all items from a hash table, use the loop demonstrated above. -.. c:function:: const itemtype *Z_next(const struct Z_head *, const itemtype *prev) +.. c:function:: const itemtype *Z_const_next(const struct Z_head *, const itemtype *prev) .. c:function:: itemtype *Z_next(struct Z_head *, itemtype *prev) Return the item that follows after ``prev``, or ``NULL`` if ``prev`` is @@ -346,7 +362,7 @@ are several functions exposed to insert data: ``item`` must not be ``NULL`` for any of the following functions. -.. c:function:: DECLARE_XXX(Z, type, field) +.. c:macro:: DECLARE_XXX(Z, type, field) :param listtype XXX: ``LIST``, ``DLIST`` or ``ATOMLIST`` to select a data structure implementation. @@ -396,6 +412,17 @@ are several functions exposed to insert data: maybe flip the order of ``item`` & ``after``? ``Z_add_after(head, item, after)`` +.. c:function:: bool Z_anywhere(const itemtype *) + + Returns whether an item is a member of *any* container of this type. + The item must either be valid on some container, or set to all zeroes. + + Guaranteed to be fast (pointer compare or similar.) + + Not currently available for sorted and atomic containers. Might be added + for sorted containers at some point (when needed.) + + API for sorted structures ------------------------- @@ -403,7 +430,7 @@ Sorted data structures do not need to have an insertion position specified, therefore the insertion calls are different from unsorted lists. Also, sorted lists can be searched for a value. -.. c:function:: DECLARE_XXX_UNIQ(Z, type, field, compare_func) +.. c:macro:: DECLARE_XXX_UNIQ(Z, type, field, compare_func) :param listtype XXX: One of the following: ``SORTLIST`` (single-linked sorted list), ``SKIPLIST`` (skiplist), @@ -423,7 +450,7 @@ sorted lists can be searched for a value. ``int function(const itemtype *, const itemtype*)``. This function may be static if the list is only used in one file. -.. c:function:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func) +.. c:macro:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func) Same as above, but allow adding multiple items to the list that compare as equal in ``compare_func``. Ordering between these items is undefined @@ -439,7 +466,7 @@ sorted lists can be searched for a value. For ``_NONUNIQ`` lists, this function always returns NULL since ``item`` can always be successfully added to the list. -.. c:function:: const itemtype *Z_find(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find(struct Z_head *, const itemtype *ref) Search the list for an item that compares equal to ``ref``. If no equal @@ -461,13 +488,13 @@ sorted lists can be searched for a value. containing non-unique items, more than one item may compare as equal to the item that is searched for. -.. c:function:: const itemtype *Z_find_gteq(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find_gteq(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find_gteq(struct Z_head *, const itemtype *ref) Search the list for an item that compares greater or equal to ``ref``. See :c:func:`Z_find()` above. -.. c:function:: const itemtype *Z_find_lt(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find_lt(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find_lt(struct Z_head *, const itemtype *ref) Search the list for an item that compares less than @@ -477,9 +504,9 @@ sorted lists can be searched for a value. API for hash tables ------------------- -.. c:function:: DECLARE_XXX(Z, type, field, compare_func, hash_func) +.. c:macro:: DECLARE_HASH(Z, type, field, compare_func, hash_func) - :param listtype XXX: Only ``HASH`` is currently available. + :param listtype HASH: Only ``HASH`` is currently available. :param token Z: Gives the name prefix that is used for the functions created for this instantiation. ``DECLARE_XXX(foo, ...)`` gives ``struct foo_item``, ``foo_add()``, ``foo_count()``, etc. Note diff --git a/doc/developer/locking.rst b/doc/developer/locking.rst index d698789f9f..c8366480d2 100644 --- a/doc/developer/locking.rst +++ b/doc/developer/locking.rst @@ -7,7 +7,9 @@ FRR ships two small wrappers around ``pthread_mutex_lock()`` / ``pthread_mutex_unlock``. Use ``#include "frr_pthread.h"`` to get these macros. -.. c:function:: frr_with_mutex(pthread_mutex_t *mutex) +.. c:macro:: frr_with_mutex(mutex) + + (With ``pthread_mutex_t *mutex``.) Begin a C statement block that is executed with the mutex locked. Any exit from the block (``break``, ``return``, ``goto``, end of block) will @@ -43,7 +45,9 @@ macros. statement works correctly, FRR coding style requires that this macro always be used with a ``{ ... }`` block. -.. c:function:: frr_mutex_lock_autounlock(pthread_mutex_t *mutex) +.. c:macro:: frr_mutex_lock_autounlock(mutex) + + (With ``pthread_mutex_t *mutex``.) Lock mutex and unlock at the end of the current C statement block:: diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst index 681fc1173c..eaf8625efa 100644 --- a/doc/developer/logging.rst +++ b/doc/developer/logging.rst @@ -489,7 +489,7 @@ calls to :c:func:`zlog_tls_buffer_flush()` in appropriate places: buffer. This function is safe to call regardless of the per-thread log buffer being set up / in use or not. -When working with threads that do not use the :c:type:`struct thread_master` +When working with threads that do not use the :c:struct:`thread_master` event loop, per-thread buffers can be managed with: .. c:function:: void zlog_tls_buffer_init(void) @@ -531,7 +531,7 @@ that they use. Basic internals ^^^^^^^^^^^^^^^ -.. c:type:: struct zlog_target +.. c:struct:: zlog_target This struct needs to be filled in by any log target and then passed to :c:func:`zlog_target_replace()`. After it has been registered, @@ -570,7 +570,7 @@ Basic internals Allocates a logging target struct. Note that the ``oldzt`` argument may be ``NULL`` to allocate a "from scratch". If ``oldzt`` is not ``NULL``, the - generic bits in :c:type:`struct zlog_target` are copied. **Target specific + generic bits in :c:struct:`zlog_target` are copied. **Target specific bits are not copied.** .. c:function:: struct zlog_target *zlog_target_replace(struct zlog_target *oldzt, struct zlog_target *newzt) diff --git a/doc/developer/memtypes.rst b/doc/developer/memtypes.rst index 08dad7fb68..2e181c4f2b 100644 --- a/doc/developer/memtypes.rst +++ b/doc/developer/memtypes.rst @@ -42,7 +42,7 @@ Example: Definition ---------- -.. c:type:: struct memtype +.. c:struct:: memtype This is the (internal) type used for MTYPE definitions. The macros below should be used to create these, but in some cases it is useful to pass a diff --git a/doc/developer/rcu.rst b/doc/developer/rcu.rst index c2ddf93f53..c8248194b7 100644 --- a/doc/developer/rcu.rst +++ b/doc/developer/rcu.rst @@ -133,9 +133,9 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks. become invalid, as another thread may have called :c:func:`rcu_free` on them. -.. c:type:: struct rcu_head -.. c:type:: struct rcu_head_close -.. c:type:: struct rcu_action +.. c:struct:: rcu_head +.. c:struct:: rcu_head_close +.. c:struct:: rcu_action The ``rcu_head`` structures are small (16-byte) bits that contain the queueing machinery for the RCU sweeper/cleanup mechanisms. @@ -209,7 +209,7 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks. Internals ^^^^^^^^^ -.. c:type:: struct rcu_thread +.. c:struct:: rcu_thread Per-thread state maintained by the RCU code, set up by the following functions. A pointer to a thread's own ``rcu_thread`` is saved in diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index b4f6ec521c..d8b3650944 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -137,14 +137,14 @@ 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 +specify the ``-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 +If you do not wish to use ``-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. @@ -197,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 :option:`-E` flag +the ``-E`` flag .. code:: shell @@ -385,7 +385,7 @@ 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 +``-E`` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to automatically pass that environment variable through to the ``sudo`` environment. @@ -903,6 +903,7 @@ Interface), from here you can call your router ``vtysh`` or even bash. Here's the help text: .. code:: shell + unet> help Commands: @@ -912,8 +913,6 @@ Here's the help text: vtysh [hosts] :: open vtysh terminals for hosts [hosts] <vtysh-command> :: execute vtysh-command on hosts -.. code:: shell - Here are some commands example: .. code:: shell diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 2ce5f5d1c8..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``. @@ -1151,6 +1161,37 @@ but are no longer actively maintained. MemorySanitizer is not available in GCC. The different Sanitizers are mostly incompatible with each other. Please refer to GCC/LLVM documentation for details. +frr-format plugin + This is a GCC plugin provided with FRR that does extended type checks for + ``%pFX``-style printfrr extensions. To use this plugin, + + 1. install GCC plugin development files, e.g.:: + + apt-get install gcc-10-plugin-dev + + 2. **before** running ``configure``, compile the plugin with:: + + make -C tools/gcc-plugins CXX=g++-10 + + (Edit the GCC version to what you're using, it should work for GCC 9 or + newer.) + + After this, the plugin should be automatically picked up by ``configure``. + The plugin does not change very frequently, so you can keep it around across + work on different FRR branches. After a ``git clean -x``, the ``make`` line + will need to be run again. You can also add ``--with-frr-format`` to the + ``configure`` line to make sure the plugin is used, otherwise if something + is not set up correctly it might be silently ignored. + + .. warning:: + + Do **not** enable this plugin for package/release builds. It is intended + for developer/debug builds only. Since it modifies the compiler, it may + cause silent corruption of the executable files. + + Using the plugin also changes the string for ``PRI[udx]64`` from the + system value to ``%L[udx]`` (normally ``%ll[udx]`` or ``%l[udx]``.) + Additionally, the FRR codebase is regularly scanned with Coverity. Unfortunately Coverity does not have the ability to handle scanning pull requests, but after code is merged it will send an email notifying project @@ -1264,6 +1305,24 @@ may not be obvious in how to fix. Here are some notes on specific warnings: (and varargs calling convention.) This is a notable difference to C++, where the ``void`` is optional and an empty parameter list means no parameters. +* ``"strict match required"`` from the frr-format plugin: check if you are + using a cast in a printf parameter list. The frr-format plugin cannot + access correct full type information for casts like + ``printfrr(..., (uint64_t)something, ...)`` and will print incorrect + warnings particularly if ``uint64_t``, ``size_t`` or ``ptrdiff_t`` are + involved. The problem is *not* triggered with a variable or function return + value of the exact same type (without a cast). + + Since these cases are very rare, community consensus is to just work around + the warning even though the code might be correct. If you are running into + this, your options are: + + 1. try to avoid the cast altogether, maybe using a different printf format + specifier (e.g. ``%lu`` instead of ``%zu`` or ``PRIu64``). + 2. fix the type(s) of the function/variable/struct member being printed + 3. create a temporary variable with the value and print that without a cast + (this is the last resort and was not necessary anywhere so far.) + .. _documentation: 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..624510323c 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 ==================================== @@ -176,7 +181,7 @@ OSPF6 area The `not-advertise` option, when present, prevents the summary route from being advertised, effectively filtering the summarized routes. -.. clicmd:: area A.B.C.D nssa [no-summary] +.. clicmd:: area A.B.C.D nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] .. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] @@ -204,6 +209,21 @@ OSPF6 area existence of a default route in the RIB that wasn't learned via the OSPF protocol. +.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>] + +.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>] + + Summarize a group of external subnets into a single Type-7 LSA, which is + then translated to a Type-5 LSA and avertised to the backbone. + This command can only be used at the area boundary (NSSA ABR router). + + By default, the metric of the summary route is calculated as the highest + metric among the summarized routes. The `cost` option, however, can be used + to set an explicit metric. + + The `not-advertise` option, when present, prevents the summary route from + being advertised, effectively filtering the summarized routes. + .. clicmd:: area A.B.C.D export-list NAME .. clicmd:: area (0-4294967295) export-list NAME @@ -476,9 +496,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_snmp.c b/isisd/isis_snmp.c index c530eb9169..1b78dc0be6 100644 --- a/isisd/isis_snmp.c +++ b/isisd/isis_snmp.c @@ -2571,7 +2571,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, */ if (adj->last_upd != 0) { val = time(NULL); - if (val < (adj->last_upd + adj->hold_time)) + if (val < ((time_t)adj->last_upd + (time_t)adj->hold_time)) return SNMP_INTEGER(adj->last_upd + adj->hold_time - val); } 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 e24eba7cd4..0ff3238ff9 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -243,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, @@ -393,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 || @@ -403,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.c b/lib/command.c index 53aa064705..ea66a17bb0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -86,6 +86,9 @@ vector cmdvec = NULL; /* Host information structure. */ struct host host; +/* for vtysh, put together CLI trees only when switching into node */ +static bool defer_cli_tree; + /* * Returns host.name if any, otherwise * it returns the system hostname. @@ -285,6 +288,11 @@ const char *cmd_prompt(enum node_type node) return cnode->prompt; } +void cmd_defer_tree(bool val) +{ + defer_cli_tree = val; +} + /* Install a command into a node. */ void _install_element(enum node_type ntype, const struct cmd_element *cmd) { @@ -319,20 +327,50 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd) assert(hash_get(cnode->cmd_hash, (void *)cmd, hash_alloc_intern)); + if (cnode->graph_built || !defer_cli_tree) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); + + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, +1); + graph_delete_graph(graph); + + cnode->graph_built = true; + } + + vector_set(cnode->cmd_vector, (void *)cmd); + + if (ntype == VIEW_NODE) + _install_element(ENABLE_NODE, cmd); +} + +static void cmd_finalize_iter(struct hash_bucket *hb, void *arg) +{ + struct cmd_node *cnode = arg; + const struct cmd_element *cmd = hb->data; struct graph *graph = graph_new(); struct cmd_token *token = cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); cmd_graph_parse(graph, cmd); cmd_graph_names(graph); cmd_graph_merge(cnode->cmdgraph, graph, +1); graph_delete_graph(graph); +} - vector_set(cnode->cmd_vector, (void *)cmd); +void cmd_finalize_node(struct cmd_node *cnode) +{ + if (cnode->graph_built) + return; - if (ntype == VIEW_NODE) - _install_element(ENABLE_NODE, cmd); + hash_iterate(cnode->cmd_hash, cmd_finalize_iter, cnode); + cnode->graph_built = true; } void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) @@ -368,15 +406,18 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) vector_unset_value(cnode->cmd_vector, (void *)cmd); - struct graph *graph = graph_new(); - struct cmd_token *token = - cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); + if (cnode->graph_built) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); - cmd_graph_parse(graph, cmd); - cmd_graph_names(graph); - cmd_graph_merge(cnode->cmdgraph, graph, -1); - graph_delete_graph(graph); + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, -1); + graph_delete_graph(graph); + } if (ntype == VIEW_NODE) uninstall_element(ENABLE_NODE, cmd); @@ -503,6 +544,8 @@ static int config_write_host(struct vty *vty) static struct graph *cmd_node_graph(vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot(v, ntype); + + cmd_finalize_node(cnode); return cnode->cmdgraph; } @@ -1506,9 +1549,10 @@ int cmd_list_cmds(struct vty *vty, int do_permute) { struct cmd_node *node = vector_slot(cmdvec, vty->node); - if (do_permute) + if (do_permute) { + cmd_finalize_node(node); permute(vector_slot(node->cmdgraph->nodes, 0), vty); - else { + } else { /* loop over all commands at this node */ const struct cmd_element *element = NULL; for (unsigned int i = 0; i < vector_active(node->cmd_vector); @@ -1551,7 +1595,10 @@ DEFUN_HIDDEN(show_cli_graph, "Dump current command space as DOT graph\n") { struct cmd_node *cn = vector_slot(cmdvec, vty->node); - char *dot = cmd_graph_dump_dot(cn->cmdgraph); + char *dot; + + cmd_finalize_node(cn); + dot = cmd_graph_dump_dot(cn->cmdgraph); vty_out(vty, "%s\n", dot); XFREE(MTYPE_TMP, dot); diff --git a/lib/command.h b/lib/command.h index 8a7c9a2048..e2086701ad 100644 --- a/lib/command.h +++ b/lib/command.h @@ -210,6 +210,9 @@ struct cmd_node { /* Hashed index of command node list, for de-dupping primarily */ struct hash *cmd_hash; + + /* set as soon as any command is in cmdgraph */ + bool graph_built; }; /* Return value of the commands. */ @@ -234,7 +237,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 */ @@ -526,6 +529,12 @@ extern void _install_element(enum node_type, const struct cmd_element *); * deprecated/hidden) are not reversed. */ extern void uninstall_element(enum node_type, const struct cmd_element *); +/* construct CLI tree only when entering nodes */ +extern void cmd_defer_tree(bool val); + +/* finish CLI tree for node when above is true (noop otherwise) */ +extern void cmd_finalize_node(struct cmd_node *node); + /* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ diff --git a/lib/command_graph.c b/lib/command_graph.c index 15c8302e63..09d802e796 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -77,16 +77,17 @@ struct cmd_token *cmd_token_dup(struct cmd_token *token) return copy; } -void cmd_token_varname_set(struct cmd_token *token, const char *varname) +static void cmd_token_varname_do(struct cmd_token *token, const char *varname, + uint8_t varname_src) { - XFREE(MTYPE_CMD_VAR, token->varname); - if (!varname) { - token->varname = NULL; + if (token->varname_src >= varname_src) return; - } + + XFREE(MTYPE_CMD_VAR, token->varname); size_t len = strlen(varname), i; token->varname = XMALLOC(MTYPE_CMD_VAR, len + 1); + token->varname_src = varname_src; for (i = 0; i < len; i++) switch (varname[i]) { @@ -102,6 +103,80 @@ void cmd_token_varname_set(struct cmd_token *token, const char *varname) token->varname[len] = '\0'; } +void cmd_token_varname_set(struct cmd_token *token, const char *varname) +{ + if (varname) { + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + return; + } + if (token->type == VARIABLE_TKN) { + if (strcmp(token->text, "WORD") && strcmp(token->text, "NAME")) + cmd_token_varname_do(token, token->text, VARNAME_TEXT); + } +} + +static void cmd_token_varname_fork(struct graph_node *node, + struct cmd_token *prevtoken) +{ + for (size_t i = 0; i < vector_active(node->to); i++) { + struct graph_node *next = vector_slot(node->to, i); + struct cmd_token *nexttoken = next->data; + + if (nexttoken->type == FORK_TKN) { + cmd_token_varname_fork(next, prevtoken); + continue; + } + if (nexttoken->varname) + continue; + if (!IS_VARYING_TOKEN(nexttoken->type)) + continue; + + cmd_token_varname_do(nexttoken, prevtoken->text, VARNAME_TEXT); + } +} + +void cmd_token_varname_join(struct graph_node *join, const char *varname) +{ + if (!varname) + return; + + for (size_t i = 0; i < vector_active(join->from); i++) { + struct graph_node *prev = vector_slot(join->from, i); + struct cmd_token *token = prev->data; + + if (token->type == JOIN_TKN) + cmd_token_varname_join(prev, varname); + else if (token->type < SPECIAL_TKN) + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + } +} + +void cmd_token_varname_seqappend(struct graph_node *node) +{ + struct graph_node *prevnode = node; + struct cmd_token *token = node->data; + struct cmd_token *prevtoken; + + if (token->type == WORD_TKN) + return; + + do { + if (vector_active(prevnode->from) != 1) + return; + + prevnode = vector_slot(prevnode->from, 0); + prevtoken = prevnode->data; + } while (prevtoken->type == FORK_TKN); + + if (prevtoken->type != WORD_TKN) + return; + + if (token->type == FORK_TKN) + cmd_token_varname_fork(node, prevtoken); + else + cmd_token_varname_do(token, prevtoken->text, VARNAME_TEXT); +} + static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to) { for (size_t i = 0; i < vector_active(from->to); i++) @@ -357,72 +432,6 @@ void cmd_graph_merge(struct graph *old, struct graph *new, int direction) vector_slot(new->nodes, 0), direction); } -static void cmd_node_names(struct graph_node *gn, struct graph_node *join, - const char *prevname) -{ - size_t i; - struct cmd_token *tok = gn->data, *jointok; - struct graph_node *stop = cmd_loopstop(gn); - - switch (tok->type) { - case WORD_TKN: - prevname = tok->text; - break; - - case VARIABLE_TKN: - if (!tok->varname && strcmp(tok->text, "WORD") - && strcmp(tok->text, "NAME")) - cmd_token_varname_set(tok, tok->text); - /* fallthrough */ - case RANGE_TKN: - case IPV4_TKN: - case IPV4_PREFIX_TKN: - case IPV6_TKN: - case IPV6_PREFIX_TKN: - case MAC_TKN: - case MAC_PREFIX_TKN: - if (!tok->varname && prevname) - cmd_token_varname_set(tok, prevname); - prevname = NULL; - break; - - case START_TKN: - case JOIN_TKN: - case NEG_ONLY_TKN: - /* "<foo|bar> WORD" -> word is not "bar" or "foo" */ - prevname = NULL; - break; - - case FORK_TKN: - /* apply "<A.B.C.D|X:X::X:X>$name" */ - jointok = tok->forkjoin->data; - if (!jointok->varname) - break; - for (i = 0; i < vector_active(tok->forkjoin->from); i++) { - struct graph_node *tail = - vector_slot(tok->forkjoin->from, i); - struct cmd_token *tailtok = tail->data; - if (tail == gn || tailtok->varname) - continue; - cmd_token_varname_set(tailtok, jointok->varname); - } - break; - - case END_TKN: - return; - } - - for (i = 0; i < vector_active(gn->to); i++) { - struct graph_node *next = vector_slot(gn->to, i); - if (next == stop || next == join) - continue; - cmd_node_names(next, join, prevname); - } - - if (tok->type == FORK_TKN && tok->forkjoin != join) - cmd_node_names(tok->forkjoin, join, NULL); -} - void cmd_graph_names(struct graph *graph) { struct graph_node *start; @@ -451,12 +460,10 @@ void cmd_graph_names(struct graph *graph) struct cmd_token *tok1 = next1->data; /* the other one needs to be "no" (only one will match here) */ if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) - cmd_token_varname_set(tok0, "no"); + cmd_token_varname_do(tok0, "no", VARNAME_AUTO); if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) - cmd_token_varname_set(tok1, "no"); + cmd_token_varname_do(tok1, "no", VARNAME_AUTO); } while (0); - - cmd_node_names(start, NULL, NULL); } #ifndef BUILDING_CLIPPY diff --git a/lib/command_graph.h b/lib/command_graph.h index c20c9874c2..ed4da6aa4c 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -79,11 +79,20 @@ enum { CMD_ATTR_NORMAL, CMD_ATTR_YANG, }; -/* Comamand token struct. */ +enum varname_src { + VARNAME_NONE = 0, + VARNAME_AUTO, + VARNAME_VAR, + VARNAME_TEXT, + VARNAME_EXPLICIT, +}; + +/* 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? + uint8_t varname_src; uint32_t refcnt; char *text; // token text @@ -119,6 +128,8 @@ extern struct cmd_token *cmd_token_new(enum cmd_token_type, uint8_t attr, extern struct cmd_token *cmd_token_dup(struct cmd_token *); extern void cmd_token_del(struct cmd_token *); extern void cmd_token_varname_set(struct cmd_token *token, const char *varname); +extern void cmd_token_varname_seqappend(struct graph_node *n); +extern void cmd_token_varname_join(struct graph_node *n, const char *varname); extern void cmd_graph_parse(struct graph *graph, const struct cmd_element *cmd); extern void cmd_graph_names(struct graph *graph); 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..35c119691b 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -217,10 +217,12 @@ cmd_token: { if ((ctx->currnode = graph_add_edge (ctx->currnode, $1)) != $1) graph_delete_node (ctx->graph, $1); + cmd_token_varname_seqappend($1); } | selector { graph_add_edge (ctx->currnode, $1.start); + cmd_token_varname_seqappend($1.start); ctx->currnode = $1.end; } ; @@ -295,9 +297,8 @@ placeholder_token_real: placeholder_token: placeholder_token_real varname_token { - struct cmd_token *token = $$->data; $$ = $1; - cmd_token_varname_set (token, $2); + cmd_token_varname_set ($$->data, $2); XFREE (MTYPE_LEX, $2); }; @@ -306,7 +307,7 @@ placeholder_token: selector: '<' selector_seq_seq '>' varname_token { $$ = $2; - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -338,11 +339,11 @@ 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, &$$); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -359,6 +360,7 @@ selector_token_seq: selector_token_seq selector_token { graph_add_edge ($1.end, $2.start); + cmd_token_varname_seqappend($2.start); $$.start = $1.start; $$.end = $2.end; } @@ -370,7 +372,7 @@ selector: '[' selector_seq_seq ']' varname_token { $$ = $2; graph_add_edge ($$.start, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; @@ -383,7 +385,7 @@ selector: EXCL_BRACKET selector_seq_seq ']' varname_token $$ = $2; graph_add_edge ($$.start, neg_only); graph_add_edge (neg_only, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; @@ -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/grammar_sandbox.c b/lib/grammar_sandbox.c index 209765bd6f..f9778c5d4c 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -395,6 +395,7 @@ DEFUN (grammar_findambig, vector_slot(cmdvec, scannode++); if (!cnode) continue; + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; if (!nodegraph) continue; @@ -466,6 +467,7 @@ DEFUN (grammar_access, } vty_out(vty, "node %d\n", (int)cnode->node); + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; return CMD_SUCCESS; } 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) \ @@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected"); DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label"); DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters"); +static void if_set_name(struct interface *ifp, const char *name); static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); @@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg) } /* Create new interface structure. */ -static struct interface *if_new(vrf_id_t vrf_id) +static struct interface *if_new(struct vrf *vrf) { struct interface *ifp; + assert(vrf); + ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); ifp->ifindex = IFINDEX_INTERNAL; ifp->name[0] = '\0'; - ifp->vrf_id = vrf_id; + ifp->vrf = vrf; + ifp->vrf_id = vrf->vrf_id; ifp->connected = list_new(); ifp->connected->del = ifp_connected_free; @@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp) (*ifp_master.down_hook)(ifp); } -struct interface *if_create_name(const char *name, vrf_id_t vrf_id) +static struct interface *if_create_name(const char *name, struct vrf *vrf) { struct interface *ifp; - ifp = if_new(vrf_id); + ifp = if_new(vrf); if_set_name(ifp, name); @@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id) return ifp; } -struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - ifp = if_new(vrf_id); - - if_set_index(ifp, ifindex); - - hook_call(if_add, ifp); - return ifp; -} - /* Create new interface structure. */ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { struct vrf *old_vrf, *vrf; /* remove interface from old master vrf list */ - old_vrf = vrf_lookup_by_id(ifp->vrf_id); - if (old_vrf) { - if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(old_vrf, ifp); + old_vrf = ifp->vrf; - if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(old_vrf, ifp); - } + if (ifp->name[0] != '\0') + IFNAME_RB_REMOVE(old_vrf, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(old_vrf, ifp); ifp->vrf_id = vrf_id; vrf = vrf_get(ifp->vrf_id, NULL); + ifp->vrf = vrf; if (ifp->name[0] != '\0') IFNAME_RB_INSERT(vrf, ifp); @@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) * the interface and readding it in the new VRF, which would have * several implications. */ - if (yang_module_find("frr-interface")) { + if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) { struct lyd_node *if_dnode; char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; @@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp) void if_delete(struct interface **ifp) { struct interface *ptr = *ifp; - struct vrf *vrf; - - vrf = vrf_lookup_by_id(ptr->vrf_id); - assert(vrf); + struct vrf *vrf = ptr->vrf; IFNAME_RB_REMOVE(vrf, ptr); if (ptr->ifindex != IFINDEX_INTERNAL) IFINDEX_RB_REMOVE(vrf, ptr); + if (!vrf_is_enabled(vrf)) + vrf_delete(vrf); + if_delete_retain(ptr); list_delete(&ptr->connected); @@ -341,7 +333,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 +346,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 +398,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); @@ -439,8 +431,8 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) return NULL; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_name(name, vrf->vrf_id); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) return ifp; } @@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, /* Get interface by name if given name interface doesn't exist create one. */ -struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, + const char *vrf_name) { - struct interface *ifp; + struct interface *ifp = NULL; + struct vrf *vrf; switch (vrf_get_backend()) { case VRF_BACKEND_UNKNOWN: case VRF_BACKEND_NETNS: - ifp = if_lookup_by_name(name, vrf_id); - if (ifp) - return ifp; - return if_create_name(name, vrf_id); - case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_name_all_vrf(name); + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_name(name, vrf_id); - } - - return NULL; -} -struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - switch (vrf_get_backend()) { - case VRF_BACKEND_UNKNOWN: - case VRF_BACKEND_NETNS: - ifp = if_lookup_by_ifindex(ifindex, vrf_id); - if (ifp) - return ifp; - return if_create_ifindex(ifindex, vrf_id); + break; case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_index_all_vrf(ifindex); + ifp = if_lookup_by_name_all_vrf(name); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_ifindex(ifindex, vrf_id); + + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + break; + default: + return NULL; } - return NULL; + return if_create_name(name, vrf); } int if_set_index(struct interface *ifp, ifindex_t ifindex) { - struct vrf *vrf; - if (ifp->ifindex == ifindex) return 0; - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - /* * If there is already an interface with this ifindex, we will collide * on insertion, so don't even try. @@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) return -1; if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(vrf, ifp); + IFINDEX_RB_REMOVE(ifp->vrf, ifp); ifp->ifindex = ifindex; @@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) * already an interface with the desired ifindex at the top of * the function. Nevertheless. */ - if (IFINDEX_RB_INSERT(vrf, ifp)) + if (IFINDEX_RB_INSERT(ifp->vrf, ifp)) return -1; } return 0; } -void if_set_name(struct interface *ifp, const char *name) +static void if_set_name(struct interface *ifp, const char *name) { - struct vrf *vrf; - - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - if (if_cmp_name_func(ifp->name, name) == 0) return; if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(vrf, ifp); + IFNAME_RB_REMOVE(ifp->vrf, ifp); strlcpy(ifp->name, name, sizeof(ifp->name)); if (ifp->name[0] != '\0') - IFNAME_RB_INSERT(vrf, ifp); + IFNAME_RB_INSERT(ifp->vrf, ifp); } /* Does interface up ? */ @@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp) struct listnode *node; struct connected *c __attribute__((unused)); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) { - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) zlog_info( "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s", - ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex, + ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); - } } /* Interface printing for all interface. */ @@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str) { struct prefix *p; struct interface *ifp; - struct vrf *vrf; char logbuf[BUFSIZ]; char buf[BUFSIZ]; ifp = connected->ifp; p = connected->address; - vrf = vrf_lookup_by_id(ifp->vrf_id); snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ", - str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, + str, ifp->name, ifp->vrf->name, ifp->vrf_id, prefix_family_str(p), p); p = connected->destination; @@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp) void if_terminate(struct vrf *vrf) { struct interface *ifp; - bool delete; - - /* - * If the default VRF is being terminated or has - * already been terminated it means that - * the program is shutting down and we need to - * delete all the interfaces. Otherwise, we only - * need to move VRF's interfaces to the default VRF. - */ - delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT - || !vrf_lookup_by_id(VRF_DEFAULT); while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) { ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name); - if (delete) { - if (ifp->node) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - } - if_delete(&ifp); - } else { - if_update_to_new_vrf(ifp, VRF_DEFAULT); + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); } + if_delete(&ifp); } } @@ -1108,6 +1061,8 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); llts(ZEBRA_LLT_SLIP6, "SLIPv6"); llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_RSRVD, "Reserved"); + llts(ZEBRA_LLT_ADAPT, "Adapt"); llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); llts(ZEBRA_LLT_X25, "CCITT X.25"); llts(ZEBRA_LLT_PPP, "PPP"); @@ -1124,8 +1079,10 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_IP6GRE, "GRE over IPv6"); llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_ECONET, "Acorn Econet"); llts(ZEBRA_LLT_IRDA, "IrDA"); llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); @@ -1136,9 +1093,6 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); - default: - flog_err(EC_LIB_DEVELOPMENT, "Unknown value %d", llt); - return "Unknown type!"; #undef llts } return NULL; @@ -1185,6 +1139,25 @@ void if_link_params_free(struct interface *ifp) /* ----------- CLI commands ----------- */ +/* Guess the VRF of an interface. */ +static int vrfname_by_ifname(const char *ifname, const char **vrfname) +{ + struct vrf *vrf; + struct interface *ifp; + int count = 0; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (strmatch(ifp->name, ifname)) { + *vrfname = vrf->name; + count++; + } + } + } + + return count; +} + /* * XPath: /frr-interface:lib/interface */ @@ -1196,12 +1169,9 @@ DEFPY_YANG_NOSH (interface, VRF_CMD_HELP_STR) { char xpath_list[XPATH_MAXLEN]; - vrf_id_t vrf_id; struct interface *ifp; - int ret; - - if (!vrf_name) - vrf_name = VRF_DEFAULT_NAME; + struct vrf *vrf; + int ret, count; /* * This command requires special handling to maintain backward @@ -1210,30 +1180,30 @@ DEFPY_YANG_NOSH (interface, * interface is found, then a new one should be created on the default * VRF. */ - VRF_GET_ID(vrf_id, vrf_name, false); - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf_id) { - struct vrf *vrf; - + if (vrf_is_backend_netns()) { /* - * Special case 1: a VRF name was specified, but the found - * interface is associated to different VRF. Reject the command. + * For backward compatibility, if the VRF name is not specified + * and there is exactly one interface with this name in the + * system, use its VRF. Otherwise fallback to the default VRF. */ - if (vrf_id != VRF_DEFAULT) { - vty_out(vty, "%% interface %s not in %s vrf\n", ifname, - vrf_name); - return CMD_WARNING_CONFIG_FAILED; + if (!vrf_name) { + count = vrfname_by_ifname(ifname, &vrf_name); + if (count != 1) + vrf_name = VRF_DEFAULT_NAME; } - + } else { /* - * Special case 2: a VRF name was *not* specified, and the found - * interface is associated to a VRF other than the default one. - * Update vrf_id and vrf_name to account for that. + * If the interface already exists, use its VRF regardless of + * what user specified. We can't have same interface name in + * different VRFs with VRF-lite backend. */ - vrf = vrf_lookup_by_id(ifp->vrf_id); - assert(vrf); - vrf_id = ifp->vrf_id; - vrf_name = vrf->name; + ifp = if_lookup_by_name_all_vrf(ifname); + if (ifp) { + vrf_name = ifp->vrf->name; + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + } } snprintf(xpath_list, sizeof(xpath_list), @@ -1251,7 +1221,15 @@ DEFPY_YANG_NOSH (interface, * all interface-level commands are converted to the new * northbound model. */ - ifp = if_lookup_by_name(ifname, vrf_id); + if (vrf_is_backend_netns()) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + ifp = if_lookup_by_name_vrf(ifname, vrf); + else + ifp = NULL; + } else { + ifp = if_lookup_by_name_all_vrf(ifname); + } if (ifp) VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); } @@ -1396,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args) { const char *ifname; const char *vrfname; - struct vrf *vrf; struct interface *ifp; ifname = yang_dnode_get_string(args->dnode, "./name"); @@ -1404,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: - vrf = vrf_lookup_by_name(vrfname); - if (!vrf) { - zlog_warn("%s: VRF %s doesn't exist", __func__, - vrfname); - return NB_ERR_VALIDATION; - } - if (vrf->vrf_id == VRF_UNKNOWN) { - zlog_warn("%s: VRF %s is not active", __func__, - vrf->name); - return NB_ERR_VALIDATION; - } - - /* if VRF is netns or not yet known - init for instance - * then assumption is that passed config is exact - * then the user intent was not to use an other iface - */ - if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) { - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf->vrf_id) { - zlog_warn( - "%s: interface %s already exists in another VRF", - __func__, ifp->name); - return NB_ERR_VALIDATION; - } - } - break; case NB_EV_PREPARE: case NB_EV_ABORT: break; case NB_EV_APPLY: - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_get_by_name(ifname, vrf->vrf_id); + ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname); ifp->configured = true; nb_running_set_entry(args->dnode, ifp); @@ -1487,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args) assert(vrf); pif = RB_MIN(if_name_head, &vrf->ifaces_by_name); } else { - vrf = vrf_lookup_by_id(pif->vrf_id); + vrf = pif->vrf; pif = RB_NEXT(if_name_head, pif); /* if no more interfaces, switch to next vrf */ while (pif == NULL) { @@ -1505,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args) { const struct interface *ifp = args->list_entry; - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - - assert(vrf); - args->keys->num = 2; strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0])); - strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1])); + strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1])); return NB_OK; } @@ -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; @@ -293,6 +293,8 @@ struct interface { #endif /* HAVE_NET_RT_IFLIST */ struct route_node *node; + + struct vrf *vrf; vrf_id_t vrf_id; /* @@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2); */ extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); -/* Create new interface, adds to name list only */ -extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id); - -/* Create new interface, adds to index list only */ -extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id); @@ -532,13 +529,11 @@ struct vrf; extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id, + const char *vrf_name); /* Sets the index and adds to index list */ extern int if_set_index(struct interface *ifp, ifindex_t ifindex); -/* Sets the name and adds to name list */ -extern void if_set_name(struct interface *ifp, const char *name); /* Delete the interface, but do not free the structure, and leave it in the interface list. It is often advisable to leave the pseudo interface 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/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/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/network.h b/lib/network.h index 4a9666984f..10ed917572 100644 --- a/lib/network.h +++ b/lib/network.h @@ -22,6 +22,13 @@ #ifndef _ZEBRA_NETWORK_H #define _ZEBRA_NETWORK_H +#ifdef HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#endif + #ifdef __cplusplus extern "C" { #endif @@ -45,6 +52,35 @@ extern int set_cloexec(int fd); extern float htonf(float); extern float ntohf(float); +/* force type for be64toh/htobe64 to be uint64_t, *without* a direct cast + * + * this is a workaround for false-positive printfrr warnings from FRR's + * frr-format GCC plugin that would be triggered from + * { printfrr("%"PRIu64, (uint64_t)be64toh(...)); } + * + * the key element here is that "(uint64_t)expr" causes the warning, while + * "({ uint64_t x = expr; x; })" does not. (The cast is the trigger, a + * variable of the same type works correctly.) + */ + +/* zap system definitions... */ +#ifdef be64toh +#undef be64toh +#endif +#ifdef htobe64 +#undef htobe64 +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define be64toh(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#define htobe64(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#elif BYTE_ORDER == BIG_ENDIAN +#define be64toh(x) ({ uint64_t r = (x); r; }) +#define htobe64(x) ({ uint64_t r = (x); r; }) +#else +#error nobody expects the endianish inquisition. check OS endian.h headers. +#endif + /** * Helper function that returns a random long value. The main purpose of * this function is to hide a `random()` call that gets flagged by coverity 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/sockopt.c b/lib/sockopt.c index 150736e00c..45f3c23330 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -122,7 +122,7 @@ int setsockopt_ipv6_pktinfo(int sock, int val) if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_PKTINFO : %s", safe_strerror(errno)); -#endif /* INIA_IPV6 */ +#endif /* IANA_IPV6 */ return ret; } @@ -595,7 +595,7 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen, /* If this does not work, then all users of this sockopt will * need to - * differentiate between IPv4 and IPv6, and keep seperate + * differentiate between IPv4 and IPv6, and keep separate * sockets for * each. * diff --git a/lib/table.c b/lib/table.c index e6030ca4ca..523183bef2 100644 --- a/lib/table.c +++ b/lib/table.c @@ -393,7 +393,7 @@ void route_node_delete(struct route_node *node) route_node_delete(parent); } -/* Get fist node and lock it. This function is useful when one want +/* Get first node and lock it. This function is useful when one wants to lookup all the node exist in the routing table. */ struct route_node *route_top(struct route_table *table) { diff --git a/lib/thread.c b/lib/thread.c index 835aa38115..5dbba6363d 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -922,10 +922,10 @@ done: } /* Add new read thread. */ -struct thread *_thread_add_read_write(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int fd, struct thread **t_ptr) +void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, int fd, + struct thread **t_ptr) { int dir = xref->thread_type; struct thread *thread = NULL; @@ -1000,15 +1000,13 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } -static struct thread * -_thread_add_timer_timeval(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), - void *arg, struct timeval *time_relative, - struct thread **t_ptr) +static void _thread_add_timer_timeval(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, + struct timeval *time_relative, + struct thread **t_ptr) { struct thread *thread; struct timeval t; @@ -1028,7 +1026,7 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) /* thread is already scheduled; don't reschedule */ - return NULL; + return; thread = thread_get(m, THREAD_TIMER, func, arg, xref); @@ -1048,16 +1046,13 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, if (thread_timer_list_first(&m->timer) == thread) AWAKEN(m); } - - return thread; } /* Add timer event thread. */ -struct thread *_thread_add_timer(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, struct thread **t_ptr) +void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, long timer, struct thread **t_ptr) { struct timeval trel; @@ -1066,15 +1061,14 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref, trel.tv_sec = timer; trel.tv_usec = 0; - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "millisecond" resolution */ -struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, - struct thread **t_ptr) +void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, long timer, + struct thread **t_ptr) { struct timeval trel; @@ -1083,24 +1077,21 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, trel.tv_sec = timer / 1000; trel.tv_usec = 1000 * (timer % 1000); - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "timeval" resolution */ -struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, struct timeval *tv, - struct thread **t_ptr) +void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, struct timeval *tv, struct thread **t_ptr) { - return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); } /* Add simple event thread. */ -struct thread *_thread_add_event(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int val, struct thread **t_ptr) +void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, int val, struct thread **t_ptr) { struct thread *thread = NULL; @@ -1128,8 +1119,6 @@ struct thread *_thread_add_event(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } /* Thread cancellation ------------------------------------------------------ */ @@ -2059,3 +2048,11 @@ void debug_signals(const sigset_t *sigs) zlog_debug("%s: %s", __func__, buf); } + +bool thread_is_scheduled(struct thread *thread) +{ + if (thread == NULL) + return false; + + return true; +} diff --git a/lib/thread.h b/lib/thread.h index abd94ff4f0..39f21da11d 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -219,26 +219,30 @@ void thread_master_set_name(struct thread_master *master, const char *name); extern void thread_master_free(struct thread_master *); extern void thread_master_free_unused(struct thread_master *); -extern struct thread *_thread_add_read_write( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int fd, struct thread **tref); - -extern struct thread *_thread_add_timer( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_msec( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_tv( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, struct timeval *tv, - struct thread **tref); - -extern struct thread *_thread_add_event( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int val, struct thread **tref); +extern void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + int fd, struct thread **tref); + +extern void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, long t, + struct thread **tref); + +extern void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + long t, struct thread **tref); + +extern void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + struct timeval *tv, struct thread **tref); + +extern void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, int val, + struct thread **tref); extern void _thread_execute(const struct xref_threadsched *xref, struct thread_master *master, @@ -273,6 +277,7 @@ extern pthread_key_t thread_current; extern char *thread_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer); +extern bool thread_is_scheduled(struct thread *thread); /* Debug signal mask */ void debug_signals(const sigset_t *sigs); diff --git a/lib/typerb.c b/lib/typerb.c index 092faa4cc9..e1346df191 100644 --- a/lib/typerb.c +++ b/lib/typerb.c @@ -45,6 +45,7 @@ #include "config.h" #endif +#include <string.h> #include "typerb.h" #define RB_BLACK 0 @@ -330,6 +331,7 @@ color: rbe_remove_color(rbt, parent, child); rbt->count--; + memset(old, 0, sizeof(*old)); return (old); } @@ -478,3 +480,11 @@ struct rb_entry *typed_rb_min(const struct rbt_tree *rbt) return parent; } + +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe) +{ + while (rbe->rbt_parent) + rbe = rbe->rbt_parent; + return rbe == rbt->rbt_root; +} diff --git a/lib/typerb.h b/lib/typerb.h index cbed8d4893..d22d864aae 100644 --- a/lib/typerb.h +++ b/lib/typerb.h @@ -62,6 +62,8 @@ const struct typed_rb_entry *typed_rb_find_lt(const struct typed_rb_root *rbt, const struct typed_rb_entry *b)); struct typed_rb_entry *typed_rb_min(const struct typed_rb_root *rbt); struct typed_rb_entry *typed_rb_next(const struct typed_rb_entry *rbe); +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe); #define _PREDECL_RBTREE(prefix) \ struct prefix ## _head { struct typed_rb_root rr; }; \ @@ -142,6 +144,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->rr.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typed_rb_member(&h->rr, &item->field.re); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ #define PREDECL_RBTREE_UNIQ(prefix) \ diff --git a/lib/typesafe.c b/lib/typesafe.c index 76705fad0d..f90b59daf0 100644 --- a/lib/typesafe.c +++ b/lib/typesafe.c @@ -29,6 +29,46 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket"); DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow"); DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array"); +struct slist_item typesafe_slist_sentinel = { NULL }; + +bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item) +{ + struct slist_item *fromhead = head->first; + struct slist_item **fromnext = (struct slist_item **)&item->next; + + while (fromhead != _SLIST_LAST) { + if (fromhead == item || fromnext == head->last_next) + return true; + + fromhead = fromhead->next; + if (!*fromnext || *fromnext == _SLIST_LAST) + break; + fromnext = &(*fromnext)->next; + } + + return false; +} + +bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item) +{ + const struct dlist_item *fromhead = head->hitem.next; + const struct dlist_item *fromitem = item->next; + + if (!item->prev || !item->next) + return false; + + while (fromhead != &head->hitem && fromitem != item) { + if (fromitem == &head->hitem || fromhead == item) + return true; + fromhead = fromhead->next; + fromitem = fromitem->next; + } + + return false; +} + #if 0 static void hash_consistency_check(struct thash_head *head) { diff --git a/lib/typesafe.h b/lib/typesafe.h index ecac1a4381..44c42ffbca 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -78,8 +78,34 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ } \ /* ... */ +/* *_member via find - when there is no better membership check than find() */ +#define TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + return item == prefix ## _const_find(h, item); \ +} \ +/* ... */ + +/* *_member via find_gteq - same for non-unique containers */ +#define TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + const type *iter; \ + for (iter = prefix ## _const_find_gteq(h, item); iter; \ + iter = prefix ## _const_next(h, iter)) { \ + if (iter == item) \ + return true; \ + if (cmpfn(iter, item) > 0) \ + break; \ + } \ + return false; \ +} \ +/* ... */ + /* SWAP_ALL_SIMPLE = for containers where the items don't point back to the - * head *AND* the head doesn'T points to itself (= everything except LIST, + * head *AND* the head doesn't point to itself (= everything except LIST, * DLIST and SKIPLIST), just switch out the entire head */ #define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ @@ -106,6 +132,10 @@ struct slist_head { size_t count; }; +/* this replaces NULL as the value for ->next on the last item. */ +extern struct slist_item typesafe_slist_sentinel; +#define _SLIST_LAST &typesafe_slist_sentinel + static inline void typesafe_list_add(struct slist_head *head, struct slist_item **pos, struct slist_item *item) { @@ -116,6 +146,9 @@ static inline void typesafe_list_add(struct slist_head *head, head->count++; } +extern bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item); + /* use as: * * PREDECL_LIST(namelist); @@ -136,6 +169,7 @@ MACRO_REQUIRE_SEMICOLON() /* end */ macro_inline void prefix ## _init(struct prefix##_head *h) \ { \ memset(h, 0, sizeof(*h)); \ + h->sh.first = _SLIST_LAST; \ h->sh.last_next = &h->sh.first; \ } \ macro_inline void prefix ## _fini(struct prefix##_head *h) \ @@ -161,25 +195,27 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct slist_item **iter = &h->sh.first; \ - while (*iter && *iter != &item->field.si) \ + while (*iter != _SLIST_LAST && *iter != &item->field.si) \ iter = &(*iter)->next; \ - if (!*iter) \ + if (*iter == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ - if (!item->field.si.next) \ + if (item->field.si.next == _SLIST_LAST) \ h->sh.last_next = iter; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ struct slist_item *sitem = h->sh.first; \ - if (!sitem) \ + if (sitem == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ h->sh.first = sitem->next; \ - if (h->sh.first == NULL) \ + if (h->sh.first == _SLIST_LAST) \ h->sh.last_next = &h->sh.first; \ + sitem->next = NULL; \ return container_of(sitem, type, field.si); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -195,13 +231,17 @@ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ } \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ - return container_of_null(h->sh.first, type, field.si); \ + if (h->sh.first != _SLIST_LAST) \ + return container_of(h->sh.first, type, field.si); \ + return NULL; \ } \ macro_pure const type *prefix ## _const_next(const struct prefix##_head *h, \ const type *item) \ { \ const struct slist_item *sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ TYPESAFE_FIRST_NEXT(prefix, type) \ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ @@ -210,12 +250,23 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ if (!item) \ return NULL; \ sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + return item->field.si.next != NULL; \ +} \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_list_member(&h->sh, &item->field.si); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* don't use these structs directly */ @@ -267,6 +318,9 @@ static inline void typesafe_dlist_swap_all(struct dlist_head *a, } } +extern bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item); + /* double-linked list, for fast item deletion */ #define PREDECL_DLIST(prefix) \ @@ -321,6 +375,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ ditem->prev->next = ditem->next; \ ditem->next->prev = ditem->prev; \ h->dh.count--; \ + ditem->prev = ditem->next = NULL; \ return container_of(ditem, type, field.di); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -354,6 +409,16 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->dh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + const struct dlist_item *ditem = &item->field.di; \ + return ditem->next && ditem->prev; \ +} \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_dlist_member(&h->dh, &item->field.di); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* note: heap currently caps out at 4G items */ @@ -463,6 +528,14 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t idx = item->field.hi.index; \ + if (idx >= h->hh.count) \ + return false; \ + return h->hh.array[idx] == &item->field.hi; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ extern void typesafe_heap_resize(struct heap_head *head, bool grow); @@ -565,6 +638,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ @@ -618,6 +692,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ MACRO_REQUIRE_SEMICOLON() /* end */ #define DECLARE_SORTLIST_NONUNIQ(prefix, type, field, cmpfn) \ @@ -633,6 +708,7 @@ macro_inline int _ ## prefix ## _cmp(const type *a, const type *b) \ return 0; \ } \ _DECLARE_SORTLIST(prefix, type, field, cmpfn, _ ## prefix ## _cmp); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ @@ -799,6 +875,19 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \ + const struct thash_item *hitem = h->hh.entries[hbits]; \ + while (hitem && hitem->hashval < hval) \ + hitem = hitem->next; \ + for (hitem = h->hh.entries[hbits]; hitem && hitem->hashval <= hval; \ + hitem = hitem->next) \ + if (hitem == &item->field.hi) \ + return true; \ + return false; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* skiplist, sorted. @@ -937,6 +1026,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of_null(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp); \ @@ -968,6 +1058,7 @@ macro_inline int prefix ## __cmp_uq(const struct sskip_item *a, \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp_uq); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ diff --git a/lib/vector.c b/lib/vector.c index 565c49fd59..38f9b1b85f 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -37,6 +37,7 @@ vector vector_init(unsigned int size) v->alloced = size; v->active = 0; + v->count = 0; v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size); return v; } @@ -54,6 +55,7 @@ vector vector_copy(vector v) new->active = v->active; new->alloced = v->alloced; + new->count = v->count; size = sizeof(void *) * (v->alloced); new->index = XCALLOC(MTYPE_VECTOR_INDEX, size); @@ -84,6 +86,9 @@ int vector_empty_slot(vector v) { unsigned int i; + if (v->active == v->count) + return v->active; + if (v->active == 0) return 0; @@ -102,6 +107,10 @@ int vector_set(vector v, void *val) i = vector_empty_slot(v); vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -115,6 +124,10 @@ int vector_set_index(vector v, unsigned int i, void *val) { vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -123,6 +136,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) { @@ -144,6 +168,9 @@ void vector_unset(vector v, unsigned int i) if (i >= v->alloced) return; + if (v->index[i]) + v->count--; + v->index[i] = NULL; if (i + 1 == v->active) { @@ -158,6 +185,9 @@ void vector_remove(vector v, unsigned int ix) if (ix >= v->active) return; + if (v->index[ix]) + v->count--; + int n = (--v->active) - ix; memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *)); @@ -181,6 +211,7 @@ void vector_unset_value(vector v, void *val) for (i = 0; i < v->active; i++) if (v->index[i] == val) { v->index[i] = NULL; + v->count--; break; } @@ -190,19 +221,6 @@ void vector_unset_value(vector v, void *val) while (i && v->index[--i] == NULL); } -/* Count the number of not emplty slot. */ -unsigned int vector_count(vector v) -{ - unsigned int i; - unsigned count = 0; - - for (i = 0; i < v->active; i++) - if (v->index[i] != NULL) - count++; - - return count; -} - void vector_to_array(vector v, void ***dest, int *argc) { *dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active); diff --git a/lib/vector.h b/lib/vector.h index d5857eb599..6208be1cc7 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -32,6 +32,7 @@ extern "C" { struct _vector { unsigned int active; /* number of active slots */ unsigned int alloced; /* number of allocated slot */ + unsigned int count; void **index; /* index to data */ }; typedef struct _vector *vector; @@ -54,12 +55,17 @@ 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); extern void vector_compact(vector v); -extern unsigned int vector_count(vector v); +static inline unsigned int vector_count(vector v) +{ + return v->count; +} + extern void vector_free(vector v); extern vector vector_copy(vector v); @@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf) if (vrf_is_enabled(vrf)) vrf_disable(vrf); + if (vrf->vrf_id != VRF_UNKNOWN) { + RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); + vrf->vrf_id = VRF_UNKNOWN; + } + /* If the VRF is user configured, it'll stick around, just remove * the ID mapping. Interfaces assigned to this VRF should've been * removed already as part of the VRF going down. */ if (vrf_is_user_cfged(vrf)) { - if (vrf->vrf_id != VRF_UNKNOWN) { - /* Delete any VRF interfaces - should be only - * the VRF itself, other interfaces should've - * been moved out of the VRF. - */ - if_terminate(vrf); - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); - vrf->vrf_id = VRF_UNKNOWN; - } vrf->ns_ctxt = NULL; return; } + /* Do not delete the VRF if it has interfaces configured in it. */ + if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) + return; + if (vrf_master.vrf_delete_hook) (*vrf_master.vrf_delete_hook)(vrf); QOBJ_UNREG(vrf); - if_terminate(vrf); - if (vrf->vrf_id != VRF_UNKNOWN) - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); if (vrf->name[0] != '\0') RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); @@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf) { /* Clear configured flag and invoke delete. */ UNSET_FLAG(vrf->status, VRF_CONFIGURED); + if_terminate(vrf); vrf_delete(vrf); } @@ -776,7 +776,7 @@ static void vty_end_config(struct vty *vty) vty->cp = 0; } -/* Delete a charcter at the current point. */ +/* Delete a character at the current point. */ static void vty_delete_char(struct vty *vty) { int i; @@ -2282,7 +2282,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp) vty = vty_new(); /* vty_close won't close stderr; if some config command prints - * something it'll end up there. (not ideal; it'd be beter if output + * something it'll end up there. (not ideal; it'd be better if output * from a file-load went to logging instead. Also note that if this * function is called after daemonizing, stderr will be /dev/null.) * @@ -2697,19 +2697,21 @@ static struct thread_master *vty_master; static void vty_event_serv(enum event event, int sock) { - struct thread *vty_serv_thread = NULL; + struct thread **vty_serv_thread_ptr = NULL; switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read(vty_master, vty_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vty_accept, NULL, sock, + vty_serv_thread_ptr); break; #ifdef VTYSH case VTYSH_SERV: - vty_serv_thread = thread_add_read(vty_master, vtysh_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vtysh_accept, NULL, sock, + vty_serv_thread_ptr); break; #endif /* VTYSH */ default: @@ -3165,7 +3167,7 @@ void vty_init(struct thread_master *master_thread, bool do_command_logging) atexit(vty_stdio_atexit); - /* Initilize server thread vector. */ + /* Initialize server thread vector. */ Vvty_serv_thread = vector_init(VECTOR_MIN_SIZE); /* Install bgp top node. */ diff --git a/lib/vxlan.h b/lib/vxlan.h index 62963a6097..220fd8d232 100644 --- a/lib/vxlan.h +++ b/lib/vxlan.h @@ -26,7 +26,7 @@ extern "C" { #endif -/* EVPN MH DF election alogorithm */ +/* EVPN MH DF election algorithm */ #define EVPN_MH_DF_ALG_SERVICE_CARVING 0 #define EVPN_MH_DF_ALG_HRW 1 #define EVPN_MH_DF_ALG_PREF 2 diff --git a/lib/yang.h b/lib/yang.h index d4517f969a..d625b24f6a 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -183,7 +183,7 @@ extern int yang_snodes_iterate_subtree(const struct lysc_node *snode, void *arg); /* - * Iterate over all libyang schema nodes from all loeaded modules of from the + * Iterate over all libyang schema nodes from all loaded modules of the * given YANG module. * * module diff --git a/lib/zclient.c b/lib/zclient.c index dde60a6c90..90439d5e17 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) { @@ -2096,7 +2099,7 @@ stream_failure: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Harware Address Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hardware Address if HW lenght different from 0 | + * | Hardware Address if HW length different from 0 | * | ... max INTERFACE_HWADDR_MAX | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Link_params? | Whether a link-params follows: 1 or 0. @@ -2161,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id) struct interface *ifp; char ifname_tmp[INTERFACE_NAMSIZ + 1] = {}; struct stream *s = zclient->ibuf; + struct vrf *vrf; /* Read interface name. */ STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - if (!vrf_get(vrf_id, NULL)) { + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) { zlog_debug( "Rx'd interface add from Zebra, but VRF %u does not exist", vrf_id); return -1; } - ifp = if_get_by_name(ifname_tmp, vrf_id); + ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name); zebra_interface_if_set_value(s, ifp); @@ -2435,7 +2440,7 @@ size_t zebra_interface_link_params_write(struct stream *s, } /* - * format of message for address additon is: + * format of message for address addition is: * 0 * 0 1 2 3 4 5 6 7 * +-+-+-+-+-+-+-+-+ @@ -2700,9 +2705,9 @@ static int zclient_read_sync_response(struct zclient *zclient, return 0; } /** - * Connect to label manager in a syncronous way + * Connect to label manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -2795,7 +2800,7 @@ stream_failure: } /** - * Function to request a srv6-locator chunk in an Asyncronous way + * Function to request a srv6-locator chunk in an asynchronous way * * @param zclient Zclient used to connect to table manager (zebra) * @param locator_name Name of SRv6-locator @@ -2905,9 +2910,9 @@ enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, } /** - * Function to request a label chunk in a syncronous way + * Function to request a label chunk in a synchronous way * - * It first writes the request to zlcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -3082,9 +3087,9 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start, } /** - * Connect to table manager in a syncronous way + * Connect to table manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to table manager (zebra) @@ -3141,7 +3146,7 @@ stream_failure: } /** - * Function to request a table chunk in a syncronous way + * Function to request a table chunk in a synchronous way * * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. @@ -4016,13 +4021,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..3cad9bd4fa 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, @@ -292,7 +289,7 @@ struct zclient { /* The thread master we schedule ourselves on */ struct thread_master *master; - /* Priviledges to change socket values */ + /* Privileges to change socket values */ struct zebra_privs_t *privs; /* Do we care about failure events for route install? */ @@ -332,7 +329,7 @@ struct zclient { struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - /* Redistribute defauilt. */ + /* Redistribute default. */ vrf_bitmap_t default_information[AFI_MAX]; #define ZAPI_CALLBACK_ARGS \ @@ -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/list.h b/nhrpd/list.h deleted file mode 100644 index a43687ac08..0000000000 --- a/nhrpd/list.h +++ /dev/null @@ -1,209 +0,0 @@ -/* Linux kernel style list handling function - * - * Written from scratch by Timo Teräs <timo.teras@iki.fi>, but modeled - * after the linux kernel code. - * - * This file is free software: you may copy, redistribute 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. - */ - -#ifndef LIST_H -#define LIST_H - -#ifndef NULL -#define NULL 0L -#endif - -#ifndef offsetof -#ifdef __compiler_offsetof -#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) -#else -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif -#endif - -#ifndef container_of -#define container_of(ptr, type, member) \ - ({ \ - const typeof(((type *)0)->member) *__mptr = (ptr); \ - (type *)((char *)__mptr - offsetof(type, member)); \ - }) -#endif - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next; - struct hlist_node **pprev; -}; - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline int hlist_hashed(const struct hlist_node *n) -{ - return n->pprev != NULL; -} - -static inline void hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - - *pprev = next; - if (next) - next->pprev = pprev; - - n->next = NULL; - n->pprev = NULL; -} - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - - n->next = first; - if (first) - first->pprev = &n->next; - n->pprev = &h->first; - h->first = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *prev) -{ - n->next = prev->next; - n->pprev = &prev->next; - prev->next = n; -} - -static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h) -{ - struct hlist_node *n = h->first; - if (n == NULL) - return &h->first; - while (n->next != NULL) - n = n->next; - return &n->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos; pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ \ - n = pos->next; \ - 1; \ - }); \ - pos = n) - -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ \ - tpos = hlist_entry(pos, typeof(*tpos), member); \ - 1; \ - }); \ - pos = pos->next) - -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ \ - n = pos->next; \ - 1; \ - }) \ - && ({ \ - tpos = hlist_entry(pos, typeof(*tpos), member); \ - 1; \ - }); \ - pos = n) - - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_INITIALIZER(l) { .next = &l, .prev = &l } - -static inline void list_init(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -static inline void __list_add(struct list_head *new, struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = NULL; - entry->prev = NULL; -} - -static inline int list_hashed(const struct list_head *n) -{ - return n->next != n && n->next != NULL; -} - -static inline int list_empty(const struct list_head *n) -{ - return !list_hashed(n); -} - -#define list_next(ptr, type, member) \ - (list_hashed(ptr) ? container_of((ptr)->next, type, member) : NULL) - -#define list_entry(ptr, type, member) container_of(ptr,type,member) - -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = ((head)->next != head ? \ - list_entry((head)->next, typeof(*pos), member) : \ - NULL), \ - n = (pos ? \ - list_entry(pos->member.next, typeof(*pos), member) : NULL); \ - pos && (&pos->member != (head)); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -#endif 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_cache.c b/nhrpd/nhrp_cache.c index c358baecb2..3823464a73 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -315,7 +315,7 @@ static void nhrp_cache_peer_notifier(struct notifier_block *n, static void nhrp_cache_reset_new(struct nhrp_cache *c) { THREAD_OFF(c->t_auth); - if (list_hashed(&c->newpeer_notifier.notifier_entry)) + if (notifier_list_anywhere(&c->newpeer_notifier)) nhrp_peer_notify_del(c->new.peer, &c->newpeer_notifier); nhrp_peer_unref(c->new.peer); memset(&c->new, 0, sizeof(c->new)); @@ -574,5 +574,5 @@ void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *n, void nhrp_cache_notify_del(struct nhrp_cache *c, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &c->notifier_list); } 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_interface.c b/nhrpd/nhrp_interface.c index 2db8997bad..94cec0281f 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -79,8 +79,8 @@ static int nhrp_if_new_hook(struct interface *ifp) for (afi = 0; afi < AFI_MAX; afi++) { struct nhrp_afi_data *ad = &nifp->afi[afi]; ad->holdtime = NHRPD_DEFAULT_HOLDTIME; - list_init(&ad->nhslist_head); - list_init(&ad->mcastlist_head); + nhrp_nhslist_init(&ad->nhslist_head); + nhrp_mcastlist_init(&ad->mcastlist_head); } return 0; @@ -224,8 +224,12 @@ void nhrp_interface_update_nbma(struct interface *ifp, nbmanifp = nbmaifp->info; if (nbmaifp != nifp->nbmaifp) { - if (nifp->nbmaifp) - notifier_del(&nifp->nbmanifp_notifier); + if (nifp->nbmaifp) { + struct nhrp_interface *prev_nifp = nifp->nbmaifp->info; + + notifier_del(&nifp->nbmanifp_notifier, + &prev_nifp->notifier_list); + } nifp->nbmaifp = nbmaifp; if (nbmaifp) { notifier_add(&nifp->nbmanifp_notifier, @@ -509,12 +513,15 @@ void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n, notifier_fn_t fn) { struct nhrp_interface *nifp = ifp->info; + notifier_add(n, &nifp->notifier_list, fn); } void nhrp_interface_notify_del(struct interface *ifp, struct notifier_block *n) { - notifier_del(n); + struct nhrp_interface *nifp = ifp->info; + + notifier_del(n, &nifp->notifier_list); } void nhrp_interface_set_protection(struct interface *ifp, const char *profile, diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index 73684046a8..4c98f02e1d 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -55,8 +55,10 @@ struct zebra_privs_t nhrpd_privs = { #endif .caps_p = _caps_p, .cap_num_p = array_size(_caps_p), + .cap_num_i = 0 }; + static void parse_arguments(int argc, char **argv) { int opt; diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c index b78afda2c4..d8372ae8a8 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) { @@ -220,7 +219,9 @@ void netlink_mcast_set_nflog_group(int nlgroup) static int nhrp_multicast_free(struct interface *ifp, struct nhrp_multicast *mcast) { - list_del(&mcast->list_entry); + struct nhrp_interface *nifp = ifp->info; + + nhrp_mcastlist_del(&nifp->afi[mcast->afi].mcastlist_head, mcast); XFREE(MTYPE_NHRP_MULTICAST, mcast); return 0; } @@ -231,8 +232,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi, struct nhrp_interface *nifp = ifp->info; struct nhrp_multicast *mcast; - list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { if (sockunion_same(&mcast->nbma_addr, nbma_addr)) return NHRP_ERR_ENTRY_EXISTS; } @@ -242,7 +242,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi, *mcast = (struct nhrp_multicast){ .afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr, }; - list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head); + nhrp_mcastlist_add_tail(&nifp->afi[afi].mcastlist_head, mcast); debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr); @@ -253,11 +253,9 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi, union sockunion *nbma_addr) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_multicast *mcast, *tmp; + struct nhrp_multicast *mcast; - list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head, - list_entry) - { + frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { if (!sockunion_same(&mcast->nbma_addr, nbma_addr)) continue; @@ -275,17 +273,15 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi, void nhrp_multicast_interface_del(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_multicast *mcast, *tmp; + struct nhrp_multicast *mcast; afi_t afi; for (afi = 0; afi < AFI_MAX; afi++) { - debugf(NHRP_DEBUG_COMMON, - "Cleaning up multicast entries (%d)", - !list_empty(&nifp->afi[afi].mcastlist_head)); + debugf(NHRP_DEBUG_COMMON, "Cleaning up multicast entries (%zu)", + nhrp_mcastlist_count(&nifp->afi[afi].mcastlist_head)); - list_for_each_entry_safe( - mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, + mcast) { nhrp_multicast_free(ifp, mcast); } } @@ -298,8 +294,7 @@ void nhrp_multicast_foreach(struct interface *ifp, afi_t afi, struct nhrp_interface *nifp = ifp->info; struct nhrp_multicast *mcast; - list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { cb(mcast, ctx); } } diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 9dfaf073d8..597c125e17 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); @@ -256,7 +254,7 @@ static void nhrp_reg_delete(struct nhrp_registration *r) { nhrp_peer_notify_del(r->peer, &r->peer_notifier); nhrp_peer_unref(r->peer); - list_del(&r->reglist_entry); + nhrp_reglist_del(&r->nhs->reglist_head, r); THREAD_OFF(r->t_register); XFREE(MTYPE_NHRP_REGISTRATION, r); } @@ -266,10 +264,9 @@ nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr) { struct nhrp_registration *r; - list_for_each_entry( - r, &nhs->reglist_head, - reglist_entry) if (sockunion_same(&r->peer->vc->remote.nbma, - nbma_addr)) return r; + frr_each (nhrp_reglist, &nhs->reglist_head, r) + if (sockunion_same(&r->peer->vc->remote.nbma, nbma_addr)) + return r; return NULL; } @@ -278,10 +275,9 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, { struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve); struct nhrp_interface *nifp = nhs->ifp->info; - struct nhrp_registration *reg, *regn; + struct nhrp_registration *reg; int i; - nhs->t_resolve = NULL; if (n < 0) { /* Failed, retry in a moment */ thread_add_timer(master, nhrp_nhs_resolve, nhs, 5, @@ -292,8 +288,8 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, thread_add_timer(master, nhrp_nhs_resolve, nhs, 2 * 60 * 60, &nhs->t_resolve); - list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) reg->mark = - 1; + frr_each (nhrp_reglist, &nhs->reglist_head, reg) + reg->mark = 1; nhs->hub = 0; for (i = 0; i < n; i++) { @@ -312,19 +308,16 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, reg->peer = nhrp_peer_get(nhs->ifp, &addrs[i]); reg->nhs = nhs; reg->timeout = 1; - list_init(®->reglist_entry); - list_add_tail(®->reglist_entry, &nhs->reglist_head); + nhrp_reglist_add_tail(&nhs->reglist_head, reg); nhrp_peer_notify_add(reg->peer, ®->peer_notifier, nhrp_reg_peer_notify); thread_add_timer_msec(master, nhrp_reg_send_req, reg, 50, ®->t_register); } - list_for_each_entry_safe(reg, regn, &nhs->reglist_head, reglist_entry) - { + frr_each_safe (nhrp_reglist, &nhs->reglist_head, reg) if (reg->mark) nhrp_reg_delete(reg); - } } static int nhrp_nhs_resolve(struct thread *t) @@ -347,8 +340,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, && sockunion_family(proto_addr) != afi2family(afi)) return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH; - list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) - { + frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC && sockunion_family(proto_addr) != AF_UNSPEC && sockunion_same(&nhs->proto_addr, proto_addr)) @@ -365,9 +357,9 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, .ifp = ifp, .proto_addr = *proto_addr, .nbma_fqdn = strdup(nbma_fqdn), - .reglist_head = LIST_INITIALIZER(nhs->reglist_head), + .reglist_head = INIT_DLIST(nhs->reglist_head), }; - list_add_tail(&nhs->nhslist_entry, &nifp->afi[afi].nhslist_head); + nhrp_nhslist_add_tail(&nifp->afi[afi].nhslist_head, nhs); thread_add_timer_msec(master, nhrp_nhs_resolve, nhs, 1000, &nhs->t_resolve); @@ -378,36 +370,34 @@ int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_nhs *nhs, *nnhs; + struct nhrp_nhs *nhs; int ret = NHRP_ERR_ENTRY_NOT_FOUND; if (sockunion_family(proto_addr) != AF_UNSPEC && sockunion_family(proto_addr) != afi2family(afi)) return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH; - list_for_each_entry_safe(nhs, nnhs, &nifp->afi[afi].nhslist_head, - nhslist_entry) - { + frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { if (!sockunion_same(&nhs->proto_addr, proto_addr)) continue; if (strcmp(nhs->nbma_fqdn, nbma_fqdn) != 0) continue; - nhrp_nhs_free(nhs); + nhrp_nhs_free(nifp, afi, nhs); ret = NHRP_OK; } return ret; } -int nhrp_nhs_free(struct nhrp_nhs *nhs) +int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs) { - struct nhrp_registration *r, *rn; + struct nhrp_registration *r; - list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry) + frr_each_safe (nhrp_reglist, &nhs->reglist_head, r) nhrp_reg_delete(r); THREAD_OFF(nhs->t_resolve); - list_del(&nhs->nhslist_entry); + nhrp_nhslist_del(&nifp->afi[afi].nhslist_head, nhs); free((void *)nhs->nbma_fqdn); XFREE(MTYPE_NHRP_NHS, nhs); return 0; @@ -416,18 +406,15 @@ int nhrp_nhs_free(struct nhrp_nhs *nhs) void nhrp_nhs_interface_del(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_nhs *nhs, *tmp; + struct nhrp_nhs *nhs; afi_t afi; for (afi = 0; afi < AFI_MAX; afi++) { - debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%d)", - !list_empty(&nifp->afi[afi].nhslist_head)); + debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%zu)", + nhrp_nhslist_count(&nifp->afi[afi].nhslist_head)); - list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head, - nhslist_entry) - { - nhrp_nhs_free(nhs); - } + frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) + nhrp_nhs_free(nifp, afi, nhs); } } @@ -436,15 +423,15 @@ void nhrp_nhs_terminate(void) struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp; struct nhrp_interface *nifp; - struct nhrp_nhs *nhs, *tmp; + struct nhrp_nhs *nhs; afi_t afi; FOR_ALL_INTERFACES (vrf, ifp) { nifp = ifp->info; for (afi = 0; afi < AFI_MAX; afi++) { - list_for_each_entry_safe( - nhs, tmp, &nifp->afi[afi].nhslist_head, - nhslist_entry) nhrp_nhs_free(nhs); + frr_each_safe (nhrp_nhslist, + &nifp->afi[afi].nhslist_head, nhs) + nhrp_nhs_free(nifp, afi, nhs); } } } @@ -458,11 +445,10 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, struct nhrp_nhs *nhs; struct nhrp_registration *reg; - list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) - { - if (!list_empty(&nhs->reglist_head)) { - list_for_each_entry(reg, &nhs->reglist_head, - reglist_entry) cb(nhs, reg, ctx); + frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { + if (nhrp_reglist_count(&nhs->reglist_head)) { + frr_each (nhrp_reglist, &nhs->reglist_head, reg) + cb(nhs, reg, ctx); } else cb(nhs, 0, ctx); } @@ -475,19 +461,14 @@ int nhrp_nhs_match_ip(union sockunion *in_ip, struct nhrp_interface *nifp) struct nhrp_registration *reg; for (i = 0; i < AFI_MAX; i++) { - list_for_each_entry(nhs, &nifp->afi[i].nhslist_head, - nhslist_entry) - { - if (!list_empty(&nhs->reglist_head)) { - list_for_each_entry(reg, &nhs->reglist_head, - reglist_entry) - { - if (!sockunion_cmp( - in_ip, - ®->peer->vc->remote - .nbma)) - return 1; - } + frr_each (nhrp_nhslist, &nifp->afi[i].nhslist_head, nhs) { + if (!nhrp_reglist_count(&nhs->reglist_head)) + continue; + + frr_each (nhrp_reglist, &nhs->reglist_head, reg) { + if (!sockunion_cmp(in_ip, + ®->peer->vc->remote.nbma)) + return 1; } } } diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 5a7da703ac..51cae44bd1 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; @@ -360,7 +359,7 @@ void nhrp_peer_notify_add(struct nhrp_peer *p, struct notifier_block *n, void nhrp_peer_notify_del(struct nhrp_peer *p, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &p->notifier_list); nhrp_peer_check_delete(p); } 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/nhrp_vc.c b/nhrpd/nhrp_vc.c index b3b657f3fa..4b45389dad 100644 --- a/nhrpd/nhrp_vc.c +++ b/nhrpd/nhrp_vc.c @@ -19,14 +19,18 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection"); +PREDECL_DLIST(childlist); + struct child_sa { uint32_t id; struct nhrp_vc *vc; - struct list_head childlist_entry; + struct childlist_item childlist_entry; }; +DECLARE_DLIST(childlist, struct child_sa, childlist_entry); + static struct hash *nhrp_vc_hash; -static struct list_head childlist_head[512]; +static struct childlist_head childlist_head[512]; static unsigned int nhrp_vc_key(const void *peer_data) { @@ -104,8 +108,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) uint32_t child_hash = child_id % array_size(childlist_head); int abort_migration = 0; - list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry) - { + frr_each (childlist, &childlist_head[child_hash], lsa) { if (lsa->id == child_id) { sa = lsa; break; @@ -120,12 +123,9 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) *sa = (struct child_sa){ .id = child_id, - .childlist_entry = - LIST_INITIALIZER(sa->childlist_entry), .vc = NULL, }; - list_add_tail(&sa->childlist_entry, - &childlist_head[child_hash]); + childlist_add_tail(&childlist_head[child_hash], sa); } if (sa->vc == vc) @@ -155,7 +155,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) /* Update */ sa->vc = vc; if (!vc) { - list_del(&sa->childlist_entry); + childlist_del(&childlist_head[child_hash], sa); XFREE(MTYPE_NHRP_VC, sa); } @@ -170,7 +170,7 @@ void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n, void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &vc->notifier_list); nhrp_vc_check_delete(vc); } @@ -200,17 +200,16 @@ void nhrp_vc_init(void) nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash"); for (i = 0; i < array_size(childlist_head); i++) - list_init(&childlist_head[i]); + childlist_init(&childlist_head[i]); } void nhrp_vc_reset(void) { - struct child_sa *sa, *n; + struct child_sa *sa; size_t i; for (i = 0; i < array_size(childlist_head); i++) { - list_for_each_entry_safe(sa, n, &childlist_head[i], - childlist_entry) + frr_each_safe (childlist, &childlist_head[i], sa) nhrp_vc_ipsec_updown(sa->id, 0); } } diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 50161dae2f..0dfabcf6ae 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1200,9 +1200,7 @@ static int interface_config_write(struct vty *vty) nhrp_cache_config_foreach( ifp, interface_config_write_nhrp_map, &mapctx); - list_for_each_entry(nhs, &ad->nhslist_head, - nhslist_entry) - { + frr_each (nhrp_nhslist, &ad->nhslist_head, nhs) { vty_out(vty, " %s nhrp nhs ", aficmd); if (sockunion_family(&nhs->proto_addr) == AF_UNSPEC) @@ -1212,9 +1210,7 @@ static int interface_config_write(struct vty *vty) vty_out(vty, " nbma %s\n", nhs->nbma_fqdn); } - list_for_each_entry(mcast, &ad->mcastlist_head, - list_entry) - { + frr_each (nhrp_mcastlist, &ad->mcastlist_head, mcast) { vty_out(vty, " %s nhrp map multicast ", aficmd); if (sockunion_family(&mcast->nbma_addr) == AF_UNSPEC) diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 17abb04762..63f1cb97ef 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -10,8 +10,6 @@ #ifndef NHRPD_H #define NHRPD_H -#include "list.h" - #include "zbuf.h" #include "zclient.h" #include "debug.h" @@ -42,48 +40,53 @@ struct notifier_block; typedef void (*notifier_fn_t)(struct notifier_block *, unsigned long); +PREDECL_DLIST(notifier_list); + struct notifier_block { - struct list_head notifier_entry; + struct notifier_list_item notifier_entry; notifier_fn_t action; }; +DECLARE_DLIST(notifier_list, struct notifier_block, notifier_entry); + struct notifier_list { - struct list_head notifier_head; + struct notifier_list_head head; }; #define NOTIFIER_LIST_INITIALIZER(l) \ { \ - .notifier_head = LIST_INITIALIZER((l)->notifier_head) \ + .head = INIT_DLIST((l)->head) \ } static inline void notifier_init(struct notifier_list *l) { - list_init(&l->notifier_head); + notifier_list_init(&l->head); } static inline void notifier_add(struct notifier_block *n, struct notifier_list *l, notifier_fn_t action) { n->action = action; - list_add_tail(&n->notifier_entry, &l->notifier_head); + notifier_list_add_tail(&l->head, n); } -static inline void notifier_del(struct notifier_block *n) +static inline void notifier_del(struct notifier_block *n, + struct notifier_list *l) { - list_del(&n->notifier_entry); + notifier_list_del(&l->head, n); } static inline void notifier_call(struct notifier_list *l, int cmd) { - struct notifier_block *n, *nn; - list_for_each_entry_safe(n, nn, &l->notifier_head, notifier_entry) { + struct notifier_block *n; + + frr_each_safe (notifier_list, &l->head, n) n->action(n, cmd); - } } static inline int notifier_active(struct notifier_list *l) { - return !list_empty(&l->notifier_head); + return notifier_list_count(&l->head) > 0; } extern struct hash *nhrp_gre_list; @@ -263,9 +266,13 @@ struct nhrp_shortcut { struct notifier_block cache_notifier; }; +PREDECL_DLIST(nhrp_nhslist); +PREDECL_DLIST(nhrp_mcastlist); +PREDECL_DLIST(nhrp_reglist); + struct nhrp_nhs { struct interface *ifp; - struct list_head nhslist_entry; + struct nhrp_nhslist_item nhslist_entry; unsigned hub : 1; afi_t afi; @@ -274,18 +281,22 @@ struct nhrp_nhs { struct thread *t_resolve; struct resolver_query dns_resolve; - struct list_head reglist_head; + struct nhrp_reglist_head reglist_head; }; +DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry); + struct nhrp_multicast { struct interface *ifp; - struct list_head list_entry; + struct nhrp_mcastlist_item mcastlist_entry; afi_t afi; union sockunion nbma_addr; /* IP-address */ }; +DECLARE_DLIST(nhrp_mcastlist, struct nhrp_multicast, mcastlist_entry); + struct nhrp_registration { - struct list_head reglist_entry; + struct nhrp_reglist_item reglist_entry; struct thread *t_register; struct nhrp_nhs *nhs; struct nhrp_reqid reqid; @@ -296,6 +307,8 @@ struct nhrp_registration { struct notifier_block peer_notifier; }; +DECLARE_DLIST(nhrp_reglist, struct nhrp_registration, reglist_entry); + #define NHRP_IFF_SHORTCUT 0x0001 #define NHRP_IFF_REDIRECT 0x0002 #define NHRP_IFF_REG_NO_UNIQUE 0x0100 @@ -330,8 +343,8 @@ struct nhrp_interface { short configured_mtu; unsigned short mtu; unsigned int holdtime; - struct list_head nhslist_head; - struct list_head mcastlist_head; + struct nhrp_nhslist_head nhslist_head; + struct nhrp_mcastlist_head mcastlist_head; } afi[AFI_MAX]; }; @@ -381,7 +394,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn); int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn); -int nhrp_nhs_free(struct nhrp_nhs *nhs); +int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs); void nhrp_nhs_terminate(void); void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am index 9a186d6ed8..dc0c162c83 100644 --- a/nhrpd/subdir.am +++ b/nhrpd/subdir.am @@ -34,7 +34,6 @@ nhrpd_nhrpd_SOURCES = \ noinst_HEADERS += \ nhrpd/debug.h \ - nhrpd/list.h \ nhrpd/netlink.h \ nhrpd/nhrp_errors.h \ nhrpd/nhrp_protocol.h \ 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/nhrpd/zbuf.c b/nhrpd/zbuf.c index e191a90f2d..9cc2b56245 100644 --- a/nhrpd/zbuf.c +++ b/nhrpd/zbuf.c @@ -164,35 +164,33 @@ void *zbuf_may_pull_until(struct zbuf *zb, const char *sep, struct zbuf *msg) void zbufq_init(struct zbuf_queue *zbq) { *zbq = (struct zbuf_queue){ - .queue_head = LIST_INITIALIZER(zbq->queue_head), + .queue_head = INIT_DLIST(zbq->queue_head), }; } void zbufq_reset(struct zbuf_queue *zbq) { - struct zbuf *buf, *bufn; + struct zbuf *buf; - list_for_each_entry_safe(buf, bufn, &zbq->queue_head, queue_list) - { - list_del(&buf->queue_list); + frr_each_safe (zbuf_queue, &zbq->queue_head, buf) { + zbuf_queue_del(&zbq->queue_head, buf); zbuf_free(buf); } } void zbufq_queue(struct zbuf_queue *zbq, struct zbuf *zb) { - list_add_tail(&zb->queue_list, &zbq->queue_head); + zbuf_queue_add_tail(&zbq->queue_head, zb); } int zbufq_write(struct zbuf_queue *zbq, int fd) { struct iovec iov[16]; - struct zbuf *zb, *zbn; + struct zbuf *zb; ssize_t r; size_t iovcnt = 0; - list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list) - { + frr_each_safe (zbuf_queue, &zbq->queue_head, zb) { iov[iovcnt++] = (struct iovec){ .iov_base = zb->head, .iov_len = zbuf_used(zb), }; @@ -204,15 +202,14 @@ int zbufq_write(struct zbuf_queue *zbq, int fd) if (r < 0) return r; - list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list) - { + frr_each_safe (zbuf_queue, &zbq->queue_head, zb) { if (r < (ssize_t)zbuf_used(zb)) { zb->head += r; return 1; } r -= zbuf_used(zb); - list_del(&zb->queue_list); + zbuf_queue_del(&zbq->queue_head, zb); zbuf_free(zb); } diff --git a/nhrpd/zbuf.h b/nhrpd/zbuf.h index 2741860bfd..d036b10460 100644 --- a/nhrpd/zbuf.h +++ b/nhrpd/zbuf.h @@ -15,18 +15,22 @@ #include <endian.h> #include <sys/types.h> -#include "list.h" +#include "typesafe.h" + +PREDECL_DLIST(zbuf_queue); struct zbuf { - struct list_head queue_list; + struct zbuf_queue_item queue_entry; unsigned allocated : 1; unsigned error : 1; uint8_t *buf, *end; uint8_t *head, *tail; }; +DECLARE_DLIST(zbuf_queue, struct zbuf, queue_entry); + struct zbuf_queue { - struct list_head queue_head; + struct zbuf_queue_head queue_head; }; struct zbuf *zbuf_alloc(size_t size); diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 57165201bd..a9b4c7756c 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; @@ -96,8 +106,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route, return 0; } -static void ospf6_abr_delete_route(struct ospf6_route *range, - struct ospf6_route *summary, +static void ospf6_abr_delete_route(struct ospf6_route *summary, struct ospf6_route_table *summary_table, struct ospf6_lsa *old) { @@ -375,8 +384,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, - summary_table, old); + ospf6_abr_delete_route(summary, summary_table, + old); } } else if (old) { ospf6_route_remove(summary, summary_table); @@ -390,7 +399,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Area has been stubbed, purge Inter-Router LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -399,7 +408,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug("Area has been stubbed, purge prefix LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -434,8 +443,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the secondary path to the ASBR, ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -465,8 +473,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Suppressed by range %pFX of area %s", &range->prefix, route_area->name); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -478,8 +485,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the range with DoNotAdvertise set. ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -487,8 +493,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug("The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -598,10 +603,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6) struct ospf6_area *oa; struct ospf6_route *range; - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { for (range = ospf6_route_head(oa->range_table); range; range = ospf6_route_next(range)) OSPF6_ABR_RANGE_CLEAR_COST(range); + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) + OSPF6_ABR_RANGE_CLEAR_COST(range); + } } static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, @@ -612,10 +621,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro; ro = ospf6_route_match_next(&range->prefix, ro)) { - if (ro->path.area_id == range->path.area_id - && (ro->path.type == OSPF6_PATH_TYPE_INTRA) - && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) - cost = MAX(cost, ro->path.cost); + if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) + continue; + if (ro->path.area_id != range->path.area_id) + continue; + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1 + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2) + continue; + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_INTRA) + continue; + + cost = MAX(cost, ro->path.cost); } return cost; @@ -664,6 +682,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) int summary_orig = 0; assert(range->type == OSPF6_DEST_TYPE_RANGE); + oa = ospf6_area_lookup(range->path.area_id, ospf6); + assert(oa); /* update range's cost and active flag */ cost = ospf6_abr_range_compute_cost(range, ospf6); @@ -686,34 +706,49 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) * if there * were active ranges. */ + if (!ospf6_abr_range_summary_needs_update(range, cost)) + return; - if (ospf6_abr_range_summary_needs_update(range, cost)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s: range %pFX update", __func__, - &range->prefix); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: range %pFX update", __func__, &range->prefix); + + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) { + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + ospf6_nssa_lsa_originate(range, oa, true); + summary_orig = 1; + } else { + struct ospf6_lsa *lsa; + + lsa = ospf6_lsdb_lookup(range->path.origin.type, + range->path.origin.id, + ospf6->router_id, oa->lsdb); + if (lsa) + ospf6_lsa_premature_aging(lsa); + } + } else { + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { summary_orig += ospf6_abr_originate_summary_to_area(range, oa); + } + } - if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) - && summary_orig) { - if (!CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Add discard route"); + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && summary_orig) { + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Add discard route"); - ospf6_zebra_add_discard(range, ospf6); - } - } else { - /* Summary removed or no summary generated as no - * specifics exist */ - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Delete discard route"); + ospf6_zebra_add_discard(range, ospf6); + } + } else { + /* Summary removed or no summary generated as no + * specifics exist */ + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Delete discard route"); - ospf6_zebra_delete_discard(range, ospf6); - } + ospf6_zebra_delete_discard(range, ospf6); } } } @@ -815,9 +850,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 +1266,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_area.c b/ospf6d/ospf6_area.c index 999266b8d1..996892c49c 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -306,7 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df) oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); oa->range_table->scope = oa; - bf_init(oa->range_table->idspace, 32); + oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + oa->nssa_range_table->scope = oa; oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES); oa->summary_prefix->scope = oa; oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); @@ -361,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa) ospf6_route_table_delete(oa->route_table); ospf6_route_table_delete(oa->range_table); + ospf6_route_table_delete(oa->nssa_range_table); ospf6_route_table_delete(oa->summary_prefix); ospf6_route_table_delete(oa->summary_router); @@ -576,8 +578,6 @@ DEFUN (area_range, range->path.u.cost_config = cost; - zlog_debug("%s: for prefix %s, flag = %x", __func__, - argv[idx_ipv6_prefixlen]->arg, range->flag); if (range->rnode == NULL) { ospf6_route_add(range, oa->range_table); } @@ -694,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6) vty_out(vty, " no-summary"); vty_out(vty, "\n"); } + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) { + vty_out(vty, " area %s nssa range %pFX", oa->name, + &range->prefix); + + if (CHECK_FLAG(range->flag, + OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + vty_out(vty, " not-advertise"); + } else { + if (range->path.u.cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %u", + range->path.u.cost_config); + } + vty_out(vty, "\n"); + } if (PREFIX_NAME_IN(oa)) vty_out(vty, " area %s filter-list prefix %s in\n", oa->name, PREFIX_NAME_IN(oa)); diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 77cbad8b9e..905fbac949 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -46,6 +46,7 @@ struct ospf6_area { /* Summary routes to be originated (includes Configured Address Ranges) */ struct ospf6_route_table *range_table; + struct ospf6_route_table *nssa_range_table; struct ospf6_route_table *summary_prefix; struct ospf6_route_table *summary_router; diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index df40c608a1..1eb53411c1 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); @@ -1531,7 +1522,6 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, route = ospf6_route_create(ospf6); route->type = OSPF6_DEST_TYPE_NETWORK; prefix_copy(&route->prefix, prefix); - route->ospf6 = ospf6; info = (struct ospf6_external_info *)XCALLOC( MTYPE_OSPF6_EXTERNAL_INFO, sizeof(struct ospf6_external_info)); @@ -3378,7 +3368,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..6e00bd766f 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -266,10 +266,14 @@ void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa) /* RFC2328 section 13.2 Installing LSAs in the database */ void ospf6_install_lsa(struct ospf6_lsa *lsa) { + struct ospf6 *ospf6; struct timeval now; struct ospf6_lsa *old; struct ospf6_area *area = NULL; + ospf6 = ospf6_get_by_lsdb(lsa); + assert(ospf6); + /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, @@ -288,7 +292,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, @@ -331,20 +334,14 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) && !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) { /* check if it is new lsa ? or existing lsa got modified ?*/ - if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) { - struct ospf6 *ospf6; - - ospf6 = ospf6_get_by_lsdb(lsa); - - assert(ospf6); - + if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) ospf6_helper_handle_topo_chg(ospf6, lsa); - } } ospf6_lsdb_add(lsa, lsa->lsdb); - if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) { + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7 + && lsa->header->adv_router != ospf6->router_id) { area = OSPF6_AREA(lsa->lsdb->data); ospf6_translated_nssa_refresh(area, lsa, NULL); ospf6_schedule_abr_task(area->ospf6); @@ -547,7 +544,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 +1024,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 +1071,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 +1110,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 +1235,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, ospf6_lsa_delete(new); return; } - return; } } diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c index 40893ed998..c3e6f62f06 100644 --- a/ospf6d/ospf6_gr.c +++ b/ospf6d/ospf6_gr.c @@ -58,7 +58,7 @@ static int ospf6_gr_lsa_originate(struct ospf6_interface *oi) char buffer[OSPF6_MAX_LSASIZE]; if (IS_OSPF6_DEBUG_ORIGINATE(LINK)) - zlog_debug("Originate Link-LSA for Interface %s", + zlog_debug("Originate Grace-LSA for Interface %s", oi->interface->name); /* prepare buffer */ 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..64992bbcee 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); } @@ -1242,7 +1241,6 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { struct listnode *n; struct connected *c; - struct in6_addr *l = (struct in6_addr *)NULL; /* for each connected address */ for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { @@ -1251,9 +1249,10 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) continue; if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) - l = &c->address->u.prefix6; + return &c->address->u.prefix6; } - return l; + + return NULL; } @@ -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..77f0f8f4e5 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); @@ -1071,7 +1070,7 @@ DEFPY (debug_ospf6_lsa_aggregation, DEFUN (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_cmd, - "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]", + "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -1080,6 +1079,7 @@ DEFUN (debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" @@ -1123,7 +1123,7 @@ DEFUN (debug_ospf6_lsa_type, DEFUN (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_cmd, - "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]", + "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]", NO_STR DEBUG_STR OSPF6_STR @@ -1133,6 +1133,7 @@ DEFUN (no_debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 2316040694..c0d3cc149b 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -87,11 +87,6 @@ #define OSPF6_SCOPE_AS 0x4000 #define OSPF6_SCOPE_RESERVED 0x6000 -/* AS-external-LSA refresh method. */ -#define LSA_REFRESH_IF_CHANGED 0 -#define LSA_REFRESH_FORCE 1 - - /* XXX U-bit handling should be treated here */ #define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK) 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..36948dc0a7 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -48,7 +48,7 @@ #include "ospf6_gr.h" #include "lib/json.h" -DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); DEFINE_HOOK(ospf6_neighbor_change, (struct ospf6_neighbor * on, int state, int next_state), @@ -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..84f014d680 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -49,6 +49,9 @@ #include "ospf6_asbr.h" #include "ospf6d.h" #include "ospf6_nssa.h" +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_nssa_clippy.c" +#endif DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA"); unsigned char config_debug_ospf6_nssa = 0; @@ -262,22 +265,20 @@ static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6) { struct ospf6_area *area; struct ospf6_route *range; - struct listnode *node, *nnode; + struct listnode *node; if (IS_OSPF6_DEBUG_ABR) zlog_debug("ospf6_abr_announce_aggregates(): Start"); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) - ospf6_abr_range_update(range, ospf6); - } - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { if (IS_OSPF6_DEBUG_ABR) zlog_debug( "ospf_abr_announce_aggregates(): looking at area %pI4", &area->area_id); + + for (range = ospf6_route_head(area->range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); } if (IS_OSPF6_DEBUG_ABR) @@ -304,24 +305,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); } } @@ -389,22 +382,18 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) { struct ospf6_lsa *lsa; uint16_t type; - struct ospf6_area *oa; - struct listnode *node; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_unapprove_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { - SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : approved unset on link id %pI4", - __func__, &lsa->header->id); - } + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { + SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s : approved unset on link id %pI4", + __func__, &lsa->header->id); } } @@ -416,17 +405,17 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, struct ospf6_lsa *type7) { - char *buffer; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa *lsa; struct ospf6_as_external_lsa *ext, *extnew; struct ospf6_lsa_header *lsa_header; caddr_t old_ptr, new_ptr; struct ospf6_as_external_lsa *nssa; struct prefix prefix; - struct ospf6_route *match; struct ospf6 *ospf6 = area->ospf6; ptrdiff_t tag_offset = 0; route_tag_t network_order; + struct ospf6_route *range; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Start", __func__); @@ -438,7 +427,27 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, return NULL; } - buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE); + /* find the translated Type-5 for this Type-7 */ + nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + type7->header); + prefix.family = AF_INET6; + prefix.prefixlen = nssa->prefix.prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); + + /* Check if the Type-7 LSA should be suppressed by aggregation. */ + range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table); + if (range && !prefix_same(&prefix, &range->prefix) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) { + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s: LSA %s suppressed by range %pFX of area %s", + __func__, type7->name, &range->prefix, + area->name); + return NULL; + } + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); lsa_header = (struct ospf6_lsa_header *)buffer; extnew = (struct ospf6_as_external_lsa *)((caddr_t)lsa_header @@ -453,23 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa)); - /* find the translated Type-5 for this Type-7 */ - nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( - type7->header); - - prefix.family = AF_INET6; - prefix.prefixlen = nssa->prefix.prefix_length; - ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); - - /* Find the LSA from the external route */ - match = ospf6_route_lookup(&prefix, area->route_table); - if (match == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : no matching route %pFX", __func__, - &prefix); - return NULL; - } - /* set Prefix */ memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length)); ospf6_prefix_apply_mask(&extnew->prefix); @@ -550,7 +542,6 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, struct ospf6_lsa *type5) { struct ospf6_lsa *new = NULL; - struct ospf6_as_external_lsa *ext_lsa; struct prefix prefix; struct ospf6 *ospf6 = area->ospf6; @@ -562,27 +553,27 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, /* Find the AS external LSA */ if (type5 == NULL) { + struct ospf6_as_external_lsa *ext_lsa; + struct ospf6_route *match; + + /* Find the AS external LSA from Type-7 LSA */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( - "%s: No translated Type-5 found for Type-7 with Id %pI4", - __func__, &type7->header->id); + "%s: try to find translated Type-5 LSA for %s", + __func__, type7->name); - /* find the translated Type-5 for this Type-7 */ ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( type7->header); - prefix.family = AF_INET6; prefix.prefixlen = ext_lsa->prefix.prefix_length; ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa, &ext_lsa->prefix); - /* Find the AS external LSA from Type-7 LSA */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s: try to find external LSA id %d", - __func__, type7->external_lsa_id); - type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - type7->external_lsa_id, - ospf6->router_id, ospf6->lsdb); + match = ospf6_route_lookup(&prefix, ospf6->external_table); + if (match) + type5 = ospf6_lsdb_lookup( + OSPF6_LSTYPE_AS_EXTERNAL, match->path.origin.id, + ospf6->router_id, ospf6->lsdb); } if (type5) { @@ -610,6 +601,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, __func__, &type7->header->id); return NULL; } + UNSET_FLAG(new->flag, OSPF6_LSA_UNAPPROVED); } if (IS_OSPF6_DEBUG_NSSA) @@ -618,32 +610,11 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, return new; } -/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */ -struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa, - struct ospf6_lsa *type7) -{ - struct ospf6_lsa *new; - - if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7) - return NULL; - - if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : Could not translate Type-7, Id %pI4, to Type-5", - __func__, &type7->header->id); - return NULL; - } - - return new; -} - -int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) +static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) { /* Incoming Type-7 or later aggregated Type-7 * * LSA is skipped if P-bit is off. - * LSA is aggregated if within range. * * The Type-7 is translated, Installed/Approved as a Type-5 into * global LSDB, then Flooded through AS @@ -667,7 +638,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, P-bit off, NO Translation", __func__, &lsa->header->id); - return 1; + return; } if (IS_OSPF6_DEBUG_NSSA) @@ -684,7 +655,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, Forward address is 0, NO Translation", __func__, &lsa->header->id); - return 1; + return; } /* Find the existing AS-External LSA for this prefix */ @@ -695,23 +666,13 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) ospf6->lsdb); } - /* Check Type 5 LSA using the matching external ID */ - if (old == NULL) { - old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - lsa->external_lsa_id, ospf6->router_id, - ospf6->lsdb); + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (old) + ospf6_lsa_premature_aging(old); + return; } if (old) { - /* Do not continue if type 5 LSA not approved */ - if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : LSA Id %pI4 type 5 is not approved", - __func__, &old->header->id); - return 1; - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : found old translated LSA Id %pI4, refreshing", @@ -730,16 +691,14 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) * originate translated LSA */ - if (ospf6_translated_nssa_originate(area, lsa) == NULL) { + if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : Could not translate Type-7 for %pI4 to Type-5", __func__, &lsa->header->id); - return 1; + return; } } - - return 0; } static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) @@ -759,6 +718,8 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + if (!IS_AREA_NSSA(oa)) + continue; /* skip if not translator */ if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) { @@ -768,13 +729,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) continue; } - /* skip if not Nssa Area */ - if (!IS_AREA_NSSA(oa)) { - zlog_debug("%s area %pI4 Flag %x", __func__, - &oa->area_id, oa->flag); - continue; - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : looking at area %pI4", __func__, &oa->area_id); @@ -792,71 +746,30 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Stop", __func__); } -/* Generate translated type-5 LSA from the configured area ranges*/ -static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6) -{ - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *range; - struct ospf6_lsa *lsa; - - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { - for (range = ospf6_route_head(oa->range_table); range; - range = ospf6_route_next(range)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "Translating range %pFX of area %pI4", - &range->prefix, &oa->area_id); - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - continue; - - /* Find the NSSA LSA from the route */ - /* Generate and flood external LSA */ - lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7, - range->path.origin.id, - ospf6->router_id, oa->lsdb); - if (lsa) - ospf6_abr_translate_nssa(oa, lsa); - } - } -} - static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6) { struct listnode *node; struct ospf6_area *area; + struct ospf6_route *range; if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Start", __func__); + zlog_debug("%s: Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) continue; if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : looking at area %pI4", __func__, + zlog_debug("%s: looking at area %pI4", __func__, &area->area_id); - ospf6_abr_translate_nssa_range(ospf6); + for (range = ospf6_route_head(area->nssa_range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); } if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Stop", __func__); -} - -/*Flood max age LSA's for the unapproved LSA's */ -static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa) -{ - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) - && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - zlog_debug("%s : removing unapproved translates, lsa : %s", - __func__, lsa->name); - - /* FLUSH THROUGHOUT AS */ - ospf6_lsa_premature_aging(lsa); - } - return 0; + zlog_debug("%s: Stop", __func__); } static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) @@ -870,8 +783,16 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) zlog_debug("ospf6_abr_remove_unapproved_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) - ospf6_abr_remove_unapproved_translates_apply(lsa); + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { + zlog_debug( + "%s : removing unapproved translates, lsa : %s", + __func__, lsa->name); + + ospf6_lsa_premature_aging(lsa); + } + } if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf_abr_remove_unapproved_translates(): Stop"); @@ -956,11 +877,6 @@ void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6) static void ospf6_abr_nssa_task(struct ospf6 *ospf6) { - /* called only if any_nssa */ - struct ospf6_route *range; - struct ospf6_area *area; - struct listnode *node, *nnode; - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("Check for NSSA-ABR Tasks():"); @@ -986,10 +902,10 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) ospf6_abr_unapprove_translates(ospf6); - /* RESET all Ranges in every Area, same as summaries */ + /* Originate Type-7 aggregates */ if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates"); - ospf6_abr_range_reset_cost(ospf6); + zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); + ospf6_abr_send_nssa_aggregates(ospf6); /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or * Aggregate as Type-7 @@ -999,32 +915,12 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) zlog_debug("ospf6_abr_nssa_task(): process translates"); ospf6_abr_process_nssa_translates(ospf6); - /* Translate/Send any "ranged" aggregates, and also 5-Install and - * Approve - * Scan Type-7's for aggregates, translate to Type-5's, - * Install/Flood/Approve - */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); - ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */ - /* Flush any unapproved previous translates from Global Data Base */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "ospf6_abr_nssa_task(): remove unapproved translates"); ospf6_abr_remove_unapproved_translates(ospf6); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) { - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - ospf6_zebra_delete_discard(range, ospf6); - else - ospf6_zebra_add_discard(range, ospf6); - } - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_nssa_task(): Stop"); } @@ -1071,113 +967,11 @@ int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, return 1; } -static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type, - unsigned short instance, int force) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - if (type == ZEBRA_ROUTE_MAX) - return; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - info = route->route_option; - - /* Find the external LSA in the database */ - if (!is_default_prefix(&route->prefix)) { - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - THREAD_OFF(lsa->refresh); - - /* LSA is maxage, immediate refresh */ - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else { - /* LSA not found in the database - * Verify and originate external LSA - */ - if (ospf6_redistribute_check(ospf6, route, - type)) - ospf6_as_external_lsa_originate(route, - ospf6); - } - } - } -} - -/* Refresh default route */ -static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - if (is_default_prefix(&route->prefix)) { - info = route->route_option; - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", - (void *)lsa); - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else if (!lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); - ospf6_as_external_lsa_originate(route, ospf6); - } - } - } -} - -/* If there's redistribution configured, we need to refresh external - * LSAs in order to install Type-7 and flood to all NSSA Areas - */ -void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6) -{ - int type; - struct ospf6_redist *red; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - red = ospf6_redist_lookup(ospf6, type, 0); - if (!red) - return; - - ospf6_external_lsa_refresh_type(ospf6, type, red->instance, - LSA_REFRESH_IF_CHANGED); - } - ospf6_external_lsa_refresh_default(ospf6); -} - /* This function performs ABR related processing */ 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"); @@ -1186,7 +980,6 @@ static int ospf6_abr_task_timer(struct thread *thread) ospf6_abr_task(ospf6); /* if nssa-abr, then scan Type-7 LSDB */ ospf6_abr_nssa_task(ospf6); - ospf6_asbr_nssa_redist_task(ospf6); return 0; } @@ -1347,6 +1140,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area) UNSET_FLAG(area->flag, OSPF6_AREA_NSSA); if (IS_OSPF6_DEBUG_NSSA) zlog_debug("area %s nssa reset", area->name); + + /* Clear the table of NSSA ranges. */ + ospf6_route_table_delete(area->nssa_range_table); + area->nssa_range_table = + OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + area->nssa_range_table->scope = area; + ospf6_area_nssa_update(area); } @@ -1360,10 +1160,14 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa) struct ospf6_interface *oi; for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { - if (if_is_operative(oi->interface)) - if (oi->area && IS_AREA_NSSA(oi->area)) - return ospf6_interface_get_global_address( - oi->interface); + struct in6_addr *addr; + + if (!if_is_operative(oi->interface)) + continue; + + addr = ospf6_interface_get_global_address(oi->interface); + if (addr) + return addr; } return NULL; } @@ -1473,17 +1277,119 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area, if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : start", __func__); + if (!ospf6_check_and_set_router_abr(ospf6)) + return; + type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), lsa->external_lsa_id, ospf6->router_id, ospf6->lsdb); - - if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) { + if (!type5) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Originating type5 LSA", __func__); ospf6_lsa_translated_nssa_new(area, lsa); } } +DEFPY (area_nssa_range, + area_nssa_range_cmd, + "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]", + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + if (!IS_AREA_NSSA(oa)) { + vty_out(vty, "%% First configure %s as an NSSA area\n", area); + return CMD_WARNING; + } + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + range = ospf6_route_create(ospf6); + range->type = OSPF6_DEST_TYPE_RANGE; + SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE); + prefix_copy(&range->prefix, prefix); + range->path.area_id = oa->area_id; + range->path.metric_type = 2; + range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7); + range->path.origin.id = htonl(ospf6->external_id++); + range->path.origin.adv_router = ospf6->router_id; + ospf6_route_add(range, oa->nssa_range_table); + } + + /* process "not-advertise" */ + if (not_adv) + SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + else + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + + /* process "cost" */ + if (!cost_str) + cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.u.cost_config = cost; + + /* Redo summaries if required */ + if (ospf6_check_and_set_router_abr(ospf6)) + ospf6_schedule_abr_task(ospf6); + + return CMD_SUCCESS; +} + +DEFPY (no_area_nssa_range, + no_area_nssa_range_cmd, + "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]", + NO_STR + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + vty_out(vty, "%% range %s does not exists.\n", prefix_str); + return CMD_SUCCESS; + } + + if (ospf6_check_and_set_router_abr(oa->ospf6)) { + /* Blow away the aggregated LSA and route */ + SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE); + + /* Redo summaries if required */ + thread_execute(master, ospf6_abr_task_timer, ospf6, 0); + } + + ospf6_route_remove(range, oa->nssa_range_table); + + return CMD_SUCCESS; +} + DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd, "debug ospf6 nssa", DEBUG_STR @@ -1513,6 +1419,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty) void install_element_ospf6_debug_nssa(void) { + install_element(OSPF6_NODE, &area_nssa_range_cmd); + install_element(OSPF6_NODE, &no_area_nssa_range_cmd); + install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd); install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd); install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd); diff --git a/ospf6d/ospf6_nssa.h b/ospf6d/ospf6_nssa.h index 99cb04c003..02234cc8bd 100644 --- a/ospf6d/ospf6_nssa.h +++ b/ospf6d/ospf6_nssa.h @@ -55,8 +55,6 @@ extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p); extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa, struct ospf6_lsa *type7, struct ospf6_lsa *type5); -extern struct ospf6_lsa * -ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7); extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6); @@ -69,8 +67,6 @@ extern void install_element_ospf6_debug_nssa(void); extern void ospf6_abr_nssa_type_7_defaults(struct ospf6 *osof6); int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, int type); -extern int ospf6_abr_translate_nssa(struct ospf6_area *area, - struct ospf6_lsa *lsa); extern void ospf6_abr_check_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa); extern void ospf6_abr_nssa_check_status(struct ospf6 *ospf6); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 8bfd3b7124..a4ed99ea2d 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) @@ -1100,7 +1098,6 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t) void ospf6_route_table_delete(struct ospf6_route_table *table) { ospf6_route_remove_all(table); - bf_free(table->idspace); route_table_finish(table->table); XFREE(MTYPE_OSPF6_ROUTE_TABLE, table); } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e29439b95e..fd8b6a9c1d 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -186,7 +186,7 @@ struct ospf6_route { struct timeval changed; /* flag */ - uint8_t flag; + uint16_t flag; /* Prefix Options */ uint8_t prefix_options; @@ -221,14 +221,15 @@ struct ospf6_route { #define OSPF6_DEST_TYPE_RANGE 5 #define OSPF6_DEST_TYPE_MAX 6 -#define OSPF6_ROUTE_CHANGE 0x01 -#define OSPF6_ROUTE_ADD 0x02 -#define OSPF6_ROUTE_REMOVE 0x04 -#define OSPF6_ROUTE_BEST 0x08 -#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10 -#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20 -#define OSPF6_ROUTE_WAS_REMOVED 0x40 -#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80 +#define OSPF6_ROUTE_CHANGE 0x0001 +#define OSPF6_ROUTE_ADD 0x0002 +#define OSPF6_ROUTE_REMOVE 0x0004 +#define OSPF6_ROUTE_BEST 0x0008 +#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010 +#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020 +#define OSPF6_ROUTE_WAS_REMOVED 0x0040 +#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080 +#define OSPF6_ROUTE_NSSA_RANGE 0x0100 struct ospf6; struct ospf6_route_table { @@ -241,8 +242,6 @@ struct ospf6_route_table { uint32_t count; - bitfield_t idspace; - /* hooks */ void (*hook_add)(struct ospf6_route *); void (*hook_change)(struct ospf6_route *); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6fe7055202..7e9ed4160d 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; @@ -1033,7 +1032,6 @@ DEFUN_HIDDEN (ospf6_interface_area, struct ospf6_area *oa; struct ospf6_interface *oi; struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; uint32_t area_id; int format; @@ -1042,11 +1040,8 @@ DEFUN_HIDDEN (ospf6_interface_area, vty_out(vty, "Please, use \"ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) oi = ospf6_interface_create(ifp); @@ -1108,18 +1103,14 @@ DEFUN_HIDDEN (no_ospf6_interface_area, struct ospf6_area *oa; struct interface *ifp; uint32_t area_id; - vrf_id_t vrf_id = VRF_DEFAULT; vty_out(vty, "This command is deprecated, because it is not VRF-aware.\n"); vty_out(vty, "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); if (ifp == NULL) { vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); 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/ospf6d/subdir.am b/ospf6d/subdir.am index be626646a0..34aabc205b 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -99,6 +99,7 @@ clippy_scan += \ ospf6d/ospf6_lsa.c \ ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_gr.c \ + ospf6d/ospf6_nssa.c \ ospf6d/ospf6_route.c \ # end 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..8276ccb89c 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -150,7 +150,7 @@ static struct ospf_lsa *ospf_gr_lsa_new(struct ospf_interface *oi) } /* Originate and install Grace-LSA for a given interface. */ -static void ospf_gr_lsa_originate(struct ospf_interface *oi) +static void ospf_gr_lsa_originate(struct ospf_interface *oi, bool maxage) { struct ospf_lsa *lsa, *old; @@ -164,6 +164,9 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi) return; } + if (maxage) + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + /* Find the old LSA and increase the seqno. */ old = ospf_gr_lsa_lookup(oi->ospf, oi->area); if (old) @@ -183,37 +186,6 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi) ospf_flood_through_interface(oi, NULL, lsa); } -/* Flush a given self-originated Grace-LSA. */ -static struct ospf_lsa *ospf_gr_flush_grace_lsa(struct ospf_interface *oi, - struct ospf_lsa *old) -{ - struct ospf_lsa *lsa; - - if (ospf_interface_neighbor_count(oi) == 0) - return NULL; - - if (IS_DEBUG_OSPF_GR) - zlog_debug( - "GR: flushing self-originated Grace-LSAs [interface %s]", - oi->ifp->name); - - lsa = ospf_lsa_dup(old); - lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); - lsa->data->ls_seqnum = lsa_seqnum_increment(lsa); - - /* Install updated LSA into LSDB. */ - if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) { - zlog_warn("%s: ospf_lsa_install() failed", __func__); - ospf_lsa_unlock(&lsa); - return NULL; - } - - /* Flood the LSA through out the interface */ - ospf_flood_through_interface(oi, NULL, lsa); - - return lsa; -} - /* Flush all self-originated Grace-LSAs. */ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) { @@ -221,7 +193,6 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) struct listnode *anode; for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) { - struct ospf_lsa *lsa; struct ospf_interface *oi; struct listnode *inode; @@ -230,15 +201,8 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) "GR: flushing self-originated Grace-LSAs [area %pI4]", &area->area_id); - lsa = ospf_gr_lsa_lookup(ospf, area); - if (!lsa) { - zlog_warn("%s: Grace-LSA not found [area %pI4]", - __func__, &area->area_id); - continue; - } - for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) - ospf_gr_flush_grace_lsa(oi, lsa); + ospf_gr_lsa_originate(oi, true); } } @@ -584,7 +548,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 +594,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 +627,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) @@ -750,7 +714,7 @@ static void ospf_gr_prepare(void) /* Send a Grace-LSA to all neighbors. */ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) - ospf_gr_lsa_originate(oi); + ospf_gr_lsa_originate(oi, false); /* Record end of the grace period in non-volatile memory. */ ospf_gr_nvm_update(ospf); @@ -770,6 +734,18 @@ DEFPY(graceful_restart_prepare, graceful_restart_prepare_cmd, IP_STR "Prepare to restart the OSPF process") { + struct ospf *ospf; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + vty_out(vty, + "%% Can't start graceful restart: opaque capability not enabled (VRF %s)\n\n", + ospf_get_name(ospf)); + return CMD_WARNING; + } + } + ospf_gr_prepare(); return CMD_SUCCESS; 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..60e109ea80 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; @@ -915,9 +915,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, ospf->vrf_id); snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count); - vi = if_create_name(ifname, ospf->vrf_id); + vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name); /* - * if_create_name sets ZEBRA_INTERFACE_LINKDETECTION + * if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION * virtual links don't need this. */ UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION); @@ -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_lsa.c b/ospfd/ospf_lsa.c index cc1b2919c0..10541b09bb 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2480,10 +2480,6 @@ ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc) return new; } -#define OSPF_INTERFACE_TIMER_ON(T, F, V) \ - if (!(T)) \ - (T) = thread_add_timer(master, (F), oi, (V)) - /* Install network-LSA to an area. */ static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf, struct ospf_interface *oi, diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 5dcd072774..2e648b3354 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -223,10 +223,6 @@ struct as_external_lsa { #define OSPF_LSA_UPDATE_DELAY 2 -#define OSPF_LSA_UPDATE_TIMER_ON(T, F) \ - if (!(T)) \ - (T) = thread_add_timer(master, (F), 0, 2) - #define CHECK_LSA_TYPE_1_TO_5_OR_7(type) \ ((type == OSPF_ROUTER_LSA) || (type == OSPF_NETWORK_LSA) \ || (type == OSPF_SUMMARY_LSA) || (type == OSPF_ASBR_SUMMARY_LSA) \ 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..ca4bb0a2b9 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, @@ -1096,44 +1096,61 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, zlog_debug( "%s, Neighbor is under GR Restart, hence ignoring the ISM Events", __PRETTY_FUNCTION__); - - return; - } - - /* If neighbor itself declares DR and no BDR exists, - cause event BackupSeen */ - if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)) - if (hello->bd_router.s_addr == INADDR_ANY - && oi->state == ISM_Waiting) + } else { + /* If neighbor itself declares DR and no BDR exists, + cause event BackupSeen */ + if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)) + if (hello->bd_router.s_addr == INADDR_ANY + && oi->state == ISM_Waiting) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); + + /* neighbor itself declares BDR. */ + if (oi->state == ISM_Waiting + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &hello->bd_router)) OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); - /* neighbor itself declares BDR. */ - if (oi->state == ISM_Waiting - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router)) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); - - /* had not previously. */ - if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router) - && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router)) - || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router) - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->d_router))) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); - - /* had not previously. */ - if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router) - && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router)) - || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->bd_router) - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->bd_router))) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); - - /* Neighbor priority check. */ - if (nbr->priority >= 0 && nbr->priority != hello->priority) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &nbr->d_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, + &hello->bd_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &nbr->bd_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* Neighbor priority check. */ + if (nbr->priority >= 0 && nbr->priority != hello->priority) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } /* Set neighbor information. */ 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 +1392,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 +1633,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 +1877,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 +2263,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 +3895,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 +3914,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..64d3b7a028 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); @@ -453,7 +445,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr, "Please, use \"ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg); @@ -514,7 +506,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface, "Please, use \"no ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg); @@ -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/ospfd/ospfd.c b/ospfd/ospfd.c index 766be60778..1e1057dc39 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -582,6 +582,7 @@ static void ospf_deferred_shutdown_finish(struct ospf *ospf) /* ospfd being shut-down? If so, was this the last ospf instance? */ if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN) && (listcount(om->ospf) == 0)) { + frr_fini(); exit(0); } diff --git a/pathd/pathd.c b/pathd/pathd.c index 90b8727284..7f6d34f752 100644 --- a/pathd/pathd.c +++ b/pathd/pathd.c @@ -22,6 +22,7 @@ #include "log.h" #include "lib_errors.h" #include "network.h" +#include "libfrr.h" #include "pathd/pathd.h" #include "pathd/path_zebra.h" @@ -1223,6 +1224,7 @@ void pathd_shutdown(void) { path_ted_teardown(); srte_clean_zebra(); + frr_fini(); } void trigger_pathd_candidate_created(struct srte_candidate *candidate) diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 8a4132642d..a16d00c472 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -575,7 +575,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, actual = vrf_lookup_by_id(ifp->vrf_id); vty_out(vty, "Specified Intf %s is not in vrf %s but is in vrf %s, using actual vrf\n", - ifp->name, vrf->name, actual->name); + ifp->name, vrf->name, VRF_LOGNAME(actual)); } nhop.ifindex = ifp->ifindex; nhop.vrf_id = ifp->vrf_id; diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 47d82950e7..44c258cb3d 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_iface.c b/pimd/pim_iface.c index eb19cf4ddf..5e311d101a 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1482,7 +1482,8 @@ void pim_if_create_pimreg(struct pim_instance *pim) snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u", pim->vrf->data.l.table_id); - pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id); + pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id, + pim->vrf->name); pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; pim_if_new(pim->regiface, false, false, true, 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_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/redhat/frr.spec.in b/redhat/frr.spec.in index 066c45f55c..a7286d1878 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -717,6 +717,7 @@ fi %files pythontools %{_sbindir}/generate_support_bundle.py %{_sbindir}/frr-reload.py +%{_sbindir}/frr_babeltrace.py %if 0%{?rhel} > 7 || 0%{?fedora} > 29 %{_sbindir}/__pycache__/* %else @@ -724,6 +725,8 @@ fi %{_sbindir}/generate_support_bundle.pyo %{_sbindir}/frr-reload.pyc %{_sbindir}/frr-reload.pyo +%{_sbindir}/frr_babeltrace.pyc +%{_sbindir}/frr_babeltrace.pyo %endif 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/.gitignore b/tests/.gitignore index 498d7dd0b7..8cc2aa98f9 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -28,6 +28,7 @@ /lib/test_frrscript /lib/test_frrlua /lib/test_graph +/lib/test_grpc /lib/test_heavy /lib/test_heavy_thread /lib/test_heavy_wq @@ -44,6 +45,7 @@ /lib/test_segv /lib/test_seqlock /lib/test_sig +/lib/test_skiplist /lib/test_srcdest_table /lib/test_stream /lib/test_table 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_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/lib/test_typelist.h b/tests/lib/test_typelist.h index 379a2396b4..8261616ed2 100644 --- a/tests/lib/test_typelist.h +++ b/tests/lib/test_typelist.h @@ -39,6 +39,8 @@ #define list_find concat(TYPE, _find) #define list_find_lt concat(TYPE, _find_lt) #define list_find_gteq concat(TYPE, _find_gteq) +#define list_member concat(TYPE, _member) +#define list_anywhere concat(TYPE, _anywhere) #define list_del concat(TYPE, _del) #define list_pop concat(TYPE, _pop) #define list_swap_all concat(TYPE, _swap_all) @@ -239,6 +241,13 @@ static void concat(test_, TYPE)(void) ts_hash_headx( &head, "swap2b", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838"); + + while (list_pop(&other)) + ; + list_fini(&other); + prng_free(prng_swap); + + ts_ref("swap-cleanup"); #endif /* !IS_ATOMIC */ k = 0; @@ -294,7 +303,7 @@ static void concat(test_, TYPE)(void) #elif IS_HEAP(REALTYPE) /* heap - partially sorted. */ prev = NULL; - l = k / 2; + l = k / 4; for (i = 0; i < l; i++) { item = list_pop(&head); if (prev) @@ -303,7 +312,24 @@ static void concat(test_, TYPE)(void) k--; prev = item; } - ts_hash("pop", NULL); + ts_hash("pop#1", NULL); + + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hash("member", NULL); + + l = k / 2; + for (; i < l; i++) { + item = list_pop(&head); + if (prev) + assert(prev->val < item->val); + item->scratchpad = 0; + k--; + prev = item; + } + ts_hash("pop#2", NULL); #else /* !IS_UNIQ(REALTYPE) && !IS_HEAP(REALTYPE) */ for (i = 0; i < NITEM; i++) { @@ -380,6 +406,14 @@ static void concat(test_, TYPE)(void) assert(l + list_count(&head) == k); ts_hashx("del", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca"); +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hashx("member", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca"); +#endif + frr_each_safe(list, &head, item) { assert(item->scratchpad != 0); @@ -449,6 +483,13 @@ static void concat(test_, TYPE)(void) ts_hash_head( &head, "swap2b", "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19"); + + while (list_pop(&other)) + ; + list_fini(&other); + prng_free(prng_swap); + + ts_ref("swap-cleanup"); #endif for (i = 0; i < NITEM / 2; i++) { @@ -461,7 +502,39 @@ static void concat(test_, TYPE)(void) } ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) { + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + assertf(list_anywhere(&itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_anywhere(&itm[i])); + } + ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); +#endif + l = 0; + while (l < (k / 4) && (prev = list_pop(&head))) { + assert(prev->scratchpad != 0); + + prev->scratchpad = 0; + l++; + } + ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); + +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) { + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + assertf(list_anywhere(&itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_anywhere(&itm[i])); + } + ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); +#endif + while ((item = list_pop(&head))) { assert(item->scratchpad != 0); @@ -471,7 +544,7 @@ static void concat(test_, TYPE)(void) assert(l == k); assert(list_count(&head) == 0); assert(list_first(&head) == NULL); - ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"); + ts_hash("pop#2", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"); prng_free(prng); prng = prng_new(0x1e5a2d69); @@ -650,6 +723,7 @@ static void concat(test_, TYPE)(void) list_fini(&head); ts_ref("fini"); ts_end(); + prng_free(prng); printfrr("%s end\n", str(TYPE)); } @@ -680,6 +754,8 @@ static void concat(test_, TYPE)(void) #undef list_find #undef list_find_lt #undef list_find_gteq +#undef list_member +#undef list_anywhere #undef list_del #undef list_pop #undef list_swap_all 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..f35c20e16c 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,10 +195,10 @@ 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 + "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 10, 2 ) router_compare_json_output( "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_rt2_down.ref", 1, 0 @@ -234,10 +234,9 @@ 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 + "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 10, 2 ) router_compare_json_output( "rt1", "show ipv6 route ospf json", "step3/show_ipv6_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/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/bgp_lu_topo1/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json index 29e6c2cbf7..9c817e8075 100644 --- a/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json +++ b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json @@ -1,8 +1,8 @@ { - "Ledger":506, - "InUse":506, + "Ledger":0, + "InUse":0, "Requests":0, - "LabelChunks":11, + "LabelChunks":0, "Pending":0, "Reconnects":0 } diff --git a/tests/topotests/bgp_lu_topo2/R1/bgpd.conf b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf new file mode 100644 index 0000000000..13383e20b6 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf @@ -0,0 +1,29 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 1 + bgp router-id 10.0.0.1 + timers bgp 3 9 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 10.0.0.2 remote-as 2 +! neighbor 10.0.0.2 solo + neighbor 10.0.0.2 timers connect 10 + neighbor 10.0.4.4 remote-as 4 +! neighbor 10.0.4.4 solo + neighbor 10.0.4.4 timers connect 10 +! + address-family ipv4 unicast + no neighbor 10.0.0.2 activate + no neighbor 10.0.4.4 activate + redistribute connected + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.0.2 activate + neighbor 10.0.4.4 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json new file mode 100644 index 0000000000..77705e8d35 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json @@ -0,0 +1,8 @@ +{ + "Ledger":51, + "InUse":51, + "Requests":0, + "LabelChunks":2, + "Pending":0, + "Reconnects":0 +} diff --git a/tests/topotests/bgp_lu_topo2/R1/zebra.conf b/tests/topotests/bgp_lu_topo2/R1/zebra.conf new file mode 100644 index 0000000000..c782481860 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/zebra.conf @@ -0,0 +1,13 @@ +! +no log unique-id +! +debug zebra events +debug zebra rib det +debug zebra dplane +debug zebra mpls +! +interface R1-eth0 + ip address 10.0.0.1/24 +! +interface R1-eth1 + ip address 10.0.4.1/24 diff --git a/tests/topotests/bgp_lu_topo2/R2/bgpd.conf b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf new file mode 100644 index 0000000000..bab3b8dd78 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf @@ -0,0 +1,27 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 2 + bgp router-id 10.0.0.2 + no bgp ebgp-requires-policy + no bgp network import-check + timers bgp 3 9 + neighbor 10.0.0.1 remote-as 1 + neighbor 10.0.0.1 timers connect 10 + neighbor 10.0.1.3 remote-as 2 + neighbor 10.0.1.3 update-source 10.0.1.2 + neighbor 10.0.1.3 timers connect 10 +! + address-family ipv4 unicast + network 10.0.0.0/24 + neighbor 10.0.1.3 activate + no neighbor 10.0.0.1 activate + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.0.1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json new file mode 100644 index 0000000000..eb1ae93b6c --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json @@ -0,0 +1,8 @@ +{ + "Ledger":1, + "InUse":1, + "Requests":0, + "LabelChunks":1, + "Pending":0, + "Reconnects":0 +} diff --git a/tests/topotests/bgp_lu_topo2/R2/zebra.conf b/tests/topotests/bgp_lu_topo2/R2/zebra.conf new file mode 100644 index 0000000000..b8a03e4fcb --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/zebra.conf @@ -0,0 +1,14 @@ +! +no log unique-id +! +debug zebra events +debug zebra dplane +debug zebra mpls +debug zebra rib det +! +interface R2-eth0 + ip address 10.0.0.2/24 +! +interface R2-eth1 + ip address 10.0.1.2/24 +!
\ No newline at end of file diff --git a/tests/topotests/bgp_lu_topo2/R3/bgpd.conf b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf new file mode 100644 index 0000000000..2dfeaa3274 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf @@ -0,0 +1,70 @@ +log file /tmp/bgpd.log +no log unique-id +! +! +debug bgp updates +! +router bgp 2 + bgp router-id 10.0.1.3 + no bgp ebgp-requires-policy + no bgp network import-check + timers bgp 3 9 + neighbor 10.0.1.2 remote-as 2 + neighbor 10.0.1.2 timers connect 10 + ! + address-family ipv4 unicast + neighbor 10.0.1.2 activate + network 10.0.1.0/24 + network 11.0.0.1/32 + network 11.0.0.2/32 + network 11.0.0.3/32 + network 11.0.0.4/32 + network 11.0.0.5/32 + network 11.0.0.6/32 + network 11.0.0.7/32 + network 11.0.0.8/32 + network 11.0.0.9/32 + network 11.0.0.10/32 + network 11.0.0.11/32 + network 11.0.0.12/32 + network 11.0.0.13/32 + network 11.0.0.14/32 + network 11.0.0.15/32 + network 11.0.0.16/32 + network 11.0.0.17/32 + network 11.0.0.18/32 + network 11.0.0.19/32 + network 11.0.0.20/32 + network 11.0.0.21/32 + network 11.0.0.22/32 + network 11.0.0.23/32 + network 11.0.0.24/32 + network 11.0.0.25/32 + network 11.0.0.26/32 + network 11.0.0.27/32 + network 11.0.0.28/32 + network 11.0.0.29/32 + network 11.0.0.30/32 + network 11.0.0.31/32 + network 11.0.0.32/32 + network 11.0.0.33/32 + network 11.0.0.34/32 + network 11.0.0.35/32 + network 11.0.0.36/32 + network 11.0.0.37/32 + network 11.0.0.38/32 + network 11.0.0.39/32 + network 11.0.0.40/32 + network 11.0.0.41/32 + network 11.0.0.42/32 + network 11.0.0.43/32 + network 11.0.0.44/32 + network 11.0.0.45/32 + network 11.0.0.46/32 + network 11.0.0.47/32 + network 11.0.0.48/32 + network 11.0.0.49/32 + network 11.0.0.50/32 + exit-address-family + ! +! diff --git a/tests/topotests/bgp_lu_topo2/R3/staticd.conf b/tests/topotests/bgp_lu_topo2/R3/staticd.conf new file mode 100644 index 0000000000..867fc5a837 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/staticd.conf @@ -0,0 +1,5 @@ +log file /tmp/staticd.log +no log unique-id +! +! +ip route 10.0.4.0/24 10.0.1.2 diff --git a/tests/topotests/bgp_lu_topo2/R3/zebra.conf b/tests/topotests/bgp_lu_topo2/R3/zebra.conf new file mode 100644 index 0000000000..e4234de48c --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/zebra.conf @@ -0,0 +1,11 @@ +log file /tmp/zebra.log +no log unique-id +! +! +debug zebra events +debug zebra packet detail +debug zebra mpls +! +interface R3-eth0 + ip address 10.0.1.3/24 +! diff --git a/tests/topotests/bgp_lu_topo2/R4/bgpd.conf b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf new file mode 100644 index 0000000000..3cef827b86 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf @@ -0,0 +1,23 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 4 + bgp router-id 10.0.4.4 + timers bgp 3 9 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 10.0.4.1 remote-as 1 + neighbor 10.0.4.1 solo + neighbor 10.0.4.1 timers connect 10 +! + address-family ipv4 unicast + no neighbor 10.0.4.1 activate + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.4.1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R4/zebra.conf b/tests/topotests/bgp_lu_topo2/R4/zebra.conf new file mode 100644 index 0000000000..ba1b2bba6e --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R4/zebra.conf @@ -0,0 +1,9 @@ +no log unique-id +! +debug zebra events +debug zebra dplane +debug zebra mpls +debug zebra rib det +! +interface R4-eth0 + ip address 10.0.4.4/24 diff --git a/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py new file mode 100644 index 0000000000..fc9d2c433a --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +# +# test_bgp_lu2.py +# +# Part of FRR/NetDEF Topology Tests +# +# Copyright (c) 2020 by Volta Networks +# Copyright (c) 2021 by Nvidia, Inc. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_bgp_lu2.py: Test BGP LU label allocation +""" + +import os +import sys +import json +from functools import partial +import pytest + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +pytestmark = [pytest.mark.bgpd] + +# +# Basic scenario for BGP-LU. Nodes are directly connected. +# Node 3 is advertising routes to 2, which advertises them +# as BGP-LU to 1; this way we get routes with actual labels, as +# opposed to implicit-null routes in the 2-node case. +# +# R2 is an LER, with MPLS towards R1, and IP towards R3. R1 is an LSR, with +# MPLS on both sides. +# +# +# AS4 BGP-LU AS1 BGP-LU AS2 iBGP AS2 +# +-----+ +-----+ +-----+ +-----+ +# | |.4 .1| |.1 .2| |.2 .3| | +# | 4 +-------------+ 1 +----------------+ 2 +-----------------+ 3 | +# | | 10.0.4.0/24 | | 10.0.0.0/24 | | 10.0.1.0/24 | | +# +-----+ +-----+ +-----+ +-----+ +# +# + + +def build_topo(tgen): + "Build function" + + # This function's only purpose is to define allocation and relationship + # between routers, switches and hosts. + # + # + # Create routers + tgen.add_router("R1") + tgen.add_router("R2") + tgen.add_router("R3") + tgen.add_router("R4") + + # R1-R2 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["R1"]) + switch.add_link(tgen.gears["R2"]) + + # R2-R3 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["R2"]) + switch.add_link(tgen.gears["R3"]) + + # R1-R4 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["R1"]) + switch.add_link(tgen.gears["R4"]) + + +def setup_module(mod): + "Sets up the pytest environment" + # This function initiates the topology build with Topogen... + tgen = Topogen(build_topo, mod.__name__) + + # Skip if no mpls support + if not tgen.hasmpls: + logger.info("MPLS is not available, skipping test") + pytest.skip("MPLS is not available, skipping") + return + + # ... and here it calls Mininet initialization functions. + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + + # Enable mpls input for routers, so we can ping + sval = "net.mpls.conf.{}.input" + topotest.sysctl_assure(router_list["R2"], sval.format("R2-eth0"), 1) + topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth0"), 1) + topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth1"), 1) + topotest.sysctl_assure(router_list["R4"], sval.format("R4-eth0"), 1) + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + # Have static config for R3 too + if router == router_list["R3"]: + router.load_config( + TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname)) + ) + + # After loading the configurations, this function loads configured daemons. + tgen.start_router() + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def check_labelpool(router): + json_file = "{}/{}/labelpool.summ.json".format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show bgp labelpool summary json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"{}" JSON output mismatches - Did not converge'.format(router.name) + assert result is None, assertmsg + + +def test_converge_bgplu(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # TODO -- enable for debugging + # tgen.mininet_cli() + + r1 = tgen.gears["R1"] + r2 = tgen.gears["R2"] + + check_labelpool(r1) + check_labelpool(r2) + + +def test_ping(): + "Simple ping tests" + + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # + logger.info("Ping from R2 to R3") + router = tgen.gears["R2"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3")) + assert " 0% packet loss" in output, "Ping R2->R3 FAILED" + logger.info("Ping from R2 to R3 ... success") + + # + logger.info("Ping from R4 to R2") + router = tgen.gears["R4"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.0.2")) + assert " 0% packet loss" in output, "Ping R4->R2 FAILED" + logger.info("Ping from R4 to R2 ... success") + + # + logger.info("Ping from R4 to R3") + router = tgen.gears["R4"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3")) + assert " 0% packet loss" in output, "Ping R4->R3 FAILED" + logger.info("Ping from R4 to R3 ... success") + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/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/common_config.py b/tests/topotests/lib/common_config.py index 1bce3c6bb2..cf8efdea16 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -2552,6 +2552,7 @@ def create_route_maps(tgen, input_dict, build=False): nexthop = set_data.setdefault("nexthop", None) origin = set_data.setdefault("origin", None) ext_comm_list = set_data.setdefault("extcommunity", {}) + metrictype = set_data.setdefault("metric-type", {}) # Local Preference if local_preference: @@ -2559,6 +2560,10 @@ def create_route_maps(tgen, input_dict, build=False): "set local-preference {}".format(local_preference) ) + # Metric-Type + if metrictype: + rmap_data.append("set metric-type {}\n".format(metrictype)) + # Metric if metric: rmap_data.append("set metric {} \n".format(metric)) diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index c98bfac9ee..18882285ed 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -291,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/topotest.py b/tests/topotests/lib/topotest.py index b98698185c..947ea196b6 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1445,7 +1445,7 @@ class Router(Node): running = self.listDaemons() if running: - for _ in range(0, 5): + for _ in range(0, 30): sleep( 0.5, "{}: waiting for daemons stopping: {}".format( 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/ospf6_topo2/r1/ospf6d.conf b/tests/topotests/ospf6_topo2/r1/ospf6d.conf index 2e465e6d1f..1bf6550d9f 100644 --- a/tests/topotests/ospf6_topo2/r1/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r1/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r1-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.1 area 0.0.0.1 stub - interface r1-eth0 area 0.0.0.1 ! diff --git a/tests/topotests/ospf6_topo2/r2/ospf6d.conf b/tests/topotests/ospf6_topo2/r2/ospf6d.conf index 4a1d10693d..7567c9cd64 100644 --- a/tests/topotests/ospf6_topo2/r2/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r2/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,14 +27,17 @@ debug ospf6 asbr debug ospf6 nssa ! interface r2-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth2 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -42,7 +48,4 @@ router ospf6 default-information originate always metric 123 area 0.0.0.1 stub area 0.0.0.2 nssa - interface r2-eth0 area 0.0.0.1 - interface r2-eth1 area 0.0.0.0 - interface r2-eth2 area 0.0.0.2 ! diff --git a/tests/topotests/ospf6_topo2/r3/ospf6d.conf b/tests/topotests/ospf6_topo2/r3/ospf6d.conf index 5faeb70e56..0fb4e7e365 100644 --- a/tests/topotests/ospf6_topo2/r3/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r3/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,6 +27,7 @@ debug ospf6 asbr debug ospf6 nssa ! interface r3-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -31,5 +35,4 @@ router ospf6 ospf6 router-id 10.254.254.3 redistribute connected redistribute static - interface r3-eth0 area 0.0.0.0 ! diff --git a/tests/topotests/ospf6_topo2/r4/ospf6d.conf b/tests/topotests/ospf6_topo2/r4/ospf6d.conf index 04d763f6a8..91f8df440c 100644 --- a/tests/topotests/ospf6_topo2/r4/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r4/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r4-eth0 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.4 area 0.0.0.2 nssa - interface r4-eth0 area 0.0.0.2 ! diff --git a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py index 303bcd014d..eb8561c404 100644 --- a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py +++ b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py @@ -131,6 +131,8 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r4"]) + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet") def setup_module(mod): "Sets up the pytest environment" @@ -484,7 +486,7 @@ def test_area_filters(): pytest.skip(tgen.errors) # - # Configure import/export filters on r2 (ABR for area 1). + # Configure import/export filters on r2 (ABR for area 2). # config = """ configure terminal @@ -544,6 +546,102 @@ def test_area_filters(): expect_ospfv3_routes("r1", routes, wait=30, type="inter-area") +def test_nssa_range(): + """ + Test NSSA ABR ranges. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Configure new addresses on r4 and enable redistribution of connected + # routes. + config = """ + configure terminal + interface r4-stubnet + ipv6 address 2001:db8:1000::1/128 + ipv6 address 2001:db8:1000::2/128 + router ospf6 + redistribute connected + """ + tgen.gears["r4"].vtysh_cmd(config) + logger.info("Expecting NSSA-translated external routes to be added on r3") + routes = {"2001:db8:1000::1/128": {}, "2001:db8:1000::2/128": {}} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2") + + # Configure an NSSA range on r2 (ABR for area 2). + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting summarized routes to be removed from r3") + for route in ["2001:db8:1000::1/128", "2001:db8:1000::2/128"]: + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} summarized route still exists".format("r3", route) + assert result is None, assertmsg + logger.info("Expecting NSSA range to be added on r3") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":10, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Change the NSSA range cost. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 cost 1000 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA range to be updated with new cost") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":1000, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Configure the NSSA range to not be advertised. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 not-advertise + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA summary route to be removed") + route = "2001:db8:1000::/64" + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} NSSA summary route still exists".format("r3", route) + assert result is None, assertmsg + + # Remove the NSSA range. + config = """ + configure terminal + router ospf6 + no area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting previously summarized routes to be re-added") + routes = { + "2001:db8:1000::1/128": { + "metricType":2, + "metricCost":20, + }, + "2001:db8:1000::2/128": { + "metricType":2, + "metricCost":20, + }, + } + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + def teardown_module(_mod): "Teardown the pytest environment" tgen = get_topogen() diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py index 64dfa0c69d..f9fa55e275 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py @@ -669,89 +669,6 @@ def test_ospf_type5_summary_tc48_p0(request): result is True ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - step("Configure metric type as 1 in route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [{"action": "permit", "set": {"metric-type": "type-1"}}] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Un configure metric type from route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [ - { - "action": "permit", - "set": {"metric-type": "type-1"}, - "delete": True, - } - ] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Change rule from permit to deny in prefix list.") - pfx_list = { - "r0": { - "prefix_lists": { - "ipv4": { - "pf_list_1_ipv4": [ - {"seqid": 10, "network": "any", "action": "deny"} - ] - } - } - } - } - result = create_prefix_lists(tgen, pfx_list) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - write_test_footer(tc_name) 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/checkpatch.pl b/tools/checkpatch.pl index cf15d00796..d2eb20ce5b 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -409,6 +409,25 @@ our $Operators = qr{ }x; our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; +our $Iterators = qr{ + frr_each|frr_each_safe|frr_each_from| + frr_with_mutex|frr_with_privs| + LIST_FOREACH|LIST_FOREACH_SAFE| + SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR| + STAILQ_FOREACH|STAILQ_FOREACH_SAFE| + TAILQ_FOREACH|TAILQ_FOREACH_SAFE|TAILQ_FOREACH_REVERSE|TAILQ_FOREACH_REVERSE_SAFE| + RB_FOREACH|RB_FOREACH_SAFE|RB_FOREACH_REVERSE|RB_FOREACH_REVERSE_SAFE| + SPLAY_FOREACH| + FOR_ALL_INTERFACES|FOR_ALL_INTERFACES_ADDRESSES|JSON_FOREACH| + LY_FOR_KEYS|LY_LIST_FOR|LY_TREE_FOR|LY_TREE_DFS_BEGIN|LYD_TREE_DFS_BEGIN| + RE_DEST_FOREACH_ROUTE|RE_DEST_FOREACH_ROUTE_SAFE| + RNODE_FOREACH_RE|RNODE_FOREACH_RE_SAFE| + UPDGRP_FOREACH_SUBGRP|UPDGRP_FOREACH_SUBGRP_SAFE| + SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE| + SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE| + AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI| + LSDB_LOOP + }x; our $BasicType; our $NonptrType; @@ -1009,9 +1028,9 @@ sub top_of_kernel_tree { my ($root) = @_; my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", + "COPYING", "configure.ac", "Makefile.am", + "README.md", "doc", "lib", "vtysh", "watchfrr", "tests", + "zebra", "bgpd", "ospfd", "ospf6d", "isisd", "staticd", ); foreach my $check (@tree_check) { @@ -2655,8 +2674,8 @@ sub process { (defined($1) || defined($2))))) { $is_patch = 1; $reported_maintainer_file = 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + #WARN("FILE_PATH_CHANGES", + # "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); } # Check for wrappage within a valid hunk of the file @@ -4028,7 +4047,8 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__| + $Iterators)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open 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/frr_babeltrace.py b/tools/frr_babeltrace.py new file mode 100755 index 0000000000..27d830a119 --- /dev/null +++ b/tools/frr_babeltrace.py @@ -0,0 +1,266 @@ +#!/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) + +def parse_frr_bgp_evpn_mh_local_es_add_zrecv(event): + """ + bgp evpn local-es parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_del_zrecv(event): + """ + bgp evpn local-es parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv(event): + """ + bgp evpn local-es-evi parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv(event): + """ + bgp evpn local-es-evi parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_vni_add_zrecv(event): + """ + bgp evpn local-vni parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer_network_hex(unsigned int, mc_grp, mc_grp.s_addr) + """ + field_parsers = {"vtep": print_net_ipv4_addr, + "mc_grp": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_l3vni_add_zrecv(event): + """ + bgp evpn local-l3vni parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, svi_rmac, svi_rmac, sizeof(struct ethaddr)) + ctf_array(unsigned char, vrr_rmac, vrr_rmac, sizeof(struct ethaddr)) + """ + field_parsers = {"vtep": print_net_ipv4_addr, + "svi_rmac": print_mac, + "vrr_rmac": print_mac} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_macip_add_zrecv(event): + """ + bgp evpn local-mac-ip parser; raw format - + ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) + ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"ip": print_ip_addr, + "mac": print_mac, + "esi": print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_macip_del_zrecv(event): + """ + bgp evpn local-mac-ip del parser; raw format - + ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) + ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) + """ + field_parsers = {"ip": print_ip_addr, + "mac": 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, + "frr_bgp:evpn_mh_local_es_add_zrecv": + parse_frr_bgp_evpn_mh_local_es_add_zrecv, + "frr_bgp:evpn_mh_local_es_del_zrecv": + parse_frr_bgp_evpn_mh_local_es_del_zrecv, + "frr_bgp:evpn_mh_local_es_evi_add_zrecv": + parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv, + "frr_bgp:evpn_mh_local_es_evi_del_zrecv": + parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv, + "frr_bgp:evpn_local_vni_add_zrecv": + parse_frr_bgp_evpn_local_vni_add_zrecv, + "frr_bgp:evpn_local_l3vni_add_zrecv": + parse_frr_bgp_evpn_local_l3vni_add_zrecv, + "frr_bgp:evpn_local_macip_add_zrecv": + parse_frr_bgp_evpn_local_macip_add_zrecv, + "frr_bgp:evpn_local_macip_del_zrecv": + parse_frr_bgp_evpn_local_macip_del_zrecv, +} + + # 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/tools/subdir.am b/tools/subdir.am index e4b9ecd84f..64ca0bd514 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -21,6 +21,7 @@ sbin_SCRIPTS += \ tools/frrcommon.sh \ tools/frrinit.sh \ tools/generate_support_bundle.py \ + tools/frr_babeltrace.py \ tools/watchfrr.sh \ # end @@ -58,6 +59,7 @@ EXTRA_DIST += \ tools/frr.service \ tools/frr@.service \ tools/generate_support_bundle.py \ + tools/frr_babeltrace.py \ tools/multiple-bgpd.sh \ tools/rrcheck.pl \ tools/rrlookup.pl \ diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index beb7045a7d..53349452e6 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -3923,6 +3923,8 @@ void vtysh_uninit(void) void vtysh_init_vty(void) { + cmd_defer_tree(true); + /* Make vty structure. */ vty = vty_new(); vty->type = VTY_SHELL; 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_ioctl.c b/zebra/if_ioctl.c index 14d8ac442e..c3faf22d17 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -109,7 +109,8 @@ static int interface_list_ioctl(void) unsigned int size; ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); size = ifreq->ifr_addr.sa_len; if (size < sizeof(ifreq->ifr_addr)) @@ -119,7 +120,8 @@ static int interface_list_ioctl(void) } #else for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); ifreq++; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 28a64407e5..187cd10e9c 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -972,17 +972,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) link_nsid = ns_id_get_absolute(ns_id, link_nsid); } - /* Add interface. - * We add by index first because in some cases such as the master - * interface, we have the index before we have the name. Fixing - * back references on the slave interfaces is painful if not done - * this way, i.e. by creating by ifindex. - */ - ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */ - if_set_name(ifp, name); - ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; @@ -1089,7 +1081,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 +1091,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 +1120,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 +1129,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 +1160,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 +1284,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 */ @@ -1803,7 +1806,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (ifp == NULL) { /* unknown interface */ - ifp = if_get_by_name(name, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); } else { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) @@ -1832,6 +1835,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 +1904,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 +2061,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/interface.c b/zebra/interface.c index a68d00d55c..595862a6c9 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1616,7 +1616,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; zebra_if = ifp->info; @@ -1644,8 +1643,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) zebra_ptm_show_status(vty, NULL, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - vty_out(vty, " vrf: %s\n", vrf->name); + vty_out(vty, " vrf: %s\n", ifp->vrf->name); if (ifp->desc) vty_out(vty, " Description: %s\n", ifp->desc); @@ -1941,7 +1939,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; char buf[BUFSIZ]; json_object *json_if; @@ -1979,8 +1976,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, zebra_ptm_show_status(vty, json, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - json_object_string_add(json_if, "vrfName", vrf->name); + json_object_string_add(json_if, "vrfName", ifp->vrf->name); if (ifp->desc) json_object_string_add(json_if, "description", ifp->desc); @@ -4206,21 +4202,19 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp) static int if_config_write(struct vty *vty) { - struct vrf *vrf0; + struct vrf *vrf; struct interface *ifp; zebra_ptm_write(vty); - RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name) - FOR_ALL_INTERFACES (vrf0, ifp) { + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + FOR_ALL_INTERFACES (vrf, ifp) { struct zebra_if *if_data; struct listnode *addrnode; struct connected *ifc; struct prefix *p; - struct vrf *vrf; if_data = ifp->info; - vrf = vrf_lookup_by_id(ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) vty_frame(vty, "interface %s\n", ifp->name); 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/kernel_socket.c b/zebra/kernel_socket.c index d9c69ceb6d..2db3e6e904 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -443,7 +443,8 @@ static int ifan_read(struct if_announcemsghdr *ifan) __func__, ifan->ifan_index, ifan->ifan_name); /* Create Interface */ - ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT); + ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_set_index(ifp, ifan->ifan_index); if_get_metric(ifp); @@ -624,7 +625,8 @@ int ifm_read(struct if_msghdr *ifm) if (ifp == NULL) { /* Interface that zebra was not previously aware of, so * create. */ - ifp = if_create_name(ifname, VRF_DEFAULT); + ifp = if_get_by_name(ifname, VRF_DEFAULT, + VRF_DEFAULT_NAME); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: creating ifp for ifindex %d", __func__, ifm->ifm_index); 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 b125897fc4..6cb4cf5ca1 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); } } @@ -3688,8 +3680,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_evpn.c b/zebra/zebra_evpn.c index d5e043eea8..4006e1fed5 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -1423,8 +1423,24 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr, * REMOTE - if ES is not local */ if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) { - zebra_evpn_process_sync_macip_add(zevpn, macaddr, ipa_len, - ipaddr, flags, seq, esi); + struct zebra_evpn_es *es; + + es = zebra_evpn_es_find(esi); + if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) { + zebra_evpn_process_sync_macip_add(zevpn, macaddr, + ipa_len, ipaddr, + flags, seq, esi); + } else { + if (IS_ZEBRA_DEBUG_EVPN_MH_ES) { + char esi_str[ESI_STR_LEN]; + + esi_to_str(esi, esi_str, sizeof(esi_str)); + zlog_debug( + "Ignore sync-macip add; ES %s is not ready", + esi_str); + } + } + return; } diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index 472e53b730..c1bb19d4e5 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -1342,6 +1342,25 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, struct zebra_if *zif; struct interface *br_ifp; + /* If the ES-EVI doesn't exist defer install. When the ES-EVI is + * created we will attempt to install the mac entry again + */ + if (mac->es) { + struct zebra_evpn_es_evi *es_evi; + + es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn); + if (!es_evi) { + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + zlog_debug( + "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi", + caller, zevpn->vni, &mac->macaddr, + mac->es ? mac->es->esi_str : "-", + mac->flags, + set_inactive ? "inactive " : ""); + return -1; + } + } + /* get the access vlan from the vxlan_device */ zebra_evpn_mac_get_access_info(mac, &ifp, &vid); diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index e03cf9db06..3f7e6256fc 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -186,8 +186,8 @@ static void zebra_evpn_es_evi_free(struct zebra_evpn_es_evi *es_evi) } /* find the ES-EVI in the per-L2-VNI RB tree */ -static struct zebra_evpn_es_evi * -zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn) +struct zebra_evpn_es_evi *zebra_evpn_es_evi_find(struct zebra_evpn_es *es, + struct zebra_evpn *zevpn) { struct zebra_evpn_es_evi es_evi; @@ -229,6 +229,34 @@ static void zebra_evpn_local_es_evi_del(struct zebra_evpn_es *es, zebra_evpn_local_es_evi_do_del(es_evi); } +/* If there are any existing MAC entries for this es/zevpn we need + * to install it in the dataplane. + * + * Note: primary purpose of this is to handle es del/re-add windows where + * sync MAC entries may be added by bgpd before the es-evi membership is + * created in the dataplane and in zebra + */ +static void zebra_evpn_es_evi_mac_install(struct zebra_evpn_es_evi *es_evi) +{ + struct zebra_mac *mac; + struct listnode *node; + struct zebra_evpn_es *es = es_evi->es; + + if (listcount(es->mac_list) && IS_ZEBRA_DEBUG_EVPN_MH_ES) + zlog_debug("dp-mac install on es %s evi %d add", es->esi_str, + es_evi->zevpn->vni); + + for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) { + if (mac->zevpn != es_evi->zevpn) + continue; + + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + continue; + + zebra_evpn_sync_mac_dp_install(mac, false, false, __func__); + } +} + /* Create an ES-EVI if it doesn't already exist and tell BGP */ static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es, struct zebra_evpn *zevpn) @@ -250,6 +278,8 @@ static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es, listnode_add(zevpn->local_es_evi_list, &es_evi->l2vni_listnode); zebra_evpn_es_evi_re_eval_send_to_client(es_evi); + + zebra_evpn_es_evi_mac_install(es_evi); } } @@ -1050,15 +1080,15 @@ void zebra_evpn_if_cleanup(struct zebra_if *zif) vlanid_t vid; struct zebra_evpn_es *es; - if (!bf_is_inited(zif->vlan_bitmap)) - return; + if (bf_is_inited(zif->vlan_bitmap)) { + bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) + { + zebra_evpn_vl_mbr_deref(vid, zif); + } - bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) { - zebra_evpn_vl_mbr_deref(vid, zif); + bf_free(zif->vlan_bitmap); } - bf_free(zif->vlan_bitmap); - /* Delete associated Ethernet Segment */ es = zif->es_info.es; if (es) diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h index 853af7c4bc..af6832092b 100644 --- a/zebra/zebra_evpn_mh.h +++ b/zebra/zebra_evpn_mh.h @@ -387,5 +387,7 @@ extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if); extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es, struct interface *ifp, bool bypass); extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS); +extern struct zebra_evpn_es_evi * +zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn); #endif /* _ZEBRA_EVPN_MH_H */ diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index 5a02149611..30e74902aa 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -431,10 +431,10 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp, if (zif->zif_type == ZEBRA_IF_VXLAN && chgflags != ZEBRA_BRIDGE_NO_ACTION) { - if (ZEBRA_BRIDGE_MASTER_MAC_CHANGE) + if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_MAC_CHANGE); - if (ZEBRA_BRIDGE_MASTER_UP) + if (chgflags & ZEBRA_BRIDGE_MASTER_UP) zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE); } old_bridge_ifindex = zif->brslave_info.bridge_ifindex; diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 054015846f..2d25801590 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -249,8 +249,8 @@ static int zebra_ns_notify_read(struct thread *t) char buf[BUFSIZ]; ssize_t len; - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); len = read(fd_monitor, buf, sizeof(buf)); if (len < 0) { flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ, @@ -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( @@ -360,8 +359,8 @@ void zebra_ns_notify_init(void) "NS notify watch: failed to add watch (%s)", safe_strerror(errno)); } - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); } void zebra_ns_notify_close(void) 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..fcac3328c9 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; @@ -3891,14 +3890,16 @@ void rib_update(enum rib_update_event event) { struct rib_update_ctx *ctx; - ctx = rib_update_ctx_init(0, event); + if (thread_is_scheduled(t_rib_update_threads[event])) + return; + ctx = rib_update_ctx_init(0, event); ctx->vrf_all = true; - if (!thread_add_event(zrouter.master, rib_update_handler, ctx, 0, - &t_rib_update_threads[event])) - rib_update_ctx_fini(&ctx); /* Already scheduled */ - else if (IS_ZEBRA_DEBUG_EVENT) + thread_add_event(zrouter.master, rib_update_handler, ctx, 0, + &t_rib_update_threads[event]); + + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__, rib_update_event2str(event)); } 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..5b79de9697 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; @@ -775,6 +776,13 @@ static void show_nexthop_json_helper(json_object *json_nexthop, break; } + /* This nexthop is a resolver for the parent nexthop. + * Set resolver flag for better clarity and delimiter + * in flat list of nexthops in json. + */ + if (nexthop->rparent) + json_object_boolean_true_add(json_nexthop, "resolver"); + if (nexthop->vrf_id != re->vrf_id) json_object_string_add(json_nexthop, "vrf", vrf_id_to_name(nexthop->vrf_id)); @@ -965,6 +973,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 +1339,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 +1348,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 +1362,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 +1381,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 +1720,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 +1740,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 +1761,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 +4293,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 +4466,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: |
