/*
* 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
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 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;
*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)
{
if (isis->debugs & DEBUG_BFD) {
char dst_buf[INET6_ADDRSTRLEN];
+
inet_ntop(AF_INET, &dst_ip.u.prefix4,
dst_buf, sizeof(dst_buf));
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;
}
goto out;
struct list *local_ips = fabricd_ip_addrs(adj->circuit);
+
if (!local_ips)
goto out;
struct listnode *node;
struct isis_adjacency *adj;
+
for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
bfd_adj_cmd(adj, command);
}
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;
}