mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 02:46:26 +00:00
OSPFd: Explicit Null option for Segment-Routing
Add new option to `segment-routing prefix` command to set the Explcit Null flag in addition to the No-PHP flag. MPLS LFIB configuration has been also updated to take into account the Explicit Null flag. Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
parent
6f751f1493
commit
f786c4d7c9
@ -1099,13 +1099,15 @@ dataplane.
|
||||
Fix the Maximum Stack Depth supported by the router. The value depend of the
|
||||
MPLS dataplane. E.g. for Linux kernel, since version 4.13 it is 32.
|
||||
|
||||
.. index:: [no] segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag]
|
||||
.. clicmd:: [no] segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag]
|
||||
.. index:: [no] segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag|explicit-null]
|
||||
.. clicmd:: [no] segment-routing prefix A.B.C.D/M [index (0-65535)|no-php-flag|explicit-null]
|
||||
|
||||
Set the Segment Routing index for the specified prefix. Note that, only
|
||||
prefix with /32 corresponding to a loopback interface are currently
|
||||
supported. The 'no-php-flag' means NO Penultimate Hop Popping that allows SR
|
||||
node to request to its neighbor to not pop the label.
|
||||
node to request to its neighbor to not pop the label. The 'explicit-null' means that
|
||||
neighbor nodes must swap the incoming label by the MPLS Explicit Null label
|
||||
before delivering the packet.
|
||||
|
||||
.. index:: show ip ospf database segment-routing <adv-router ADVROUTER|self-originate> [json]
|
||||
.. clicmd:: show ip ospf database segment-routing <adv-router ADVROUTER|self-originate> [json]
|
||||
|
174
ospfd/ospf_sr.c
174
ospfd/ospf_sr.c
@ -641,9 +641,12 @@ static mpls_label_t index2label(uint32_t index, struct sr_block srgb)
|
||||
mpls_label_t label;
|
||||
|
||||
label = srgb.lower_bound + index;
|
||||
if (label > (srgb.lower_bound + srgb.range_size))
|
||||
if (label > (srgb.lower_bound + srgb.range_size)) {
|
||||
flog_warn(EC_OSPF_SR_SID_OVERFLOW,
|
||||
"%s: SID index %u falls outside SRGB range",
|
||||
__func__, index);
|
||||
return MPLS_INVALID_LABEL;
|
||||
else
|
||||
} else
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -750,6 +753,45 @@ static int compute_link_nhlfe(struct sr_link *srl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute output label for the given Prefix-SID.
|
||||
*
|
||||
* @param srp Segment Routing Prefix
|
||||
* @param srnext Segment Routing nexthop node
|
||||
*
|
||||
* @return MPLS label or MPLS_INVALID_LABEL in case of error
|
||||
*/
|
||||
static mpls_label_t sr_prefix_out_label(const struct sr_prefix *srp,
|
||||
const struct sr_node *srnext)
|
||||
{
|
||||
/* Check if the nexthop SR Node is the last hop? */
|
||||
if (srnext == srp->srn) {
|
||||
/* SR-Node doesn't request NO-PHP. Return Implicit NULL label */
|
||||
if (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG))
|
||||
return MPLS_LABEL_IMPLICIT_NULL;
|
||||
|
||||
/* SR-Node requests Explicit NULL Label */
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
|
||||
return MPLS_LABEL_IPV4_EXPLICIT_NULL;
|
||||
/* Fallthrough */
|
||||
}
|
||||
|
||||
/* Return SID value as MPLS label if it is an Absolute SID */
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG
|
||||
| EXT_SUBTLV_PREFIX_SID_LFLG)) {
|
||||
/*
|
||||
* V/L SIDs have local significance, so only adjacent routers
|
||||
* can use them (RFC8665 section #5)
|
||||
*/
|
||||
if (srp->srn != srnext)
|
||||
return MPLS_INVALID_LABEL;
|
||||
return srp->sid;
|
||||
}
|
||||
|
||||
/* Return MPLS label as SRGB lower bound + SID index as per RFC 8665 */
|
||||
return (index2label(srp->sid, srnext->srgb));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute NHLFE entry for Extended Prefix
|
||||
*
|
||||
@ -800,10 +842,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
|
||||
|
||||
/* And store this information for later update */
|
||||
srnext->neighbor = OspfSR.self;
|
||||
if (IPV4_ADDR_SAME(&srnext->adv_router, &srp->adv_router))
|
||||
path->srni.nexthop = NULL;
|
||||
else
|
||||
path->srni.nexthop = srnext;
|
||||
path->srni.nexthop = srnext;
|
||||
|
||||
/*
|
||||
* SR Node could be known, but SRGB could be not initialize
|
||||
@ -818,18 +857,8 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
|
||||
srnext->srgb.range_size, srnext->srgb.lower_bound,
|
||||
&srnext->adv_router);
|
||||
|
||||
/*
|
||||
* Compute Output Label with Nexthop SR Node SRGB or Implicit
|
||||
* Null label if next hop is the destination and request PHP
|
||||
*/
|
||||
if ((path->srni.nexthop == NULL)
|
||||
&& (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)))
|
||||
path->srni.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
else if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
|
||||
path->srni.label_out = srp->sid;
|
||||
else
|
||||
path->srni.label_out =
|
||||
index2label(srp->sid, srnext->srgb);
|
||||
/* Compute Output Label with Nexthop SR Node SRGB */
|
||||
path->srni.label_out = sr_prefix_out_label(srp, srnext);
|
||||
|
||||
osr_debug(" |- Computed new labels in: %u out: %u",
|
||||
srp->label_in, path->srni.label_out);
|
||||
@ -1194,7 +1223,7 @@ static void update_out_nhlfe(struct hash_bucket *bucket, void *args)
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(srp->route->paths, pnode, path)) {
|
||||
/* Process only SID Index for next hop without PHP */
|
||||
if ((path->srni.nexthop == NULL)
|
||||
if ((path->srni.nexthop == srp->srn)
|
||||
&& (!CHECK_FLAG(srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_NPFLG)))
|
||||
continue;
|
||||
@ -1784,9 +1813,10 @@ void ospf_sr_update_local_prefix(struct interface *ifp, struct prefix *p)
|
||||
" |- Update Node SID %pFX - %u for self SR Node",
|
||||
(struct prefix *)&srp->prefv4, srp->sid);
|
||||
|
||||
/* Install NHLFE if NO-PHP is requested */
|
||||
if (CHECK_FLAG(srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_NPFLG)) {
|
||||
/* Install SID if NO-PHP is set and not EXPLICIT-NULL */
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
|
||||
&& !CHECK_FLAG(srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_EFLG)) {
|
||||
srp->label_in = index2label(srp->sid,
|
||||
OspfSR.self->srgb);
|
||||
srp->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
@ -1913,13 +1943,19 @@ void ospf_sr_config_write_router(struct vty *vty)
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node,
|
||||
srp)) {
|
||||
vty_out(vty,
|
||||
" segment-routing prefix %s/%u index %u%s\n",
|
||||
" segment-routing prefix %s/%u "
|
||||
"index %u",
|
||||
inet_ntoa(srp->prefv4.prefix),
|
||||
srp->prefv4.prefixlen, srp->sid,
|
||||
CHECK_FLAG(srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_NPFLG)
|
||||
? " no-php-flag"
|
||||
: "");
|
||||
srp->prefv4.prefixlen, srp->sid);
|
||||
if (CHECK_FLAG(srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_EFLG))
|
||||
vty_out(vty, " explicit-null\n");
|
||||
else if (CHECK_FLAG(
|
||||
srp->flags,
|
||||
EXT_SUBTLV_PREFIX_SID_NPFLG))
|
||||
vty_out(vty, " no-php-flag\n");
|
||||
else
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2287,19 +2323,20 @@ DEFUN (no_sr_node_msd,
|
||||
|
||||
DEFUN (sr_prefix_sid,
|
||||
sr_prefix_sid_cmd,
|
||||
"segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag]",
|
||||
"segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag|explicit-null]",
|
||||
SR_STR
|
||||
"Prefix SID\n"
|
||||
"IPv4 Prefix as A.B.C.D/M\n"
|
||||
"SID index for this prefix in decimal (0-65535)\n"
|
||||
"Index value inside SRGB (lower_bound < index < upper_bound)\n"
|
||||
"Don't request Penultimate Hop Popping (PHP)\n")
|
||||
"Don't request Penultimate Hop Popping (PHP)\n"
|
||||
"Upstream neighbor must replace prefix-sid with explicit null label\n")
|
||||
{
|
||||
int idx = 0;
|
||||
struct prefix p;
|
||||
uint32_t index;
|
||||
struct listnode *node;
|
||||
struct sr_prefix *srp, *new;
|
||||
struct sr_prefix *srp, *new = NULL;
|
||||
struct interface *ifp;
|
||||
|
||||
if (!ospf_sr_enabled(vty))
|
||||
@ -2321,27 +2358,42 @@ DEFUN (sr_prefix_sid,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* check that the index is not already used */
|
||||
/* Search for an existing Prefix-SID */
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
|
||||
if (srp->sid == index) {
|
||||
vty_out(vty, "Index %u is already used\n", index);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
if (prefix_same((struct prefix *)&srp->prefv4, &p)) {
|
||||
new = srp;
|
||||
break;
|
||||
} else {
|
||||
vty_out(vty, "Index %u is already used\n",
|
||||
index);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create new Extended Prefix to SRDB if not found */
|
||||
new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
|
||||
IPV4_ADDR_COPY(&new->prefv4.prefix, &p.u.prefix4);
|
||||
new->prefv4.prefixlen = p.prefixlen;
|
||||
new->prefv4.family = p.family;
|
||||
new->sid = index;
|
||||
new->type = LOCAL_SID;
|
||||
if (new == NULL) {
|
||||
new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
|
||||
IPV4_ADDR_COPY(&new->prefv4.prefix, &p.u.prefix4);
|
||||
new->prefv4.prefixlen = p.prefixlen;
|
||||
new->prefv4.family = p.family;
|
||||
new->sid = index;
|
||||
new->type = LOCAL_SID;
|
||||
}
|
||||
|
||||
/* Set NO PHP flag if present and compute NHLFE */
|
||||
if (argv_find(argv, argc, "no-php-flag", &idx)) {
|
||||
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
|
||||
UNSET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG);
|
||||
new->label_in = index2label(new->sid, OspfSR.self->srgb);
|
||||
new->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
}
|
||||
/* Set EXPLICIT NULL flag is present */
|
||||
if (argv_find(argv, argc, "explicit-null", &idx)) {
|
||||
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
|
||||
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG);
|
||||
}
|
||||
|
||||
osr_debug("SR (%s): Add new index %u to Prefix %pFX", __func__, index,
|
||||
(struct prefix *)&new->prefv4);
|
||||
@ -2369,27 +2421,16 @@ DEFUN (sr_prefix_sid,
|
||||
}
|
||||
new->nhlfe.ifindex = ifp->ifindex;
|
||||
|
||||
/* Search if this prefix already exist */
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
|
||||
if ((IPV4_ADDR_SAME(&srp->prefv4.prefix, &p.u.prefix4)
|
||||
&& srp->prefv4.prefixlen == p.prefixlen))
|
||||
break;
|
||||
else
|
||||
srp = NULL;
|
||||
}
|
||||
|
||||
/* Update or Add this new SR Prefix */
|
||||
if (srp) {
|
||||
listnode_delete(OspfSR.self->ext_prefix, srp);
|
||||
/* Add this new SR Prefix if not already found */
|
||||
if (srp != new)
|
||||
listnode_add(OspfSR.self->ext_prefix, new);
|
||||
} else {
|
||||
listnode_add(OspfSR.self->ext_prefix, new);
|
||||
}
|
||||
|
||||
/* Install Prefix SID if SR is UP */
|
||||
if (OspfSR.status == SR_UP)
|
||||
ospf_zebra_update_prefix_sid(new);
|
||||
else
|
||||
/* Install Prefix SID if SR is UP and a valid input label set */
|
||||
if (OspfSR.status == SR_UP) {
|
||||
if (CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
|
||||
&& !CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
|
||||
ospf_zebra_update_prefix_sid(new);
|
||||
} else
|
||||
return CMD_SUCCESS;
|
||||
|
||||
/* Finally, update Extended Prefix LSA id SR is UP */
|
||||
@ -2406,14 +2447,15 @@ DEFUN (sr_prefix_sid,
|
||||
|
||||
DEFUN (no_sr_prefix_sid,
|
||||
no_sr_prefix_sid_cmd,
|
||||
"no segment-routing prefix A.B.C.D/M [index (0-65535) no-php-flag]",
|
||||
"no segment-routing prefix A.B.C.D/M [index (0-65535)|no-php-flag|explicit-null]",
|
||||
NO_STR
|
||||
SR_STR
|
||||
"Prefix SID\n"
|
||||
"IPv4 Prefix as A.B.C.D/M\n"
|
||||
"SID index for this prefix in decimal (0-65535)\n"
|
||||
"Index value inside SRGB (lower_bound < index < upper_bound)\n"
|
||||
"Don't request Penultimate Hop Popping (PHP)\n")
|
||||
"Don't request Penultimate Hop Popping (PHP)\n"
|
||||
"Upstream neighbor must replace prefix-sid with explicit null label\n")
|
||||
{
|
||||
int idx = 0;
|
||||
struct prefix p;
|
||||
@ -2468,8 +2510,9 @@ DEFUN (no_sr_prefix_sid,
|
||||
osr_debug("SR (%s): Remove Prefix %pFX with index %u", __func__,
|
||||
(struct prefix *)&srp->prefv4, srp->sid);
|
||||
|
||||
/* Delete NHLFE if NO-PHP is set */
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG))
|
||||
/* Delete NHLFE if NO-PHP is set and EXPLICIT NULL not set */
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
|
||||
&& !CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
|
||||
ospf_zebra_delete_prefix_sid(srp);
|
||||
|
||||
/* OK, all is clean, remove SRP from SRDB */
|
||||
@ -2491,7 +2534,10 @@ static char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
|
||||
snprintf(buf, size, "Pop(%u)", label_in);
|
||||
break;
|
||||
case MPLS_LABEL_IPV4_EXPLICIT_NULL:
|
||||
snprintf(buf, size, "Swap(%u, null)", label_in);
|
||||
if (label_in == MPLS_LABEL_IPV4_EXPLICIT_NULL)
|
||||
snprintf(buf, size, "no-op.");
|
||||
else
|
||||
snprintf(buf, size, "Swap(%u, null)", label_in);
|
||||
break;
|
||||
case MPLS_INVALID_LABEL:
|
||||
snprintf(buf, size, "no-op.");
|
||||
|
@ -112,10 +112,10 @@
|
||||
{
|
||||
"prefix":"10.0.255.1\/32",
|
||||
"sid":100,
|
||||
"inputLabel":20100,
|
||||
"inputLabel":0,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":3,
|
||||
"outputLabel":0,
|
||||
"interface":"lo",
|
||||
"nexthop":"10.0.255.1"
|
||||
}
|
||||
|
@ -18,6 +18,6 @@ router ospf
|
||||
segment-routing on
|
||||
segment-routing node-msd 16
|
||||
segment-routing global-block 20000 29999
|
||||
segment-routing prefix 10.0.255.1/32 index 100 no-php-flag
|
||||
segment-routing prefix 10.0.255.1/32 index 100 explicit-null
|
||||
!
|
||||
|
||||
|
@ -1,19 +1,4 @@
|
||||
[
|
||||
{
|
||||
"inLabel":20100,
|
||||
"installed":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"inLabel":20200,
|
||||
"installed":true,
|
||||
@ -43,20 +28,13 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8300,
|
||||
"outLabel":16300,
|
||||
"outLabelStack":[
|
||||
8300
|
||||
16300
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
},
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":16300,
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.2"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -66,20 +44,13 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8400,
|
||||
"outLabel":16400,
|
||||
"outLabelStack":[
|
||||
8400
|
||||
16400
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
},
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":16400,
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.2"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -166,12 +166,12 @@
|
||||
"inputLabel":16100,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":20100,
|
||||
"outputLabel":0,
|
||||
"interface":"r2-eth0",
|
||||
"nexthop":"10.0.0.1"
|
||||
},
|
||||
{
|
||||
"outputLabel":20100,
|
||||
"outputLabel":0,
|
||||
"interface":"r2-eth1",
|
||||
"nexthop":"10.0.1.1"
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":20100,
|
||||
"outLabel":0,
|
||||
"outLabelStack":[
|
||||
20100
|
||||
0
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":20100,
|
||||
"outLabel":0,
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.1"
|
||||
|
@ -5,9 +5,9 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8100,
|
||||
"outLabel":16100,
|
||||
"outLabelStack":[
|
||||
8100
|
||||
16100
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
@ -37,9 +37,9 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8400,
|
||||
"outLabel":16400,
|
||||
"outLabelStack":[
|
||||
8400
|
||||
16400
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
|
@ -5,9 +5,9 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8100,
|
||||
"outLabel":16100,
|
||||
"outLabelStack":[
|
||||
8100
|
||||
16100
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
@ -37,9 +37,9 @@
|
||||
"nexthops":[
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8300,
|
||||
"outLabel":16300,
|
||||
"outLabelStack":[
|
||||
8300
|
||||
16300
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
|
Loading…
Reference in New Issue
Block a user