summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Hopps <chopps@labn.net>2022-01-08 22:57:10 +0100
committerChristian Hopps <chopps@labn.net>2022-06-02 22:37:16 +0200
commit5349121b4c6ea2126be87bcbe6400a8f10ea99fc (patch)
tree4863a63656b2f3d7ff45f0b6eac69dfe5d030163
parentospfd: cli: add "show ip ospf reachable-routers" CLI (diff)
downloadfrr-5349121b4c6ea2126be87bcbe6400a8f10ea99fc.tar.xz
frr-5349121b4c6ea2126be87bcbe6400a8f10ea99fc.zip
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>
-rw-r--r--ospfd/ospf_apiserver.c24
-rw-r--r--ospfd/ospf_apiserver.h3
-rw-r--r--ospfd/ospf_opaque.c96
-rw-r--r--ospfd/ospf_opaque.h2
4 files changed, 73 insertions, 52 deletions
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index 259ba2a3f..4015566b1 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -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;
}
diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h
index 8a756e9c3..a57f172b5 100644
--- a/ospfd/ospf_apiserver.h
+++ b/ospfd/ospf_apiserver.h
@@ -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);
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 947454c0d..7e95cb591 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -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)
-{
- 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)
+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;
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.
*------------------------------------------------------------------------*/
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index 59d4288bf..9c7687790 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -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 */