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. */
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 ();
/* 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;
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:
#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.
*/
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
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)
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);
as_t as;
struct bgp *bgp;
const char *name = NULL;
+ enum bgp_instance_type inst_type;
// "router bgp" without an ASN
if (argc < 1)
{
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:
}
/* 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;
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,
{
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;
}
}
-/* 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)
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)
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;
}
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;
}
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;
}
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);
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);
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);
/* 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);
}
}
{
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))
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,
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)
{
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);
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)
{
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;
}
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)
{
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);
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,
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,
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,
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,
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 &&
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++)
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++)
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++)
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;
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))
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);
}
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);
}
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. */
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. */
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);
}
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?
+ */
}
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,
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);
/* BGP community-list. */
struct community_list_handler *bgp_clist;
+extern struct zclient *zclient;
void
bgp_session_reset(struct peer *peer)
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;
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);
}
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);
}
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;
}
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)
{
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;
*as = bgp->as;
return BGP_ERR_INSTANCE_MISMATCH;
}
+ if (bgp->inst_type != inst_type)
+ return BGP_ERR_INSTANCE_MISMATCH;
*bgp_val = bgp;
return 0;
}
}
}
- 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);
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. */
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. */
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.
*/
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 */
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);
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);
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)
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
{
/* 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 */
#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];
#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
{
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)
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);
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 *);