Merge pull request #9683 from volta-networks/sr-minor-fixes

ospfd, isisd: minor SR fixes
This commit is contained in:
Igor Ryzhov 2021-11-20 14:53:09 +03:00 committed by GitHub
commit 587cf8f170
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 216 additions and 106 deletions

View File

@ -550,13 +550,13 @@ static void sr_local_block_delete(struct isis_area *area)
*/ */
static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb) static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
{ {
mpls_label_t label; mpls_label_t label;
uint32_t index; uint32_t index;
uint32_t pos; uint32_t pos;
uint32_t size = srlb->end - srlb->start + 1;
/* Check if we ran out of available labels */ /* Check if we ran out of available labels */
if (srlb->current >= srlb->end) if (srlb->current >= size)
return MPLS_INVALID_LABEL; return MPLS_INVALID_LABEL;
/* Get first available label and mark it used */ /* Get first available label and mark it used */
@ -568,7 +568,7 @@ static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
/* Jump to the next free position */ /* Jump to the next free position */
srlb->current++; srlb->current++;
pos = srlb->current % SRLB_BLOCK_SIZE; pos = srlb->current % SRLB_BLOCK_SIZE;
while (srlb->current < srlb->end) { while (srlb->current < size) {
if (pos == 0) if (pos == 0)
index++; index++;
if (!((1ULL << pos) & srlb->used_mark[index])) if (!((1ULL << pos) & srlb->used_mark[index]))
@ -579,6 +579,10 @@ static mpls_label_t sr_local_block_request_label(struct sr_local_block *srlb)
} }
} }
if (srlb->current == size)
zlog_warn(
"SR: Warning, SRLB is depleted and next label request will fail");
return label; return label;
} }

View File

@ -1645,11 +1645,15 @@ DEFUN (no_debug_ospf,
DEBUG_OFF(nsm, NSM_EVENTS); DEBUG_OFF(nsm, NSM_EVENTS);
DEBUG_OFF(nsm, NSM_STATUS); DEBUG_OFF(nsm, NSM_STATUS);
DEBUG_OFF(nsm, NSM_TIMERS); DEBUG_OFF(nsm, NSM_TIMERS);
DEBUG_OFF(event, EVENT);
DEBUG_OFF(zebra, ZEBRA); DEBUG_OFF(zebra, ZEBRA);
DEBUG_OFF(zebra, ZEBRA_INTERFACE); DEBUG_OFF(zebra, ZEBRA_INTERFACE);
DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
DEBUG_OFF(defaultinfo, DEFAULTINFO); DEBUG_OFF(defaultinfo, DEFAULTINFO);
DEBUG_OFF(ldp_sync, LDP_SYNC); DEBUG_OFF(ldp_sync, LDP_SYNC);
DEBUG_OFF(te, TE);
DEBUG_OFF(sr, SR);
DEBUG_OFF(ti_lfa, TI_LFA);
/* BFD debugging is two parts: OSPF and library. */ /* BFD debugging is two parts: OSPF and library. */
DEBUG_OFF(bfd, BFD_LIB); DEBUG_OFF(bfd, BFD_LIB);
@ -1682,6 +1686,9 @@ DEFUN (no_debug_ospf,
TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO); TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
TERM_DEBUG_OFF(ldp_sync, LDP_SYNC); TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
TERM_DEBUG_OFF(te, TE);
TERM_DEBUG_OFF(sr, SR);
TERM_DEBUG_OFF(ti_lfa, TI_LFA);
TERM_DEBUG_OFF(bfd, BFD_LIB); TERM_DEBUG_OFF(bfd, BFD_LIB);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -1792,6 +1799,18 @@ static int show_debugging_ospf_common(struct vty *vty)
if (IS_DEBUG_OSPF(gr, GR) == OSPF_DEBUG_GR) if (IS_DEBUG_OSPF(gr, GR) == OSPF_DEBUG_GR)
vty_out(vty, " OSPF Graceful Restart debugging is on\n"); vty_out(vty, " OSPF Graceful Restart debugging is on\n");
/* Show debug status for TE */
if (IS_DEBUG_OSPF(te, TE) == OSPF_DEBUG_TE)
vty_out(vty, " OSPF TE debugging is on\n");
/* Show debug status for SR */
if (IS_DEBUG_OSPF(sr, SR) == OSPF_DEBUG_SR)
vty_out(vty, " OSPF SR debugging is on\n");
/* Show debug status for TI-LFA */
if (IS_DEBUG_OSPF(ti_lfa, TI_LFA) == OSPF_DEBUG_TI_LFA)
vty_out(vty, " OSPF TI-LFA debugging is on\n");
if (IS_DEBUG_OSPF(bfd, BFD_LIB) == OSPF_DEBUG_BFD_LIB) if (IS_DEBUG_OSPF(bfd, BFD_LIB) == OSPF_DEBUG_BFD_LIB)
vty_out(vty, vty_out(vty,
" OSPF BFD integration library debugging is on\n"); " OSPF BFD integration library debugging is on\n");
@ -1966,7 +1985,7 @@ static int config_write_debug(struct vty *vty)
} }
/* debug ospf sr ti-lfa */ /* debug ospf sr ti-lfa */
if (IS_CONF_DEBUG_OSPF(sr, TI_LFA) == OSPF_DEBUG_TI_LFA) { if (IS_CONF_DEBUG_OSPF(ti_lfa, TI_LFA) == OSPF_DEBUG_TI_LFA) {
vty_out(vty, "debug ospf%s ti-lfa\n", str); vty_out(vty, "debug ospf%s ti-lfa\n", str);
write = 1; write = 1;
} }

View File

@ -256,10 +256,10 @@ static uint32_t get_ext_link_instance_value(void)
/* Lookup Extended Prefix/Links by ifp from OspfEXT struct iflist */ /* Lookup Extended Prefix/Links by ifp from OspfEXT struct iflist */
static struct ext_itf *lookup_ext_by_ifp(struct interface *ifp) static struct ext_itf *lookup_ext_by_ifp(struct interface *ifp)
{ {
struct listnode *node, *nnode; struct listnode *node;
struct ext_itf *exti; struct ext_itf *exti;
for (ALL_LIST_ELEMENTS(OspfEXT.iflist, node, nnode, exti)) for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
if (exti->ifp == ifp) if (exti->ifp == ifp)
return exti; return exti;

View File

@ -279,17 +279,19 @@ static int sr_local_block_init(uint32_t lower_bound, uint32_t upper_bound)
*/ */
size = upper_bound - lower_bound + 1; size = upper_bound - lower_bound + 1;
if (ospf_zebra_request_label_range(lower_bound, size)) { if (ospf_zebra_request_label_range(lower_bound, size)) {
srlb->reserved = false; zlog_err("SR: Error reserving SRLB [%u/%u] %u labels",
lower_bound, upper_bound, size);
return -1; return -1;
} }
osr_debug("SR (%s): Got new SRLB [%u/%u]", __func__, lower_bound, osr_debug("SR: Got new SRLB [%u/%u], %u labels", lower_bound,
upper_bound); upper_bound, size);
/* Initialize the SRLB */ /* Initialize the SRLB */
srlb->start = lower_bound; srlb->start = lower_bound;
srlb->end = upper_bound; srlb->end = upper_bound;
srlb->current = 0; srlb->current = 0;
/* Compute the needed Used Mark number and allocate them */ /* Compute the needed Used Mark number and allocate them */
srlb->max_block = size / SRLB_BLOCK_SIZE; srlb->max_block = size / SRLB_BLOCK_SIZE;
if ((size % SRLB_BLOCK_SIZE) != 0) if ((size % SRLB_BLOCK_SIZE) != 0)
@ -301,6 +303,31 @@ static int sr_local_block_init(uint32_t lower_bound, uint32_t upper_bound)
return 0; return 0;
} }
static int sr_global_block_init(uint32_t start, uint32_t size)
{
struct sr_global_block *srgb = &OspfSR.srgb;
/* Check if already configured */
if (srgb->reserved)
return 0;
/* request chunk */
uint32_t end = start + size - 1;
if (ospf_zebra_request_label_range(start, size) < 0) {
zlog_err("SR: Error reserving SRGB [%u/%u], %u labels", start,
end, size);
return -1;
}
osr_debug("SR: Got new SRGB [%u/%u], %u labels", start, end, size);
/* success */
srgb->start = start;
srgb->size = size;
srgb->reserved = true;
return 0;
}
/** /**
* Remove Segment Routing Local Block. * Remove Segment Routing Local Block.
* *
@ -322,9 +349,30 @@ static void sr_local_block_delete(void)
/* Then reset SRLB structure */ /* Then reset SRLB structure */
if (srlb->used_mark != NULL) if (srlb->used_mark != NULL)
XFREE(MTYPE_OSPF_SR_PARAMS, srlb->used_mark); XFREE(MTYPE_OSPF_SR_PARAMS, srlb->used_mark);
srlb->reserved = false; srlb->reserved = false;
} }
/**
* Remove Segment Routing Global block
*/
static void sr_global_block_delete(void)
{
struct sr_global_block *srgb = &OspfSR.srgb;
if (!srgb->reserved)
return;
osr_debug("SR (%s): Remove SRGB [%u/%u]", __func__, srgb->start,
srgb->start + srgb->size - 1);
ospf_zebra_release_label_range(srgb->start,
srgb->start + srgb->size - 1);
srgb->reserved = false;
}
/** /**
* Request a label from the Segment Routing Local Block. * Request a label from the Segment Routing Local Block.
* *
@ -337,9 +385,10 @@ mpls_label_t ospf_sr_local_block_request_label(void)
mpls_label_t label; mpls_label_t label;
uint32_t index; uint32_t index;
uint32_t pos; uint32_t pos;
uint32_t size = srlb->end - srlb->start + 1;
/* Check if we ran out of available labels */ /* Check if we ran out of available labels */
if (srlb->current >= srlb->end) if (srlb->current >= size)
return MPLS_INVALID_LABEL; return MPLS_INVALID_LABEL;
/* Get first available label and mark it used */ /* Get first available label and mark it used */
@ -351,7 +400,7 @@ mpls_label_t ospf_sr_local_block_request_label(void)
/* Jump to the next free position */ /* Jump to the next free position */
srlb->current++; srlb->current++;
pos = srlb->current % SRLB_BLOCK_SIZE; pos = srlb->current % SRLB_BLOCK_SIZE;
while (srlb->current < srlb->end) { while (srlb->current < size) {
if (pos == 0) if (pos == 0)
index++; index++;
if (!((1ULL << pos) & srlb->used_mark[index])) if (!((1ULL << pos) & srlb->used_mark[index]))
@ -362,6 +411,10 @@ mpls_label_t ospf_sr_local_block_request_label(void)
} }
} }
if (srlb->current == size)
zlog_warn(
"SR: Warning, SRLB is depleted and next label request will fail");
return label; return label;
} }
@ -469,16 +522,11 @@ static int ospf_sr_start(struct ospf *ospf)
* If the allocation fails, return an error to disable SR until a new * If the allocation fails, return an error to disable SR until a new
* SRLB and/or SRGB are successfully allocated. * SRLB and/or SRGB are successfully allocated.
*/ */
sr_local_block_init(OspfSR.srlb.start, OspfSR.srlb.end); if (sr_local_block_init(OspfSR.srlb.start, OspfSR.srlb.end) < 0)
if (!OspfSR.srgb.reserved) { return -1;
if (ospf_zebra_request_label_range(OspfSR.srgb.start,
OspfSR.srgb.size) if (sr_global_block_init(OspfSR.srgb.start, OspfSR.srgb.size) < 0)
< 0) {
OspfSR.srgb.reserved = false;
return -1; return -1;
} else
OspfSR.srgb.reserved = true;
}
/* SR is UP and ready to flood LSA */ /* SR is UP and ready to flood LSA */
OspfSR.status = SR_UP; OspfSR.status = SR_UP;
@ -534,13 +582,10 @@ static void ospf_sr_stop(void)
/* Disable any re-attempt to connect to Label Manager */ /* Disable any re-attempt to connect to Label Manager */
THREAD_OFF(OspfSR.t_start_lm); THREAD_OFF(OspfSR.t_start_lm);
/* Release SRGB & SRLB if active. */ /* Release SRGB if active */
if (OspfSR.srgb.reserved) { sr_global_block_delete();
ospf_zebra_release_label_range(
OspfSR.srgb.start, /* Release SRLB if active */
OspfSR.srgb.start + OspfSR.srgb.size - 1);
OspfSR.srgb.reserved = false;
}
sr_local_block_delete(); sr_local_block_delete();
/* /*
@ -581,7 +626,7 @@ int ospf_sr_init(void)
OspfSR.srgb.reserved = false; OspfSR.srgb.reserved = false;
OspfSR.srlb.start = DEFAULT_SRLB_LABEL; OspfSR.srlb.start = DEFAULT_SRLB_LABEL;
OspfSR.srlb.end = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1; OspfSR.srlb.end = DEFAULT_SRLB_END;
OspfSR.srlb.reserved = false; OspfSR.srlb.reserved = false;
OspfSR.msd = 0; OspfSR.msd = 0;
@ -1200,7 +1245,9 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
/* Search for existing Segment Prefix */ /* Search for existing Segment Prefix */
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, pref)) for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, pref))
if (pref->instance == srp->instance) { if (pref->instance == srp->instance
&& prefix_same((struct prefix *)&srp->prefv4,
&pref->prefv4)) {
found = true; found = true;
break; break;
} }
@ -1231,9 +1278,6 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
/* Replace Segment Prefix */ /* Replace Segment Prefix */
listnode_delete(srn->ext_prefix, pref); listnode_delete(srn->ext_prefix, pref);
XFREE(MTYPE_OSPF_SR_PARAMS, pref); XFREE(MTYPE_OSPF_SR_PARAMS, pref);
srp->srn = srn;
IPV4_ADDR_COPY(&srp->adv_router,
&srn->adv_router);
listnode_add(srn->ext_prefix, srp); listnode_add(srn->ext_prefix, srp);
ospf_zebra_update_prefix_sid(srp); ospf_zebra_update_prefix_sid(srp);
} else { } else {
@ -2099,6 +2143,20 @@ static int ospf_sr_enabled(struct vty *vty)
return 0; return 0;
} }
/* tell if two ranges [r1_lower, r1_upper] and [r2_lower,r2_upper] overlap */
static bool ranges_overlap(uint32_t r1_lower, uint32_t r1_upper,
uint32_t r2_lower, uint32_t r2_upper)
{
return !((r1_upper < r2_lower) || (r1_lower > r2_upper));
}
/* tell if a range is valid */
static bool sr_range_is_valid(uint32_t lower, uint32_t upper, uint32_t min_size)
{
return (upper >= lower + min_size);
}
/** /**
* Update SRGB and/or SRLB using new CLI values. * Update SRGB and/or SRLB using new CLI values.
* *
@ -2136,12 +2194,8 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
/* Release old SRGB if it has changed and is active. */ /* Release old SRGB if it has changed and is active. */
if (gb_changed) { if (gb_changed) {
if (OspfSR.srgb.reserved) {
ospf_zebra_release_label_range( sr_global_block_delete();
OspfSR.srgb.start,
OspfSR.srgb.start + OspfSR.srgb.size - 1);
OspfSR.srgb.reserved = false;
}
/* Set new SRGB values - but do not reserve yet (we need to /* Set new SRGB values - but do not reserve yet (we need to
* release the SRLB too) */ * release the SRLB too) */
@ -2155,7 +2209,7 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
/* Release old SRLB if it has changed and reserve new block as needed. /* Release old SRLB if it has changed and reserve new block as needed.
*/ */
if (lb_changed) { if (lb_changed) {
if (OspfSR.srlb.reserved)
sr_local_block_delete(); sr_local_block_delete();
/* Set new SRLB values */ /* Set new SRLB values */
@ -2175,18 +2229,11 @@ static int update_sr_blocks(uint32_t gb_lower, uint32_t gb_upper,
* allocated. * allocated.
*/ */
if (gb_changed) { if (gb_changed) {
if (ospf_zebra_request_label_range(OspfSR.srgb.start, if (sr_global_block_init(OspfSR.srgb.start, OspfSR.srgb.size)
OspfSR.srgb.size)
< 0) { < 0) {
OspfSR.srgb.reserved = false;
ospf_sr_stop(); ospf_sr_stop();
return -1; return -1;
} else }
OspfSR.srgb.reserved = true;
osr_debug("SR(%s): Got new SRGB [%u/%u]", __func__,
OspfSR.srgb.start,
OspfSR.srgb.start + OspfSR.srgb.size - 1);
} }
/* Update Self SR-Node */ /* Update Self SR-Node */
@ -2227,16 +2274,29 @@ DEFUN(sr_global_label_range, sr_global_label_range_cmd,
/* Get lower and upper bound for mandatory global-block */ /* Get lower and upper bound for mandatory global-block */
gb_lower = strtoul(argv[idx_gb_low]->arg, NULL, 10); gb_lower = strtoul(argv[idx_gb_low]->arg, NULL, 10);
gb_upper = strtoul(argv[idx_gb_up]->arg, NULL, 10); gb_upper = strtoul(argv[idx_gb_up]->arg, NULL, 10);
/* SRLB values are taken from vtysh if there, else use the known ones */ /* SRLB values are taken from vtysh if there, else use the known ones */
lb_upper = argc > idx_lb_up ? strtoul(argv[idx_lb_up]->arg, NULL, 10) lb_upper = argc > idx_lb_up ? strtoul(argv[idx_lb_up]->arg, NULL, 10)
: OspfSR.srlb.end; : OspfSR.srlb.end;
lb_lower = argc > idx_lb_low ? strtoul(argv[idx_lb_low]->arg, NULL, 10) lb_lower = argc > idx_lb_low ? strtoul(argv[idx_lb_low]->arg, NULL, 10)
: OspfSR.srlb.start; : OspfSR.srlb.start;
/* check correctness of input SRGB */
if (!sr_range_is_valid(gb_lower, gb_upper, MIN_SRGB_SIZE)) {
vty_out(vty, "Invalid SRGB range\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* check correctness of SRLB */
if (!sr_range_is_valid(lb_lower, lb_upper, MIN_SRLB_SIZE)) {
vty_out(vty, "Invalid SRLB range\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Validate SRGB against SRLB */ /* Validate SRGB against SRLB */
if (!((gb_upper < lb_lower) || (gb_lower > lb_upper))) { if (ranges_overlap(gb_lower, gb_upper, lb_lower, lb_upper)) {
vty_out(vty, vty_out(vty,
"New SR Global Block (%u/%u) conflict with Local Block (%u/%u)\n", "New SR Global Block (%u/%u) conflicts with Local Block (%u/%u)\n",
gb_lower, gb_upper, lb_lower, lb_upper); gb_lower, gb_upper, lb_lower, lb_upper);
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
@ -2287,6 +2347,12 @@ DEFUN_HIDDEN(sr_local_label_range, sr_local_label_range_cmd,
lower = strtoul(argv[idx_low]->arg, NULL, 10); lower = strtoul(argv[idx_low]->arg, NULL, 10);
upper = strtoul(argv[idx_up]->arg, NULL, 10); upper = strtoul(argv[idx_up]->arg, NULL, 10);
/* check correctness of SRLB */
if (!sr_range_is_valid(lower, upper, MIN_SRLB_SIZE)) {
vty_out(vty, "Invalid SRLB range\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Check if values have changed */ /* Check if values have changed */
if ((OspfSR.srlb.start == lower) if ((OspfSR.srlb.start == lower)
&& (OspfSR.srlb.end == upper)) && (OspfSR.srlb.end == upper))
@ -2294,9 +2360,10 @@ DEFUN_HIDDEN(sr_local_label_range, sr_local_label_range_cmd,
/* Validate SRLB against SRGB */ /* Validate SRLB against SRGB */
srgb_upper = OspfSR.srgb.start + OspfSR.srgb.size - 1; srgb_upper = OspfSR.srgb.start + OspfSR.srgb.size - 1;
if (!((upper < OspfSR.srgb.start) || (lower > srgb_upper))) {
if (ranges_overlap(OspfSR.srgb.start, srgb_upper, lower, upper)) {
vty_out(vty, vty_out(vty,
"New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n", "New SR Local Block (%u/%u) conflicts with Global Block (%u/%u)\n",
lower, upper, OspfSR.srgb.start, srgb_upper); lower, upper, OspfSR.srgb.start, srgb_upper);
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
@ -2319,10 +2386,10 @@ DEFUN_HIDDEN(no_sr_local_label_range, no_sr_local_label_range_cmd,
/* Validate SRLB against SRGB */ /* Validate SRLB against SRGB */
srgb_end = OspfSR.srgb.start + OspfSR.srgb.size - 1; srgb_end = OspfSR.srgb.start + OspfSR.srgb.size - 1;
if (!((DEFAULT_SRLB_END < OspfSR.srgb.start) if (ranges_overlap(OspfSR.srgb.start, srgb_end, DEFAULT_SRLB_LABEL,
|| (DEFAULT_SRLB_LABEL > srgb_end))) { DEFAULT_SRLB_END)) {
vty_out(vty, vty_out(vty,
"New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n", "New SR Local Block (%u/%u) conflicts with Global Block (%u/%u)\n",
DEFAULT_SRLB_LABEL, DEFAULT_SRLB_END, OspfSR.srgb.start, DEFAULT_SRLB_LABEL, DEFAULT_SRLB_END, OspfSR.srgb.start,
srgb_end); srgb_end);
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
@ -2412,11 +2479,15 @@ DEFUN (sr_prefix_sid,
"Upstream neighbor must replace prefix-sid with explicit null label\n") "Upstream neighbor must replace prefix-sid with explicit null label\n")
{ {
int idx = 0; int idx = 0;
struct prefix p; struct prefix p, pexist;
uint32_t index; uint32_t index;
struct listnode *node; struct listnode *node;
struct sr_prefix *srp, *new = NULL; struct sr_prefix *srp, *exist = NULL;
struct interface *ifp; struct interface *ifp;
bool no_php_flag = false;
bool exp_null = false;
bool index_in_use = false;
uint8_t desired_flags = 0;
if (!ospf_sr_enabled(vty)) if (!ospf_sr_enabled(vty))
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
@ -2437,53 +2508,67 @@ DEFUN (sr_prefix_sid,
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
/* Get options */
no_php_flag = argv_find(argv, argc, "no-php-flag", &idx);
exp_null = argv_find(argv, argc, "explicit-null", &idx);
desired_flags |= no_php_flag ? EXT_SUBTLV_PREFIX_SID_NPFLG : 0;
desired_flags |= exp_null ? EXT_SUBTLV_PREFIX_SID_NPFLG : 0;
desired_flags |= exp_null ? EXT_SUBTLV_PREFIX_SID_EFLG : 0;
/* Search for an existing Prefix-SID */ /* Search for an existing Prefix-SID */
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) { for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
if (prefix_same((struct prefix *)&srp->prefv4, &p))
exist = srp;
if (srp->sid == index) { if (srp->sid == index) {
if (prefix_same((struct prefix *)&srp->prefv4, &p)) { index_in_use = true;
new = srp; pexist = p;
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 */ /* done if prefix segment already there with same index and flags */
if (new == NULL) { if (exist && exist->sid == index && exist->flags == desired_flags)
new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix)); return CMD_SUCCESS;
IPV4_ADDR_COPY(&new->prefv4.prefix, &p.u.prefix4);
new->prefv4.prefixlen = p.prefixlen; /* deny if index is already in use by a distinct prefix */
new->prefv4.family = p.family; if (!exist && index_in_use) {
new->sid = index; vty_out(vty, "Index %u is already used by %pFX\n", index,
new->type = LOCAL_SID; &pexist);
return CMD_WARNING_CONFIG_FAILED;
} }
/* First, remove old NHLFE if installed */ /* First, remove old NHLFE if installed */
if (srp == new && CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG) if (exist && CHECK_FLAG(exist->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
&& !CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_EFLG)) && !CHECK_FLAG(exist->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
ospf_zebra_delete_prefix_sid(srp); ospf_zebra_delete_prefix_sid(exist);
/* Then, reset Flag & labels to handle flag update */
new->flags = 0;
new->label_in = 0;
new->nhlfe.label_out = 0;
/* Set NO PHP flag if present and compute NHLFE */ /* Create new Extended Prefix to SRDB if not found */
if (argv_find(argv, argc, "no-php-flag", &idx)) { if (exist == NULL) {
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG); srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
new->label_in = index2label(new->sid, OspfSR.self->srgb); IPV4_ADDR_COPY(&srp->prefv4.prefix, &p.u.prefix4);
new->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL; srp->prefv4.prefixlen = p.prefixlen;
srp->prefv4.family = p.family;
srp->sid = index;
srp->type = LOCAL_SID;
} else {
/* we work on the existing SR prefix */
srp = exist;
} }
/* Set EXPLICIT NULL flag is present */
if (argv_find(argv, argc, "explicit-null", &idx)) { /* Reset labels to handle flag update */
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG); srp->label_in = 0;
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG); srp->nhlfe.label_out = 0;
srp->sid = index;
srp->flags = desired_flags;
/* If NO PHP flag is present, compute NHLFE and set label */
if (no_php_flag) {
srp->label_in = index2label(srp->sid, OspfSR.self->srgb);
srp->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
} }
osr_debug("SR (%s): Add new index %u to Prefix %pFX", __func__, index, osr_debug("SR (%s): Add new index %u to Prefix %pFX", __func__, index,
(struct prefix *)&new->prefv4); (struct prefix *)&srp->prefv4);
/* Get Interface and check if it is a Loopback */ /* Get Interface and check if it is a Loopback */
ifp = if_lookup_prefix(&p, VRF_DEFAULT); ifp = if_lookup_prefix(&p, VRF_DEFAULT);
@ -2494,7 +2579,8 @@ DEFUN (sr_prefix_sid,
* ready. In this case, store the prefix SID for latter * ready. In this case, store the prefix SID for latter
* update of this Extended Prefix * update of this Extended Prefix
*/ */
listnode_add(OspfSR.self->ext_prefix, new); if (exist == NULL)
listnode_add(OspfSR.self->ext_prefix, srp);
zlog_info( zlog_info(
"Interface for prefix %pFX not found. Deferred LSA flooding", "Interface for prefix %pFX not found. Deferred LSA flooding",
&p); &p);
@ -2503,27 +2589,26 @@ DEFUN (sr_prefix_sid,
if (!if_is_loopback(ifp)) { if (!if_is_loopback(ifp)) {
vty_out(vty, "interface %s is not a Loopback\n", ifp->name); vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
XFREE(MTYPE_OSPF_SR_PARAMS, new); XFREE(MTYPE_OSPF_SR_PARAMS, srp);
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
new->nhlfe.ifindex = ifp->ifindex; srp->nhlfe.ifindex = ifp->ifindex;
/* Add this new SR Prefix if not already found */ /* Add SR Prefix if new */
if (srp != new) if (!exist)
listnode_add(OspfSR.self->ext_prefix, new); listnode_add(OspfSR.self->ext_prefix, srp);
/* Update Prefix SID if SR is UP */ /* Update Prefix SID if SR is UP */
if (OspfSR.status == SR_UP) { if (OspfSR.status == SR_UP) {
if (CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG) if (no_php_flag && !exp_null)
&& !CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG)) ospf_zebra_update_prefix_sid(srp);
ospf_zebra_update_prefix_sid(new);
} else } else
return CMD_SUCCESS; return CMD_SUCCESS;
/* Finally, update Extended Prefix LSA id SR is UP */ /* Finally, update Extended Prefix LSA id SR is UP */
new->instance = ospf_ext_schedule_prefix_index( srp->instance = ospf_ext_schedule_prefix_index(
ifp, new->sid, &new->prefv4, new->flags); ifp, srp->sid, &srp->prefv4, srp->flags);
if (new->instance == 0) { if (srp->instance == 0) {
vty_out(vty, "Unable to set index %u for prefix %pFX\n", vty_out(vty, "Unable to set index %u for prefix %pFX\n",
index, &p); index, &p);
return CMD_WARNING; return CMD_WARNING;

View File

@ -38,7 +38,9 @@
#define SET_LABEL(label) ((label << 8) & SET_LABEL_MASK) #define SET_LABEL(label) ((label << 8) & SET_LABEL_MASK)
#define GET_LABEL(label) ((label >> 8) & GET_LABEL_MASK) #define GET_LABEL(label) ((label >> 8) & GET_LABEL_MASK)
#define OSPF_SR_DEFAULT_METRIC 1 /* smallest configurable SRGB / SRLB sizes */
#define MIN_SRLB_SIZE 16
#define MIN_SRGB_SIZE 16
/* Segment Routing TLVs as per RFC 8665 */ /* Segment Routing TLVs as per RFC 8665 */
@ -221,7 +223,7 @@ struct sr_local_block {
enum sid_type { PREF_SID, LOCAL_SID, ADJ_SID, LAN_ADJ_SID }; enum sid_type { PREF_SID, LOCAL_SID, ADJ_SID, LAN_ADJ_SID };
/* Status of Segment Routing: Off (Disable), On (Enable), (Up) Started */ /* Status of Segment Routing: Off (Disable), On (Enable), (Up) Started */
enum sr_status { SR_OFF, SR_ON, SR_UP, SR_DOWN }; enum sr_status { SR_OFF, SR_ON, SR_UP };
/* Structure aggregating all OSPF Segment Routing information for the node */ /* Structure aggregating all OSPF Segment Routing information for the node */
struct ospf_sr_db { struct ospf_sr_db {