mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 03:28:31 +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. */
|
/* Determine if LSA is new or an update for an existing one. */
|
||||||
old = ospf_lsdb_lookup(lsdb, new);
|
old = ospf_lsdb_lookup(lsdb, new);
|
||||||
|
|
||||||
if (!old) {
|
if (!old || !ospf_opaque_is_owned(old)) {
|
||||||
/* New LSA install in LSDB. */
|
/* New LSA install in LSDB. */
|
||||||
rc = ospf_apiserver_originate1(new);
|
rc = ospf_apiserver_originate1(new, old);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Keep the new LSA instance in the "waiting place" until the
|
* 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;
|
struct ospf *ospf;
|
||||||
|
|
||||||
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
|
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
|
||||||
assert(ospf);
|
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. */
|
/* Install this LSA into LSDB. */
|
||||||
if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
|
if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) {
|
||||||
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
|
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
|
||||||
"ospf_apiserver_originate1: ospf_lsa_install failed");
|
"%s: ospf_lsa_install failed", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,8 @@ extern struct ospf_interface *
|
|||||||
ospf_apiserver_if_lookup_by_addr(struct in_addr address);
|
ospf_apiserver_if_lookup_by_addr(struct in_addr address);
|
||||||
extern struct ospf_interface *
|
extern struct ospf_interface *
|
||||||
ospf_apiserver_if_lookup_by_ifp(struct interface *ifp);
|
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);
|
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_register_vty(void);
|
||||||
static void ospf_opaque_funclist_init(void);
|
static void ospf_opaque_funclist_init(void);
|
||||||
static void ospf_opaque_funclist_term(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_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_install_hook(struct ospf_lsa *lsa);
|
||||||
static int ospf_opaque_lsa_delete_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);
|
list_delete(&oi->opaque_lsa_self);
|
||||||
|
|
||||||
oi->opaque_lsa_self = list_new();
|
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;
|
oi->t_opaque_lsa_self = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -161,7 +160,7 @@ int ospf_opaque_type10_lsa_init(struct ospf_area *area)
|
|||||||
list_delete(&area->opaque_lsa_self);
|
list_delete(&area->opaque_lsa_self);
|
||||||
|
|
||||||
area->opaque_lsa_self = list_new();
|
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;
|
area->t_opaque_lsa_self = NULL;
|
||||||
|
|
||||||
#ifdef MONITOR_LSDB_CHANGE
|
#ifdef MONITOR_LSDB_CHANGE
|
||||||
@ -189,7 +188,7 @@ int ospf_opaque_type11_lsa_init(struct ospf *top)
|
|||||||
list_delete(&top->opaque_lsa_self);
|
list_delete(&top->opaque_lsa_self);
|
||||||
|
|
||||||
top->opaque_lsa_self = list_new();
|
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;
|
top->t_opaque_lsa_self = NULL;
|
||||||
|
|
||||||
#ifdef MONITOR_LSDB_CHANGE
|
#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. */
|
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 {
|
struct ospf_opaque_functab {
|
||||||
uint8_t opaque_type;
|
uint8_t opaque_type;
|
||||||
struct opaque_info_per_type *oipt;
|
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) {
|
if (functab->opaque_type == opaque_type) {
|
||||||
/* Cleanup internal control information, if it
|
/* Cleanup internal control information, if it
|
||||||
* still remains. */
|
* still remains. */
|
||||||
if (functab->oipt != NULL) {
|
if (functab->oipt != NULL)
|
||||||
free_opaque_info_owner(functab->oipt);
|
free_opaque_info_per_type(functab->oipt,
|
||||||
free_opaque_info_per_type(
|
true);
|
||||||
functab->oipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dequeue listnode entry from the list. */
|
/* Dequeue listnode entry from the list. */
|
||||||
listnode_delete(funclist, functab);
|
listnode_delete(funclist, functab);
|
||||||
|
|
||||||
@ -558,8 +557,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
|
|||||||
case OSPF_OPAQUE_AS_LSA:
|
case OSPF_OPAQUE_AS_LSA:
|
||||||
top = ospf_lookup_by_vrf_id(new->vrf_id);
|
top = ospf_lookup_by_vrf_id(new->vrf_id);
|
||||||
if (new->area != NULL && (top = new->area->ospf) == NULL) {
|
if (new->area != NULL && (top = new->area->ospf) == NULL) {
|
||||||
free_opaque_info_owner(oipt);
|
free_opaque_info_per_type(oipt, true);
|
||||||
free_opaque_info_per_type(oipt);
|
|
||||||
oipt = NULL;
|
oipt = NULL;
|
||||||
goto out; /* This case may not exist. */
|
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,
|
EC_OSPF_LSA_UNEXPECTED,
|
||||||
"register_opaque_info_per_type: Unexpected LSA-type(%u)",
|
"register_opaque_info_per_type: Unexpected LSA-type(%u)",
|
||||||
new->data->type);
|
new->data->type);
|
||||||
free_opaque_info_owner(oipt);
|
free_opaque_info_per_type(oipt, true);
|
||||||
free_opaque_info_per_type(oipt);
|
|
||||||
oipt = NULL;
|
oipt = NULL;
|
||||||
goto out; /* This case may not exist. */
|
goto out; /* This case may not exist. */
|
||||||
}
|
}
|
||||||
@ -589,42 +586,13 @@ out:
|
|||||||
return oipt;
|
return oipt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove "oipt" from its owner's self-originated LSA list. */
|
static void free_opaque_info_per_type(struct opaque_info_per_type *oipt,
|
||||||
static void free_opaque_info_owner(void *val)
|
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 opaque_info_per_id *oipi;
|
||||||
struct ospf_lsa *lsa;
|
struct ospf_lsa *lsa;
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
|
struct list *l;
|
||||||
|
|
||||||
/* Control information per opaque-id may still exist. */
|
/* Control information per opaque-id may still exist. */
|
||||||
for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) {
|
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);
|
OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
|
||||||
list_delete(&oipt->id_list);
|
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);
|
XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
|
||||||
return;
|
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 *
|
static struct opaque_info_per_type *
|
||||||
lookup_opaque_info_by_type(struct ospf_lsa *lsa)
|
lookup_opaque_info_by_type(struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
@ -758,6 +753,13 @@ out:
|
|||||||
return oipi;
|
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.
|
* 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);
|
struct ospf_lsa *lsa);
|
||||||
extern struct ospf *oi_to_top(struct ospf_interface *oi);
|
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 */
|
#endif /* _ZEBRA_OSPF_OPAQUE_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user