bgpd: handle srv6 locator notification and update vpn-rib

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
This commit is contained in:
Hiroki Shirokura 2021-09-05 02:24:23 +00:00
parent 0a735cd523
commit d79ff732cd
3 changed files with 123 additions and 2 deletions

View File

@ -714,6 +714,15 @@ static void setsids(struct bgp_path_info *bpi,
extra->num_sids = num_sids;
}
static void unsetsids(struct bgp_path_info *bpi)
{
struct bgp_path_info_extra *extra;
extra = bgp_path_info_extra_get(bpi);
extra->num_sids = 0;
memset(extra->sid, 0, sizeof(extra->sid));
}
/*
* returns pointer to new bgp_path_info upon success
*/
@ -821,7 +830,8 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
else if (new_attr->srv6_vpn)
setsids(bpi, &new_attr->srv6_vpn->sid,
num_sids);
}
} else
unsetsids(bpi);
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
@ -847,6 +857,17 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
nh_valid = bgp_find_or_add_nexthop(
bgp, bgp_nexthop, afi, safi, bpi, NULL, 0, p);
/*
* If you are using SRv6 VPN instead of MPLS, it need to check
* the SID allocation. If the sid is not allocated, the rib
* will be invalid.
*/
if (bgp->srv6_enabled
&& (!new_attr->srv6_l3vpn && !new_attr->srv6_vpn)) {
bgp_path_info_unset_flag(bn, bpi, BGP_PATH_VALID);
nh_valid = false;
}
if (debug)
zlog_debug("%s: nexthop is %svalid (in vrf %s)",
__func__, (nh_valid ? "" : "not "),
@ -893,7 +914,8 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
setsids(new, &new_attr->srv6_l3vpn->sid, num_sids);
else if (new_attr->srv6_vpn)
setsids(new, &new_attr->srv6_vpn->sid, num_sids);
}
} else
unsetsids(new);
if (num_labels)
setlabels(new, label, num_labels);
@ -933,6 +955,17 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
nh_valid = bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi,
new, NULL, 0, p);
/*
* If you are using SRv6 VPN instead of MPLS, it need to check
* the SID allocation. If the sid is not allocated, the rib
* will be invalid.
*/
if (bgp->srv6_enabled
&& (!new->attr->srv6_l3vpn && !new->attr->srv6_vpn)) {
bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
nh_valid = false;
}
if (debug)
zlog_debug("%s: nexthop is %svalid (in vrf %s)",
__func__, (nh_valid ? "" : "not "),

View File

@ -243,6 +243,10 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
if (!bgp_vrf->vpn_policy[afi].tovpn_sid)
ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
if (!bgp_vrf->vpn_policy[afi].tovpn_sid
&& bgp_vrf->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf, afi);
if (sid_diff(bgp_vrf->vpn_policy[afi].tovpn_sid,
bgp_vrf->vpn_policy[afi]
.tovpn_zebra_vrf_sid_last_sent)) {

View File

@ -3077,6 +3077,88 @@ static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
vpn_leak_postchange_all();
}
static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
{
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
const char *loc_name = bgp->srv6_locator_name;
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
if (!bgp || !bgp->srv6_enabled)
return 0;
if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0)
return -1;
return 0;
}
static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
{
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
struct listnode *node, *nnode;
struct prefix_ipv6 *chunk;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
struct in6_addr *tovpn_sid;
struct prefix_ipv6 tmp_prefi;
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
// refresh chunks
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk))
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)chunk))
listnode_delete(bgp->srv6_locator_chunks, chunk);
// refresh functions
for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) {
tmp_prefi.family = AF_INET6;
tmp_prefi.prefixlen = 128;
tmp_prefi.prefix = func->sid;
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)&tmp_prefi))
listnode_delete(bgp->srv6_functions, func);
}
// refresh tovpn_sid
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
// refresh vpnv4 tovpn_sid
tovpn_sid = bgp_vrf->vpn_policy[AFI_IP].tovpn_sid;
if (tovpn_sid) {
tmp_prefi.family = AF_INET6;
tmp_prefi.prefixlen = 128;
tmp_prefi.prefix = *tovpn_sid;
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)&tmp_prefi))
XFREE(MTYPE_BGP_SRV6_SID,
bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
}
// refresh vpnv6 tovpn_sid
tovpn_sid = bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid;
if (tovpn_sid) {
tmp_prefi.family = AF_INET6;
tmp_prefi.prefixlen = 128;
tmp_prefi.prefix = *tovpn_sid;
if (prefix_match((struct prefix *)&loc.prefix,
(struct prefix *)&tmp_prefi))
XFREE(MTYPE_BGP_SRV6_SID,
bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
}
}
vpn_leak_postchange_all();
return 0;
}
void bgp_zebra_init(struct thread_master *master, unsigned short instance)
{
zclient_num_connects = 0;
@ -3119,6 +3201,8 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
zclient->iptable_notify_owner = iptable_notify_owner;
zclient->route_notify_owner = bgp_zebra_route_notify_owner;
zclient->instance = instance;
zclient->srv6_locator_add = bgp_zebra_process_srv6_locator_add;
zclient->srv6_locator_delete = bgp_zebra_process_srv6_locator_delete;
zclient->process_srv6_locator_chunk =
bgp_zebra_process_srv6_locator_chunk;
}