mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 11:18:52 +00:00
Merge pull request #9683 from volta-networks/sr-minor-fixes
ospfd, isisd: minor SR fixes
This commit is contained in:
commit
587cf8f170
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
277
ospfd/ospf_sr.c
277
ospfd/ospf_sr.c
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user