#include "ospfd/ospf_ri.h"
#include "ospfd/ospf_errors.h"
-/* Store Router Information PCE TLV and SubTLV in network byte order. */
-struct ospf_pce_info {
- bool enabled;
- struct ri_tlv_pce pce_header;
- struct ri_pce_subtlv_address pce_address;
- struct ri_pce_subtlv_path_scope pce_scope;
- struct list *pce_domain;
- struct list *pce_neighbor;
- struct ri_pce_subtlv_cap_flag pce_cap_flag;
-};
-
-/*
- * Store Router Information Segment Routing TLV and SubTLV
- * in network byte order
- */
-struct ospf_ri_sr_info {
- bool enabled;
- /* Algorithms supported by the node */
- struct ri_sr_tlv_sr_algorithm algo;
- /*
- * Segment Routing Global Block i.e. label range
- * Only one range supported in this code
- */
- struct ri_sr_tlv_sid_label_range range;
- /* Maximum SID Depth supported by the node */
- struct ri_sr_tlv_node_msd msd;
-};
-
-/* Following structure are internal use only. */
-struct ospf_router_info {
- bool enabled;
-
- uint8_t registered;
- uint8_t scope;
-
-/* Flags to manage this router information. */
-#define RIFLG_LSA_ENGAGED 0x1
-#define RIFLG_LSA_FORCED_REFRESH 0x2
- uint32_t flags;
-
- /* area pointer if flooding is Type 10 Null if flooding is AS scope */
- struct ospf_area *area;
- struct in_addr area_id;
-
- /* Store Router Information Capabilities LSA */
- struct ri_tlv_router_cap router_cap;
-
- /* Store PCE capability LSA */
- struct ospf_pce_info pce_info;
-
- /* Store SR capability LSA */
- struct ospf_ri_sr_info sr_info;
-};
-
/*
* Global variable to manage Opaque-LSA/Router Information on this node.
* Note that all parameter values are stored in network byte order.
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_status);
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_status);
static void ospf_router_info_config_write_router(struct vty *vty);
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_router_info_lsa_originate(void *arg);
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode);
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode);
static void ospf_router_info_register_vty(void);
static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
+static void del_area_info(void *val);
static void del_pce_info(void *val);
int ospf_router_info_init(void)
{
- zlog_info("RI -> Initialize Router Information");
+ zlog_info("RI (%s): Initialize Router Information", __func__);
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
OspfRI.enabled = false;
OspfRI.registered = 0;
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
- OspfRI.area_id.s_addr = 0;
- OspfRI.flags = 0;
+ OspfRI.as_flags = RIFLG_LSA_INACTIVE;
+ OspfRI.area_info = list_new();
+ OspfRI.area_info->del = del_area_info;
/* Initialize pce domain and neighbor list */
OspfRI.pce_info.enabled = false;
if (OspfRI.registered)
return rc;
- zlog_info("RI -> Register Router Information with scope %s(%d)",
+ zlog_info("RI (%s): Register Router Information with scope %s(%d)",
+ __func__,
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
rc = ospf_register_opaque_functab(
scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
NULL, /* new interface */
NULL, /* del interface */
- ospf_router_info_ism_change, ospf_router_info_nsm_change,
+ ospf_router_info_ism_change,
+ NULL, /* NSM change */
ospf_router_info_config_write_router,
NULL, /* Config. write interface */
NULL, /* Config. write debug */
if (rc != 0) {
flog_warn(
EC_OSPF_OPAQUE_REGISTRATION,
- "ospf_router_info_init: Failed to register functions");
+ "RI (%s): Failed to register functions", __func__);
return rc;
}
return rc;
}
-static int ospf_router_info_unregister()
+static int ospf_router_info_unregister(void)
{
if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
OspfRI.enabled = false;
}
+static void del_area_info(void *val)
+{
+ XFREE(MTYPE_OSPF_ROUTER_INFO, val);
+}
+
static void del_pce_info(void *val)
{
XFREE(MTYPE_OSPF_PCE_PARAMS, val);
- return;
}
/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
- flooding_scope.area_id.s_addr = 0;
+ flooding_scope.areas = NULL;
return flooding_scope;
}
flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
- flooding_scope.area_id.s_addr = OspfRI.area_id.s_addr;
+ flooding_scope.areas = OspfRI.area_info;
return flooding_scope;
}
+static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
+ if (ai->area == area)
+ return ai;
+
+ return NULL;
+}
+
/*------------------------------------------------------------------------*
* Followings are control functions for ROUTER INFORMATION parameters
*management.
{
uint32_t cap = 0;
struct ospf *top;
+ struct listnode *node, *nnode;
+ struct ospf_area *area;
+ struct ospf_ri_area_info *new;
/*
* Initialize default Router Information Capabilities.
/* If Area address is not null and exist, retrieve corresponding
* structure */
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- zlog_info("RI-> Initialize Router Info for %s scope within area %s",
- OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
- inet_ntoa(OspfRI.area_id));
+ zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
- /* Try to get the Area context at this step. Do it latter if not
- * available */
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ /* Try to get available Area's context from ospf at this step.
+ * Do it latter if not available */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
+ zlog_debug("RI (%s): Add area %s to Router Information",
+ __func__, inet_ntoa(area->area_id));
+ new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
+ sizeof(struct ospf_ri_area_info));
+ new->area = area;
+ new->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, new);
+ }
+ }
/*
* Initialize default PCE Information values
*/
void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ /* First, check if Router Information is registered or not */
+ if (!OspfRI.registered)
+ ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
+
+ /* Verify that scope is AREA */
+ if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
+ zlog_err(
+ "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
+ __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
+ return;
+ }
- /* First activate and initialize Router Information is necessary */
+ /* Then, activate and initialize Router Information if necessary */
if (!OspfRI.enabled) {
OspfRI.enabled = true;
initialize_params(&OspfRI);
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug("RI-> %s Routing Information for Segment Routing",
- enable ? "Enable" : "Disable");
+ zlog_debug("RI (%s): %s Routing Information for Segment Routing",
+ __func__, enable ? "Enable" : "Disable");
/* Unset or Set SR parameters */
if (!enable) {
}
/* Refresh if already engaged or originate RI LSA */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- else
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ else
+ ospf_router_info_lsa_schedule(ai,
+ REORIGINATE_THIS_LSA);
+
+ }
}
/*------------------------------------------------------------------------*
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_state)
{
- /* So far, nothing to do here. */
- return;
-}
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_state)
-{
- /* So far, nothing to do here. */
+ struct ospf_ri_area_info *ai;
+
+ /* Collect area information */
+ ai = lookup_by_area(oi->area);
+
+ /* Check if area is not yet registered */
+ if (ai != NULL)
+ return;
+
+ /* Add this new area to the list */
+ ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
+ ai->area = oi->area;
+ ai->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, ai);
+
return;
}
}
/* Create new opaque-LSA. */
-static struct ospf_lsa *ospf_router_info_lsa_new()
+static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
{
struct ospf *top;
struct stream *s;
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new_and_data(length);
- new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
- scope, fulfill otherwise */
+ new->area = area;
if (new->area && new->area->ospf)
new->vrf_id = new->area->ospf->vrf_id;
return new;
}
-static int ospf_router_info_lsa_originate1(void *arg)
+static int ospf_router_info_lsa_originate_as(void *arg)
{
struct ospf_lsa *new;
struct ospf *top;
- struct ospf_area *area;
int rc = -1;
vrf_id_t vrf_id = VRF_DEFAULT;
- /* First check if the area is known if flooding scope is Area */
+ /* Sanity Check */
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
- area = (struct ospf_area *)arg;
- if (area->area_id.s_addr != OspfRI.area_id.s_addr) {
- zlog_debug(
- "RI -> This is not the Router Information Area. Stop processing");
- return rc;
- }
- OspfRI.area = area;
- if (area->ospf)
- vrf_id = area->ospf->vrf_id;
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AREA instead of AS ?",
+ __func__);
+ return rc;
}
/* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->vrf_id = vrf_id;
+ new = ospf_router_info_lsa_new(NULL);
+ new->vrf_id = VRF_DEFAULT;
+ top = (struct ospf *)arg;
- /* Get ospf info */
- top = ospf_lookup_by_vrf_id(vrf_id);
+ /* Check ospf info */
if (top == NULL) {
- zlog_debug("%s: ospf instance not found for vrf id %u",
- __PRETTY_FUNCTION__, vrf_id);
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
flog_warn(
EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
+
+ /* Update new LSA origination count. */
+ top->lsa_originate_count++;
+
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_as(top, NULL /*nbr */, new);
+
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
+ zlog_debug(
+ "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
+ new->data->type, inet_ntoa(new->data->id));
+ ospf_lsa_header_dump(new->data);
+ }
+
+ rc = 0;
+ return rc;
+}
+
+static int ospf_router_info_lsa_originate_area(void *arg)
+{
+ struct ospf_lsa *new;
+ struct ospf *top;
+ struct ospf_ri_area_info *ai = NULL;
+ int rc = -1;
+ vrf_id_t vrf_id = VRF_DEFAULT;
+
+ /* Sanity Check */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AS instead of AREA ?",
+ __func__);
+ return rc;
+ }
+
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
+ zlog_debug(
+ "RI (%s): There is no context for this Router Information. Stop processing",
+ __func__);
+ return rc;
+ }
+ if (ai->area->ospf) {
+ vrf_id = ai->area->ospf->vrf_id;
+ top = ai->area->ospf;
+ } else {
+ top = ospf_lookup_by_vrf_id(vrf_id);
+ }
+ new = ospf_router_info_lsa_new(ai->area);
+ new->vrf_id = vrf_id;
+
+ /* Check ospf info */
+ if (top == NULL) {
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
- /* Now this Router Info parameter entry has associated LSA. */
- SET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ /* Install this LSA into LSDB. */
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
/* Update new LSA origination count. */
top->lsa_originate_count++;
- /* Flood new LSA through AS. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
- ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug(
static int ospf_router_info_lsa_originate(void *arg)
{
+ struct ospf_ri_area_info *ai;
int rc = -1;
if (!OspfRI.enabled) {
- zlog_info(
- "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
rc = 0; /* This is not an error case. */
return rc;
}
/* Check if Router Information LSA is already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH);
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(OspfRI.as_flags,
+ RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
}
} else {
- if (!is_mandated_params_set(OspfRI))
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
-
- /* Ok, let's try to originate an LSA */
- if (ospf_router_info_lsa_originate1(arg) != 0)
+ "RI (%s): Missing area information", __func__);
return rc;
+ }
+ if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
+ }
}
- rc = 0;
+ /* Router Information is not yet Engaged, check parameters */
+ if (!is_mandated_params_set(OspfRI))
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): lacks mandated ROUTER INFORMATION parameters",
+ __func__);
+
+ /* Ok, let's try to originate an LSA */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ rc = ospf_router_info_lsa_originate_as(arg);
+ else
+ rc = ospf_router_info_lsa_originate_area(arg);
+
return rc;
}
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
{
+ struct ospf_ri_area_info *ai = NULL;
struct ospf_lsa *new = NULL;
struct ospf *top;
* status change.
* It seems a slip among routers in the routing domain.
*/
- zlog_info(
- "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
lsa->data->ls_age =
htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
}
if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
+ "RI (%s): Unsupported Router Information ID",
+ __func__);
return NULL;
}
- /* If the lsa's age reached to MaxAge, start flushing procedure. */
- if (IS_LSA_MAXAGE(lsa)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
- ospf_opaque_lsa_flush_schedule(lsa);
- return NULL;
- }
-
- /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->data->ls_seqnum = lsa_seqnum_increment(lsa);
- new->vrf_id = lsa->vrf_id;
-
- /* Install this LSA into LSDB. */
- /* Given "lsa" will be freed in the next function. */
- top = ospf_lookup_by_vrf_id(lsa->vrf_id);
- if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
- flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
- ospf_lsa_unlock(&new);
- return new;
- }
-
- /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ /* Process LSA depending of the flooding scope */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ /* Get context AREA context */
+ ai = lookup_by_area(lsa->area);
+ if (ai == NULL) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): No associated Area", __func__);
+ return NULL;
+ }
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(ai->area);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AREA */
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
+
+ } else { /* AS Flooding scope */
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(NULL);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AS */
ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ }
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
return new;
}
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode)
{
struct ospf_lsa lsa;
struct lsa_header lsah;
memset(&lsa, 0, sizeof(lsa));
memset(&lsah, 0, sizeof(lsah));
- zlog_debug("RI-> LSA schedule %s%s%s",
+ zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "");
- /* Check LSA flags state coherence */
- if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode != REORIGINATE_THIS_LSA))
- return;
+ /* Check LSA flags state coherence and collect area information */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ if ((ai == NULL) || (ai->area == NULL)) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): Router Info is Area scope flooding but area is not set",
+ __func__);
+ return;
+ }
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode == REORIGINATE_THIS_LSA))
- opcode = REFRESH_THIS_LSA;
+ if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
- top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ lsa.area = ai->area;
+ top = ai->area->ospf;
+ } else {
+ if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
+
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+ lsa.area = NULL;
}
- lsa.area = OspfRI.area;
+
lsa.data = &lsah;
lsah.type = OspfRI.scope;
case REORIGINATE_THIS_LSA:
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
ospf_opaque_lsa_reoriginate_schedule(
- (void *)OspfRI.area, OSPF_OPAQUE_AREA_LSA,
+ (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
else
ospf_opaque_lsa_reoriginate_schedule(
ospf_opaque_lsa_refresh_schedule(&lsa);
break;
case FLUSH_THIS_LSA:
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ else
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(&lsa);
break;
}
/* Sanity Check */
if (lsa == NULL) {
- flog_warn(EC_OSPF_LSA, "OSPF-RI (%s): Abort! LSA is NULL",
+ flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
__func__);
return -1;
}
}
else {
- zlog_debug(" Segment Routing Algorithm TLV:\n");
+ zlog_debug(" Segment Routing Algorithm TLV:");
for (i = 0; i < ntohs(algo->header.length); i++)
switch (algo->value[i]) {
case 0:
- zlog_debug(" Algorithm %d: SPF\n", i);
+ zlog_debug(" Algorithm %d: SPF", i);
break;
case 1:
- zlog_debug(" Algorithm %d: Strict SPF\n", i);
+ zlog_debug(" Algorithm %d: Strict SPF", i);
break;
default:
zlog_debug(
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
vty_out(vty, " router-info as\n");
else
- vty_out(vty, " router-info area %s\n",
- inet_ntoa(OspfRI.area_id));
+ vty_out(vty, " router-info area\n");
if (OspfRI.pce_info.enabled) {
/*------------------------------------------------------------------------*
* Followings are vty command functions.
*------------------------------------------------------------------------*/
+/* Simple wrapper schedule RI LSA action in function of the scope */
+static void ospf_router_info_schedule(enum lsa_opcode opcode)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ else if (opcode == REORIGINATE_THIS_LSA)
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ } else {
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, opcode);
+ }
+ }
+}
DEFUN (router_info,
router_info_area_cmd,
- "router-info <as|area A.B.C.D>",
+ "router-info <as|area [A.B.C.D]>",
OSPF_RI_STR
"Enable the Router Information functionality with AS flooding scope\n"
"Enable the Router Information functionality with Area flooding scope\n"
- "OSPF area ID in IP format\n")
+ "OSPF area ID in IP format (deprecated)\n")
{
- int idx_ipv4 = 2;
- char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
-
+ int idx_mode = 1;
uint8_t scope;
if (OspfRI.enabled)
return CMD_SUCCESS;
/* Check and get Area value if present */
- if (area) {
- if (!inet_aton(area, &OspfRI.area_id)) {
- vty_out(vty, "%% specified Area ID %s is invalid\n",
- area);
- return CMD_WARNING_CONFIG_FAILED;
- }
- scope = OSPF_OPAQUE_AREA_LSA;
- } else {
- OspfRI.area_id.s_addr = 0;
+ if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
scope = OSPF_OPAQUE_AS_LSA;
- }
+ else
+ scope = OSPF_OPAQUE_AREA_LSA;
/* First start to register Router Information callbacks */
- if ((ospf_router_info_register(scope)) != 0) {
+ if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
vty_out(vty,
"%% Unable to register Router Information callbacks.");
flog_err(
EC_OSPF_INIT_FAIL,
- "Unable to register Router Information callbacks. Abort!");
+ "RI (%s): Unable to register Router Information callbacks. Abort!",
+ __func__);
return CMD_WARNING_CONFIG_FAILED;
}
initialize_params(&OspfRI);
- /* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- zlog_debug("RI-> Refresh LSA following configuration");
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- } else {
- zlog_debug("RI-> Initial origination following configuration");
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
- }
+ /* Originate or Refresh RI LSA if already engaged */
+ ospf_router_info_schedule(REORIGINATE_THIS_LSA);
return CMD_SUCCESS;
}
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("RI-> Router Information: ON -> OFF");
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(FLUSH_THIS_LSA);
+ ospf_router_info_schedule(FLUSH_THIS_LSA);
OspfRI.enabled = false;
set_pce_address(value, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
set_pce_path_scope(scope, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
set_pce_cap_flag(cap, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
unset_param(&OspfRI.pce_info.pce_cap_flag);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}