Skip to content

Commit 7774f47

Browse files
authored
Merge pull request FRRouting#18519 from GaladrielZhao/bgp_srv6_sid_explicit
bgpd: Add support for BGP to use SRv6 SID in an explicit way
2 parents 9054fcd + a9c8e72 commit 7774f47

23 files changed

+1103
-24
lines changed

bgpd/bgp_mplsvpn.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
848848
struct in6_addr tovpn_sid = {};
849849
uint32_t tovpn_sid_index = 0;
850850
bool tovpn_sid_auto = false;
851+
bool is_tovpn_sid_explicit = false;
851852
struct srv6_sid_ctx ctx = {};
852853
uint32_t sid_func;
853854

@@ -875,25 +876,39 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
875876

876877
tovpn_sid_index = bgp_vrf->tovpn_sid_index;
877878
tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
879+
is_tovpn_sid_explicit = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT);
878880

879881
/* skip when VPN isn't configured on vrf-instance */
880-
if (tovpn_sid_index == 0 && !tovpn_sid_auto)
882+
if (tovpn_sid_index == 0 && !tovpn_sid_auto && !is_tovpn_sid_explicit)
881883
return;
882884

883-
/* check invalid case both configured index and auto */
884-
if (tovpn_sid_index != 0 && tovpn_sid_auto) {
885-
zlog_err("%s: index-mode and auto-mode both selected. ignored.",
885+
/*
886+
* check invalid case more than one mode configured
887+
* among index, auto and explicit
888+
*/
889+
if ((tovpn_sid_index != 0 && tovpn_sid_auto) ||
890+
(tovpn_sid_index != 0 && is_tovpn_sid_explicit) ||
891+
(tovpn_sid_auto && is_tovpn_sid_explicit)) {
892+
zlog_err("%s: more than one mode selected among index-mode, auto-mode and explicit-mode. ignored.",
886893
__func__);
887894
return;
888895
}
889896

890-
if (!tovpn_sid_auto) {
897+
/* skip when sid value isn't set for explicit-mode */
898+
if (is_tovpn_sid_explicit && !bgp_vrf->tovpn_sid_explicit) {
899+
zlog_err("%s: explicit-mode seleted without sid value.", __func__);
900+
return;
901+
}
902+
903+
if (!tovpn_sid_auto && !is_tovpn_sid_explicit) {
891904
if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator,
892905
bgp_vrf->tovpn_sid_index)) {
893906
zlog_err("%s: failed to compose new sid for vrf %s",
894907
__func__, bgp_vrf->name_pretty);
895908
return;
896909
}
910+
} else if (is_tovpn_sid_explicit) {
911+
tovpn_sid = *(bgp_vrf->tovpn_sid_explicit);
897912
}
898913

899914
ctx.vrf_id = bgp_vrf->vrf_id;
@@ -916,7 +931,8 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
916931

917932
/* per-vrf sid */
918933
if (bgp_vrf->tovpn_sid_index != 0 ||
919-
CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
934+
CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO) ||
935+
CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT))
920936
return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf);
921937
}
922938

@@ -967,6 +983,7 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
967983
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
968984
uint32_t tovpn_sid_index = 0;
969985
bool tovpn_sid_auto = false;
986+
bool is_tovpn_sid_explicit = false;
970987
struct srv6_sid_ctx ctx = {};
971988

972989
if (debug)
@@ -976,9 +993,10 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
976993
tovpn_sid_index = bgp_vrf->tovpn_sid_index;
977994
tovpn_sid_auto =
978995
CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VPN_POLICY_TOVPN_SID_AUTO);
996+
is_tovpn_sid_explicit = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT);
979997

980998
/* skip when VPN is configured on vrf-instance */
981-
if (tovpn_sid_index != 0 || tovpn_sid_auto)
999+
if (tovpn_sid_index != 0 || tovpn_sid_auto || is_tovpn_sid_explicit)
9821000
return;
9831001

9841002
if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
@@ -999,6 +1017,9 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
9991017
sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
10001018
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
10011019
}
1020+
if (bgp_vrf->tovpn_sid_explicit) {
1021+
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid_explicit);
1022+
}
10021023
bgp_vrf->tovpn_sid_transpose_label = 0;
10031024
}
10041025

bgpd/bgp_mplsvpn.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,14 @@ static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
278278
}
279279

280280
if (bgp_vrf->vpn_policy[afi].tovpn_sid_index == 0 &&
281-
!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
282-
BGP_VPN_POLICY_TOVPN_SID_AUTO) &&
281+
!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_SID_AUTO) &&
283282
bgp_vrf->tovpn_sid_index == 0 &&
284-
!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
283+
!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO) &&
284+
!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT))
285285
delete_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
286286

287-
if (!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->tovpn_sid)
287+
if (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT) ||
288+
(!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->tovpn_sid))
288289
ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
289290

290291
if ((!bgp_vrf->vpn_policy[afi].tovpn_sid &&
@@ -366,6 +367,7 @@ static inline bool is_pi_srv6_valid(struct bgp_path_info *pi, struct bgp *bgp_ne
366367

367368
if (bgp_nexthop->tovpn_sid_index == 0 &&
368369
!CHECK_FLAG(bgp_nexthop->vrf_flags, BGP_VRF_TOVPN_SID_AUTO) &&
370+
!CHECK_FLAG(bgp_nexthop->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT) &&
369371
bgp_nexthop->vpn_policy[afi].tovpn_sid_index == 0 &&
370372
!CHECK_FLAG(bgp_nexthop->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_SID_AUTO))
371373
return false;

bgpd/bgp_vty.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10157,31 +10157,37 @@ DEFPY (af_sid_vpn_export,
1015710157

1015810158
DEFPY (bgp_sid_vpn_export,
1015910159
bgp_sid_vpn_export_cmd,
10160-
"[no] sid vpn per-vrf export <(1-1048575)$sid_idx|auto$sid_auto>",
10160+
"[no] sid vpn per-vrf export <(1-1048575)$sid_idx|auto$sid_auto|explicit$sid_explicit X:X::X:X$sid_value>",
1016110161
NO_STR
1016210162
"sid value for VRF\n"
1016310163
"Between current vrf and vpn\n"
1016410164
"sid per-VRF (both IPv4 and IPv6 address families)\n"
1016510165
"For routes leaked from current vrf to vpn\n"
1016610166
"Sid allocation index\n"
10167-
"Automatically assign a label\n")
10167+
"Automatically assign a label\n"
10168+
"Explicitly assign a sid value\n"
10169+
"Sid value\n")
1016810170
{
1016910171
VTY_DECLVAR_CONTEXT(bgp, bgp);
1017010172
int debug;
10173+
struct in6_addr *tovpn_sid_explicit = NULL;
1017110174

1017210175
debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
1017310176
BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
1017410177

1017510178
if (no) {
1017610179
/* when per-VRF SID is not set, do nothing */
1017710180
if (bgp->tovpn_sid_index == 0 &&
10178-
!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
10181+
!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO) &&
10182+
!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT))
1017910183
return CMD_SUCCESS;
1018010184

1018110185
sid_idx = 0;
1018210186
sid_auto = false;
10187+
sid_explicit = false;
1018310188
bgp->tovpn_sid_index = 0;
1018410189
UNSET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
10190+
UNSET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT);
1018510191
}
1018610192

1018710193
if (bgp->vpn_policy[AFI_IP].tovpn_sid_index != 0 ||
@@ -10198,18 +10204,28 @@ DEFPY (bgp_sid_vpn_export,
1019810204

1019910205
/* skip when it's already configured */
1020010206
if ((sid_idx != 0 && bgp->tovpn_sid_index != 0) ||
10201-
(sid_auto && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)))
10207+
(sid_auto && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) ||
10208+
(sid_explicit && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT)))
1020210209
return CMD_SUCCESS;
1020310210

1020410211
/*
10205-
* mode change between sid_idx and sid_auto isn't supported.
10212+
* mode change among sid_idx, sid_auto and sid_explicit isn't supported.
1020610213
* user must negate sid vpn export when they want to change the mode
1020710214
*/
1020810215
if ((sid_auto && bgp->tovpn_sid_index != 0) ||
10209-
(sid_idx != 0 &&
10210-
CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))) {
10211-
vty_out(vty, "it's already configured as %s.\n",
10212-
sid_auto ? "auto-mode" : "idx-mode");
10216+
(sid_auto && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT)) ||
10217+
(sid_idx != 0 && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) ||
10218+
(sid_idx != 0 && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT)) ||
10219+
(sid_explicit && bgp->tovpn_sid_index != 0) ||
10220+
(sid_explicit && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))) {
10221+
vty_out(vty, "it's already configured as ");
10222+
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
10223+
vty_out(vty, "auto-mode.\n");
10224+
else if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT))
10225+
vty_out(vty, "explicit-mode.\n");
10226+
else if (sid_idx != 0)
10227+
vty_out(vty, "idx-mode.\n");
10228+
1021310229
return CMD_WARNING_CONFIG_FAILED;
1021410230
}
1021510231

@@ -10230,6 +10246,15 @@ DEFPY (bgp_sid_vpn_export,
1023010246
zlog_debug("%s: idx %ld per-vrf sid alloc.", __func__,
1023110247
sid_idx);
1023210248
bgp->tovpn_sid_index = sid_idx;
10249+
} else if (sid_explicit) {
10250+
/* SID allocation explicit-mode */
10251+
tovpn_sid_explicit = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
10252+
memcpy(tovpn_sid_explicit, &sid_value, sizeof(struct in6_addr));
10253+
bgp->tovpn_sid_explicit = tovpn_sid_explicit;
10254+
10255+
if (debug)
10256+
zlog_debug("%s: explicit per-vrf sid alloc.", __func__);
10257+
SET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT);
1023310258
}
1023410259

1023510260
/* post-change */
@@ -20032,6 +20057,9 @@ int bgp_config_write(struct vty *vty)
2003220057
tovpn_sid_index = bgp->tovpn_sid_index;
2003320058
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) {
2003420059
vty_out(vty, " sid vpn per-vrf export auto\n");
20060+
} else if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_EXPLICIT)) {
20061+
vty_out(vty, " sid vpn per-vrf export explicit %pI6\n",
20062+
bgp->tovpn_sid_explicit);
2003520063
} else if (tovpn_sid_index != 0) {
2003620064
vty_out(vty, " sid vpn per-vrf export %d\n",
2003720065
tovpn_sid_index);

bgpd/bgpd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,9 @@ static void bgp_srv6_cleanup(struct bgp *bgp)
15341534
sid_unregister(bgp, bgp->tovpn_sid);
15351535
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_sid);
15361536
}
1537+
if (bgp->tovpn_sid_explicit != NULL) {
1538+
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_sid_explicit);
1539+
}
15371540

15381541
if (bgp->srv6_locator_chunks)
15391542
list_delete(&bgp->srv6_locator_chunks);

bgpd/bgpd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ struct bgp {
907907
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6)
908908
/* per-VRF toVPN SID */
909909
#define BGP_VRF_TOVPN_SID_AUTO (1 << 7)
910+
#define BGP_VRF_TOVPN_SID_EXPLICIT (1 << 8)
910911

911912
/* unique ID for auto derivation of RD for this vrf */
912913
uint16_t vrf_rd_id;
@@ -961,6 +962,7 @@ struct bgp {
961962
struct list *srv6_functions;
962963
uint32_t tovpn_sid_index; /* unset => set to 0 */
963964
struct in6_addr *tovpn_sid;
965+
struct in6_addr *tovpn_sid_explicit;
964966
struct srv6_locator *tovpn_sid_locator;
965967
uint32_t tovpn_sid_transpose_label;
966968
struct in6_addr *tovpn_zebra_vrf_sid_last_sent;

doc/user/bgp.rst

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,16 +3427,19 @@ General configuration
34273427
Configuration of the SRv6 SID used to advertise a L3VPN for both IPv4 and IPv6
34283428
is accomplished via the following command in the context of a VRF:
34293429

3430-
.. clicmd:: sid vpn per-vrf export (1..1048575)|auto
3430+
.. clicmd:: sid vpn per-vrf export <(1..1048575)|auto|explicit X:X::X:X>
34313431

34323432
Enables a SRv6 SID to be attached to a route exported from the current
34333433
unicast VRF to VPN. A single SID is used for both IPv4 and IPv6 address
34343434
families. If you want to set a SID for only IPv4 address family or IPv6
3435-
address family, you need to use the command ``sid vpn export (1..1048575)|auto``
3435+
address family, you need to use the command ``sid vpn export <(1..1048575)|auto|explicit X:X::X:X>``
34363436
in the context of an address-family. If the value specified is ``auto``,
34373437
the SID value is automatically assigned from a pool maintained by the Zebra
3438-
daemon. If Zebra is not running, or if this command is not configured, automatic
3439-
SID assignment will not complete, which will block corresponding route export.
3438+
daemon. If the value specified is ``explicit X:X::X:X``, SID allocation
3439+
with the explicit value is requested from the Zebra daemon.
3440+
If Zebra is not running, or if this command is not configured, or if SID
3441+
allocation is failed, automatic or explicit SID assignment will not complete,
3442+
which will block corresponding route export.
34403443

34413444
.. _bgp-evpn:
34423445

tests/topotests/bgp_srv6_sid_explicit/__init__.py

Whitespace-only changes.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
frr version 8.2.2-my-manual-build
2+
frr defaults traditional
3+
hostname c11
4+
!
5+
ip route 0.0.0.0/0 192.168.1.254
6+
ipv6 route ::/0 2001:1::ffff
7+
!
8+
interface eth10
9+
ip address 192.168.1.1/24
10+
ipv6 address 2001:1::1/64
11+
exit
12+
!
13+
segment-routing
14+
traffic-eng
15+
exit
16+
srv6
17+
exit
18+
!
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
frr version 8.2.2-my-manual-build
2+
frr defaults traditional
3+
hostname c12
4+
log stdout
5+
!
6+
ip route 0.0.0.0/0 192.168.1.254
7+
ipv6 route ::/0 2001:1::ffff
8+
!
9+
interface ce2-eth0
10+
ip address 162.0.1.2/24
11+
exit
12+
!
13+
interface eth10
14+
ip address 192.168.1.1/24
15+
ipv6 address 2001:1::1/64
16+
exit
17+
!
18+
interface lo
19+
ip address 2.2.2.2/32
20+
exit
21+
!
22+
router bgp 300
23+
neighbor 162.0.1.1 remote-as 200
24+
!
25+
address-family ipv4 unicast
26+
network 2.2.2.2/32
27+
exit-address-family
28+
exit
29+
!
30+
segment-routing
31+
traffic-eng
32+
exit
33+
srv6
34+
exit
35+
!
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
frr version 10.3-dev-my-manual-build
2+
frr defaults traditional
3+
hostname c21
4+
no ipv6 forwarding
5+
!
6+
ip route 0.0.0.0/0 192.168.2.254
7+
ip route 192.168.0.0/16 192.168.2.254
8+
ipv6 route ::/0 2001:2::ffff
9+
!
10+
interface eth10
11+
ip address 192.168.2.1/24
12+
ipv6 address 2001:2::1/64
13+
exit
14+
!
15+
segment-routing
16+
traffic-eng
17+
exit
18+
exit
19+
!
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
frr version 10.3-dev-my-manual-build
2+
frr defaults traditional
3+
hostname c22
4+
no ipv6 forwarding
5+
!
6+
ip route 0.0.0.0/0 192.168.2.254
7+
ip route 192.168.0.0/16 192.168.2.254
8+
ipv6 route ::/0 2001:2::ffff
9+
!
10+
interface eth10
11+
ip address 192.168.2.1/24
12+
ipv6 address 2001:2::1/64
13+
exit
14+
!
15+
segment-routing
16+
traffic-eng
17+
exit
18+
exit
19+
!

0 commit comments

Comments
 (0)