mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-11-02 23:52:33 +00:00
Merge pull request #3137 from opensourcerouting/feature/isis-bfd
Feature: BFD for IS-IS
This commit is contained in:
commit
b0ecf336f3
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
350
isisd/isis_bfd.c
Normal file
350
isisd/isis_bfd.c
Normal file
@ -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);
|
||||
}
|
||||
31
isisd/isis_bfd.h
Normal file
31
isisd/isis_bfd.h
Normal file
@ -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
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -28,12 +28,14 @@
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 { \
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user