1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
22 #include <sys/un.h> /* for sockaddr_un */
25 #include "zebra/zserv.h"
26 #include "zebra/interface.h"
27 #include "zebra/debug.h"
28 #include "zebra/zebra_ptm.h"
35 #include "zebra/zebra_ptm_redistribute.h"
39 #include "zebra_vrf.h"
42 #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
43 #define ZEBRA_PTM_RECONNECT_TIME_MAX 300
46 #define PTM_HEADER_LEN 37
48 const char ZEBRA_PTM_GET_STATUS_CMD
[] = "get-status";
49 const char ZEBRA_PTM_BFD_START_CMD
[] = "start-bfd-sess";
50 const char ZEBRA_PTM_BFD_STOP_CMD
[] = "stop-bfd-sess";
51 const char ZEBRA_PTM_BFD_CLIENT_REG_CMD
[] = "reg-bfd-client";
52 const char ZEBRA_PTM_BFD_CLIENT_DEREG_CMD
[] = "dereg-bfd-client";
54 const char ZEBRA_PTM_CMD_STR
[] = "cmd";
55 const char ZEBRA_PTM_CMD_STATUS_STR
[] = "cmd_status";
56 const char ZEBRA_PTM_PORT_STR
[] = "port";
57 const char ZEBRA_PTM_CBL_STR
[] = "cbl status";
58 const char ZEBRA_PTM_PASS_STR
[] = "pass";
59 const char ZEBRA_PTM_FAIL_STR
[] = "fail";
60 const char ZEBRA_PTM_BFDSTATUS_STR
[] = "state";
61 const char ZEBRA_PTM_BFDSTATUS_UP_STR
[] = "Up";
62 const char ZEBRA_PTM_BFDSTATUS_DOWN_STR
[] = "Down";
63 const char ZEBRA_PTM_BFDDEST_STR
[] = "peer";
64 const char ZEBRA_PTM_BFDSRC_STR
[] = "local";
65 const char ZEBRA_PTM_BFDVRF_STR
[] = "vrf";
66 const char ZEBRA_PTM_INVALID_PORT_NAME
[] = "N/A";
67 const char ZEBRA_PTM_INVALID_SRC_IP
[] = "N/A";
68 const char ZEBRA_PTM_INVALID_VRF
[] = "N/A";
70 const char ZEBRA_PTM_BFD_DST_IP_FIELD
[] = "dstIPaddr";
71 const char ZEBRA_PTM_BFD_SRC_IP_FIELD
[] = "srcIPaddr";
72 const char ZEBRA_PTM_BFD_MIN_RX_FIELD
[] = "requiredMinRx";
73 const char ZEBRA_PTM_BFD_MIN_TX_FIELD
[] = "upMinTx";
74 const char ZEBRA_PTM_BFD_DETECT_MULT_FIELD
[] = "detectMult";
75 const char ZEBRA_PTM_BFD_MULTI_HOP_FIELD
[] = "multiHop";
76 const char ZEBRA_PTM_BFD_CLIENT_FIELD
[] = "client";
77 const char ZEBRA_PTM_BFD_SEQID_FIELD
[] = "seqid";
78 const char ZEBRA_PTM_BFD_IFNAME_FIELD
[] = "ifName";
79 const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD
[] = "maxHopCnt";
80 const char ZEBRA_PTM_BFD_SEND_EVENT
[] = "sendEvent";
81 const char ZEBRA_PTM_BFD_VRF_NAME_FIELD
[] = "vrfName";
83 static ptm_lib_handle_t
*ptm_hdl
;
85 struct zebra_ptm_cb ptm_cb
;
87 static int zebra_ptm_socket_init(void);
88 int zebra_ptm_sock_read(struct thread
*);
89 static void zebra_ptm_install_commands (void);
90 static int zebra_ptm_handle_msg_cb(void *arg
, void *in_ctxt
);
91 void zebra_bfd_peer_replay_req (void);
92 void zebra_ptm_send_status_req(void);
93 void zebra_ptm_reset_status(int ptm_disable
);
95 const char ZEBRA_PTM_SOCK_NAME
[] = "\0/var/run/ptmd.socket";
102 memset(&ptm_cb
, 0, sizeof(struct zebra_ptm_cb
));
104 ptm_cb
.out_data
= calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF
);
105 if (!ptm_cb
.out_data
)
107 zlog_warn("%s: Allocation of send data failed", __func__
);
111 ptm_cb
.in_data
= calloc(1, ZEBRA_PTM_MAX_SOCKBUF
);
114 zlog_warn("%s: Allocation of recv data failed", __func__
);
115 free(ptm_cb
.out_data
);
119 ptm_cb
.pid
= getpid();
120 zebra_ptm_install_commands();
122 sprintf(buf
, "%s", FRR_PTM_NAME
);
123 ptm_hdl
= ptm_lib_register(buf
, NULL
, zebra_ptm_handle_msg_cb
,
124 zebra_ptm_handle_msg_cb
);
125 ptm_cb
.wb
= buffer_new(0);
127 ptm_cb
.reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
129 ptm_cb
.ptm_sock
= -1;
133 zebra_ptm_finish(void)
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
);
141 buffer_flush_all(ptm_cb
.wb
, ptm_cb
.ptm_sock
);
146 free(ptm_cb
.out_data
);
149 free(ptm_cb
.in_data
);
151 /* Release threads. */
153 thread_cancel (ptm_cb
.t_read
);
155 thread_cancel (ptm_cb
.t_write
);
157 thread_cancel (ptm_cb
.t_timer
);
160 buffer_free(ptm_cb
.wb
);
162 if (ptm_cb
.ptm_sock
!= -1)
163 close(ptm_cb
.ptm_sock
);
167 zebra_ptm_flush_messages (struct thread
*thread
)
169 ptm_cb
.t_write
= NULL
;
171 if (ptm_cb
.ptm_sock
== -1)
176 switch (buffer_flush_available(ptm_cb
.wb
, ptm_cb
.ptm_sock
))
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;
183 zebra_ptm_reset_status(0);
184 ptm_cb
.t_timer
= NULL
;
185 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
189 ptm_cb
.t_write
= NULL
;
190 thread_add_write(zebrad
.master
, zebra_ptm_flush_messages
, NULL
, ptm_cb
.ptm_sock
,
201 zebra_ptm_send_message(char *data
, int size
)
204 switch (buffer_write(ptm_cb
.wb
, ptm_cb
.ptm_sock
, data
, size
))
207 zlog_warn ("%s ptm socket error: %s", __func__
, safe_strerror (errno
));
208 close(ptm_cb
.ptm_sock
);
209 ptm_cb
.ptm_sock
= -1;
210 zebra_ptm_reset_status(0);
211 ptm_cb
.t_timer
= NULL
;
212 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
216 THREAD_OFF(ptm_cb
.t_write
);
219 thread_add_write(zebrad
.master
, zebra_ptm_flush_messages
, NULL
,
220 ptm_cb
.ptm_sock
, &ptm_cb
.t_write
);
228 zebra_ptm_connect (struct thread
*t
)
232 if (ptm_cb
.ptm_sock
== -1) {
233 zebra_ptm_socket_init();
237 if (ptm_cb
.ptm_sock
!= -1) {
239 ptm_cb
.t_read
= NULL
;
240 thread_add_read(zebrad
.master
, zebra_ptm_sock_read
, NULL
, ptm_cb
.ptm_sock
,
242 zebra_bfd_peer_replay_req();
244 zebra_ptm_send_status_req();
245 ptm_cb
.reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
246 } else if (ptm_cb
.reconnect_time
< ZEBRA_PTM_RECONNECT_TIME_MAX
){
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
;
251 ptm_cb
.t_timer
= NULL
;
252 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
254 } else if (ptm_cb
.reconnect_time
>= ZEBRA_PTM_RECONNECT_TIME_MAX
){
255 ptm_cb
.reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
261 DEFUN (zebra_ptm_enable
,
262 zebra_ptm_enable_cmd
,
264 "Enable neighbor check with specified topology\n")
268 struct interface
*ifp
;
269 struct zebra_if
*if_data
;
271 ptm_cb
.ptm_enable
= ZEBRA_IF_PTM_ENABLE_ON
;
273 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
274 for (ALL_LIST_ELEMENTS_RO (vrf
->iflist
, i
, ifp
))
275 if (!ifp
->ptm_enable
)
277 if_data
= (struct zebra_if
*)ifp
->info
;
279 (if_data
->ptm_enable
== ZEBRA_IF_PTM_ENABLE_UNSPEC
))
281 ifp
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_ON
;
283 /* Assign a default unknown status */
284 ifp
->ptm_status
= ZEBRA_PTM_STATUS_UNKNOWN
;
287 zebra_ptm_connect(NULL
);
292 DEFUN (no_zebra_ptm_enable
,
293 no_zebra_ptm_enable_cmd
,
296 "Enable neighbor check with specified topology\n")
298 ptm_cb
.ptm_enable
= ZEBRA_IF_PTM_ENABLE_OFF
;
299 zebra_ptm_reset_status(1);
303 DEFUN (zebra_ptm_enable_if
,
304 zebra_ptm_enable_if_cmd
,
306 "Enable neighbor check with specified topology\n")
308 VTY_DECLVAR_CONTEXT (interface
, ifp
);
309 struct zebra_if
*if_data
;
311 int send_linkdown
= 0;
313 if (ifp
->ifindex
== IFINDEX_INTERNAL
)
318 old_ptm_enable
= ifp
->ptm_enable
;
319 ifp
->ptm_enable
= ptm_cb
.ptm_enable
;
321 if (if_is_no_ptm_operative(ifp
))
324 if (!old_ptm_enable
&& ptm_cb
.ptm_enable
)
326 if (!if_is_operative (ifp
) && send_linkdown
)
328 if (IS_ZEBRA_DEBUG_EVENT
)
329 zlog_debug ("%s: Bringing down interface %s\n", __func__
,
336 if_data
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_UNSPEC
;
341 DEFUN (no_zebra_ptm_enable_if
,
342 no_zebra_ptm_enable_if_cmd
,
345 "Enable neighbor check with specified topology\n")
347 VTY_DECLVAR_CONTEXT (interface
, ifp
);
349 struct zebra_if
*if_data
;
351 if ((ifp
->ifindex
!= IFINDEX_INTERNAL
) && (ifp
->ptm_enable
))
353 if (!if_is_operative(ifp
))
356 ifp
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_OFF
;
357 if (if_is_no_ptm_operative (ifp
) && send_linkup
)
359 if (IS_ZEBRA_DEBUG_EVENT
)
360 zlog_debug ("%s: Bringing up interface %s\n", __func__
,
367 if_data
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_OFF
;
374 zebra_ptm_write (struct vty
*vty
)
376 if (ptm_cb
.ptm_enable
)
377 vty_out (vty
, "ptm-enable%s", VTY_NEWLINE
);
383 zebra_ptm_socket_init (void)
387 struct sockaddr_un addr
;
389 ptm_cb
.ptm_sock
= -1;
391 sock
= socket (PF_UNIX
, SOCK_STREAM
, 0);
394 if (set_nonblocking(sock
) < 0)
396 if (IS_ZEBRA_DEBUG_EVENT
)
397 zlog_debug ("%s: Unable to set socket non blocking[%s]",
398 __PRETTY_FUNCTION__
, safe_strerror (errno
));
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
));
409 ret
= connect(sock
, (struct sockaddr
*) &addr
,
410 sizeof (addr
.sun_family
)+sizeof (ZEBRA_PTM_SOCK_NAME
)-1);
413 if (IS_ZEBRA_DEBUG_EVENT
)
414 zlog_debug("%s: Unable to connect to socket %s [%s]",
415 __func__
, ZEBRA_PTM_SOCK_NAME
, safe_strerror(errno
));
419 ptm_cb
.ptm_sock
= sock
;
424 zebra_ptm_install_commands (void)
426 install_element (CONFIG_NODE
, &zebra_ptm_enable_cmd
);
427 install_element (CONFIG_NODE
, &no_zebra_ptm_enable_cmd
);
428 install_element (INTERFACE_NODE
, &zebra_ptm_enable_if_cmd
);
429 install_element (INTERFACE_NODE
, &no_zebra_ptm_enable_if_cmd
);
432 /* BFD session goes down, send message to the protocols. */
434 if_bfd_session_update (struct interface
*ifp
, struct prefix
*dp
,
435 struct prefix
*sp
, int status
, vrf_id_t vrf_id
)
437 if (IS_ZEBRA_DEBUG_EVENT
)
439 char buf
[2][INET6_ADDRSTRLEN
];
443 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s"
445 inet_ntop (dp
->family
, &dp
->u
.prefix
, buf
[0],
446 INET6_ADDRSTRLEN
), dp
->prefixlen
, ifp
->name
,
447 bfd_get_status_str(status
));
451 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
452 "with src %s/%d and vrf %d %s event",
453 inet_ntop (dp
->family
, &dp
->u
.prefix
, buf
[0], INET6_ADDRSTRLEN
),
455 inet_ntop (sp
->family
, &sp
->u
.prefix
, buf
[1], INET6_ADDRSTRLEN
),
456 sp
->prefixlen
, vrf_id
, bfd_get_status_str(status
));
460 zebra_interface_bfd_update (ifp
, dp
, sp
, status
, vrf_id
);
464 zebra_ptm_handle_bfd_msg(void *arg
, void *in_ctxt
, struct interface
*ifp
)
470 struct prefix dest_prefix
;
471 struct prefix src_prefix
;
474 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDSTATUS_STR
, bfdst_str
);
476 if (bfdst_str
[0] == '\0') {
480 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDDEST_STR
, dest_str
);
482 if (dest_str
[0] == '\0') {
483 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
484 ZEBRA_PTM_BFDDEST_STR
);
488 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDSRC_STR
, src_str
);
490 if (src_str
[0] == '\0') {
491 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
492 ZEBRA_PTM_BFDSRC_STR
);
496 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDVRF_STR
, vrf_str
);
498 if (vrf_str
[0] == '\0') {
499 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
500 ZEBRA_PTM_BFDVRF_STR
);
504 if (IS_ZEBRA_DEBUG_EVENT
)
505 zlog_debug("%s: Recv Port [%s] bfd status [%s] vrf [%s]"
506 " peer [%s] local [%s]",
507 __func__
, ifp
? ifp
->name
: "N/A", bfdst_str
,
508 vrf_str
, dest_str
, src_str
);
510 if (str2prefix(dest_str
, &dest_prefix
) == 0) {
511 zlog_err("%s: Peer addr %s not found", __func__
,
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__
,
525 if (!strcmp(ZEBRA_PTM_INVALID_VRF
, vrf_str
) && ifp
) {
526 vrf_id
= ifp
->vrf_id
;
528 vrf_id
= vrf_name_to_id(vrf_str
);
531 if (!strcmp (bfdst_str
, ZEBRA_PTM_BFDSTATUS_DOWN_STR
)) {
532 if_bfd_session_update(ifp
, &dest_prefix
, &src_prefix
, BFD_STATUS_DOWN
,
535 if_bfd_session_update(ifp
, &dest_prefix
, &src_prefix
, BFD_STATUS_UP
,
543 zebra_ptm_handle_cbl_msg(void *arg
, void *in_ctxt
, struct interface
*ifp
,
548 if (IS_ZEBRA_DEBUG_EVENT
)
549 zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__
,
552 if (!strcmp(cbl_str
, ZEBRA_PTM_PASS_STR
) &&
553 (ifp
->ptm_status
!= ZEBRA_PTM_STATUS_UP
)) {
555 if (ifp
->ptm_status
== ZEBRA_PTM_STATUS_DOWN
)
557 ifp
->ptm_status
= ZEBRA_PTM_STATUS_UP
;
558 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
) && send_linkup
)
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
;
563 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
))
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.
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.
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.
588 zebra_ptm_handle_msg_cb(void *arg
, void *in_ctxt
)
590 struct interface
*ifp
= NULL
;
593 char cmd_status_str
[32];
595 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_CMD_STATUS_STR
, cmd_status_str
);
597 /* Drop command response messages */
598 if (cmd_status_str
[0] != '\0') {
602 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_PORT_STR
, port_str
);
604 if (port_str
[0] == '\0') {
605 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
610 if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME
, port_str
)) {
611 ifp
= if_lookup_by_name_all_vrf(port_str
);
614 zlog_err("%s: %s not found in interface list", __func__
, port_str
);
619 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_CBL_STR
, cbl_str
);
621 if (cbl_str
[0] == '\0') {
622 return zebra_ptm_handle_bfd_msg(arg
, in_ctxt
, ifp
);
625 return zebra_ptm_handle_cbl_msg(arg
, in_ctxt
, ifp
, cbl_str
);
633 zebra_ptm_sock_read (struct thread
*thread
)
639 sock
= THREAD_FD (thread
);
644 /* PTM communicates in CSV format */
646 rc
= ptm_lib_process_msg(ptm_hdl
, sock
, ptm_cb
.in_data
, ZEBRA_PTM_MAX_SOCKBUF
,
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
);
657 close (ptm_cb
.ptm_sock
);
658 ptm_cb
.ptm_sock
= -1;
659 zebra_ptm_reset_status(0);
660 ptm_cb
.t_timer
= NULL
;
661 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
667 ptm_cb
.t_read
= NULL
;
668 thread_add_read(zebrad
.master
, zebra_ptm_sock_read
, NULL
, ptm_cb
.ptm_sock
,
674 /* BFD peer/dst register/update */
676 zebra_ptm_bfd_dst_register (struct zserv
*client
, int sock
, u_short length
,
677 int command
, struct zebra_vrf
*zvrf
)
683 u_char multi_hop_cnt
;
685 unsigned int min_rx_timer
;
686 unsigned int min_tx_timer
;
687 char if_name
[INTERFACE_NAMSIZ
];
690 char buf
[INET6_ADDRSTRLEN
];
692 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
695 if (command
== ZEBRA_BFD_DEST_UPDATE
)
696 client
->bfd_peer_upd8_cnt
++;
698 client
->bfd_peer_add_cnt
++;
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
);
704 if (ptm_cb
.ptm_sock
== -1)
706 ptm_cb
.t_timer
= NULL
;
707 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
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
);
714 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_CMD_STR
, tmp_buf
);
715 sprintf(tmp_buf
, "%s", zebra_route_string(client
->proto
));
716 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
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
);
725 dst_p
.family
= stream_getw(s
);
727 if (dst_p
.family
== AF_INET
)
728 dst_p
.prefixlen
= IPV4_MAX_BYTELEN
;
730 dst_p
.prefixlen
= IPV6_MAX_BYTELEN
;
732 stream_get(&dst_p
.u
.prefix
, s
, dst_p
.prefixlen
);
733 if (dst_p
.family
== AF_INET
)
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
);
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
);
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
,
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
,
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
,
757 multi_hop
= stream_getc(s
);
760 sprintf(tmp_buf
, "%d", 1);
761 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MULTI_HOP_FIELD
,
763 src_p
.family
= stream_getw(s
);
765 if (src_p
.family
== AF_INET
)
766 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
768 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
770 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
771 if (src_p
.family
== AF_INET
)
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
);
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
);
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
,
789 if (zvrf_id (zvrf
) != VRF_DEFAULT
)
790 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_VRF_NAME_FIELD
,
795 if (dst_p
.family
== AF_INET6
)
797 src_p
.family
= stream_getw(s
);
799 if (src_p
.family
== AF_INET
)
800 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
802 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
804 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
805 if (src_p
.family
== AF_INET
)
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
);
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
);
818 len
= stream_getc(s
);
819 stream_get(if_name
, s
, len
);
822 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_IFNAME_FIELD
,
826 sprintf(tmp_buf
, "%d", 1);
827 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_SEND_EVENT
,
830 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, ptm_cb
.out_data
, &data_len
);
832 if (IS_ZEBRA_DEBUG_SEND
)
833 zlog_debug ("%s: Sent message (%d) %s", __func__
, data_len
,
835 zebra_ptm_send_message(ptm_cb
.out_data
, data_len
);
839 /* BFD peer/dst deregister */
841 zebra_ptm_bfd_dst_deregister (struct zserv
*client
, int sock
, u_short length
,
842 struct zebra_vrf
*zvrf
)
848 char if_name
[INTERFACE_NAMSIZ
];
850 char buf
[INET6_ADDRSTRLEN
];
852 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
856 client
->bfd_peer_del_cnt
++;
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
);
862 if (ptm_cb
.ptm_sock
== -1)
864 ptm_cb
.t_timer
= NULL
;
865 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
870 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
872 sprintf(tmp_buf
, "%s", ZEBRA_PTM_BFD_STOP_CMD
);
873 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_CMD_STR
, tmp_buf
);
875 sprintf(tmp_buf
, "%s", zebra_route_string(client
->proto
));
876 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
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
);
885 dst_p
.family
= stream_getw(s
);
887 if (dst_p
.family
== AF_INET
)
888 dst_p
.prefixlen
= IPV4_MAX_BYTELEN
;
890 dst_p
.prefixlen
= IPV6_MAX_BYTELEN
;
892 stream_get(&dst_p
.u
.prefix
, s
, dst_p
.prefixlen
);
893 if (dst_p
.family
== AF_INET
)
894 inet_ntop(AF_INET
, &dst_p
.u
.prefix4
, buf
, sizeof(buf
));
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
);
900 multi_hop
= stream_getc(s
);
903 sprintf(tmp_buf
, "%d", 1);
904 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MULTI_HOP_FIELD
,
907 src_p
.family
= stream_getw(s
);
909 if (src_p
.family
== AF_INET
)
910 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
912 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
914 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
915 if (src_p
.family
== AF_INET
)
916 inet_ntop(AF_INET
, &src_p
.u
.prefix4
, buf
, sizeof(buf
));
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
);
922 if (zvrf_id (zvrf
) != VRF_DEFAULT
)
923 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_VRF_NAME_FIELD
,
928 if (dst_p
.family
== AF_INET6
)
930 src_p
.family
= stream_getw(s
);
932 if (src_p
.family
== AF_INET
)
933 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
935 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
937 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
938 if (src_p
.family
== AF_INET
)
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
);
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
);
952 len
= stream_getc(s
);
953 stream_get(if_name
, s
, len
);
956 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_IFNAME_FIELD
,
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
,
965 zebra_ptm_send_message(ptm_cb
.out_data
, data_len
);
969 /* BFD client register */
971 zebra_ptm_bfd_client_register (struct zserv
*client
, int sock
, u_short length
)
977 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
979 client
->bfd_client_reg_cnt
++;
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
);
985 if (ptm_cb
.ptm_sock
== -1)
987 ptm_cb
.t_timer
= NULL
;
988 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
993 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
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
);
998 sprintf(tmp_buf
, "%s", zebra_route_string(client
->proto
));
999 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
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
,
1009 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, ptm_cb
.out_data
, &data_len
);
1011 if (IS_ZEBRA_DEBUG_SEND
)
1012 zlog_debug ("%s: Sent message (%d) %s", __func__
, data_len
,
1014 zebra_ptm_send_message(ptm_cb
.out_data
, data_len
);
1016 SET_FLAG(ptm_cb
.client_flags
[client
->proto
], ZEBRA_PTM_BFD_CLIENT_FLAG_REG
);
1020 /* BFD client deregister */
1022 zebra_ptm_bfd_client_deregister (int proto
)
1026 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
1028 if (proto
!= ZEBRA_ROUTE_OSPF
&& proto
!= ZEBRA_ROUTE_BGP
1029 && proto
!= ZEBRA_ROUTE_OSPF6
)
1032 if (IS_ZEBRA_DEBUG_EVENT
)
1033 zlog_err("bfd_client_deregister msg for client %s",
1034 zebra_route_string(proto
));
1036 if (ptm_cb
.ptm_sock
== -1)
1038 ptm_cb
.t_timer
= NULL
;
1039 thread_add_timer(zebrad
.master
, zebra_ptm_connect
, NULL
, ptm_cb
.reconnect_time
,
1044 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
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
);
1049 sprintf(tmp_buf
, "%s", zebra_route_string(proto
));
1050 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
1053 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, ptm_cb
.out_data
, &data_len
);
1055 if (IS_ZEBRA_DEBUG_SEND
)
1056 zlog_debug ("%s: Sent message (%d) %s", __func__
, data_len
,
1059 zebra_ptm_send_message(ptm_cb
.out_data
, data_len
);
1060 UNSET_FLAG(ptm_cb
.client_flags
[proto
], ZEBRA_PTM_BFD_CLIENT_FLAG_REG
);
1064 zebra_ptm_get_enable_state(void)
1066 return ptm_cb
.ptm_enable
;
1070 * zebra_ptm_get_status_str - Convert status to a display string.
1073 zebra_ptm_get_status_str(int status
)
1077 case ZEBRA_PTM_STATUS_DOWN
:
1079 case ZEBRA_PTM_STATUS_UP
:
1081 case ZEBRA_PTM_STATUS_UNKNOWN
:
1088 zebra_ptm_show_status(struct vty
*vty
, struct interface
*ifp
)
1090 vty_out (vty
, " PTM status: ");
1091 if (ifp
->ptm_enable
) {
1092 vty_out (vty
, "%s%s", zebra_ptm_get_status_str (ifp
->ptm_status
),
1095 vty_out (vty
, "disabled%s", VTY_NEWLINE
);
1100 zebra_ptm_send_status_req(void)
1103 int len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
1105 if (ptm_cb
.ptm_enable
)
1107 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
1108 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_CMD_STR
,
1109 ZEBRA_PTM_GET_STATUS_CMD
);
1110 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, ptm_cb
.out_data
, &len
);
1112 zebra_ptm_send_message(ptm_cb
.out_data
, len
);
1117 zebra_ptm_reset_status(int ptm_disable
)
1121 struct interface
*ifp
;
1124 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
1125 for (ALL_LIST_ELEMENTS_RO (vrf
->iflist
, i
, ifp
))
1128 if (ifp
->ptm_enable
)
1130 if (!if_is_operative(ifp
))
1134 ifp
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_OFF
;
1135 ifp
->ptm_status
= ZEBRA_PTM_STATUS_UNKNOWN
;
1137 if (if_is_operative (ifp
) && send_linkup
)
1139 if (IS_ZEBRA_DEBUG_EVENT
)
1140 zlog_debug ("%s: Bringing up interface %s", __func__
,
1149 zebra_ptm_if_init(struct zebra_if
*zebra_ifp
)
1151 zebra_ifp
->ptm_enable
= ZEBRA_IF_PTM_ENABLE_UNSPEC
;
1155 zebra_ptm_if_set_ptm_state(struct interface
*ifp
, struct zebra_if
*zebra_ifp
)
1157 if (zebra_ifp
&& zebra_ifp
->ptm_enable
!= ZEBRA_IF_PTM_ENABLE_UNSPEC
)
1158 ifp
->ptm_enable
= zebra_ifp
->ptm_enable
;
1162 zebra_ptm_if_write (struct vty
*vty
, struct zebra_if
*zebra_ifp
)
1164 if (zebra_ifp
->ptm_enable
== ZEBRA_IF_PTM_ENABLE_OFF
)
1165 vty_out (vty
, " no ptm-enable%s", VTY_NEWLINE
);