Merge pull request #6416 from Orange-OpenSource/master

ospfd: Solve crash after removing and adding conf.
This commit is contained in:
Renato Westphal 2020-05-28 20:03:43 -03:00 committed by GitHub
commit ca4f4a3660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 94 deletions

View File

@ -80,7 +80,6 @@ static struct ospf_ext_lp OspfEXT;
*/
/* Extended Prefix Opaque LSA related callback functions */
static void ospf_ext_pref_ism_change(struct ospf_interface *oi, int old_status);
static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_ext_pref_lsa_originate(void *arg);
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa);
@ -89,7 +88,7 @@ static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
/* Extended Link Opaque LSA related callback functions */
static int ospf_ext_link_new_if(struct interface *ifp);
static int ospf_ext_link_del_if(struct interface *ifp);
static void ospf_ext_link_ism_change(struct ospf_interface *oi, int old_status);
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status);
static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status);
static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_ext_link_lsa_originate(void *arg);
@ -125,7 +124,7 @@ int ospf_ext_init(void)
OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_EXTENDED_LINK_LSA,
ospf_ext_link_new_if, /* new if */
ospf_ext_link_del_if, /* del if */
ospf_ext_link_ism_change, /* ism change */
ospf_ext_ism_change, /* ism change */
ospf_ext_link_nsm_change, /* nsm change */
NULL, /* Write router config. */
NULL, /* Write interface conf. */
@ -148,7 +147,7 @@ int ospf_ext_init(void)
OspfEXT.scope, OPAQUE_TYPE_EXTENDED_PREFIX_LSA,
NULL, /* new if handle by link */
NULL, /* del if handle by link */
ospf_ext_pref_ism_change, /* ism change */
NULL, /* ism change */
NULL, /* nsm change */
ospf_sr_config_write_router, /* Write router config. */
NULL, /* Write interface conf. */
@ -200,7 +199,15 @@ void ospf_ext_term(void)
*/
void ospf_ext_finish(void)
{
// list_delete_all_node(OspfEXT.iflist);
struct listnode *node;
struct ext_itf *exti;
/* Flush Router Info LSA */
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
OspfEXT.enabled = false;
}
@ -471,11 +478,15 @@ uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index,
set_prefix_sid(exti, SR_ALGORITHM_SPF, index, SID_INDEX, flags);
/* Try to Schedule LSA */
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_pref_lsa_schedule(exti, REFRESH_THIS_LSA);
else
ospf_ext_pref_lsa_schedule(exti, REORIGINATE_THIS_LSA);
// SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_pref_lsa_schedule(exti,
REFRESH_THIS_LSA);
else
ospf_ext_pref_lsa_schedule(
exti, REORIGINATE_THIS_LSA);
}
} else {
if (IS_DEBUG_OSPF_SR)
zlog_debug("EXT (%s): Remove prefix for interface %s",
@ -483,8 +494,7 @@ uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index,
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
ospf_ext_pref_lsa_schedule(exti, FLUSH_THIS_LSA);
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
exti->flags = EXT_LPFLG_LSA_INACTIVE;
}
}
@ -509,18 +519,26 @@ void ospf_ext_update_sr(bool enable)
if (enable) {
OspfEXT.enabled = true;
/* Refresh LSAs if already engaged or originate */
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
continue;
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_lsa_schedule(exti, REFRESH_THIS_LSA);
else
ospf_ext_lsa_schedule(exti,
REORIGINATE_THIS_LSA);
}
} else {
/* Start by Flushing engaged LSAs */
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti))
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
exti->flags = EXT_LPFLG_LSA_INACTIVE;
}
/* And then disable Extended Link/Prefix */
OspfEXT.enabled = false;
}
@ -580,39 +598,10 @@ static int ospf_ext_link_del_if(struct interface *ifp)
}
/*
* Determine if an Interface belongs to an Extended Link Adjacency or LAN Adj.
* type and allocate new instance value accordingly
* Determine if an Interface belongs to an Extended Link Adjacency or
* Extended Prefix SID type and allocate new instance value accordingly
*/
static void ospf_ext_link_ism_change(struct ospf_interface *oi, int old_status)
{
struct ext_itf *exti;
/* Get interface information for Segment Routing */
exti = lookup_ext_by_ifp(oi->ifp);
if (exti == NULL)
return;
/* Determine if interface is related to Adjacency or LAN Adj. SID */
if (oi->type != OSPF_IFTYPE_LOOPBACK) {
if (oi->state == ISM_DR)
exti->stype = LAN_ADJ_SID;
else
exti->stype = ADJ_SID;
exti->instance = get_ext_link_instance_value();
exti->type = OPAQUE_TYPE_EXTENDED_LINK_LSA;
zlog_debug("EXT (%s): Set %s SID to interface %s ", __func__,
exti->stype == ADJ_SID ? "Adj." : "LAN Adj.",
oi->ifp->name);
}
}
/*
* Determine if an Interface belongs to an Extended Prefix and
* allocate new instance value accordingly
*/
static void ospf_ext_pref_ism_change(struct ospf_interface *oi, int old_status)
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status)
{
struct ext_itf *exti;
@ -625,18 +614,45 @@ static void ospf_ext_pref_ism_change(struct ospf_interface *oi, int old_status)
return;
}
/* Determine if interface is related to a Node SID */
/* Reset Extended information if ospf interface goes Down */
if (oi->state == ISM_Down) {
exti->area = NULL;
exti->flags = EXT_LPFLG_LSA_INACTIVE;
return;
}
/* Determine if interface is related to a Prefix or an Adjacency SID */
if (oi->type == OSPF_IFTYPE_LOOPBACK) {
exti->stype = PREF_SID;
exti->instance = get_ext_pref_instance_value();
exti->type = OPAQUE_TYPE_EXTENDED_PREFIX_LSA;
exti->flags = EXT_LPFLG_LSA_ACTIVE;
exti->instance = get_ext_pref_instance_value();
exti->area = oi->area;
zlog_debug("EXT (%s): Set Node SID to interface %s ", __func__,
oi->ifp->name);
zlog_debug("EXT (%s): Set Prefix SID to interface %s ",
__func__, oi->ifp->name);
/* Complete SRDB if the interface belongs to a Prefix */
if (OspfEXT.enabled)
ospf_sr_update_prefix(oi->ifp, oi->address);
} else {
/* Determine if interface is related to Adj. or LAN Adj. SID */
if (oi->state == ISM_DR)
exti->stype = LAN_ADJ_SID;
else
exti->stype = ADJ_SID;
exti->type = OPAQUE_TYPE_EXTENDED_LINK_LSA;
exti->instance = get_ext_link_instance_value();
exti->area = oi->area;
/*
* Note: Adjacency SID information are completed when ospf
* adjacency become up see ospf_ext_link_nsm_change()
*/
zlog_debug("EXT (%s): Set %sAdjacency SID for interface %s ",
__func__, exti->stype == ADJ_SID ? "" : "LAN-",
oi->ifp->name);
}
}
@ -663,17 +679,6 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
return;
}
if (oi->area == NULL || oi->area->ospf == NULL) {
flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
"EXT (%s): Cannot refer to OSPF from OI(%s)",
__func__, IF_NAME(oi));
return;
}
/* Keep Area information in combination with SR info. */
exti->area = oi->area;
OspfEXT.area = oi->area;
/* Process only Adjacency/LAN SID */
if (exti->stype == PREF_SID)
return;
@ -731,19 +736,17 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
break;
default:
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
ospf_ext_link_lsa_schedule(exti, FLUSH_THIS_LSA);
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
}
exti->flags = EXT_LPFLG_LSA_INACTIVE;
return;
}
if (IS_DEBUG_OSPF_SR)
zlog_debug("EXT (%s): Complete %s SID to interface %s ",
__func__,
exti->stype == ADJ_SID ? "Adj." : "LAN Adj.",
oi->ifp->name);
zlog_debug(
"EXT (%s): Complete %sAdjacency SID for interface %s ",
__func__, exti->stype == ADJ_SID ? "" : "LAN-",
oi->ifp->name);
/* flood this links params if everything is ok */
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
@ -1244,6 +1247,10 @@ static int ospf_ext_link_lsa_originate(void *arg)
|| (!IPV4_ADDR_SAME(&exti->area->area_id, &area->area_id)))
continue;
/* Skip Extended Link which are not Active */
if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
continue;
/* Check if LSA not already engaged */
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
if (CHECK_FLAG(exti->flags,
@ -1467,19 +1474,23 @@ static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
opcode == FLUSH_THIS_LSA ? "Flush" : "",
exti->ifp ? exti->ifp->name : "-");
/* Set LSA header information */
/* Verify Area */
if (exti->area == NULL) {
flog_warn(
EC_OSPF_EXT_LSA_UNEXPECTED,
"EXT (%s): Flooding is Area scope but area is not yet set",
__func__);
if (OspfEXT.area == NULL) {
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
OspfEXT.area = ospf_area_lookup_by_area_id(
top, OspfEXT.area_id);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"EXT (%s): Area is not yet set. Try to use Backbone Area",
__func__);
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
struct in_addr backbone = {.s_addr = INADDR_ANY};
exti->area = ospf_area_lookup_by_area_id(top, backbone);
if (exti->area == NULL) {
flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
"EXT (%s): Unable to set Area", __func__);
return;
}
exti->area = OspfEXT.area;
}
/* Set LSA header information */
lsa.area = exti->area;
lsa.data = &lsah;
lsah.type = OSPF_OPAQUE_AREA_LSA;
@ -1528,19 +1539,23 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
opcode == FLUSH_THIS_LSA ? "Flush" : "",
exti->ifp ? exti->ifp->name : "-");
/* Set LSA header information */
/* Verify Area */
if (exti->area == NULL) {
flog_warn(
EC_OSPF_EXT_LSA_UNEXPECTED,
"EXT (%s): Flooding is Area scope but area is not yet set",
__func__);
if (OspfEXT.area == NULL) {
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
OspfEXT.area = ospf_area_lookup_by_area_id(
top, OspfEXT.area_id);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"EXT (%s): Area is not yet set. Try to use Backbone Area",
__func__);
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
struct in_addr backbone = {.s_addr = INADDR_ANY};
exti->area = ospf_area_lookup_by_area_id(top, backbone);
if (exti->area == NULL) {
flog_warn(EC_OSPF_EXT_LSA_UNEXPECTED,
"EXT (%s): Unable to set Area", __func__);
return;
}
exti->area = OspfEXT.area;
}
/* Set LSA header information */
lsa.area = exti->area;
lsa.data = &lsah;
lsah.type = OSPF_OPAQUE_AREA_LSA;
@ -1557,7 +1572,6 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
ospf_opaque_lsa_refresh_schedule(&lsa);
break;
case FLUSH_THIS_LSA:
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(&lsa);
break;
}

View File

@ -151,10 +151,6 @@ struct ospf_ext_lp {
*/
uint8_t scope;
/* area pointer if flooding is Type 10 Null if flooding is AS scope */
struct ospf_area *area;
struct in_addr area_id;
/* List of interface with Segment Routing enable */
struct list *iflist;
};

View File

@ -178,6 +178,14 @@ void ospf_router_info_term(void)
void ospf_router_info_finish(void)
{
struct listnode *node, *nnode;
struct ospf_ri_area_info *ai;
/* Flush Router Info 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, FLUSH_THIS_LSA);
list_delete_all_node(OspfRI.pce_info.pce_domain);
list_delete_all_node(OspfRI.pce_info.pce_neighbor);
@ -510,6 +518,8 @@ static void initialize_params(struct ospf_router_info *ori)
/* 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) {
if (!list_isempty(OspfRI.area_info))
list_delete_all_node(OspfRI.area_info);
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));

View File

@ -1,4 +1,6 @@
!
debug ospf sr
!
interface lo
ip ospf area 0.0.0.0
!