diff options
| -rw-r--r-- | bgpd/bgp_evpn.c | 29 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.c | 58 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.h | 6 | ||||
| -rw-r--r-- | bgpd/bgp_main.c | 10 | ||||
| -rw-r--r-- | bgpd/bgp_nb_config.c | 102 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 4 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 19 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 48 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 2 | ||||
| -rw-r--r-- | tests/lib/test_assert.c | 2 | ||||
| -rw-r--r-- | zebra/redistribute.c | 17 |
11 files changed, 192 insertions, 105 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index fae3f1000f..d8e57419ee 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -3562,8 +3562,12 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) const struct prefix_evpn *evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest); - /* Identify MAC-IP local routes. */ - if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + /* + * We have already processed type-3 routes. + * Process only type-1 and type-2 routes here. + */ + if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE + && evp->prefix.route_type != BGP_EVPN_AD_ROUTE) continue; for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) @@ -3581,10 +3585,23 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi, evp, &vpn->prd); assert(global_dest); - update_evpn_route_entry(bgp, vpn, afi, safi, global_dest, attr, 1, - &global_pi, 0, - mac_mobility_seqnum(attr), + + if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { + /* Type-2 route */ + update_evpn_route_entry( + bgp, vpn, afi, safi, global_dest, attr, 1, + &global_pi, 0, mac_mobility_seqnum(attr), false /* setup_sync */, NULL /* old_is_sync */); + } else { + /* Type-1 route */ + struct bgp_evpn_es *es; + int route_changed = 0; + + es = bgp_evpn_es_find(&evp->prefix.ead_addr.esi); + bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, + global_dest, attr, 1, + &global_pi, &route_changed); + } /* Schedule for processing and unlock node. */ bgp_process(bgp, global_dest, afi, safi); @@ -3630,6 +3647,8 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) bgp_dest_unlock_node(global_dest); } + + delete_global_ead_evi_routes(bgp, vpn); return 0; } diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 6467ff8a28..59bced6f93 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -347,11 +347,10 @@ static void bgp_evpn_es_route_del_all(struct bgp *bgp, struct bgp_evpn_es *es) * Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and * ESR). */ -static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, - struct bgpevpn *vpn, afi_t afi, safi_t safi, - struct bgp_dest *dest, struct attr *attr, - int add, struct bgp_path_info **ri, - int *route_changed) +int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, + struct bgpevpn *vpn, afi_t afi, safi_t safi, + struct bgp_dest *dest, struct attr *attr, int add, + struct bgp_path_info **ri, int *route_changed) { struct bgp_path_info *tmp_pi = NULL; struct bgp_path_info *local_pi = NULL; /* local route entry if any */ @@ -384,7 +383,8 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, flog_err( EC_BGP_ES_INVALID, "%u ERROR: local es route for ESI: %s Vtep %pI4 also learnt from remote", - bgp->vrf_id, es->esi_str, &es->originator_ip); + bgp->vrf_id, es ? es->esi_str : "Null", + &es->originator_ip); return -1; } @@ -441,7 +441,7 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) zlog_debug( "local ES %s vni %u route-type %s nexthop %pI4 updated", - es->esi_str, vpn ? vpn->vni : 0, + es ? es->esi_str : "Null", vpn ? vpn->vni : 0, evp->prefix.route_type == BGP_EVPN_ES_ROUTE ? "esr" : (vpn ? "ead-evi" : "ead-es"), @@ -524,6 +524,50 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es, return 0; } +/* + * This function is called when the VNI RD changes. + * Delete all EAD/EVI local routes for this VNI from the global routing table. + * These routes are scheduled for withdraw from peers. + */ +int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn) +{ + afi_t afi; + safi_t safi; + struct bgp_dest *rdrn, *rn; + struct bgp_table *table; + struct bgp_path_info *pi; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + + /* Find the RD node for the VNI in the global table */ + rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd); + if (rdrn && bgp_dest_has_bgp_path_info_data(rdrn)) { + table = bgp_dest_get_bgp_table_info(rdrn); + + /* + * Iterate over all the routes in this table and delete EAD/EVI + * routes + */ + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + if (evp->prefix.route_type != BGP_EVPN_AD_ROUTE) + continue; + + delete_evpn_route_entry(bgp, afi, safi, rn, &pi); + if (pi) + bgp_process(bgp, rn, afi, safi); + } + } + + /* Unlock RD node. */ + if (rdrn) + bgp_dest_unlock_node(rdrn); + + return 0; +} + /***************************************************************************** * Ethernet Segment (Type-4) Routes * ESRs are used for DF election. Currently service-carving described in diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index c96de86871..22a4215664 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -377,6 +377,12 @@ extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, struct prefix_evpn *evp, struct bgp_path_info *pi, int install); extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn); +extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn); +extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, + struct bgpevpn *vpn, afi_t afi, safi_t safi, + struct bgp_dest *dest, struct attr *attr, + int add, struct bgp_path_info **ri, + int *route_changed); int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi, struct attr *attr, uint8_t *pfx, int psize, uint32_t addpath_id); diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index ddc5c61ee7..d545becded 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -314,9 +314,6 @@ static int bgp_vrf_enable(struct vrf *vrf) bgp_vrf_link(bgp, vrf); bgp_handle_socket(bgp, vrf, old_vrf_id, true); - /* Update any redistribution if vrf_id changed */ - if (old_vrf_id != bgp->vrf_id) - bgp_redistribute_redo(bgp); bgp_instance_up(bgp); vpn_leak_zebra_vrf_label_update(bgp, AFI_IP); vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); @@ -336,7 +333,6 @@ static int bgp_vrf_enable(struct vrf *vrf) static int bgp_vrf_disable(struct vrf *vrf) { struct bgp *bgp; - vrf_id_t old_vrf_id; if (vrf->vrf_id == VRF_DEFAULT) return 0; @@ -358,15 +354,11 @@ static int bgp_vrf_disable(struct vrf *vrf) vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6, bgp_get_default(), bgp); - old_vrf_id = bgp->vrf_id; bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false); /* We have instance configured, unlink from VRF and make it * "down". */ - bgp_vrf_unlink(bgp, vrf); - /* Delete any redistribute vrf bitmaps if the vrf_id changed */ - if (old_vrf_id != bgp->vrf_id) - bgp_unset_redist_vrf_bitmaps(bgp, old_vrf_id); bgp_instance_down(bgp); + bgp_vrf_unlink(bgp, vrf); } /* Note: This is a callback, the VRF will be deleted by the caller. */ diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index ff2c8ce93e..8ca7836a99 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -111,15 +111,24 @@ int bgp_router_create(struct nb_cb_create_args *args) is_new_bgp = (bgp_lookup_by_name(name) == NULL); ret = bgp_get_vty(&bgp, &as, name, inst_type); - switch (ret) { - case BGP_ERR_AS_MISMATCH: - snprintf(args->errmsg, args->errmsg_len, - "BGP instance is already running; AS is %u", - as); - return NB_ERR_INCONSISTENCY; - case BGP_ERR_INSTANCE_MISMATCH: - snprintf(args->errmsg, args->errmsg_len, - "BGP instance type mismatch"); + if (ret) { + switch (ret) { + case BGP_ERR_AS_MISMATCH: + snprintf( + args->errmsg, args->errmsg_len, + "BGP instance is already running; AS is %u", + as); + break; + case BGP_ERR_INSTANCE_MISMATCH: + snprintf(args->errmsg, args->errmsg_len, + "BGP instance type mismatch"); + break; + } + + UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO); + + nb_running_set_entry(args->dnode, bgp); + return NB_ERR_INCONSISTENCY; } @@ -221,64 +230,26 @@ int bgp_router_destroy(struct nb_cb_destroy_args *args) int bgp_global_local_as_modify(struct nb_cb_modify_args *args) { struct bgp *bgp; - as_t as; - const struct lyd_node *vrf_dnode; - const char *vrf_name; - const char *name = NULL; - enum bgp_instance_type inst_type; - int ret; - bool is_view_inst = false; switch (args->event) { case NB_EV_VALIDATE: - as = yang_dnode_get_uint32(args->dnode, NULL); - - inst_type = BGP_INSTANCE_TYPE_DEFAULT; - - vrf_dnode = yang_dnode_get_parent(args->dnode, - "control-plane-protocol"); - vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf"); - - if (strmatch(vrf_name, VRF_DEFAULT_NAME)) { - name = NULL; - } else { - name = vrf_name; - inst_type = BGP_INSTANCE_TYPE_VRF; - } - - is_view_inst = yang_dnode_get_bool(args->dnode, - "../instance-type-view"); - if (is_view_inst) - inst_type = BGP_INSTANCE_TYPE_VIEW; - - ret = bgp_lookup_by_as_name_type(&bgp, &as, name, inst_type); - switch (ret) { - case BGP_ERR_AS_MISMATCH: - snprintf(args->errmsg, args->errmsg_len, - "BGP instance is already running; AS is %u", - as); - return NB_ERR_VALIDATION; - case BGP_ERR_INSTANCE_MISMATCH: + /* + * Changing AS number is not allowed, but we must allow it + * once, when the BGP instance is created the first time. + * If the instance already exists - return the validation + * error. + */ + bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent, + NULL, false); + if (bgp) { snprintf(args->errmsg, args->errmsg_len, - "BGP instance type mismatch"); + "Changing AS number is not allowed"); return NB_ERR_VALIDATION; } break; case NB_EV_PREPARE: case NB_EV_ABORT: - return NB_OK; case NB_EV_APPLY: - /* NOTE: handled in bgp_global_create callback, the as change - * will be rejected in validate phase. - */ - as = yang_dnode_get_uint32(args->dnode, NULL); - bgp = nb_running_get_entry(args->dnode, NULL, true); - if (bgp->as != as) { - snprintf(args->errmsg, args->errmsg_len, - "BGP instance is already running; AS is %u", - bgp->as); - return NB_ERR_INCONSISTENCY; - } break; } @@ -1514,12 +1485,27 @@ int bgp_global_global_config_timers_keepalive_modify( */ int bgp_global_instance_type_view_modify(struct nb_cb_modify_args *args) { + struct bgp *bgp; + switch (args->event) { case NB_EV_VALIDATE: + /* + * Changing instance type is not allowed, but we must allow it + * once, when the BGP instance is created the first time. + * If the instance already exists - return the validation + * error. + */ + bgp = nb_running_get_entry_non_rec(args->dnode->parent->parent, + NULL, false); + if (bgp) { + snprintf(args->errmsg, args->errmsg_len, + "Changing instance type is not allowed"); + return NB_ERR_VALIDATION; + } + break; case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 36aa3e1a3e..5b5f166e4b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1380,6 +1380,10 @@ DEFUN_YANG_NOSH(router_bgp, nb_cli_enqueue_change(vty, "./global/instance-type-view", NB_OP_MODIFY, "true"); + } else { + nb_cli_enqueue_change(vty, + "./global/instance-type-view", + NB_OP_MODIFY, "false"); } ret = nb_cli_apply_changes(vty, base_xpath); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 288c2851b3..45b60b4903 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1700,6 +1700,9 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, redist_add_instance(&zclient->mi_redist[afi][type], instance); } else { + if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) + return CMD_WARNING; + #ifdef ENABLE_BGP_VNC if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) { vnc_export_bgp_enable( @@ -1909,22 +1912,6 @@ void bgp_redistribute_redo(struct bgp *bgp) } } -/* Unset redistribute vrf bitmap during triggers like - restart networking or delete VRFs */ -void bgp_unset_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id) -{ - int i; - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (vrf_bitmap_check(zclient->redist[afi][i], - old_vrf_id)) - vrf_bitmap_unset(zclient->redist[afi][i], - old_vrf_id); - return; -} - void bgp_zclient_reset(void) { zclient_reset(zclient); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 21abfeb001..9d2ff9c00e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3378,13 +3378,13 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name, bgp = bgp_get_default(); if (bgp) { + *bgp_val = bgp; if (bgp->as != *as) { *as = bgp->as; return BGP_ERR_AS_MISMATCH; } if (bgp->inst_type != inst_type) return BGP_ERR_INSTANCE_MISMATCH; - *bgp_val = bgp; return BGP_SUCCESS; } *bgp_val = NULL; @@ -3438,6 +3438,46 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, return BGP_CREATED; } +static void bgp_zclient_set_redist(afi_t afi, int type, unsigned short instance, + vrf_id_t vrf_id, bool set) +{ + if (instance) { + if (set) + redist_add_instance(&zclient->mi_redist[afi][type], + instance); + else + redist_del_instance(&zclient->mi_redist[afi][type], + instance); + } else { + if (set) + vrf_bitmap_set(zclient->redist[afi][type], vrf_id); + else + vrf_bitmap_unset(zclient->redist[afi][type], vrf_id); + } +} + +static void bgp_set_redist_vrf_bitmaps(struct bgp *bgp, bool set) +{ + afi_t afi; + int i; + struct list *red_list; + struct listnode *node; + struct bgp_redist *red; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + + red_list = bgp->redist[afi][i]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + bgp_zclient_set_redist(afi, i, red->instance, + bgp->vrf_id, set); + } + } +} + /* * Make BGP instance "up". Applies only to VRFs (non-default) and * implies the VRF has been learnt from Zebra. @@ -3447,6 +3487,8 @@ void bgp_instance_up(struct bgp *bgp) struct peer *peer; struct listnode *node, *next; + bgp_set_redist_vrf_bitmaps(bgp, true); + /* Register with zebra. */ bgp_zebra_instance_register(bgp); @@ -3491,6 +3533,10 @@ void bgp_instance_down(struct bgp *bgp) /* Cleanup registered nexthops (flags) */ bgp_cleanup_nexthops(bgp); + + bgp_zebra_instance_deregister(bgp); + + bgp_set_redist_vrf_bitmaps(bgp, false); } /* Delete BGP instance. */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 38c6a70b8b..4a17b72b7f 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -2386,8 +2386,6 @@ static inline bool bgp_in_graceful_shutdown(struct bgp *bgp) !!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)); } -extern void bgp_unset_redist_vrf_bitmaps(struct bgp *, vrf_id_t); - /* For benefit of rfapi */ extern struct peer *peer_new(struct bgp *bgp); diff --git a/tests/lib/test_assert.c b/tests/lib/test_assert.c index 8f1f4f2bad..a4535651d4 100644 --- a/tests/lib/test_assert.c +++ b/tests/lib/test_assert.c @@ -27,7 +27,7 @@ #include <assert.h> __attribute__((noinline)) -void func_for_bt(int number) +static void func_for_bt(int number) { assert(number > 2); assertf(number > 3, "(A) the number was %d", number); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 7cb426359d..89f46f9c97 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -337,12 +337,17 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS) zvrf_id(zvrf), afi); } } else { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: setting vrf %s(%u) redist bitmap", - __func__, VRF_LOGNAME(zvrf->vrf), - zvrf_id(zvrf)); - vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf)); - zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); + if (!vrf_bitmap_check(client->redist[afi][type], + zvrf_id(zvrf))) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: setting vrf %s(%u) redist bitmap", + __func__, VRF_LOGNAME(zvrf->vrf), + zvrf_id(zvrf)); + vrf_bitmap_set(client->redist[afi][type], + zvrf_id(zvrf)); + zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); + } } stream_failure: |
