]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospfd: OSPF multi-instance default origination fixes
authorAcee Lindem <acee@lindem.com>
Fri, 15 Nov 2024 18:58:49 +0000 (18:58 +0000)
committerAcee Lindem <acee@lindem.com>
Sun, 17 Nov 2024 13:33:48 +0000 (13:33 +0000)
When originating a default AS-External LSA in one OSPF instance,
it wasn't working if the criteria route was installed by another OSPF
instance. This required more flexible processing of the OSPF external
route information.

Also fix problem multi-instance display for "show ip ospf
 <instance> database ...".

Signed-off-by: Acee Lindem <acee@lindem.com>
ospfd/ospf_asbr.c
ospfd/ospf_asbr.h
ospfd/ospf_lsa.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
ospfd/ospf_zebra.h

index b47c39008819d44795fb18677d3b4edf47cf2555..738ac6d8cf05aa449e1492ee6975140931621ce1 100644 (file)
@@ -168,6 +168,38 @@ void ospf_external_info_delete(struct ospf *ospf, uint8_t type,
        }
 }
 
+/*
+ * ospf_external_info_delete_multi_instance
+ *
+ * Delete instances of the external route information for a given route type.
+ * The preserve_instance parameter may be used to prevent the current instance
+ * from being deleted.
+ */
+void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type, struct prefix_ipv4 p,
+                                             unsigned long preserve_instance)
+{
+       struct route_node *rn;
+       struct ospf_external *ext;
+       struct list *ext_list;
+       struct listnode *node;
+
+       ext_list = ospf->external[type];
+       if (!ext_list)
+               return;
+
+       for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+               if (ext->instance != preserve_instance) {
+                       rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+                       if (rn) {
+                               ospf_external_info_free(rn->info);
+                               rn->info = NULL;
+                               route_unlock_node(rn);
+                               route_unlock_node(rn);
+                       }
+               }
+       }
+}
+
 struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
                                                unsigned short instance,
                                                struct prefix_ipv4 *p)
@@ -189,6 +221,44 @@ struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
        return NULL;
 }
 
+/*
+ * ospf_external_info_default_lookup
+ *
+ * For default information criteria, we really don't care about the
+ * source of the route and there only should be one.
+ */
+struct external_info *ospf_external_info_default_lookup(struct ospf *ospf)
+{
+       struct ospf_external *ext;
+       struct external_info *ei;
+       struct list *ext_list;
+       struct listnode *node;
+       struct route_node *rn;
+       struct prefix_ipv4 p = {
+               .family = AF_INET,
+               .prefixlen = 0,
+               .prefix.s_addr = INADDR_ANY,
+       };
+
+       ext_list = ospf->external[DEFAULT_ROUTE];
+       if (!ext_list)
+               return (NULL);
+
+       for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+               rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+               if (rn) {
+                       route_unlock_node(rn);
+                       if (rn->info) {
+                               ei = rn->info;
+                               if (ei->type != ZEBRA_ROUTE_OSPF || ei->instance != ospf->instance)
+                                       return ei;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
 struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,
                                             struct prefix_ipv4 *p)
 {
index 6158d65f22e85433886b363849b3505f114e9290..648a5a11aee293a02b3bbadacb185a43b4ea8ab7 100644 (file)
@@ -109,6 +109,10 @@ ospf_external_info_add(struct ospf *, uint8_t, unsigned short,
                       route_tag_t, uint32_t metric);
 extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
                                      struct prefix_ipv4);
+extern void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type,
+                                                    struct prefix_ipv4 p,
+                                                    unsigned long preserve_instance);
+#define OSPF_DELETE_ANY_INSTANCE 0xffffffff
 extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
                                                       unsigned short,
                                                       struct prefix_ipv4 *);
index 1350487898581d5c7dccdaa202c6981edb2bd329..73542233976e03e567c7e038c164530f680b0b98 100644 (file)
@@ -2407,15 +2407,10 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
 static struct external_info *ospf_default_external_info(struct ospf *ospf)
 {
        int type;
-       struct prefix_ipv4 p;
        struct external_info *default_ei;
        int ret = 0;
 
-       p.family = AF_INET;
-       p.prefix.s_addr = 0;
-       p.prefixlen = 0;
-
-       default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p);
+       default_ei = ospf_external_info_default_lookup(ospf);
        if (!default_ei)
                return NULL;
 
index 0457b13337530694891d1c1045ef0e872e482aa9..27528f659432854b9ffdcebd1edfe9b6bc75e81c 100644 (file)
@@ -7347,6 +7347,9 @@ DEFPY (show_ip_ospf_database,
        struct in_addr *adv_router_p = NULL;
        json_object *json = NULL;
 
+       if (instance_id != ospf_instance)
+               return CMD_NOT_MY_INSTANCE;
+
        if (uj)
                json = json_object_new_object();
        if (lsid_str)
index c7cba1e20fee789d0cd8a6c5a2356d843cf22456..b718d498ae0de0e7be09a63af55c10aacaecd6dd 100644 (file)
@@ -1292,15 +1292,14 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
         * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.
         * Resolved this inconsistency by maintaining same route type.
         */
-       if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF))
+       if ((is_default_prefix(&pgen)) &&
+           ((api.type != ZEBRA_ROUTE_OSPF) || (api.instance != ospf->instance)))
                rt_type = DEFAULT_ROUTE;
 
        if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
-               zlog_debug("%s: cmd %s from client %s: vrf %s(%u), p %pFX, metric %d",
-                          __func__, zserv_command_string(cmd),
-                          zebra_route_string(api.type),
-                          ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix,
-                          api.metric);
+               zlog_debug("%s: cmd %s from client %s-%d: vrf %s(%u), p %pFX, metric %d", __func__,
+                          zserv_command_string(cmd), zebra_route_string(api.type), api.instance,
+                          ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix, api.metric);
 
        if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
                /* XXX|HACK|TODO|FIXME:
@@ -1315,16 +1314,17 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                        api.tag = ospf->dtag[rt_type];
 
                /*
-                * Given zebra sends update for a prefix via ADD message, it
-                * should
-                * be considered as an implicit DEL for that prefix with other
-                * source
-                * types.
+                * Given zebra sends an update for a prefix via an ADD message, it
+                * will be considered as an impilict DELETE for that prefix for other
+                * types and instances other than the type and instance associated with
+                * the prefix.
                 */
-               for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
-                       if (i != rt_type)
-                               ospf_external_info_delete(ospf, i, api.instance,
-                                                         p);
+               for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+                       unsigned long preserve_instance;
+
+                       preserve_instance = (i == rt_type) ? api.instance : OSPF_DELETE_ANY_INSTANCE;
+                       ospf_external_info_delete_multi_instance(ospf, i, p, preserve_instance);
+               }
 
                ei = ospf_external_info_add(ospf, rt_type, api.instance, p,
                                            ifindex, nexthop, api.tag,
index 86a5678fc4fa89917f3c794ad7b181d91394ec81..b83524303fa74016d0908a5c4230e7e15831db0c 100644 (file)
@@ -47,6 +47,9 @@ extern uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *,
                                   struct ospf_route *);
 extern struct ospf_external *ospf_external_lookup(struct ospf *, uint8_t,
                                                  unsigned short);
+
+extern struct external_info *ospf_external_info_default_lookup(struct ospf *ospf);
+
 extern struct ospf_external *ospf_external_add(struct ospf *, uint8_t,
                                               unsigned short);