]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf: Default-information originate with routemap 6333/head
authorSantosh P K <sapk@vmware.com>
Sun, 3 May 2020 09:25:55 +0000 (02:25 -0700)
committerSantosh P K <sapk@vmware.com>
Tue, 7 Jul 2020 11:53:14 +0000 (04:53 -0700)
Default originate with route-map was broken. Routemap
was not getting applied for redistribute route but was
getting applied default route itself. No default route
was originated even when routemap was satisfied.

Signed-off-by: Santosh P K <sapk@vmware.com>
ospfd/ospf_dump.c
ospfd/ospf_dump.h
ospfd/ospf_lsa.c
ospfd/ospf_zebra.c
ospfd/ospf_zebra.h
ospfd/ospfd.c
ospfd/ospfd.h

index 3dcb2b481d3bd8c3618abfa1d133c96eeb63fdf2..dcc479def6b0969418c6dd09a1cbd568f7f15840 100644 (file)
@@ -53,10 +53,11 @@ unsigned long conf_debug_ospf_nssa = 0;
 unsigned long conf_debug_ospf_te = 0;
 unsigned long conf_debug_ospf_ext = 0;
 unsigned long conf_debug_ospf_sr = 0;
+unsigned long conf_debug_ospf_defaultinfo = 0;
 
 /* Enable debug option variables -- valid only session. */
 unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
-unsigned long term_debug_ospf_event = 0;
+unsigned long term_debug_ospf_event;
 unsigned long term_debug_ospf_ism = 0;
 unsigned long term_debug_ospf_nsm = 0;
 unsigned long term_debug_ospf_lsa = 0;
@@ -65,6 +66,7 @@ unsigned long term_debug_ospf_nssa = 0;
 unsigned long term_debug_ospf_te = 0;
 unsigned long term_debug_ospf_ext = 0;
 unsigned long term_debug_ospf_sr = 0;
+unsigned long term_debug_ospf_defaultinfo;
 
 const char *ospf_redist_string(unsigned int route_type)
 {
@@ -1447,6 +1449,33 @@ DEFUN (no_debug_ospf_sr,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_ospf_default_info,
+       debug_ospf_default_info_cmd,
+       "debug ospf default-information",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF default information\n")
+{
+       if (vty->node == CONFIG_NODE)
+               CONF_DEBUG_ON(defaultinfo, DEFAULTINFO);
+       TERM_DEBUG_ON(defaultinfo, DEFAULTINFO);
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf_default_info,
+       no_debug_ospf_default_info_cmd,
+       "no debug ospf default-information",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF default information\n")
+{
+       if (vty->node == CONFIG_NODE)
+               CONF_DEBUG_OFF(defaultinfo, DEFAULTINFO);
+       TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
+       return CMD_SUCCESS;
+}
+
 DEFUN (no_debug_ospf,
        no_debug_ospf_cmd,
        "no debug ospf",
@@ -1475,6 +1504,7 @@ DEFUN (no_debug_ospf,
                DEBUG_OFF(zebra, ZEBRA);
                DEBUG_OFF(zebra, ZEBRA_INTERFACE);
                DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
+               DEBUG_OFF(defaultinfo, DEFAULTINFO);
 
                for (i = 0; i < 5; i++)
                        DEBUG_PACKET_OFF(i, flag);
@@ -1501,6 +1531,7 @@ DEFUN (no_debug_ospf,
        TERM_DEBUG_OFF(zebra, ZEBRA);
        TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE);
        TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE);
+       TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
 
        return CMD_SUCCESS;
 }
@@ -1595,6 +1626,9 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
                                "  OSPF Zebra redistribute debugging is on\n");
        }
 
+       if (IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) == OSPF_DEBUG_DEFAULTINFO)
+               vty_out(vty, "OSPF default information is on\n");
+
        /* Show debug status for NSSA. */
        if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA)
                vty_out(vty, "  OSPF NSSA debugging is on\n");
@@ -1797,6 +1831,7 @@ void ospf_debug_init(void)
        install_element(ENABLE_NODE, &debug_ospf_nssa_cmd);
        install_element(ENABLE_NODE, &debug_ospf_te_cmd);
        install_element(ENABLE_NODE, &debug_ospf_sr_cmd);
+       install_element(ENABLE_NODE, &debug_ospf_default_info_cmd);
        install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd);
        install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd);
        install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd);
@@ -1805,6 +1840,7 @@ void ospf_debug_init(void)
        install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd);
        install_element(ENABLE_NODE, &no_debug_ospf_te_cmd);
        install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd);
+       install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd);
 
        install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd);
        install_element(ENABLE_NODE, &debug_ospf_packet_cmd);
@@ -1834,6 +1870,7 @@ void ospf_debug_init(void)
        install_element(CONFIG_NODE, &debug_ospf_nssa_cmd);
        install_element(CONFIG_NODE, &debug_ospf_te_cmd);
        install_element(CONFIG_NODE, &debug_ospf_sr_cmd);
+       install_element(CONFIG_NODE, &debug_ospf_default_info_cmd);
        install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd);
        install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd);
        install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
@@ -1841,6 +1878,7 @@ void ospf_debug_init(void)
        install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd);
        install_element(CONFIG_NODE, &no_debug_ospf_te_cmd);
        install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd);
+       install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd);
 
        install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd);
        install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd);
index 6b2ebb125a76d6807b8a8fa186aa9a94a9de87ae..8c01977ff883b7cd59b22099d808e7d752a02ef0 100644 (file)
@@ -59,6 +59,7 @@
 #define OSPF_DEBUG_TE          0x04
 #define OSPF_DEBUG_EXT         0x08
 #define OSPF_DEBUG_SR          0x10
+#define OSPF_DEBUG_DEFAULTINFO 0x20
 
 /* Macro for setting debug option. */
 #define CONF_DEBUG_PACKET_ON(a, b)         conf_debug_ospf_packet[a] |= (b)
 
 #define IS_DEBUG_OSPF_SR  IS_DEBUG_OSPF(sr, SR)
 
+#define IS_DEBUG_OSPF_DEFAULT_INFO IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO)
+
 #define IS_CONF_DEBUG_OSPF_PACKET(a, b)                                        \
        (conf_debug_ospf_packet[a] & OSPF_DEBUG_##b)
 #define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b)
@@ -122,6 +125,7 @@ extern unsigned long term_debug_ospf_nssa;
 extern unsigned long term_debug_ospf_te;
 extern unsigned long term_debug_ospf_ext;
 extern unsigned long term_debug_ospf_sr;
+extern unsigned long term_debug_ospf_defaultinfo;
 
 /* Message Strings. */
 extern char *ospf_lsa_type_str[];
index d089ea76cd51ce4b34a7fb8efab6d141628f41f2..07feb2482eb9dd825c33eeaf3117e700a359764c 100644 (file)
@@ -2032,18 +2032,22 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
 static struct external_info *ospf_default_external_info(struct ospf *ospf)
 {
        int type;
-       struct route_node *rn;
        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,
+                                              ospf->instance, &p);
+       if (!default_ei)
+               return NULL;
+
        /* First, lookup redistributed default route. */
        for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
                struct list *ext_list;
-               struct listnode *node;
-               struct ospf_external *ext;
 
                if (type == ZEBRA_ROUTE_OSPF)
                        continue;
@@ -2052,17 +2056,10 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf)
                if (!ext_list)
                        continue;
 
-               for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
-                       rn = route_node_lookup(ext->external_info,
-                                              (struct prefix *)&p);
-                       if (rn != NULL) {
-                               route_unlock_node(rn);
-                               assert(rn->info);
-                               if (ospf_redistribute_check(ospf, rn->info,
-                                                           NULL))
-                                       return rn->info;
-                       }
-               }
+               ret = ospf_external_default_routemap_apply_walk(ospf, ext_list,
+                                                               default_ei);
+               if (ret)
+                       return default_ei;
        }
 
        return NULL;
index 644ea7f92278e66abdc72764d7ce0112c0d2b792..04b500d66297a61fef5085c580818918e68963b9 100644 (file)
@@ -56,6 +56,7 @@ DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table")
 DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute")
 DEFINE_MTYPE_STATIC(OSPFD, OSPF_DIST_ARGS, "OSPF Distribute arguments")
 
+
 /* Zebra structure to hold current status. */
 struct zclient *zclient = NULL;
 
@@ -397,6 +398,101 @@ struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,
        return ext;
 }
 
+/*
+ * Walk all the ei received from zebra for a route type and apply
+ * default route-map.
+ */
+bool ospf_external_default_routemap_apply_walk(struct ospf *ospf,
+                                              struct list *ext_list,
+                                              struct external_info *default_ei)
+{
+       struct listnode *node;
+       struct ospf_external *ext;
+       struct route_node *rn;
+       struct external_info *ei = NULL;
+       int ret = 0;
+
+       for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+               if (!ext->external_info)
+                       continue;
+
+               for (rn = route_top(ext->external_info); rn;
+                    rn = route_next(rn)) {
+                       ei = rn->info;
+                       if (!ei)
+                               continue;
+                       ret = ospf_external_info_apply_default_routemap(
+                               ospf, ei, default_ei);
+                       if (ret)
+                               break;
+               }
+       }
+
+       if (ret && ei) {
+               if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                       zlog_debug("Default originate routemap permit ei: %s",
+                                  inet_ntoa(ei->p.prefix));
+               return true;
+       }
+
+       return false;
+}
+
+/*
+ * Function to originate or flush default after applying
+ * route-map on all ei.
+ */
+static int ospf_external_lsa_default_routemap_timer(struct thread *thread)
+{
+       struct list *ext_list;
+       struct ospf *ospf = THREAD_ARG(thread);
+       struct prefix_ipv4 p;
+       int type;
+       int ret = 0;
+       struct ospf_lsa *lsa;
+       struct external_info *default_ei;
+
+       p.family = AF_INET;
+       p.prefixlen = 0;
+       p.prefix.s_addr = INADDR_ANY;
+
+       /* Get the default extenal info. */
+       default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
+                                              ospf->instance, &p);
+       if (!default_ei) {
+               /* Nothing to be done here. */
+               if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                       zlog_debug("Default originate info not present");
+               return 0;
+       }
+
+       /* For all the ei apply route-map */
+       for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+               ext_list = ospf->external[type];
+               if (!ext_list || type == ZEBRA_ROUTE_OSPF)
+                       continue;
+
+               ret = ospf_external_default_routemap_apply_walk(ospf, ext_list,
+                                                               default_ei);
+               if (ret)
+                       break;
+       }
+
+       /* Get the default LSA. */
+       lsa = ospf_external_info_find_lsa(ospf, &p);
+
+       /* If permit then originate default. */
+       if (ret && !lsa)
+               ospf_external_lsa_originate(ospf, default_ei);
+       else if (ret && lsa && IS_LSA_MAXAGE(lsa))
+               ospf_external_lsa_refresh(ospf, lsa, default_ei, true);
+       else if (!ret && lsa)
+               ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0);
+
+       return 1;
+}
+
+
 void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)
 {
        struct ospf_external *ext;
@@ -414,6 +510,12 @@ void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)
 
                XFREE(MTYPE_OSPF_EXTERNAL, ext);
        }
+
+       /*
+        * Check if default needs to be flushed too.
+        */
+       thread_add_event(master, ospf_external_lsa_default_routemap_timer, ospf,
+                        0, &ospf->t_default_routemap_timer);
 }
 
 /* Update NHLFE for Prefix SID */
@@ -801,6 +903,132 @@ int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei)
        return 1;
 }
 
+
+/* Apply default route-map on ei received. */
+int ospf_external_info_apply_default_routemap(struct ospf *ospf,
+                                             struct external_info *ei,
+                                             struct external_info *default_ei)
+{
+       struct ospf_redist *red;
+       int type = default_ei->type;
+       struct prefix_ipv4 *p = &ei->p;
+       struct route_map_set_values save_values;
+
+
+       if (!ospf_external_lsa_originate_check(ospf, default_ei))
+               return 0;
+
+       save_values = default_ei->route_map_set;
+       ospf_reset_route_map_set_values(&default_ei->route_map_set);
+
+       /* apply route-map if needed */
+       red = ospf_redist_lookup(ospf, type, ospf->instance);
+       if (red && ROUTEMAP_NAME(red)) {
+               route_map_result_t ret;
+
+               ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p,
+                                     RMAP_OSPF, ei);
+
+               if (ret == RMAP_DENYMATCH) {
+                       ei->route_map_set = save_values;
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+
+/*
+ * Default originated is based on route-map condition then
+ * apply route-map on received external info. Originate or
+ * flush based on route-map condition.
+ */
+static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf,
+                                                    struct external_info *ei,
+                                                    int cmd)
+{
+       struct external_info *default_ei;
+       struct prefix_ipv4 p;
+       struct ospf_lsa *lsa;
+       int ret;
+
+       p.family = AF_INET;
+       p.prefixlen = 0;
+       p.prefix.s_addr = INADDR_ANY;
+
+
+       /* Get the default extenal info. */
+       default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
+                                              ospf->instance, &p);
+       if (!default_ei) {
+               /* Nothing to be done here. */
+               return false;
+       }
+
+       if (IS_DEBUG_OSPF_DEFAULT_INFO)
+               zlog_debug("Apply default originate routemap on ei: %s cmd: %d",
+                          inet_ntoa(ei->p.prefix), cmd);
+
+       ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei);
+
+       /* If deny then nothing to be done both in add and del case. */
+       if (!ret) {
+               if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                       zlog_debug("Default originte routemap deny for ei: %s",
+                                  inet_ntoa(ei->p.prefix));
+               return false;
+       }
+
+       /* Get the default LSA. */
+       lsa = ospf_external_info_find_lsa(ospf, &p);
+
+       /* If this is add route and permit then ooriginate default. */
+       if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
+               /* If permit and default already advertise then return. */
+               if (lsa && !IS_LSA_MAXAGE(lsa)) {
+                       if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                               zlog_debug("Defult lsa already originated");
+                       return true;
+               }
+
+               if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                       zlog_debug("Originating/Refreshing default lsa");
+
+               if (lsa && IS_LSA_MAXAGE(lsa))
+                       /* Refresh lsa.*/
+                       ospf_external_lsa_refresh(ospf, lsa, default_ei, true);
+               else
+                       /* If permit and default not advertised then advertise.
+                        */
+                       ospf_external_lsa_originate(ospf, default_ei);
+
+       } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) {
+               /* If deny and lsa is not originated then nothing to be done.*/
+               if (!lsa) {
+                       if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                               zlog_debug(
+                                       "Default lsa not originated, not flushing");
+                       return true;
+               }
+
+               if (IS_DEBUG_OSPF_DEFAULT_INFO)
+                       zlog_debug(
+                               "Running default route-map again as ei: %s deleted",
+                               inet_ntoa(ei->p.prefix));
+               /*
+                * if this route delete was permitted then we need to check
+                * there are any other external info which can still trigger
+                * default route origination else flush it.
+                */
+               thread_add_event(master,
+                                ospf_external_lsa_default_routemap_timer, ospf,
+                                0, &ospf->t_default_routemap_timer);
+       }
+
+       return true;
+}
+
 /* return 1 if external LSA must be originated, 0 otherwise */
 int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
                            int *changed)
@@ -812,6 +1040,10 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
        unsigned short instance = is_prefix_default(&ei->p) ? 0 : ei->instance;
        route_tag_t saved_tag = 0;
 
+       /* Default is handled differently. */
+       if (type == DEFAULT_ROUTE)
+               return 1;
+
        if (changed)
                *changed = 0;
 
@@ -1004,8 +1236,24 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                                }
                        }
                }
+
+               /*
+                * Check if default-information originate is
+                * with some routemap prefix/access list match.
+                */
+               ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
+
        } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
        {
+               /*
+                * Check if default-information originate is
+                * with some routemap prefix/access list match.
+                * Apply before ei is deleted.
+                */
+               ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p);
+               if (ei)
+                       ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
+
                ospf_external_info_delete(ospf, rt_type, api.instance, p);
                if (is_prefix_default(&p))
                        ospf_external_lsa_refresh_default(ospf);
@@ -1014,6 +1262,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                                                ifindex /*, nexthop */);
        }
 
+
        return 0;
 }
 
index 253d2e0a3faa1b45dd058114e159e6125651cb98..80abf62369abb3fec9fb29af5f909be71c5efafe 100644 (file)
@@ -92,5 +92,10 @@ extern int ospf_distance_unset(struct vty *, struct ospf *, const char *,
 extern void ospf_zebra_init(struct thread_master *, unsigned short);
 extern void ospf_zebra_vrf_register(struct ospf *ospf);
 extern void ospf_zebra_vrf_deregister(struct ospf *ospf);
-
+bool ospf_external_default_routemap_apply_walk(
+       struct ospf *ospf, struct list *ext_list,
+       struct external_info *default_ei);
+int ospf_external_info_apply_default_routemap(struct ospf *ospf,
+                                             struct external_info *ei,
+                                             struct external_info *default_ei);
 #endif /* _ZEBRA_OSPF_ZEBRA_H */
index cdfcaa44d6793ffc2a4602231b8bae47d5ea5d31..3b1fbb3677301174b74470999cba3f59b0e9dcb6 100644 (file)
@@ -674,6 +674,7 @@ static void ospf_finish_final(struct ospf *ospf)
        OSPF_TIMER_OFF(ospf->t_lsa_refresher);
        OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
        OSPF_TIMER_OFF(ospf->t_sr_update);
+       OSPF_TIMER_OFF(ospf->t_default_routemap_timer);
 
        LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
                ospf_discard_from_db(ospf, ospf->lsdb, lsa);
index 5e91e6f8e6f73dcde6b513dfa9db1ba5c1d3e94e..cdeaa38dc0c3ae26ae53c4ed7e170d461c1b9667 100644 (file)
@@ -249,6 +249,8 @@ struct ospf {
 
        struct thread *t_write;
 #define OSPF_WRITE_INTERFACE_COUNT_DEFAULT    20
+       struct thread *t_default_routemap_timer;
+
        int write_oi_count; /* Num of packets sent per thread invocation */
        struct thread *t_read;
        int fd;