ospfd: Fix ospfd crash

- ospfd/ospf_opaque.c: Update issue #1652 by introducing a new
function 'free_opaque_info_owner()' to clean list of callback owner
and call this function in appropriate place where 'listdelete_and_null'
is not used.

 - ospfd/ospf_packet.c: In case of crash, ospfd is not been able to
flush LSA. In case of self Opaque LSA, when restarting, ospfd crash
during the resynchronisation process with its neighbor due to an
empty list of LSA to flood. Just add a control on the list count
in 'ospf_ls_upd_queue_send()' to escape the function and avoid the
problem.

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
Olivier Dugeon 2018-02-09 12:13:07 +01:00
parent 25236dd35d
commit 19274fe8c7
2 changed files with 39 additions and 1 deletions

View File

@ -75,6 +75,7 @@ static void ospf_opaque_funclist_init(void);
static void ospf_opaque_funclist_term(void);
static void free_opaque_info_per_type(void *val);
static void free_opaque_info_per_id(void *val);
static void free_opaque_info_owner(void *val);
static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa);
static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa);
@ -439,9 +440,11 @@ void ospf_delete_opaque_functab(u_char lsa_type, u_char opaque_type)
if (functab->opaque_type == opaque_type) {
/* Cleanup internal control information, if it
* still remains. */
if (functab->oipt != NULL)
if (functab->oipt != NULL) {
free_opaque_info_per_type(
functab->oipt);
free_opaque_info_owner(functab->oipt);
}
/* Dequeue listnode entry from the list. */
listnode_delete(funclist, functab);
@ -572,6 +575,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
top = ospf_lookup_by_vrf_id(new->vrf_id);
if (new->area != NULL && (top = new->area->ospf) == NULL) {
free_opaque_info_per_type((void *)oipt);
free_opaque_info_owner(oipt);
oipt = NULL;
goto out; /* This case may not exist. */
}
@ -583,6 +587,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
"register_opaque_info_per_type: Unexpected LSA-type(%u)",
new->data->type);
free_opaque_info_per_type((void *)oipt);
free_opaque_info_owner(oipt);
oipt = NULL;
goto out; /* This case may not exist. */
}
@ -600,6 +605,35 @@ out:
return oipt;
}
/* Remove "oipt" from its owner's self-originated LSA list. */
static void free_opaque_info_owner(void *val)
{
struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;
switch (oipt->lsa_type) {
case OSPF_OPAQUE_LINK_LSA: {
struct ospf_interface *oi =
(struct ospf_interface *)(oipt->owner);
listnode_delete(oi->opaque_lsa_self, oipt);
break;
}
case OSPF_OPAQUE_AREA_LSA: {
struct ospf_area *area = (struct ospf_area *)(oipt->owner);
listnode_delete(area->opaque_lsa_self, oipt);
break;
}
case OSPF_OPAQUE_AS_LSA: {
struct ospf *top = (struct ospf *)(oipt->owner);
listnode_delete(top->opaque_lsa_self, oipt);
break;
}
default:
zlog_warn("free_opaque_info_owner: Unexpected LSA-type(%u)",
oipt->lsa_type);
break; /* This case may not exist. */
}
}
static void free_opaque_info_per_type(void *val)
{
struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;

View File

@ -3897,6 +3897,10 @@ static void ospf_ls_upd_queue_send(struct ospf_interface *oi,
zlog_debug("listcount = %d, [%s]dst %s", listcount(update),
IF_NAME(oi), inet_ntoa(addr));
/* Check that we have really something to process */
if (listcount(update) == 0)
return;
op = ospf_ls_upd_packet_new(update, oi);
/* Prepare OSPF common header. */