]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_bfd.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / isisd / isis_bfd.c
index 6f89d9873592b7329c4219ab47657ebc56c46ff6..81976f8dd293d33bf5d4475237122ac8cfb855e1 100644 (file)
@@ -1,19 +1,16 @@
 /*
  * IS-IS Rout(e)ing protocol - BFD support
- *
  * Copyright (C) 2018 Christian Franke
  *
- * This file is part of FreeRangeRouting (FRR)
- *
- * FRR 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, or (at your option) any
- * later version.
+ * 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.
  *
- * FRR 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.
+ * 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
@@ -38,6 +35,7 @@ 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,
@@ -45,7 +43,7 @@ static struct bfd_session *bfd_session_new(struct in_addr *dst_ip,
 {
        struct bfd_session *rv;
 
-       rv = XMALLOC(MTYPE_BFD_SESSION, sizeof(*rv));
+       rv = XCALLOC(MTYPE_BFD_SESSION, sizeof(*rv));
        rv->dst_ip = *dst_ip;
        rv->src_ip = *src_ip;
        return rv;
@@ -60,6 +58,40 @@ static void bfd_session_free(struct 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)
 {
@@ -73,6 +105,7 @@ static int isis_bfd_interface_dest_update(int command, struct zclient *zclient,
 
        if (isis->debugs & DEBUG_BFD) {
                char dst_buf[INET6_ADDRSTRLEN];
+
                inet_ntop(AF_INET, &dst_ip.u.prefix4,
                          dst_buf, sizeof(dst_buf));
 
@@ -80,6 +113,28 @@ static int isis_bfd_interface_dest_update(int command, struct zclient *zclient,
                           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;
 }
 
@@ -180,6 +235,7 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj, int command)
                goto out;
 
        struct list *local_ips = fabricd_ip_addrs(adj->circuit);
+
        if (!local_ips)
                goto out;
 
@@ -240,6 +296,7 @@ void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command)
 
                        struct listnode *node;
                        struct isis_adjacency *adj;
+
                        for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
                                bfd_adj_cmd(adj, command);
                }
@@ -274,14 +331,7 @@ static int bfd_circuit_write_settings(struct isis_circuit *circuit,
        if (!bfd_info)
                return 0;
 
-#if HAVE_BFDD == 0
-       if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
-               vty_out(vty, " %s bfd %" PRIu8 " %" PRIu32 " %" PRIu32 "\n",
-                       PROTO_NAME, bfd_info->detect_mult,
-                       bfd_info->required_min_rx, bfd_info->desired_min_tx);
-       } else
-#endif
-               vty_out(vty, " %s bfd\n", PROTO_NAME);
+       vty_out(vty, " %s bfd\n", PROTO_NAME);
        return 1;
 }