diff options
53 files changed, 1664 insertions, 1056 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index 22401f0017..55a86f99fc 100644 --- a/bgpd/bgp_addpath.c +++ b/bgpd/bgp_addpath.c @@ -193,7 +193,7 @@ static void bgp_addpath_flush_type(struct bgp *bgp, afi_t afi, safi_t safi, idalloc_drain_pool( bgp->tx_addpath.id_allocators[afi][safi][addpath_type], &(rn->tx_addpath.free_ids[addpath_type])); - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (pi->tx_addpath.addpath_tx_id[addpath_type] != IDALLOC_INVALID) { idalloc_free( @@ -256,7 +256,7 @@ static void bgp_addpath_populate_type(struct bgp *bgp, afi_t afi, safi_t safi, for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) - for (bi = rn->info; bi; bi = bi->next) + for (bi = bgp_node_get_bgp_path_info(rn); bi; bi = bi->next) bgp_addpath_populate_path(allocator, bi, addpath_type); } @@ -396,7 +396,7 @@ void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_node *bn, afi_t afi, continue; /* Free Unused IDs back to the pool.*/ - for (pi = bn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(bn); pi; pi = pi->next) { if (pi->tx_addpath.addpath_tx_id[i] != IDALLOC_INVALID && !bgp_addpath_tx_path(i, pi)) { idalloc_free_to_pool(pool_ptr, @@ -407,7 +407,7 @@ void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_node *bn, afi_t afi, } /* Give IDs to paths that need them (pulling from the pool) */ - for (pi = bn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(bn); pi; pi = pi->next) { if (pi->tx_addpath.addpath_tx_id[i] == IDALLOC_INVALID && bgp_addpath_tx_path(i, pi)) { pi->tx_addpath.addpath_tx_id[i] = diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 3d1880ca48..751140850a 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -410,7 +410,7 @@ static unsigned int bgp_dump_routes_func(int afi, int first_run, table = bgp->rib[afi][SAFI_UNICAST]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - path = rn->info; + path = bgp_node_get_bgp_path_info(rn); while (path) { path = bgp_dump_route_node_record(afi, rn, path, seq); seq++; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ac5880938f..da91f4623c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1232,7 +1232,8 @@ static int evpn_route_is_def_gw(struct bgp *bgp, struct bgp_node *rn) struct bgp_path_info *local_pi = NULL; local_pi = NULL; - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -1255,7 +1256,8 @@ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn) struct bgp_path_info *local_pi; local_pi = NULL; - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -1292,7 +1294,8 @@ static int update_evpn_type4_route_entry(struct bgp *bgp, struct evpnes *es, evp = (struct prefix_evpn *)&rn->p; /* locate the local and remote entries if any */ - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -1303,7 +1306,7 @@ static int update_evpn_type4_route_entry(struct bgp *bgp, struct evpnes *es, remote_pi = tmp_pi; } - /* we don't expect to see a remote_pi at this point. + /* we don't expect to see a remote_ri at this point. * An ES route has esi + vtep_ip as the key, * We shouldn't see the same route from any other vtep. */ @@ -1449,7 +1452,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, *route_changed = 0; /* locate the local route entry if any */ - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp_def->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -1587,7 +1591,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, /* See if this is an update of an existing route, or a new add. */ local_pi = NULL; - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -1726,7 +1731,8 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp, bgp_path_info_reap(rn, local_pi); /* tell zebra to re-add the best remote path */ - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); + tmp_pi; tmp_pi = tmp_pi->next) { if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) { curr_select = tmp_pi; break; @@ -1863,7 +1869,8 @@ static void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, *pi = NULL; /* Now, find matching route. */ - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -2034,7 +2041,8 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) continue; /* Identify local route. */ - for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi; + tmp_pi = tmp_pi->next) { if (tmp_pi->peer == bgp->peer_self && tmp_pi->type == ZEBRA_ROUTE_BGP && tmp_pi->sub_type == BGP_ROUTE_STATIC) @@ -2125,8 +2133,8 @@ static int delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) safi = SAFI_EVPN; rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd); - if (rdrn && rdrn->info) { - table = (struct bgp_table *)rdrn->info; + if (rdrn && bgp_node_has_bgp_path_info_data(rdrn)) { + table = bgp_node_get_bgp_table_info(rdrn); for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; @@ -2195,8 +2203,8 @@ static int delete_all_es_routes(struct bgp *bgp, struct evpnes *es) /* Walk this ES's route table and delete all routes. */ for (rn = bgp_table_top(es->route_table); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); - pi = nextpi) { + for (pi = bgp_node_get_bgp_path_info(rn); + (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { bgp_path_info_delete(rn, pi); bgp_path_info_reap(rn, pi); } @@ -2216,8 +2224,8 @@ static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) /* Walk this VNI's route table and delete all routes. */ for (rn = bgp_table_top(vpn->route_table); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); - pi = nextpi) { + for (pi = bgp_node_get_bgp_path_info(rn); + (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { bgp_path_info_delete(rn, pi); bgp_path_info_reap(rn, pi); } @@ -2353,7 +2361,7 @@ static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, rn = bgp_node_get(es->route_table, (struct prefix *)p); /* Check if route entry is already present. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2454,7 +2462,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); /* Check if route entry is already present. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2530,7 +2538,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, rn = bgp_node_get(vpn->route_table, (struct prefix *)p); /* Check if route entry is already present. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2602,7 +2610,7 @@ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, return 0; /* Find matching route entry. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2667,7 +2675,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, return 0; /* Find matching route entry. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2708,7 +2716,7 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, return 0; /* Find matching route entry. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->extra && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; @@ -2901,14 +2909,15 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, */ for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next(rd_rn)) { - table = (struct bgp_table *)(rd_rn->info); + table = bgp_node_get_bgp_table_info(rd_rn); if (!table) continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { /* * Consider "valid" remote routes applicable for * this ES. @@ -2973,7 +2982,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) */ for (rd_rn = bgp_table_top(bgp_def->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next(rd_rn)) { - table = (struct bgp_table *)(rd_rn->info); + table = bgp_node_get_bgp_table_info(rd_rn); if (!table) continue; @@ -2991,7 +3000,8 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) || is_evpn_prefix_ipaddr_v6(evp))) continue; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { /* Consider "valid" remote routes applicable for * this VRF. */ @@ -3056,7 +3066,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, /* EVPN routes are a 2-level table. */ for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next(rd_rn)) { - table = (struct bgp_table *)(rd_rn->info); + table = bgp_node_get_bgp_table_info(rd_rn); if (!table) continue; @@ -3066,7 +3076,8 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, if (evp->prefix.route_type != rtype) continue; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { /* Consider "valid" remote routes applicable for * this VNI. */ if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) @@ -3501,7 +3512,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); if (!rn) /* unexpected */ return 0; - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) @@ -3531,7 +3542,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) @@ -4229,7 +4240,7 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { /* Only care about "selected" routes - non-imported. */ /* TODO: Support for AddPath for EVPN. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (!pi->extra || !pi->extra->parent)) { bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, @@ -4301,7 +4312,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, * attribute. Also, we only consider "non-imported" routes. * TODO: Support for AddPath for EVPN. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (!pi->extra || !pi->extra->parent)) { @@ -5263,13 +5274,14 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) /* EVPN routes are a 2-level table. */ for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next(rd_rn)) { - table = (struct bgp_table *)(rd_rn->info); + table = bgp_node_get_bgp_table_info(rd_rn); if (!table) continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { /* Consider "valid" remote routes applicable for * this VNI. */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index c6b08d1a2f..c6db45d7d3 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -556,7 +556,8 @@ static void show_esi_routes(struct bgp *bgp, if (json) json_prefix = json_object_new_object(); - if (rn->info) { + pi = bgp_node_get_bgp_path_info(rn); + if (pi) { /* Overall header/legend displayed once. */ if (header) { bgp_evpn_show_route_header(vty, bgp, @@ -573,7 +574,7 @@ static void show_esi_routes(struct bgp *bgp, /* For EVPN, the prefix is displayed for each path (to fit in * with code that already exists). */ - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { json_object *json_path = NULL; if (json) @@ -643,7 +644,8 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, if (json) json_prefix = json_object_new_object(); - if (rn->info) { + pi = bgp_node_get_bgp_path_info(rn); + if (pi) { /* Overall header/legend displayed once. */ if (header) { bgp_evpn_show_route_header(vty, bgp, @@ -660,7 +662,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, /* For EVPN, the prefix is displayed for each path (to fit in * with code that already exists). */ - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { json_object *json_path = NULL; if (vtep_ip.s_addr @@ -1039,14 +1041,16 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) == NULL) + table = bgp_node_get_bgp_table_info(rn); + if (!table) continue; rd_header = 1; tbl_ver = table->version; for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) - for (pi = rm->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rm); pi; + pi = pi->next) { total_count++; if (type == bgp_show_type_neighbor) { union sockunion *su = output_arg; @@ -2036,7 +2040,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, /* See if route exists. */ build_evpn_type3_prefix(&p, orig_ip); rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); - if (!rn || !rn->info) { + if (!rn || !bgp_node_has_bgp_path_info_data(rn)) { if (!json) vty_out(vty, "%% Network not in table\n"); return; @@ -2049,7 +2053,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json); /* Display each path for this prefix. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { json_object *json_path = NULL; if (json) @@ -2106,7 +2110,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, /* See if route exists. Look for both non-sticky and sticky. */ build_evpn_type2_prefix(&p, mac, ip); rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); - if (!rn || !rn->info) { + if (!rn || !bgp_node_has_bgp_path_info_data(rn)) { if (!json) vty_out(vty, "%% Network not in table\n"); return; @@ -2119,7 +2123,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json); /* Display each path for this prefix. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { json_object *json_path = NULL; if (json) @@ -2210,7 +2214,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, build_evpn_type2_prefix(&p, mac, ip); rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, (struct prefix *)&p, prd); - if (!rn || !rn->info) { + if (!rn || !bgp_node_has_bgp_path_info_data(rn)) { if (!json) vty_out(vty, "%% Network not in table\n"); return; @@ -2226,7 +2230,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, json_paths = json_object_new_array(); /* Display each path for this prefix. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { json_object *json_path = NULL; if (json) @@ -2281,7 +2285,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, if (!rd_rn) return; - table = (struct bgp_table *)rd_rn->info; + table = bgp_node_get_bgp_table_info(rd_rn); if (table == NULL) return; @@ -2307,7 +2311,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, if (json) json_prefix = json_object_new_object(); - if (rn->info) { + pi = bgp_node_get_bgp_path_info(rn); + if (pi) { /* RD header and legend - once overall. */ if (rd_header && !json) { vty_out(vty, @@ -2330,7 +2335,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, json_paths = json_object_new_array(); /* Display each path for this prefix. */ - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { json_object *json_path = NULL; if (json) @@ -2404,7 +2409,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, int add_rd_to_json = 0; uint64_t tbl_ver; - table = (struct bgp_table *)rd_rn->info; + table = bgp_node_get_bgp_table_info(rd_rn); if (table == NULL) continue; @@ -2435,7 +2440,8 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, if (type && evp->prefix.route_type != type) continue; - if (rn->info) { + pi = bgp_node_get_bgp_path_info(rn); + if (pi) { /* Overall header/legend displayed once. */ if (header) { bgp_evpn_show_route_header(vty, bgp, @@ -2467,7 +2473,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, * fit in * with code that already exists). */ - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { json_object *json_path = NULL; path_cnt++; add_prefix_to_json = 1; diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 9c230d1126..26f0fffb37 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -380,13 +380,14 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, return CMD_SUCCESS; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - if (rn->info == NULL) + pi = bgp_node_get_bgp_path_info(rn); + if (pi == NULL) continue; if (use_json) { json_paths = json_object_new_array(); display = NLRI_STRING_FORMAT_JSON; } - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { total_count++; route_vty_out_flowspec(vty, &rn->p, pi, display, json_paths); @@ -543,11 +544,11 @@ extern int bgp_flowspec_display_match_per_ip(afi_t afi, struct bgp_table *rib, continue; if (bgp_flowspec_contains_prefix(prefix, match, prefix_check)) { - route_vty_out_flowspec(vty, &rn->p, - rn->info, use_json ? - NLRI_STRING_FORMAT_JSON : - NLRI_STRING_FORMAT_LARGE, - json_paths); + route_vty_out_flowspec( + vty, &rn->p, bgp_node_get_bgp_path_info(rn), + use_json ? NLRI_STRING_FORMAT_JSON + : NLRI_STRING_FORMAT_LARGE, + json_paths); display++; } } diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index d4204126e1..cf91faf964 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -500,7 +500,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ /* * match parent */ - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { if (bpi->extra && bpi->extra->parent == parent) break; } @@ -919,11 +919,13 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p, &(bgp_vrf->vpn_policy[afi].tovpn_rd)); + if (!bn) + return; /* * vrf -> vpn * match original bpi imported from */ - for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { if (bpi->extra && bpi->extra->parent == path_vrf) { break; } @@ -959,7 +961,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ struct bgp_path_info *bpi; /* This is the per-RD table of prefixes */ - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); if (!table) continue; @@ -968,13 +970,14 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ char buf[PREFIX2STR_BUFFER]; - if (debug && bn->info) { + bpi = bgp_node_get_bgp_path_info(bn); + if (debug && bpi) { zlog_debug( "%s: looking at prefix %s", __func__, prefix2str(&bn->p, buf, sizeof(buf))); } - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (; bpi; bpi = bpi->next) { if (debug) zlog_debug("%s: type %d, sub_type %d", __func__, bpi->type, @@ -1017,7 +1020,8 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ if (debug) zlog_debug("%s: node=%p", __func__, bn); - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; + bpi = bpi->next) { if (debug) zlog_debug( "%s: calling vpn_leak_from_vrf_update", @@ -1299,7 +1303,9 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ bgp->name_pretty); bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); - for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { + + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; + bpi = bpi->next) { if (bpi->extra && (struct bgp_path_info *)bpi->extra->parent == path_vpn) { @@ -1335,7 +1341,8 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */ for (bn = bgp_table_top(bgp_vrf->rib[afi][safi]); bn; bn = bgp_route_next(bn)) { - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; + bpi = bpi->next) { if (bpi->extra && bpi->extra->bgp_orig != bgp_vrf) { /* delete route */ @@ -1374,14 +1381,15 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ memcpy(prd.val, prn->p.u.val, 8); /* This is the per-RD table of prefixes */ - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); if (!table) continue; for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) { - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; + bpi = bpi->next) { if (bpi->extra && bpi->extra->bgp_orig == bgp_vrf) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 1cb7e4c5e1..30d786fcda 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -44,8 +44,6 @@ #include "bgpd/bgp_damp.h" #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_vty.h" -#include "zebra/rib.h" -#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String"); @@ -83,7 +81,7 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table) struct bgp_nexthop_cache *bnc; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) continue; @@ -94,7 +92,7 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table) } bnc_free(bnc); - bgp_nexthop_set_node_info(rn, NULL); + bgp_node_set_bgp_nexthop_info(rn, NULL); bgp_unlock_node(rn); } } @@ -351,14 +349,14 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) rn = bgp_node_get(bgp->connected_table[AFI_IP], (struct prefix *)&p); - bc = bgp_connected_get_node_info(rn); + bc = bgp_node_get_bgp_connected_ref_info(rn); if (bc) bc->refcnt++; else { bc = XCALLOC(MTYPE_BGP_CONN, sizeof(struct bgp_connected_ref)); bc->refcnt = 1; - bgp_connected_set_node_info(rn, bc); + bgp_node_set_bgp_connected_ref_info(rn, bc); } for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { @@ -384,14 +382,14 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) rn = bgp_node_get(bgp->connected_table[AFI_IP6], (struct prefix *)&p); - bc = bgp_connected_get_node_info(rn); + bc = bgp_node_get_bgp_connected_ref_info(rn); if (bc) bc->refcnt++; else { bc = XCALLOC(MTYPE_BGP_CONN, sizeof(struct bgp_connected_ref)); bc->refcnt = 1; - bgp_connected_set_node_info(rn, bc); + bgp_node_set_bgp_connected_ref_info(rn, bc); } } } @@ -428,11 +426,11 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) if (!rn) return; - bc = bgp_connected_get_node_info(rn); + bc = bgp_node_get_bgp_connected_ref_info(rn); bc->refcnt--; if (bc->refcnt == 0) { XFREE(MTYPE_BGP_CONN, bc); - bgp_connected_set_node_info(rn, NULL); + bgp_node_set_bgp_connected_ref_info(rn, NULL); } bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -444,14 +442,14 @@ static void bgp_connected_cleanup(struct route_table *table, struct bgp_connected_ref *bc; struct bgp_node *bn = bgp_node_from_rnode(rn); - bc = bgp_connected_get_node_info(bn); + bc = bgp_node_get_bgp_connected_ref_info(bn); if (!bc) return; bc->refcnt--; if (bc->refcnt == 0) { XFREE(MTYPE_BGP_CONN, bc); - bgp_connected_set_node_info(bn, NULL); + bgp_node_set_bgp_connected_ref_info(bn, NULL); } } @@ -603,7 +601,7 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next(rn)) { - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) continue; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index c5d12a5706..b6ef5a55c5 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -95,7 +95,7 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc) } unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); - bgp_nexthop_set_node_info(bnc->node, NULL); + bgp_node_set_bgp_nexthop_info(bnc->node, NULL); bgp_unlock_node(bnc->node); bnc->node = NULL; bnc_free(bnc); @@ -126,7 +126,7 @@ void bgp_unlink_nexthop_by_peer(struct peer *peer) rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p); - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) return; @@ -183,10 +183,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, else rn = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p); - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) { bnc = bnc_new(); - bgp_nexthop_set_node_info(rn, bnc); + bgp_node_set_bgp_nexthop_info(rn, bnc); bnc->node = rn; bnc->bgp = bgp_nexthop; bgp_lock_node(rn); @@ -293,7 +293,7 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) return; } - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) { if (BGP_DEBUG(nht, NHT)) zlog_debug("Cannot find connected NHT node for peer %s on route_node as expected", @@ -318,7 +318,7 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) zlog_debug("Freeing connected NHT node %p for peer %s", bnc, peer->host); unregister_zebra_rnh(bnc, 0); - bgp_nexthop_set_node_info(bnc->node, NULL); + bgp_node_set_bgp_nexthop_info(bnc->node, NULL); bgp_unlock_node(bnc->node); bnc_free(bnc); } @@ -371,7 +371,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) return; } - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) { if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; @@ -510,7 +510,7 @@ void bgp_cleanup_nexthops(struct bgp *bgp) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next(rn)) { - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) continue; @@ -829,7 +829,7 @@ void bgp_nht_register_nexthops(struct bgp *bgp) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next(rn)) { - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) continue; @@ -869,7 +869,7 @@ void bgp_nht_register_enhe_capability_interfaces(struct peer *peer) if (!rn) return; - bnc = bgp_nexthop_get_node_info(rn); + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) return; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8cefb3ff39..47c04c4963 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -120,11 +120,12 @@ struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, || (safi == SAFI_EVPN)) { prn = bgp_node_get(table, (struct prefix *)prd); - if (prn->info == NULL) - prn->info = bgp_table_init(table->bgp, afi, safi); + if (!bgp_node_has_bgp_path_info_data(prn)) + bgp_node_set_bgp_table_info( + prn, bgp_table_init(table->bgp, afi, safi)); else bgp_unlock_node(prn); - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); } rn = bgp_node_get(table, p); @@ -152,12 +153,12 @@ struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, if (!prn) return NULL; - if (prn->info == NULL) { + if (!bgp_node_has_bgp_path_info_data(prn)) { bgp_unlock_node(prn); return NULL; } - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); } rn = bgp_node_lookup(table, p); @@ -291,13 +292,13 @@ void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi) { struct bgp_path_info *top; - top = rn->info; + top = bgp_node_get_bgp_path_info(rn); - pi->next = rn->info; + pi->next = top; pi->prev = NULL; if (top) top->prev = pi; - rn->info = pi; + bgp_node_set_bgp_path_info(rn, pi); bgp_path_info_lock(pi); bgp_lock_node(rn); @@ -313,7 +314,7 @@ void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi) if (pi->prev) pi->prev->next = pi->next; else - rn->info = pi->next; + bgp_node_set_bgp_path_info(rn, pi->next); bgp_path_info_mpath_dequeue(pi); bgp_path_info_unlock(pi); @@ -1895,11 +1896,13 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { /* Clear BGP_PATH_DMED_SELECTED for all paths */ - for (pi1 = rn->info; pi1; pi1 = pi1->next) + for (pi1 = bgp_node_get_bgp_path_info(rn); pi1; + pi1 = pi1->next) bgp_path_info_unset_flag(rn, pi1, BGP_PATH_DMED_SELECTED); - for (pi1 = rn->info; pi1; pi1 = pi1->next) { + for (pi1 = bgp_node_get_bgp_path_info(rn); pi1; + pi1 = pi1->next) { if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK)) continue; if (BGP_PATH_HOLDDOWN(pi1)) @@ -1965,8 +1968,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, /* Check old selected route and new selected route. */ old_select = NULL; new_select = NULL; - for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); - pi = nextpi) { + for (pi = bgp_node_get_bgp_path_info(rn); + (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) old_select = pi; @@ -2030,8 +2033,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, } if (do_mpath && new_select) { - for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); - pi = nextpi) { + for (pi = bgp_node_get_bgp_path_info(rn); + (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { if (debug) bgp_path_info_path_with_addpath_rx_str( @@ -2151,7 +2154,7 @@ void bgp_zebra_clear_route_change_flags(struct bgp_node *rn) { struct bgp_path_info *pi; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) continue; UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED); @@ -2741,8 +2744,8 @@ static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi, prn = bgp_node_get(peer->bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); + if (bgp_node_has_bgp_path_info_data(prn)) { + table = bgp_node_get_bgp_table_info(prn); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( peer->bgp, prd, table, &rn->p, pi); @@ -2948,7 +2951,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, bgp_adj_in_set(rn, peer, attr, addpath_id); /* Check previously received route. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == peer && pi->type == type && pi->sub_type == sub_type && pi->addpath_rx_id == addpath_id) @@ -3172,8 +3175,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); + if (bgp_node_has_bgp_path_info_data(prn)) { + table = bgp_node_get_bgp_table_info(prn); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, pi); @@ -3322,8 +3325,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); + if (bgp_node_has_bgp_path_info_data(prn)) { + table = bgp_node_get_bgp_table_info(prn); vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, pi); @@ -3459,8 +3462,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, struct bgp_table *table = NULL; prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); + if (bgp_node_has_bgp_path_info_data(prn)) { + table = bgp_node_get_bgp_table_info(prn); vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, new); @@ -3611,7 +3614,7 @@ int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* Lookup withdrawn route. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == peer && pi->type == type && pi->sub_type == sub_type && pi->addpath_rx_id == addpath_id) @@ -3765,7 +3768,8 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, if (ain->peer != peer) continue; - struct bgp_path_info *pi = rn->info; + struct bgp_path_info *pi = + bgp_node_get_bgp_path_info(rn); uint32_t num_labels = 0; mpls_label_t *label_pnt = NULL; @@ -3799,9 +3803,11 @@ void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi) bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL); else for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; - rn = bgp_route_next(rn)) - if ((table = rn->info) != NULL) { + rn = bgp_route_next(rn)) { + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { struct prefix_rd prd; + prd.family = AF_UNSPEC; prd.prefixlen = 64; memcpy(&prd.val, rn->p.u.val, 8); @@ -3809,6 +3815,7 @@ void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi) bgp_soft_reconfig_table(peer, afi, safi, table, &prd); } + } } @@ -3832,7 +3839,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) /* It is possible that we have multiple paths for a prefix from a peer * if that peer is using AddPath. */ - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (pi->peer != peer) continue; @@ -3971,7 +3978,7 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, ain = ain_next; } - for (pi = rn->info; pi; pi = next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) { next = pi->next; if (pi->peer != peer) continue; @@ -4028,9 +4035,13 @@ void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi) bgp_clear_route_table(peer, afi, safi, NULL); else for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; - rn = bgp_route_next(rn)) - if ((table = rn->info) != NULL) - bgp_clear_route_table(peer, afi, safi, table); + rn = bgp_route_next(rn)) { + table = bgp_node_get_bgp_table_info(rn); + if (!table) + continue; + + bgp_clear_route_table(peer, afi, safi, table); + } /* unlock if no nodes got added to the clear-node-queue. */ if (!peer->clear_node_queue->thread) @@ -4090,12 +4101,14 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) struct bgp_node *rm; /* look for neighbor in tables */ - if ((table = rn->info) == NULL) + table = bgp_node_get_bgp_table_info(rn); + if (!table) continue; for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) - for (pi = rm->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rm); pi; + pi = pi->next) { if (pi->peer != peer) continue; if (!CHECK_FLAG(pi->flags, @@ -4109,7 +4122,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) } else { for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { if (pi->peer != peer) continue; if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE)) @@ -4128,7 +4142,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, struct bgp_path_info *next; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - for (pi = rn->info; pi; pi = next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) { next = pi->next; if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && pi->type == ZEBRA_ROUTE_BGP @@ -4149,6 +4163,7 @@ void bgp_cleanup_routes(struct bgp *bgp) { afi_t afi; struct bgp_node *rn; + struct bgp_table *table; for (afi = AFI_IP; afi < AFI_MAX; ++afi) { if (afi == AFI_L2VPN) @@ -4163,26 +4178,22 @@ void bgp_cleanup_routes(struct bgp *bgp) safi = SAFI_MPLS_VPN; for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info) { - bgp_cleanup_table(bgp, - (struct bgp_table *)(rn->info), - safi); - bgp_table_finish((struct bgp_table **)&( - rn->info)); - rn->info = NULL; + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { + bgp_cleanup_table(bgp, table, safi); + bgp_table_finish(&table); + bgp_node_set_bgp_table_info(rn, NULL); bgp_unlock_node(rn); } } safi = SAFI_ENCAP; for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info) { - bgp_cleanup_table(bgp, - (struct bgp_table *)(rn->info), - safi); - bgp_table_finish((struct bgp_table **)&( - rn->info)); - rn->info = NULL; + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { + bgp_cleanup_table(bgp, table, safi); + bgp_table_finish(&table); + bgp_node_set_bgp_table_info(rn, NULL); bgp_unlock_node(rn); } } @@ -4190,12 +4201,11 @@ void bgp_cleanup_routes(struct bgp *bgp) } for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; rn = bgp_route_next(rn)) { - if (rn->info) { - bgp_cleanup_table(bgp, - (struct bgp_table *)(rn->info), - SAFI_EVPN); - bgp_table_finish((struct bgp_table **)&(rn->info)); - rn->info = NULL; + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { + bgp_cleanup_table(bgp, table, SAFI_EVPN); + bgp_table_finish(&table); + bgp_node_set_bgp_table_info(rn, NULL); bgp_unlock_node(rn); } } @@ -4458,7 +4468,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, attr_new = bgp_attr_intern(&attr); } - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) break; @@ -4626,7 +4636,7 @@ void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi, rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); /* Check selected route and self inserted route. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) break; @@ -4661,7 +4671,7 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p, rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); /* Check selected route and self inserted route. */ - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) break; @@ -4771,7 +4781,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, attr_new = bgp_attr_intern(&attr); } - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) break; @@ -4895,7 +4905,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, return CMD_WARNING_CONFIG_FAILED; } - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); if ((label_index != BGP_INVALID_LABEL_INDEX) && (label_index != bgp_static->label_index)) { @@ -4917,7 +4927,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, /* Clear configuration. */ bgp_static_free(bgp_static); - bgp_static_set_node_info(rn, NULL); + bgp_node_set_bgp_static_info(rn, NULL); bgp_unlock_node(rn); bgp_unlock_node(rn); } else { @@ -4925,7 +4935,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, /* Set BGP static route configuration. */ rn = bgp_node_get(bgp->route[afi][safi], &p); - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); if (bgp_static) { /* Configuration change. */ /* Label index cannot be changed. */ @@ -4976,7 +4986,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, bgp_static->rmap.map = route_map_lookup_by_name(rmap); } - bgp_static_set_node_info(rn, bgp_static); + bgp_node_set_bgp_static_info(rn, bgp_static); } bgp_static->valid = 1; @@ -5002,25 +5012,27 @@ void bgp_static_add(struct bgp *bgp) FOREACH_AFI_SAFI (afi, safi) for (rn = bgp_table_top(bgp->route[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info == NULL) + if (!bgp_node_has_bgp_path_info_data(rn)) continue; if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { - table = rn->info; + table = bgp_node_get_bgp_table_info(rn); for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { bgp_static = - bgp_static_get_node_info(rm); + bgp_node_get_bgp_static_info( + rm); bgp_static_update_safi(bgp, &rm->p, bgp_static, afi, safi); } } else { - bgp_static_update(bgp, &rn->p, - bgp_static_get_node_info(rn), - afi, safi); + bgp_static_update( + bgp, &rn->p, + bgp_node_get_bgp_static_info(rn), afi, + safi); } } } @@ -5039,29 +5051,30 @@ void bgp_static_delete(struct bgp *bgp) FOREACH_AFI_SAFI (afi, safi) for (rn = bgp_table_top(bgp->route[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info == NULL) + if (!bgp_node_has_bgp_path_info_data(rn)) continue; if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { - table = rn->info; + table = bgp_node_get_bgp_table_info(rn); for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { bgp_static = - bgp_static_get_node_info(rm); + bgp_node_get_bgp_static_info( + rm); bgp_static_withdraw_safi( bgp, &rm->p, AFI_IP, safi, (struct prefix_rd *)&rn->p); bgp_static_free(bgp_static); - bgp_static_set_node_info(rn, NULL); + bgp_node_set_bgp_static_info(rn, NULL); bgp_unlock_node(rn); } } else { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); bgp_static_withdraw(bgp, &rn->p, afi, safi); bgp_static_free(bgp_static); - bgp_static_set_node_info(rn, NULL); + bgp_node_set_bgp_static_info(rn, NULL); bgp_unlock_node(rn); } } @@ -5081,23 +5094,24 @@ void bgp_static_redo_import_check(struct bgp *bgp) FOREACH_AFI_SAFI (afi, safi) { for (rn = bgp_table_top(bgp->route[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info == NULL) + if (!bgp_node_has_bgp_path_info_data(rn)) continue; if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { - table = rn->info; + table = bgp_node_get_bgp_table_info(rn); for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { bgp_static = - bgp_static_get_node_info(rm); + bgp_node_get_bgp_static_info( + rm); bgp_static_update_safi(bgp, &rm->p, bgp_static, afi, safi); } } else { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); bgp_static_update(bgp, &rn->p, bgp_static, afi, safi); } @@ -5115,7 +5129,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi, table = bgp->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (pi->peer == bgp->peer_self && ((pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_STATIC) @@ -5222,15 +5236,16 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, } } prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); - if (prn->info == NULL) - prn->info = bgp_table_init(bgp, afi, safi); + if (!bgp_node_has_bgp_path_info_data(prn)) + bgp_node_set_bgp_table_info(prn, + bgp_table_init(bgp, afi, safi)); else bgp_unlock_node(prn); - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); rn = bgp_node_get(table, &p); - if (rn->info) { + if (bgp_node_has_bgp_path_info_data(rn)) { vty_out(vty, "%% Same network configuration exists\n"); bgp_unlock_node(rn); } else { @@ -5269,7 +5284,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, if (gwip) prefix_copy(&bgp_static->gatewayIp, &gw_ip); } - bgp_static_set_node_info(rn, bgp_static); + bgp_node_set_bgp_static_info(rn, bgp_static); bgp_static->valid = 1; bgp_static_update_safi(bgp, &p, bgp_static, afi, safi); @@ -5320,20 +5335,21 @@ int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, } prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); - if (prn->info == NULL) - prn->info = bgp_table_init(bgp, afi, safi); + if (!bgp_node_has_bgp_path_info_data(prn)) + bgp_node_set_bgp_table_info(prn, + bgp_table_init(bgp, afi, safi)); else bgp_unlock_node(prn); - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); rn = bgp_node_lookup(table, &p); if (rn) { bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd); - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); bgp_static_free(bgp_static); - bgp_static_set_node_info(rn, NULL); + bgp_node_set_bgp_static_info(rn, NULL); bgp_unlock_node(rn); bgp_unlock_node(rn); } else @@ -5553,13 +5569,13 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, { struct bgp_node *rn; struct bgp_table *table; - struct bgp_path_info *pi, *new; + struct bgp_path_info *pi, *orig, *new; table = bgp->rib[afi][safi]; rn = bgp_node_get(table, p); - for (pi = rn->info; pi; pi = pi->next) + for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_AGGREGATE) break; @@ -5569,7 +5585,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, * If the aggregate information has not changed * no need to re-install it again. */ - if (bgp_aggregate_info_same(rn->info, origin, aspath, community, + if (bgp_aggregate_info_same(orig, origin, aspath, community, ecommunity, lcommunity)) { bgp_unlock_node(rn); @@ -5604,7 +5620,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, bgp_path_info_add(rn, new); bgp_process(bgp, rn, afi, safi); } else { - for (pi = rn->info; pi; pi = pi->next) + for (pi = orig; pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP && pi->sub_type == BGP_ROUTE_AGGREGATE) @@ -5662,7 +5678,7 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, match = 0; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) continue; @@ -5854,7 +5870,7 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, continue; match = 0; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) continue; @@ -5904,7 +5920,7 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, /* Aggregate address configuration check. */ for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { - aggregate = bgp_aggregate_get_node_info(rn); + aggregate = bgp_node_get_bgp_aggregate_info(rn); if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL, @@ -5935,7 +5951,7 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, /* Aggregate address configuration check. */ for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { - aggregate = bgp_aggregate_get_node_info(rn); + aggregate = bgp_node_get_bgp_aggregate_info(rn); if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del, @@ -5974,13 +5990,13 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, return CMD_WARNING_CONFIG_FAILED; } - aggregate = bgp_aggregate_get_node_info(rn); + aggregate = bgp_node_get_bgp_aggregate_info(rn); bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, NULL, NULL, 0, aggregate); /* Unlock aggregate address configuration. */ - bgp_aggregate_set_node_info(rn, NULL); + bgp_node_set_bgp_aggregate_info(rn, NULL); bgp_aggregate_free(aggregate); bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -6015,7 +6031,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, /* Old configuration check. */ rn = bgp_node_get(bgp->aggregate[afi][safi], &p); - if (rn->info) { + if (bgp_node_has_bgp_path_info_data(rn)) { vty_out(vty, "There is already same aggregate network.\n"); /* try to remove the old entry */ ret = bgp_aggregate_unset(vty, prefix_str, afi, safi); @@ -6031,7 +6047,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, aggregate->summary_only = summary_only; aggregate->as_set = as_set; aggregate->safi = safi; - bgp_aggregate_set_node_info(rn, aggregate); + bgp_node_set_bgp_aggregate_info(rn, aggregate); /* Aggregate address insert into BGP routing table. */ bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate); @@ -6269,7 +6285,8 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, new_attr = bgp_attr_intern(&attr_new); - for (bpi = bn->info; bpi; bpi = bpi->next) + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; + bpi = bpi->next) if (bpi->peer == bgp->peer_self && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE) break; @@ -6351,7 +6368,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type, rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == type) break; @@ -6381,7 +6398,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, table = bgp->rib[afi][SAFI_UNICAST]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == type && pi->instance == instance) break; @@ -8446,7 +8463,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, /* Start processing of routes. */ for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - if (rn->info == NULL) + pi = bgp_node_get_bgp_path_info(rn); + if (pi == NULL) continue; display = 0; @@ -8455,7 +8473,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, else json_paths = NULL; - for (pi = rn->info; pi; pi = pi->next) { + for (; pi; pi = pi->next) { total_count++; if (type == bgp_show_type_flap_statistics || type == bgp_show_type_flap_neighbor @@ -8715,6 +8733,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, unsigned long output_cum = 0; unsigned long total_cum = 0; unsigned long json_header_depth = 0; + struct bgp_table *itable; bool show_msg; show_msg = (!use_json && type == bgp_show_type_normal); @@ -8723,16 +8742,17 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, next = bgp_route_next(rn); if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0) continue; - if (rn->info != NULL) { + + itable = bgp_node_get_bgp_table_info(rn); + if (itable != NULL) { struct prefix_rd prd; char rd[RD_ADDRSTRLEN]; memcpy(&prd, &(rn->p), sizeof(struct prefix_rd)); prefix_rd2str(&prd, rd, sizeof(rd)); - bgp_show_table(vty, bgp, safi, rn->info, type, - output_arg, use_json, rd, next == NULL, - &output_cum, &total_cum, - &json_header_depth); + bgp_show_table(vty, bgp, safi, itable, type, output_arg, + use_json, rd, next == NULL, &output_cum, + &total_cum, &json_header_depth); if (next == NULL) show_msg = false; } @@ -8897,7 +8917,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, vty_out(vty, "not allocated\n"); } - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { count++; if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { best = count; @@ -9061,8 +9081,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - - if ((table = rn->info) == NULL) + table = bgp_node_get_bgp_table_info(rn); + if (!table) continue; header = 1; @@ -9076,7 +9096,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, continue; } - for (pi = rm->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rm); pi; + pi = pi->next) { if (header) { route_vty_out_detail_header( vty, bgp, rm, @@ -9114,7 +9135,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, if ((rn = bgp_node_match(rib, &match)) != NULL) { if (!prefix_check || rn->p.prefixlen == match.prefixlen) { - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; + pi = pi->next) { if (header) { route_vty_out_detail_header( vty, bgp, rn, NULL, afi, @@ -9923,7 +9945,7 @@ static int bgp_table_stats_walker(struct thread *t) if (rn == top) continue; - if (!rn->info) + if (!bgp_node_has_bgp_path_info_data(rn)) continue; ts->counts[BGP_STATS_PREFIXES]++; @@ -9937,7 +9959,7 @@ static int bgp_table_stats_walker(struct thread *t) #endif /* check if the prefix is included by any other announcements */ - while (prn && !prn->info) + while (prn && !bgp_node_has_bgp_path_info_data(prn)) prn = bgp_node_parent_nolock(prn); if (prn == NULL || prn == top) { @@ -9946,10 +9968,10 @@ static int bgp_table_stats_walker(struct thread *t) if (space) ts->total_space += pow(2.0, space - rn->p.prefixlen); - } else if (prn->info) + } else if (bgp_node_has_bgp_path_info_data(prn)) ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { pinum++; ts->counts[BGP_STATS_RIB]++; @@ -10132,7 +10154,8 @@ static int bgp_peer_count_walker(struct thread *t) if (ain->peer == peer) pc->count[PCOUNT_ADJ_IN]++; - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { + if (pi->peer != peer) continue; @@ -11033,12 +11056,12 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str, /* Get BGP distance node. */ rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p); - bdistance = bgp_distance_get_node(rn); + bdistance = bgp_node_get_bgp_distance_info(rn); if (bdistance) bgp_unlock_node(rn); else { bdistance = bgp_distance_new(); - bgp_distance_set_node_info(rn, bdistance); + bgp_node_set_bgp_distance_info(rn, bdistance); } /* Set distance value. */ @@ -11083,7 +11106,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, return CMD_WARNING_CONFIG_FAILED; } - bdistance = bgp_distance_get_node(rn); + bdistance = bgp_node_get_bgp_distance_info(rn); distance = atoi(distance_str); if (bdistance->distance != distance) { @@ -11095,7 +11118,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, XFREE(MTYPE_AS_LIST, bdistance->access_list); bgp_distance_free(bdistance); - rn->info = NULL; + bgp_node_set_bgp_path_info(rn, NULL); bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -11122,7 +11145,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo, sockunion2hostprefix(&peer->su, &q); rn = bgp_node_match(bgp_distance_table[afi][safi], &q); if (rn) { - bdistance = bgp_distance_get_node(rn); + bdistance = bgp_node_get_bgp_distance_info(rn); bgp_unlock_node(rn); if (bdistance->access_list) { @@ -11137,7 +11160,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo, /* Backdoor check. */ rn = bgp_node_lookup(bgp->route[afi][safi], p); if (rn) { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); bgp_unlock_node(rn); if (bgp_static->backdoor) { @@ -11418,14 +11441,15 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, rn = bgp_route_next(rn)) { if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) == NULL) + table = bgp_node_get_bgp_table_info(rn); + if (!table) continue; if ((rm = bgp_node_match(table, &match)) == NULL) continue; if (!prefix_check || rm->p.prefixlen == match.prefixlen) { - pi = rm->info; + pi = bgp_node_get_bgp_path_info(rm); while (pi) { if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; @@ -11445,7 +11469,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, != NULL) { if (!prefix_check || rn->p.prefixlen == match.prefixlen) { - pi = rn->info; + pi = bgp_node_get_bgp_path_info(rn); while (pi) { if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; @@ -11578,11 +11602,12 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, /* Network configuration. */ for (prn = bgp_table_top(bgp->route[afi][safi]); prn; prn = bgp_route_next(prn)) { - if ((table = prn->info) == NULL) + table = bgp_node_get_bgp_table_info(prn); + if (!table) continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); if (bgp_static == NULL) continue; @@ -11628,11 +11653,12 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, /* Network configuration. */ for (prn = bgp_table_top(bgp->route[afi][safi]); prn; prn = bgp_route_next(prn)) { - if ((table = prn->info) == NULL) + table = bgp_node_get_bgp_table_info(prn); + if (!table) continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); if (bgp_static == NULL) continue; @@ -11708,7 +11734,7 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, /* Network configuration. */ for (rn = bgp_table_top(bgp->route[afi][safi]); rn; rn = bgp_route_next(rn)) { - bgp_static = bgp_static_get_node_info(rn); + bgp_static = bgp_node_get_bgp_static_info(rn); if (bgp_static == NULL) continue; @@ -11755,7 +11781,7 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, /* Aggregate-address configuration. */ for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn; rn = bgp_route_next(rn)) { - bgp_aggregate = bgp_aggregate_get_node_info(rn); + bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn); if (bgp_aggregate == NULL) continue; @@ -11807,7 +11833,7 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn; rn = bgp_route_next(rn)) { - bdistance = bgp_distance_get_node(rn); + bdistance = bgp_node_get_bgp_distance_info(rn); if (bdistance != NULL) { char buf[PREFIX_STRLEN]; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index fc27c546b4..a308e8fec6 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3226,33 +3226,29 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name, /* For network route-map updates. */ for (bn = bgp_table_top(bgp->route[afi][safi]); bn; - bn = bgp_route_next(bn)) - if ((bgp_static = bn->info) != NULL) { - if (bgp_static->rmap.name - && (strcmp(rmap_name, bgp_static->rmap.name) - == 0)) { - bgp_static->rmap.map = map; - - if (route_update) - if (!bgp_static->backdoor) { - if (bgp_debug_zebra( - &bn->p)) - zlog_debug( - "Processing route_map %s update on " - "static route %s", - rmap_name, - inet_ntop( - bn->p.family, - &bn->p.u.prefix, - buf, - INET6_ADDRSTRLEN)); - bgp_static_update( - bgp, &bn->p, - bgp_static, afi, - safi); - } - } + bn = bgp_route_next(bn)) { + bgp_static = bgp_node_get_bgp_static_info(bn); + if (!bgp_static) + continue; + + if (!bgp_static->rmap.name + || (strcmp(rmap_name, bgp_static->rmap.name) != 0)) + continue; + + bgp_static->rmap.map = map; + + if (route_update && !bgp_static->backdoor) { + if (bgp_debug_zebra(&bn->p)) + zlog_debug( + "Processing route_map %s update on static route %s", + rmap_name, + inet_ntop(bn->p.family, + &bn->p.u.prefix, buf, + INET6_ADDRSTRLEN)); + bgp_static_update(bgp, &bn->p, bgp_static, afi, + safi); } + } } /* For redistribute route-map updates. */ @@ -3266,38 +3262,38 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name, continue; for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - if (red->rmap.name - && (strcmp(rmap_name, red->rmap.name) - == 0)) { - red->rmap.map = map; - - if (route_update) { - if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug( - "Processing route_map %s update on " - "redistributed routes", - rmap_name); - - bgp_redistribute_resend( - bgp, afi, i, + if (!red->rmap.name + || (strcmp(rmap_name, red->rmap.name) != 0)) + continue; + + red->rmap.map = map; + + if (!route_update) + continue; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug( + "Processing route_map %s update on redistributed routes", + rmap_name); + + bgp_redistribute_resend(bgp, afi, i, red->instance); - } - } } } /* for type5 command route-maps */ FOREACH_AFI_SAFI (afi, safi) { - if (bgp->adv_cmd_rmap[afi][safi].name - && strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name) - == 0) { - if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug( - "Processing route_map %s update on advertise type5 route command", - rmap_name); - bgp_evpn_withdraw_type5_routes(bgp, afi, safi); - bgp_evpn_advertise_type5_routes(bgp, afi, safi); - } + if (!bgp->adv_cmd_rmap[afi][safi].name + || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name) + != 0) + continue; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug( + "Processing route_map %s update on advertise type5 route command", + rmap_name); + bgp_evpn_withdraw_type5_routes(bgp, afi, safi); + bgp_evpn_advertise_type5_routes(bgp, afi, safi); } } diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index c5d38f3009..b614e87d23 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -418,7 +418,8 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, for (ain = bgp_node->adj_in; ain; ain = ain->next) { int ret; - struct bgp_path_info *path = bgp_node->info; + struct bgp_path_info *path = + bgp_node_get_bgp_path_info(bgp_node); mpls_label_t *label = NULL; uint32_t num_labels = 0; diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index d539fad510..c1321dd7dc 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -715,7 +715,8 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], if (rn) { bgp_unlock_node(rn); - for (path = rn->info; path; path = path->next) + for (path = bgp_node_get_bgp_path_info(rn); path; + path = path->next) if (sockunion_same(&path->peer->su, &su)) return path; } @@ -762,7 +763,8 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], do { min = NULL; - for (path = rn->info; path; path = path->next) { + for (path = bgp_node_get_bgp_path_info(rn); path; + path = path->next) { if (path->peer->su.sin.sin_family == AF_INET && ntohl(paddr.s_addr) < ntohl(path->peer->su.sin diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 0321412263..ecde71279d 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -158,7 +158,8 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, while (node && node->p.prefixlen <= p->prefixlen && prefix_match(&node->p, p)) { - if (node->info && node->p.prefixlen == p->prefixlen) { + if (bgp_node_has_bgp_path_info_data(node) + && node->p.prefixlen == p->prefixlen) { matched = node; break; } @@ -174,14 +175,14 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, else if (matched == NULL) matched = node = bgp_node_from_rnode(node->parent); - if (matched->info) { + if (bgp_node_has_bgp_path_info_data(matched)) { bgp_lock_node(matched); listnode_add(matches, matched); } while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) { if (prefix_match(p, &node->p)) { - if (node->info) { + if (bgp_node_has_bgp_path_info_data(node)) { bgp_lock_node(node); listnode_add(matches, node); } diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 4795ab741c..040e83a8cd 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -61,9 +61,10 @@ struct bgp_node { STAILQ_ENTRY(bgp_node) pq; + uint64_t version; + mpls_label_t local_label; - uint64_t version; uint8_t flags; #define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_USER_CLEAR (1 << 1) @@ -319,61 +320,94 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, static inline struct bgp_aggregate * -bgp_aggregate_get_node_info(struct bgp_node *node) +bgp_node_get_bgp_aggregate_info(struct bgp_node *node) { return node->info; } -static inline void bgp_aggregate_set_node_info(struct bgp_node *node, - struct bgp_aggregate *aggregate) +static inline void +bgp_node_set_bgp_aggregate_info(struct bgp_node *node, + struct bgp_aggregate *aggregate) { node->info = aggregate; } -static inline struct bgp_distance *bgp_distance_get_node(struct bgp_node *node) +static inline struct bgp_distance * +bgp_node_get_bgp_distance_info(struct bgp_node *node) { return node->info; } -static inline void bgp_distance_set_node_info(struct bgp_node *node, - struct bgp_distance *distance) +static inline void bgp_node_set_bgp_distance_info(struct bgp_node *node, + struct bgp_distance *distance) { node->info = distance; } -static inline struct bgp_static *bgp_static_get_node_info(struct bgp_node *node) +static inline struct bgp_static * +bgp_node_get_bgp_static_info(struct bgp_node *node) { return node->info; } -static inline void bgp_static_set_node_info(struct bgp_node *node, - struct bgp_static *bgp_static) +static inline void bgp_node_set_bgp_static_info(struct bgp_node *node, + struct bgp_static *bgp_static) { node->info = bgp_static; } static inline struct bgp_connected_ref * -bgp_connected_get_node_info(struct bgp_node *node) +bgp_node_get_bgp_connected_ref_info(struct bgp_node *node) { return node->info; } -static inline void bgp_connected_set_node_info(struct bgp_node *node, - struct bgp_connected_ref *bc) +static inline void +bgp_node_set_bgp_connected_ref_info(struct bgp_node *node, + struct bgp_connected_ref *bc) { node->info = bc; } static inline struct bgp_nexthop_cache * -bgp_nexthop_get_node_info(struct bgp_node *node) +bgp_node_get_bgp_nexthop_info(struct bgp_node *node) { return node->info; } -static inline void bgp_nexthop_set_node_info(struct bgp_node *node, +static inline void bgp_node_set_bgp_nexthop_info(struct bgp_node *node, struct bgp_nexthop_cache *bnc) { node->info = bnc; } +static inline struct bgp_path_info * +bgp_node_get_bgp_path_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_node_set_bgp_path_info(struct bgp_node *node, + struct bgp_path_info *bi) +{ + node->info = bi; +} + +static inline struct bgp_table * +bgp_node_get_bgp_table_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_node_set_bgp_table_info(struct bgp_node *node, + struct bgp_table *table) +{ + node->info = table; +} + +static inline bool bgp_node_has_bgp_path_info_data(struct bgp_node *node) +{ + return !!node->info; +} + #endif /* _QUAGGA_BGP_TABLE_H */ diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index cefbf72b58..3870df593f 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -122,7 +122,8 @@ static void subgrp_withdraw_stale_addpath(struct updwalk_context *ctx, RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->rn->adj_out, adj_next) { if (adj->subgroup == subgrp) { - for (pi = ctx->rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(ctx->rn); + pi; pi = pi->next) { id = bgp_addpath_id_for_peer(peer, afi, safi, &pi->tx_addpath); @@ -176,7 +177,8 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) if (addpath_capable) { subgrp_withdraw_stale_addpath(ctx, subgrp); - for (pi = ctx->rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(ctx->rn); + pi; pi = pi->next) { /* Skip the bestpath for now */ if (pi == ctx->pi) continue; @@ -629,7 +631,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp, subgroup_default_originate(subgrp, 0); for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = ri->next) + for (ri = bgp_node_get_bgp_path_info(rn); ri; ri = ri->next) if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED) || (addpath_capable @@ -695,9 +697,12 @@ void subgroup_announce_route(struct update_subgroup *subgrp) subgroup_announce_table(subgrp, NULL); else for (rn = bgp_table_top(update_subgroup_rib(subgrp)); rn; - rn = bgp_route_next(rn)) - if ((table = (rn->info)) != NULL) - subgroup_announce_table(subgrp, table); + rn = bgp_route_next(rn)) { + table = bgp_node_get_bgp_table_info(rn); + if (!table) + continue; + subgroup_announce_table(subgrp, table); + } } void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) @@ -752,7 +757,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) { + for (ri = bgp_node_get_bgp_path_info(rn); + ri; ri = ri->next) { struct attr dummy_attr; /* Provide dummy so the route-map can't modify diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index 2b4477ddde..54ca980cad 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -38,7 +38,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct bgp_table *table; struct bgp_node *rn; struct bgp_node *rm; - struct attr *attr; + struct bgp_path_info *path; int rd_header; int header = 1; json_object *json = NULL; @@ -79,170 +79,129 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) != NULL) { - if (use_json) - json_array = json_object_new_array(); - else - json_array = NULL; - - rd_header = 1; + table = bgp_node_get_bgp_table_info(rn); + if (table == NULL) + continue; - for (rm = bgp_table_top(table); rm; - rm = bgp_route_next(rm)) { - if ((attr = rm->info) != NULL) { - if (header) { - if (use_json) { - json_object_int_add( - json, - "bgpTableVersion", - 0); - json_object_string_add( - json, - "bgpLocalRouterId", - inet_ntoa( - bgp->router_id)); - json_object_object_add( - json, - "bgpStatusCodes", - json_scode); - json_object_object_add( - json, - "bgpOriginCodes", - json_ocode); - } else { - vty_out(vty, - "BGP table version is 0, local router ID is %s\n", - inet_ntoa( - bgp->router_id)); - vty_out(vty, - "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out(vty, - "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out(vty, V4_HEADER); - } - header = 0; - } + if (use_json) + json_array = json_object_new_array(); + else + json_array = NULL; + + rd_header = 1; + + for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { + path = bgp_node_get_bgp_path_info(rm); + if (path == NULL) + continue; + + if (header) { + if (use_json) { + json_object_int_add( + json, "bgpTableVersion", 0); + json_object_string_add( + json, "bgpLocalRouterId", + inet_ntoa(bgp->router_id)); + json_object_object_add(json, + "bgpStatusCodes", + json_scode); + json_object_object_add(json, + "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa(bgp->router_id)); + vty_out(vty, + "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); + vty_out(vty, + "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); + vty_out(vty, V4_HEADER); + } + header = 0; + } - if (rd_header) { - uint16_t type; - struct rd_as rd_as = {0}; - struct rd_ip rd_ip = {0}; + if (rd_header) { + uint16_t type; + struct rd_as rd_as = {0}; + struct rd_ip rd_ip = {0}; #if ENABLE_BGP_VNC - struct rd_vnc_eth rd_vnc_eth = { - 0}; + struct rd_vnc_eth rd_vnc_eth = {0}; #endif - uint8_t *pnt; - - pnt = rn->p.u.val; - - /* Decode RD type. */ - type = decode_rd_type(pnt); - /* Decode RD value. */ - if (type == RD_TYPE_AS) - decode_rd_as(pnt + 2, - &rd_as); - else if (type == RD_TYPE_AS4) - decode_rd_as4(pnt + 2, - &rd_as); - else if (type == RD_TYPE_IP) - decode_rd_ip(pnt + 2, - &rd_ip); + uint8_t *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type(pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as(pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4(pnt + 2, &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip(pnt + 2, &rd_ip); #if ENABLE_BGP_VNC - else if (type - == RD_TYPE_VNC_ETH) - decode_rd_vnc_eth( - pnt, - &rd_vnc_eth); + else if (type == RD_TYPE_VNC_ETH) + decode_rd_vnc_eth(pnt, &rd_vnc_eth); #endif - - if (use_json) { - char buffer[BUFSIZ]; - if (type == RD_TYPE_AS - || type == RD_TYPE_AS4) - sprintf(buffer, - "%u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_IP) - sprintf(buffer, - "%s:%d", - inet_ntoa( - rd_ip.ip), - rd_ip.val); - json_object_string_add( - json_routes, - "routeDistinguisher", - buffer); - } else { - vty_out(vty, - "Route Distinguisher: "); - - if (type == RD_TYPE_AS - || type == RD_TYPE_AS4) - vty_out(vty, - "%u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_IP) - vty_out(vty, - "%s:%d", - inet_ntoa( - rd_ip.ip), - rd_ip.val); + if (use_json) { + char buffer[BUFSIZ]; + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + sprintf(buffer, "%u:%d", + rd_as.as, rd_as.val); + else if (type == RD_TYPE_IP) + sprintf(buffer, "%s:%d", + inet_ntoa(rd_ip.ip), + rd_ip.val); + json_object_string_add( + json_routes, + "routeDistinguisher", buffer); + } else { + vty_out(vty, "Route Distinguisher: "); + + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + vty_out(vty, "%u:%d", rd_as.as, + rd_as.val); + else if (type == RD_TYPE_IP) + vty_out(vty, "%s:%d", + inet_ntoa(rd_ip.ip), + rd_ip.val); #if ENABLE_BGP_VNC - else if ( - type - == RD_TYPE_VNC_ETH) - vty_out(vty, - "%u:%02x:%02x:%02x:%02x:%02x:%02x", - rd_vnc_eth - .local_nve_id, - rd_vnc_eth - .macaddr - .octet[0], - rd_vnc_eth - .macaddr - .octet[1], - rd_vnc_eth - .macaddr - .octet[2], - rd_vnc_eth - .macaddr - .octet[3], - rd_vnc_eth - .macaddr - .octet[4], - rd_vnc_eth - .macaddr - .octet[5]); + else if (type == RD_TYPE_VNC_ETH) + vty_out(vty, + "%u:%02x:%02x:%02x:%02x:%02x:%02x", + rd_vnc_eth.local_nve_id, + rd_vnc_eth.macaddr + .octet[0], + rd_vnc_eth.macaddr + .octet[1], + rd_vnc_eth.macaddr + .octet[2], + rd_vnc_eth.macaddr + .octet[3], + rd_vnc_eth.macaddr + .octet[4], + rd_vnc_eth.macaddr + .octet[5]); #endif - vty_out(vty, "\n"); - } - rd_header = 0; - } - if (use_json) { - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - - sprintf(buf_a, "%s/%d", - inet_ntop(rm->p.family, - rm->p.u.val, - buf_b, - BUFSIZ), - rm->p.prefixlen); - json_object_object_add( - json_routes, buf_a, - json_array); - } else { - route_vty_out_tmp( - vty, &rm->p, attr, - SAFI_MPLS_VPN, use_json, - json_array); - } + vty_out(vty, "\n"); } + rd_header = 0; + } + if (use_json) { + char buf[BUFSIZ]; + + prefix2str(&rm->p, buf, sizeof(buf)); + json_object_object_add(json_routes, buf, + json_array); + } else { + route_vty_out_tmp(vty, &rm->p, path->attr, + SAFI_MPLS_VPN, use_json, + json_array); } } } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f83b146175..bac46f251b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7213,7 +7213,9 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name, if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) != NULL) { + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { + if ((rm = bgp_node_match(table, &match)) != NULL) { if (rm->p.prefixlen diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1e0abaa29e..66d3333739 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1482,7 +1482,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) return; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - for (pi = rn->info; pi; pi = pi->next) + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (pi->type == ZEBRA_ROUTE_BGP @@ -1694,7 +1694,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - for (pi = rn->info; pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { if (pi->sub_type == BGP_ROUTE_REDISTRIBUTE && pi->type == type && pi->instance == red->instance) { diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d6be3228fe..8b8a2c4d81 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1464,16 +1464,17 @@ static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi) { struct bgp_node *rn, *nrn; + struct bgp_table *table; for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { - if (rn->info != NULL) { + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) { /* Special handling for 2-level routing * tables. */ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { - for (nrn = bgp_table_top( - (struct bgp_table *)(rn->info)); + for (nrn = bgp_table_top(table); nrn; nrn = bgp_route_next(nrn)) bgp_process(bgp, nrn, afi, safi); } else @@ -3354,7 +3355,7 @@ void bgp_free(struct bgp *bgp) || safi == SAFI_EVPN) { for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { - table = (struct bgp_table *)rn->info; + table = bgp_node_get_bgp_table_info(rn); bgp_table_finish(&table); } } diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 6978dd145d..a41473fa4f 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -382,9 +382,10 @@ void del_vnc_route(struct rfapi_descriptor *rfd, vnc_zlog_debug_verbose( "%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p", __func__, peer, buf, prefix_rd2str(prd, buf2, sizeof(buf2)), - afi, safi, bn, (bn ? bn->info : NULL)); + afi, safi, bn, (bn ? bgp_node_get_bgp_path_info(bn) : NULL)); - for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { + for (bpi = (bn ? bgp_node_get_bgp_path_info(bn) : NULL); bpi; + bpi = bpi->next) { vnc_zlog_debug_verbose( "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%u", @@ -471,12 +472,10 @@ void del_vnc_route(struct rfapi_descriptor *rfd, prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - + table = bgp_node_get_bgp_table_info(prn); + if (table) vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, bpi); - } bgp_unlock_node(prn); } @@ -945,7 +944,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr * aspath: POINTS TO interned/refcounted hashed block */ - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { /* probably only need to check * bpi->extra->vnc.export.rfapi_handle */ if (bpi->peer == rfd->peer && bpi->type == type @@ -1017,12 +1016,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - + table = bgp_node_get_bgp_table_info(prn); + if (table) vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, bpi); - } bgp_unlock_node(prn); } @@ -1042,12 +1039,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - + table = bgp_node_get_bgp_table_info(prn); + if (table) vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, bpi); - } bgp_unlock_node(prn); } @@ -1081,7 +1076,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ /* debug */ if (VNC_DEBUG(VERBOSE)) { - vnc_zlog_debug_verbose("%s: printing BI", __func__); + vnc_zlog_debug_verbose("%s: printing BPI", __func__); rfapiPrintBi(NULL, new); } @@ -1093,12 +1088,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ struct bgp_table *table = NULL; prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - + table = bgp_node_get_bgp_table_info(prn); + if (table) vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( bgp, prd, table, p, new); - } bgp_unlock_node(prn); encode_label(label_val, &bn->local_label); } @@ -3696,30 +3689,39 @@ static void rfapi_print_exported(struct bgp *bgp) for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rdn; rdn = bgp_route_next(rdn)) { - if (!rdn->info) + struct bgp_table *table; + + table = bgp_node_get_bgp_table_info(rdn); + if (!table) continue; fprintf(stderr, "%s: vpn rdn=%p\n", __func__, rdn); - for (rn = bgp_table_top(rdn->info); rn; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - if (!rn->info) + bpi = bgp_node_get_bgp_path_info(rn); + + if (!bpi) continue; fprintf(stderr, "%s: rn=%p\n", __func__, rn); - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (; bpi; bpi = bpi->next) { rfapiPrintBi((void *)2, bpi); /* 2 => stderr */ } } } for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); rdn; rdn = bgp_route_next(rdn)) { - if (!rdn->info) + struct bgp_table *table; + + table = bgp_node_get_bgp_table_info(rdn); + if (!table) continue; fprintf(stderr, "%s: encap rdn=%p\n", __func__, rdn); - for (rn = bgp_table_top(rdn->info); rn; + for (rn = bgp_table_top(table)); rn; rn = bgp_route_next(rn)) { - if (!rn->info) + bpi = bgp_node_get_bgp_path_info(rn); + if (!bpi) continue; fprintf(stderr, "%s: rn=%p\n", __func__, rn); - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (; bpi; bpi = bpi->next) { rfapiPrintBi((void *)2, bpi); /* 2 => stderr */ } } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 6b2d5d3426..904d43c65a 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4241,13 +4241,15 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp, for (rn1 = bgp_table_top(bgp->rib[afi][safi]); rn1; rn1 = bgp_route_next(rn1)) { - if (rn1->info) { - for (rn2 = bgp_table_top(rn1->info); rn2; + if (bgp_node_has_bgp_path_info_data(rn1)) { + + for (rn2 = bgp_table_top(bgp_node_get_bgp_table_info(rn1)); rn2; rn2 = bgp_route_next(rn2)) { struct bgp_path_info *bpi; - for (bpi = rn2->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(rn2); + bpi; bpi = bpi->next) { uint32_t label = 0; if (CHECK_FLAG(bpi->flags, diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 1844839f25..04ddff934d 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1570,7 +1570,7 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd, vty_out(vty, " bn=%p%s", bn, HVTYNL); - for (bpi = bn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { if (bpi->peer == rfd->peer && bpi->type == type && bpi->sub_type == BGP_ROUTE_RFP && bpi->extra && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) { diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 212d394fdc..3d8d5bccb0 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -256,7 +256,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, */ urn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, prefix, NULL); - for (ubpi = urn->info; ubpi; ubpi = ubpi->next) { + for (ubpi = bgp_node_get_bgp_path_info(urn); ubpi; ubpi = ubpi->next) { struct prefix unicast_nexthop; if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED)) @@ -483,7 +483,8 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) struct bgp_path_info *ri; struct bgp_path_info *next; - for (ri = rn->info, next = NULL; ri; ri = next) { + for (ri = bgp_node_get_bgp_path_info(rn), next = NULL; + ri; ri = next) { next = ri->next; @@ -1846,7 +1847,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) memcpy(prd.val, prn->p.u.val, 8); /* This is the per-RD table of prefixes */ - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); if (!table) continue; @@ -1856,7 +1857,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) /* * skip prefix list check if no routes here */ - if (!rn->info) + if (!bgp_node_has_bgp_path_info_data(rn)) continue; { @@ -1883,7 +1884,8 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) } } - for (ri = rn->info; ri; ri = ri->next) { + for (ri = bgp_node_get_bgp_path_info(rn); + ri; ri = ri->next) { vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__, ri->sub_type); @@ -2003,7 +2005,7 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi) struct bgp_path_info *ri; struct bgp_path_info *next; - for (ri = rn->info, next = NULL; ri; ri = next) { + for (ri = bgp_node_get_bgp_path_info(rn), next = NULL; ri; ri = next) { next = ri->next; diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 2f634f6f40..eb2d0fd889 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -545,8 +545,8 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd( return; } - /* Iterate over bgp_path_info items at this node */ - for (bpi = bn->info; bpi; bpi = bpi->next) { + /* Iterate over bgp_info items at this node */ + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { vnc_import_bgp_add_route_mode_resolve_nve_one_bi( bgp, afi, bpi, /* VPN bpi */ @@ -676,7 +676,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve( struct bgp_table *table; - table = (struct bgp_table *)(bnp->info); + table = bgp_node_get_bgp_table_info(bnp); if (!table) continue; @@ -1305,8 +1305,8 @@ static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd( return; } - /* Iterate over bgp_path_info items at this node */ - for (bpi = bn->info; bpi; bpi = bpi->next) { + /* Iterate over bgp_info items at this node */ + for (bpi = bgp_node_get_bgp_path_info(bn); bpi; bpi = bpi->next) { vnc_import_bgp_del_route_mode_resolve_nve_one_bi( bgp, afi, bpi, /* VPN bpi */ @@ -1377,7 +1377,7 @@ vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi, struct bgp_table *table; - table = (struct bgp_table *)(bnp->info); + table = bgp_node_get_bgp_table_info(bnp); if (!table) continue; @@ -2780,7 +2780,8 @@ void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi) struct bgp_path_info *bpi; - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(rn); bpi; + bpi = bpi->next) { if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; @@ -2820,7 +2821,8 @@ void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi) struct bgp_path_info *bpi; - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(rn); bpi; + bpi = bpi->next) { if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; @@ -2865,7 +2867,8 @@ void vnc_import_bgp_exterior_redist_enable_it( struct bgp_path_info *bpi; - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(rn); bpi; + bpi = bpi->next) { if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; @@ -2902,14 +2905,17 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) for (rn1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn1; rn1 = bgp_route_next(rn1)) { - if (rn1->info) { - for (rn2 = bgp_table_top(rn1->info); rn2; - rn2 = bgp_route_next(rn2)) { + if (bgp_node_has_bgp_path_info_data(rn1)) { + + for (rn2 = bgp_table_top( + bgp_node_get_bgp_table_info(rn1)); + rn2; rn2 = bgp_route_next(rn2)) { struct bgp_path_info *bpi; struct bgp_path_info *nextbpi; - for (bpi = rn2->info; bpi; bpi = nextbpi) { + for (bpi = bgp_node_get_bgp_path_info(rn2); bpi; + bpi = nextbpi) { nextbpi = bpi->next; @@ -2999,7 +3005,8 @@ void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi) struct bgp_path_info *bpi; - for (bpi = rn->info; bpi; bpi = bpi->next) { + for (bpi = bgp_node_get_bgp_path_info(rn); bpi; + bpi = bpi->next) { if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index a43cf1f6a9..98f719969c 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -312,7 +312,7 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) memcpy(prd.val, prn->p.u.val, 8); /* This is the per-RD table of prefixes */ - table = prn->info; + table = bgp_node_get_bgp_table_info(prn); if (!table) continue; @@ -320,7 +320,8 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) struct bgp_path_info *ri; - for (ri = rn->info; ri; ri = ri->next) { + for (ri = bgp_node_get_bgp_path_info(rn); ri; + ri = ri->next) { if (ri->type == type) { /* has matching redist type */ break; diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 2b3116b1ff..e8b729c779 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -31,9 +31,11 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_spf_private.h" #include "isisd/isis_tx_queue.h" +#include "isisd/isis_csm.h" DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric") DEFINE_MTYPE_STATIC(ISISD, FABRICD_NEIGHBOR, "ISIS OpenFabric Neighbor Entry") +DEFINE_MTYPE_STATIC(ISISD, FABRICD_FLOODING_INFO, "ISIS OpenFabric Flooding Log") /* Tracks initial synchronization as per section 2.4 * @@ -63,20 +65,28 @@ struct fabricd { uint8_t tier_pending; struct thread *tier_calculation_timer; struct thread *tier_set_timer; + + int csnp_delay; + bool always_send_csnp; }; /* Code related to maintaining the neighbor lists */ struct neighbor_entry { - struct isis_vertex *vertex; + uint8_t id[ISIS_SYS_ID_LEN]; + struct isis_adjacency *adj; bool present; }; -static struct neighbor_entry *neighbor_entry_new(struct isis_vertex *vertex) +static struct neighbor_entry *neighbor_entry_new(const uint8_t *id, + struct isis_adjacency *adj) { - struct neighbor_entry *rv = XMALLOC(MTYPE_FABRICD_NEIGHBOR, sizeof(*rv)); + struct neighbor_entry *rv = XMALLOC(MTYPE_FABRICD_NEIGHBOR, + sizeof(*rv)); + + memcpy(rv->id, id, sizeof(rv->id)); + rv->adj = adj; - rv->vertex = vertex; return rv; } @@ -102,32 +112,29 @@ static unsigned neighbor_entry_hash_key(void *np) { struct neighbor_entry *n = np; - return jhash(n->vertex->N.id, ISIS_SYS_ID_LEN, 0x55aa5a5a); + return jhash(n->id, sizeof(n->id), 0x55aa5a5a); } static bool neighbor_entry_hash_cmp(const void *a, const void *b) { const struct neighbor_entry *na = a, *nb = b; - return memcmp(na->vertex->N.id, nb->vertex->N.id, ISIS_SYS_ID_LEN) == 0; + return memcmp(na->id, nb->id, sizeof(na->id)) == 0; } static int neighbor_entry_list_cmp(void *a, void *b) { struct neighbor_entry *na = a, *nb = b; - return -memcmp(na->vertex->N.id, nb->vertex->N.id, ISIS_SYS_ID_LEN); + return -memcmp(na->id, nb->id, sizeof(na->id)); } static struct neighbor_entry *neighbor_entry_lookup_list(struct skiplist *list, const uint8_t *id) { - struct isis_vertex querier; - isis_vertex_id_init(&querier, id, VTYPE_NONPSEUDO_TE_IS); + struct neighbor_entry n = { {0} }; - struct neighbor_entry n = { - .vertex = &querier - }; + memcpy(n.id, id, sizeof(n.id)); struct neighbor_entry *rv; @@ -143,12 +150,9 @@ static struct neighbor_entry *neighbor_entry_lookup_list(struct skiplist *list, static struct neighbor_entry *neighbor_entry_lookup_hash(struct hash *hash, const uint8_t *id) { - struct isis_vertex querier; - isis_vertex_id_init(&querier, id, VTYPE_NONPSEUDO_TE_IS); + struct neighbor_entry n = {{0}}; - struct neighbor_entry n = { - .vertex = &querier - }; + memcpy(n.id, id, sizeof(n.id)); struct neighbor_entry *rv = hash_lookup(hash, &n); @@ -158,28 +162,55 @@ static struct neighbor_entry *neighbor_entry_lookup_hash(struct hash *hash, return rv; } -static void neighbor_lists_update(struct fabricd *f) +static int fabricd_handle_adj_state_change(struct isis_adjacency *arg) { - neighbor_lists_clear(f); + struct fabricd *f = arg->circuit->area->fabricd; + + if (!f) + return 0; + + while (!skiplist_empty(f->neighbors)) + skiplist_delete_first(f->neighbors); + + struct listnode *node; + struct isis_circuit *circuit; + + for (ALL_LIST_ELEMENTS_RO(f->area->circuit_list, node, circuit)) { + if (circuit->state != C_STATE_UP) + continue; + + struct isis_adjacency *adj = circuit->u.p2p.neighbor; + + if (!adj || adj->adj_state != ISIS_ADJ_UP) + continue; + + struct neighbor_entry *n = neighbor_entry_new(adj->sysid, adj); + + skiplist_insert(f->neighbors, n, n); + } + + return 0; +} + +static void neighbors_neighbors_update(struct fabricd *f) +{ + hash_clean(f->neighbors_neighbors, neighbor_entry_del_void); struct listnode *node; struct isis_vertex *v; for (ALL_QUEUE_ELEMENTS_RO(&f->spftree->paths, node, v)) { - if (!v->d_N || !VTYPE_IS(v->type)) + if (v->d_N < 2 || !VTYPE_IS(v->type)) continue; if (v->d_N > 2) break; - struct neighbor_entry *n = neighbor_entry_new(v); - if (v->d_N == 1) { - skiplist_insert(f->neighbors, n, n); - } else { - struct neighbor_entry *inserted; - inserted = hash_get(f->neighbors_neighbors, n, hash_alloc_intern); - assert(inserted == n); - } + struct neighbor_entry *n = neighbor_entry_new(v->N.id, NULL); + struct neighbor_entry *inserted; + inserted = hash_get(f->neighbors_neighbors, n, + hash_alloc_intern); + assert(inserted == n); } } @@ -198,6 +229,8 @@ struct fabricd *fabricd_new(struct isis_area *area) "Fabricd Neighbors"); rv->tier = rv->tier_config = ISIS_TIER_UNDEFINED; + + rv->csnp_delay = FABRICD_DEFAULT_CSNP_DELAY; return rv; }; @@ -445,7 +478,7 @@ void fabricd_run_spf(struct isis_area *area) return; isis_run_hopcount_spf(area, isis->sysid, f->spftree); - neighbor_lists_update(f); + neighbors_neighbors_update(f); fabricd_bump_tier_calculation_timer(f); } @@ -493,43 +526,37 @@ int fabricd_write_settings(struct isis_area *area, struct vty *vty) written++; } + if (f->csnp_delay != FABRICD_DEFAULT_CSNP_DELAY + || f->always_send_csnp) { + vty_out(vty, " triggered-csnp-delay %d%s\n", f->csnp_delay, + f->always_send_csnp ? " always" : ""); + } + return written; } -static void move_to_dnr(struct isis_lsp *lsp, struct neighbor_entry *n) +static void move_to_queue(struct isis_lsp *lsp, struct neighbor_entry *n, + enum isis_tx_type type, struct isis_circuit *circuit) { - struct isis_adjacency *adj = listnode_head(n->vertex->Adj_N); - n->present = false; - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; - zlog_debug("OpenFabric: Adding %s to DNR", - vid2string(n->vertex, buff, sizeof(buff))); - } + if (n->adj && n->adj->circuit == circuit) + return; - if (adj) { - isis_tx_queue_add(adj->circuit->tx_queue, lsp, - TX_LSP_CIRCUIT_SCOPED); + if (isis->debugs & DEBUG_FLOODING) { + zlog_debug("OpenFabric: Adding %s to %s", + print_sys_hostname(n->id), + (type == TX_LSP_NORMAL) ? "RF" : "DNR"); } -} -static void move_to_rf(struct isis_lsp *lsp, struct neighbor_entry *n) -{ - struct isis_adjacency *adj = listnode_head(n->vertex->Adj_N); + if (n->adj) + isis_tx_queue_add(n->adj->circuit->tx_queue, lsp, type); - n->present = false; - - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; - zlog_debug("OpenFabric: Adding %s to RF", - vid2string(n->vertex, buff, sizeof(buff))); - } + uint8_t *neighbor_id = XMALLOC(MTYPE_FABRICD_FLOODING_INFO, + sizeof(n->id)); - if (adj) { - isis_tx_queue_add(adj->circuit->tx_queue, lsp, - TX_LSP_NORMAL); - } + memcpy(neighbor_id, n->id, sizeof(n->id)); + listnode_add(lsp->flooding_neighbors[type], neighbor_id); } static void mark_neighbor_as_present(struct hash_backet *backet, void *arg) @@ -549,66 +576,89 @@ static void handle_firsthops(struct hash_backet *backet, void *arg) n = neighbor_entry_lookup_list(f->neighbors, vertex->N.id); if (n) { - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("Removing %s from NL as its in the reverse path", - vid2string(vertex, buff, sizeof(buff))); + print_sys_hostname(n->id)); } n->present = false; } n = neighbor_entry_lookup_hash(f->neighbors_neighbors, vertex->N.id); if (n) { - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("Removing %s from NN as its in the reverse path", - vid2string(vertex, buff, sizeof(buff))); + print_sys_hostname(n->id)); } n->present = false; } } -void fabricd_lsp_flood(struct isis_lsp *lsp) +static struct isis_lsp *lsp_for_neighbor(struct fabricd *f, + struct neighbor_entry *n) { - struct fabricd *f = lsp->area->fabricd; - assert(f); + uint8_t id[ISIS_SYS_ID_LEN + 1] = {0}; - void *cursor = NULL; - struct neighbor_entry *n; + memcpy(id, n->id, sizeof(n->id)); - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - zlog_debug("OpenFabric: Flooding LSP %s", - rawlspid_print(lsp->hdr.lsp_id)); - } + struct isis_vertex vertex = {0}; - /* Mark all elements in NL as present and move T0s into DNR */ - while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor)) { - n->present = true; + isis_vertex_id_init(&vertex, id, VTYPE_NONPSEUDO_TE_IS); - struct isis_lsp *node_lsp = lsp_for_vertex(f->spftree, - n->vertex); - if (!node_lsp - || !node_lsp->tlvs - || !node_lsp->tlvs->spine_leaf - || !node_lsp->tlvs->spine_leaf->has_tier - || node_lsp->tlvs->spine_leaf->tier != 0) { + return lsp_for_vertex(f->spftree, &vertex); +} + +static void fabricd_free_lsp_flooding_info(void *val) +{ + XFREE(MTYPE_FABRICD_FLOODING_INFO, val); +} + +static void fabricd_lsp_reset_flooding_info(struct isis_lsp *lsp, + struct isis_circuit *circuit) +{ + lsp->flooding_time = time(NULL); + + XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface); + for (enum isis_tx_type type = TX_LSP_NORMAL; + type <= TX_LSP_CIRCUIT_SCOPED; type++) { + if (lsp->flooding_neighbors[type]) { + list_delete_all_node(lsp->flooding_neighbors[type]); continue; } - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - zlog_debug("Moving %s to DNR because it's T0", - rawlspid_print(node_lsp->hdr.lsp_id)); - } + lsp->flooding_neighbors[type] = list_new(); + lsp->flooding_neighbors[type]->del = + fabricd_free_lsp_flooding_info; + } - move_to_dnr(lsp, n); + if (circuit) { + lsp->flooding_interface = XSTRDUP(MTYPE_FABRICD_FLOODING_INFO, + circuit->interface->name); } + lsp->flooding_circuit_scoped = false; +} + +void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit) +{ + struct fabricd *f = lsp->area->fabricd; + assert(f); + + fabricd_lsp_reset_flooding_info(lsp, circuit); + + void *cursor = NULL; + struct neighbor_entry *n; + + /* Mark all elements in NL as present */ + while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor)) + n->present = true; + /* Mark all elements in NN as present */ hash_iterate(f->neighbors_neighbors, mark_neighbor_as_present, NULL); - struct isis_vertex *originator = isis_find_vertex(&f->spftree->paths, - lsp->hdr.lsp_id, - VTYPE_NONPSEUDO_TE_IS); + struct isis_vertex *originator = + isis_find_vertex(&f->spftree->paths, + lsp->hdr.lsp_id, + VTYPE_NONPSEUDO_TE_IS); /* Remove all IS from NL and NN in the shortest path * to the IS that originated the LSP */ @@ -621,22 +671,20 @@ void fabricd_lsp_flood(struct isis_lsp *lsp) if (!n->present) continue; - struct isis_lsp *nlsp = lsp_for_vertex(f->spftree, n->vertex); + struct isis_lsp *nlsp = lsp_for_neighbor(f, n); if (!nlsp || !nlsp->tlvs) { - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("Moving %s to DNR as it has no LSP", - vid2string(n->vertex, buff, sizeof(buff))); + print_sys_hostname(n->id)); } - move_to_dnr(lsp, n); + move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit); continue; } - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("Considering %s from NL...", - vid2string(n->vertex, buff, sizeof(buff))); + print_sys_hostname(n->id)); } /* For all neighbors of the NL IS check whether they are present @@ -651,10 +699,9 @@ void fabricd_lsp_flood(struct isis_lsp *lsp) er->id); if (nn) { - if (isis->debugs & DEBUG_FABRICD_FLOODING) { - char buff[PREFIX2STR_BUFFER]; + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("Found neighbor %s in NN, removing it from NN and setting reflood.", - vid2string(nn->vertex, buff, sizeof(buff))); + print_sys_hostname(nn->id)); } nn->present = false; @@ -662,24 +709,26 @@ void fabricd_lsp_flood(struct isis_lsp *lsp) } } - if (need_reflood) - move_to_rf(lsp, n); - else - move_to_dnr(lsp, n); + move_to_queue(lsp, n, need_reflood ? + TX_LSP_NORMAL : TX_LSP_CIRCUIT_SCOPED, + circuit); } - if (isis->debugs & DEBUG_FABRICD_FLOODING) { + if (isis->debugs & DEBUG_FLOODING) { zlog_debug("OpenFabric: Flooding algorithm complete."); } } -void fabricd_trigger_csnp(struct isis_area *area) +void fabricd_trigger_csnp(struct isis_area *area, bool circuit_scoped) { struct fabricd *f = area->fabricd; if (!f) return; + if (!circuit_scoped && !f->always_send_csnp) + return; + struct listnode *node; struct isis_circuit *circuit; @@ -689,7 +738,7 @@ void fabricd_trigger_csnp(struct isis_area *area) thread_cancel(circuit->t_send_csnp[ISIS_LEVEL2 - 1]); thread_add_timer_msec(master, send_l2_csnp, circuit, - isis_jitter(500, CSNP_JITTER), + isis_jitter(f->csnp_delay, CSNP_JITTER), &circuit->t_send_csnp[ISIS_LEVEL2 - 1]); } } @@ -717,3 +766,43 @@ struct list *fabricd_ip_addrs(struct isis_circuit *circuit) return NULL; } + +void fabricd_lsp_free(struct isis_lsp *lsp) +{ + XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface); + for (enum isis_tx_type type = TX_LSP_NORMAL; + type <= TX_LSP_CIRCUIT_SCOPED; type++) { + if (!lsp->flooding_neighbors[type]) + continue; + + list_delete(&lsp->flooding_neighbors[type]); + } +} + +void fabricd_update_lsp_no_flood(struct isis_lsp *lsp, + struct isis_circuit *circuit) +{ + if (!fabricd) + return; + + fabricd_lsp_reset_flooding_info(lsp, circuit); + lsp->flooding_circuit_scoped = true; +} + +void fabricd_configure_triggered_csnp(struct isis_area *area, int delay, + bool always_send_csnp) +{ + struct fabricd *f = area->fabricd; + + if (!f) + return; + + f->csnp_delay = delay; + f->always_send_csnp = always_send_csnp; +} + +void fabricd_init(void) +{ + hook_register(isis_adj_state_change_hook, + fabricd_handle_adj_state_change); +} diff --git a/isisd/fabricd.h b/isisd/fabricd.h index 76c182f2d2..315cfba3f0 100644 --- a/isisd/fabricd.h +++ b/isisd/fabricd.h @@ -22,6 +22,8 @@ #ifndef FABRICD_H #define FABRICD_H +#define FABRICD_DEFAULT_CSNP_DELAY 500 + struct fabricd; struct isis_circuit; @@ -42,8 +44,13 @@ struct isis_spftree *fabricd_spftree(struct isis_area *area); void fabricd_configure_tier(struct isis_area *area, uint8_t tier); uint8_t fabricd_tier(struct isis_area *area); int fabricd_write_settings(struct isis_area *area, struct vty *vty); -void fabricd_lsp_flood(struct isis_lsp *lsp); -void fabricd_trigger_csnp(struct isis_area *area); +void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit); +void fabricd_trigger_csnp(struct isis_area *area, bool circuit_scoped); struct list *fabricd_ip_addrs(struct isis_circuit *circuit); - +void fabricd_lsp_free(struct isis_lsp *lsp); +void fabricd_update_lsp_no_flood(struct isis_lsp *lsp, + struct isis_circuit *circuit); +void fabricd_configure_triggered_csnp(struct isis_area *area, int delay, + bool always_send_csnp); +void fabricd_init(void); #endif diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 06385a4e1f..e76e27a7dc 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -729,7 +729,6 @@ void isis_circuit_down(struct isis_circuit *circuit) THREAD_TIMER_OFF(circuit->t_send_csnp[1]); THREAD_TIMER_OFF(circuit->t_send_psnp[0]); THREAD_TIMER_OFF(circuit->t_send_psnp[1]); - THREAD_OFF(circuit->t_send_lsp); THREAD_OFF(circuit->t_read); if (circuit->tx_queue) { diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 7d7b25b92f..5a0d4ffbab 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -86,7 +86,6 @@ struct isis_circuit { struct thread *t_read; struct thread *t_send_csnp[2]; struct thread *t_send_psnp[2]; - struct thread *t_send_lsp; struct isis_tx_queue *tx_queue; struct isis_circuit_arg level_arg[2]; /* used as argument for threads */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 9a57d0d0ac..8d393c7a08 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -143,6 +143,8 @@ static void lsp_destroy(struct isis_lsp *lsp) if (lsp->pdu) stream_free(lsp->pdu); + + fabricd_lsp_free(lsp); XFREE(MTYPE_ISIS_LSP, lsp); } @@ -384,6 +386,7 @@ static void lsp_purge(struct isis_lsp *lsp, int level, lsp->hdr.rem_lifetime = 0; lsp->level = level; lsp->age_out = lsp->area->max_lsp_lifetime[level - 1]; + lsp->area->lsp_purge_count[level - 1]++; lsp_purge_add_poi(lsp, sender); @@ -611,7 +614,7 @@ static void lsp_set_time(struct isis_lsp *lsp) stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime); } -static void lspid_print(uint8_t *lsp_id, uint8_t *trg, char dynhost, char frag) +void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag) { struct isis_dynhn *dyn = NULL; uint8_t id[SYSID_STRLEN]; @@ -628,10 +631,10 @@ static void lspid_print(uint8_t *lsp_id, uint8_t *trg, char dynhost, char frag) else memcpy(id, sysid_print(lsp_id), 15); if (frag) - sprintf((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id), + sprintf(dest, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id), LSP_FRAGMENT(lsp_id)); else - sprintf((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id)); + sprintf(dest, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id)); } /* Convert the lsp attribute bits to attribute string */ @@ -660,7 +663,7 @@ static const char *lsp_bits2string(uint8_t lsp_bits, char *buf, size_t buf_size) /* this function prints the lsp on show isis database */ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) { - uint8_t LSPid[255]; + char LSPid[255]; char age_out[8]; char b[200]; @@ -1238,6 +1241,7 @@ int lsp_generate(struct isis_area *area, int level) lsp_seqno_update(newlsp); newlsp->last_generated = time(NULL); lsp_flood(newlsp, NULL); + area->lsp_gen_count[level - 1]++; refresh_time = lsp_refresh_time(newlsp, rem_lifetime); @@ -1298,6 +1302,7 @@ static int lsp_regenerate(struct isis_area *area, int level) lsp->hdr.rem_lifetime = rem_lifetime; lsp->last_generated = time(NULL); lsp_flood(lsp, NULL); + area->lsp_gen_count[level - 1]++; for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { if (!frag->tlvs) { /* Updating and flooding should only affect fragments @@ -1962,6 +1967,7 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, lsp->level = level; lsp_adjust_stream(lsp); lsp->age_out = ZERO_AGE_LIFETIME; + lsp->area->lsp_purge_count[level - 1]++; memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr)); lsp->hdr.rem_lifetime = 0; @@ -1997,12 +2003,21 @@ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set) } } -void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit) +void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit, + const char *func, const char *file, int line) { + if (isis->debugs & DEBUG_FLOODING) { + zlog_debug("Flooding LSP %s%s%s (From %s %s:%d)", + rawlspid_print(lsp->hdr.lsp_id), + circuit ? " except on " : "", + circuit ? circuit->interface->name : "", + func, file, line); + } + if (!fabricd) lsp_set_all_srmflags(lsp, true); else - fabricd_lsp_flood(lsp); + fabricd_lsp_flood(lsp, circuit); if (circuit) isis_tx_queue_del(circuit->tx_queue, lsp); diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 2b45e6994c..e6ea0b4eda 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -47,6 +47,11 @@ struct isis_lsp { int age_out; struct isis_area *area; struct isis_tlvs *tlvs; + + time_t flooding_time; + struct list *flooding_neighbors[TX_LSP_CIRCUIT_SCOPED + 1]; + char *flooding_interface; + bool flooding_circuit_scoped; }; dict_t *lsp_db_init(void); @@ -100,12 +105,17 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level, bool confusion); void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno); +void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag); void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost); void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost); int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost); /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set); -void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit); + +#define lsp_flood(lsp, circuit) \ + _lsp_flood((lsp), (circuit), __func__, __FILE__, __LINE__) +void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit, + const char *func, const char *file, int line); void lsp_init(void); #endif /* ISIS_LSP */ diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 2d540348e4..cda3b2b3c5 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -58,6 +58,7 @@ #include "isisd/isis_bfd.h" #include "isisd/isis_lsp.h" #include "isisd/isis_mt.h" +#include "isisd/fabricd.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" @@ -228,6 +229,7 @@ int main(int argc, char **argv, char **envp) isis_zebra_init(master); isis_bfd_init(); + fabricd_init(); frr_config_fork(); frr_run(master); diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 900ce9f922..6303536c11 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -58,6 +58,7 @@ #include "isisd/isis_errors.h" #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" +#include "isisd/isis_pdu_counter.h" static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, int level) @@ -88,6 +89,7 @@ static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, /* Update PDU length */ stream_putw_at(circuit->snd_stream, lenp, length); + pdu_counter_count(circuit->area->pdu_tx_counters, pdu_type); retval = circuit->tx(circuit, level); if (retval != ISIS_OK) flog_err(EC_ISIS_PACKET, @@ -702,6 +704,16 @@ out: return retval; } +static void lsp_flood_or_update(struct isis_lsp *lsp, + struct isis_circuit *circuit, + bool circuit_scoped) +{ + if (!circuit_scoped) + lsp_flood(lsp, circuit); + else + fabricd_update_lsp_no_flood(lsp, circuit); +} + /* * Process Level 1/2 Link State * ISO - 10589 @@ -931,8 +943,8 @@ dontcheckadj: lsp_confusion); tlvs = NULL; /* ii */ - if (!circuit_scoped) - lsp_flood(lsp, NULL); + lsp_flood_or_update(lsp, NULL, + circuit_scoped); /* v */ ISIS_FLAGS_CLEAR_ALL( lsp->SSNflags); /* FIXME: @@ -977,8 +989,8 @@ dontcheckadj: /* our own LSP -> 7.3.16.4 c) */ if (comp == LSP_NEWER) { lsp_inc_seqno(lsp, hdr.seqno); - if (!circuit_scoped) - lsp_flood(lsp, NULL); + lsp_flood_or_update(lsp, NULL, + circuit_scoped); } else { isis_tx_queue_add(circuit->tx_queue, lsp, TX_LSP_NORMAL); @@ -986,7 +998,9 @@ dontcheckadj: } if (isis->debugs & DEBUG_UPDATE_PACKETS) zlog_debug( - "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08" PRIx32, + "ISIS-Upd (%s): (1) " + "re-originating LSP %s new seq " + "0x%08" PRIx32, circuit->area->area_tag, rawlspid_print(hdr.lsp_id), lsp->hdr.seqno); @@ -1068,8 +1082,7 @@ dontcheckadj: circuit->area, level, false); tlvs = NULL; } - if (!circuit_scoped) - lsp_flood(lsp, circuit); + lsp_flood_or_update(lsp, circuit, circuit_scoped); /* iv */ if (circuit->circ_type != CIRCUIT_T_BROADCAST) @@ -1096,9 +1109,7 @@ dontcheckadj: retval = ISIS_OK; out: - if (circuit_scoped) { - fabricd_trigger_csnp(circuit->area); - } + fabricd_trigger_csnp(circuit->area, circuit_scoped); isis_free_tlvs(tlvs); return retval; @@ -1429,6 +1440,8 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) stream_forward_getp(circuit->rcv_stream, 1); /* reserved */ uint8_t max_area_addrs = stream_getc(circuit->rcv_stream); + pdu_counter_count(circuit->area->pdu_rx_counters, pdu_type); + if (idrp == ISO9542_ESIS) { flog_err(EC_LIB_DEVELOPMENT, "No support for ES-IS packet IDRP=%" PRIx8, idrp); @@ -1581,15 +1594,18 @@ void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream) stream_putc(stream, 0); /* Max Area Addresses 0 => 3 */ } -static void put_hello_hdr(struct isis_circuit *circuit, int level, - size_t *len_pointer) +static uint8_t hello_pdu_type(struct isis_circuit *circuit, int level) { - uint8_t pdu_type; - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - pdu_type = (level == IS_LEVEL_1) ? L1_LAN_HELLO : L2_LAN_HELLO; + return (level == IS_LEVEL_1) ? L1_LAN_HELLO : L2_LAN_HELLO; else - pdu_type = P2P_HELLO; + return P2P_HELLO; +} + +static void put_hello_hdr(struct isis_circuit *circuit, int level, + size_t *len_pointer) +{ + uint8_t pdu_type = hello_pdu_type(circuit, level); isis_circuit_stream(circuit, &circuit->snd_stream); fill_fixed_hdr(pdu_type, circuit->snd_stream); @@ -1732,6 +1748,8 @@ int send_hello(struct isis_circuit *circuit, int level) isis_free_tlvs(tlvs); + pdu_counter_count(circuit->area->pdu_tx_counters, + hello_pdu_type(circuit, level)); retval = circuit->tx(circuit, level); if (retval != ISIS_OK) flog_err(EC_ISIS_PACKET, @@ -1745,9 +1763,8 @@ int send_hello(struct isis_circuit *circuit, int level) static int send_hello_cb(struct thread *thread) { struct isis_circuit_arg *arg = THREAD_ARG(thread); - assert(arg); - + struct isis_circuit *circuit = arg->circuit; int level = arg->level; @@ -1858,10 +1875,11 @@ int send_csnp(struct isis_circuit *circuit, int level) || dict_count(circuit->area->lspdb[level - 1]) == 0) return ISIS_OK; + uint8_t pdu_type = (level == ISIS_LEVEL1) ? L1_COMPLETE_SEQ_NUM + : L2_COMPLETE_SEQ_NUM; + isis_circuit_stream(circuit, &circuit->snd_stream); - fill_fixed_hdr((level == ISIS_LEVEL1) ? L1_COMPLETE_SEQ_NUM - : L2_COMPLETE_SEQ_NUM, - circuit->snd_stream); + fill_fixed_hdr(pdu_type, circuit->snd_stream); size_t len_pointer = stream_get_endp(circuit->snd_stream); stream_putw(circuit->snd_stream, 0); @@ -1943,6 +1961,7 @@ int send_csnp(struct isis_circuit *circuit, int level) stream_get_endp(circuit->snd_stream)); } + pdu_counter_count(circuit->area->pdu_tx_counters, pdu_type); int retval = circuit->tx(circuit, level); if (retval != ISIS_OK) { flog_err(EC_ISIS_PACKET, @@ -2036,10 +2055,11 @@ static int send_psnp(int level, struct isis_circuit *circuit) if (!circuit->snd_stream) return ISIS_ERROR; + uint8_t pdu_type = (level == ISIS_LEVEL1) ? L1_PARTIAL_SEQ_NUM + : L2_PARTIAL_SEQ_NUM; + isis_circuit_stream(circuit, &circuit->snd_stream); - fill_fixed_hdr((level == ISIS_LEVEL1) ? L1_PARTIAL_SEQ_NUM - : L2_PARTIAL_SEQ_NUM, - circuit->snd_stream); + fill_fixed_hdr(pdu_type, circuit->snd_stream); size_t len_pointer = stream_get_endp(circuit->snd_stream); stream_putw(circuit->snd_stream, 0); /* length is filled in later */ @@ -2110,6 +2130,7 @@ static int send_psnp(int level, struct isis_circuit *circuit) stream_get_endp(circuit->snd_stream)); } + pdu_counter_count(circuit->area->pdu_tx_counters, pdu_type); int retval = circuit->tx(circuit, level); if (retval != ISIS_OK) { flog_err(EC_ISIS_PACKET, @@ -2182,9 +2203,9 @@ int send_l2_psnp(struct thread *thread) /* * ISO 10589 - 7.3.14.3 */ -void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type) +void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp, + enum isis_tx_type tx_type) { - struct isis_circuit *circuit = arg; int clear_srm = 1; int retval = ISIS_OK; @@ -2229,14 +2250,18 @@ void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type) if (tx_type == TX_LSP_CIRCUIT_SCOPED) { stream_putc_at(circuit->snd_stream, 4, FS_LINK_STATE); - stream_putc_at(circuit->snd_stream, 7, L2_CIRCUIT_FLOODING_SCOPE); + stream_putc_at(circuit->snd_stream, 7, + L2_CIRCUIT_FLOODING_SCOPE); } if (isis->debugs & DEBUG_UPDATE_PACKETS) { - zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32 + zlog_debug("ISIS-Upd (%s): Sending %sL%d LSP %s, seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s on %s", - circuit->area->area_tag, lsp->level, + circuit->area->area_tag, + (tx_type == TX_LSP_CIRCUIT_SCOPED) + ? "Circuit scoped " : "", + lsp->level, rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno, lsp->hdr.checksum, lsp->hdr.rem_lifetime, circuit->interface->name); @@ -2245,7 +2270,12 @@ void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type) stream_get_endp(circuit->snd_stream)); } + uint8_t pdu_type = (tx_type == TX_LSP_CIRCUIT_SCOPED) ? FS_LINK_STATE + : (lsp->level == ISIS_LEVEL1) ? L1_LINK_STATE + : L2_LINK_STATE; + clear_srm = 0; + pdu_counter_count(circuit->area->pdu_tx_counters, pdu_type); retval = circuit->tx(circuit, lsp->level); if (retval != ISIS_OK) { flog_err(EC_ISIS_PACKET, diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index 0fa3b2c7ab..1e70a42f13 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -214,7 +214,8 @@ int send_l1_csnp(struct thread *thread); int send_l2_csnp(struct thread *thread); int send_l1_psnp(struct thread *thread); int send_l2_psnp(struct thread *thread); -void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type); +void send_lsp(struct isis_circuit *circuit, + struct isis_lsp *lsp, enum isis_tx_type tx_type); void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream); int send_hello(struct isis_circuit *circuit, int level); int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa); diff --git a/isisd/isis_pdu_counter.c b/isisd/isis_pdu_counter.c new file mode 100644 index 0000000000..ec2a0c2076 --- /dev/null +++ b/isisd/isis_pdu_counter.c @@ -0,0 +1,104 @@ +/* + * IS-IS Routing protocol - isis_pdu_counter.c + * Copyright (C) 2018 Christian Franke, for NetDEF Inc. + * + * 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 + */ + +#include <zebra.h> + +#include "vty.h" + +#include "isisd/isis_pdu_counter.h" +#include "isisd/isisd.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_pdu.h" + +static int pdu_type_to_counter_index(uint8_t pdu_type) +{ + switch (pdu_type) { + case L1_LAN_HELLO: + return L1_LAN_HELLO_INDEX; + case L2_LAN_HELLO: + return L2_LAN_HELLO_INDEX; + case P2P_HELLO: + return P2P_HELLO_INDEX; + case L1_LINK_STATE: + return L1_LINK_STATE_INDEX; + case L2_LINK_STATE: + return L2_LINK_STATE_INDEX; + case FS_LINK_STATE: + return FS_LINK_STATE_INDEX; + case L1_COMPLETE_SEQ_NUM: + return L1_COMPLETE_SEQ_NUM_INDEX; + case L2_COMPLETE_SEQ_NUM: + return L2_COMPLETE_SEQ_NUM_INDEX; + case L1_PARTIAL_SEQ_NUM: + return L1_PARTIAL_SEQ_NUM_INDEX; + case L2_PARTIAL_SEQ_NUM: + return L2_PARTIAL_SEQ_NUM_INDEX; + default: + return -1; + } +} + +static const char *pdu_counter_index_to_name(enum pdu_counter_index index) +{ + switch (index) { + case L1_LAN_HELLO_INDEX: + return " L1 IIH"; + case L2_LAN_HELLO_INDEX: + return " L2 IIH"; + case P2P_HELLO_INDEX: + return "P2P IIH"; + case L1_LINK_STATE_INDEX: + return " L1 LSP"; + case L2_LINK_STATE_INDEX: + return " L2 LSP"; + case FS_LINK_STATE_INDEX: + return " FS LSP"; + case L1_COMPLETE_SEQ_NUM_INDEX: + return "L1 CSNP"; + case L2_COMPLETE_SEQ_NUM_INDEX: + return "L2 CSNP"; + case L1_PARTIAL_SEQ_NUM_INDEX: + return "L1 PSNP"; + case L2_PARTIAL_SEQ_NUM_INDEX: + return "L2 PSNP"; + default: + return "???????"; + } +} + +void pdu_counter_count(pdu_counter_t counter, uint8_t pdu_type) +{ + int index = pdu_type_to_counter_index(pdu_type); + + if (index < 0) + return; + + counter[index]++; +} + +void pdu_counter_print(struct vty *vty, const char *prefix, + pdu_counter_t counter) +{ + for (int i = 0; i < PDU_COUNTER_SIZE; i++) { + if (!counter[i]) + continue; + vty_out(vty, "%s%s: %" PRIu64 "\n", prefix, + pdu_counter_index_to_name(i), counter[i]); + } +} diff --git a/isisd/isis_pdu_counter.h b/isisd/isis_pdu_counter.h new file mode 100644 index 0000000000..7f07adf5cd --- /dev/null +++ b/isisd/isis_pdu_counter.h @@ -0,0 +1,41 @@ +/* + * IS-IS Routing protocol - isis_pdu_counter.c + * Copyright (C) 2018 Christian Franke, for NetDEF Inc. + * + * 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 + */ +#ifndef ISIS_PDU_COUNTER_H +#define ISIS_PDU_COUNTER_H + +enum pdu_counter_index { + L1_LAN_HELLO_INDEX = 0, + L2_LAN_HELLO_INDEX, + P2P_HELLO_INDEX, + L1_LINK_STATE_INDEX, + L2_LINK_STATE_INDEX, + FS_LINK_STATE_INDEX, + L1_COMPLETE_SEQ_NUM_INDEX, + L2_COMPLETE_SEQ_NUM_INDEX, + L1_PARTIAL_SEQ_NUM_INDEX, + L2_PARTIAL_SEQ_NUM_INDEX, + PDU_COUNTER_SIZE +}; +typedef uint64_t pdu_counter_t[PDU_COUNTER_SIZE]; + +void pdu_counter_print(struct vty *vty, const char *prefix, + pdu_counter_t counter); +void pdu_counter_count(pdu_counter_t counter, uint8_t pdu_type); + +#endif diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index fe67a3f4d1..270dcae7d0 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -30,20 +30,23 @@ #include "dict.h" #include "isisd/isis_circuit.h" #include "isisd/isis_lsp.h" +#include "isisd/isis_misc.h" #include "isisd/isis_tx_queue.h" DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE, "ISIS TX Queue") DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE_ENTRY, "ISIS TX Queue Entry") struct isis_tx_queue { - void *arg; - void (*send_event)(void *arg, struct isis_lsp *, enum isis_tx_type); + struct isis_circuit *circuit; + void (*send_event)(struct isis_circuit *circuit, + struct isis_lsp *, enum isis_tx_type); struct hash *hash; }; struct isis_tx_queue_entry { struct isis_lsp *lsp; enum isis_tx_type type; + bool is_retry; struct thread *retry; struct isis_tx_queue *queue; }; @@ -72,14 +75,15 @@ static bool tx_queue_hash_cmp(const void *a, const void *b) return true; } -struct isis_tx_queue *isis_tx_queue_new(void *arg, - void(*send_event)(void *arg, - struct isis_lsp *, - enum isis_tx_type)) +struct isis_tx_queue *isis_tx_queue_new( + struct isis_circuit *circuit, + void(*send_event)(struct isis_circuit *circuit, + struct isis_lsp *, + enum isis_tx_type)) { struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv)); - rv->arg = arg; + rv->circuit = circuit; rv->send_event = send_event; rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL); @@ -121,19 +125,35 @@ static int tx_queue_send_event(struct thread *thread) e->retry = NULL; thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry); - queue->send_event(queue->arg, e->lsp, e->type); + if (e->is_retry) + queue->circuit->area->lsp_rxmt_count++; + else + e->is_retry = true; + + queue->send_event(queue->circuit, e->lsp, e->type); /* Don't access e here anymore, send_event might have destroyed it */ return 0; } -void isis_tx_queue_add(struct isis_tx_queue *queue, - struct isis_lsp *lsp, - enum isis_tx_type type) +void _isis_tx_queue_add(struct isis_tx_queue *queue, + struct isis_lsp *lsp, + enum isis_tx_type type, + const char *func, const char *file, + int line) { if (!queue) return; + if (isis->debugs & DEBUG_TX_QUEUE) { + zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)", + rawlspid_print(lsp->hdr.lsp_id), + queue->circuit->interface->name, + (type == TX_LSP_CIRCUIT_SCOPED) ? + "circuit scoped" : "regular", + func, file, line); + } + struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp); if (!e) { e = XCALLOC(MTYPE_TX_QUEUE_ENTRY, sizeof(*e)); @@ -150,9 +170,12 @@ void isis_tx_queue_add(struct isis_tx_queue *queue, if (e->retry) thread_cancel(e->retry); thread_add_event(master, tx_queue_send_event, e, 0, &e->retry); + + e->is_retry = false; } -void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp) +void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp, + const char *func, const char *file, int line) { if (!queue) return; @@ -161,6 +184,13 @@ void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp) if (!e) return; + if (isis->debugs & DEBUG_TX_QUEUE) { + zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)", + rawlspid_print(lsp->hdr.lsp_id), + queue->circuit->interface->name, + func, file, line); + } + if (e->retry) thread_cancel(e->retry); diff --git a/isisd/isis_tx_queue.h b/isisd/isis_tx_queue.h index ddecdf1e4f..c2beda45b7 100644 --- a/isisd/isis_tx_queue.h +++ b/isisd/isis_tx_queue.h @@ -29,18 +29,26 @@ enum isis_tx_type { struct isis_tx_queue; -struct isis_tx_queue *isis_tx_queue_new(void *arg, - void(*send_event)(void *arg, - struct isis_lsp *, - enum isis_tx_type)); +struct isis_tx_queue *isis_tx_queue_new( + struct isis_circuit *circuit, + void(*send_event)(struct isis_circuit *circuit, + struct isis_lsp *, + enum isis_tx_type) +); void isis_tx_queue_free(struct isis_tx_queue *queue); -void isis_tx_queue_add(struct isis_tx_queue *queue, - struct isis_lsp *lsp, - enum isis_tx_type type); - -void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp); +#define isis_tx_queue_add(queue, lsp, type) \ + _isis_tx_queue_add((queue), (lsp), (type), \ + __func__, __FILE__, __LINE__) +void _isis_tx_queue_add(struct isis_tx_queue *queue, struct isis_lsp *lsp, + enum isis_tx_type type, const char *func, + const char *file, int line); + +#define isis_tx_queue_del(queue, lsp) \ + _isis_tx_queue_del((queue), (lsp), __func__, __FILE__, __LINE__) +void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp, + const char *func, const char *file, int line); unsigned long isis_tx_queue_len(struct isis_tx_queue *queue); diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 95ebe0de81..aa48fe1d3a 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -23,10 +23,12 @@ #include "command.h" -#include "isisd.h" -#include "isis_vty_common.h" -#include "fabricd.h" -#include "isis_tlvs.h" +#include "isisd/isisd.h" +#include "isisd/isis_vty_common.h" +#include "isisd/fabricd.h" +#include "isisd/isis_tlvs.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_lsp.h" DEFUN (fabric_tier, fabric_tier_cmd, @@ -55,40 +57,136 @@ DEFUN (no_fabric_tier, return CMD_SUCCESS; } -DEFUN (debug_fabric_flooding, - debug_fabric_flooding_cmd, - "debug openfabric flooding", - DEBUG_STR - PROTO_HELP - "Flooding optimization algorithm\n") +DEFUN (triggered_csnp, + triggered_csnp_cmd, + "triggered-csnp-delay (100-10000) [always]", + "Configure the delay for triggered CSNPs\n" + "Delay in milliseconds\n" + "Trigger CSNP for all LSPs, not only circuit-scoped\n") { - isis->debugs |= DEBUG_FABRICD_FLOODING; - print_debug(vty, DEBUG_FABRICD_FLOODING, 1); + VTY_DECLVAR_CONTEXT(isis_area, area); + int csnp_delay = atoi(argv[1]->arg); + bool always_send_csnp = (argc == 3); + + fabricd_configure_triggered_csnp(area, csnp_delay, always_send_csnp); return CMD_SUCCESS; } -DEFUN (no_debug_fabric_flooding, - no_debug_fabric_flooding_cmd, - "no debug openfabric flooding", +DEFUN (no_triggered_csnp, + no_triggered_csnp_cmd, + "no triggered-csnp-delay [(100-10000) [always]]", NO_STR - UNDEBUG_STR - PROTO_HELP - "Flooding optimization algorithm\n") + "Configure the delay for triggered CSNPs\n" + "Delay in milliseconds\n" + "Trigger CSNP for all LSPs, not only circuit-scoped\n") { - isis->debugs &= ~DEBUG_FABRICD_FLOODING; - print_debug(vty, DEBUG_FABRICD_FLOODING, 0); + VTY_DECLVAR_CONTEXT(isis_area, area); + fabricd_configure_triggered_csnp(area, FABRICD_DEFAULT_CSNP_DELAY, + false); return CMD_SUCCESS; } +static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) +{ + char lspid[255]; + + lspid_print(lsp->hdr.lsp_id, lspid, true, true); + vty_out(vty, "Flooding information for %s\n", lspid); + + if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) { + vty_out(vty, " Never received.\n"); + return; + } + + vty_out(vty, " Last received on: %s (", + lsp->flooding_interface ? + lsp->flooding_interface : "(null)"); + + time_t uptime = time(NULL) - lsp->flooding_time; + struct tm *tm = gmtime(&uptime); + + if (uptime < ONE_DAY_SECOND) + vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + vty_out(vty, " ago)\n"); + + if (lsp->flooding_circuit_scoped) { + vty_out(vty, " Received as circuit-scoped LSP, so not " + "flooded.\n"); + return; + } + + for (enum isis_tx_type type = TX_LSP_NORMAL; + type <= TX_LSP_CIRCUIT_SCOPED; type++) { + struct listnode *node; + uint8_t *neighbor_id; + + vty_out(vty, " %s:\n", + (type == TX_LSP_NORMAL) ? "RF" : "DNR"); + for (ALL_LIST_ELEMENTS_RO(lsp->flooding_neighbors[type], + node, neighbor_id)) { + vty_out(vty, " %s\n", + print_sys_hostname(neighbor_id)); + } + } +} + +DEFUN (show_lsp_flooding, + show_lsp_flooding_cmd, + "show openfabric flooding [WORD]", + SHOW_STR + PROTO_HELP + "Flooding information\n" + "LSP ID\n") +{ + const char *lspid = NULL; + + if (argc == 4) + lspid = argv[3]->arg; + + struct listnode *node; + struct isis_area *area; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + dict_t *lspdb = area->lspdb[ISIS_LEVEL2 - 1]; + + vty_out(vty, "Area %s:\n", area->area_tag ? + area->area_tag : "null"); + + if (lspid) { + struct isis_lsp *lsp = lsp_for_arg(lspid, lspdb); + + if (lsp) + lsp_print_flooding(vty, lsp); + + continue; + } + + for (dnode_t *dnode = dict_first(lspdb); dnode; + dnode = dict_next(lspdb, dnode)) { + lsp_print_flooding(vty, dnode_get(dnode)); + vty_out(vty, "\n"); + } + } + + return CMD_SUCCESS; +} void isis_vty_daemon_init(void) { install_element(ROUTER_NODE, &fabric_tier_cmd); install_element(ROUTER_NODE, &no_fabric_tier_cmd); - install_element(ENABLE_NODE, &debug_fabric_flooding_cmd); - install_element(ENABLE_NODE, &no_debug_fabric_flooding_cmd); - install_element(CONFIG_NODE, &debug_fabric_flooding_cmd); - install_element(CONFIG_NODE, &no_debug_fabric_flooding_cmd); + install_element(ROUTER_NODE, &triggered_csnp_cmd); + install_element(ROUTER_NODE, &no_triggered_csnp_cmd); + + install_element(ENABLE_NODE, &show_lsp_flooding_cmd); } diff --git a/isisd/isisd.c b/isisd/isisd.c index ce45ba65ec..0e496193a3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -720,6 +720,9 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS Adjacency related packets debugging is %s\n", onoffs); + if (flags & DEBUG_TX_QUEUE) + vty_out(vty, "IS-IS TX queue debugging is %s\n", + onoffs); if (flags & DEBUG_SNP_PACKETS) vty_out(vty, "IS-IS CSNP/PSNP packets debugging is %s\n", onoffs); @@ -738,8 +741,8 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS LSP generation debugging is %s\n", onoffs); if (flags & DEBUG_LSP_SCHED) vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); - if (flags & DEBUG_FABRICD_FLOODING) - vty_out(vty, "OpenFabric Flooding debugging is %s\n", onoffs); + if (flags & DEBUG_FLOODING) + vty_out(vty, "IS-IS Flooding debugging is %s\n", onoffs); if (flags & DEBUG_BFD) vty_out(vty, "IS-IS BFD debugging is %s\n", onoffs); } @@ -771,6 +774,10 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug " PROTO_NAME " adj-packets\n"); write++; } + if (flags & DEBUG_TX_QUEUE) { + vty_out(vty, "debug " PROTO_NAME " tx-queue\n"); + write++; + } if (flags & DEBUG_SNP_PACKETS) { vty_out(vty, "debug " PROTO_NAME " snp-packets\n"); write++; @@ -803,7 +810,7 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug " PROTO_NAME " lsp-sched\n"); write++; } - if (flags & DEBUG_FABRICD_FLOODING) { + if (flags & DEBUG_FLOODING) { vty_out(vty, "debug " PROTO_NAME " flooding\n"); write++; } @@ -843,6 +850,60 @@ DEFUN (no_debug_isis_adj, return CMD_SUCCESS; } +DEFUN (debug_isis_tx_queue, + debug_isis_tx_queue_cmd, + "debug " PROTO_NAME " tx-queue", + DEBUG_STR + PROTO_HELP + "IS-IS TX queues\n") +{ + isis->debugs |= DEBUG_TX_QUEUE; + print_debug(vty, DEBUG_TX_QUEUE, 1); + + return CMD_SUCCESS; +} + +DEFUN (no_debug_isis_tx_queue, + no_debug_isis_tx_queue_cmd, + "no debug " PROTO_NAME " tx-queue", + NO_STR + UNDEBUG_STR + PROTO_HELP + "IS-IS TX queues\n") +{ + isis->debugs &= ~DEBUG_TX_QUEUE; + print_debug(vty, DEBUG_TX_QUEUE, 0); + + return CMD_SUCCESS; +} + +DEFUN (debug_isis_flooding, + debug_isis_flooding_cmd, + "debug " PROTO_NAME " flooding", + DEBUG_STR + PROTO_HELP + "Flooding algorithm\n") +{ + isis->debugs |= DEBUG_FLOODING; + print_debug(vty, DEBUG_FLOODING, 1); + + return CMD_SUCCESS; +} + +DEFUN (no_debug_isis_flooding, + no_debug_isis_flooding_cmd, + "no debug " PROTO_NAME " flooding", + NO_STR + UNDEBUG_STR + PROTO_HELP + "Flooding algorithm\n") +{ + isis->debugs &= ~DEBUG_FLOODING; + print_debug(vty, DEBUG_FLOODING, 0); + + return CMD_SUCCESS; +} + DEFUN (debug_isis_snp, debug_isis_snp_cmd, "debug " PROTO_NAME " snp-packets", @@ -1197,11 +1258,25 @@ DEFUN (show_isis_summary, } } + vty_out(vty, " TX counters per PDU type:\n"); + pdu_counter_print(vty, " ", area->pdu_tx_counters); + vty_out(vty, " LSP RXMT: %" PRIu64 "\n", + area->lsp_rxmt_count); + vty_out(vty, " RX counters per PDU type:\n"); + pdu_counter_print(vty, " ", area->pdu_rx_counters); + for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { if ((area->is_type & level) == 0) continue; vty_out(vty, " Level-%d:\n", level); + + vty_out(vty, " LSP0 regenerated: %" PRIu64 "\n", + area->lsp_gen_count[level - 1]); + + vty_out(vty, " LSPs purged: %" PRIu64 "\n", + area->lsp_purge_count[level - 1]); + if (area->spf_timer[level - 1]) vty_out(vty, " SPF: (pending)\n"); else @@ -1232,39 +1307,17 @@ DEFUN (show_isis_summary, return CMD_SUCCESS; } -/* - * This function supports following display options: - * [ show isis database [detail] ] - * [ show isis database <sysid> [detail] ] - * [ show isis database <hostname> [detail] ] - * [ show isis database <sysid>.<pseudo-id> [detail] ] - * [ show isis database <hostname>.<pseudo-id> [detail] ] - * [ show isis database <sysid>.<pseudo-id>-<fragment-number> [detail] ] - * [ show isis database <hostname>.<pseudo-id>-<fragment-number> [detail] ] - * [ show isis database detail <sysid> ] - * [ show isis database detail <hostname> ] - * [ show isis database detail <sysid>.<pseudo-id> ] - * [ show isis database detail <hostname>.<pseudo-id> ] - * [ show isis database detail <sysid>.<pseudo-id>-<fragment-number> ] - * [ show isis database detail <hostname>.<pseudo-id>-<fragment-number> ] - */ -static int show_isis_database(struct vty *vty, const char *argv, int ui_level) +struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb) { - struct listnode *node; - struct isis_area *area; - struct isis_lsp *lsp; - struct isis_dynhn *dynhn; - const char *pos; - uint8_t lspid[ISIS_SYS_ID_LEN + 2]; - char sysid[255]; + char sysid[255] = {0}; uint8_t number[3]; - int level, lsp_count; - - if (isis->area_list->count == 0) - return CMD_SUCCESS; + const char *pos; + uint8_t lspid[ISIS_SYS_ID_LEN + 2] = {0}; + struct isis_dynhn *dynhn; + struct isis_lsp *lsp = NULL; - memset(&lspid, 0, ISIS_SYS_ID_LEN); - memset(&sysid, 0, 255); + if (!argv) + return NULL; /* * extract fragment and pseudo id from the string argv @@ -1285,7 +1338,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) (uint8_t)strtol((char *)number, NULL, 16); pos -= 4; if (strncmp(pos, ".", 1) != 0) - return CMD_WARNING; + return NULL; } if (strncmp(pos, ".", 1) == 0) { memcpy(number, ++pos, 2); @@ -1295,6 +1348,51 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) } } + /* + * Try to find the lsp-id if the argv + * string is in + * the form + * hostname.<pseudo-id>-<fragment> + */ + if (sysid2buff(lspid, sysid)) { + lsp = lsp_search(lspid, lspdb); + } else if ((dynhn = dynhn_find_by_name(sysid))) { + memcpy(lspid, dynhn->id, ISIS_SYS_ID_LEN); + lsp = lsp_search(lspid, lspdb); + } else if (strncmp(cmd_hostname_get(), sysid, 15) == 0) { + memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN); + lsp = lsp_search(lspid, lspdb); + } + + return lsp; +} + +/* + * This function supports following display options: + * [ show isis database [detail] ] + * [ show isis database <sysid> [detail] ] + * [ show isis database <hostname> [detail] ] + * [ show isis database <sysid>.<pseudo-id> [detail] ] + * [ show isis database <hostname>.<pseudo-id> [detail] ] + * [ show isis database <sysid>.<pseudo-id>-<fragment-number> [detail] ] + * [ show isis database <hostname>.<pseudo-id>-<fragment-number> [detail] ] + * [ show isis database detail <sysid> ] + * [ show isis database detail <hostname> ] + * [ show isis database detail <sysid>.<pseudo-id> ] + * [ show isis database detail <hostname>.<pseudo-id> ] + * [ show isis database detail <sysid>.<pseudo-id>-<fragment-number> ] + * [ show isis database detail <hostname>.<pseudo-id>-<fragment-number> ] + */ +static int show_isis_database(struct vty *vty, const char *argv, int ui_level) +{ + struct listnode *node; + struct isis_area *area; + struct isis_lsp *lsp; + int level, lsp_count; + + if (isis->area_list->count == 0) + return CMD_SUCCESS; + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); @@ -1302,35 +1400,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) for (level = 0; level < ISIS_LEVELS; level++) { if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) { - lsp = NULL; - if (argv != NULL) { - /* - * Try to find the lsp-id if the argv - * string is in - * the form - * hostname.<pseudo-id>-<fragment> - */ - if (sysid2buff(lspid, sysid)) { - lsp = lsp_search( - lspid, - area->lspdb[level]); - } else if ((dynhn = dynhn_find_by_name( - sysid))) { - memcpy(lspid, dynhn->id, - ISIS_SYS_ID_LEN); - lsp = lsp_search( - lspid, - area->lspdb[level]); - } else if (strncmp(cmd_hostname_get(), - sysid, 15) - == 0) { - memcpy(lspid, isis->sysid, - ISIS_SYS_ID_LEN); - lsp = lsp_search( - lspid, - area->lspdb[level]); - } - } + lsp = lsp_for_arg(argv, area->lspdb[level]); if (lsp != NULL || argv == NULL) { vty_out(vty, @@ -2061,6 +2131,10 @@ void isis_init() install_element(ENABLE_NODE, &debug_isis_adj_cmd); install_element(ENABLE_NODE, &no_debug_isis_adj_cmd); + install_element(ENABLE_NODE, &debug_isis_tx_queue_cmd); + install_element(ENABLE_NODE, &no_debug_isis_tx_queue_cmd); + install_element(ENABLE_NODE, &debug_isis_flooding_cmd); + install_element(ENABLE_NODE, &no_debug_isis_flooding_cmd); install_element(ENABLE_NODE, &debug_isis_snp_cmd); install_element(ENABLE_NODE, &no_debug_isis_snp_cmd); install_element(ENABLE_NODE, &debug_isis_upd_cmd); @@ -2082,6 +2156,10 @@ void isis_init() install_element(CONFIG_NODE, &debug_isis_adj_cmd); install_element(CONFIG_NODE, &no_debug_isis_adj_cmd); + install_element(CONFIG_NODE, &debug_isis_tx_queue_cmd); + install_element(CONFIG_NODE, &no_debug_isis_tx_queue_cmd); + install_element(CONFIG_NODE, &debug_isis_flooding_cmd); + install_element(CONFIG_NODE, &no_debug_isis_flooding_cmd); install_element(CONFIG_NODE, &debug_isis_snp_cmd); install_element(CONFIG_NODE, &no_debug_isis_snp_cmd); install_element(CONFIG_NODE, &debug_isis_upd_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index fe9abff93c..2c0ea203f3 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -28,6 +28,7 @@ #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_redist.h" +#include "isisd/isis_pdu_counter.h" #include "isis_flags.h" #include "dict.h" #include "isis_memory.h" @@ -148,6 +149,8 @@ struct isis_area { uint16_t min_spf_interval[ISIS_LEVELS]; /* the percentage of LSP mtu size used, before generating a new frag */ int lsp_frag_threshold; + uint64_t lsp_gen_count[ISIS_LEVELS]; + uint64_t lsp_purge_count[ISIS_LEVELS]; int ip_circuits; /* logging adjacency changes? */ uint8_t log_adj_changes; @@ -168,6 +171,10 @@ struct isis_area { struct lsp_refresh_arg lsp_refresh_arg[ISIS_LEVELS]; + pdu_counter_t pdu_tx_counters; + pdu_counter_t pdu_rx_counters; + uint64_t lsp_rxmt_count; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(isis_area) @@ -178,6 +185,7 @@ struct isis_area *isis_area_create(const char *); struct isis_area *isis_area_lookup(const char *); int isis_area_get(struct vty *vty, const char *area_tag); void print_debug(struct vty *, int, int); +struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb); void isis_area_invalidate_routes(struct isis_area *area, int levels); void isis_area_verify_routes(struct isis_area *area); @@ -212,8 +220,9 @@ extern struct thread_master *master; #define DEBUG_PACKET_DUMP (1<<6) #define DEBUG_LSP_GEN (1<<7) #define DEBUG_LSP_SCHED (1<<8) -#define DEBUG_FABRICD_FLOODING (1<<9) +#define DEBUG_FLOODING (1<<9) #define DEBUG_BFD (1<<10) +#define DEBUG_TX_QUEUE (1<<11) #define lsp_debug(...) \ do { \ diff --git a/isisd/subdir.am b/isisd/subdir.am index 552bc49b80..29ec1cdd17 100644 --- a/isisd/subdir.am +++ b/isisd/subdir.am @@ -43,6 +43,7 @@ noinst_HEADERS += \ isisd/isis_mt.h \ isisd/isis_network.h \ isisd/isis_pdu.h \ + isisd/isis_pdu_counter.h \ isisd/isis_redist.h \ isisd/isis_route.h \ isisd/isis_routemap.h \ @@ -74,6 +75,7 @@ LIBISIS_SOURCES = \ isisd/isis_misc.c \ isisd/isis_mt.c \ isisd/isis_pdu.c \ + isisd/isis_pdu_counter.c \ isisd/isis_redist.c \ isisd/isis_route.c \ isisd/isis_routemap.c \ diff --git a/lib/northbound.c b/lib/northbound.c index 8b96dc4a6c..09aa60b1d2 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -1071,7 +1071,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, /* Iterate over all list entries. */ do { struct yang_list_keys list_keys; - char xpath[XPATH_MAXLEN]; + char xpath[XPATH_MAXLEN * 2]; int ret; /* Obtain list entry. */ diff --git a/lib/zebra.h b/lib/zebra.h index 46721cc1ab..0f3f45f7ba 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -410,18 +410,47 @@ extern const char *zserv_command_string(unsigned int command); #define strmatch(a,b) (!strcmp((a), (b))) /* Zebra message flags */ + +/* + * Cause Zebra to consider this routes nexthops recursively + */ #define ZEBRA_FLAG_ALLOW_RECURSION 0x01 +/* + * This is a route that is read in on startup that was left around + * from a previous run of FRR + */ #define ZEBRA_FLAG_SELFROUTE 0x02 -#define ZEBRA_FLAG_IBGP 0x08 -#define ZEBRA_FLAG_SELECTED 0x10 -#define ZEBRA_FLAG_STATIC 0x40 -#define ZEBRA_FLAG_SCOPE_LINK 0x100 -#define ZEBRA_FLAG_FIB_OVERRIDE 0x200 -#define ZEBRA_FLAG_EVPN_ROUTE 0x400 -#define ZEBRA_FLAG_RR_USE_DISTANCE 0x800 -#define ZEBRA_FLAG_ONLINK 0x1000 -/* ZEBRA_FLAG_BLACKHOLE was 0x04 */ -/* ZEBRA_FLAG_REJECT was 0x80 */ +/* + * This flag is used to tell Zebra that the BGP route being passed + * down is a IBGP route + */ +#define ZEBRA_FLAG_IBGP 0x04 +/* + * This is a route that has been selected for FIB installation. + * This flag is set in zebra and can be passed up to routing daemons + */ +#define ZEBRA_FLAG_SELECTED 0x08 +/* + * This is a route that we are telling Zebra that this route *must* + * win and will be installed even over ZEBRA_FLAG_SELECTED + */ +#define ZEBRA_FLAG_FIB_OVERRIDE 0x10 +/* + * This flag tells Zebra that the route is a EVPN route and should + * be treated specially + */ +#define ZEBRA_FLAG_EVPN_ROUTE 0x20 +/* + * This flag tells Zebra that it should treat the distance passed + * down as an additional discriminator for route selection of the + * route entry. This mainly is used for backup static routes. + */ +#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40 +/* + * This flag tells Zebra that the passed down route is ONLINK and the + * kernel install flag for it should be turned on + */ +#define ZEBRA_FLAG_ONLINK 0x80 /* Zebra FEC flags. */ #define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1 diff --git a/tests/topotests/bgp-vrf-route-leak-basic/r1/bgpd.conf b/tests/topotests/bgp-vrf-route-leak-basic/r1/bgpd.conf new file mode 100644 index 0000000000..626c268392 --- /dev/null +++ b/tests/topotests/bgp-vrf-route-leak-basic/r1/bgpd.conf @@ -0,0 +1,14 @@ +hostname r1 + +router bgp 99 vrf DONNA + address-family ipv4 unicast + redistribute connected + import vrf EVA + ! +! +router bgp 99 vrf EVA + address-family ipv4 unicast + redistribute connected + import vrf DONNA + ! +!
\ No newline at end of file diff --git a/tests/topotests/bgp-vrf-route-leak-basic/r1/zebra.conf b/tests/topotests/bgp-vrf-route-leak-basic/r1/zebra.conf new file mode 100644 index 0000000000..35038557df --- /dev/null +++ b/tests/topotests/bgp-vrf-route-leak-basic/r1/zebra.conf @@ -0,0 +1,18 @@ +hostname r1 + +int dummy1 + ip address 10.0.0.1/24 + no shut +! +int dummy2 + ip address 10.0.1.1/24 + no shut +! +int dummy3 + ip address 10.0.2.1/24 + no shut +! +int dummy4 + ip address 10.0.3.1/24 + no shut +! diff --git a/tests/topotests/bgp-vrf-route-leak-basic/setup_vrfs b/tests/topotests/bgp-vrf-route-leak-basic/setup_vrfs new file mode 100644 index 0000000000..fb67953fe3 --- /dev/null +++ b/tests/topotests/bgp-vrf-route-leak-basic/setup_vrfs @@ -0,0 +1,16 @@ +#!/bin/bash + +ip link add DONNA type vrf table 1001 +ip link add EVA type vrf table 1002 + +ip link add dummy1 type dummy +ip link add dummy2 type dummy +ip link add dummy3 type dummy +ip link add dummy4 type dummy + +ip link set dummy1 master DONNA +ip link set dummy2 master EVA +ip link set dummy3 master DONNA +ip link set dummy4 master EVA + + diff --git a/tests/topotests/bgp-vrf-route-leak-basic/test_bgp.py b/tests/topotests/bgp-vrf-route-leak-basic/test_bgp.py new file mode 100644 index 0000000000..b0d60403db --- /dev/null +++ b/tests/topotests/bgp-vrf-route-leak-basic/test_bgp.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python + +# +# test_bgp.py +# +# Copyright (c) 2018 Cumulus Networks, Inc. +# Donald Sharp +# +# 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 Cumulus Networks 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.py: Test basic vrf route leaking +""" + +import json +import os +import sys +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +from mininet.topo import Topo + + +class BGPVRFTopo(Topo): + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + for routern in range(1, 2): + tgen.add_router('r{}'.format(routern)) + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(BGPVRFTopo, mod.__name__) + tgen.start_topology() + + # For all registered routers, load the zebra configuration file + for rname, router in tgen.routers().iteritems(): + router.run("/bin/bash {}/setup_vrfs".format(CWD)) + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, + os.path.join(CWD, '{}/bgpd.conf'.format(rname)) + ) + + # After loading the configurations, this function loads configured daemons. + tgen.start_router() + #tgen.mininet_cli() + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + +def test_vrf_route_leak(): + logger.info("Ensure that routes are leaked back and forth") + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears['r1'] + + donna = r1.vtysh_cmd("show ip route vrf DONNA json", isjson=True) + route0 = donna["10.0.0.0/24"][0] + assert route0['protocol'] == "connected" + route1 = donna["10.0.1.0/24"][0] + assert route1['protocol'] == "bgp" + assert route1['selected'] == True + nhop = route1['nexthops'][0] + assert nhop['fib'] == True + route2 = donna["10.0.2.0/24"][0] + assert route2['protocol'] == "connected" + route3 = donna["10.0.3.0/24"][0] + assert route3['protocol'] == "bgp" + assert route3['selected'] == True + nhop = route3['nexthops'][0] + assert nhop['fib'] == True + eva = r1.vtysh_cmd("show ip route vrf EVA json", isjson=True) + route0 = eva["10.0.0.0/24"][0] + assert route0['protocol'] == "bgp" + assert route0['selected'] == True + nhop = route0['nexthops'][0] + assert nhop['fib'] == True + route1 = eva["10.0.1.0/24"][0] + assert route1['protocol'] == "connected" + route2 = eva["10.0.2.0/24"][0] + assert route2['protocol'] == "bgp" + assert route2['selected'] == True + nhop = route2['nexthops'][0] + assert nhop['fib'] == True + route3 = eva["10.0.3.0/24"][0] + assert route3['protocol'] == "connected" + #tgen.mininet_cli() + +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/docker/README.md b/tests/topotests/docker/README.md index cdc41fad52..2b40994cf6 100644 --- a/tests/topotests/docker/README.md +++ b/tests/topotests/docker/README.md @@ -10,19 +10,15 @@ Your current user needs to have access to the Docker daemon. Alternatively you can run these commands as root. ```console -make topotests-build make topotests ``` -The first command will build a docker image with all the dependencies needed -to run the topotests. - -The second command will spawn an instance of this image, compile FRR inside +This command will pull the most recent topotests image from dockerhub, compile FRR inside of it, and run the topotests. ## Advanced Usage -Internally, the topotests make target uses a shell script to spawn the docker +Internally, the topotests make target uses a shell script to pull the image and spawn the docker container. There are several environment variables which can be used to modify the behavior @@ -55,3 +51,22 @@ And to compile FRR but drop into a shell instead of running pytest: ```console ./tests/topotests/docker/frr-topotests.sh /bin/bash ``` + +## Development + +The docker image just includes all the components to run the topotests, but not the topotests +themselves. So if you just want to write tests and don't want to make changes to the environment +provided by the docker image. You don't need to build your own docker image if you do not want to. + +When developing new tests, there is one caveat though: The startup script of the container will +run a `git-clean` on its copy of the FRR tree to avoid any pollution of the container with build +artefacts from the host. This will also result in your newly written tests being unavailable in the +container unless at least added to the index with `git-add`. + +If you do want to test changes to the docker image, you can locally build the image and run the tests +without pulling from the registry using the following commands: + +```console +make topotests-build +TOPOTEST_PULL=0 make topotests +``` diff --git a/tests/topotests/docker/frr-topotests.sh b/tests/topotests/docker/frr-topotests.sh index 8e93ed31ff..6d8bea0002 100755 --- a/tests/topotests/docker/frr-topotests.sh +++ b/tests/topotests/docker/frr-topotests.sh @@ -61,6 +61,9 @@ if [[ "$1" = "-h" ]] || [[ "$1" = "--help" ]]; then TOPOTEST_OPTIONS These options are appended to the docker-run command for starting the tests. + TOPOTEST_PULL If set to 0, don't try to pull the most recent + version of the docker image from dockerhub. + TOPOTEST_SANITIZER Controls whether to use the address sanitizer. Enabled by default, set to 0 to disable. @@ -132,6 +135,10 @@ if [ -z "$TOPOTEST_BUILDCACHE" ]; then || docker volume create "${TOPOTEST_BUILDCACHE}" fi +if [ "${TOPOTEST_PULL:-1}" = "1" ]; then + docker pull frrouting/frr:topotests-latest +fi + set -- --rm -i \ -v "$TOPOTEST_LOGS:/tmp" \ -v "$TOPOTEST_FRR:/root/host-frr:ro" \ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 8a7cb0e528..4f89d53e39 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -918,6 +918,9 @@ void rtm_read(struct rt_msghdr *rtm) char ifname[INTERFACE_NAMSIZ + 1]; short ifnlen = 0; struct nexthop nh; + struct prefix p; + ifindex_t ifindex = 0; + afi_t afi; zebra_flags = 0; @@ -951,10 +954,6 @@ void rtm_read(struct rt_msghdr *rtm) if (flags & RTF_PROTO1) SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); - /* This is persistent route. */ - if (flags & RTF_STATIC) - SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC); - memset(&nh, 0, sizeof(nh)); nh.vrf_id = VRF_DEFAULT; @@ -967,9 +966,14 @@ void rtm_read(struct rt_msghdr *rtm) nh.bh_type = BLACKHOLE_NULL; } - if (dest.sa.sa_family == AF_INET) { - struct prefix p; + /* + * Ignore our own messages. + */ + if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) + return; + if (dest.sa.sa_family == AF_INET) { + afi = AFI_IP; p.family = AF_INET; p.u.prefix4 = dest.sin.sin_addr; if (flags & RTF_HOST) @@ -977,146 +981,12 @@ void rtm_read(struct rt_msghdr *rtm) else p.prefixlen = ip_masklen(mask.sin.sin_addr); - /* Catch self originated messages and match them against our - * current RIB. - * At the same time, ignore unconfirmed messages, they should be - * tracked - * by rtm_write() and kernel_rtm_ipv4(). - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) { - char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN]; - int ret; - if (!IS_ZEBRA_DEBUG_RIB) - return; - ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p, - &gate, VRF_DEFAULT); - prefix2str(&p, buf, sizeof(buf)); - switch (rtm->rtm_type) { - case RTM_ADD: - case RTM_GET: - case RTM_CHANGE: - /* The kernel notifies us about a new route in - FIB created by us. - Do we have a correspondent entry in our RIB? - */ - switch (ret) { - case ZEBRA_RIB_NOTFOUND: - zlog_debug( - "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB", - __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - inet_ntop(AF_INET, &gate.sin.sin_addr, - gate_buf, INET_ADDRSTRLEN); - zlog_debug( - "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)", - __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf, gate_buf); - break; - case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR - */ - zlog_debug( - "%s: %s %s: done Ok", __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf); - rib_lookup_and_dump( - (struct prefix_ipv4 *)&p, - VRF_DEFAULT); - return; - break; - } - break; - case RTM_DELETE: - /* The kernel notifies us about a route deleted - by us. Do we still - have it in the RIB? Do we have anything - instead? */ - switch (ret) { - case ZEBRA_RIB_FOUND_EXACT: - zlog_debug( - "%s: %s %s: desync: RR is still in RIB, while already not in FIB", - __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf); - rib_lookup_and_dump( - (struct prefix_ipv4 *)&p, - VRF_DEFAULT); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - zlog_debug( - "%s: %s %s: desync: RR is still in RIB, plus gate differs", - __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf); - rib_lookup_and_dump( - (struct prefix_ipv4 *)&p, - VRF_DEFAULT); - break; - case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ - zlog_debug( - "%s: %s %s: done Ok", __func__, - lookup_msg(rtm_type_str, - rtm->rtm_type, NULL), - buf); - rib_lookup_and_dump( - (struct prefix_ipv4 *)&p, - VRF_DEFAULT); - return; - break; - } - break; - default: - zlog_debug( - "%s: %s: warning: loopback RTM of type %s received", - __func__, buf, - lookup_msg(rtm_type_str, rtm->rtm_type, - NULL)); - } - return; - } - - /* Change, delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - NULL, 0, 0, 0, true); - if (!nh.type) { nh.type = NEXTHOP_TYPE_IPV4; nh.gate.ipv4 = gate.sin.sin_addr; } - - if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, 0, 0); - else - rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, true); - } - if (dest.sa.sa_family == AF_INET6) { - /* One day we might have a debug section here like one in the - * IPv4 case above. Just ignore own messages at the moment. - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) - return; - struct prefix p; - ifindex_t ifindex = 0; - + } else if (dest.sa.sa_family == AF_INET6) { + afi = AFI_IP6; p.family = AF_INET6; p.u.prefix6 = dest.sin6.sin6_addr; if (flags & RTF_HOST) @@ -1131,31 +1001,29 @@ void rtm_read(struct rt_msghdr *rtm) } #endif /* KAME */ - /* CHANGE: delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - NULL, 0, 0, 0, true); - if (!nh.type) { nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX : NEXTHOP_TYPE_IPV6; nh.gate.ipv6 = gate.sin6.sin6_addr; nh.ifindex = ifindex; } + } else + return; - if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, 0, 0); - else - rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, - ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, true); - } + /* + * CHANGE: delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, NULL, 0, 0, 0, true); + if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) + rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, + zebra_flags, &p, NULL, &nh, 0, 0, 0, 0, 0); + else + rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, + 0, zebra_flags, &p, NULL, &nh, 0, 0, 0, true); } /* Interface function for the kernel routing table updates. Support diff --git a/zebra/rib.h b/zebra/rib.h index 97eae79f03..ae25a0e679 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -282,8 +282,6 @@ extern enum multicast_mode multicast_mode_ipv4_get(void); extern void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id); extern void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id); -extern int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, - vrf_id_t vrf_id); #define ZEBRA_RIB_LOOKUP_ERROR -1 #define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_NOGATE 1 diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index f2d07310ee..c7ad2508fe 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -412,7 +412,7 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ static int nexthop_active(afi_t afi, struct route_entry *re, - struct nexthop *nexthop, int set, + struct nexthop *nexthop, bool set, struct route_node *top) { struct prefix p; @@ -808,84 +808,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) return NULL; } -/* - * This clone function, unlike its original rib_lookup_ipv4(), checks - * if specified IPv4 route record (prefix/mask -> gate) exists in - * the whole RIB and has ROUTE_ENTRY_SELECTED_FIB set. - * - * Return values: - * -1: error - * 0: exact match found - * 1: a match was found with a different gate - * 2: connected route found - * 3: no matches found - */ -int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, - vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *match = NULL; - struct nexthop *nexthop; - int nexthops_active; - rib_dest_t *dest; - - /* Lookup table. */ - table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); - if (!table) - return ZEBRA_RIB_LOOKUP_ERROR; - - /* Scan the RIB table for exactly matching RIB entry. */ - rn = route_node_lookup(table, (struct prefix *)p); - - /* No route for this prefix. */ - if (!rn) - return ZEBRA_RIB_NOTFOUND; - - /* Unlock node. */ - route_unlock_node(rn); - dest = rib_dest_from_rnode(rn); - - /* Find out if a "selected" RR for the discovered RIB entry exists ever. - */ - if (dest && dest->selected_fib - && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED)) - match = dest->selected_fib; - - /* None such found :( */ - if (!match) - return ZEBRA_RIB_NOTFOUND; - - if (match->type == ZEBRA_ROUTE_CONNECT) - return ZEBRA_RIB_FOUND_CONNECTED; - - /* Ok, we have a cood candidate, let's check it's nexthop list... */ - nexthops_active = 0; - for (ALL_NEXTHOPS(match->ng, nexthop)) - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { - nexthops_active = 1; - if (nexthop->gate.ipv4.s_addr == sockunion2ip(qgate)) - return ZEBRA_RIB_FOUND_EXACT; - if (IS_ZEBRA_DEBUG_RIB) { - char gate_buf[INET_ADDRSTRLEN], - qgate_buf[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &nexthop->gate.ipv4.s_addr, - gate_buf, INET_ADDRSTRLEN); - inet_ntop(AF_INET, &sockunion2ip(qgate), - qgate_buf, INET_ADDRSTRLEN); - zlog_debug("%s: qgate == %s, %s == %s", - __func__, qgate_buf, - nexthop->rparent ? "rgate" : "gate", - gate_buf); - } - } - - if (nexthops_active) - return ZEBRA_RIB_FOUND_NOGATE; - - return ZEBRA_RIB_NOTFOUND; -} - #define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) @@ -904,7 +826,7 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, static unsigned nexthop_active_check(struct route_node *rn, struct route_entry *re, - struct nexthop *nexthop, int set) + struct nexthop *nexthop, bool set) { struct interface *ifp; route_map_result_t ret = RMAP_MATCH; @@ -1031,7 +953,7 @@ static unsigned nexthop_active_check(struct route_node *rn, */ static int nexthop_active_update(struct route_node *rn, struct route_entry *re, - int set) + bool set) { struct nexthop *nexthop; union g_addr prev_src; @@ -1322,7 +1244,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active * or not. */ - if (!nexthop_active_update(rn, new, 1)) { + if (!nexthop_active_update(rn, new, true)) { UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); return; } @@ -1383,7 +1305,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, * down, causing the kernel to delete routes without sending DELROUTE * notifications */ - if (!nexthop_active_update(rn, old, 1) && + if (!nexthop_active_update(rn, old, true) && (RIB_KERNEL_ROUTE(old))) SET_FLAG(old->status, ROUTE_ENTRY_REMOVED); else @@ -1408,7 +1330,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update the nexthop; we could determine here that nexthop is * inactive. */ - if (nexthop_active_update(rn, new, 1)) + if (nexthop_active_update(rn, new, true)) nh_active = 1; /* If nexthop is active, install the selected route, if @@ -1533,7 +1455,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update prior route. */ if (new != old) { /* Set real nexthop. */ - nexthop_active_update(rn, old, 1); + nexthop_active_update(rn, old, true); UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); } @@ -1682,7 +1604,7 @@ static void rib_process(struct route_node *rn) * recursive NHs. */ if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) - && !nexthop_active_update(rn, re, 0)) { + && !nexthop_active_update(rn, re, false)) { if (re->type == ZEBRA_ROUTE_TABLE) { /* XXX: HERE BE DRAGONS!!!!! * In all honesty, I have not yet figured out @@ -1774,7 +1696,7 @@ static void rib_process(struct route_node *rn) if (old_selected != new_selected || selected_changed) { if (new_selected && new_selected != new_fib) { - nexthop_active_update(rn, new_selected, 1); + nexthop_active_update(rn, new_selected, true); UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); } |
