diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index c20c435003..2f0751a5f0 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -4122,7 +4122,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* SRv6 Service Information Attribute. */ - if (afi == AFI_IP && safi == SAFI_MPLS_VPN) { + if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) { if (attr->srv6_l3vpn) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index c16edc20f5..2d0c9ec017 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -684,6 +684,33 @@ static void setlabels(struct bgp_path_info *bpi, extra->num_labels = num_labels; } +/* + * make encoded route SIDs match specified encoded sid set + */ +static void setsids(struct bgp_path_info *bpi, + struct in6_addr *sid, + uint32_t num_sids) +{ + uint32_t i; + struct bgp_path_info_extra *extra; + + if (num_sids) + assert(sid); + assert(num_sids <= BGP_MAX_SIDS); + + if (!num_sids) { + if (bpi->extra) + bpi->extra->num_sids = 0; + return; + } + + extra = bgp_path_info_extra_get(bpi); + for (i = 0; i < num_sids; i++) { + memcpy(&extra->sid[i], &sid[i], sizeof(struct in6_addr)); + } + extra->num_sids = num_sids; +} + /* * returns pointer to new bgp_path_info upon success */ @@ -700,6 +727,10 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ struct bgp_path_info *bpi_ultimate; struct bgp_path_info *new; + uint32_t num_sids = 0; + if (new_attr->srv6_l3vpn || new_attr->srv6_vpn) + num_sids = 1; + if (debug) zlog_debug( "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d", @@ -777,6 +808,16 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (!labelssame) setlabels(bpi, label, num_labels); + /* + * rewrite sid + */ + if (num_sids) { + if (new_attr->srv6_l3vpn) + setsids(bpi, &new_attr->srv6_l3vpn->sid, num_sids); + else if (new_attr->srv6_vpn) + setsids(bpi, &new_attr->srv6_vpn->sid, num_sids); + } + if (nexthop_self_flag) bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF); @@ -839,6 +880,16 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ bgp_path_info_extra_get(new); + /* + * rewrite sid + */ + if (num_sids) { + if (new_attr->srv6_l3vpn) + setsids(new, &new_attr->srv6_l3vpn->sid, num_sids); + else if (new_attr->srv6_vpn) + setsids(new, &new_attr->srv6_vpn->sid, num_sids); + } + if (num_labels) setlabels(new, label, num_labels); @@ -1095,6 +1146,17 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)); static_attr.originator_id = bgp_vpn->router_id; + /* Set SID for SRv6 VPN */ + if (!sid_zero(bgp_vrf->vpn_policy[afi].tovpn_sid)) { + static_attr.srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN, + sizeof(struct bgp_attr_srv6_l3vpn)* 100); + static_attr.srv6_l3vpn->sid_flags = 0x00; + static_attr.srv6_l3vpn->endpoint_behavior = 0xffff; + memcpy(&static_attr.srv6_l3vpn->sid, + bgp_vrf->vpn_policy[afi].tovpn_sid, + sizeof(static_attr.srv6_l3vpn->sid)); + } + new_attr = bgp_attr_intern( &static_attr); /* hashed refcounted everything */