2015-05-20 02:40:44 +02:00
|
|
|
/* Kernel routing table updates using netlink over GNU/Linux system.
|
|
|
|
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra 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, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra 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.
|
|
|
|
*
|
2017-05-13 10:25:29 +02:00
|
|
|
* 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
|
2015-05-20 02:40:44 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
2018-06-19 20:29:05 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
#include <sys/un.h> /* for sockaddr_un */
|
2015-05-20 02:40:44 +02:00
|
|
|
#include <net/if.h>
|
2018-06-19 20:29:05 +02:00
|
|
|
|
|
|
|
#include "bfd.h"
|
|
|
|
#include "buffer.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "ptm_lib.h"
|
|
|
|
#include "rib.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include "vrf.h"
|
2015-07-22 22:07:08 +02:00
|
|
|
#include "vty.h"
|
2018-08-24 19:14:09 +02:00
|
|
|
#include "lib_errors.h"
|
2018-06-19 20:29:05 +02:00
|
|
|
|
2015-05-20 02:40:44 +02:00
|
|
|
#include "zebra/debug.h"
|
2018-06-19 20:29:05 +02:00
|
|
|
#include "zebra/interface.h"
|
|
|
|
#include "zebra/zebra_errors.h"
|
2015-05-20 02:40:44 +02:00
|
|
|
#include "zebra/zebra_ptm.h"
|
2015-06-12 16:59:11 +02:00
|
|
|
#include "zebra/zebra_ptm_redistribute.h"
|
2018-06-19 20:29:05 +02:00
|
|
|
#include "zebra/zserv.h"
|
2016-04-14 15:20:47 +02:00
|
|
|
#include "zebra_vrf.h"
|
2015-05-20 02:40:44 +02:00
|
|
|
|
2018-06-27 18:40:50 +02:00
|
|
|
/*
|
|
|
|
* Choose the BFD implementation that we'll use.
|
|
|
|
*
|
|
|
|
* There are two implementations:
|
|
|
|
* - PTM BFD: which uses an external daemon;
|
|
|
|
* - bfdd: FRR's own BFD daemon;
|
|
|
|
*/
|
|
|
|
#if HAVE_BFDD == 0
|
|
|
|
|
2015-05-20 02:40:44 +02:00
|
|
|
#define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
|
|
|
|
#define ZEBRA_PTM_RECONNECT_TIME_MAX 300
|
2015-05-20 02:47:24 +02:00
|
|
|
|
|
|
|
#define PTM_MSG_LEN 4
|
2015-05-20 03:04:22 +02:00
|
|
|
#define PTM_HEADER_LEN 37
|
2015-06-12 16:59:11 +02:00
|
|
|
|
|
|
|
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";
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
const char ZEBRA_PTM_BFD_CLIENT_REG_CMD[] = "reg-bfd-client";
|
2016-05-09 05:11:18 +02:00
|
|
|
const char ZEBRA_PTM_BFD_CLIENT_DEREG_CMD[] = "dereg-bfd-client";
|
2015-06-12 16:59:11 +02:00
|
|
|
|
2015-07-22 22:07:08 +02:00
|
|
|
const char ZEBRA_PTM_CMD_STR[] = "cmd";
|
2015-08-26 21:37:46 +02:00
|
|
|
const char ZEBRA_PTM_CMD_STATUS_STR[] = "cmd_status";
|
2015-06-12 16:59:11 +02:00
|
|
|
const char ZEBRA_PTM_PORT_STR[] = "port";
|
|
|
|
const char ZEBRA_PTM_CBL_STR[] = "cbl status";
|
|
|
|
const char ZEBRA_PTM_PASS_STR[] = "pass";
|
|
|
|
const char ZEBRA_PTM_FAIL_STR[] = "fail";
|
|
|
|
const char ZEBRA_PTM_BFDSTATUS_STR[] = "state";
|
|
|
|
const char ZEBRA_PTM_BFDSTATUS_UP_STR[] = "Up";
|
|
|
|
const char ZEBRA_PTM_BFDSTATUS_DOWN_STR[] = "Down";
|
|
|
|
const char ZEBRA_PTM_BFDDEST_STR[] = "peer";
|
|
|
|
const char ZEBRA_PTM_BFDSRC_STR[] = "local";
|
2016-03-08 14:10:56 +01:00
|
|
|
const char ZEBRA_PTM_BFDVRF_STR[] = "vrf";
|
2015-06-12 16:59:11 +02:00
|
|
|
const char ZEBRA_PTM_INVALID_PORT_NAME[] = "N/A";
|
|
|
|
const char ZEBRA_PTM_INVALID_SRC_IP[] = "N/A";
|
2016-03-08 14:10:56 +01:00
|
|
|
const char ZEBRA_PTM_INVALID_VRF[] = "N/A";
|
2015-06-12 16:59:11 +02:00
|
|
|
|
|
|
|
const char ZEBRA_PTM_BFD_DST_IP_FIELD[] = "dstIPaddr";
|
|
|
|
const char ZEBRA_PTM_BFD_SRC_IP_FIELD[] = "srcIPaddr";
|
|
|
|
const char ZEBRA_PTM_BFD_MIN_RX_FIELD[] = "requiredMinRx";
|
|
|
|
const char ZEBRA_PTM_BFD_MIN_TX_FIELD[] = "upMinTx";
|
|
|
|
const char ZEBRA_PTM_BFD_DETECT_MULT_FIELD[] = "detectMult";
|
|
|
|
const char ZEBRA_PTM_BFD_MULTI_HOP_FIELD[] = "multiHop";
|
|
|
|
const char ZEBRA_PTM_BFD_CLIENT_FIELD[] = "client";
|
|
|
|
const char ZEBRA_PTM_BFD_SEQID_FIELD[] = "seqid";
|
|
|
|
const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName";
|
|
|
|
const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt";
|
Support of BFD status in Quagga
Ticket:CM-6802, CM-6952
Reviewed By: Donald, Kanna
Testing Done:
Double commit of b76943235e09472ec174edcf7204fc82d27fe966 from br2.5. But, manually resolved all the compilation errors. Also, modified the shows to support the json format which was not supported in br2.5.
CM-6802 – Currently, BFD session status can be monitored only through ptmctl. There is no way to check the BFD status of a peer/neighbor through Quagga. Debugging becomes easier if BFD status is shown in Quagga too. BFD status is relevant when it is shown against the BGP peer/OSPF neighbor. For, this following code changes have been done:
- Only down messages from PTM were being propagated from Zebra daemon to clients (bgpd, ospfd and ospf6d). Now, both up and down messages are redistributed to the clients from zebra. BFD status field has been added to the messaging. Handling of BFD session up messages has been added to the client code. BGP/OSPF neighbor is brought down only if the old BFD session status is ‘Up’ to handle extra/initial down messages.
- BFD status and last update timestamp fields have been added to the common BFD info structure. Also, common show functions for showing BFD information have been added to BFD lib.
- Modified the BGP neighbor show functions to call common BFD lib functions.
- For ospf and ospf6, BFD information was maintained only at interface level. To show BFD status per neighbor, BFD information has been added at neighbor level too. “show ip ospf interface”, “show ip ospf neighbor detail”, “show ipv6 ospf6 interface” and “show ipv6 ospf6 neighbor detail” output have been modified to show BFD information.
CM-6952 - IBGP peers were always assumed to be multi-hop since there was no easy way to determine whether an IBGP peer was single hop or multihop unlike EBGP. But, this is causing problem with IBGP link local peers since BFD doesn't allow multihop BFD session with link local IP addresses. Link local peers were discovered when the interface peering was enabled. Interface peering is always singlehop. So, added checks to treat all interface based peers as single hop irrespective of whether the peer is IBGP or EBGP.
2015-08-31 23:56:11 +02:00
|
|
|
const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent";
|
2016-03-08 14:10:56 +01:00
|
|
|
const char ZEBRA_PTM_BFD_VRF_NAME_FIELD[] = "vrfName";
|
2015-05-20 02:47:24 +02:00
|
|
|
|
2015-06-12 16:59:11 +02:00
|
|
|
static ptm_lib_handle_t *ptm_hdl;
|
2015-05-20 02:40:44 +02:00
|
|
|
|
2015-07-22 22:07:08 +02:00
|
|
|
struct zebra_ptm_cb ptm_cb;
|
|
|
|
|
2015-05-20 02:40:44 +02:00
|
|
|
static int zebra_ptm_socket_init(void);
|
|
|
|
int zebra_ptm_sock_read(struct thread *);
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_ptm_install_commands(void);
|
2015-08-26 21:37:46 +02:00
|
|
|
static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt);
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_bfd_peer_replay_req(void);
|
2015-10-09 20:18:09 +02:00
|
|
|
void zebra_ptm_send_status_req(void);
|
|
|
|
void zebra_ptm_reset_status(int ptm_disable);
|
2018-04-23 04:32:49 +02:00
|
|
|
static int zebra_ptm_bfd_client_deregister(struct zserv *client);
|
2015-05-20 02:40:44 +02:00
|
|
|
|
|
|
|
const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket";
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_init(void)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
char buf[64];
|
2015-06-12 16:59:11 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb));
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF);
|
|
|
|
if (!ptm_cb.out_data) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: Allocation of send data failed", __func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF);
|
|
|
|
if (!ptm_cb.in_data) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: Allocation of recv data failed", __func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
free(ptm_cb.out_data);
|
|
|
|
return;
|
|
|
|
}
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.pid = getpid();
|
|
|
|
zebra_ptm_install_commands();
|
2015-06-12 16:59:11 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(buf, "%s", FRR_PTM_NAME);
|
|
|
|
ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb,
|
|
|
|
zebra_ptm_handle_msg_cb);
|
|
|
|
ptm_cb.wb = buffer_new(0);
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.ptm_sock = -1;
|
2018-04-22 23:03:52 +02:00
|
|
|
|
2018-04-24 00:35:35 +02:00
|
|
|
hook_register(zserv_client_close, zebra_ptm_bfd_client_deregister);
|
2015-07-22 22:07:08 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_finish(void)
|
2015-07-22 22:07:08 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock);
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
free(ptm_hdl);
|
2016-11-01 21:57:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.out_data)
|
|
|
|
free(ptm_cb.out_data);
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.in_data)
|
|
|
|
free(ptm_cb.in_data);
|
2015-07-22 22:07:08 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Release threads. */
|
|
|
|
if (ptm_cb.t_read)
|
|
|
|
thread_cancel(ptm_cb.t_read);
|
|
|
|
if (ptm_cb.t_write)
|
|
|
|
thread_cancel(ptm_cb.t_write);
|
|
|
|
if (ptm_cb.t_timer)
|
|
|
|
thread_cancel(ptm_cb.t_timer);
|
2016-06-21 12:39:58 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.wb)
|
|
|
|
buffer_free(ptm_cb.wb);
|
2016-06-21 12:39:58 +02:00
|
|
|
|
2017-08-25 14:07:58 +02:00
|
|
|
if (ptm_cb.ptm_sock >= 0)
|
2017-07-17 14:03:14 +02:00
|
|
|
close(ptm_cb.ptm_sock);
|
2015-07-22 22:07:08 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_flush_messages(struct thread *thread)
|
2015-07-22 22:07:08 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.t_write = NULL;
|
|
|
|
|
|
|
|
if (ptm_cb.ptm_sock == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) {
|
|
|
|
case BUFFER_ERROR:
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s ptm socket error: %s",
|
2018-08-16 22:10:32 +02:00
|
|
|
__func__, safe_strerror(errno));
|
2017-07-17 14:03:14 +02:00
|
|
|
close(ptm_cb.ptm_sock);
|
|
|
|
ptm_cb.ptm_sock = -1;
|
|
|
|
zebra_ptm_reset_status(0);
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
|
|
|
return (-1);
|
|
|
|
case BUFFER_PENDING:
|
|
|
|
ptm_cb.t_write = NULL;
|
|
|
|
thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL,
|
|
|
|
ptm_cb.ptm_sock, &ptm_cb.t_write);
|
|
|
|
break;
|
|
|
|
case BUFFER_EMPTY:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
2015-07-22 22:07:08 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_send_message(char *data, int size)
|
2015-07-22 22:07:08 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
errno = 0;
|
|
|
|
switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) {
|
|
|
|
case BUFFER_ERROR:
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s ptm socket error: %s",
|
2018-08-16 22:10:32 +02:00
|
|
|
__func__, safe_strerror(errno));
|
2017-07-17 14:03:14 +02:00
|
|
|
close(ptm_cb.ptm_sock);
|
|
|
|
ptm_cb.ptm_sock = -1;
|
|
|
|
zebra_ptm_reset_status(0);
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
|
|
|
return -1;
|
|
|
|
case BUFFER_EMPTY:
|
|
|
|
THREAD_OFF(ptm_cb.t_write);
|
|
|
|
break;
|
|
|
|
case BUFFER_PENDING:
|
|
|
|
thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL,
|
|
|
|
ptm_cb.ptm_sock, &ptm_cb.t_write);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int zebra_ptm_connect(struct thread *t)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int init = 0;
|
|
|
|
|
|
|
|
if (ptm_cb.ptm_sock == -1) {
|
|
|
|
zebra_ptm_socket_init();
|
|
|
|
init = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptm_cb.ptm_sock != -1) {
|
|
|
|
if (init) {
|
|
|
|
ptm_cb.t_read = NULL;
|
|
|
|
thread_add_read(zebrad.master, zebra_ptm_sock_read,
|
|
|
|
NULL, ptm_cb.ptm_sock, &ptm_cb.t_read);
|
|
|
|
zebra_bfd_peer_replay_req();
|
|
|
|
}
|
|
|
|
zebra_ptm_send_status_req();
|
|
|
|
ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
|
|
|
|
} else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX) {
|
|
|
|
ptm_cb.reconnect_time *= 2;
|
|
|
|
if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX)
|
|
|
|
ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX;
|
|
|
|
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
|
|
|
} else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX) {
|
|
|
|
ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (errno);
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (zebra_ptm_enable,
|
|
|
|
zebra_ptm_enable_cmd,
|
|
|
|
"ptm-enable",
|
|
|
|
"Enable neighbor check with specified topology\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct vrf *vrf;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct zebra_if *if_data;
|
|
|
|
|
|
|
|
ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON;
|
|
|
|
|
2017-09-15 17:47:35 +02:00
|
|
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
2017-10-06 20:25:58 +02:00
|
|
|
FOR_ALL_INTERFACES (vrf, ifp)
|
2017-09-15 17:47:35 +02:00
|
|
|
if (!ifp->ptm_enable) {
|
|
|
|
if_data = (struct zebra_if *)ifp->info;
|
|
|
|
if (if_data
|
|
|
|
&& (if_data->ptm_enable
|
2017-07-22 14:52:33 +02:00
|
|
|
== ZEBRA_IF_PTM_ENABLE_UNSPEC)) {
|
2017-09-15 17:47:35 +02:00
|
|
|
ifp->ptm_enable =
|
|
|
|
ZEBRA_IF_PTM_ENABLE_ON;
|
|
|
|
}
|
|
|
|
/* Assign a default unknown status */
|
|
|
|
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
zebra_ptm_connect(NULL);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_zebra_ptm_enable,
|
|
|
|
no_zebra_ptm_enable_cmd,
|
|
|
|
"no ptm-enable",
|
|
|
|
NO_STR
|
|
|
|
"Enable neighbor check with specified topology\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
|
|
|
|
zebra_ptm_reset_status(1);
|
|
|
|
return CMD_SUCCESS;
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
2016-04-22 00:39:38 +02:00
|
|
|
DEFUN (zebra_ptm_enable_if,
|
|
|
|
zebra_ptm_enable_if_cmd,
|
|
|
|
"ptm-enable",
|
|
|
|
"Enable neighbor check with specified topology\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
struct zebra_if *if_data;
|
|
|
|
int old_ptm_enable;
|
|
|
|
int send_linkdown = 0;
|
|
|
|
|
2017-08-01 19:10:35 +02:00
|
|
|
if_data = ifp->info;
|
|
|
|
if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ifp->ifindex == IFINDEX_INTERNAL) {
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
old_ptm_enable = ifp->ptm_enable;
|
|
|
|
ifp->ptm_enable = ptm_cb.ptm_enable;
|
|
|
|
|
|
|
|
if (if_is_no_ptm_operative(ifp))
|
|
|
|
send_linkdown = 1;
|
|
|
|
|
|
|
|
if (!old_ptm_enable && ptm_cb.ptm_enable) {
|
|
|
|
if (!if_is_operative(ifp) && send_linkdown) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("%s: Bringing down interface %s\n",
|
|
|
|
__func__, ifp->name);
|
|
|
|
if_down(ifp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
2016-04-22 00:39:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_zebra_ptm_enable_if,
|
|
|
|
no_zebra_ptm_enable_if_cmd,
|
|
|
|
"no ptm-enable",
|
|
|
|
NO_STR
|
|
|
|
"Enable neighbor check with specified topology\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
|
|
|
int send_linkup = 0;
|
|
|
|
struct zebra_if *if_data;
|
|
|
|
|
|
|
|
if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) {
|
|
|
|
if (!if_is_operative(ifp))
|
|
|
|
send_linkup = 1;
|
|
|
|
|
|
|
|
ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
|
|
|
|
if (if_is_no_ptm_operative(ifp) && send_linkup) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("%s: Bringing up interface %s\n",
|
|
|
|
__func__, ifp->name);
|
|
|
|
if_up(ifp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if_data = ifp->info;
|
|
|
|
if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
2016-04-22 00:39:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_write(struct vty *vty)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.ptm_enable)
|
|
|
|
vty_out(vty, "ptm-enable\n");
|
2015-05-20 02:40:44 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return;
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_socket_init(void)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
int sock;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
|
|
|
|
ptm_cb.ptm_sock = -1;
|
|
|
|
|
|
|
|
sock = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
|
|
if (sock < 0)
|
|
|
|
return -1;
|
|
|
|
if (set_nonblocking(sock) < 0) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("%s: Unable to set socket non blocking[%s]",
|
|
|
|
__PRETTY_FUNCTION__, safe_strerror(errno));
|
|
|
|
close(sock);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make server socket. */
|
|
|
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
memcpy(&addr.sun_path, ZEBRA_PTM_SOCK_NAME,
|
|
|
|
sizeof(ZEBRA_PTM_SOCK_NAME));
|
|
|
|
|
|
|
|
ret = connect(sock, (struct sockaddr *)&addr,
|
|
|
|
sizeof(addr.sun_family) + sizeof(ZEBRA_PTM_SOCK_NAME)
|
|
|
|
- 1);
|
|
|
|
if (ret < 0) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("%s: Unable to connect to socket %s [%s]",
|
|
|
|
__func__, ZEBRA_PTM_SOCK_NAME,
|
|
|
|
safe_strerror(errno));
|
|
|
|
close(sock);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ptm_cb.ptm_sock = sock;
|
|
|
|
return sock;
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_ptm_install_commands(void)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(CONFIG_NODE, &zebra_ptm_enable_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_zebra_ptm_enable_cmd);
|
|
|
|
install_element(INTERFACE_NODE, &zebra_ptm_enable_if_cmd);
|
|
|
|
install_element(INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd);
|
2015-05-20 02:40:44 +02:00
|
|
|
}
|
|
|
|
|
2015-06-12 16:59:11 +02:00
|
|
|
/* BFD session goes down, send message to the protocols. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void if_bfd_session_update(struct interface *ifp, struct prefix *dp,
|
|
|
|
struct prefix *sp, int status,
|
|
|
|
vrf_id_t vrf_id)
|
2015-05-20 02:47:24 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_EVENT) {
|
|
|
|
char buf[2][INET6_ADDRSTRLEN];
|
|
|
|
|
|
|
|
if (ifp) {
|
|
|
|
zlog_debug(
|
|
|
|
"MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s"
|
|
|
|
" %s event",
|
|
|
|
inet_ntop(dp->family, &dp->u.prefix, buf[0],
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
dp->prefixlen, ifp->name,
|
|
|
|
bfd_get_status_str(status));
|
|
|
|
} else {
|
|
|
|
zlog_debug(
|
|
|
|
"MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
|
lib: increase vrf_id from 16 bit to 32 bit identifier
This is a preparatory work for configuring vrf/frr over netns
vrf structure is being changed to 32 bit, and the VRF will have the
possibility to have a backend made up of NETNS.
Let's put some history.
Initially the 32 bit was because one wanted to map on vrf_id both the
VRFLITE and the NSID.
Initially, one would have liked to make zebra configure at the same time
both vrf lite and vrf from netns in a flat way. From the show
running perspective, one would have had both kind of vrfs, thatone
would configure on the same way.
however, it leads to inconsistencies in concepts, because it mixes vrf
vrf with vrf, and vrf is not always mapped with netns.
For instance, logical-router could also be used with netns. In that
case, it would not be possible to map vrf with netns.
There was an other reason why 32 bit is proposed. this is because
some systems handle NSID to 32 bits. As vrf lite exists only on
Linux, there are other systems that would like to use an other vrf
backend than vrf lite. The netns backend for vrf will be used for that
too. for instance, for windows or freebsd, some similar
netns concept exists; so it will be easier to reuse netns
backend for vrf, than reusing vrflite backend for vrf.
This commit is here to extend vrf_id to 32 bits. Following commits in a
second step will help in enable a VRF backend.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2017-12-14 16:01:36 +01:00
|
|
|
"with src %s/%d and vrf %u %s event",
|
2017-07-17 14:03:14 +02:00
|
|
|
inet_ntop(dp->family, &dp->u.prefix, buf[0],
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
dp->prefixlen,
|
|
|
|
inet_ntop(sp->family, &sp->u.prefix, buf[1],
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
sp->prefixlen, vrf_id,
|
|
|
|
bfd_get_status_str(status));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
zebra_interface_bfd_update(ifp, dp, sp, status, vrf_id);
|
2015-05-20 02:47:24 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt,
|
|
|
|
struct interface *ifp)
|
2015-05-20 02:40:44 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
char bfdst_str[32];
|
|
|
|
char dest_str[64];
|
|
|
|
char src_str[64];
|
|
|
|
char vrf_str[64];
|
|
|
|
struct prefix dest_prefix;
|
|
|
|
struct prefix src_prefix;
|
|
|
|
vrf_id_t vrf_id;
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str);
|
|
|
|
|
|
|
|
if (bfdst_str[0] == '\0') {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str);
|
|
|
|
|
|
|
|
if (dest_str[0] == '\0') {
|
|
|
|
zlog_debug("%s: Key %s not found in PTM msg", __func__,
|
|
|
|
ZEBRA_PTM_BFDDEST_STR);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str);
|
|
|
|
|
|
|
|
if (src_str[0] == '\0') {
|
|
|
|
zlog_debug("%s: Key %s not found in PTM msg", __func__,
|
|
|
|
ZEBRA_PTM_BFDSRC_STR);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str);
|
|
|
|
|
|
|
|
if (vrf_str[0] == '\0') {
|
|
|
|
zlog_debug("%s: Key %s not found in PTM msg", __func__,
|
|
|
|
ZEBRA_PTM_BFDVRF_STR);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: Recv Port [%s] bfd status [%s] vrf [%s]"
|
|
|
|
" peer [%s] local [%s]",
|
|
|
|
__func__, ifp ? ifp->name : "N/A", bfdst_str, vrf_str,
|
|
|
|
dest_str, src_str);
|
|
|
|
|
|
|
|
if (str2prefix(dest_str, &dest_prefix) == 0) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_err(EC_ZEBRA_PREFIX_PARSE_ERROR,
|
2018-06-19 20:29:05 +02:00
|
|
|
"%s: Peer addr %s not found", __func__, dest_str);
|
2017-07-17 14:03:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&src_prefix, 0, sizeof(struct prefix));
|
|
|
|
if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
|
|
|
|
if (str2prefix(src_str, &src_prefix) == 0) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_err(EC_ZEBRA_PREFIX_PARSE_ERROR,
|
2018-06-19 20:29:05 +02:00
|
|
|
"%s: Local addr %s not found", __func__,
|
|
|
|
src_str);
|
2017-07-17 14:03:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) {
|
|
|
|
vrf_id = ifp->vrf_id;
|
|
|
|
} else {
|
|
|
|
vrf_id = vrf_name_to_id(vrf_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
|
|
|
|
if_bfd_session_update(ifp, &dest_prefix, &src_prefix,
|
|
|
|
BFD_STATUS_DOWN, vrf_id);
|
|
|
|
} else {
|
|
|
|
if_bfd_session_update(ifp, &dest_prefix, &src_prefix,
|
|
|
|
BFD_STATUS_UP, vrf_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-05-20 02:47:24 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt,
|
|
|
|
struct interface *ifp, char *cbl_str)
|
2015-05-20 02:47:24 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int send_linkup = 0;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__,
|
|
|
|
ifp->name, cbl_str);
|
|
|
|
|
|
|
|
if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR)
|
|
|
|
&& (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) {
|
|
|
|
|
|
|
|
if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)
|
|
|
|
send_linkup = 1;
|
|
|
|
ifp->ptm_status = ZEBRA_PTM_STATUS_UP;
|
|
|
|
if (ifp->ptm_enable && if_is_no_ptm_operative(ifp)
|
|
|
|
&& send_linkup)
|
|
|
|
if_up(ifp);
|
|
|
|
} else if (!strcmp(cbl_str, ZEBRA_PTM_FAIL_STR)
|
|
|
|
&& (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) {
|
|
|
|
ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN;
|
|
|
|
if (ifp->ptm_enable && if_is_no_ptm_operative(ifp))
|
|
|
|
if_down(ifp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-08-26 21:37:46 +02:00
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
|
2015-08-26 21:37:46 +02:00
|
|
|
/*
|
|
|
|
* zebra_ptm_handle_msg_cb - The purpose of this callback function is to handle
|
|
|
|
* all the command responses and notifications received from PTM.
|
|
|
|
*
|
|
|
|
* Command responses: Upon establishing connection with PTM, Zebra requests
|
|
|
|
* status of all interfaces using 'get-status' command if global ptm-enable
|
|
|
|
* knob is enabled. As a response to the get-status command PTM sends status
|
|
|
|
* of all the interfaces as command responses. All other type of command
|
|
|
|
* responses with cmd_status key word are dropped. The sole purpose of
|
|
|
|
* registering this function as callback for the command responses is to
|
|
|
|
* handle the responses to get-status command.
|
|
|
|
*
|
|
|
|
* Notifications: Cable status and BFD session status changes are sent as
|
|
|
|
* notifications by PTM. So, this function is also the callback function for
|
|
|
|
* processing all the notifications from the PTM.
|
|
|
|
*
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt)
|
2015-08-26 21:37:46 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct interface *ifp = NULL;
|
|
|
|
char port_str[128];
|
|
|
|
char cbl_str[32];
|
|
|
|
char cmd_status_str[32];
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR,
|
|
|
|
cmd_status_str);
|
|
|
|
|
|
|
|
/* Drop command response messages */
|
|
|
|
if (cmd_status_str[0] != '\0') {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str);
|
|
|
|
|
|
|
|
if (port_str[0] == '\0') {
|
|
|
|
zlog_debug("%s: Key %s not found in PTM msg", __func__,
|
|
|
|
ZEBRA_PTM_PORT_STR);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) {
|
|
|
|
ifp = if_lookup_by_name_all_vrf(port_str);
|
|
|
|
|
|
|
|
if (!ifp) {
|
2018-09-13 21:21:05 +02:00
|
|
|
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
|
2018-08-16 22:10:32 +02:00
|
|
|
"%s: %s not found in interface list",
|
2018-06-19 20:29:05 +02:00
|
|
|
__func__, port_str);
|
2017-07-17 14:03:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str);
|
|
|
|
|
|
|
|
if (cbl_str[0] == '\0') {
|
|
|
|
return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp);
|
|
|
|
} else {
|
|
|
|
if (ifp) {
|
|
|
|
return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp,
|
|
|
|
cbl_str);
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2015-05-20 02:47:24 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int zebra_ptm_sock_read(struct thread *thread)
|
2015-05-20 02:47:24 +02:00
|
|
|
{
|
2018-07-02 18:50:20 +02:00
|
|
|
int sock;
|
2017-07-17 14:03:14 +02:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
sock = THREAD_FD(thread);
|
|
|
|
|
|
|
|
if (sock == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* PTM communicates in CSV format */
|
2018-07-02 18:50:20 +02:00
|
|
|
do {
|
2017-07-17 14:03:14 +02:00
|
|
|
rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data,
|
|
|
|
ZEBRA_PTM_MAX_SOCKBUF, NULL);
|
2018-07-02 18:50:20 +02:00
|
|
|
} while (rc > 0);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-07-02 18:50:20 +02:00
|
|
|
if (((rc == 0) && !errno)
|
|
|
|
|| (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-16 22:10:32 +02:00
|
|
|
"%s routing socket error: %s(%d) bytes %d",
|
|
|
|
__func__, safe_strerror(errno), errno, rc);
|
2018-07-02 18:50:20 +02:00
|
|
|
|
|
|
|
close(ptm_cb.ptm_sock);
|
|
|
|
ptm_cb.ptm_sock = -1;
|
|
|
|
zebra_ptm_reset_status(0);
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time,
|
|
|
|
&ptm_cb.t_timer);
|
|
|
|
return (-1);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ptm_cb.t_read = NULL;
|
|
|
|
thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL,
|
|
|
|
ptm_cb.ptm_sock, &ptm_cb.t_read);
|
|
|
|
|
|
|
|
return 0;
|
2015-06-12 16:59:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* BFD peer/dst register/update */
|
2018-03-06 23:57:33 +01:00
|
|
|
void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
|
2015-06-12 16:59:11 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
struct prefix src_p;
|
|
|
|
struct prefix dst_p;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t multi_hop;
|
|
|
|
uint8_t multi_hop_cnt;
|
|
|
|
uint8_t detect_mul;
|
2017-07-17 14:03:14 +02:00
|
|
|
unsigned int min_rx_timer;
|
|
|
|
unsigned int min_tx_timer;
|
|
|
|
char if_name[INTERFACE_NAMSIZ];
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t len;
|
2017-07-17 14:03:14 +02:00
|
|
|
void *out_ctxt;
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
char tmp_buf[64];
|
|
|
|
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
|
|
|
unsigned int pid;
|
|
|
|
|
2018-03-06 23:57:33 +01:00
|
|
|
if (hdr->command == ZEBRA_BFD_DEST_UPDATE)
|
2017-07-17 14:03:14 +02:00
|
|
|
client->bfd_peer_upd8_cnt++;
|
|
|
|
else
|
|
|
|
client->bfd_peer_add_cnt++;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_dst_register msg from client %s: length=%d",
|
2018-03-06 23:57:33 +01:00
|
|
|
zebra_route_string(client->proto), hdr->length);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (ptm_cb.ptm_sock == -1) {
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
|
|
|
|
sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_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);
|
|
|
|
|
2018-03-07 00:08:37 +01:00
|
|
|
s = msg;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETL(s, pid);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", pid);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
|
|
|
|
tmp_buf);
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, dst_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (dst_p.family == AF_INET)
|
|
|
|
dst_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
dst_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&dst_p.u.prefix, s, dst_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (dst_p.family == AF_INET) {
|
|
|
|
inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
|
|
|
|
} else {
|
|
|
|
inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
|
|
|
|
}
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETL(s, min_rx_timer);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", min_rx_timer);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD,
|
|
|
|
tmp_buf);
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETL(s, min_tx_timer);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", min_tx_timer);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD,
|
|
|
|
tmp_buf);
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, detect_mul);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", detect_mul);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD,
|
|
|
|
tmp_buf);
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, multi_hop);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (multi_hop) {
|
|
|
|
sprintf(tmp_buf, "%d", 1);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf);
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, src_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (src_p.family == AF_INET)
|
|
|
|
src_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
src_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (src_p.family == AF_INET) {
|
|
|
|
inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
|
|
|
|
} else {
|
|
|
|
inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
|
|
|
|
}
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, multi_hop_cnt);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", multi_hop_cnt);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, tmp_buf);
|
|
|
|
|
|
|
|
if (zvrf_id(zvrf) != VRF_DEFAULT)
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_VRF_NAME_FIELD,
|
|
|
|
zvrf_name(zvrf));
|
|
|
|
} else {
|
|
|
|
if (dst_p.family == AF_INET6) {
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, src_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (src_p.family == AF_INET)
|
|
|
|
src_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
src_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (src_p.family == AF_INET) {
|
|
|
|
inet_ntop(AF_INET, &src_p.u.prefix4, buf,
|
|
|
|
sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD,
|
|
|
|
buf);
|
|
|
|
} else {
|
|
|
|
inet_ntop(AF_INET6, &src_p.u.prefix6, buf,
|
|
|
|
sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD,
|
|
|
|
buf);
|
|
|
|
}
|
|
|
|
}
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, len);
|
|
|
|
STREAM_GET(if_name, s, len);
|
2017-07-17 14:03:14 +02:00
|
|
|
if_name[len] = '\0';
|
|
|
|
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_IFNAME_FIELD, if_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(tmp_buf, "%d", 1);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT,
|
|
|
|
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);
|
2017-11-10 14:51:34 +01:00
|
|
|
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2018-01-25 02:53:40 +01:00
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
stream_failure:
|
2017-12-05 01:03:51 +01:00
|
|
|
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
2015-06-12 16:59:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* BFD peer/dst deregister */
|
2018-03-06 23:57:33 +01:00
|
|
|
void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
|
2015-06-12 16:59:11 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
struct prefix src_p;
|
|
|
|
struct prefix dst_p;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t multi_hop;
|
2017-07-17 14:03:14 +02:00
|
|
|
char if_name[INTERFACE_NAMSIZ];
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t len;
|
2017-07-17 14:03:14 +02:00
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
char tmp_buf[64];
|
|
|
|
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
|
|
|
void *out_ctxt;
|
|
|
|
unsigned int pid;
|
|
|
|
|
|
|
|
client->bfd_peer_del_cnt++;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
|
2018-03-06 23:57:33 +01:00
|
|
|
zebra_route_string(client->proto), hdr->length);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (ptm_cb.ptm_sock == -1) {
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
|
|
|
|
|
|
|
|
sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_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);
|
|
|
|
|
2018-03-07 00:08:37 +01:00
|
|
|
s = msg;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETL(s, pid);
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", pid);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
|
|
|
|
tmp_buf);
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, dst_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (dst_p.family == AF_INET)
|
|
|
|
dst_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
dst_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&dst_p.u.prefix, s, dst_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (dst_p.family == AF_INET)
|
|
|
|
inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf));
|
|
|
|
else
|
|
|
|
inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
|
|
|
|
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, multi_hop);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (multi_hop) {
|
|
|
|
sprintf(tmp_buf, "%d", 1);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf);
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, src_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (src_p.family == AF_INET)
|
|
|
|
src_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
src_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (src_p.family == AF_INET)
|
|
|
|
inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
|
|
|
|
else
|
|
|
|
inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
|
|
|
|
|
|
|
|
if (zvrf_id(zvrf) != VRF_DEFAULT)
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_VRF_NAME_FIELD,
|
|
|
|
zvrf_name(zvrf));
|
|
|
|
} else {
|
|
|
|
if (dst_p.family == AF_INET6) {
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETW(s, src_p.family);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (src_p.family == AF_INET)
|
|
|
|
src_p.prefixlen = IPV4_MAX_BYTELEN;
|
|
|
|
else
|
|
|
|
src_p.prefixlen = IPV6_MAX_BYTELEN;
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GET(&src_p.u.prefix, s, src_p.prefixlen);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (src_p.family == AF_INET) {
|
|
|
|
inet_ntop(AF_INET, &src_p.u.prefix4, buf,
|
|
|
|
sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD,
|
|
|
|
buf);
|
|
|
|
} else {
|
|
|
|
inet_ntop(AF_INET6, &src_p.u.prefix6, buf,
|
|
|
|
sizeof(buf));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_SRC_IP_FIELD,
|
|
|
|
buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETC(s, len);
|
|
|
|
STREAM_GET(if_name, s, len);
|
2017-07-17 14:03:14 +02:00
|
|
|
if_name[len] = '\0';
|
|
|
|
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt,
|
|
|
|
ZEBRA_PTM_BFD_IFNAME_FIELD, if_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2017-11-10 14:51:34 +01:00
|
|
|
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2018-01-25 02:53:40 +01:00
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
stream_failure:
|
2017-12-05 01:03:51 +01:00
|
|
|
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
2015-05-20 02:47:24 +02:00
|
|
|
}
|
2015-07-22 22:07:08 +02:00
|
|
|
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
/* BFD client register */
|
2018-03-06 23:57:33 +01:00
|
|
|
void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
unsigned int pid;
|
2018-01-25 02:53:40 +01:00
|
|
|
void *out_ctxt = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
char tmp_buf[64];
|
|
|
|
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->bfd_client_reg_cnt++;
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_client_register msg from client %s: length=%d",
|
2018-03-06 23:57:33 +01:00
|
|
|
zebra_route_string(client->proto), hdr->length);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2018-03-07 00:08:37 +01:00
|
|
|
s = msg;
|
2017-11-10 14:51:34 +01:00
|
|
|
STREAM_GETL(s, pid);
|
2017-10-11 14:09:28 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.ptm_sock == -1) {
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
|
|
|
|
tmp_buf);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%d", pid);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
|
|
|
|
tmp_buf);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
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);
|
2016-06-21 12:39:58 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
SET_FLAG(ptm_cb.client_flags[client->proto],
|
|
|
|
ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
|
2018-01-25 02:53:40 +01:00
|
|
|
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
2018-01-25 02:53:40 +01:00
|
|
|
|
2017-11-10 14:51:34 +01:00
|
|
|
stream_failure:
|
2018-02-14 05:39:09 +01:00
|
|
|
/*
|
|
|
|
* IF we ever add more STREAM_GETXXX functions after the out_ctxt
|
|
|
|
* is allocated then we need to add this code back in
|
|
|
|
*
|
|
|
|
* if (out_ctxt)
|
|
|
|
* ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
|
|
|
*/
|
2018-03-06 23:01:42 +01:00
|
|
|
return;
|
Support for multi-client and client reg msg
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke
Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5
Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.
Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.
Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”
CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.
Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.
Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.
Code Changes: To support the new client registration message following changes have been made
- Added support for client registration messaging in zebra for sending messages to PTM.
- Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
- Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
- Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.
2016-03-09 08:31:32 +01:00
|
|
|
}
|
|
|
|
|
2016-05-09 05:11:18 +02:00
|
|
|
/* BFD client deregister */
|
2018-04-22 23:03:52 +02:00
|
|
|
int zebra_ptm_bfd_client_deregister(struct zserv *client)
|
2016-05-09 05:11:18 +02:00
|
|
|
{
|
2018-04-22 23:03:52 +02:00
|
|
|
uint8_t proto = client->proto;
|
2017-07-17 14:03:14 +02:00
|
|
|
void *out_ctxt;
|
|
|
|
char tmp_buf[64];
|
|
|
|
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP
|
|
|
|
&& proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM)
|
2018-04-22 23:03:52 +02:00
|
|
|
return 0;
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("bfd_client_deregister msg for client %s",
|
|
|
|
zebra_route_string(proto));
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ptm_cb.ptm_sock == -1) {
|
|
|
|
ptm_cb.t_timer = NULL;
|
|
|
|
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
|
|
|
ptm_cb.reconnect_time, &ptm_cb.t_timer);
|
2018-04-22 23:03:52 +02:00
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(tmp_buf, "%s", zebra_route_string(proto));
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
|
|
|
|
tmp_buf);
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
|
2016-05-09 05:11:18 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (IS_ZEBRA_DEBUG_SEND)
|
|
|
|
zlog_debug("%s: Sent message (%d) %s", __func__, data_len,
|
|
|
|
ptm_cb.out_data);
|
2016-06-21 12:39:58 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zebra_ptm_send_message(ptm_cb.out_data, data_len);
|
|
|
|
UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
|
2018-04-22 23:03:52 +02:00
|
|
|
|
|
|
|
return 0;
|
2016-05-09 05:11:18 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int zebra_ptm_get_enable_state(void)
|
2015-07-22 22:07:08 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return ptm_cb.ptm_enable;
|
2015-07-22 22:07:08 +02:00
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* zebra_ptm_get_status_str - Convert status to a display string.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static const char *zebra_ptm_get_status_str(int status)
|
2015-10-09 20:18:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
switch (status) {
|
|
|
|
case ZEBRA_PTM_STATUS_DOWN:
|
|
|
|
return "fail";
|
|
|
|
case ZEBRA_PTM_STATUS_UP:
|
|
|
|
return "pass";
|
|
|
|
case ZEBRA_PTM_STATUS_UNKNOWN:
|
|
|
|
default:
|
|
|
|
return "n/a";
|
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_show_status(struct vty *vty, struct interface *ifp)
|
2015-10-09 20:18:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty, " PTM status: ");
|
|
|
|
if (ifp->ptm_enable) {
|
|
|
|
vty_out(vty, "%s\n", zebra_ptm_get_status_str(ifp->ptm_status));
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "disabled\n");
|
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_send_status_req(void)
|
2015-10-09 20:18:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
void *out_ctxt;
|
|
|
|
int len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
|
|
|
|
|
|
|
|
if (ptm_cb.ptm_enable) {
|
|
|
|
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL,
|
|
|
|
&out_ctxt);
|
|
|
|
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR,
|
|
|
|
ZEBRA_PTM_GET_STATUS_CMD);
|
|
|
|
ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len);
|
|
|
|
|
|
|
|
zebra_ptm_send_message(ptm_cb.out_data, len);
|
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_reset_status(int ptm_disable)
|
2015-10-09 20:18:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct vrf *vrf;
|
|
|
|
struct interface *ifp;
|
|
|
|
int send_linkup;
|
|
|
|
|
2017-09-15 17:47:35 +02:00
|
|
|
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
|
2017-10-06 20:25:58 +02:00
|
|
|
FOR_ALL_INTERFACES (vrf, ifp) {
|
2017-09-15 17:47:35 +02:00
|
|
|
send_linkup = 0;
|
|
|
|
if (ifp->ptm_enable) {
|
|
|
|
if (!if_is_operative(ifp))
|
|
|
|
send_linkup = 1;
|
|
|
|
|
|
|
|
if (ptm_disable)
|
|
|
|
ifp->ptm_enable =
|
|
|
|
ZEBRA_IF_PTM_ENABLE_OFF;
|
|
|
|
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
|
|
|
|
|
|
|
|
if (if_is_operative(ifp) && send_linkup) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: Bringing up interface %s",
|
|
|
|
__func__, ifp->name);
|
|
|
|
if_up(ifp);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-09 20:18:09 +02:00
|
|
|
}
|
2016-04-22 00:39:38 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_if_init(struct zebra_if *zebra_ifp)
|
2016-04-22 00:39:38 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
|
2016-04-22 00:39:38 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_if_set_ptm_state(struct interface *ifp,
|
|
|
|
struct zebra_if *zebra_ifp)
|
2016-04-22 00:39:38 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC)
|
|
|
|
ifp->ptm_enable = zebra_ifp->ptm_enable;
|
2016-04-22 00:39:38 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp)
|
2016-04-22 00:39:38 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF)
|
|
|
|
vty_out(vty, " no ptm-enable\n");
|
2016-04-22 00:39:38 +02:00
|
|
|
}
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
#else /* HAVE_BFDD */
|
|
|
|
|
|
|
|
#include "zebra/zebra_memory.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Data structures.
|
|
|
|
*/
|
|
|
|
struct ptm_process {
|
|
|
|
struct zserv *pp_zs;
|
|
|
|
pid_t pp_pid;
|
|
|
|
|
|
|
|
TAILQ_ENTRY(ptm_process) pp_entry;
|
|
|
|
};
|
|
|
|
TAILQ_HEAD(ppqueue, ptm_process) ppqueue;
|
|
|
|
|
|
|
|
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_PTM_BFD_PROCESS,
|
|
|
|
"PTM BFD process registration table.");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prototypes.
|
|
|
|
*/
|
|
|
|
static struct ptm_process *pp_new(pid_t pid, struct zserv *zs);
|
|
|
|
static struct ptm_process *pp_lookup_byzs(struct zserv *zs);
|
|
|
|
static void pp_free(struct ptm_process *pp);
|
2018-07-25 18:39:58 +02:00
|
|
|
static void pp_free_all(void);
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
static void zebra_ptm_send_bfdd(struct stream *msg);
|
|
|
|
static void zebra_ptm_send_clients(struct stream *msg);
|
|
|
|
static int _zebra_ptm_bfd_client_deregister(struct zserv *zs);
|
|
|
|
static void _zebra_ptm_reroute(struct zserv *zs, struct stream *msg,
|
|
|
|
uint32_t command);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Process PID registration.
|
|
|
|
*/
|
|
|
|
static struct ptm_process *pp_new(pid_t pid, struct zserv *zs)
|
|
|
|
{
|
|
|
|
struct ptm_process *pp;
|
|
|
|
|
|
|
|
#ifdef PTM_DEBUG
|
|
|
|
/* Sanity check: more than one client can't have the same PID. */
|
|
|
|
TAILQ_FOREACH(pp, &ppqueue, pp_entry) {
|
|
|
|
if (pp->pp_pid == pid && pp->pp_zs != zs)
|
|
|
|
zlog_err("%s:%d pid and client pointer doesn't match",
|
|
|
|
__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
#endif /* PTM_DEBUG */
|
|
|
|
|
|
|
|
/* Lookup for duplicates. */
|
|
|
|
pp = pp_lookup_byzs(zs);
|
|
|
|
if (pp != NULL)
|
|
|
|
return pp;
|
|
|
|
|
|
|
|
/* Allocate and register new process. */
|
|
|
|
pp = XCALLOC(MTYPE_ZEBRA_PTM_BFD_PROCESS, sizeof(*pp));
|
|
|
|
if (pp == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pp->pp_pid = pid;
|
|
|
|
pp->pp_zs = zs;
|
|
|
|
TAILQ_INSERT_HEAD(&ppqueue, pp, pp_entry);
|
|
|
|
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ptm_process *pp_lookup_byzs(struct zserv *zs)
|
|
|
|
{
|
|
|
|
struct ptm_process *pp;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(pp, &ppqueue, pp_entry) {
|
|
|
|
if (pp->pp_zs != zs)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pp_free(struct ptm_process *pp)
|
|
|
|
{
|
|
|
|
if (pp == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TAILQ_REMOVE(&ppqueue, pp, pp_entry);
|
|
|
|
XFREE(MTYPE_ZEBRA_PTM_BFD_PROCESS, pp);
|
|
|
|
}
|
|
|
|
|
2018-07-25 18:39:58 +02:00
|
|
|
static void pp_free_all(void)
|
|
|
|
{
|
|
|
|
struct ptm_process *pp;
|
|
|
|
|
|
|
|
while (!TAILQ_EMPTY(&ppqueue)) {
|
|
|
|
pp = TAILQ_FIRST(&ppqueue);
|
|
|
|
pp_free(pp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Use the FRR's internal daemon implementation.
|
|
|
|
*/
|
|
|
|
static void zebra_ptm_send_bfdd(struct stream *msg)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct zserv *client;
|
|
|
|
struct stream *msgc;
|
|
|
|
|
|
|
|
/* Create copy for replication. */
|
|
|
|
msgc = stream_dup(msg);
|
|
|
|
if (msgc == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send message to all running BFDd daemons. */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
|
|
|
|
if (client->proto != ZEBRA_ROUTE_BFD)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
zserv_send_message(client, msg);
|
|
|
|
|
|
|
|
/* Allocate more messages. */
|
|
|
|
msg = stream_dup(msgc);
|
|
|
|
if (msg == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stream_free(msgc);
|
2018-08-16 20:23:13 +02:00
|
|
|
stream_free(msg);
|
2018-06-27 18:40:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void zebra_ptm_send_clients(struct stream *msg)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct zserv *client;
|
|
|
|
struct stream *msgc;
|
|
|
|
|
|
|
|
/* Create copy for replication. */
|
|
|
|
msgc = stream_dup(msg);
|
|
|
|
if (msgc == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
zserv_send_message(client, msg);
|
|
|
|
|
|
|
|
/* Allocate more messages. */
|
|
|
|
msg = stream_dup(msgc);
|
|
|
|
if (msg == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stream_free(msgc);
|
2018-08-16 20:23:13 +02:00
|
|
|
stream_free(msg);
|
2018-06-27 18:40:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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. */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Unsupported daemon. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find daemon pid by zebra connection pointer. */
|
|
|
|
pp = pp_lookup_byzs(zs);
|
|
|
|
if (pp == NULL) {
|
|
|
|
zlog_err("%s:%d failed to find process pid registration",
|
|
|
|
__FILE__, __LINE__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Generate, send message and free() daemon related data. */
|
|
|
|
msg = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
|
|
|
if (msg == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The message type will be BFD_DEST_REPLY so we can use only
|
|
|
|
* one callback at the `bfdd` side, however the real command
|
|
|
|
* number will be included right after the zebra header.
|
|
|
|
*/
|
|
|
|
zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, 0);
|
|
|
|
stream_putl(msg, ZEBRA_BFD_CLIENT_DEREGISTER);
|
|
|
|
|
|
|
|
/* Put process PID. */
|
|
|
|
stream_putl(msg, pp->pp_pid);
|
|
|
|
|
|
|
|
/* Update the data pointers. */
|
|
|
|
stream_putw_at(msg, 0, stream_get_endp(msg));
|
|
|
|
|
|
|
|
zebra_ptm_send_bfdd(msg);
|
|
|
|
|
|
|
|
pp_free(pp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_init(void)
|
|
|
|
{
|
|
|
|
/* Initialize the ptm process information list. */
|
|
|
|
TAILQ_INIT(&ppqueue);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send deregistration messages to BFD daemon when some other
|
|
|
|
* daemon closes. This will help avoid sending daemons
|
|
|
|
* unnecessary notification messages.
|
|
|
|
*/
|
|
|
|
hook_register(zserv_client_close, _zebra_ptm_bfd_client_deregister);
|
|
|
|
}
|
|
|
|
|
2018-07-25 18:39:58 +02:00
|
|
|
void zebra_ptm_finish(void)
|
|
|
|
{
|
|
|
|
/* Remove the client disconnect hook and free all memory. */
|
|
|
|
hook_unregister(zserv_client_close, _zebra_ptm_bfd_client_deregister);
|
|
|
|
pp_free_all();
|
|
|
|
}
|
|
|
|
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Message handling.
|
|
|
|
*/
|
|
|
|
static void _zebra_ptm_reroute(struct zserv *zs, struct stream *msg,
|
|
|
|
uint32_t command)
|
|
|
|
{
|
|
|
|
struct stream *msgc;
|
|
|
|
size_t zmsglen, zhdrlen;
|
|
|
|
pid_t ppid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't modify message in the zebra API. In order to do that we
|
|
|
|
* need to allocate a new message stream and copy the message
|
|
|
|
* provided by zebra.
|
|
|
|
*/
|
|
|
|
msgc = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
|
|
|
if (msgc == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate our header size plus the message contents. */
|
|
|
|
zhdrlen = ZEBRA_HEADER_SIZE + sizeof(uint32_t);
|
|
|
|
zmsglen = msg->endp - msg->getp;
|
|
|
|
memcpy(msgc->data + zhdrlen, msg->data + msg->getp, zmsglen);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The message type will be BFD_DEST_REPLY so we can use only
|
|
|
|
* one callback at the `bfdd` side, however the real command
|
|
|
|
* number will be included right after the zebra header.
|
|
|
|
*/
|
|
|
|
zclient_create_header(msgc, ZEBRA_BFD_DEST_REPLAY, 0);
|
|
|
|
stream_putl(msgc, command);
|
|
|
|
|
|
|
|
/* Update the data pointers. */
|
|
|
|
msgc->getp = 0;
|
|
|
|
msgc->endp = zhdrlen + zmsglen;
|
|
|
|
stream_putw_at(msgc, 0, stream_get_endp(msgc));
|
|
|
|
|
|
|
|
zebra_ptm_send_bfdd(msgc);
|
|
|
|
|
|
|
|
/* Registrate process PID for shutdown hook. */
|
|
|
|
STREAM_GETL(msg, ppid);
|
|
|
|
pp_new(ppid, zs);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
stream_failure:
|
|
|
|
zlog_err("%s:%d failed to registrate client pid", __FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_dst_register msg from client %s: length=%d",
|
|
|
|
zebra_route_string(client->proto), hdr->length);
|
|
|
|
|
|
|
|
_zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_REGISTER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
|
|
|
|
zebra_route_string(client->proto), hdr->length);
|
|
|
|
|
|
|
|
_zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_DEREGISTER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_client_register msg from client %s: length=%d",
|
|
|
|
zebra_route_string(client->proto), hdr->length);
|
|
|
|
|
|
|
|
_zebra_ptm_reroute(client, msg, ZEBRA_BFD_CLIENT_REGISTER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_bfd_dst_replay(ZAPI_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
struct stream *msgc;
|
|
|
|
size_t zmsglen, zhdrlen;
|
2018-07-11 20:55:12 +02:00
|
|
|
uint32_t cmd;
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* NOTE:
|
|
|
|
* Replay messages with HAVE_BFDD are meant to be replayed to
|
|
|
|
* the client daemons. These messages are composed and
|
|
|
|
* originated from the `bfdd` daemon.
|
|
|
|
*/
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("bfd_dst_update msg from client %s: length=%d",
|
|
|
|
zebra_route_string(client->proto), hdr->length);
|
|
|
|
|
2018-07-11 20:55:12 +02:00
|
|
|
/*
|
|
|
|
* Client messages must be re-routed, otherwise do the `bfdd`
|
|
|
|
* special treatment.
|
|
|
|
*/
|
|
|
|
if (client->proto != ZEBRA_ROUTE_BFD) {
|
|
|
|
_zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_REPLAY);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Figure out if this is an DEST_UPDATE or DEST_REPLAY. */
|
|
|
|
if (stream_getl2(msg, &cmd) == false) {
|
|
|
|
zlog_err("%s: expected at least 4 bytes (command)", __func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-27 18:40:50 +02:00
|
|
|
/*
|
|
|
|
* Don't modify message in the zebra API. In order to do that we
|
|
|
|
* need to allocate a new message stream and copy the message
|
|
|
|
* provided by zebra.
|
|
|
|
*/
|
|
|
|
msgc = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
|
|
|
if (msgc == NULL) {
|
2018-08-16 22:10:32 +02:00
|
|
|
zlog_debug("%s: not enough memory", __func__);
|
2018-06-27 18:40:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate our header size plus the message contents. */
|
2018-07-11 20:55:12 +02:00
|
|
|
if (cmd != ZEBRA_BFD_DEST_REPLAY) {
|
|
|
|
zhdrlen = ZEBRA_HEADER_SIZE;
|
|
|
|
zmsglen = msg->endp - msg->getp;
|
|
|
|
memcpy(msgc->data + zhdrlen, msg->data + msg->getp, zmsglen);
|
2018-06-27 18:40:50 +02:00
|
|
|
|
2018-07-11 20:55:12 +02:00
|
|
|
zclient_create_header(msgc, cmd, zvrf_id(zvrf));
|
|
|
|
|
|
|
|
msgc->getp = 0;
|
|
|
|
msgc->endp = zhdrlen + zmsglen;
|
|
|
|
} else
|
|
|
|
zclient_create_header(msgc, cmd, zvrf_id(zvrf));
|
2018-06-27 18:40:50 +02:00
|
|
|
|
|
|
|
/* Update the data pointers. */
|
|
|
|
stream_putw_at(msgc, 0, stream_get_endp(msgc));
|
|
|
|
|
|
|
|
zebra_ptm_send_clients(msgc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unused functions.
|
|
|
|
*/
|
|
|
|
void zebra_ptm_if_init(struct zebra_if *zifp __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
/* NOTHING */
|
|
|
|
}
|
|
|
|
|
|
|
|
int zebra_ptm_get_enable_state(void)
|
|
|
|
{
|
2018-08-16 22:29:08 +02:00
|
|
|
return 0;
|
2018-06-27 18:40:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_show_status(struct vty *vty __attribute__((__unused__)),
|
|
|
|
struct interface *ifp __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
/* NOTHING */
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_write(struct vty *vty __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
/* NOTHING */
|
|
|
|
}
|
|
|
|
|
|
|
|
void zebra_ptm_if_write(struct vty *vty __attribute__((__unused__)),
|
|
|
|
struct zebra_if *zifp __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
/* NOTHING */
|
|
|
|
}
|
|
|
|
void zebra_ptm_if_set_ptm_state(struct interface *i __attribute__((__unused__)),
|
|
|
|
struct zebra_if *zi __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
/* NOTHING */
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* HAVE_BFDD */
|