summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_ri.c
diff options
context:
space:
mode:
authorOlivier Dugeon <olivier.dugeon@orange.com>2018-10-26 19:12:41 +0200
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-11-09 10:09:47 +0100
commitddd73a968dc61766b6a44442c0bccd7ff0a643a8 (patch)
tree228365f0477115012e2ae36bf37b2181558c57ae /ospfd/ospf_ri.c
parentMerge pull request #3202 from donaldsharp/evpn_dump (diff)
downloadfrr-ddd73a968dc61766b6a44442c0bccd7ff0a643a8.tar.xz
frr-ddd73a968dc61766b6a44442c0bccd7ff0a643a8.zip
OSPF: Add support to multi-area to Router Info.
Router Information needs to specify the area ID when flooding scope is set to AREA. However, this authorize only one AREA. Thus, Area Border Router (ABR) are unable to flood Router Information Opaque LSA in all areas they are belongs to. The path implies that the area ID is no more necessary for the command 'router-info area'. It remains suported for compatibility, but mark as deprecated. Documentation has been updated accordingly. Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Diffstat (limited to 'ospfd/ospf_ri.c')
-rw-r--r--ospfd/ospf_ri.c576
1 files changed, 351 insertions, 225 deletions
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index bef16761f..72f6dbe08 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -59,60 +59,6 @@
#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.
@@ -126,28 +72,29 @@ static struct ospf_router_info OspfRI;
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;
@@ -171,13 +118,15 @@ static int ospf_router_info_register(uint8_t scope)
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 */
@@ -188,7 +137,7 @@ static int ospf_router_info_register(uint8_t scope)
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;
}
@@ -235,10 +184,14 @@ void ospf_router_info_finish(void)
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 */
@@ -248,14 +201,26 @@ struct scope_info ospf_router_info_get_flooding_scope(void)
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.
@@ -525,6 +490,9 @@ static void initialize_params(struct ospf_router_info *ori)
{
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.
@@ -536,14 +504,22 @@ static void initialize_params(struct ospf_router_info *ori)
/* 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
@@ -597,16 +573,31 @@ static int is_mandated_params_set(struct ospf_router_info ori)
*/
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) {
@@ -626,10 +617,14 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
}
/* 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);
+
+ }
}
/*------------------------------------------------------------------------*
@@ -638,14 +633,22 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
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;
}
@@ -723,7 +726,7 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
}
/* 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;
@@ -768,8 +771,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
/* 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;
@@ -783,36 +785,31 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
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;
}
@@ -821,22 +818,86 @@ static int ospf_router_info_lsa_originate1(void *arg)
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(
@@ -852,38 +913,62 @@ static int ospf_router_info_lsa_originate1(void *arg)
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;
@@ -893,8 +978,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
* 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. */
}
@@ -903,37 +988,66 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
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)) {
@@ -946,7 +1060,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
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;
@@ -956,28 +1071,44 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
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;
@@ -989,7 +1120,7 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
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(
@@ -1000,7 +1131,10 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
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;
}
@@ -1014,7 +1148,7 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
/* 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;
}
@@ -1356,8 +1490,7 @@ static void ospf_router_info_config_write_router(struct vty *vty)
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) {
@@ -1405,43 +1538,53 @@ static void ospf_router_info_config_write_router(struct vty *vty)
/*------------------------------------------------------------------------*
* 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;
}
@@ -1463,14 +1606,8 @@ DEFUN (router_info,
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;
}
@@ -1488,8 +1625,7 @@ DEFUN (no_router_info,
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;
@@ -1533,8 +1669,7 @@ DEFUN (pce_address,
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;
@@ -1552,8 +1687,7 @@ DEFUN (no_pce_address,
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;
}
@@ -1583,8 +1717,7 @@ DEFUN (pce_path_scope,
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;
@@ -1602,8 +1735,7 @@ DEFUN (no_pce_path_scope,
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;
}
@@ -1641,8 +1773,7 @@ DEFUN (pce_domain,
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;
}
@@ -1671,8 +1802,7 @@ DEFUN (no_pce_domain,
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;
}
@@ -1711,8 +1841,7 @@ DEFUN (pce_neigbhor,
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;
}
@@ -1741,8 +1870,7 @@ DEFUN (no_pce_neighbor,
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;
}
@@ -1773,8 +1901,7 @@ DEFUN (pce_cap_flag,
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;
@@ -1791,8 +1918,7 @@ DEFUN (no_pce_cap_flag,
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;
}