From: radhika Date: Mon, 9 May 2016 03:11:18 +0000 (-0700) Subject: zebra - BFD client de-registration support X-Git-Tag: frr-2.0-rc1~930 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=567b877d7ff2c04ccf62bca75338cec7a560f184;p=matthieu%2Ffrr.git zebra - BFD client de-registration support CM-10680 Issue: When BGP daemon is stopped, all the BGP BFD sessions are not getting deleted from PTM. Root cause: BGP daemon stop causes BFD de-register message to be sent for every peer on which BFD is enabled. But, all the de-register messages from bgpd to zebra are not processed before the socket close. This results in some stale BGP BFD sessions. Fix: Support for client de-register message has been added in PTM/BFD. Changes in Quagga to support BFD client de-registrations: − The BFD clients de-registration is sent directly from zebra daemon when zebra client (bgpd, ospfd and ospf6d) socket close is detected. − Introduced a BFD flag for the zebra clients to prevent BFD de-registration messages from being sent to zebra daemon when the client is shutting down. This reduces the BFD messaging. CM-10540 Issue: Invalid ptm status “fail” instead of “n/a” being displayed for VRF interfaces. Root cause: ptm status is not being initialized to “unknown” status when VRF interface is added or changed. The uninitialized value is ‘0’ which is the value for “fail” Fix: Initialized the ptm status to the correct value. Signed-off-by: Radhika Mahankali Reviewed-by: Donald Sharp Reviewed-by: Kanna Rajagopal Ticket: CM-10680, CM-10540 Reviewed By: CCR-4653 Testing Done: PTM smoke, BGP smoke and ptmd_test.py:TestMultipleAddrsIntfOspfBgp --- diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index da50fd2bae..b64fbee04d 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -698,6 +698,8 @@ DEFUN_HIDDEN (no_neighbor_bfd_type, void bgp_bfd_init(void) { + bfd_gbl_init(); + /* Initialize BFD client functions */ zclient->interface_bfd_dest_update = bgp_bfd_dest_update; zclient->bfd_dest_replay = bgp_bfd_dest_replay; diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 656f49d183..271e1d97bb 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "queue.h" #include "vrf.h" +#include "bfd.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" @@ -229,6 +230,8 @@ bgp_exit (int status) /* it only makes sense for this to be called on a clean exit */ assert (status == 0); + bfd_gbl_exit(); + bgp_close(); if (retain_mode) diff --git a/lib/bfd.c b/lib/bfd.c index d48dc651c6..2116fa5c1f 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -34,6 +34,25 @@ #include "bfd.h" int bfd_debug = 0; +struct bfd_gbl bfd_gbl; + +/* + * bfd_gbl_init - Initialize the BFD global structure + */ +void +bfd_gbl_init(void) +{ + memset(&bfd_gbl, 0, sizeof (struct bfd_gbl)); +} + +/* + * bfd_gbl_exit - Called when daemon exits + */ +void +bfd_gbl_exit(void) +{ + SET_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN); +} /* * bfd_info_create - Allocate the BFD information @@ -129,6 +148,14 @@ bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info, int ret; int len; + /* Individual reg/dereg messages are supressed during shutdown. */ + if (CHECK_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) + { + if (bfd_debug) + zlog_debug("%s: Suppressing BFD peer reg/dereg messages", __FUNCTION__); + return; + } + /* Check socket. */ if (!zclient || zclient->sock < 0) { diff --git a/lib/bfd.h b/lib/bfd.h index 31e542d8b7..bbe96b07b4 100644 --- a/lib/bfd.h +++ b/lib/bfd.h @@ -41,6 +41,12 @@ #define BFD_MIN_DETECT_MULT 2 #define BFD_MAX_DETECT_MULT 255 +#define BFD_GBL_FLAG_IN_SHUTDOWN (1 << 0) /* The daemon in shutdown */ +struct bfd_gbl +{ + u_int16_t flags; +}; + #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ #define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ #define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */ @@ -107,4 +113,10 @@ bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, extern void bfd_client_sendmsg (struct zclient *zclient, int command); +extern void +bfd_gbl_init(void); + +extern void +bfd_gbl_exit(void); + #endif /* _ZEBRA_BFD_H */ diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index adcfcbf19c..503c7e0cd7 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -410,6 +410,8 @@ DEFUN (no_ipv6_ospf6_bfd, void ospf6_bfd_init(void) { + bfd_gbl_init(); + /* Initialize BFD client functions */ zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update; zclient->bfd_dest_replay = ospf6_bfd_nbr_replay; diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 9a73ccc4b8..52dc6677f0 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -37,6 +37,7 @@ #include "sigevent.h" #include "zclient.h" #include "vrf.h" +#include "bfd.h" #include "ospf6d.h" #include "ospf6_top.h" @@ -144,6 +145,8 @@ ospf6_exit (int status) if (ospf6) ospf6_delete (ospf6); + bfd_gbl_exit(); + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) if (ifp->info != NULL) ospf6_interface_delete(ifp->info); diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index e9c6bfd8e7..ec486c4688 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -441,6 +441,8 @@ ALIAS (no_ip_ospf_bfd, void ospf_bfd_init(void) { + bfd_gbl_init(); + /* Initialize BFD client functions */ zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update; zclient->bfd_dest_replay = ospf_bfd_nbr_replay; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 3bb7148242..91702c34b5 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "zclient.h" #include "plist.h" #include "sockopt.h" +#include "bfd.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -468,6 +469,7 @@ ospf_terminate (void) if (listcount(om->ospf) == 0) exit(0); + bfd_gbl_exit(); for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf)) ospf_finish (ospf); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0c7d72130a..50a269dbc6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -47,6 +47,7 @@ #include "zebra/interface.h" #include "zebra/debug.h" #include "zebra/rtadv.h" +#include "zebra/zebra_ptm.h" #include "rt_netlink.h" @@ -684,6 +685,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Hardware type and address. */ ifp->hw_type = ifi->ifi_type; @@ -1359,6 +1361,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; netlink_interface_update_hw_addr (tb, ifp); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 731bd3562b..bf6afb0216 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -48,6 +48,7 @@ const char ZEBRA_PTM_GET_STATUS_CMD[] = "get-status"; const char ZEBRA_PTM_BFD_START_CMD[] = "start-bfd-sess"; const char ZEBRA_PTM_BFD_STOP_CMD[] = "stop-bfd-sess"; const char ZEBRA_PTM_BFD_CLIENT_REG_CMD[] = "reg-bfd-client"; +const char ZEBRA_PTM_BFD_CLIENT_DEREG_CMD[] = "dereg-bfd-client"; const char ZEBRA_PTM_CMD_STR[] = "cmd"; const char ZEBRA_PTM_CMD_STATUS_STR[] = "cmd_status"; @@ -1001,6 +1002,46 @@ zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length) return 0; } +/* BFD client deregister */ +void +zebra_ptm_bfd_client_deregister (struct zserv *client) +{ + void *out_ctxt; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + + if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP + && client->proto != ZEBRA_ROUTE_OSPF6) + return; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_client_deregister msg for client %s", + zebra_route_string(client->proto)); + + if (ptm_cb.ptm_sock == -1) + { + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); + return; + } + + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); + + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); +} + int zebra_ptm_get_enable_state(void) { diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 190ae996ec..27c0e42f99 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -72,4 +72,5 @@ int zebra_ptm_bfd_client_register (struct zserv *client, int sock, void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp); +void zebra_ptm_bfd_client_deregister (struct zserv *client); #endif diff --git a/zebra/zserv.c b/zebra/zserv.c index c31a0b6a9e..d6de0792e1 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1751,6 +1751,9 @@ zebra_client_close_cleanup_rnh (struct zserv *client) static void zebra_client_close (struct zserv *client) { + /* Send client de-registration to BFD */ + zebra_ptm_bfd_client_deregister(client); + /* Cleanup any registered nexthops - across all VRFs. */ zebra_client_close_cleanup_rnh (client);