]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_ptm.c
*: add indent control files
[mirror_frr.git] / zebra / zebra_ptm.c
CommitLineData
244c1cdc
DS
1/* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
244c1cdc
DS
19 */
20
21#include <zebra.h>
22#include <sys/un.h> /* for sockaddr_un */
23#include <net/if.h>
c8ed14dd 24#include "vty.h"
244c1cdc
DS
25#include "zebra/zserv.h"
26#include "zebra/interface.h"
27#include "zebra/debug.h"
28#include "zebra/zebra_ptm.h"
29#include "if.h"
30#include "command.h"
c43ed2e4
DS
31#include "stream.h"
32#include "ptm_lib.h"
8f500a1c 33#include "network.h"
c8ed14dd 34#include "buffer.h"
c43ed2e4 35#include "zebra/zebra_ptm_redistribute.h"
68fe91d6 36#include "bfd.h"
d553294e 37#include "vrf.h"
7c551956
DS
38#include "rib.h"
39#include "zebra_vrf.h"
ae435b19 40#include "version.h"
244c1cdc
DS
41
42#define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
43#define ZEBRA_PTM_RECONNECT_TIME_MAX 300
c01acf98 44
c01acf98 45#define PTM_MSG_LEN 4
0a56c844 46#define PTM_HEADER_LEN 37
c43ed2e4
DS
47
48const char ZEBRA_PTM_GET_STATUS_CMD[] = "get-status";
49const char ZEBRA_PTM_BFD_START_CMD[] = "start-bfd-sess";
50const char ZEBRA_PTM_BFD_STOP_CMD[] = "stop-bfd-sess";
055c4dfc 51const char ZEBRA_PTM_BFD_CLIENT_REG_CMD[] = "reg-bfd-client";
567b877d 52const char ZEBRA_PTM_BFD_CLIENT_DEREG_CMD[] = "dereg-bfd-client";
c43ed2e4 53
c8ed14dd 54const char ZEBRA_PTM_CMD_STR[] = "cmd";
b255a4b1 55const char ZEBRA_PTM_CMD_STATUS_STR[] = "cmd_status";
c43ed2e4
DS
56const char ZEBRA_PTM_PORT_STR[] = "port";
57const char ZEBRA_PTM_CBL_STR[] = "cbl status";
58const char ZEBRA_PTM_PASS_STR[] = "pass";
59const char ZEBRA_PTM_FAIL_STR[] = "fail";
60const char ZEBRA_PTM_BFDSTATUS_STR[] = "state";
61const char ZEBRA_PTM_BFDSTATUS_UP_STR[] = "Up";
62const char ZEBRA_PTM_BFDSTATUS_DOWN_STR[] = "Down";
63const char ZEBRA_PTM_BFDDEST_STR[] = "peer";
64const char ZEBRA_PTM_BFDSRC_STR[] = "local";
d553294e 65const char ZEBRA_PTM_BFDVRF_STR[] = "vrf";
c43ed2e4
DS
66const char ZEBRA_PTM_INVALID_PORT_NAME[] = "N/A";
67const char ZEBRA_PTM_INVALID_SRC_IP[] = "N/A";
d553294e 68const char ZEBRA_PTM_INVALID_VRF[] = "N/A";
c43ed2e4
DS
69
70const char ZEBRA_PTM_BFD_DST_IP_FIELD[] = "dstIPaddr";
71const char ZEBRA_PTM_BFD_SRC_IP_FIELD[] = "srcIPaddr";
72const char ZEBRA_PTM_BFD_MIN_RX_FIELD[] = "requiredMinRx";
73const char ZEBRA_PTM_BFD_MIN_TX_FIELD[] = "upMinTx";
74const char ZEBRA_PTM_BFD_DETECT_MULT_FIELD[] = "detectMult";
75const char ZEBRA_PTM_BFD_MULTI_HOP_FIELD[] = "multiHop";
76const char ZEBRA_PTM_BFD_CLIENT_FIELD[] = "client";
77const char ZEBRA_PTM_BFD_SEQID_FIELD[] = "seqid";
78const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName";
79const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt";
68fe91d6 80const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent";
d553294e 81const char ZEBRA_PTM_BFD_VRF_NAME_FIELD[] = "vrfName";
c01acf98 82
c43ed2e4 83static ptm_lib_handle_t *ptm_hdl;
244c1cdc 84
c8ed14dd
DS
85struct zebra_ptm_cb ptm_cb;
86
244c1cdc 87static int zebra_ptm_socket_init(void);
244c1cdc
DS
88int zebra_ptm_sock_read(struct thread *);
89static void zebra_ptm_install_commands (void);
b255a4b1 90static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt);
c43ed2e4 91void zebra_bfd_peer_replay_req (void);
950bd436 92void zebra_ptm_send_status_req(void);
93void zebra_ptm_reset_status(int ptm_disable);
244c1cdc
DS
94
95const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket";
96
244c1cdc
DS
97void
98zebra_ptm_init (void)
99{
c43ed2e4
DS
100 char buf[64];
101
c8ed14dd
DS
102 memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb));
103
104 ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF);
105 if (!ptm_cb.out_data)
106 {
107 zlog_warn("%s: Allocation of send data failed", __func__);
108 return;
109 }
110
111 ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF);
112 if (!ptm_cb.in_data)
113 {
114 zlog_warn("%s: Allocation of recv data failed", __func__);
115 free(ptm_cb.out_data);
116 return;
117 }
118
119 ptm_cb.pid = getpid();
244c1cdc 120 zebra_ptm_install_commands();
c43ed2e4 121
ae435b19 122 sprintf(buf, "%s", FRR_PTM_NAME);
b255a4b1 123 ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb,
124 zebra_ptm_handle_msg_cb);
c8ed14dd
DS
125 ptm_cb.wb = buffer_new(0);
126
127 ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
128
129 ptm_cb.ptm_sock = -1;
130}
131
132void
133zebra_ptm_finish(void)
134{
2376c3f2 135 int proto;
c8ed14dd 136
2376c3f2 137 for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++)
138 if (CHECK_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG))
139 zebra_ptm_bfd_client_deregister(proto);
140
141 buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock);
c8ed14dd 142
58ac32e2
RW
143 free (ptm_hdl);
144
c8ed14dd
DS
145 if (ptm_cb.out_data)
146 free(ptm_cb.out_data);
147
148 if (ptm_cb.in_data)
149 free(ptm_cb.in_data);
150
151 /* Release threads. */
152 if (ptm_cb.t_read)
153 thread_cancel (ptm_cb.t_read);
154 if (ptm_cb.t_write)
155 thread_cancel (ptm_cb.t_write);
156 if (ptm_cb.t_timer)
157 thread_cancel (ptm_cb.t_timer);
2376c3f2 158
159 if (ptm_cb.wb)
160 buffer_free(ptm_cb.wb);
161
162 if (ptm_cb.ptm_sock != -1)
163 close(ptm_cb.ptm_sock);
c8ed14dd
DS
164}
165
166static int
167zebra_ptm_flush_messages (struct thread *thread)
168{
169 ptm_cb.t_write = NULL;
170
171 if (ptm_cb.ptm_sock == -1)
172 return -1;
173
174 errno = 0;
175
176 switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock))
177 {
178 case BUFFER_ERROR:
179 zlog_warn ("%s ptm socket error: %s", __func__,
180 safe_strerror (errno));
181 close(ptm_cb.ptm_sock);
182 ptm_cb.ptm_sock = -1;
950bd436 183 zebra_ptm_reset_status(0);
66e78ae6
QY
184 ptm_cb.t_timer = NULL;
185 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
186 &ptm_cb.t_timer);
c8ed14dd
DS
187 return (-1);
188 case BUFFER_PENDING:
66e78ae6
QY
189 ptm_cb.t_write = NULL;
190 thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, ptm_cb.ptm_sock,
191 &ptm_cb.t_write);
c8ed14dd
DS
192 break;
193 case BUFFER_EMPTY:
194 break;
195 }
196
197 return(0);
198}
199
200static int
201zebra_ptm_send_message(char *data, int size)
202{
203 errno = 0;
204 switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size))
205 {
206 case BUFFER_ERROR:
207 zlog_warn ("%s ptm socket error: %s", __func__, safe_strerror (errno));
208 close(ptm_cb.ptm_sock);
209 ptm_cb.ptm_sock = -1;
950bd436 210 zebra_ptm_reset_status(0);
66e78ae6
QY
211 ptm_cb.t_timer = NULL;
212 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
213 &ptm_cb.t_timer);
c8ed14dd
DS
214 return -1;
215 case BUFFER_EMPTY:
216 THREAD_OFF(ptm_cb.t_write);
217 break;
218 case BUFFER_PENDING:
ffa2c898
QY
219 thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL,
220 ptm_cb.ptm_sock, &ptm_cb.t_write);
c8ed14dd
DS
221 break;
222 }
223
224 return 0;
244c1cdc
DS
225}
226
227int
228zebra_ptm_connect (struct thread *t)
229{
c43ed2e4 230 int init = 0;
c43ed2e4 231
c8ed14dd 232 if (ptm_cb.ptm_sock == -1) {
c43ed2e4
DS
233 zebra_ptm_socket_init();
234 init = 1;
235 }
244c1cdc 236
c8ed14dd 237 if (ptm_cb.ptm_sock != -1) {
c43ed2e4 238 if (init) {
66e78ae6
QY
239 ptm_cb.t_read = NULL;
240 thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock,
241 &ptm_cb.t_read);
c43ed2e4
DS
242 zebra_bfd_peer_replay_req();
243 }
950bd436 244 zebra_ptm_send_status_req();
c8ed14dd 245 ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
986aa00f 246 } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX){
c8ed14dd
DS
247 ptm_cb.reconnect_time *= 2;
248 if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX)
249 ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX;
244c1cdc 250
66e78ae6
QY
251 ptm_cb.t_timer = NULL;
252 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
253 &ptm_cb.t_timer);
986aa00f 254 } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX){
255 ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
244c1cdc
DS
256 }
257
258 return(errno);
259}
260
244c1cdc
DS
261DEFUN (zebra_ptm_enable,
262 zebra_ptm_enable_cmd,
263 "ptm-enable",
264 "Enable neighbor check with specified topology\n")
265{
1a1a7065 266 struct vrf *vrf;
244c1cdc
DS
267 struct listnode *i;
268 struct interface *ifp;
986aa00f 269 struct zebra_if *if_data;
244c1cdc 270
986aa00f 271 ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON;
244c1cdc 272
a62c4901 273 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1a1a7065 274 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp))
b2d7c082
DS
275 if (!ifp->ptm_enable)
276 {
986aa00f 277 if_data = (struct zebra_if *)ifp->info;
278 if (if_data &&
279 (if_data->ptm_enable == ZEBRA_IF_PTM_ENABLE_UNSPEC))
280 {
281 ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON;
282 }
b2d7c082 283 /* Assign a default unknown status */
986aa00f 284 ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
b2d7c082 285 }
244c1cdc
DS
286
287 zebra_ptm_connect(NULL);
288
289 return CMD_SUCCESS;
290}
291
292DEFUN (no_zebra_ptm_enable,
293 no_zebra_ptm_enable_cmd,
294 "no ptm-enable",
295 NO_STR
296 "Enable neighbor check with specified topology\n")
297{
986aa00f 298 ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
950bd436 299 zebra_ptm_reset_status(1);
244c1cdc
DS
300 return CMD_SUCCESS;
301}
302
986aa00f 303DEFUN (zebra_ptm_enable_if,
304 zebra_ptm_enable_if_cmd,
305 "ptm-enable",
306 "Enable neighbor check with specified topology\n")
307{
3ddccf18 308 VTY_DECLVAR_CONTEXT (interface, ifp);
986aa00f 309 struct zebra_if *if_data;
310 int old_ptm_enable;
311 int send_linkdown = 0;
312
986aa00f 313 if (ifp->ifindex == IFINDEX_INTERNAL)
314 {
315 return CMD_SUCCESS;
316 }
317
318 old_ptm_enable = ifp->ptm_enable;
319 ifp->ptm_enable = ptm_cb.ptm_enable;
320
321 if (if_is_no_ptm_operative(ifp))
322 send_linkdown = 1;
323
324 if (!old_ptm_enable && ptm_cb.ptm_enable)
325 {
326 if (!if_is_operative (ifp) && send_linkdown)
327 {
328 if (IS_ZEBRA_DEBUG_EVENT)
329 zlog_debug ("%s: Bringing down interface %s\n", __func__,
330 ifp->name);
331 if_down (ifp);
332 }
333 }
334
335 if_data = ifp->info;
336 if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
337
338 return CMD_SUCCESS;
339}
340
341DEFUN (no_zebra_ptm_enable_if,
342 no_zebra_ptm_enable_if_cmd,
343 "no ptm-enable",
344 NO_STR
345 "Enable neighbor check with specified topology\n")
346{
3ddccf18 347 VTY_DECLVAR_CONTEXT (interface, ifp);
986aa00f 348 int send_linkup = 0;
349 struct zebra_if *if_data;
350
986aa00f 351 if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable))
352 {
353 if (!if_is_operative(ifp))
354 send_linkup = 1;
355
356 ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
357 if (if_is_no_ptm_operative (ifp) && send_linkup)
358 {
359 if (IS_ZEBRA_DEBUG_EVENT)
360 zlog_debug ("%s: Bringing up interface %s\n", __func__,
361 ifp->name);
362 if_up (ifp);
363 }
364 }
365
366 if_data = ifp->info;
367 if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
368
369 return CMD_SUCCESS;
370}
371
372
244c1cdc
DS
373void
374zebra_ptm_write (struct vty *vty)
375{
c8ed14dd 376 if (ptm_cb.ptm_enable)
5c7571d4 377 vty_out (vty, "ptm-enable\n");
244c1cdc
DS
378
379 return;
380}
381
382static int
383zebra_ptm_socket_init (void)
384{
385 int ret;
386 int sock;
387 struct sockaddr_un addr;
388
c8ed14dd 389 ptm_cb.ptm_sock = -1;
c01acf98 390
8f500a1c 391 sock = socket (PF_UNIX, SOCK_STREAM, 0);
244c1cdc
DS
392 if (sock < 0)
393 return -1;
8f500a1c 394 if (set_nonblocking(sock) < 0)
95c54276
DS
395 {
396 if (IS_ZEBRA_DEBUG_EVENT)
397 zlog_debug ("%s: Unable to set socket non blocking[%s]",
398 __PRETTY_FUNCTION__, safe_strerror (errno));
399 close (sock);
400 return -1;
401 }
244c1cdc
DS
402
403 /* Make server socket. */
404 memset (&addr, 0, sizeof (struct sockaddr_un));
405 addr.sun_family = AF_UNIX;
406 memcpy (&addr.sun_path, ZEBRA_PTM_SOCK_NAME,
407 sizeof(ZEBRA_PTM_SOCK_NAME));
408
409 ret = connect(sock, (struct sockaddr *) &addr,
c01acf98 410 sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1);
244c1cdc
DS
411 if (ret < 0)
412 {
986aa00f 413 if (IS_ZEBRA_DEBUG_EVENT)
414 zlog_debug("%s: Unable to connect to socket %s [%s]",
c01acf98 415 __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno));
244c1cdc
DS
416 close (sock);
417 return -1;
418 }
c8ed14dd 419 ptm_cb.ptm_sock = sock;
244c1cdc
DS
420 return sock;
421}
422
423static void
424zebra_ptm_install_commands (void)
425{
426 install_element (CONFIG_NODE, &zebra_ptm_enable_cmd);
427 install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd);
986aa00f 428 install_element (INTERFACE_NODE, &zebra_ptm_enable_if_cmd);
429 install_element (INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd);
244c1cdc
DS
430}
431
c43ed2e4 432/* BFD session goes down, send message to the protocols. */
c8ed14dd 433static void
68fe91d6 434if_bfd_session_update (struct interface *ifp, struct prefix *dp,
d553294e 435 struct prefix *sp, int status, vrf_id_t vrf_id)
c01acf98 436{
c43ed2e4
DS
437 if (IS_ZEBRA_DEBUG_EVENT)
438 {
439 char buf[2][INET6_ADDRSTRLEN];
440
441 if (ifp)
442 {
68fe91d6 443 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s"
444 " %s event",
445 inet_ntop (dp->family, &dp->u.prefix, buf[0],
446 INET6_ADDRSTRLEN), dp->prefixlen, ifp->name,
447 bfd_get_status_str(status));
c43ed2e4
DS
448 }
449 else
450 {
68fe91d6 451 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
d553294e 452 "with src %s/%d and vrf %d %s event",
c43ed2e4
DS
453 inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN),
454 dp->prefixlen,
455 inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN),
d553294e 456 sp->prefixlen, vrf_id, bfd_get_status_str(status));
c43ed2e4 457 }
c01acf98 458 }
c01acf98 459
d553294e 460 zebra_interface_bfd_update (ifp, dp, sp, status, vrf_id);
c01acf98
DS
461}
462
c43ed2e4 463static int
b255a4b1 464zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp)
244c1cdc 465{
c43ed2e4
DS
466 char bfdst_str[32];
467 char dest_str[64];
468 char src_str[64];
d553294e 469 char vrf_str[64];
244c1cdc 470 struct prefix dest_prefix;
c43ed2e4 471 struct prefix src_prefix;
3fa113f0 472 vrf_id_t vrf_id;
244c1cdc 473
c43ed2e4 474 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str);
c01acf98 475
c43ed2e4 476 if (bfdst_str[0] == '\0') {
c43ed2e4 477 return -1;
c01acf98
DS
478 }
479
c43ed2e4 480 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str);
c01acf98 481
c43ed2e4
DS
482 if (dest_str[0] == '\0') {
483 zlog_debug("%s: Key %s not found in PTM msg", __func__,
c01acf98 484 ZEBRA_PTM_BFDDEST_STR);
c43ed2e4 485 return -1;
c01acf98 486 }
244c1cdc 487
c43ed2e4 488 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str);
c01acf98 489
c43ed2e4
DS
490 if (src_str[0] == '\0') {
491 zlog_debug("%s: Key %s not found in PTM msg", __func__,
492 ZEBRA_PTM_BFDSRC_STR);
493 return -1;
c01acf98
DS
494 }
495
d553294e 496 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str);
497
498 if (vrf_str[0] == '\0') {
499 zlog_debug("%s: Key %s not found in PTM msg", __func__,
500 ZEBRA_PTM_BFDVRF_STR);
501 return -1;
502 }
503
c8ed14dd 504 if (IS_ZEBRA_DEBUG_EVENT)
3fa113f0 505 zlog_debug("%s: Recv Port [%s] bfd status [%s] vrf [%s]"
506 " peer [%s] local [%s]",
b255a4b1 507 __func__, ifp ? ifp->name : "N/A", bfdst_str,
d553294e 508 vrf_str, dest_str, src_str);
c43ed2e4 509
68fe91d6 510 if (str2prefix(dest_str, &dest_prefix) == 0) {
511 zlog_err("%s: Peer addr %s not found", __func__,
512 dest_str);
513 return -1;
514 }
c01acf98 515
68fe91d6 516 memset(&src_prefix, 0, sizeof(struct prefix));
517 if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
518 if (str2prefix(src_str, &src_prefix) == 0) {
519 zlog_err("%s: Local addr %s not found", __func__,
520 src_str);
521 return -1;
c43ed2e4 522 }
68fe91d6 523 }
c43ed2e4 524
3fa113f0 525 if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) {
526 vrf_id = ifp->vrf_id;
527 } else {
528 vrf_id = vrf_name_to_id(vrf_str);
529 }
530
68fe91d6 531 if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
d553294e 532 if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN,
3fa113f0 533 vrf_id);
68fe91d6 534 } else {
d553294e 535 if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP,
3fa113f0 536 vrf_id);
c01acf98 537 }
c43ed2e4
DS
538
539 return 0;
c01acf98
DS
540}
541
c43ed2e4 542static int
b255a4b1 543zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp,
544 char *cbl_str)
c01acf98 545{
950bd436 546 int send_linkup = 0;
547
b255a4b1 548 if (IS_ZEBRA_DEBUG_EVENT)
549 zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__,
550 ifp->name, cbl_str);
551
950bd436 552 if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) &&
553 (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) {
554
555 if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)
556 send_linkup = 1;
557 ifp->ptm_status = ZEBRA_PTM_STATUS_UP;
558 if (ifp->ptm_enable && if_is_no_ptm_operative (ifp) && send_linkup)
b255a4b1 559 if_up (ifp);
950bd436 560 } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) &&
561 (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) {
562 ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN;
b255a4b1 563 if (ifp->ptm_enable && if_is_no_ptm_operative (ifp))
564 if_down (ifp);
565 }
566
567 return 0;
568}
950bd436 569
b255a4b1 570/*
571 * zebra_ptm_handle_msg_cb - The purpose of this callback function is to handle
572 * all the command responses and notifications received from PTM.
573 *
574 * Command responses: Upon establishing connection with PTM, Zebra requests
575 * status of all interfaces using 'get-status' command if global ptm-enable
576 * knob is enabled. As a response to the get-status command PTM sends status
577 * of all the interfaces as command responses. All other type of command
578 * responses with cmd_status key word are dropped. The sole purpose of
579 * registering this function as callback for the command responses is to
580 * handle the responses to get-status command.
581 *
582 * Notifications: Cable status and BFD session status changes are sent as
583 * notifications by PTM. So, this function is also the callback function for
584 * processing all the notifications from the PTM.
585 *
586 */
587static int
588zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt)
589{
590 struct interface *ifp = NULL;
c43ed2e4 591 char port_str[128];
b255a4b1 592 char cbl_str[32];
593 char cmd_status_str[32];
c8ed14dd 594
b255a4b1 595 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR, cmd_status_str);
c8ed14dd
DS
596
597 /* Drop command response messages */
b255a4b1 598 if (cmd_status_str[0] != '\0') {
c8ed14dd
DS
599 return 0;
600 }
c01acf98 601
c43ed2e4 602 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str);
c01acf98 603
c43ed2e4 604 if (port_str[0] == '\0') {
b255a4b1 605 zlog_debug("%s: Key %s not found in PTM msg", __func__,
c01acf98 606 ZEBRA_PTM_PORT_STR);
b255a4b1 607 return -1;
c01acf98
DS
608 }
609
b255a4b1 610 if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) {
f8962871 611 ifp = if_lookup_by_name_all_vrf(port_str);
c01acf98 612
b255a4b1 613 if (!ifp) {
614 zlog_err("%s: %s not found in interface list", __func__, port_str);
615 return -1;
616 }
c01acf98
DS
617 }
618
b255a4b1 619 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str);
244c1cdc 620
b255a4b1 621 if (cbl_str[0] == '\0') {
622 return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp);
623 } else {
624 if (ifp) {
625 return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp, cbl_str);
626 } else {
627 return -1;
628 }
244c1cdc 629 }
c01acf98
DS
630}
631
c01acf98
DS
632int
633zebra_ptm_sock_read (struct thread *thread)
634{
635 int sock, done = 0;
c43ed2e4 636 int rc;
c01acf98 637
c43ed2e4 638 errno = 0;
c01acf98
DS
639 sock = THREAD_FD (thread);
640
641 if (sock == -1)
642 return -1;
643
644 /* PTM communicates in CSV format */
645 while(!done) {
c8ed14dd 646 rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, ZEBRA_PTM_MAX_SOCKBUF,
c43ed2e4
DS
647 NULL);
648 if (rc <= 0)
649 break;
c01acf98
DS
650 }
651
c43ed2e4
DS
652 if (rc <= 0) {
653 if (((rc == 0) && !errno) || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) {
654 zlog_warn ("%s routing socket error: %s(%d) bytes %d", __func__,
655 safe_strerror (errno), errno, rc);
c01acf98 656
c8ed14dd
DS
657 close (ptm_cb.ptm_sock);
658 ptm_cb.ptm_sock = -1;
950bd436 659 zebra_ptm_reset_status(0);
66e78ae6
QY
660 ptm_cb.t_timer = NULL;
661 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
662 &ptm_cb.t_timer);
c01acf98 663 return (-1);
0a56c844 664 }
c01acf98
DS
665 }
666
66e78ae6
QY
667 ptm_cb.t_read = NULL;
668 thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock,
669 &ptm_cb.t_read);
c43ed2e4
DS
670
671 return 0;
672}
673
674/* BFD peer/dst register/update */
675int
676zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
d651649e 677 int command, struct zebra_vrf *zvrf)
c43ed2e4 678{
c43ed2e4
DS
679 struct stream *s;
680 struct prefix src_p;
681 struct prefix dst_p;
682 u_char multi_hop;
683 u_char multi_hop_cnt;
684 u_char detect_mul;
685 unsigned int min_rx_timer;
686 unsigned int min_tx_timer;
687 char if_name[INTERFACE_NAMSIZ];
688 u_char len;
689 void *out_ctxt;
690 char buf[INET6_ADDRSTRLEN];
691 char tmp_buf[64];
692 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
055c4dfc 693 unsigned int pid;
c43ed2e4
DS
694
695 if (command == ZEBRA_BFD_DEST_UPDATE)
696 client->bfd_peer_upd8_cnt++;
697 else
698 client->bfd_peer_add_cnt++;
699
c8ed14dd
DS
700 if (IS_ZEBRA_DEBUG_EVENT)
701 zlog_debug("bfd_dst_register msg from client %s: length=%d",
702 zebra_route_string(client->proto), length);
c43ed2e4 703
c8ed14dd 704 if (ptm_cb.ptm_sock == -1)
c43ed2e4 705 {
66e78ae6
QY
706 ptm_cb.t_timer = NULL;
707 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
708 &ptm_cb.t_timer);
c43ed2e4
DS
709 return -1;
710 }
711
712 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
713 sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD);
c8ed14dd 714 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
055c4dfc 715 sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
c43ed2e4
DS
716 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
717 tmp_buf);
c43ed2e4
DS
718
719 s = client->ibuf;
720
055c4dfc 721 pid = stream_getl(s);
722 sprintf(tmp_buf, "%d", pid);
723 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf);
724
c43ed2e4
DS
725 dst_p.family = stream_getw(s);
726
727 if (dst_p.family == AF_INET)
728 dst_p.prefixlen = IPV4_MAX_BYTELEN;
729 else
730 dst_p.prefixlen = IPV6_MAX_BYTELEN;
731
732 stream_get(&dst_p.u.prefix, s, dst_p.prefixlen);
733 if (dst_p.family == AF_INET)
734 {
735 inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf));
736 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
737 }
c43ed2e4
DS
738 else
739 {
740 inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf));
741 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
742 }
c43ed2e4
DS
743
744 min_rx_timer = stream_getl(s);
745 sprintf(tmp_buf, "%d", min_rx_timer);
746 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD,
747 tmp_buf);
748 min_tx_timer = stream_getl(s);
749 sprintf(tmp_buf, "%d", min_tx_timer);
750 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD,
751 tmp_buf);
752 detect_mul = stream_getc(s);
753 sprintf(tmp_buf, "%d", detect_mul);
754 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD,
755 tmp_buf);
756
757 multi_hop = stream_getc(s);
758 if (multi_hop)
759 {
760 sprintf(tmp_buf, "%d", 1);
761 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD,
762 tmp_buf);
763 src_p.family = stream_getw(s);
764
765 if (src_p.family == AF_INET)
766 src_p.prefixlen = IPV4_MAX_BYTELEN;
767 else
768 src_p.prefixlen = IPV6_MAX_BYTELEN;
769
770 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
771 if (src_p.family == AF_INET)
772 {
773 inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
774 ptm_lib_append_msg(ptm_hdl, out_ctxt,
775 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
776 }
c43ed2e4
DS
777 else
778 {
779 inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
780 ptm_lib_append_msg(ptm_hdl, out_ctxt,
781 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
782 }
c43ed2e4
DS
783
784 multi_hop_cnt = stream_getc(s);
785 sprintf(tmp_buf, "%d", multi_hop_cnt);
786 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD,
787 tmp_buf);
d553294e 788
661512bf 789 if (zvrf_id (zvrf) != VRF_DEFAULT)
7b3eaa99 790 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
661512bf 791 zvrf_name (zvrf));
c43ed2e4
DS
792 }
793 else
794 {
c43ed2e4
DS
795 if (dst_p.family == AF_INET6)
796 {
797 src_p.family = stream_getw(s);
798
799 if (src_p.family == AF_INET)
800 src_p.prefixlen = IPV4_MAX_BYTELEN;
801 else
802 src_p.prefixlen = IPV6_MAX_BYTELEN;
803
804 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
805 if (src_p.family == AF_INET)
806 {
807 inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
808 ptm_lib_append_msg(ptm_hdl, out_ctxt,
809 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
810 }
811 else
812 {
813 inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
814 ptm_lib_append_msg(ptm_hdl, out_ctxt,
815 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
816 }
817 }
c43ed2e4
DS
818 len = stream_getc(s);
819 stream_get(if_name, s, len);
820 if_name[len] = '\0';
821
822 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD,
823 if_name);
824 }
825
68fe91d6 826 sprintf(tmp_buf, "%d", 1);
827 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT,
828 tmp_buf);
829
c8ed14dd
DS
830 ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
831
832 if (IS_ZEBRA_DEBUG_SEND)
833 zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
834 ptm_cb.out_data);
835 zebra_ptm_send_message(ptm_cb.out_data, data_len);
c43ed2e4
DS
836 return 0;
837}
838
839/* BFD peer/dst deregister */
840int
d553294e 841zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
d651649e 842 struct zebra_vrf *zvrf)
c43ed2e4 843{
c43ed2e4
DS
844 struct stream *s;
845 struct prefix src_p;
846 struct prefix dst_p;
847 u_char multi_hop;
848 char if_name[INTERFACE_NAMSIZ];
849 u_char len;
850 char buf[INET6_ADDRSTRLEN];
851 char tmp_buf[64];
852 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
853 void *out_ctxt;
055c4dfc 854 unsigned int pid;
c43ed2e4
DS
855
856 client->bfd_peer_del_cnt++;
857
c8ed14dd
DS
858 if (IS_ZEBRA_DEBUG_EVENT)
859 zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
860 zebra_route_string(client->proto), length);
c43ed2e4 861
c8ed14dd 862 if (ptm_cb.ptm_sock == -1)
c43ed2e4 863 {
66e78ae6
QY
864 ptm_cb.t_timer = NULL;
865 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
866 &ptm_cb.t_timer);
c43ed2e4
DS
867 return -1;
868 }
869
870 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
871
872 sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD);
c8ed14dd 873 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
c43ed2e4 874
055c4dfc 875 sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
c43ed2e4
DS
876 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
877 tmp_buf);
878
c43ed2e4
DS
879 s = client->ibuf;
880
055c4dfc 881 pid = stream_getl(s);
882 sprintf(tmp_buf, "%d", pid);
883 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf);
884
c43ed2e4
DS
885 dst_p.family = stream_getw(s);
886
887 if (dst_p.family == AF_INET)
888 dst_p.prefixlen = IPV4_MAX_BYTELEN;
889 else
890 dst_p.prefixlen = IPV6_MAX_BYTELEN;
891
892 stream_get(&dst_p.u.prefix, s, dst_p.prefixlen);
893 if (dst_p.family == AF_INET)
56c1f7d8 894 inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf));
c43ed2e4 895 else
56c1f7d8
DS
896 inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf));
897 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf);
898
c43ed2e4
DS
899
900 multi_hop = stream_getc(s);
901 if (multi_hop)
902 {
903 sprintf(tmp_buf, "%d", 1);
904 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD,
905 tmp_buf);
906
907 src_p.family = stream_getw(s);
908
909 if (src_p.family == AF_INET)
910 src_p.prefixlen = IPV4_MAX_BYTELEN;
911 else
912 src_p.prefixlen = IPV6_MAX_BYTELEN;
913
914 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
915 if (src_p.family == AF_INET)
602ba9bd 916 inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
c43ed2e4 917 else
602ba9bd
DS
918 inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
919 ptm_lib_append_msg(ptm_hdl, out_ctxt,
920 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
921
661512bf 922 if (zvrf_id (zvrf) != VRF_DEFAULT)
7b3eaa99 923 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
661512bf 924 zvrf_name (zvrf));
c43ed2e4
DS
925 }
926 else
927 {
c43ed2e4
DS
928 if (dst_p.family == AF_INET6)
929 {
930 src_p.family = stream_getw(s);
931
932 if (src_p.family == AF_INET)
933 src_p.prefixlen = IPV4_MAX_BYTELEN;
934 else
935 src_p.prefixlen = IPV6_MAX_BYTELEN;
936
937 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
938 if (src_p.family == AF_INET)
939 {
940 inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf));
941 ptm_lib_append_msg(ptm_hdl, out_ctxt,
942 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
943 }
944 else
945 {
946 inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf));
947 ptm_lib_append_msg(ptm_hdl, out_ctxt,
948 ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
949 }
950 }
c43ed2e4
DS
951
952 len = stream_getc(s);
953 stream_get(if_name, s, len);
954 if_name[len] = '\0';
955
956 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD,
957 if_name);
958 }
c01acf98 959
c8ed14dd
DS
960 ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
961 if (IS_ZEBRA_DEBUG_SEND)
962 zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
963 ptm_cb.out_data);
964
965 zebra_ptm_send_message(ptm_cb.out_data, data_len);
c01acf98
DS
966 return 0;
967}
c8ed14dd 968
055c4dfc 969/* BFD client register */
970int
971zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length)
972{
973 struct stream *s;
974 unsigned int pid;
975 void *out_ctxt;
976 char tmp_buf[64];
977 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
978
979 client->bfd_client_reg_cnt++;
980
981 if (IS_ZEBRA_DEBUG_EVENT)
982 zlog_debug("bfd_client_register msg from client %s: length=%d",
983 zebra_route_string(client->proto), length);
984
985 if (ptm_cb.ptm_sock == -1)
986 {
66e78ae6
QY
987 ptm_cb.t_timer = NULL;
988 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
989 &ptm_cb.t_timer);
055c4dfc 990 return -1;
991 }
992
993 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
994
995 sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD);
996 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
997
998 sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
999 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
1000 tmp_buf);
1001
1002 s = client->ibuf;
1003
1004 pid = stream_getl(s);
1005 sprintf(tmp_buf, "%d", pid);
1006 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
1007 tmp_buf);
1008
1009 ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
1010
1011 if (IS_ZEBRA_DEBUG_SEND)
1012 zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
1013 ptm_cb.out_data);
1014 zebra_ptm_send_message(ptm_cb.out_data, data_len);
2376c3f2 1015
1016 SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
055c4dfc 1017 return 0;
1018}
1019
567b877d 1020/* BFD client deregister */
1021void
2376c3f2 1022zebra_ptm_bfd_client_deregister (int proto)
567b877d 1023{
1024 void *out_ctxt;
1025 char tmp_buf[64];
1026 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
1027
2376c3f2 1028 if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP
ba4eb1bc 1029 && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM)
567b877d 1030 return;
1031
1032 if (IS_ZEBRA_DEBUG_EVENT)
2376c3f2 1033 zlog_err("bfd_client_deregister msg for client %s",
1034 zebra_route_string(proto));
567b877d 1035
1036 if (ptm_cb.ptm_sock == -1)
1037 {
66e78ae6
QY
1038 ptm_cb.t_timer = NULL;
1039 thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time,
1040 &ptm_cb.t_timer);
567b877d 1041 return;
1042 }
1043
1044 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
1045
1046 sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD);
1047 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
1048
2376c3f2 1049 sprintf(tmp_buf, "%s", zebra_route_string(proto));
567b877d 1050 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
1051 tmp_buf);
1052
1053 ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
1054
1055 if (IS_ZEBRA_DEBUG_SEND)
1056 zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
1057 ptm_cb.out_data);
2376c3f2 1058
567b877d 1059 zebra_ptm_send_message(ptm_cb.out_data, data_len);
2376c3f2 1060 UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
567b877d 1061}
1062
c8ed14dd
DS
1063int
1064zebra_ptm_get_enable_state(void)
1065{
1066 return ptm_cb.ptm_enable;
1067}
950bd436 1068
1069/*
1070 * zebra_ptm_get_status_str - Convert status to a display string.
1071 */
1072static const char *
1073zebra_ptm_get_status_str(int status)
1074{
1075 switch (status)
1076 {
1077 case ZEBRA_PTM_STATUS_DOWN:
1078 return "fail";
1079 case ZEBRA_PTM_STATUS_UP:
1080 return "pass";
1081 case ZEBRA_PTM_STATUS_UNKNOWN:
1082 default:
1083 return "n/a";
1084 }
1085}
1086
1087void
1088zebra_ptm_show_status(struct vty *vty, struct interface *ifp)
1089{
1090 vty_out (vty, " PTM status: ");
1091 if (ifp->ptm_enable) {
5c7571d4 1092 vty_out (vty, "%s\n",zebra_ptm_get_status_str(ifp->ptm_status));
950bd436 1093 } else {
5c7571d4 1094 vty_out (vty, "disabled\n");
950bd436 1095 }
1096}
1097
1098void
1099zebra_ptm_send_status_req(void)
1100{
1101 void *out_ctxt;
1102 int len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
1103
1104 if (ptm_cb.ptm_enable)
1105 {
1106 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
1107 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR,
1108 ZEBRA_PTM_GET_STATUS_CMD);
1109 ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len);
1110
1111 zebra_ptm_send_message(ptm_cb.out_data, len);
1112 }
1113}
1114
1115void
1116zebra_ptm_reset_status(int ptm_disable)
1117{
1a1a7065 1118 struct vrf *vrf;
950bd436 1119 struct listnode *i;
1120 struct interface *ifp;
1121 int send_linkup;
1122
1a1a7065
RW
1123 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
1124 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp))
b2d7c082
DS
1125 {
1126 send_linkup = 0;
1127 if (ifp->ptm_enable)
986aa00f 1128 {
1129 if (!if_is_operative(ifp))
1130 send_linkup = 1;
b2d7c082
DS
1131
1132 if (ptm_disable)
986aa00f 1133 ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
b2d7c082
DS
1134 ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
1135
986aa00f 1136 if (if_is_operative (ifp) && send_linkup)
1137 {
1138 if (IS_ZEBRA_DEBUG_EVENT)
1139 zlog_debug ("%s: Bringing up interface %s", __func__,
1140 ifp->name);
1141 if_up (ifp);
b2d7c082
DS
1142 }
1143 }
1144 }
950bd436 1145}
986aa00f 1146
1147void
1148zebra_ptm_if_init(struct zebra_if *zebra_ifp)
1149{
1150 zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
1151}
1152
1153void
1154zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp)
1155{
1156 if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC)
1157 ifp->ptm_enable = zebra_ifp->ptm_enable;
1158}
1159
1160void
1161zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp)
1162{
1163 if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF)
5c7571d4 1164 vty_out (vty, " no ptm-enable\n");
986aa00f 1165}