summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c46
-rw-r--r--bfdd/bfd.h4
-rw-r--r--bfdd/bfdd_northbound.c4
-rw-r--r--bfdd/control.c4
-rw-r--r--bfdd/ptm_adapter.c13
-rw-r--r--bgpd/bgp_bfd.c3
-rw-r--r--isisd/isis_bfd.c3
-rw-r--r--lib/bfd.c2
-rw-r--r--lib/bfd.h14
-rw-r--r--ospf6d/ospf6_bfd.c2
-rw-r--r--ospfd/ospf_bfd.c2
-rw-r--r--pimd/pim_bfd.c2
12 files changed, 78 insertions, 21 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index feb9827ce..50c46fbd3 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -49,6 +49,8 @@ static void bs_admin_down_handler(struct bfd_session *bs, int nstate);
static void bs_down_handler(struct bfd_session *bs, int nstate);
static void bs_init_handler(struct bfd_session *bs, int nstate);
static void bs_up_handler(struct bfd_session *bs, int nstate);
+static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
+ uint8_t diag);
/* Zeroed array with the size of an IPv6 address. */
struct in6_addr zero_addr;
@@ -307,7 +309,7 @@ void ptm_bfd_sess_up(struct bfd_session *bfd)
/* Start sending control packets with poll bit immediately. */
ptm_bfd_snd(bfd, 0);
- control_notify(bfd);
+ control_notify(bfd, bfd->ses_state);
if (old_state != bfd->ses_state) {
bfd->stats.session_up++;
@@ -335,7 +337,7 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
/* only signal clients when going from up->down state */
if (old_state == PTM_BFD_UP)
- control_notify(bfd);
+ control_notify(bfd, PTM_BFD_DOWN);
/* Stop echo packet transmission if they are active */
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
@@ -570,7 +572,7 @@ skip_echo:
/* Change and notify state change. */
bs->ses_state = PTM_BFD_ADM_DOWN;
- control_notify(bs);
+ control_notify(bs, bs->ses_state);
/* Don't try to send packets with a disabled session. */
if (bs->sock != -1)
@@ -584,7 +586,7 @@ skip_echo:
/* Change and notify state change. */
bs->ses_state = PTM_BFD_DOWN;
- control_notify(bs);
+ control_notify(bs, bs->ses_state);
/* Enable all timers. */
bfd_recvtimer_update(bs);
@@ -856,10 +858,46 @@ static void bs_init_handler(struct bfd_session *bs, int nstate)
}
}
+static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
+ uint8_t diag)
+{
+ int old_state = bfd->ses_state;
+
+ bfd->local_diag = diag;
+ bfd->discrs.remote_discr = 0;
+ bfd->ses_state = PTM_BFD_DOWN;
+ bfd->polling = 0;
+ bfd->demand_mode = 0;
+ monotime(&bfd->downtime);
+
+ /* Slow down the control packets, the connection is down. */
+ bs_set_slow_timers(bfd);
+
+ /* only signal clients when going from up->down state */
+ if (old_state == PTM_BFD_UP)
+ control_notify(bfd, PTM_BFD_ADM_DOWN);
+
+ /* Stop echo packet transmission if they are active */
+ if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
+ ptm_bfd_echo_stop(bfd);
+
+ if (old_state != bfd->ses_state) {
+ bfd->stats.session_down++;
+
+ log_info("state-change: [%s] %s -> %s reason:%s",
+ bs_to_string(bfd), state_list[old_state].str,
+ state_list[bfd->ses_state].str,
+ get_diag_str(bfd->local_diag));
+ }
+}
+
static void bs_up_handler(struct bfd_session *bs, int nstate)
{
switch (nstate) {
case PTM_BFD_ADM_DOWN:
+ bs_neighbour_admin_down_handler(bs, BD_ADMIN_DOWN);
+ break;
+
case PTM_BFD_DOWN:
/* Peer lost or asked to shutdown connection. */
ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index cdec78d12..89f97d2e3 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -369,7 +369,7 @@ TAILQ_HEAD(bcslist, bfd_control_socket);
int control_init(const char *path);
void control_shutdown(void);
-int control_notify(struct bfd_session *bs);
+int control_notify(struct bfd_session *bs, uint8_t notify_state);
int control_notify_config(const char *op, struct bfd_session *bs);
int control_accept(struct thread *t);
@@ -632,7 +632,7 @@ void bfdd_sessions_enable_vrf(struct vrf *vrf);
void bfdd_sessions_disable_vrf(struct vrf *vrf);
void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf);
-int ptm_bfd_notify(struct bfd_session *bs);
+int ptm_bfd_notify(struct bfd_session *bs, uint8_t notify_state);
/*
diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c
index 7cd2fb6b9..b8a7e9555 100644
--- a/bfdd/bfdd_northbound.c
+++ b/bfdd/bfdd_northbound.c
@@ -405,7 +405,7 @@ static int bfdd_bfd_sessions_single_hop_administrative_down_modify(
/* Change and notify state change. */
bs->ses_state = PTM_BFD_DOWN;
- control_notify(bs);
+ control_notify(bs, bs->ses_state);
/* Enable all timers. */
bfd_recvtimer_update(bs);
@@ -428,7 +428,7 @@ static int bfdd_bfd_sessions_single_hop_administrative_down_modify(
/* Change and notify state change. */
bs->ses_state = PTM_BFD_ADM_DOWN;
- control_notify(bs);
+ control_notify(bs, bs->ses_state);
ptm_bfd_snd(bs, 0);
}
diff --git a/bfdd/control.c b/bfdd/control.c
index c308d647d..5c5421c04 100644
--- a/bfdd/control.c
+++ b/bfdd/control.c
@@ -774,13 +774,13 @@ static void _control_notify(struct bfd_control_socket *bcs,
control_queue_enqueue(bcs, bcm);
}
-int control_notify(struct bfd_session *bs)
+int control_notify(struct bfd_session *bs, uint8_t notify_state)
{
struct bfd_control_socket *bcs;
struct bfd_notify_peer *bnp;
/* Notify zebra listeners as well. */
- ptm_bfd_notify(bs);
+ ptm_bfd_notify(bs, notify_state);
/*
* PERFORMANCE: reuse the bfd_control_msg allocated data for
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index ae6d04e77..2677eb31f 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -153,7 +153,7 @@ static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
return 0;
}
-int ptm_bfd_notify(struct bfd_session *bs)
+int ptm_bfd_notify(struct bfd_session *bs, uint8_t notify_state)
{
struct stream *msg;
@@ -204,12 +204,15 @@ int ptm_bfd_notify(struct bfd_session *bs)
_ptm_msg_address(msg, bs->key.family, &bs->key.peer);
/* BFD status */
- switch (bs->ses_state) {
+ switch (notify_state) {
case PTM_BFD_UP:
stream_putl(msg, BFD_STATUS_UP);
break;
case PTM_BFD_ADM_DOWN:
+ stream_putl(msg, BFD_STATUS_ADMIN_DOWN);
+ break;
+
case PTM_BFD_DOWN:
case PTM_BFD_INIT:
stream_putl(msg, BFD_STATUS_DOWN);
@@ -432,7 +435,7 @@ static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id)
return;
}
- ptm_bfd_notify(bs);
+ ptm_bfd_notify(bs, bs->ses_state);
}
static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
@@ -461,6 +464,10 @@ static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
if (bs->refcount ||
BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
return;
+
+ bs->ses_state = PTM_BFD_ADM_DOWN;
+ ptm_bfd_snd(bs, 0);
+
ptm_bfd_sess_del(&bpc);
}
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 57fef8e91..0ed6057ea 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -282,7 +282,8 @@ static void bgp_bfd_peer_status_update(struct peer *peer, int status,
return;
old_status = bfd_info->status;
- bfd_info->status = status;
+ BFD_SET_CLIENT_STATUS(bfd_info->status, status);
+
bfd_info->last_update = bgp_clock();
if (status != old_status) {
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index 8fc7997d7..cf4b84179 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -118,7 +118,8 @@ static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
int old_status = adj->bfd_session->status;
- adj->bfd_session->status = new_status;
+ BFD_SET_CLIENT_STATUS(adj->bfd_session->status, new_status);
+
if (old_status == new_status)
return;
diff --git a/lib/bfd.c b/lib/bfd.c
index 00dbd1b3d..ffb3cbc1f 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -315,6 +315,8 @@ const char *bfd_get_status_str(int status)
return "Down";
case BFD_STATUS_UP:
return "Up";
+ case BFD_STATUS_ADMIN_DOWN:
+ return "Admin Down";
case BFD_STATUS_UNKNOWN:
default:
return "Unknown";
diff --git a/lib/bfd.h b/lib/bfd.h
index e4781f4ea..7f5d11150 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -51,9 +51,17 @@ struct bfd_gbl {
#define BFD_FLAG_BFD_CBIT_ON (1 << 3) /* Peer registered with CBIT set to on */
#define BFD_FLAG_BFD_CHECK_CONTROLPLANE (1 << 4) /* BFD and controlplane daemon are linked */
-#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
-#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */
-#define BFD_STATUS_UP (1 << 2) /* BFD session status is up */
+#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
+#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */
+#define BFD_STATUS_UP (1 << 2) /* BFD session status is up */
+#define BFD_STATUS_ADMIN_DOWN (1 << 3) /* BFD session is admin down */
+
+#define BFD_SET_CLIENT_STATUS(current_status, new_status) \
+ do { \
+ (current_status) = \
+ (((new_status) == BFD_STATUS_ADMIN_DOWN) ? \
+ BFD_STATUS_DOWN : (new_status));\
+ } while (0)
enum bfd_sess_type {
BFD_TYPE_NOT_CONFIGURED,
diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c
index f0500601b..4e7a0050a 100644
--- a/ospf6d/ospf6_bfd.c
+++ b/ospf6d/ospf6_bfd.c
@@ -236,7 +236,7 @@ static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
continue;
old_status = bfd_info->status;
- bfd_info->status = status;
+ BFD_SET_CLIENT_STATUS(bfd_info->status, status);
monotime(&tv);
bfd_info->last_update = tv.tv_sec;
diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c
index a17975270..73802ce13 100644
--- a/ospfd/ospf_bfd.c
+++ b/ospfd/ospf_bfd.c
@@ -240,7 +240,7 @@ static int ospf_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
continue;
old_status = bfd_info->status;
- bfd_info->status = status;
+ BFD_SET_CLIENT_STATUS(bfd_info->status, status);
monotime(&tv);
bfd_info->last_update = tv.tv_sec;
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 87d0f9fa2..01a798085 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -270,7 +270,7 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
continue;
}
old_status = bfd_info->status;
- bfd_info->status = status;
+ BFD_SET_CLIENT_STATUS(bfd_info->status, status);
monotime(&tv);
bfd_info->last_update = tv.tv_sec;