diff options
-rw-r--r-- | bfdd/bfd.c | 46 | ||||
-rw-r--r-- | bfdd/bfd.h | 4 | ||||
-rw-r--r-- | bfdd/bfdd_northbound.c | 4 | ||||
-rw-r--r-- | bfdd/control.c | 4 | ||||
-rw-r--r-- | bfdd/ptm_adapter.c | 13 | ||||
-rw-r--r-- | bgpd/bgp_bfd.c | 3 | ||||
-rw-r--r-- | isisd/isis_bfd.c | 3 | ||||
-rw-r--r-- | lib/bfd.c | 2 | ||||
-rw-r--r-- | lib/bfd.h | 14 | ||||
-rw-r--r-- | ospf6d/ospf6_bfd.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_bfd.c | 2 | ||||
-rw-r--r-- | pimd/pim_bfd.c | 2 |
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; @@ -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"; @@ -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; |