mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 21:10:28 +00:00
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 <vivek@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Ticket: CM-9128, CM-7203 Reviewed By: CCR-4098 Testing Done: Manual
This commit is contained in:
parent
0e5223e7a0
commit
ad4cbda1a3
@ -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. */
|
||||
|
@ -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 ();
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
295
bgpd/bgp_zebra.c
295
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;
|
||||
|
||||
vrf = zebra_vrf_state_read (zclient->ibuf, vrf_id);
|
||||
/* Default VRF cannot be deleted. */
|
||||
assert (vrf_id != VRF_DEFAULT);
|
||||
|
||||
if (BGP_DEBUG (zebra, ZEBRA) && vrf)
|
||||
zlog_debug("Zebra rcvd: vrf delete %s", vrf->name);
|
||||
vrf = zebra_vrf_state_read (zclient->ibuf, vrf_id);
|
||||
if (!vrf) // unexpected
|
||||
return -1;
|
||||
|
||||
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))
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
||||
{
|
||||
if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
|
||||
continue;
|
||||
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?
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
283
bgpd/bgpd.c
283
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_up (struct bgp *bgp)
|
||||
{
|
||||
struct peer *peer;
|
||||
struct listnode *node, *next;
|
||||
|
||||
/* 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 (!BGP_PEER_START_SUPPRESSED (peer))
|
||||
BGP_EVENT_ADD (peer, BGP_Start);
|
||||
}
|
||||
|
||||
/* Process any networks that have been configured. */
|
||||
bgp_static_add (bgp);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 peer_group *group;
|
||||
struct listnode *node, *pnode;
|
||||
struct listnode *next, *pnext;
|
||||
afi_t afi;
|
||||
int i;
|
||||
|
||||
THREAD_OFF (bgp->t_startup);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
struct listnode *node;
|
||||
struct listnode *next;
|
||||
|
||||
/* Stop timers. */
|
||||
if (bgp->t_rmap_update)
|
||||
BGP_TIMER_OFF(bgp->t_rmap_update);
|
||||
|
||||
/* Delete static route. */
|
||||
bgp_static_delete (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);
|
||||
|
||||
for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_unlock(bgp); /* TODO - This timer is started with a lock - why? */
|
||||
}
|
||||
|
||||
return;
|
||||
/* 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))
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
|
||||
else
|
||||
bgp_session_reset(peer);
|
||||
}
|
||||
|
||||
/* 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? */
|
||||
}
|
||||
|
||||
/* Delete static route. */
|
||||
/* 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 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)
|
||||
|
31
bgpd/bgpd.h
31
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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user