summaryrefslogtreecommitdiff
path: root/bgpd/bgp_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_zebra.c')
-rw-r--r--bgpd/bgp_zebra.c1230
1 files changed, 745 insertions, 485 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 96b1f3e00f..dbba1dc71a 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* zebra client
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ * Copyright (c) 2023 LabN Consulting, L.L.C.
*/
#include <zebra.h>
@@ -23,6 +24,7 @@
#include "mpls.h"
#include "vxlan.h"
#include "pbr.h"
+#include "frrdistance.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h"
@@ -55,6 +57,8 @@
/* All information about zebra. */
struct zclient *zclient = NULL;
+struct zclient *zclient_sync;
+static bool bgp_zebra_label_manager_connect(void);
/* hook to indicate vrf status change for SNMP */
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
@@ -69,9 +73,10 @@ static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
return false;
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
- zlog_debug(
- "%s: No zebra instance to talk to, not installing information",
- __func__);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug(
+ "%s: No zebra instance to talk to, not installing information",
+ __func__);
return false;
}
@@ -95,13 +100,6 @@ static int bgp_router_id_update(ZAPI_CALLBACK_ARGS)
return 0;
}
-/* Nexthop update message from zebra. */
-static int bgp_read_nexthop_update(ZAPI_CALLBACK_ARGS)
-{
- bgp_parse_nexthop_update(cmd, vrf_id);
- return 0;
-}
-
/* Set or clear interface on which unnumbered neighbor is configured. This
* would in turn cause BGP to initiate or turn off IPv6 RAs on this
* interface.
@@ -137,18 +135,17 @@ static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp)
struct peer *peer;
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0)
- && !peer_established(peer)) {
+ if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) &&
+ !peer_established(peer->connection)) {
if (peer_active(peer))
- BGP_EVENT_ADD(peer, BGP_Stop);
- BGP_EVENT_ADD(peer, BGP_Start);
+ BGP_EVENT_ADD(peer->connection, BGP_Stop);
+ BGP_EVENT_ADD(peer->connection, BGP_Start);
}
}
}
static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc)
{
- struct listnode *node;
struct connected *connected;
struct interface *ifp;
struct prefix *p;
@@ -157,7 +154,7 @@ static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc)
* valid local address on the interface.
*/
ifp = ifc->ifp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
p = connected->address;
if (p->family == AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
@@ -180,7 +177,7 @@ static void bgp_nbr_connected_delete(struct bgp *bgp, struct nbr_connected *ifc,
if (peer->conf_if
&& (strcmp(peer->conf_if, ifc->ifp->name) == 0)) {
peer->last_reset = PEER_DOWN_NBR_ADDR_DEL;
- BGP_EVENT_ADD(peer, BGP_Stop);
+ BGP_EVENT_ADD(peer->connection, BGP_Stop);
}
}
/* Free neighbor also, if we're asked to. */
@@ -229,7 +226,7 @@ static int bgp_ifp_up(struct interface *ifp)
if (!bgp)
return 0;
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
+ frr_each (if_connected, ifp->connected, c)
bgp_connected_add(bgp, c);
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
@@ -238,6 +235,14 @@ static int bgp_ifp_up(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_up(ifp);
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
@@ -260,7 +265,7 @@ static int bgp_ifp_down(struct interface *ifp)
if (!bgp)
return 0;
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
+ frr_each (if_connected, ifp->connected, c)
bgp_connected_delete(bgp, c);
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
@@ -276,7 +281,7 @@ static int bgp_ifp_down(struct interface *ifp)
continue;
if (ifp == peer->nexthop.ifp) {
- BGP_EVENT_ADD(peer, BGP_Stop);
+ BGP_EVENT_ADD(peer->connection, BGP_Stop);
peer->last_reset = PEER_DOWN_IF_DOWN;
}
}
@@ -285,6 +290,14 @@ static int bgp_ifp_down(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_down(ifp);
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
@@ -474,65 +487,6 @@ static int bgp_interface_nbr_address_delete(ZAPI_CALLBACK_ARGS)
return 0;
}
-/* VRF update for an interface. */
-static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS)
-{
- struct interface *ifp;
- vrf_id_t new_vrf_id;
- struct connected *c;
- struct nbr_connected *nc;
- struct listnode *node, *nnode;
- struct bgp *bgp;
- struct peer *peer;
-
- ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
- &new_vrf_id);
- if (!ifp)
- return 0;
-
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", vrf_id,
- ifp->name, new_vrf_id);
-
- bgp = bgp_lookup_by_vrf_id(vrf_id);
-
- if (bgp) {
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
- bgp_connected_delete(bgp, c);
-
- for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
- bgp_nbr_connected_delete(bgp, nc, 1);
-
- /* Fast external-failover */
- if (!CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) {
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if ((peer->ttl != BGP_DEFAULT_TTL)
- && (peer->gtsm_hops
- != BGP_GTSM_HOPS_CONNECTED))
- continue;
-
- if (ifp == peer->nexthop.ifp)
- BGP_EVENT_ADD(peer, BGP_Stop);
- }
- }
- }
-
- if_update_to_new_vrf(ifp, new_vrf_id);
-
- bgp = bgp_lookup_by_vrf_id(new_vrf_id);
- if (!bgp)
- return 0;
-
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
- bgp_connected_add(bgp, c);
-
- for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
- bgp_nbr_connected_add(bgp, nc);
-
- hook_call(bgp_vrf_status_changed, bgp, ifp);
- return 0;
-}
-
/* Zebra route add and delete treatment. */
static int zebra_read_route(ZAPI_CALLBACK_ARGS)
{
@@ -620,7 +574,6 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv4 p;
@@ -635,7 +588,7 @@ struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
p.prefixlen = IPV4_MAX_BITLEN;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET)
@@ -649,7 +602,6 @@ struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
@@ -659,7 +611,7 @@ struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id)
return NULL;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET)
@@ -674,7 +626,6 @@ struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex,
vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv6 p;
@@ -689,7 +640,7 @@ struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex,
p.prefixlen = IPV6_MAX_BITLEN;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -710,7 +661,6 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
ifindex_t ifindex, vrf_id_t vrf_id)
{
struct vrf *vrf;
- struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
@@ -720,7 +670,7 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
return NULL;
FOR_ALL_INTERFACES (vrf, ifp) {
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -739,11 +689,10 @@ struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -757,11 +706,10 @@ static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr)
static bool if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if (cp->family == AF_INET6)
@@ -775,11 +723,10 @@ static bool if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr)
static int if_get_ipv4_address(struct interface *ifp, struct in_addr *addr)
{
- struct listnode *cnode;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
cp = connected->address;
if ((cp->family == AF_INET)
&& !ipv4_martian(&(cp->u.prefix4))) {
@@ -996,7 +943,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
|| path->attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
- if (path->attr->mp_nexthop_prefer_global) {
+ if (CHECK_FLAG(path->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
@@ -1073,14 +1021,17 @@ static void bgp_zebra_tm_connect(struct event *t)
ret = tm_table_manager_connect(zclient);
}
if (ret < 0) {
- zlog_info("Error connecting to table manager!");
+ zlog_err("Error connecting to table manager!");
bgp_tm_status_connected = false;
} else {
- if (!bgp_tm_status_connected)
- zlog_debug("Connecting to table manager. Success");
+ if (!bgp_tm_status_connected) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug(
+ "Connecting to table manager. Success");
+ }
bgp_tm_status_connected = true;
if (!bgp_tm_chunk_obtained) {
- if (bgp_zebra_get_table_range(bgp_tm_chunk_size,
+ if (bgp_zebra_get_table_range(zclient, bgp_tm_chunk_size,
&bgp_tm_min,
&bgp_tm_max) >= 0) {
bgp_tm_chunk_obtained = true;
@@ -1120,18 +1071,18 @@ void bgp_zebra_init_tm_connect(struct bgp *bgp)
bgp_tm_min = bgp_tm_max = 0;
bgp_tm_chunk_size = BGP_FLOWSPEC_TABLE_CHUNK;
bgp_tm_bgp = bgp;
- event_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
+ event_add_timer(bm->master, bgp_zebra_tm_connect, zclient_sync, delay,
&bgp_tm_thread_connect);
}
-int bgp_zebra_get_table_range(uint32_t chunk_size,
+int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
uint32_t *start, uint32_t *end)
{
int ret;
if (!bgp_tm_status_connected)
return -1;
- ret = tm_get_table_chunk(zclient, chunk_size, start, end);
+ ret = tm_get_table_chunk(zc, chunk_size, start, end);
if (ret < 0) {
flog_err(EC_BGP_TABLE_CHUNK,
"BGP: Error getting table chunk %u", chunk_size);
@@ -1260,145 +1211,61 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
- uint64_t tot_bw, uint32_t *nh_weight)
+ uint32_t *nh_weight)
{
- uint32_t bw;
- uint64_t tmp;
-
- bw = attr->link_bw;
/* zero link-bandwidth and link-bandwidth not present are treated
* as the same situation.
*/
- if (!bw) {
+ if (!attr->link_bw) {
/* the only situations should be if we're either told
* to skip or use default weight.
*/
if (bgp->lb_handling == BGP_LINK_BW_SKIP_MISSING)
return false;
*nh_weight = BGP_ZEBRA_DEFAULT_NHOP_WEIGHT;
- } else {
- tmp = (uint64_t)bw * 100;
- *nh_weight = ((uint32_t)(tmp / tot_bw));
- }
+ } else
+ *nh_weight = attr->link_bw;
return true;
}
-void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
- safi_t safi)
+static void bgp_zebra_announce_parse_nexthop(
+ struct bgp_path_info *info, const struct prefix *p, struct bgp *bgp,
+ struct zapi_route *api, unsigned int *valid_nh_count, afi_t afi,
+ safi_t safi, uint32_t *nhg_id, uint32_t *metric, route_tag_t *tag,
+ bool *allow_recursion)
{
- struct zapi_route api = { 0 };
struct zapi_nexthop *api_nh;
int nh_family;
- unsigned int valid_nh_count = 0;
- bool allow_recursion = false;
- uint8_t distance;
- struct peer *peer;
struct bgp_path_info *mpinfo;
struct bgp *bgp_orig;
- uint32_t metric;
struct attr local_attr;
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
- route_tag_t tag;
- struct bgp_sid_info *sid_info;
mpls_label_t *labels;
uint32_t num_labels = 0;
mpls_label_t nh_label;
int nh_othervrf = 0;
bool nh_updated = false;
bool do_wt_ecmp;
- uint64_t cum_bw = 0;
- uint32_t nhg_id = 0;
- bool is_add;
uint32_t ttl = 0;
uint32_t bos = 0;
uint32_t exp = 0;
- /*
- * BGP is installing this route and bgp has been configured
- * to suppress announcements until the route has been installed
- * let's set the fact that we expect this route to be installed
- */
- if (BGP_SUPPRESS_FIB_ENABLED(bgp))
- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* 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 (bgp->main_zebra_update_hold)
- return;
-
- if (safi == SAFI_FLOWSPEC) {
- bgp_pbr_update_entry(bgp, bgp_dest_get_prefix(dest), info, afi,
- safi, true);
- return;
- }
+ /* Determine if we're doing weighted ECMP or not */
+ do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
/*
* vrf leaking support (will have only one nexthop)
*/
- if (info->extra && info->extra->bgp_orig)
+ if (info->extra && info->extra->vrfleak &&
+ info->extra->vrfleak->bgp_orig)
nh_othervrf = 1;
- /* Make Zebra API structure. */
- api.vrf_id = bgp->vrf_id;
- api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
- api.prefix = *p;
- SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-
- peer = info->peer;
-
- if (info->type == ZEBRA_ROUTE_BGP
- && info->sub_type == BGP_ROUTE_IMPORTED) {
-
- /* Obtain peer from parent */
- if (info->extra && info->extra->parent)
- peer = ((struct bgp_path_info *)(info->extra->parent))
- ->peer;
- }
-
- tag = info->attr->tag;
-
- if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
- || info->sub_type == BGP_ROUTE_AGGREGATE) {
- SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
- SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
- }
-
- if ((peer->sort == BGP_PEER_EBGP && peer->ttl != BGP_DEFAULT_TTL)
- || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
- || CHECK_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
-
- allow_recursion = true;
-
- if (info->attr->rmap_table_id) {
- SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
- api.tableid = info->attr->rmap_table_id;
- }
-
- if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
-
- /* Metric is currently based on the best-path only */
- metric = info->attr->med;
-
- /* Determine if we're doing weighted ECMP or not */
- do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
- if (do_wt_ecmp)
- cum_bw = bgp_path_info_mpath_cumbw(info);
-
/* EVPN MAC-IP routes are installed with a L3 NHG id */
- if (bgp_evpn_path_es_use_nhg(bgp, info, &nhg_id)) {
+ if (nhg_id && bgp_evpn_path_es_use_nhg(bgp, info, nhg_id)) {
mpinfo = NULL;
- api.nhgid = nhg_id;
- if (nhg_id)
- SET_FLAG(api.message, ZAPI_MESSAGE_NHG);
+ zapi_route_set_nhg_id(api, nhg_id);
} else {
mpinfo = info;
}
@@ -1410,7 +1277,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
bool is_evpn;
bool is_parent_evpn;
- if (valid_nh_count >= multipath_num)
+ if (*valid_nh_count >= multipath_num)
break;
*mpinfo_cp = *mpinfo;
@@ -1433,16 +1300,19 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
*/
if (do_wt_ecmp) {
if (!bgp_zebra_use_nhop_weighted(bgp, mpinfo->attr,
- cum_bw, &nh_weight))
+ &nh_weight))
continue;
}
- api_nh = &api.nexthops[valid_nh_count];
+ if (CHECK_FLAG(info->flags, BGP_PATH_SELECTED))
+ api_nh = &api->nexthops[*valid_nh_count];
+ else
+ api_nh = &api->backup_nexthops[*valid_nh_count];
if (CHECK_FLAG(info->attr->flag,
ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- api_nh->srte_color = info->attr->srte_color;
+ api_nh->srte_color = bgp_attr_get_color(info->attr);
- if (bgp_debug_zebra(&api.prefix)) {
+ if (bgp_debug_zebra(&api->prefix)) {
if (mpinfo->extra) {
zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d",
__func__, p,
@@ -1467,8 +1337,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
/* metric/tag is only allowed to be
* overridden on 1st nexthop */
if (mpinfo == info) {
- metric = mpinfo_cp->attr->med;
- tag = mpinfo_cp->attr->tag;
+ if (metric)
+ *metric = mpinfo_cp->attr->med;
+ if (tag)
+ *tag = mpinfo_cp->attr->tag;
}
}
@@ -1509,11 +1381,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
/* Allow recursion if it is a multipath group with both
* eBGP and iBGP paths.
*/
- if (!allow_recursion
- && CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX)
- && (mpinfo->peer->sort == BGP_PEER_IBGP
- || mpinfo->peer->sort == BGP_PEER_CONFED))
- allow_recursion = true;
+ if (allow_recursion && !*allow_recursion &&
+ CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX) &&
+ (mpinfo->peer->sort == BGP_PEER_IBGP ||
+ mpinfo->peer->sort == BGP_PEER_CONFED))
+ *allow_recursion = true;
if (mpinfo->extra) {
labels = mpinfo->extra->label;
@@ -1547,36 +1419,178 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api_nh->weight = nh_weight;
- if (mpinfo->extra && !is_evpn &&
- bgp_is_valid_label(&labels[0]) &&
- !sid_zero(&mpinfo->extra->sid[0].sid)) {
- sid_info = &mpinfo->extra->sid[0];
-
- memcpy(&api_nh->seg6_segs, &sid_info->sid,
- sizeof(api_nh->seg6_segs));
-
- if (sid_info->transposition_len != 0) {
+ if (((mpinfo->attr->srv6_l3vpn &&
+ !sid_zero_ipv6(&mpinfo->attr->srv6_l3vpn->sid)) ||
+ (mpinfo->attr->srv6_vpn &&
+ !sid_zero_ipv6(&mpinfo->attr->srv6_vpn->sid))) &&
+ !is_evpn && bgp_is_valid_label(&labels[0])) {
+ struct in6_addr *sid_tmp =
+ mpinfo->attr->srv6_l3vpn
+ ? (&mpinfo->attr->srv6_l3vpn->sid)
+ : (&mpinfo->attr->srv6_vpn->sid);
+
+ memcpy(&api_nh->seg6_segs[0], sid_tmp,
+ sizeof(api_nh->seg6_segs[0]));
+
+ if (mpinfo->attr->srv6_l3vpn &&
+ mpinfo->attr->srv6_l3vpn->transposition_len != 0) {
mpls_lse_decode(labels[0], &nh_label, &ttl,
&exp, &bos);
if (nh_label < MPLS_LABEL_UNRESERVED_MIN) {
- if (bgp_debug_zebra(&api.prefix))
+ if (bgp_debug_zebra(&api->prefix))
zlog_debug(
"skip invalid SRv6 routes: transposition scheme is used, but label is too small");
continue;
}
- transpose_sid(&api_nh->seg6_segs, nh_label,
- sid_info->transposition_offset,
- sid_info->transposition_len);
+ transpose_sid(&api_nh->seg6_segs[0], nh_label,
+ mpinfo->attr->srv6_l3vpn
+ ->transposition_offset,
+ mpinfo->attr->srv6_l3vpn
+ ->transposition_len);
}
+ api_nh->seg_num = 1;
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
}
- valid_nh_count++;
+ (*valid_nh_count)++;
+ }
+}
+
+static void bgp_debug_zebra_nh(struct zapi_route *api)
+{
+ int i;
+ int nh_family;
+ char nh_buf[INET6_ADDRSTRLEN];
+ char eth_buf[ETHER_ADDR_STRLEN + 7] = { '\0' };
+ char buf1[ETHER_ADDR_STRLEN];
+ char label_buf[20];
+ char sid_buf[20];
+ char segs_buf[256];
+ struct zapi_nexthop *api_nh;
+ int count;
+
+ count = api->nexthop_num;
+ for (i = 0; i < count; i++) {
+ api_nh = &api->nexthops[i];
+ switch (api_nh->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ nh_buf[0] = '\0';
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ nh_family = AF_INET;
+ inet_ntop(nh_family, &api_nh->gate, nh_buf,
+ sizeof(nh_buf));
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ nh_family = AF_INET6;
+ inet_ntop(nh_family, &api_nh->gate, nh_buf,
+ sizeof(nh_buf));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ strlcpy(nh_buf, "blackhole", sizeof(nh_buf));
+ break;
+ default:
+ /* Note: add new nexthop case */
+ assert(0);
+ break;
+ }
+
+ label_buf[0] = '\0';
+ eth_buf[0] = '\0';
+ segs_buf[0] = '\0';
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) &&
+ !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
+ snprintf(label_buf, sizeof(label_buf), "label %u",
+ api_nh->labels[0]);
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&
+ !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
+ inet_ntop(AF_INET6, &api_nh->seg6_segs[0], sid_buf,
+ sizeof(sid_buf));
+ snprintf(segs_buf, sizeof(segs_buf), "segs %s", sid_buf);
+ }
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN) &&
+ !is_zero_mac(&api_nh->rmac))
+ snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
+ prefix_mac2str(&api_nh->rmac, buf1,
+ sizeof(buf1)));
+ zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1,
+ nh_buf, api_nh->ifindex, api_nh->vrf_id,
+ api_nh->weight, label_buf, segs_buf, eth_buf);
+ }
+}
+
+static enum zclient_send_status
+bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp)
+{
+ struct bgp_path_info *bpi_ultimate;
+ struct zapi_route api = { 0 };
+ unsigned int valid_nh_count = 0;
+ bool allow_recursion = false;
+ uint8_t distance;
+ struct peer *peer;
+ uint32_t metric;
+ route_tag_t tag;
+ bool is_add;
+ uint32_t nhg_id = 0;
+ uint32_t recursion_flag = 0;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
+
+ if (table->safi == SAFI_FLOWSPEC) {
+ bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi,
+ true);
+ return ZCLIENT_SEND_SUCCESS;
}
+ /* Make Zebra API structure. */
+ api.vrf_id = bgp->vrf_id;
+ api.type = ZEBRA_ROUTE_BGP;
+ api.safi = table->safi;
+ api.prefix = *p;
+ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+ peer = info->peer;
+
+ if (info->type == ZEBRA_ROUTE_BGP) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(info);
+ peer = bpi_ultimate->peer;
+ }
+
+ tag = info->attr->tag;
+
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
+ || info->sub_type == BGP_ROUTE_AGGREGATE) {
+ SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
+ SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
+ }
+
+ if ((peer->sort == BGP_PEER_EBGP && peer->ttl != BGP_DEFAULT_TTL)
+ || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
+ || CHECK_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+
+ allow_recursion = true;
+
+ if (info->attr->rmap_table_id) {
+ SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
+ api.tableid = info->attr->rmap_table_id;
+ }
+
+ if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
+ SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
+
+ /* Metric is currently based on the best-path only */
+ metric = info->attr->med;
+
+ bgp_zebra_announce_parse_nexthop(info, p, bgp, &api, &valid_nh_count,
+ table->afi, table->safi, &nhg_id,
+ &metric, &tag, &allow_recursion);
+
is_add = (valid_nh_count || nhg_id) ? true : false;
if (is_add && CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) {
@@ -1628,82 +1642,19 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.tag = tag;
}
- distance = bgp_distance_apply(p, info, afi, safi, bgp);
+ distance = bgp_distance_apply(p, info, table->afi, table->safi, bgp);
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
}
if (bgp_debug_zebra(p)) {
- char nh_buf[INET6_ADDRSTRLEN];
- char eth_buf[ETHER_ADDR_STRLEN + 7] = {'\0'};
- char buf1[ETHER_ADDR_STRLEN];
- char label_buf[20];
- char sid_buf[20];
- char segs_buf[256];
- int i;
-
zlog_debug(
"Tx route %s VRF %u %pFX metric %u tag %" ROUTE_TAG_PRI
" count %d nhg %d",
is_add ? "add" : "delete", bgp->vrf_id, &api.prefix,
api.metric, api.tag, api.nexthop_num, nhg_id);
- for (i = 0; i < api.nexthop_num; i++) {
- api_nh = &api.nexthops[i];
-
- switch (api_nh->type) {
- case NEXTHOP_TYPE_IFINDEX:
- nh_buf[0] = '\0';
- break;
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- nh_family = AF_INET;
- inet_ntop(nh_family, &api_nh->gate, nh_buf,
- sizeof(nh_buf));
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- nh_family = AF_INET6;
- inet_ntop(nh_family, &api_nh->gate, nh_buf,
- sizeof(nh_buf));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- strlcpy(nh_buf, "blackhole", sizeof(nh_buf));
- break;
- default:
- /* Note: add new nexthop case */
- assert(0);
- break;
- }
-
- label_buf[0] = '\0';
- eth_buf[0] = '\0';
- segs_buf[0] = '\0';
- if (CHECK_FLAG(api_nh->flags,
- ZAPI_NEXTHOP_FLAG_LABEL) &&
- !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
- snprintf(label_buf, sizeof(label_buf),
- "label %u", api_nh->labels[0]);
- if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&
- !CHECK_FLAG(api_nh->flags,
- ZAPI_NEXTHOP_FLAG_EVPN)) {
- inet_ntop(AF_INET6, &api_nh->seg6_segs,
- sid_buf, sizeof(sid_buf));
- snprintf(segs_buf, sizeof(segs_buf), "segs %s",
- sid_buf);
- }
- if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN) &&
- !is_zero_mac(&api_nh->rmac))
- snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
- prefix_mac2str(&api_nh->rmac,
- buf1, sizeof(buf1)));
- zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s",
- i + 1, nh_buf, api_nh->ifindex,
- api_nh->vrf_id, api_nh->weight,
- label_buf, segs_buf, eth_buf);
- }
-
- int recursion_flag = 0;
+ bgp_debug_zebra_nh(&api);
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION))
recursion_flag = 1;
@@ -1711,10 +1662,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)",
__func__, p, (recursion_flag ? "" : "NOT "));
}
- zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
- zclient, &api);
+ return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
+ zclient, &api);
}
+
/* Announce all routes of a table to zebra */
void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
{
@@ -1735,14 +1687,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
-
(pi->type == ZEBRA_ROUTE_BGP
&& (pi->sub_type == BGP_ROUTE_NORMAL
|| pi->sub_type == BGP_ROUTE_IMPORTED)))
-
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
/* Announce routes of any bgp subtype of a table to zebra */
@@ -1764,39 +1713,30 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
pi->type == ZEBRA_ROUTE_BGP)
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
-void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
- struct bgp *bgp, safi_t safi)
+enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
+ struct bgp_path_info *info,
+ struct bgp *bgp)
{
struct zapi_route api;
struct peer *peer;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
- /*
- * If we are withdrawing the route, we don't need to have this
- * flag set. So unset it.
- */
- UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* 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 (safi == SAFI_FLOWSPEC) {
+ if (table->safi == SAFI_FLOWSPEC) {
peer = info->peer;
- bgp_pbr_update_entry(peer->bgp, p, info, AFI_IP, safi, false);
- return;
+ bgp_pbr_update_entry(peer->bgp, p, info, table->afi,
+ table->safi, false);
+ return ZCLIENT_SEND_SUCCESS;
}
memset(&api, 0, sizeof(api));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
+ api.safi = table->safi;
api.prefix = *p;
if (info->attr->rmap_table_id) {
@@ -1808,7 +1748,206 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id,
&api.prefix);
- zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+ return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+}
+
+/*
+ * Walk the new Fifo list one by one and invoke bgp_zebra_announce/withdraw
+ * to install/withdraw the routes to zebra.
+ *
+ * If status = ZCLIENT_SEND_SUCCESS (Buffer empt)y i.e. Zebra is free to
+ * receive more incoming data, then pick the next item on the list and
+ * continue processing.
+ *
+ * If status = ZCLIENT_SEND_BUFFERED (Buffer pending) i.e. Zebra is busy,
+ * break and bail out of the function because once at some point when zebra
+ * is free, a callback is triggered which inturn call this same function and
+ * continue processing items on list.
+ */
+#define ZEBRA_ANNOUNCEMENTS_LIMIT 1000
+static void bgp_handle_route_announcements_to_zebra(struct event *e)
+{
+ bool is_evpn = false;
+ uint32_t count = 0;
+ struct bgp_dest *dest = NULL;
+ struct bgp_table *table = NULL;
+ enum zclient_send_status status = ZCLIENT_SEND_SUCCESS;
+ bool install;
+
+ while (count < ZEBRA_ANNOUNCEMENTS_LIMIT) {
+ dest = zebra_announce_pop(&bm->zebra_announce_head);
+
+ if (!dest)
+ break;
+
+ table = bgp_dest_table(dest);
+ install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ is_evpn = true;
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
+ install ? "announcing" : "withdrawing", dest,
+ table->bgp->name_pretty, dest, dest->flags);
+
+ if (install) {
+ if (is_evpn)
+ status =
+ evpn_zebra_install(table->bgp,
+ dest->za_vpn,
+ (const struct prefix_evpn
+ *)
+ bgp_dest_get_prefix(
+ dest),
+ dest->za_bgp_pi);
+ else
+ status = bgp_zebra_announce_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ if (is_evpn)
+ status = evpn_zebra_uninstall(
+ table->bgp, dest->za_vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ dest->za_bgp_pi, false);
+ else
+ status = bgp_zebra_withdraw_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ dest->za_bgp_pi = NULL;
+ dest->za_vpn = NULL;
+ bgp_dest_unlock_node(dest);
+
+ if (status == ZCLIENT_SEND_BUFFERED)
+ break;
+
+ count++;
+ }
+
+ if (status != ZCLIENT_SEND_BUFFERED &&
+ zebra_announce_count(&bm->zebra_announce_head))
+ event_add_event(bm->master,
+ bgp_handle_route_announcements_to_zebra, NULL,
+ 0, &bm->t_bgp_zebra_route);
+}
+
+/*
+ * Callback function invoked when zclient_flush_data() receives a BUFFER_EMPTY
+ * i.e. zebra is free to receive more incoming data.
+ */
+static void bgp_zebra_buffer_write_ready(void)
+{
+ bgp_handle_route_announcements_to_zebra(NULL);
+}
+
+/*
+ * BGP is now keeping a list of dests with the dest having a pointer
+ * to the bgp_path_info that it will be working on.
+ * Here is the sequence of events that should happen:
+ *
+ * Current State New State Action
+ * ------------- --------- ------
+ * ---- Install Place dest on list, save pi, mark
+ * as going to be installed
+ * ---- Withdrawal Place dest on list, save pi, mark
+ * as going to be deleted
+ *
+ * Install Install Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * Installed
+ * Install Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawan, remove install flag
+ *
+ * Withdrawal Install Special case, send withdrawal immediately
+ * Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * installed. <see note about evpn
+ * in bgp_route.c in bgp_process_main_one>
+ * Withdrawal Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawn.
+ */
+void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp, bool install, struct bgpevpn *vpn,
+ bool is_sync)
+{
+ bool is_evpn = false;
+ struct bgp_table *table = NULL;
+
+ table = bgp_dest_table(dest);
+ if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ is_evpn = true;
+
+ /*
+ * BGP is installing this route and bgp has been configured
+ * to suppress announcements until the route has been installed
+ * let's set the fact that we expect this route to be installed
+ */
+ if (install) {
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
+ if (bgp->main_zebra_update_hold && !is_evpn)
+ return;
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+ }
+
+ /*
+ * 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) && !is_evpn)
+ return;
+
+ if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) &&
+ !CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+ /*
+ * If neither flag is set and za_bgp_pi is not set then it is a bug
+ */
+ assert(!dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ bgp_dest_lock_node(dest);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL)) {
+ assert(dest->za_bgp_pi);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ assert(dest->za_bgp_pi);
+ if (install & !is_evpn)
+ bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp);
+
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ }
+
+ if (is_evpn) {
+ dest->za_vpn = vpn;
+ dest->za_is_sync = is_sync;
+ }
+
+ if (install) {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ event_add_event(bm->master, bgp_handle_route_announcements_to_zebra,
+ NULL, 0, &bm->t_bgp_zebra_route);
}
/* Withdraw all entries in a BGP instances RIB table from Zebra */
@@ -1829,8 +1968,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& (pi->type == ZEBRA_ROUTE_BGP))
- bgp_zebra_withdraw(bgp_dest_get_prefix(dest),
- pi, bgp, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false,
+ NULL, false);
}
}
}
@@ -1909,7 +2048,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
redist_add_instance(&zclient->mi_redist[afi][type], instance);
} else {
- if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id))
+ if (vrf_bitmap_check(&zclient->redist[afi][type], bgp->vrf_id))
return CMD_WARNING;
#ifdef ENABLE_BGP_VNC
@@ -1919,7 +2058,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
}
#endif
- vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
+ vrf_bitmap_set(&zclient->redist[afi][type], bgp->vrf_id);
}
/*
@@ -2040,9 +2179,9 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,
return CMD_WARNING;
redist_del_instance(&zclient->mi_redist[afi][type], instance);
} else {
- if (!vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id))
+ if (!vrf_bitmap_check(&zclient->redist[afi][type], bgp->vrf_id))
return CMD_WARNING;
- vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id);
+ vrf_bitmap_unset(&zclient->redist[afi][type], bgp->vrf_id);
}
if (bgp_install_info_to_zebra(bgp)) {
@@ -2062,8 +2201,8 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,
}
/* Unset redistribution. */
-int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
- unsigned short instance)
+static void _bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
+ unsigned short instance)
{
struct bgp_redist *red;
@@ -2080,7 +2219,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
red = bgp_redist_lookup(bgp, afi, type, instance);
if (!red)
- return CMD_SUCCESS;
+ return;
bgp_redistribute_unreg(bgp, afi, type, instance);
@@ -2094,8 +2233,24 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
red->redist_metric = 0;
bgp_redist_del(bgp, afi, type, instance);
+}
- return CMD_SUCCESS;
+void bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
+ unsigned short instance)
+{
+ struct listnode *node, *nnode;
+ struct bgp_redist *red;
+
+ if ((type != ZEBRA_ROUTE_TABLE && type != ZEBRA_ROUTE_TABLE_DIRECT) ||
+ instance != 0)
+ return _bgp_redistribute_unset(bgp, afi, type, instance);
+
+ /* walk over instance */
+ if (!bgp->redist[afi][type])
+ return;
+
+ for (ALL_LIST_ELEMENTS(bgp->redist[afi][type], node, nnode, red))
+ _bgp_redistribute_unset(bgp, afi, type, red->instance);
}
void bgp_redistribute_redo(struct bgp *bgp)
@@ -2386,7 +2541,7 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_rule_notify_owner note;
struct bgp_pbr_action *bgp_pbra;
struct bgp_pbr_rule *bgp_pbr = NULL;
- char ifname[INTERFACE_NAMSIZ + 1];
+ char ifname[IFNAMSIZ + 1];
if (!zapi_rule_notify_decode(zclient->ibuf, &seqno, &priority, &unique,
ifname, &note))
@@ -2430,8 +2585,14 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS)
/* link bgp_info to bgp_pbr */
path = (struct bgp_path_info *)bgp_pbr->path;
extra = bgp_path_info_extra_get(path);
- listnode_add_force(&extra->bgp_fs_iprule,
- bgp_pbr);
+ if (!extra->flowspec) {
+ extra->flowspec =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS,
+ sizeof(struct bgp_path_info_extra_fs));
+ extra->flowspec->bgp_fs_iprule = NULL;
+ extra->flowspec->bgp_fs_pbr = NULL;
+ }
+ listnode_add_force(&extra->flowspec->bgp_fs_iprule, bgp_pbr);
}
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%s: Received RULE_INSTALLED", __func__);
@@ -2533,7 +2694,14 @@ static int ipset_entry_notify_owner(ZAPI_CALLBACK_ARGS)
/* link bgp_path_info to bpme */
path = (struct bgp_path_info *)bgp_pbime->path;
extra = bgp_path_info_extra_get(path);
- listnode_add_force(&extra->bgp_fs_pbr, bgp_pbime);
+ if (!extra->flowspec) {
+ extra->flowspec =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS,
+ sizeof(struct bgp_path_info_extra_fs));
+ extra->flowspec->bgp_fs_iprule = NULL;
+ extra->flowspec->bgp_fs_pbr = NULL;
+ }
+ listnode_add_force(&extra->flowspec->bgp_fs_pbr, bgp_pbime);
}
break;
case ZAPI_IPSET_ENTRY_FAIL_REMOVE:
@@ -2619,8 +2787,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
/* Find the bgp route node */
dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p,
&bgp->vrf_prd);
- if (!dest)
+ if (!dest) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %pFX does not exist in the BGP table, nothing to do for %u",
+ __func__, &p, note);
return -1;
+ }
switch (note) {
case ZAPI_ROUTE_INSTALLED:
@@ -2629,7 +2801,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route %pRN : INSTALLED", dest);
+ zlog_debug("route %pBD : INSTALLED", dest);
/* Find the best route */
for (pi = dest->info; pi; pi = pi->next) {
/* Process aggregate route */
@@ -2642,7 +2814,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
group_announce_route(bgp, afi, safi, dest, new_select);
else {
flog_err(EC_BGP_INVALID_ROUTE,
- "selected route %pRN not found", dest);
+ "selected route %pBD not found", dest);
bgp_dest_unlock_node(dest);
return -1;
@@ -2655,12 +2827,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
*/
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route %pRN: Removed from Fib", dest);
+ zlog_debug("route %pBD: Removed from Fib", dest);
break;
case ZAPI_ROUTE_FAIL_INSTALL:
new_select = NULL;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route: %pRN Failed to Install into Fib",
+ zlog_debug("route: %pBD Failed to Install into Fib",
dest);
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
@@ -2674,7 +2846,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
break;
case ZAPI_ROUTE_BETTER_ADMIN_WON:
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("route: %pRN removed due to better admin won",
+ zlog_debug("route: %pBD removed due to better admin won",
dest);
new_select = NULL;
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
@@ -2689,8 +2861,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
/* No action required */
break;
case ZAPI_ROUTE_REMOVE_FAIL:
- zlog_warn("%s: Route %pRN failure to remove",
- __func__, dest);
+ zlog_warn("%s: Route %pBD failure to remove", __func__, dest);
break;
}
@@ -2706,17 +2877,20 @@ static void bgp_encode_pbr_rule_action(struct stream *s,
struct bgp_pbr_action *pbra,
struct bgp_pbr_rule *pbr)
{
- struct prefix pfx;
uint8_t fam = AF_INET;
- char ifname[INTERFACE_NAMSIZ];
+ struct pbr_rule r;
if (pbra->nh.type == NEXTHOP_TYPE_IPV6)
fam = AF_INET6;
- stream_putl(s, 0); /* seqno unused */
+
+ /*
+ * Convert to canonical form
+ */
+ memset(&r, 0, sizeof(r));
+ /* r.seq unused */
if (pbr)
- stream_putl(s, pbr->priority);
- else
- stream_putl(s, 0);
+ r.priority = pbr->priority;
+
/* ruleno unused - priority change
* ruleno permits distinguishing various FS PBR entries
* - FS PBR entries based on ipset/iptables
@@ -2724,49 +2898,38 @@ static void bgp_encode_pbr_rule_action(struct stream *s,
* the latter may contain default routing information injected by FS
*/
if (pbr)
- stream_putl(s, pbr->unique);
+ r.unique = pbr->unique;
else
- stream_putl(s, pbra->unique);
- stream_putc(s, 0); /* ip protocol being used */
- if (pbr && pbr->flags & MATCH_IP_SRC_SET)
- memcpy(&pfx, &(pbr->src), sizeof(struct prefix));
- else {
- memset(&pfx, 0, sizeof(pfx));
- pfx.family = fam;
- }
- stream_putc(s, pfx.family);
- stream_putc(s, pfx.prefixlen);
- stream_put(s, &pfx.u.prefix, prefix_blen(&pfx));
-
- stream_putw(s, 0); /* src port */
+ r.unique = pbra->unique;
- if (pbr && pbr->flags & MATCH_IP_DST_SET)
- memcpy(&pfx, &(pbr->dst), sizeof(struct prefix));
- else {
- memset(&pfx, 0, sizeof(pfx));
- pfx.family = fam;
- }
- stream_putc(s, pfx.family);
- stream_putc(s, pfx.prefixlen);
- stream_put(s, &pfx.u.prefix, prefix_blen(&pfx));
+ r.family = fam;
- stream_putw(s, 0); /* dst port */
- stream_putc(s, 0); /* dsfield */
- /* if pbr present, fwmark is not used */
- if (pbr)
- stream_putl(s, 0);
- else
- stream_putl(s, pbra->fwmark); /* fwmark */
+ /* filter */
- stream_putl(s, 0); /* queue id */
- stream_putw(s, 0); /* vlan_id */
- stream_putw(s, 0); /* vlan_flags */
- stream_putw(s, 0); /* pcp */
+ if (pbr && pbr->flags & MATCH_IP_SRC_SET) {
+ SET_FLAG(r.filter.filter_bm, PBR_FILTER_SRC_IP);
+ r.filter.src_ip = pbr->src;
+ } else {
+ /* ??? */
+ r.filter.src_ip.family = fam;
+ }
+ if (pbr && pbr->flags & MATCH_IP_DST_SET) {
+ SET_FLAG(r.filter.filter_bm, PBR_FILTER_DST_IP);
+ r.filter.dst_ip = pbr->dst;
+ } else {
+ /* ??? */
+ r.filter.dst_ip.family = fam;
+ }
+ /* src_port, dst_port, pcp, dsfield not used */
+ if (!pbr) {
+ SET_FLAG(r.filter.filter_bm, PBR_FILTER_FWMARK);
+ r.filter.fwmark = pbra->fwmark;
+ }
- stream_putl(s, pbra->table_id);
+ SET_FLAG(r.action.flags, PBR_ACTION_TABLE); /* always valid */
+ r.action.table = pbra->table_id;
- memset(ifname, 0, sizeof(ifname));
- stream_put(s, ifname, INTERFACE_NAMSIZ); /* ifname unused */
+ zapi_pbr_rule_encode(s, &r);
}
static void bgp_encode_pbr_ipset_match(struct stream *s,
@@ -2854,9 +3017,6 @@ static void bgp_zebra_connected(struct zclient *zclient)
bgp_zebra_instance_register(bgp);
- /* tell label pool that zebra is connected */
- bgp_lp_event_zebra_up();
-
/* TODO - What if we have peers and networks configured, do we have to
* kick-start them?
*/
@@ -2983,12 +3143,11 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
is_anycast_mac = stream_getl(s);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug(
- "Rx L3-VNI ADD VRF %s VNI %u RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u",
- vrf_id_to_name(vrf_id), l3vni, &svi_rmac,
- &vrr_rmac,
- filter ? "prefix-routes-only" : "none",
- svi_ifindex);
+ zlog_debug("Rx L3VNI ADD VRF %s VNI %u Originator-IP %pI4 RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u",
+ vrf_id_to_name(vrf_id), l3vni,
+ &originator_ip, &svi_rmac, &vrr_rmac,
+ filter ? "prefix-routes-only" : "none",
+ svi_ifindex);
frrtrace(8, frr_bgp, evpn_local_l3vni_add_zrecv, l3vni, vrf_id,
&svi_rmac, &vrr_rmac, filter, originator_ip,
@@ -2999,7 +3158,7 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
is_anycast_mac);
} else {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx L3-VNI DEL VRF %s VNI %u",
+ zlog_debug("Rx L3VNI DEL VRF %s VNI %u",
vrf_id_to_name(vrf_id), l3vni);
frrtrace(2, frr_bgp, evpn_local_l3vni_del_zrecv, l3vni, vrf_id);
@@ -3161,54 +3320,6 @@ static int bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
return 0;
}
-static int bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
-{
- struct stream *s = NULL;
- uint8_t response_keep;
- uint32_t first;
- uint32_t last;
- uint8_t proto;
- unsigned short instance;
-
- s = zclient->ibuf;
- STREAM_GETC(s, proto);
- STREAM_GETW(s, instance);
- STREAM_GETC(s, response_keep);
- STREAM_GETL(s, first);
- STREAM_GETL(s, last);
-
- if (zclient->redist_default != proto) {
- flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong proto %u",
- proto);
- return 0;
- }
- if (zclient->instance != instance) {
- flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong instance %u",
- proto);
- return 0;
- }
-
- if (first > last ||
- first < MPLS_LABEL_UNRESERVED_MIN ||
- last > MPLS_LABEL_UNRESERVED_MAX) {
-
- flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u",
- __func__, first, last);
- return 0;
- }
- if (BGP_DEBUG(zebra, ZEBRA)) {
- zlog_debug("Label Chunk assign: %u - %u (%u) ",
- first, last, response_keep);
- }
-
- bgp_lp_event_chunk(response_keep, first, last);
-
- return 0;
-
-stream_failure: /* for STREAM_GETX */
- return -1;
-}
-
extern struct zebra_privs_t bgpd_privs;
static int bgp_ifp_create(struct interface *ifp)
@@ -3227,6 +3338,15 @@ static int bgp_ifp_create(struct interface *ifp)
bgp_update_interface_nbrs(bgp, ifp, ifp);
hook_call(bgp_vrf_status_changed, bgp, ifp);
+
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
@@ -3308,7 +3428,7 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)&tmp_prefi)) {
listnode_delete(bgp->srv6_functions, func);
- XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ srv6_function_free(func);
}
}
@@ -3410,10 +3530,8 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_INTERFACE_ADDRESS_DELETE] = bgp_interface_address_delete,
[ZEBRA_INTERFACE_NBR_ADDRESS_ADD] = bgp_interface_nbr_address_add,
[ZEBRA_INTERFACE_NBR_ADDRESS_DELETE] = bgp_interface_nbr_address_delete,
- [ZEBRA_INTERFACE_VRF_UPDATE] = bgp_interface_vrf_update,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = zebra_read_route,
- [ZEBRA_NEXTHOP_UPDATE] = bgp_read_nexthop_update,
[ZEBRA_FEC_UPDATE] = bgp_read_fec_update,
[ZEBRA_LOCAL_ES_ADD] = bgp_zebra_process_local_es_add,
[ZEBRA_LOCAL_ES_DEL] = bgp_zebra_process_local_es_del,
@@ -3427,7 +3545,6 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_L3VNI_DEL] = bgp_zebra_process_local_l3vni,
[ZEBRA_IP_PREFIX_ROUTE_ADD] = bgp_zebra_process_local_ip_prefix,
[ZEBRA_IP_PREFIX_ROUTE_DEL] = bgp_zebra_process_local_ip_prefix,
- [ZEBRA_GET_LABEL_CHUNK] = bgp_zebra_process_label_chunk,
[ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner,
[ZEBRA_IPSET_NOTIFY_OWNER] = ipset_notify_owner,
[ZEBRA_IPSET_ENTRY_NOTIFY_OWNER] = ipset_entry_notify_owner,
@@ -3464,19 +3581,90 @@ void bgp_if_init(void)
hook_register_prio(if_del, 0, bgp_if_delete_hook);
}
+static void bgp_start_label_manager(struct event *start)
+{
+ bgp_zebra_label_manager_connect();
+}
+
+static bool bgp_zebra_label_manager_ready(void)
+{
+ return (zclient_sync->sock > 0);
+}
+
+static bool bgp_zebra_label_manager_connect(void)
+{
+ /* Connect to label manager. */
+ if (zclient_socket_connect(zclient_sync) < 0) {
+ zlog_warn("%s: failed connecting synchronous zclient!",
+ __func__);
+ return false;
+ }
+ /* make socket non-blocking */
+ set_nonblocking(zclient_sync->sock);
+
+ /* Send hello to notify zebra this is a synchronous client */
+ if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) {
+ zlog_warn("%s: failed sending hello for synchronous zclient!",
+ __func__);
+ close(zclient_sync->sock);
+ zclient_sync->sock = -1;
+ return false;
+ }
+
+ /* Connect to label manager */
+ if (lm_label_manager_connect(zclient_sync, 0) != 0) {
+ zlog_warn("%s: failed connecting to label manager!", __func__);
+ if (zclient_sync->sock > 0) {
+ close(zclient_sync->sock);
+ zclient_sync->sock = -1;
+ }
+ return false;
+ }
+
+ /* tell label pool that zebra is connected */
+ bgp_lp_event_zebra_up();
+
+ /* tell BGP L3VPN that label manager is available */
+ if (bgp_get_default())
+ vpn_leak_postchange_all();
+ return true;
+}
+
+static void bgp_zebra_capabilities(struct zclient_capabilities *cap)
+{
+ bm->v6_with_v4_nexthops = cap->v6_with_v4_nexthop;
+}
+
void bgp_zebra_init(struct event_loop *master, unsigned short instance)
{
zclient_num_connects = 0;
- if_zapi_callbacks(bgp_ifp_create, bgp_ifp_up,
- bgp_ifp_down, bgp_ifp_destroy);
+ hook_register_prio(if_real, 0, bgp_ifp_create);
+ hook_register_prio(if_up, 0, bgp_ifp_up);
+ hook_register_prio(if_down, 0, bgp_ifp_down);
+ hook_register_prio(if_unreal, 0, bgp_ifp_destroy);
/* Set default values. */
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
+ zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready;
zclient->zebra_connected = bgp_zebra_connected;
+ zclient->zebra_capabilities = bgp_zebra_capabilities;
+ zclient->nexthop_update = bgp_nexthop_update;
zclient->instance = instance;
+
+ /* Initialize special zclient for synchronous message exchanges. */
+ zclient_sync = zclient_new(master, &zclient_options_sync, NULL, 0);
+ zclient_sync->sock = -1;
+ zclient_sync->redist_default = ZEBRA_ROUTE_BGP;
+ zclient_sync->instance = instance;
+ zclient_sync->session_id = 1;
+ zclient_sync->privs = &bgpd_privs;
+
+ if (!bgp_zebra_label_manager_ready())
+ event_add_timer(master, bgp_start_label_manager, NULL, 1,
+ &bm->t_bgp_start_label_manager);
}
void bgp_zebra_destroy(void)
@@ -3486,6 +3674,12 @@ void bgp_zebra_destroy(void)
zclient_stop(zclient);
zclient_free(zclient);
zclient = NULL;
+
+ if (zclient_sync == NULL)
+ return;
+ zclient_stop(zclient_sync);
+ zclient_free(zclient_sync);
+ zclient_sync = NULL;
}
int bgp_zebra_num_connects(void)
@@ -3517,11 +3711,9 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra,
zclient_create_header(s,
install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE,
VRF_DEFAULT);
- stream_putl(s, 1); /* send one pbr action */
bgp_encode_pbr_rule_action(s, pbra, pbr);
- stream_putw_at(s, 0, stream_get_endp(s));
if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE)
&& install) {
if (!pbr)
@@ -3704,38 +3896,26 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
api.distance = ZEBRA_EBGP_DISTANCE_DEFAULT;
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+ api_nh->vrf_id = nh->vrf_id;
+
+ if (BGP_DEBUG(zebra, ZEBRA)) {
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(nh->vrf_id);
+ zlog_debug("%s: %s default route to %pNHvv(%s) table %d",
+ bgp->name_pretty, announce ? "adding" : "withdrawing",
+ nh, VRF_LOGNAME(vrf), table_id);
+ }
+
/* redirect IP */
if (afi == AFI_IP && nh->gate.ipv4.s_addr != INADDR_ANY) {
- api_nh->vrf_id = nh->vrf_id;
api_nh->gate.ipv4 = nh->gate.ipv4;
api_nh->type = NEXTHOP_TYPE_IPV4;
-
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug(
- "BGP: %s default route to %pI4 table %d (redirect IP)",
- announce ? "adding" : "withdrawing",
- &nh->gate.ipv4, table_id);
-
- zclient_route_send(announce ? ZEBRA_ROUTE_ADD
- : ZEBRA_ROUTE_DELETE,
- zclient, &api);
- } else if (afi == AFI_IP6 &&
- memcmp(&nh->gate.ipv6,
- &in6addr_any, sizeof(struct in6_addr))) {
- api_nh->vrf_id = nh->vrf_id;
+ } else if (afi == AFI_IP6 && memcmp(&nh->gate.ipv6, &in6addr_any,
+ sizeof(struct in6_addr))) {
memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6,
sizeof(struct in6_addr));
api_nh->type = NEXTHOP_TYPE_IPV6;
-
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug(
- "BGP: %s default route to %pI6 table %d (redirect IP)",
- announce ? "adding" : "withdrawing",
- &nh->gate.ipv6, table_id);
-
- zclient_route_send(announce ? ZEBRA_ROUTE_ADD
- : ZEBRA_ROUTE_DELETE,
- zclient, &api);
} else if (nh->vrf_id != bgp->vrf_id) {
struct vrf *vrf;
struct interface *ifp;
@@ -3749,18 +3929,12 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
ifp = if_lookup_by_name_vrf(vrf->name, vrf);
if (!ifp)
return;
- api_nh->vrf_id = nh->vrf_id;
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = ifp->ifindex;
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_info("BGP: %s default route to %s table %d (redirect VRF)",
- announce ? "adding" : "withdrawing",
- vrf->name, table_id);
- zclient_route_send(announce ? ZEBRA_ROUTE_ADD
- : ZEBRA_ROUTE_DELETE,
- zclient, &api);
- return;
}
+
+ zclient_route_send(announce ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
+ zclient, &api);
}
/* Send capabilities to RIB */
@@ -3911,3 +4085,89 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
{
return srv6_manager_release_locator_chunk(zclient, name);
}
+
+void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
+ ifindex_t ifindex, vrf_id_t vrf_id,
+ enum lsp_types_t ltype, struct prefix *p,
+ uint32_t num_labels,
+ mpls_label_t out_labels[])
+{
+ struct zapi_labels zl = {};
+ struct zapi_nexthop *znh;
+ int i = 0;
+
+ zl.type = ltype;
+ zl.local_label = label;
+ zl.nexthop_num = 1;
+ znh = &zl.nexthops[0];
+ if (p->family == AF_INET)
+ IPV4_ADDR_COPY(&znh->gate.ipv4, &p->u.prefix4);
+ else
+ IPV6_ADDR_COPY(&znh->gate.ipv6, &p->u.prefix6);
+ if (ifindex == IFINDEX_INTERNAL)
+ znh->type = (p->family == AF_INET) ? NEXTHOP_TYPE_IPV4
+ : NEXTHOP_TYPE_IPV6;
+ else
+ znh->type = (p->family == AF_INET) ? NEXTHOP_TYPE_IPV4_IFINDEX
+ : NEXTHOP_TYPE_IPV6_IFINDEX;
+ znh->ifindex = ifindex;
+ znh->vrf_id = vrf_id;
+ if (num_labels == 0)
+ znh->label_num = 0;
+ else {
+ if (num_labels > MPLS_MAX_LABELS)
+ znh->label_num = MPLS_MAX_LABELS;
+ else
+ znh->label_num = num_labels;
+ for (i = 0; i < znh->label_num; i++)
+ znh->labels[i] = out_labels[i];
+ }
+ /* vrf_id is DEFAULT_VRF */
+ zebra_send_mpls_labels(zclient, cmd, &zl);
+}
+
+bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
+ bool label_auto)
+{
+ int ret;
+ uint32_t start, end;
+
+ if (!zclient_sync || !bgp_zebra_label_manager_ready())
+ return false;
+
+ ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
+ &end);
+ if (ret < 0) {
+ zlog_warn("%s: error getting label range!", __func__);
+ return false;
+ }
+
+ if (start > end || start < MPLS_LABEL_UNRESERVED_MIN ||
+ end > MPLS_LABEL_UNRESERVED_MAX) {
+ flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u",
+ __func__, start, end);
+ return false;
+ }
+
+ if (label_auto)
+ /* label automatic is serviced by the bgp label pool
+ * manager, which allocates label chunks in
+ * pre-pools, and which needs to be notified about
+ * new chunks availability
+ */
+ bgp_lp_event_chunk(start, end);
+
+ return true;
+}
+
+void bgp_zebra_release_label_range(uint32_t start, uint32_t end)
+{
+ int ret;
+
+ if (!zclient_sync || !bgp_zebra_label_manager_ready())
+ return;
+
+ ret = lm_release_label_chunk(zclient_sync, start, end);
+ if (ret < 0)
+ zlog_warn("%s: error releasing label range!", __func__);
+}