]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3167 from chiragshah6/ospfv3_dev
authorRuss White <russ@riw.us>
Fri, 12 Oct 2018 19:55:59 +0000 (15:55 -0400)
committerGitHub <noreply@github.com>
Fri, 12 Oct 2018 19:55:59 +0000 (15:55 -0400)
ospf6d: fix ospf6 crash in inp lsa processing

21 files changed:
isisd/isis_adjacency.c
isisd/isis_adjacency.h
isisd/isis_bfd.c [new file with mode: 0644]
isisd/isis_bfd.h [new file with mode: 0644]
isisd/isis_circuit.c
isisd/isis_circuit.h
isisd/isis_events.c
isisd/isis_events.h
isisd/isis_lsp.c
isisd/isis_lsp.h
isisd/isis_main.c
isisd/isis_mt.c
isisd/isis_mt.h
isisd/isis_vty_common.c
isisd/isis_zebra.h
isisd/isisd.c
isisd/isisd.h
isisd/subdir.am
zebra/zebra_ptm.c
zebra/zebra_ptm.h
zebra/zebra_ptm_redistribute.c

index a41d6ff8152267214bb99680de920d8654d6a8c8..9013c7c19b10e5df649f9b01ee59c32f34a7246c 100644 (file)
@@ -122,6 +122,8 @@ struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
        return NULL;
 }
 
+DEFINE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj))
+
 void isis_delete_adj(void *arg)
 {
        struct isis_adjacency *adj = arg;
@@ -130,6 +132,10 @@ void isis_delete_adj(void *arg)
                return;
 
        THREAD_TIMER_OFF(adj->t_expire);
+       if (adj->adj_state != ISIS_ADJ_DOWN) {
+               adj->adj_state = ISIS_ADJ_DOWN;
+               hook_call(isis_adj_state_change_hook, adj);
+       }
 
        /* remove from SPF trees */
        spftree_area_adj_del(adj->circuit->area, adj);
@@ -256,8 +262,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
                                continue;
                        if (new_state == ISIS_ADJ_UP) {
                                circuit->upadjcount[level - 1]++;
-                               isis_event_adjacency_state_change(adj,
-                                                                 new_state);
+                               hook_call(isis_adj_state_change_hook, adj);
                                /* update counter & timers for debugging
                                 * purposes */
                                adj->last_flap = time(NULL);
@@ -270,8 +275,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
                                if (circuit->upadjcount[level - 1] == 0)
                                        isis_tx_queue_clean(circuit->tx_queue);
 
-                               isis_event_adjacency_state_change(adj,
-                                                                 new_state);
+                               hook_call(isis_adj_state_change_hook, adj);
                                del = true;
                        }
 
@@ -299,8 +303,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
                                continue;
                        if (new_state == ISIS_ADJ_UP) {
                                circuit->upadjcount[level - 1]++;
-                               isis_event_adjacency_state_change(adj,
-                                                                 new_state);
+                               hook_call(isis_adj_state_change_hook, adj);
 
                                if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
                                        send_hello(circuit, level);
@@ -326,8 +329,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
                                if (circuit->upadjcount[level - 1] == 0)
                                        isis_tx_queue_clean(circuit->tx_queue);
 
-                               isis_event_adjacency_state_change(adj,
-                                                                 new_state);
+                               hook_call(isis_adj_state_change_hook, adj);
                                del = true;
                        }
                }
index 2f39378c003c4c551e01b1a59affdadaf023931f..2a4cb6e6142849c409ace39815a89f6cac2808d3 100644 (file)
@@ -68,6 +68,8 @@ struct isis_dis_record {
        time_t last_dis_change; /* timestamp for last dis change */
 };
 
+struct bfd_session;
+
 struct isis_adjacency {
        uint8_t snpa[ETH_ALEN];             /* NeighbourSNPAAddress */
        uint8_t sysid[ISIS_SYS_ID_LEN];     /* neighbourSystemIdentifier */
@@ -100,6 +102,7 @@ struct isis_adjacency {
        struct isis_circuit *circuit; /* back pointer */
        uint16_t *mt_set;      /* Topologies this adjacency is valid for */
        unsigned int mt_count; /* Number of entries in mt_set */
+       struct bfd_session *bfd_session;
 };
 
 struct isis_threeway_adj;
@@ -114,6 +117,7 @@ void isis_delete_adj(void *adj);
 void isis_adj_process_threeway(struct isis_adjacency *adj,
                               struct isis_threeway_adj *tw_adj,
                               enum isis_adj_usage adj_usage);
+DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj))
 void isis_adj_state_change(struct isis_adjacency *adj,
                           enum isis_adj_state state, const char *reason);
 void isis_adj_print(struct isis_adjacency *adj);
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
new file mode 100644 (file)
index 0000000..81976f8
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * IS-IS Rout(e)ing protocol - BFD support
+ * Copyright (C) 2018 Christian Franke
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "zclient.h"
+#include "bfd.h"
+
+#include "isisd/isis_bfd.h"
+#include "isisd/isis_zebra.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/fabricd.h"
+
+DEFINE_MTYPE_STATIC(ISISD, BFD_SESSION, "ISIS BFD Session")
+
+struct bfd_session {
+       struct in_addr dst_ip;
+       struct in_addr src_ip;
+       int status;
+};
+
+static struct bfd_session *bfd_session_new(struct in_addr *dst_ip,
+                                          struct in_addr *src_ip)
+{
+       struct bfd_session *rv;
+
+       rv = XCALLOC(MTYPE_BFD_SESSION, sizeof(*rv));
+       rv->dst_ip = *dst_ip;
+       rv->src_ip = *src_ip;
+       return rv;
+}
+
+static void bfd_session_free(struct bfd_session **session)
+{
+       if (!*session)
+               return;
+
+       XFREE(MTYPE_BFD_SESSION, *session);
+       *session = NULL;
+}
+
+static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
+                         int new_status)
+{
+       if (!adj->bfd_session)
+               return;
+
+       if (adj->bfd_session->dst_ip.s_addr != dst->u.prefix4.s_addr)
+               return;
+
+       int old_status = adj->bfd_session->status;
+
+       adj->bfd_session->status = new_status;
+       if (old_status == new_status)
+               return;
+
+       if (isis->debugs & DEBUG_BFD) {
+               char dst_str[INET6_ADDRSTRLEN];
+
+               inet_ntop(AF_INET, &adj->bfd_session->dst_ip,
+                         dst_str, sizeof(dst_str));
+               zlog_debug("ISIS-BFD: Peer %s on %s changed from %s to %s",
+                          dst_str, adj->circuit->interface->name,
+                          bfd_get_status_str(old_status),
+                          bfd_get_status_str(new_status));
+       }
+
+       if (old_status != BFD_STATUS_UP
+           || new_status != BFD_STATUS_DOWN) {
+               return;
+       }
+
+       isis_adj_state_change(adj, ISIS_ADJ_DOWN, "bfd session went down");
+}
+
+static int isis_bfd_interface_dest_update(int command, struct zclient *zclient,
+                                         zebra_size_t length, vrf_id_t vrf_id)
+{
+       struct interface *ifp;
+       struct prefix dst_ip;
+       int status;
+
+       ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, vrf_id);
+       if (!ifp || dst_ip.family != AF_INET)
+               return 0;
+
+       if (isis->debugs & DEBUG_BFD) {
+               char dst_buf[INET6_ADDRSTRLEN];
+
+               inet_ntop(AF_INET, &dst_ip.u.prefix4,
+                         dst_buf, sizeof(dst_buf));
+
+               zlog_debug("ISIS-BFD: Received update for %s on %s: Changed state to %s",
+                          dst_buf, ifp->name, bfd_get_status_str(status));
+       }
+
+       struct isis_circuit *circuit = circuit_scan_by_ifp(ifp);
+
+       if (!circuit)
+               return 0;
+
+       if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+               for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+                       struct list *adjdb = circuit->u.bc.adjdb[level - 1];
+
+                       struct listnode *node, *nnode;
+                       struct isis_adjacency *adj;
+
+                       for (ALL_LIST_ELEMENTS(adjdb, node, nnode, adj))
+                               bfd_adj_event(adj, &dst_ip, status);
+               }
+       } else if (circuit->circ_type == CIRCUIT_T_P2P) {
+               if (circuit->u.p2p.neighbor) {
+                       bfd_adj_event(circuit->u.p2p.neighbor,
+                                     &dst_ip, status);
+               }
+       }
+
+       return 0;
+}
+
+static int isis_bfd_nbr_replay(int command, struct zclient *zclient,
+                              zebra_size_t length, vrf_id_t vrf_id)
+{
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
+       struct listnode *anode;
+       struct isis_area *area;
+
+       if (isis->debugs & DEBUG_BFD)
+               zlog_debug("ISIS-BFD: Got neighbor replay request, resending neighbors.");
+
+       for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+               struct listnode *cnode;
+               struct isis_circuit *circuit;
+
+               for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
+                       isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_UPDATE);
+       }
+
+       if (isis->debugs & DEBUG_BFD)
+               zlog_debug("ISIS-BFD: Done with replay.");
+
+       return 0;
+}
+
+static void (*orig_zebra_connected)(struct zclient *);
+static void isis_bfd_zebra_connected(struct zclient *zclient)
+{
+       if (orig_zebra_connected)
+               orig_zebra_connected(zclient);
+
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+}
+
+static void bfd_debug(struct in_addr *dst, struct in_addr *src,
+                     const char *interface, int command)
+{
+       if (!(isis->debugs & DEBUG_BFD))
+               return;
+
+       char dst_str[INET6_ADDRSTRLEN];
+       char src_str[INET6_ADDRSTRLEN];
+
+       inet_ntop(AF_INET, dst, dst_str, sizeof(dst_str));
+       inet_ntop(AF_INET, src, src_str, sizeof(src_str));
+
+       const char *command_str;
+
+       switch (command) {
+       case ZEBRA_BFD_DEST_REGISTER:
+               command_str = "Register";
+               break;
+       case ZEBRA_BFD_DEST_DEREGISTER:
+               command_str = "Deregister";
+               break;
+       case ZEBRA_BFD_DEST_UPDATE:
+               command_str = "Update";
+               break;
+       default:
+               command_str = "Unknown-Cmd";
+               break;
+       }
+
+       zlog_debug("ISIS-BFD: %s peer %s on %s (src %s)",
+                  command_str, dst_str, interface, src_str);
+}
+
+static void bfd_handle_adj_down(struct isis_adjacency *adj)
+{
+       if (!adj->bfd_session)
+               return;
+
+       bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip,
+                 adj->circuit->interface->name, ZEBRA_BFD_DEST_DEREGISTER);
+
+       bfd_peer_sendmsg(zclient, NULL, AF_INET,
+                        &adj->bfd_session->dst_ip,
+                        &adj->bfd_session->src_ip,
+                        adj->circuit->interface->name,
+                        0, /* ttl */
+                        0, /* multihop */
+                        ZEBRA_BFD_DEST_DEREGISTER,
+                        0, /* set_flag */
+                        VRF_DEFAULT);
+       bfd_session_free(&adj->bfd_session);
+}
+
+static void bfd_handle_adj_up(struct isis_adjacency *adj, int command)
+{
+       struct isis_circuit *circuit = adj->circuit;
+
+       if (!circuit->bfd_info
+           || !circuit->ip_router
+           || !adj->ipv4_address_count)
+               goto out;
+
+       struct list *local_ips = fabricd_ip_addrs(adj->circuit);
+
+       if (!local_ips)
+               goto out;
+
+       struct in_addr *dst_ip = &adj->ipv4_addresses[0];
+       struct prefix_ipv4 *local_ip = listgetdata(listhead(local_ips));
+       struct in_addr *src_ip = &local_ip->prefix;
+
+       if (adj->bfd_session) {
+               if (adj->bfd_session->dst_ip.s_addr != dst_ip->s_addr
+                   || adj->bfd_session->src_ip.s_addr != src_ip->s_addr)
+                       bfd_handle_adj_down(adj);
+       }
+
+       if (!adj->bfd_session)
+               adj->bfd_session = bfd_session_new(dst_ip, src_ip);
+
+       bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip,
+                 circuit->interface->name, command);
+       bfd_peer_sendmsg(zclient, circuit->bfd_info, AF_INET,
+                        &adj->bfd_session->dst_ip,
+                        &adj->bfd_session->src_ip,
+                        circuit->interface->name,
+                        0, /* ttl */
+                        0, /* multihop */
+                        command,
+                        0, /* set flag */
+                        VRF_DEFAULT);
+       return;
+out:
+       bfd_handle_adj_down(adj);
+}
+
+static int bfd_handle_adj_state_change(struct isis_adjacency *adj)
+{
+       if (adj->adj_state == ISIS_ADJ_UP)
+               bfd_handle_adj_up(adj, ZEBRA_BFD_DEST_REGISTER);
+       else
+               bfd_handle_adj_down(adj);
+       return 0;
+}
+
+static void bfd_adj_cmd(struct isis_adjacency *adj, int command)
+{
+       if (adj->adj_state == ISIS_ADJ_UP
+           && command != ZEBRA_BFD_DEST_DEREGISTER) {
+               bfd_handle_adj_up(adj, command);
+       } else {
+               bfd_handle_adj_down(adj);
+       }
+}
+
+void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command)
+{
+       switch (circuit->circ_type) {
+       case CIRCUIT_T_BROADCAST:
+               for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
+                       struct list *adjdb = circuit->u.bc.adjdb[level - 1];
+
+                       struct listnode *node;
+                       struct isis_adjacency *adj;
+
+                       for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
+                               bfd_adj_cmd(adj, command);
+               }
+               break;
+       case CIRCUIT_T_P2P:
+               if (circuit->u.p2p.neighbor)
+                       bfd_adj_cmd(circuit->u.p2p.neighbor, command);
+               break;
+       default:
+               break;
+       }
+}
+
+void isis_bfd_circuit_param_set(struct isis_circuit *circuit,
+                               uint32_t min_rx, uint32_t min_tx,
+                               uint32_t detect_mult, int defaults)
+{
+       int command = 0;
+
+       bfd_set_param(&circuit->bfd_info, min_rx,
+                     min_tx, detect_mult, defaults, &command);
+
+       if (command)
+               isis_bfd_circuit_cmd(circuit, command);
+}
+
+static int bfd_circuit_write_settings(struct isis_circuit *circuit,
+                                     struct vty *vty)
+{
+       struct bfd_info *bfd_info = circuit->bfd_info;
+
+       if (!bfd_info)
+               return 0;
+
+       vty_out(vty, " %s bfd\n", PROTO_NAME);
+       return 1;
+}
+
+void isis_bfd_init(void)
+{
+       bfd_gbl_init();
+
+       orig_zebra_connected = zclient->zebra_connected;
+       zclient->zebra_connected = isis_bfd_zebra_connected;
+       zclient->interface_bfd_dest_update = isis_bfd_interface_dest_update;
+       zclient->bfd_dest_replay = isis_bfd_nbr_replay;
+       hook_register(isis_adj_state_change_hook,
+                     bfd_handle_adj_state_change);
+       hook_register(isis_circuit_config_write,
+                     bfd_circuit_write_settings);
+}
diff --git a/isisd/isis_bfd.h b/isisd/isis_bfd.h
new file mode 100644 (file)
index 0000000..3193f16
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * IS-IS Rout(e)ing protocol - BFD support
+ * Copyright (C) 2018 Christian Franke
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef ISIS_BFD_H
+#define ISIS_BFD_H
+
+struct isis_circuit;
+
+void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command);
+void isis_bfd_circuit_param_set(struct isis_circuit *circuit,
+                               uint32_t min_rx, uint32_t min_tx,
+                               uint32_t detect_mult, int defaults);
+void isis_bfd_init(void);
+
+#endif
+
index 58c6dfa3682a53f64c74ef705e5d418a153d7e4b..74488a1fcd8ee033bbe7c4a5e2673e3085d3936a 100644 (file)
@@ -924,6 +924,10 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty,
        return;
 }
 
+DEFINE_HOOK(isis_circuit_config_write,
+           (struct isis_circuit *circuit, struct vty *vty),
+           (circuit, vty))
+
 int isis_interface_config_write(struct vty *vty)
 {
        struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
@@ -1138,7 +1142,8 @@ int isis_interface_config_write(struct vty *vty)
                                        circuit->passwd.passwd);
                                write++;
                        }
-                       write += circuit_write_mt_settings(circuit, vty);
+                       write += hook_call(isis_circuit_config_write,
+                                          circuit, vty);
                }
                vty_endframe(vty, "!\n");
        }
index ea68767fe0fb35c1bfb5b40ff61631df5918a258..e83424a4addfd668f5f00d7ac30c2ad8dea98248 100644 (file)
@@ -65,6 +65,8 @@ struct isis_p2p_info {
        struct thread *t_send_p2p_hello; /* send P2P IIHs in this thread  */
 };
 
+struct bfd_info;
+
 struct isis_circuit {
        int state;
        uint8_t circuit_id;       /* l1/l2 bcast CircuitID */
@@ -127,6 +129,7 @@ struct isis_circuit {
 #define ISIS_CIRCUIT_FLAPPED_AFTER_SPF 0x01
        uint8_t flags;
        bool disable_threeway_adj;
+       struct bfd_info *bfd_info;
        /*
         * Counters as in 10589--11.2.5.9
         */
@@ -190,4 +193,8 @@ ferr_r isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit,
 int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid,
                                bool enabled);
 
+DECLARE_HOOK(isis_circuit_config_write,
+           (struct isis_circuit *circuit, struct vty *vty),
+           (circuit, vty))
+
 #endif /* _ZEBRA_ISIS_CIRCUIT_H */
index 5dcc0a1324248abc3efe4a7daf8477ee02336726..9f58c24b71be856585f10f5c091f1ff485ab4093 100644 (file)
@@ -216,25 +216,6 @@ void isis_circuit_is_type_set(struct isis_circuit *circuit, int newtype)
  *
  * ***********************************************************************/
 
-void isis_event_adjacency_state_change(struct isis_adjacency *adj, int newstate)
-{
-       /* adjacency state change event.
-        * - the only proto-type was supported */
-
-       /* invalid arguments */
-       if (!adj || !adj->circuit || !adj->circuit->area)
-               return;
-
-       if (isis->debugs & DEBUG_EVENTS)
-               zlog_debug("ISIS-Evt (%s) Adjacency State change",
-                          adj->circuit->area->area_tag);
-
-       /* LSP generation again */
-       lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
-
-       return;
-}
-
 /* events supporting code */
 
 int isis_event_dis_status_change(struct thread *thread)
index c3d8cf046fa6b40396fa3660e03596702c2b25e4..25643f4ededc57f2c8af1122b8eae56e14b14f77 100644 (file)
@@ -31,9 +31,6 @@ void isis_event_circuit_type_change(struct isis_circuit *circuit, int newtype);
 /*
  * Events related to adjacencies
  */
-void isis_event_adjacency_state_change(struct isis_adjacency *adj,
-                                      int newstate);
-
 int isis_event_dis_status_change(struct thread *thread);
 
 /*
index 1258bec064f2e16f18ab3fbd3b6ce3f69d9ed6f4..61ba51ffb84f9ee74b002b8e672cf1dbe4d055ab 100644 (file)
@@ -1997,3 +1997,15 @@ void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)
                fabricd_lsp_flood(lsp);
        }
 }
+
+static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
+{
+       lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
+       return 0;
+}
+
+void lsp_init(void)
+{
+       hook_register(isis_adj_state_change_hook,
+                     lsp_handle_adj_state_change);
+}
index 4e6379447cf5136de7f28ed31a6d95a34812f33d..4beee10081d2cfe5d82b118b62ad423a19228064 100644 (file)
@@ -101,5 +101,6 @@ int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost);
 /* sets SRMflags for all active circuits of an lsp */
 void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set);
 void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit);
+void lsp_init(void);
 
 #endif /* ISIS_LSP */
index 4d6a6da5d602b2b883d4b0ba75055a22bf3d70da..7956ddeaf1aead13f3de7d048f84555f4ae1751f 100644 (file)
@@ -55,6 +55,9 @@
 #include "isisd/isis_te.h"
 #include "isisd/isis_errors.h"
 #include "isisd/isis_vty_common.h"
+#include "isisd/isis_bfd.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_mt.h"
 
 /* Default configuration file name */
 #define ISISD_DEFAULT_CONFIG "isisd.conf"
@@ -213,11 +216,14 @@ int main(int argc, char **argv, char **envp)
        isis_redist_init();
        isis_route_map_init();
        isis_mpls_te_init();
+       lsp_init();
+       mt_init();
 
        /* create the global 'isis' instance */
        isis_new(1);
 
        isis_zebra_init(master);
+       isis_bfd_init();
 
        frr_config_fork();
        frr_run(master);
index e0227f46563314d28e76f1592bc3d350e3f9d786..7493b90d33638a63e8c812c86db1a2c3aa6031f2 100644 (file)
@@ -302,7 +302,8 @@ circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid)
        return setting;
 }
 
-int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty)
+static int circuit_write_mt_settings(struct isis_circuit *circuit,
+                                    struct vty *vty)
 {
        int written = 0;
        struct listnode *node;
@@ -551,3 +552,9 @@ void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
        tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id,
                        metric, subtlvs, subtlv_len);
 }
+
+void mt_init(void)
+{
+       hook_register(isis_circuit_config_write,
+                     circuit_write_mt_settings);
+}
index 8c57d24afa4dae95fca6c9afaed6dae0869e677b..515b63f50f024c7329c233c252600714db786f72 100644 (file)
@@ -109,7 +109,6 @@ void circuit_mt_init(struct isis_circuit *circuit);
 void circuit_mt_finish(struct isis_circuit *circuit);
 struct isis_circuit_mt_setting *
 circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid);
-int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty);
 struct isis_circuit_mt_setting **
 circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count);
 bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
@@ -122,4 +121,5 @@ void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
 void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
                     uint8_t *id, uint32_t metric, uint8_t *subtlvs,
                     uint8_t subtlv_len);
+void mt_init(void);
 #endif
index 2b98a88b342233637799b33412041c61b9df185c..c211763042821b8f2664b5bcf4a5e2df1eb59a87 100644 (file)
 
 #include "command.h"
 #include "spf_backoff.h"
+#include "bfd.h"
 
 #include "isis_circuit.h"
 #include "isis_csm.h"
 #include "isis_misc.h"
 #include "isis_mt.h"
 #include "isisd.h"
+#include "isis_bfd.h"
 #include "isis_vty_common.h"
 
 struct isis_circuit *isis_circuit_lookup(struct vty *vty)
@@ -498,6 +500,49 @@ DEFUN (no_circuit_topology,
        return isis_circuit_mt_enabled_set(circuit, mtid, false);
 }
 
+DEFUN (isis_bfd,
+       isis_bfd_cmd,
+       PROTO_NAME " bfd",
+       PROTO_HELP
+       "Enable BFD support\n")
+{
+       struct isis_circuit *circuit = isis_circuit_lookup(vty);
+
+       if (!circuit)
+               return CMD_ERR_NO_MATCH;
+
+       if (circuit->bfd_info
+           && CHECK_FLAG(circuit->bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
+               return CMD_SUCCESS;
+       }
+
+       isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
+                                  BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_bfd,
+       no_isis_bfd_cmd,
+       "no " PROTO_NAME " bfd",
+       NO_STR
+       PROTO_HELP
+       "Disables BFD support\n"
+)
+{
+       struct isis_circuit *circuit = isis_circuit_lookup(vty);
+
+       if (!circuit)
+               return CMD_ERR_NO_MATCH;
+
+       if (!circuit->bfd_info)
+               return CMD_SUCCESS;
+
+       isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
+       bfd_info_free(&circuit->bfd_info);
+       return CMD_SUCCESS;
+}
+
 DEFUN (set_overload_bit,
        set_overload_bit_cmd,
        "set-overload-bit",
@@ -930,6 +975,9 @@ void isis_vty_init(void)
        install_element(INTERFACE_NODE, &circuit_topology_cmd);
        install_element(INTERFACE_NODE, &no_circuit_topology_cmd);
 
+       install_element(INTERFACE_NODE, &isis_bfd_cmd);
+       install_element(INTERFACE_NODE, &no_isis_bfd_cmd);
+
        install_element(ROUTER_NODE, &set_overload_bit_cmd);
        install_element(ROUTER_NODE, &no_set_overload_bit_cmd);
 
index 4fbcf87217eef265857b036d5196d37fb870b6e9..20c10d0b2372936119f253a61387104b3515340e 100644 (file)
@@ -27,6 +27,8 @@ extern struct zclient *zclient;
 void isis_zebra_init(struct thread_master *);
 void isis_zebra_stop(void);
 
+struct isis_route_info;
+
 void isis_zebra_route_update(struct prefix *prefix,
                             struct prefix_ipv6 *src_p,
                             struct isis_route_info *route_info);
index e5e43c4b7ded8de88fbe7ef3a1da66c1a774173b..94e6a63855b30758d4b6d107efb68f1624a99b5e 100644 (file)
@@ -746,6 +746,8 @@ void print_debug(struct vty *vty, int flags, int onoff)
                vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs);
        if (flags & DEBUG_FABRICD_FLOODING)
                vty_out(vty, "OpenFabric Flooding debugging is %s\n", onoffs);
+       if (flags & DEBUG_BFD)
+               vty_out(vty, "IS-IS BFD debugging is %s\n", onoffs);
 }
 
 DEFUN_NOSH (show_debugging,
@@ -831,6 +833,10 @@ static int config_write_debug(struct vty *vty)
                vty_out(vty, "debug " PROTO_NAME " flooding\n");
                write++;
        }
+       if (flags & DEBUG_BFD) {
+               vty_out(vty, "debug " PROTO_NAME " bfd\n");
+               write++;
+       }
        write += spf_backoff_write_config(vty);
 
        return write;
@@ -1214,6 +1220,33 @@ DEFUN (no_debug_isis_lsp_sched,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_isis_bfd,
+       debug_isis_bfd_cmd,
+       "debug " PROTO_NAME " bfd",
+       DEBUG_STR
+       PROTO_HELP
+       PROTO_NAME " interaction with BFD\n")
+{
+       isis->debugs |= DEBUG_BFD;
+       print_debug(vty, DEBUG_BFD, 1);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_bfd,
+       no_debug_isis_bfd_cmd,
+       "no debug " PROTO_NAME " bfd",
+       NO_STR
+       UNDEBUG_STR
+       PROTO_HELP
+       PROTO_NAME " interaction with BFD\n")
+{
+       isis->debugs &= ~DEBUG_BFD;
+       print_debug(vty, DEBUG_BFD, 0);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (show_hostname,
        show_hostname_cmd,
        "show " PROTO_NAME " hostname",
@@ -2215,6 +2248,8 @@ void isis_init()
        install_element(ENABLE_NODE, &no_debug_isis_lsp_gen_cmd);
        install_element(ENABLE_NODE, &debug_isis_lsp_sched_cmd);
        install_element(ENABLE_NODE, &no_debug_isis_lsp_sched_cmd);
+       install_element(ENABLE_NODE, &debug_isis_bfd_cmd);
+       install_element(ENABLE_NODE, &no_debug_isis_bfd_cmd);
 
        install_element(CONFIG_NODE, &debug_isis_adj_cmd);
        install_element(CONFIG_NODE, &no_debug_isis_adj_cmd);
@@ -2244,6 +2279,8 @@ void isis_init()
        install_element(CONFIG_NODE, &no_debug_isis_lsp_gen_cmd);
        install_element(CONFIG_NODE, &debug_isis_lsp_sched_cmd);
        install_element(CONFIG_NODE, &no_debug_isis_lsp_sched_cmd);
+       install_element(CONFIG_NODE, &debug_isis_bfd_cmd);
+       install_element(CONFIG_NODE, &no_debug_isis_bfd_cmd);
 
        install_element(CONFIG_NODE, &router_isis_cmd);
        install_element(CONFIG_NODE, &no_router_isis_cmd);
index 864021428aa885dfbf07d3eae33e98dec79f4ed7..7572f551743758ffc6f09a95cedf2e360f8cd733 100644 (file)
@@ -211,6 +211,7 @@ extern struct thread_master *master;
 #define DEBUG_LSP_GEN                    (1<<13)
 #define DEBUG_LSP_SCHED                  (1<<14)
 #define DEBUG_FABRICD_FLOODING           (1<<15)
+#define DEBUG_BFD                        (1<<16)
 
 #define lsp_debug(...)                                                         \
        do {                                                                   \
index 7571255e59251cc0b22c135da34fd2967b9bd3c0..552bc49b80ebe82e2fea6a8036c7e2e673da6e23 100644 (file)
@@ -27,6 +27,7 @@ endif
 noinst_HEADERS += \
        isisd/dict.h \
        isisd/isis_adjacency.h \
+       isisd/isis_bfd.h \
        isisd/isis_circuit.h \
        isisd/isis_common.h \
        isisd/isis_constants.h \
@@ -60,6 +61,7 @@ noinst_HEADERS += \
 LIBISIS_SOURCES = \
        isisd/dict.c \
        isisd/isis_adjacency.c \
+       isisd/isis_bfd.c \
        isisd/isis_circuit.c \
        isisd/isis_csm.c \
        isisd/isis_dr.c \
index b711241611fe9b62a758fd1f34a675f7c9a17330..e4a4adba05b19f1e0b97f166d14a4b7104980f8a 100644 (file)
@@ -1030,8 +1030,7 @@ int zebra_ptm_bfd_client_deregister(struct zserv *client)
        char tmp_buf[64];
        int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
 
-       if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP
-           && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM)
+       if (!IS_BFD_ENABLED_PROTOCOL(proto))
                return 0;
 
        if (IS_ZEBRA_DEBUG_EVENT)
@@ -1310,17 +1309,8 @@ static void zebra_ptm_send_clients(struct stream *msg)
 
        /* Send message to all running client daemons. */
        for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
-               switch (client->proto) {
-               case ZEBRA_ROUTE_BGP:
-               case ZEBRA_ROUTE_OSPF:
-               case ZEBRA_ROUTE_OSPF6:
-               case ZEBRA_ROUTE_PIM:
-                       break;
-
-               default:
-                       /* NOTHING: skip this daemon. */
+               if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
-               }
 
                zserv_send_message(client, msg);
 
@@ -1341,23 +1331,9 @@ static int _zebra_ptm_bfd_client_deregister(struct zserv *zs)
        struct stream *msg;
        struct ptm_process *pp;
 
-       /* Filter daemons that must receive this treatment. */
-       switch (zs->proto) {
-       case ZEBRA_ROUTE_BGP:
-       case ZEBRA_ROUTE_OSPF:
-       case ZEBRA_ROUTE_OSPF6:
-       case ZEBRA_ROUTE_PIM:
-               break;
-
-       case ZEBRA_ROUTE_BFD:
-               /* Don't try to send BFDd messages to itself. */
+       if (!IS_BFD_ENABLED_PROTOCOL(zs->proto))
                return 0;
 
-       default:
-               /* Unsupported daemon. */
-               return 0;
-       }
-
        /* Find daemon pid by zebra connection pointer. */
        pp = pp_lookup_byzs(zs);
        if (pp == NULL) {
index ada4f7b4f7dad4ca62eab4dd0d4ca6a64caf5ed0..d0cdaf0bce8781f7409d297a0c041ad43d42a973 100644 (file)
@@ -59,6 +59,15 @@ struct zebra_ptm_cb {
 #define ZEBRA_IF_PTM_ENABLE_ON     1
 #define ZEBRA_IF_PTM_ENABLE_UNSPEC 2
 
+#define IS_BFD_ENABLED_PROTOCOL(protocol) ( \
+       (protocol) == ZEBRA_ROUTE_BGP || \
+       (protocol) == ZEBRA_ROUTE_OSPF || \
+       (protocol) == ZEBRA_ROUTE_OSPF6 || \
+       (protocol) == ZEBRA_ROUTE_ISIS || \
+       (protocol) == ZEBRA_ROUTE_PIM || \
+       (protocol) == ZEBRA_ROUTE_OPENFABRIC \
+)
+
 void zebra_ptm_init(void);
 void zebra_ptm_finish(void);
 int zebra_ptm_connect(struct thread *t);
index 815f61d157a083b4dd42789ea1e35053d6125aaf..420105198b89634a4913fc7c145e15b525aeb727 100644 (file)
@@ -24,6 +24,7 @@
 #include "stream.h"
 #include "zebra/zserv.h"
 #include "zebra/zapi_msg.h"
+#include "zebra/zebra_ptm.h"
 #include "zebra/zebra_ptm_redistribute.h"
 #include "zebra/zebra_memory.h"
 
@@ -76,11 +77,7 @@ void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp,
        struct zserv *client;
 
        for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
-               /* Supporting for OSPF, BGP and PIM */
-               if (client->proto != ZEBRA_ROUTE_OSPF
-                   && client->proto != ZEBRA_ROUTE_BGP
-                   && client->proto != ZEBRA_ROUTE_OSPF6
-                   && client->proto != ZEBRA_ROUTE_PIM)
+               if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
 
                /* Notify to the protocol daemons. */
@@ -110,11 +107,7 @@ void zebra_bfd_peer_replay_req(void)
        struct zserv *client;
 
        for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
-               /* Supporting for BGP */
-               if ((client->proto != ZEBRA_ROUTE_BGP)
-                   && (client->proto != ZEBRA_ROUTE_OSPF)
-                   && (client->proto != ZEBRA_ROUTE_OSPF6)
-                   && (client->proto != ZEBRA_ROUTE_PIM))
+               if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
 
                /* Notify to the protocol daemons. */