From: vivek Date: Fri, 12 Feb 2016 20:18:28 +0000 (-0800) Subject: BGP: VRF registration and cleanup X-Git-Tag: frr-2.0-rc1~1124^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ad4cbda1a32f0bf49d794ab5b156d49f95645871;p=mirror%2Ffrr.git BGP: VRF registration and cleanup Various changes and fixes related to VRF registration, deletion, BGP exit etc. - Define instance type - Ensure proper handling upon instance create, delete and VRF add/delete from zebra - Cleanup upon bgp_exit() - Ensure messages are not sent to zebra for unknown VRFs Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: CM-9128, CM-7203 Reviewed By: CCR-4098 Testing Done: Manual --- diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 791064aca8..962c528948 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -207,11 +207,6 @@ peer_xfer_conn(struct peer *from_peer) return(peer); } -/* Check if suppress start/restart of sessions to peer. */ -#define BGP_PEER_START_SUPPRESSED(P) \ - (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \ - || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - /* Hook function called after bgp event is occered. And vty's neighbor command invoke this function after making neighbor structure. */ diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 02dc3110fe..7c1a9ea4a6 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -236,20 +236,11 @@ bgp_exit (int status) bgp_delete (bgp); list_free (bm->bgp); - /* reverse bgp_zebra_init/if_init */ if (retain_mode) if_add_hook (IF_DELETE_HOOK, NULL); - /*Pending: Must-Do, this needs to be moved in a loop for all the instances.. - Do the iflist lookup for vrf associated with the instance - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) - { - struct listnode *c_node, *c_nnode; - struct connected *c; - for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) - bgp_connected_delete (c); - } - */ + /* free interface and connected route information. */ + bgp_if_finish (); /* reverse bgp_attr_init */ bgp_attr_finish (); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 5b54c4b1f0..9d8d8f3b52 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -539,15 +539,11 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command) /* Check socket. */ if (!zclient || zclient->sock < 0) - { - /* Hiding this error now, because bgp_nht_register_all() is implemented. - which tries it after zclient_connect() - zlog_debug("%s: Can't send NH register, Zebra client not established", - __FUNCTION__); - Pending: remove this comment after reviewing to see if no message is needed in this case - */ - return; - } + return; + + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) + return; p = &(bnc->node->p); s = zclient->obuf; @@ -702,48 +698,6 @@ evaluate_paths (struct bgp_nexthop_cache *bnc) RESET_FLAG(bnc->change_flags); } -void -bgp_nht_register_all (vrf_id_t vrf_id) -{ - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - { - zlog_err("bgp_nht_register_all: instance not found for vrf_id %d", vrf_id); - return; - } - - for (rn = bgp_table_top (bgp->nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL && - !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - { - register_zebra_rnh(bnc, 0); - } - for (rn = bgp_table_top (bgp->nexthop_cache_table[AFI_IP6]); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL && - !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - { - register_zebra_rnh(bnc, 0); - } - - for (rn = bgp_table_top (bgp->import_check_table[AFI_IP]); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL && - !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - { - register_zebra_rnh(bnc, 1); - } - for (rn = bgp_table_top (bgp->import_check_table[AFI_IP6]); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL && - !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - { - register_zebra_rnh(bnc, 1); - } - -} - /** * path_nh_map - make or break path-to-nexthop association. * ARGUMENTS: diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index 4fc45e88d0..af64750d75 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -22,8 +22,6 @@ #ifndef _BGP_NHT_H #define _BGP_NHT_H -extern void bgp_nht_register_all (vrf_id_t); - /** * bgp_parse_nexthop_update() - parse a nexthop update message from Zebra. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fb0e8b3831..ef2f07caf2 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1828,8 +1828,9 @@ bgp_process_main (struct work_queue *wq, void *data) group_announce_route(bgp, afi, safi, rn, new_select); /* FIB update. */ - if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VIEW) && - ! bgp_option_check (BGP_OPT_NO_FIB))) + if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && + (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) && + !bgp_option_check (BGP_OPT_NO_FIB)) { if (new_select && new_select->type == ZEBRA_ROUTE_BGP @@ -3784,6 +3785,48 @@ bgp_static_redo_import_check (struct bgp *bgp) bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); } +static void +bgp_purge_af_static_redist_routes (struct bgp *bgp, afi_t afi, safi_t safi) +{ + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_info *ri; + + table = bgp->rib[afi][safi]; + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + { + for (ri = rn->info; ri; ri = ri->next) + { + if (ri->peer == bgp->peer_self && + ((ri->type == ZEBRA_ROUTE_BGP && + ri->sub_type == BGP_ROUTE_STATIC) || + (ri->type != ZEBRA_ROUTE_BGP && + ri->sub_type == BGP_ROUTE_REDISTRIBUTE))) + { + bgp_aggregate_decrement (bgp, &rn->p, ri, afi, safi); + bgp_unlink_nexthop(ri); + bgp_info_delete (rn, ri); + bgp_process (bgp, rn, afi, safi); + } + } + } +} + +/* + * Purge all networks and redistributed routes from routing table. + * Invoked upon the instance going down. + */ +void +bgp_purge_static_redist_routes (struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_purge_af_static_redist_routes (bgp, afi, safi); +} + int bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, const char *tag_str) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 3a2d938289..cc26249686 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -248,6 +248,7 @@ extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short); extern void bgp_static_add (struct bgp *); extern void bgp_static_delete (struct bgp *); extern void bgp_static_redo_import_check (struct bgp *); +extern void bgp_purge_static_redist_routes (struct bgp *bgp); extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *, afi_t, safi_t); extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index a9ff757780..cda5fc1c8d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -607,6 +607,7 @@ DEFUN (router_bgp, as_t as; struct bgp *bgp; const char *name = NULL; + enum bgp_instance_type inst_type; // "router bgp" without an ASN if (argc < 1) @@ -632,10 +633,17 @@ DEFUN (router_bgp, { VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX); + inst_type = BGP_INSTANCE_TYPE_DEFAULT; if (argc == 3) - name = argv[2]; + { + name = argv[2]; + if (!strcmp(argv[1], "vrf")) + inst_type = BGP_INSTANCE_TYPE_VRF; + else if (!strcmp(argv[1], "view")) + inst_type = BGP_INSTANCE_TYPE_VIEW; + } - ret = bgp_get (&bgp, &as, name); + ret = bgp_get (&bgp, &as, name, inst_type); switch (ret) { case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: @@ -653,10 +661,6 @@ DEFUN (router_bgp, } /* Pending: handle when user tries to change a view to vrf n vv. */ - if (argc == 3 && !strcmp(argv[1], "vrf")) - bgp_flag_set (bgp, BGP_FLAG_INSTANCE_TYPE_VRF); - if (argc == 3 && !strcmp(argv[1], "view")) - bgp_flag_set (bgp, BGP_FLAG_INSTANCE_TYPE_VIEW); } vty->node = BGP_NODE; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 9ffe44f267..8a171045ff 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -89,6 +89,20 @@ do { \ bgp_attr_deep_free(info->attr); \ } while (0) + +/* Can we install into zebra? */ +static inline int +bgp_install_info_to_zebra (struct bgp *bgp) +{ + if (zclient->sock <= 0) + return 0; + + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; + + return 1; +} + /* Router-id update message from zebra. */ static int bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, @@ -104,15 +118,15 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, { char buf[PREFIX2STR_BUFFER]; prefix2str(&router_id, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: router id update %s vrf %u", buf, vrf_id); + zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); } - if (!vrf_id) + if (vrf_id == VRF_DEFAULT) { - /* This is to cover all the views */ + /* Router-id change for default VRF has to also update all views. */ for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { - if (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VRF)) + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) continue; bgp->router_id_zebra = router_id.u.prefix4; @@ -220,7 +234,7 @@ bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del) } } -/* Inteface addition message from zebra. */ +/* VRF learnt from Zebra. */ static int bgp_vrf_add (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) @@ -229,46 +243,24 @@ bgp_vrf_add (int command, struct zclient *zclient, zebra_size_t length, struct bgp *bgp; vrf = zebra_vrf_add_read (zclient->ibuf, vrf_id); + if (!vrf) // unexpected + return -1; - if (BGP_DEBUG (zebra, ZEBRA) && vrf) - zlog_debug("Zebra rcvd: vrf add %s", vrf->name); + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Rx VRF add %s id %d", vrf->name, vrf_id); bgp = bgp_lookup_by_name(vrf->name); if (bgp) { + /* We have instance configured, make it "up". */ bgp->vrf_id = vrf_id; - - if (BGP_DEBUG (zebra, ZEBRA) && vrf) - zlog_debug("zclient_send_reg_requests %u", vrf_id); - - zclient_send_reg_requests (zclient, vrf_id); - bgp_instance_up (bgp); - //Pending: See if the following can be moved inside bgp_instance_up () - bgp_nht_register_all(vrf_id); - } return 0; } -void -bgp_vrf_update (struct bgp *bgp) -{ - struct vrf *vrf; - - if (bgp->name) - { - vrf = vrf_lookup_by_name(bgp->name); - if (vrf) - bgp->vrf_id = vrf->vrf_id; - } - - zclient_send_reg_requests (zclient, bgp->vrf_id); - bgp_nht_register_all (bgp->vrf_id); -} - -/* Inteface deletion message from zebra. */ +/* VRF deleted by Zebra. */ static int bgp_vrf_delete (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) @@ -276,18 +268,25 @@ bgp_vrf_delete (int command, struct zclient *zclient, zebra_size_t length, struct vrf *vrf; struct bgp *bgp; + /* Default VRF cannot be deleted. */ + assert (vrf_id != VRF_DEFAULT); + vrf = zebra_vrf_state_read (zclient->ibuf, vrf_id); + if (!vrf) // unexpected + return -1; - if (BGP_DEBUG (zebra, ZEBRA) && vrf) - zlog_debug("Zebra rcvd: vrf delete %s", vrf->name); + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Rx VRF del %s id %d", vrf->name, vrf_id); bgp = bgp_lookup_by_name(vrf->name); if (bgp) { + /* We have instance configured, make it "down". */ + bgp->vrf_id = VRF_DEFAULT; bgp_instance_down (bgp); - bgp->vrf_id = 0; } + /* Note: This is a callback, the VRF will be deleted by the caller. */ return 0; } @@ -303,7 +302,7 @@ bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); if (BGP_DEBUG (zebra, ZEBRA) && ifp) - zlog_debug("Zebra rcvd: interface add %s", ifp->name); + zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name); return 0; } @@ -320,7 +319,7 @@ bgp_interface_delete (int command, struct zclient *zclient, ifp->ifindex = IFINDEX_INTERNAL; if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra rcvd: interface delete %s", ifp->name); + zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name); return 0; } @@ -336,10 +335,6 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, struct listnode *node, *nnode; struct bgp *bgp; - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - s = zclient->ibuf; ifp = zebra_interface_state_read (s, vrf_id); @@ -347,7 +342,11 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, return 0; if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra rcvd: interface %s up", ifp->name); + zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); + + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (!bgp) + return 0; for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) bgp_connected_add (bgp, c); @@ -369,17 +368,17 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, struct listnode *node, *nnode; struct bgp *bgp; - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - s = zclient->ibuf; ifp = zebra_interface_state_read (s, vrf_id); if (! ifp) return 0; if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra rcvd: interface %s down", ifp->name); + zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); + + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (!bgp) + return 0; for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) bgp_connected_delete (bgp, c); @@ -389,23 +388,18 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, /* Fast external-failover */ { - struct listnode *mnode; - struct bgp *bgp; struct peer *peer; - for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) - { - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - continue; + if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + return 0; - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) - continue; + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) + continue; - if (ifp == peer->nexthop.ifp) - BGP_EVENT_ADD (peer, BGP_Stop); - } + if (ifp == peer->nexthop.ifp) + BGP_EVENT_ADD (peer, BGP_Stop); } } @@ -427,8 +421,8 @@ bgp_interface_address_add (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: interface %s address add %s", - ifc->ifp->name, buf); + zlog_debug("Rx Intf address add VRF %u IF %s addr %s", + vrf_id, ifc->ifp->name, buf); } if (if_is_operative (ifc->ifp)) @@ -437,10 +431,7 @@ bgp_interface_address_add (int command, struct zclient *zclient, bgp = bgp_lookup_by_vrf_id (vrf_id); if (!bgp) - { - zlog_err("instance not found\n"); - return 0; - } + return 0; bgp_connected_add (bgp, ifc); /* If we have learnt of any neighbors on this interface, @@ -462,10 +453,6 @@ bgp_interface_address_delete (int command, struct zclient *zclient, struct connected *ifc; struct bgp *bgp; - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); if (ifc == NULL) @@ -475,12 +462,16 @@ bgp_interface_address_delete (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: interface %s address delete %s", - ifc->ifp->name, buf); + zlog_debug("Rx Intf address del VRF %u IF %s addr %s", + vrf_id, ifc->ifp->name, buf); } if (if_is_operative (ifc->ifp)) - bgp_connected_delete (bgp, ifc); + { + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (bgp) + bgp_connected_delete (bgp, ifc); + } connected_free (ifc); @@ -494,10 +485,6 @@ bgp_interface_nbr_address_add (int command, struct zclient *zclient, struct nbr_connected *ifc = NULL; struct bgp *bgp; - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); if (ifc == NULL) @@ -507,12 +494,16 @@ bgp_interface_nbr_address_add (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: interface %s nbr address add %s", - ifc->ifp->name, buf); + zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s", + vrf_id, ifc->ifp->name, buf); } if (if_is_operative (ifc->ifp)) - bgp_nbr_connected_add (bgp, ifc); + { + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (bgp) + bgp_nbr_connected_add (bgp, ifc); + } return 0; } @@ -524,10 +515,6 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient, struct nbr_connected *ifc = NULL; struct bgp *bgp; - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); if (ifc == NULL) @@ -537,12 +524,16 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient, { char buf[PREFIX2STR_BUFFER]; prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: interface %s nbr address delete %s", - ifc->ifp->name, buf); + zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s", + vrf_id, ifc->ifp->name, buf); } if (if_is_operative (ifc->ifp)) - bgp_nbr_connected_delete (bgp, ifc, 0); + { + bgp = bgp_lookup_by_vrf_id (vrf_id); + if (bgp) + bgp_nbr_connected_delete (bgp, ifc, 0); + } nbr_connected_free (ifc); @@ -616,7 +607,8 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv4 route add %s[%d] %s/%d nexthop %s metric %u tag %d", + zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d", + vrf_id, zebra_route_string(api.type), api.instance, inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, @@ -646,8 +638,9 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv4 route delete %s[%d] %s/%d " + zlog_debug("Rx IPv4 route delete VRF %u %s[%d] %s/%d " "nexthop %s metric %u tag %d", + vrf_id, zebra_route_string(api.type), api.instance, inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, @@ -735,7 +728,8 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv6 route add %s[%d] %s/%d nexthop %s metric %u tag %d", + zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d", + vrf_id, zebra_route_string(api.type), api.instance, inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, @@ -764,8 +758,9 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv6 route delete %s[%d] %s/%d " + zlog_debug("Rx IPv6 route delete VRF %u %s[%d] %s/%d " "nexthop %s metric %u tag %d", + vrf_id, zebra_route_string(api.type), api.instance, inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, @@ -1170,7 +1165,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, struct bgp_info *info_cp = &local_info; u_short tag; - if (zclient->sock < 0) + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra (bgp)) return; if ((p->family == AF_INET && @@ -1329,8 +1327,9 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (bgp_debug_zebra(p)) { int i; - zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d" + zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d" " count %d", (valid_nh_count ? "add":"delete"), + bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag, api.nexthop_num); for (i = 0; i < api.nexthop_num; i++) @@ -1508,8 +1507,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (bgp_debug_zebra(p)) { int i; - zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d", - valid_nh_count ? "add" : "delete", + zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d", + valid_nh_count ? "add" : "delete", bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); for (i = 0; i < api.nexthop_num; i++) @@ -1530,8 +1529,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (bgp_debug_zebra(p)) { int i; - zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u tag %d", - valid_nh_count ? "add" : "delete", + zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %d", + valid_nh_count ? "add" : "delete", bgp->vrf_id, inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); for (i = 0; i < api.nexthop_num; i++) @@ -1555,6 +1554,12 @@ bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi) struct bgp_table *table; struct bgp_info *ri; + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra (bgp)) + return; + table = bgp->rib[afi][safi]; if (!table) return; @@ -1572,10 +1577,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) int flags; struct peer *peer; - if (zclient->sock < 0) - return; - peer = info->peer; + assert(peer); + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra (peer->bgp)) + return; if ((p->family == AF_INET && !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id)) @@ -1623,7 +1632,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) if (bgp_debug_zebra(p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d", + zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %d", + peer->bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); } @@ -1661,7 +1671,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) if (bgp_debug_zebra(p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d", + zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %d", + peer->bgp->vrf_id, inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); } @@ -1750,12 +1761,15 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance) vrf_bitmap_set (zclient->redist[afi][type], bgp->vrf_id); } - /* Return if zebra connection is not established. */ - if (zclient->sock < 0) + /* Don't try to register if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra (bgp)) return CMD_WARNING; if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra send: redistribute add afi %d %s %d", afi, + zlog_debug("Tx redistribute add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), instance); /* Send distribute add message to zebra. */ @@ -1768,12 +1782,15 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance) int bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type, u_short instance) { - /* Return if zebra connection is not established. */ - if (zclient->sock < 0) + /* Don't try to send if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra (bgp)) return -1; if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra send: redistribute delete/add afi %d %s %d", afi, + zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), instance); /* Send distribute add message to zebra. */ @@ -1854,12 +1871,12 @@ bgp_redistribute_unreg (struct bgp *bgp, afi_t afi, int type, u_short instance) vrf_bitmap_unset (zclient->redist[afi][type], bgp->vrf_id); } - if (zclient->sock >= 0) + if (bgp_install_info_to_zebra (bgp)) { /* Send distribute delete message to zebra. */ if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra send: redistribute delete afi %d %s %d", - afi, zebra_route_string(type), instance); + zlog_debug("Tx redistribute del VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), instance); zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, instance, bgp->vrf_id); } @@ -1903,14 +1920,60 @@ bgp_zclient_reset (void) zclient_reset (zclient); } +/* Register this instance with Zebra. Invoked upon connect (for + * default instance) and when other VRFs are learnt (or created and + * already learnt). + */ +void +bgp_zebra_instance_register (struct bgp *bgp) +{ + /* Don't try to register if we're not connected to Zebra */ + if (zclient->sock < 0) + return; + + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Registering VRF %u", bgp->vrf_id); + + /* Register for router-id, interfaces, redistributed routes. */ + zclient_send_reg_requests (zclient, bgp->vrf_id); +} + +/* Deregister this instance with Zebra. Invoked upon the instance + * being deleted (default or VRF) and it is already registered. + */ +void +bgp_zebra_instance_deregister (struct bgp *bgp) +{ + /* Don't try to deregister if we're not connected to Zebra */ + if (zclient->sock < 0) + return; + + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Deregistering VRF %u", bgp->vrf_id); + + /* Deregister for router-id, interfaces, redistributed routes. */ + zclient_send_dereg_requests (zclient, bgp->vrf_id); +} + +/* BGP has established connection with Zebra. */ static void bgp_zebra_connected (struct zclient *zclient) { - struct listnode *node, *nnode; struct bgp *bgp; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - bgp_vrf_update (bgp); + /* At this point, we may or may not have BGP instances configured, but + * we're only interested in the default VRF (others wouldn't have learnt + * the VRF from Zebra yet.) + */ + bgp = bgp_get_default(); + if (!bgp) + return; + + bgp_zebra_instance_register (bgp); + + /* TODO - What if we have peers and networks configured, do we have to + * kick-start them? + */ } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index e21141238c..308834ce2b 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -29,7 +29,6 @@ extern struct stream *bgp_ifindices_buf; extern void bgp_zebra_init(struct thread_master *master); extern int bgp_if_update_all (void); -extern void bgp_vrf_update (struct bgp *); extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t, safi_t, int *); extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t, @@ -39,6 +38,9 @@ extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp * extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t); extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t); +extern void bgp_zebra_instance_register (struct bgp *); +extern void bgp_zebra_instance_deregister (struct bgp *); + extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short); extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short); extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 09a9f9dc93..ef2004295e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -80,6 +80,7 @@ struct bgp_master *bm; /* BGP community-list. */ struct community_list_handler *bgp_clist; +extern struct zclient *zclient; void bgp_session_reset(struct peer *peer) @@ -2698,10 +2699,9 @@ bgp_startup_timer_expire (struct thread *thread) return 0; } - /* BGP instance creation by `router bgp' commands. */ static struct bgp * -bgp_create (as_t *as, const char *name) +bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) { struct bgp *bgp; afi_t afi; @@ -2710,7 +2710,19 @@ bgp_create (as_t *as, const char *name) if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL) return NULL; + if (BGP_DEBUG (zebra, ZEBRA)) + { + if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Creating Default VRF, AS %u", *as); + else + zlog_debug("Creating %s %s, AS %u", + (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", + name, *as); + } + bgp_lock (bgp); + bgp->inst_type = inst_type; + bgp->vrf_id = VRF_DEFAULT; /* initialization. */ bgp->peer_self = peer_new (bgp); if (bgp->peer_self->host) XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host); @@ -2757,7 +2769,7 @@ bgp_create (as_t *as, const char *name) } else { - //Pending: See if calling bgp_instance_up() makes more sense. + /* TODO - The startup timer needs to be run for the whole of BGP */ THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire, bgp, bgp->restart_time); } @@ -2769,38 +2781,16 @@ bgp_create (as_t *as, const char *name) return bgp; } -void -bgp_instance_up (struct bgp *bgp) -{ - struct peer *peer; - struct listnode *node, *next; - afi_t afi; - int i; - - THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire, - bgp, bgp->restart_time); - - /* Delete static route. */ - bgp_static_add (bgp); - - /* Set redistribution. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != ZEBRA_ROUTE_BGP && bgp_redist_lookup(bgp, afi, i, 0)) - bgp_redistribute_set (bgp, afi, i, 0); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - BGP_EVENT_ADD (peer, BGP_Start); - } -} - -/* Return first entry of BGP. */ +/* Return the "default VRF" instance of BGP. */ struct bgp * bgp_get_default (void) { - if (bm->bgp->head) - return (listgetdata (listhead (bm->bgp))); + struct bgp *bgp; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + return bgp; return NULL; } @@ -2833,8 +2823,7 @@ bgp_lookup_by_name (const char *name) return NULL; } -/* Lookup BGP structure by view name. */ -//Pending: move this based on the vrf_hash lookup and find the linked bgp instance. +/* Lookup BGP instance based on VRF id */ struct bgp * bgp_lookup_by_vrf_id (vrf_id_t vrf_id) { @@ -2847,9 +2836,34 @@ bgp_lookup_by_vrf_id (vrf_id_t vrf_id) return NULL; } +/* Link BGP instance to VRF, if present. */ +static void +bgp_vrf_link (struct bgp *bgp) +{ + struct vrf *vrf; + + vrf = vrf_lookup_by_name(bgp->name); + if (!vrf) + return; + bgp->vrf_id = vrf->vrf_id; +} + +/* Unlink BGP instance from VRF, if present. */ +static void +bgp_vrf_unlink (struct bgp *bgp) +{ + struct vrf *vrf; + + vrf = vrf_lookup (bgp->vrf_id); + if (!vrf) + return; + bgp->vrf_id = VRF_DEFAULT; +} + /* Called from VTY commands. */ int -bgp_get (struct bgp **bgp_val, as_t *as, const char *name) +bgp_get (struct bgp **bgp_val, as_t *as, const char *name, + enum bgp_instance_type inst_type) { struct bgp *bgp; @@ -2869,6 +2883,8 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name) *as = bgp->as; return BGP_ERR_INSTANCE_MISMATCH; } + if (bgp->inst_type != inst_type) + return BGP_ERR_INSTANCE_MISMATCH; *bgp_val = bgp; return 0; } @@ -2894,7 +2910,7 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name) } } - bgp = bgp_create (as, name); + bgp = bgp_create (as, name, inst_type); bgp_router_id_set(bgp, &bgp->router_id_zebra); bgp_address_init (bgp); bgp_scan_init (bgp); @@ -2914,74 +2930,73 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name) listnode_add (bm->bgp, bgp); - bgp_vrf_update (bgp); + /* If VRF, link to the VRF structure, if present. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + bgp_vrf_link (bgp); + + /* Register with Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_register (bgp); + return 0; } -/* Delete BGP instance. */ +/* + * Make BGP instance "up". Applies only to VRFs (non-default) and + * implies the VRF has been learnt from Zebra. + */ void -bgp_instance_down (struct bgp *bgp) +bgp_instance_up (struct bgp *bgp) { struct peer *peer; - struct peer_group *group; - struct listnode *node, *pnode; - struct listnode *next, *pnext; - afi_t afi; - int i; + struct listnode *node, *next; - THREAD_OFF (bgp->t_startup); + /* Register with zebra. */ + bgp_zebra_instance_register (bgp); + /* Kick off any peers that may have been configured. */ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) { - if (peer->status == Established || - peer->status == OpenSent || - peer->status == OpenConfirm) - { - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_PEER_UNCONFIG); - } + if (!BGP_PEER_START_SUPPRESSED (peer)) + BGP_EVENT_ADD (peer, BGP_Start); } - if (bgp->t_rmap_update) - BGP_TIMER_OFF(bgp->t_rmap_update); - - /* Delete static route. */ - bgp_static_delete (bgp); + /* Process any networks that have been configured. */ + bgp_static_add (bgp); +} - /* Unset redistribution. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != ZEBRA_ROUTE_BGP) - bgp_redistribute_unreg (bgp, afi, i, 0); +/* + * Make BGP instance "down". Applies only to VRFs (non-default) and + * implies the VRF has been deleted by Zebra. + */ +void +bgp_instance_down (struct bgp *bgp) +{ + struct peer *peer; + struct listnode *node; + struct listnode *next; - for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) + /* Stop timers. */ + if (bgp->t_rmap_update) + BGP_TIMER_OFF(bgp->t_rmap_update); + if (bgp->t_rmap_def_originate_eval) { - for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - /* Send notify to remote peer. */ - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - } + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ } + /* Bring down peers, so corresponding routes are purged. */ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - /* Send notify to remote peer. */ - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - } - - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + else + bgp_session_reset(peer); } - return; + /* Purge network and redistributed routes. */ + bgp_purge_static_redist_routes (bgp); } /* Delete BGP instance. */ @@ -2996,10 +3011,33 @@ bgp_delete (struct bgp *bgp) THREAD_OFF (bgp->t_startup); + if (BGP_DEBUG (zebra, ZEBRA)) + { + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Deleting Default VRF"); + else + zlog_debug("Deleting %s %s", + (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", + bgp->name); + } + + /* Stop timers. */ if (bgp->t_rmap_update) BGP_TIMER_OFF(bgp->t_rmap_update); + if (bgp->t_rmap_def_originate_eval) + { + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ + } + + /* Inform peers we're going down. */ + for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) + { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } - /* Delete static route. */ + /* Delete static routes (networks). */ bgp_static_delete (bgp); /* Unset redistribution. */ @@ -3008,28 +3046,22 @@ bgp_delete (struct bgp *bgp) if (i != ZEBRA_ROUTE_BGP) bgp_redistribute_unset (bgp, afi, i, 0); + /* Free peers and peer-groups. */ for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) - { - peer_group_delete (group); - } + peer_group_delete (group); for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - peer_delete (peer); - } + peer_delete (peer); if (bgp->peer_self) { peer_delete(bgp->peer_self); bgp->peer_self = NULL; } - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); - } - update_bgp_group_free (bgp); + + /* TODO - Other memory may need to be freed - e.g., NHT */ + /* Remove visibility via the master list - there may however still be * routes to be processed still referencing the struct bgp. */ @@ -3037,6 +3069,14 @@ bgp_delete (struct bgp *bgp) if (list_isempty(bm->bgp)) bgp_close (); + /* Deregister from Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_deregister (bgp); + + /* If VRF, unlink from the VRF structure. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + bgp_vrf_unlink (bgp); + thread_master_free_unused(bm->master); bgp_unlock(bgp); /* initial reference */ @@ -3174,10 +3214,10 @@ peer_lookup (struct bgp *bgp, union sockunion *su) for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) { - /* - * Don't have to cross the instance boundaries for VRFs. + /* Skip VRFs, this function will not be invoked without an instance + * when examining VRFs. */ - if (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VRF)) + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) continue; peer = hash_lookup(bgp->peerhash, &tmp_peer); @@ -6904,8 +6944,9 @@ bgp_config_write (struct vty *vty) if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) { if (bgp->name) - vty_out (vty, " %s %s", (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VIEW) ? - "view" : "vrf"), bgp->name); + vty_out (vty, " %s %s", + (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ? + "view" : "vrf", bgp->name); } vty_out (vty, "%s", VTY_NEWLINE); @@ -7130,6 +7171,36 @@ bgp_master_init (void) bgp_process_queue_init(); } +/* + * Free up connected routes and interfaces; invoked upon bgp_exit() + */ +void +bgp_if_finish (void) +{ + struct bgp *bgp; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) + { + struct listnode *ifnode; + struct interface *ifp; + + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + continue; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist(bgp->vrf_id), ifnode, ifp)) + { + struct listnode *c_node, *c_nnode; + struct connected *c; + + for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) + bgp_connected_delete (bgp, c); + + if_delete (ifp); + } + list_free (vrf_iflist(bgp->vrf_id)); + } +} void bgp_init (void) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9414da4d09..ce318b3384 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -129,6 +129,21 @@ struct bgp_redist struct bgp_rmap rmap; }; +/* + * Type of 'struct bgp'. + * - Default: The default instance + * - VRF: A specific (non-default) VRF + * - View: An instance used for route exchange + * The "default" instance is treated separately to simplify the code. Note + * that if deployed in a Multi-VRF environment, it may not exist. + */ +enum bgp_instance_type +{ + BGP_INSTANCE_TYPE_DEFAULT, + BGP_INSTANCE_TYPE_VRF, + BGP_INSTANCE_TYPE_VIEW +}; + /* BGP instance structure. */ struct bgp { @@ -138,6 +153,8 @@ struct bgp /* Name of this BGP instance. */ char *name; + /* Type of instance and VRF id. */ + enum bgp_instance_type inst_type; vrf_id_t vrf_id; /* Reference count to allow peer_delete to finish after bgp_delete */ @@ -256,8 +273,6 @@ struct bgp #define BGP_FLAG_MULTIPATH_RELAX_AS_SET (1 << 17) #define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18) #define BGP_FLAG_SHOW_HOSTNAME (1 << 19) -#define BGP_FLAG_INSTANCE_TYPE_VIEW (1 << 20) -#define BGP_FLAG_INSTANCE_TYPE_VRF (1 << 21) /* BGP Per AF flags */ u_int16_t af_flags[AFI_MAX][SAFI_MAX]; @@ -333,6 +348,10 @@ struct bgp #define BGP_ROUTE_ADV_HOLD(bgp) (bgp->main_peers_update_hold) +#define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \ + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \ + (bgp->inst_type == BGP_INSTANCE_TYPE_VRF && bgp->vrf_id != VRF_DEFAULT)) + /* BGP peer-group support. */ struct peer_group { @@ -837,6 +856,11 @@ u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; char *domainname; }; +/* Check if suppress start/restart of sessions to peer. */ +#define BGP_PEER_START_SUPPRESSED(P) \ + (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \ + || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW)) + #define PEER_PASSWORD_MINLEN (1) #define PEER_PASSWORD_MAXLEN (80) @@ -1150,6 +1174,7 @@ extern char *peer_uptime (time_t, char *, size_t, u_char, json_object *); extern int bgp_config_write (struct vty *); extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *); +extern void bgp_if_finish (void); extern void bgp_master_init (void); extern void bgp_init (void); @@ -1160,7 +1185,7 @@ extern int bgp_option_set (int); extern int bgp_option_unset (int); extern int bgp_option_check (int); -extern int bgp_get (struct bgp **, as_t *, const char *); +extern int bgp_get (struct bgp **, as_t *, const char *, enum bgp_instance_type); extern void bgp_instance_up (struct bgp *); extern void bgp_instance_down (struct bgp *); extern int bgp_delete (struct bgp *);