1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* RIP BFD integration.
* Copyright (C) 2021-2023 Network Device Education Foundation, Inc. ("NetDEF")
*/
#include <zebra.h>
#include "lib/zclient.h"
#include "lib/bfd.h"
#include "ripd/ripd.h"
#include "ripd/rip_bfd.h"
#include "ripd/rip_debug.h"
DEFINE_MTYPE(RIPD, RIP_BFD_PROFILE, "RIP BFD profile name");
extern struct zclient *zclient;
static const char *rip_bfd_interface_profile(struct rip_interface *ri)
{
struct rip *rip = ri->rip;
if (ri->bfd.profile)
return ri->bfd.profile;
if (rip->default_bfd_profile)
return rip->default_bfd_profile;
return NULL;
}
static void rip_bfd_session_change(struct bfd_session_params *bsp,
const struct bfd_session_status *bss,
void *arg)
{
struct rip_peer *rp = arg;
/* BFD peer went down. */
if (bss->state == BFD_STATUS_DOWN &&
bss->previous_state == BFD_STATUS_UP) {
if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s: peer %pI4: BFD Down", __func__,
&rp->addr);
rip_peer_delete_routes(rp);
listnode_delete(rp->rip->peer_list, rp);
rip_peer_free(rp);
return;
}
/* BFD peer went up. */
if (bss->state == BSS_UP && bss->previous_state == BSS_DOWN)
if (IS_RIP_DEBUG_EVENT)
zlog_debug("%s: peer %pI4: BFD Up", __func__,
&rp->addr);
}
void rip_bfd_session_update(struct rip_peer *rp)
{
struct rip_interface *ri = rp->ri;
/* BFD configuration was removed. */
if (ri == NULL || !ri->bfd.enabled) {
bfd_sess_free(&rp->bfd_session);
return;
}
/* New BFD session. */
if (rp->bfd_session == NULL) {
rp->bfd_session = bfd_sess_new(rip_bfd_session_change, rp);
bfd_sess_set_ipv4_addrs(rp->bfd_session, NULL, &rp->addr);
bfd_sess_set_interface(rp->bfd_session, ri->ifp->name);
bfd_sess_set_vrf(rp->bfd_session, rp->rip->vrf->vrf_id);
}
/* Set new configuration. */
bfd_sess_set_timers(rp->bfd_session, BFD_DEF_DETECT_MULT,
BFD_DEF_MIN_RX, BFD_DEF_MIN_TX);
bfd_sess_set_profile(rp->bfd_session, rip_bfd_interface_profile(ri));
bfd_sess_install(rp->bfd_session);
}
void rip_bfd_interface_update(struct rip_interface *ri)
{
struct rip *rip;
struct rip_peer *rp;
struct listnode *node;
rip = ri->rip;
if (!rip)
return;
for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, rp)) {
if (rp->ri != ri)
continue;
rip_bfd_session_update(rp);
}
}
void rip_bfd_instance_update(struct rip *rip)
{
struct interface *ifp;
FOR_ALL_INTERFACES (rip->vrf, ifp) {
struct rip_interface *ri;
ri = ifp->info;
if (!ri)
continue;
rip_bfd_interface_update(ri);
}
}
void rip_bfd_init(struct event_loop *tm)
{
bfd_protocol_integration_init(zclient, tm);
}
|