Skip to content

Commit

Permalink
pathd: Support srv6 te policy
Browse files Browse the repository at this point in the history
Signed-off-by: guozhongfeng.gzf <[email protected]>
  • Loading branch information
guoguojia2021 committed Nov 27, 2024
1 parent 1dcb4bb commit a1443c2
Show file tree
Hide file tree
Showing 32 changed files with 1,009 additions and 258 deletions.
4 changes: 3 additions & 1 deletion bgpd/bgp_nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1364,8 +1364,10 @@ char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache *bnc, char *buf,
: "",
CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
? "Label Valid "
: "",
CHECK_FLAG(bnc->flags, BGP_NEXTHOP_SRV6TE_VALID)
? "SRv6 TE Valid "
: "");

return buf;
}

Expand Down
1 change: 1 addition & 0 deletions bgpd/bgp_nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct bgp_nexthop_cache {
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5)
#define BGP_NEXTHOP_LABELED_VALID (1 << 6)
#define BGP_NEXTHOP_ULTIMATE (1 << 7)
#define BGP_NEXTHOP_SRV6TE_VALID (1 << 8)

/*
* This flag is added for EVPN gateway IP nexthops.
Expand Down
35 changes: 23 additions & 12 deletions bgpd/bgp_nht.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
}

srte_color = bgp_attr_get_color(pi->attr);
if (srte_color)
p.u.prefix6 = pi->attr->mp_nexthop_global;

} else if (peer) {
/*
Expand Down Expand Up @@ -404,8 +406,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
peer);
} else {
if (BGP_DEBUG(nht, NHT))
zlog_debug("Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p, resolved prefix %pFX",
&bnc->prefix, bnc->ifindex_ipv6_ll,
zlog_debug("Found existing bnc %pFX(%d)(%u)(%s) flags 0x%x ifindex %d #paths %d peer %p, resolved prefix %pFX",
&bnc->prefix, bnc->ifindex_ipv6_ll, bnc->srte_color,
bnc->bgp->name_pretty, bnc->flags,
bnc->ifindex_ipv6_ll, bnc->path_count,
bnc->nht_info, &bnc->resolved_prefix);
Expand Down Expand Up @@ -641,9 +643,11 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,

UNSET_FLAG(bnc->flags,
BGP_NEXTHOP_LABELED_VALID); /* check below */
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_SRV6TE_VALID);

for (i = 0; i < nhr->nexthop_num; i++) {
int num_labels = 0;
int num_segs = 0;

nexthop = nexthop_from_zapi_nexthop(&nhr->nexthops[i]);

Expand Down Expand Up @@ -675,12 +679,17 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
num_labels = nexthop->nh_label->num_labels;
}

if (nexthop->nh_srv6 && nexthop->nh_srv6->seg6_segs) {
SET_FLAG(bnc->flags, BGP_NEXTHOP_SRV6TE_VALID);
num_segs = nexthop->nh_srv6->seg6_segs->num_segs;
}

if (BGP_DEBUG(nht, NHT)) {
char buf[NEXTHOP_STRLEN];
zlog_debug(
" nhop via %s (%d labels)",
" nhop via %s (%d labels) (%d segs))",
nexthop2str(nexthop, buf, sizeof(buf)),
num_labels);
num_labels, num_segs);
}

if (nhlist_tail) {
Expand Down Expand Up @@ -743,6 +752,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_SRV6TE_VALID);
bnc->nexthop_num = nhr->nexthop_num;

/* notify bgp fsm if nbr ip goes from valid->invalid */
Expand Down Expand Up @@ -1123,9 +1133,8 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
*/
static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
{
bool exact_match = false;
bool resolve_via_default = false;
int ret;
uint32_t flags = 0;

if (!zclient)
return;
Expand All @@ -1147,19 +1156,21 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
}
if (command == ZEBRA_NEXTHOP_REGISTER) {
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
exact_match = true;
SET_FLAG(flags, NEXTHOP_REGISTER_FLAG_CONNECTED);
if (CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
resolve_via_default = true;
SET_FLAG(flags, NEXTHOP_REGISTER_FLAG_RESOLVE_VIA_DEFAULT);
}

if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__,
zlog_debug("%s: sending cmd %s for %pFX (vrf %s) color %d", __func__,
zserv_command_string(command), &bnc->prefix,
bnc->bgp->name_pretty);
bnc->bgp->name_pretty, bnc->srte_color);

if (bnc->srte_color)
SET_FLAG(flags, NEXTHOP_REGISTER_FLAG_COLOR);

ret = zclient_send_rnh(zclient, command, &bnc->prefix, SAFI_UNICAST,
exact_match, resolve_via_default,
bnc->bgp->vrf_id);
flags, bnc->bgp->vrf_id, bnc->srte_color);
if (ret == ZCLIENT_SEND_FAILURE) {
flog_warn(EC_BGP_ZEBRA_SEND,
"sendmsg_nexthop: zclient_send_message() failed");
Expand Down
108 changes: 68 additions & 40 deletions bgpd/bgp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,8 @@ static void bgp_zebra_announce_parse_nexthop(
uint32_t bos = 0;
uint32_t exp = 0;
struct bgp_route_evpn *bre = NULL;
struct nexthop_srv6 *nh_srv6 = NULL;
uint8_t num_segs = 0;

/* Determine if we're doing weighted ECMP or not */
do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info);
Expand Down Expand Up @@ -1412,41 +1414,55 @@ static void bgp_zebra_announce_parse_nexthop(

api_nh->weight = nh_weight;

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))
zlog_debug(
"skip invalid SRv6 routes: transposition scheme is used, but label is too small");
continue;
}
nh_srv6 = mpinfo->nexthop->nexthop->nh_srv6;

transpose_sid(&api_nh->seg6_segs[0], nh_label,
mpinfo->attr->srv6_l3vpn
->transposition_offset,
mpinfo->attr->srv6_l3vpn
->transposition_len);
if (nh_srv6 && nh_srv6->seg6_segs && nh_srv6->seg6_segs->num_segs) {
for(num_segs = 0; num_segs < nh_srv6->seg6_segs->num_segs; num_segs++) {
memcpy(&api_nh->seg6_segs[num_segs], &nh_srv6->seg6_segs->seg[num_segs],
sizeof(struct in6_addr));
}

api_nh->seg_num = 1;
api_nh->seg_num = nh_srv6->seg6_segs->num_segs;
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
}
else {

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))
zlog_debug(
"skip invalid SRv6 routes: transposition scheme is used, but label is too small");
continue;
}

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)++;
}
Expand All @@ -1460,8 +1476,8 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
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];
char sid_buf[INET6_ADDRSTRLEN];
char segs_buf[512];
struct zapi_nexthop *api_nh;
int count;

Expand Down Expand Up @@ -1500,20 +1516,32 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
!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);
!CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {

strlcat(segs_buf, "segs ", sizeof(segs_buf));
for (int j = 0; j < api_nh->seg_num; j++) {
memset(sid_buf, 0, sizeof(sid_buf));
inet_ntop(AF_INET6, &api_nh->seg6_segs[j],
sid_buf, sizeof(sid_buf));

if (0 > j && j < api_nh->seg_num - 1)
strlcat(segs_buf, "/", sizeof(segs_buf));

strlcat(segs_buf, sid_buf, sizeof(segs_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 %" PRIu64

zlog_debug(" nhop [%d][%u]: %s if %u VRF %u wt %" PRIu64
" %s %s %s",
i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id,
i + 1, api_nh->srte_color, nh_buf, api_nh->ifindex, api_nh->vrf_id,
api_nh->weight, label_buf, segs_buf, eth_buf);
}
}
Expand Down Expand Up @@ -1639,9 +1667,9 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
}

if (bgp_debug_zebra(p)) {
zlog_debug("Tx route add %s (table id %u) %pFX metric %u tag %" ROUTE_TAG_PRI
zlog_debug("Tx route add %s (table id %u) %pFX color %u metric %u tag %" ROUTE_TAG_PRI
" count %d nhg %d",
bgp->name_pretty, api.tableid, &api.prefix,
bgp->name_pretty, api.tableid, &api.prefix, api.srte_color,
api.metric, api.tag, api.nexthop_num, nhg_id);
bgp_debug_zebra_nh(&api);

Expand Down
4 changes: 3 additions & 1 deletion lib/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_TC_FILTER_ADD),
DESC_ENTRY(ZEBRA_TC_FILTER_DELETE),
DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY),
DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY)
DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY),
DESC_ENTRY(ZEBRA_SRV6_POLICY_SET),
DESC_ENTRY(ZEBRA_SRV6_POLICY_DELETE)
};
#undef DESC_ENTRY

Expand Down
19 changes: 19 additions & 0 deletions lib/prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,25 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
return str;
}

int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip)
{
const struct prefix *p = pu.p;
memset(ip, 0, sizeof(struct ipaddr));

if (p->family == AF_INET) {
ip->ipa_type = IPADDR_V4;
memcpy(&(ip->ipaddr_v4), &(p->u.prefix4),
sizeof(struct in_addr));
} else if (p->family == AF_INET6) {
ip->ipa_type = IPADDR_V6;
memcpy(&(ip->ipaddr_v6), &(p->u.prefix6),
sizeof(struct in6_addr));
} else
return -1;

return 0;
}

void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
char *buf, int buf_size)
{
Expand Down
1 change: 1 addition & 0 deletions lib/prefix.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
extern const char *prefix2str(union prefixconstptr upfx, char *buffer,
int size);
extern int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip);
extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
const struct prefix *match_pfx);
extern int prefix_match(union prefixconstptr unet, union prefixconstptr upfx);
Expand Down
Loading

0 comments on commit a1443c2

Please sign in to comment.