mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 11:01:48 +00:00
ospfd: api: fix recovery of LSA after restart of api client
Prior to this fix, restarting the client just failed b/c the code tried to "refresh" the existing LSA being added, except that code checked for meta-data to exist, which was deleted when the client disconnected previously (or had never connected and the LSA state was picked up from the network). Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
d86760acad
commit
5349121b4c
@ -1627,9 +1627,9 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
|
||||
/* Determine if LSA is new or an update for an existing one. */
|
||||
old = ospf_lsdb_lookup(lsdb, new);
|
||||
|
||||
if (!old) {
|
||||
if (!old || !ospf_opaque_is_owned(old)) {
|
||||
/* New LSA install in LSDB. */
|
||||
rc = ospf_apiserver_originate1(new);
|
||||
rc = ospf_apiserver_originate1(new, old);
|
||||
} else {
|
||||
/*
|
||||
* Keep the new LSA instance in the "waiting place" until the
|
||||
@ -1696,17 +1696,33 @@ void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa)
|
||||
}
|
||||
}
|
||||
|
||||
int ospf_apiserver_originate1(struct ospf_lsa *lsa)
|
||||
int ospf_apiserver_originate1(struct ospf_lsa *lsa, struct ospf_lsa *old)
|
||||
{
|
||||
struct ospf *ospf;
|
||||
|
||||
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
|
||||
assert(ospf);
|
||||
|
||||
if (old) {
|
||||
/*
|
||||
* An old LSA exists that we didn't originate it in this
|
||||
* session. Dump it, but increment past it's seqnum.
|
||||
*/
|
||||
assert(!ospf_opaque_is_owned(old));
|
||||
if (IS_LSA_MAX_SEQ(old)) {
|
||||
flog_warn(
|
||||
EC_OSPF_LSA_INSTALL_FAILURE,
|
||||
"ospf_apiserver_originate1: old LSA at maxseq");
|
||||
return -1;
|
||||
}
|
||||
lsa->data->ls_seqnum = lsa_seqnum_increment(old);
|
||||
ospf_discard_from_db(ospf, old->lsdb, old);
|
||||
}
|
||||
|
||||
/* Install this LSA into LSDB. */
|
||||
if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
|
||||
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
|
||||
"ospf_apiserver_originate1: ospf_lsa_install failed");
|
||||
"%s: ospf_lsa_install failed", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,8 @@ extern struct ospf_interface *
|
||||
ospf_apiserver_if_lookup_by_addr(struct in_addr address);
|
||||
extern struct ospf_interface *
|
||||
ospf_apiserver_if_lookup_by_ifp(struct interface *ifp);
|
||||
extern int ospf_apiserver_originate1(struct ospf_lsa *lsa);
|
||||
extern int ospf_apiserver_originate1(struct ospf_lsa *lsa,
|
||||
struct ospf_lsa *old);
|
||||
extern void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa);
|
||||
|
||||
|
||||
|
@ -74,9 +74,8 @@ int ospf_apiserver_enable;
|
||||
static void ospf_opaque_register_vty(void);
|
||||
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_type_del(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);
|
||||
|
||||
@ -141,7 +140,7 @@ int ospf_opaque_type9_lsa_init(struct ospf_interface *oi)
|
||||
list_delete(&oi->opaque_lsa_self);
|
||||
|
||||
oi->opaque_lsa_self = list_new();
|
||||
oi->opaque_lsa_self->del = free_opaque_info_per_type;
|
||||
oi->opaque_lsa_self->del = free_opaque_info_per_type_del;
|
||||
oi->t_opaque_lsa_self = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -161,7 +160,7 @@ int ospf_opaque_type10_lsa_init(struct ospf_area *area)
|
||||
list_delete(&area->opaque_lsa_self);
|
||||
|
||||
area->opaque_lsa_self = list_new();
|
||||
area->opaque_lsa_self->del = free_opaque_info_per_type;
|
||||
area->opaque_lsa_self->del = free_opaque_info_per_type_del;
|
||||
area->t_opaque_lsa_self = NULL;
|
||||
|
||||
#ifdef MONITOR_LSDB_CHANGE
|
||||
@ -189,7 +188,7 @@ int ospf_opaque_type11_lsa_init(struct ospf *top)
|
||||
list_delete(&top->opaque_lsa_self);
|
||||
|
||||
top->opaque_lsa_self = list_new();
|
||||
top->opaque_lsa_self->del = free_opaque_info_per_type;
|
||||
top->opaque_lsa_self->del = free_opaque_info_per_type_del;
|
||||
top->t_opaque_lsa_self = NULL;
|
||||
|
||||
#ifdef MONITOR_LSDB_CHANGE
|
||||
@ -263,6 +262,9 @@ static const char *ospf_opaque_type_name(uint8_t opaque_type)
|
||||
|
||||
struct opaque_info_per_type; /* Forward declaration. */
|
||||
|
||||
static void free_opaque_info_per_type(struct opaque_info_per_type *oipt,
|
||||
bool cleanup_owner);
|
||||
|
||||
struct ospf_opaque_functab {
|
||||
uint8_t opaque_type;
|
||||
struct opaque_info_per_type *oipt;
|
||||
@ -433,12 +435,9 @@ void ospf_delete_opaque_functab(uint8_t lsa_type, uint8_t opaque_type)
|
||||
if (functab->opaque_type == opaque_type) {
|
||||
/* Cleanup internal control information, if it
|
||||
* still remains. */
|
||||
if (functab->oipt != NULL) {
|
||||
free_opaque_info_owner(functab->oipt);
|
||||
free_opaque_info_per_type(
|
||||
functab->oipt);
|
||||
}
|
||||
|
||||
if (functab->oipt != NULL)
|
||||
free_opaque_info_per_type(functab->oipt,
|
||||
true);
|
||||
/* Dequeue listnode entry from the list. */
|
||||
listnode_delete(funclist, functab);
|
||||
|
||||
@ -558,8 +557,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
|
||||
case OSPF_OPAQUE_AS_LSA:
|
||||
top = ospf_lookup_by_vrf_id(new->vrf_id);
|
||||
if (new->area != NULL && (top = new->area->ospf) == NULL) {
|
||||
free_opaque_info_owner(oipt);
|
||||
free_opaque_info_per_type(oipt);
|
||||
free_opaque_info_per_type(oipt, true);
|
||||
oipt = NULL;
|
||||
goto out; /* This case may not exist. */
|
||||
}
|
||||
@ -571,8 +569,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
|
||||
EC_OSPF_LSA_UNEXPECTED,
|
||||
"register_opaque_info_per_type: Unexpected LSA-type(%u)",
|
||||
new->data->type);
|
||||
free_opaque_info_owner(oipt);
|
||||
free_opaque_info_per_type(oipt);
|
||||
free_opaque_info_per_type(oipt, true);
|
||||
oipt = NULL;
|
||||
goto out; /* This case may not exist. */
|
||||
}
|
||||
@ -589,42 +586,13 @@ out:
|
||||
return oipt;
|
||||
}
|
||||
|
||||
/* Remove "oipt" from its owner's self-originated LSA list. */
|
||||
static void free_opaque_info_owner(void *val)
|
||||
static void free_opaque_info_per_type(struct opaque_info_per_type *oipt,
|
||||
bool cleanup_owner)
|
||||
{
|
||||
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:
|
||||
flog_warn(EC_OSPF_LSA_UNEXPECTED,
|
||||
"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;
|
||||
struct opaque_info_per_id *oipi;
|
||||
struct ospf_lsa *lsa;
|
||||
struct listnode *node, *nnode;
|
||||
struct list *l;
|
||||
|
||||
/* Control information per opaque-id may still exist. */
|
||||
for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) {
|
||||
@ -637,10 +605,37 @@ static void free_opaque_info_per_type(void *val)
|
||||
|
||||
OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
|
||||
list_delete(&oipt->id_list);
|
||||
if (cleanup_owner) {
|
||||
/* Remove from its owner's self-originated LSA list. */
|
||||
switch (oipt->lsa_type) {
|
||||
case OSPF_OPAQUE_LINK_LSA:
|
||||
l = ((struct ospf_interface *)oipt->owner)
|
||||
->opaque_lsa_self;
|
||||
break;
|
||||
case OSPF_OPAQUE_AREA_LSA:
|
||||
l = ((struct ospf_area *)oipt->owner)->opaque_lsa_self;
|
||||
break;
|
||||
case OSPF_OPAQUE_AS_LSA:
|
||||
l = ((struct ospf *)oipt->owner)->opaque_lsa_self;
|
||||
break;
|
||||
default:
|
||||
flog_warn(
|
||||
EC_OSPF_LSA_UNEXPECTED,
|
||||
"free_opaque_info_owner: Unexpected LSA-type(%u)",
|
||||
oipt->lsa_type);
|
||||
return;
|
||||
}
|
||||
listnode_delete(l, oipt);
|
||||
}
|
||||
XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
|
||||
return;
|
||||
}
|
||||
|
||||
static void free_opaque_info_per_type_del(void *val)
|
||||
{
|
||||
free_opaque_info_per_type((struct opaque_info_per_type *)val, false);
|
||||
}
|
||||
|
||||
static struct opaque_info_per_type *
|
||||
lookup_opaque_info_by_type(struct ospf_lsa *lsa)
|
||||
{
|
||||
@ -758,6 +753,13 @@ out:
|
||||
return oipi;
|
||||
}
|
||||
|
||||
int ospf_opaque_is_owned(struct ospf_lsa *lsa)
|
||||
{
|
||||
struct opaque_info_per_type *oipt = lookup_opaque_info_by_type(lsa);
|
||||
|
||||
return (oipt != NULL && lookup_opaque_info_by_id(oipt, lsa) != NULL);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* Following are (vty) configuration functions for Opaque-LSAs handling.
|
||||
*------------------------------------------------------------------------*/
|
||||
|
@ -173,4 +173,6 @@ extern void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
|
||||
struct ospf_lsa *lsa);
|
||||
extern struct ospf *oi_to_top(struct ospf_interface *oi);
|
||||
|
||||
extern int ospf_opaque_is_owned(struct ospf_lsa *lsa);
|
||||
|
||||
#endif /* _ZEBRA_OSPF_OPAQUE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user