2 * Copyright (C) 2018 Yasuhiro Ohara
3 * Copyright (C) 2019 David Lamparter for NetDEF, Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "sockunion.h"
34 #include "lib_errors.h"
39 #include "termtable.h"
41 #include "bgpd/bgp_table.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_route.h"
44 #include "bgpd/bgp_attr.h"
45 #include "bgpd/bgp_dump.h"
46 #include "bgpd/bgp_errors.h"
47 #include "bgpd/bgp_packet.h"
48 #include "bgpd/bgp_bmp.h"
49 #include "bgpd/bgp_fsm.h"
50 #include "bgpd/bgp_updgrp.h"
51 #include "bgpd/bgp_vty.h"
52 #include "bgpd/bgp_trace.h"
54 static void bmp_close(struct bmp
*bmp
);
55 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
);
56 static void bmp_targets_put(struct bmp_targets
*bt
);
57 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
);
58 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
);
59 static void bmp_active_disconnected(struct bmp_active
*ba
);
60 static void bmp_active_put(struct bmp_active
*ba
);
62 DEFINE_MGROUP(BMP
, "BMP (BGP Monitoring Protocol)");
64 DEFINE_MTYPE_STATIC(BMP
, BMP_CONN
, "BMP connection state");
65 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETS
, "BMP targets");
66 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETSNAME
, "BMP targets name");
67 DEFINE_MTYPE_STATIC(BMP
, BMP_LISTENER
, "BMP listener");
68 DEFINE_MTYPE_STATIC(BMP
, BMP_ACTIVE
, "BMP active connection config");
69 DEFINE_MTYPE_STATIC(BMP
, BMP_ACLNAME
, "BMP access-list name");
70 DEFINE_MTYPE_STATIC(BMP
, BMP_QUEUE
, "BMP update queue item");
71 DEFINE_MTYPE_STATIC(BMP
, BMP
, "BMP instance state");
72 DEFINE_MTYPE_STATIC(BMP
, BMP_MIRRORQ
, "BMP route mirroring buffer");
73 DEFINE_MTYPE_STATIC(BMP
, BMP_PEER
, "BMP per BGP peer data");
74 DEFINE_MTYPE_STATIC(BMP
, BMP_OPEN
, "BMP stored BGP OPEN message");
76 DEFINE_QOBJ_TYPE(bmp_targets
);
78 static int bmp_bgp_cmp(const struct bmp_bgp
*a
, const struct bmp_bgp
*b
)
87 static uint32_t bmp_bgp_hash(const struct bmp_bgp
*e
)
89 return jhash(&e
->bgp
, sizeof(e
->bgp
), 0x55aa5a5a);
92 DECLARE_HASH(bmp_bgph
, struct bmp_bgp
, bbi
, bmp_bgp_cmp
, bmp_bgp_hash
)
94 struct bmp_bgph_head bmp_bgph
;
96 static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer
*a
,
97 const struct bmp_bgp_peer
*b
)
99 if (a
->peerid
< b
->peerid
)
101 if (a
->peerid
> b
->peerid
)
106 static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer
*e
)
111 DECLARE_HASH(bmp_peerh
, struct bmp_bgp_peer
, bpi
,
112 bmp_bgp_peer_cmp
, bmp_bgp_peer_hash
)
114 struct bmp_peerh_head bmp_peerh
;
116 DECLARE_LIST(bmp_mirrorq
, struct bmp_mirrorq
, bmi
)
118 /* listener management */
120 static int bmp_listener_cmp(const struct bmp_listener
*a
,
121 const struct bmp_listener
*b
)
125 c
= sockunion_cmp(&a
->addr
, &b
->addr
);
128 if (a
->port
< b
->port
)
130 if (a
->port
> b
->port
)
135 DECLARE_SORTLIST_UNIQ(bmp_listeners
, struct bmp_listener
, bli
, bmp_listener_cmp
)
137 static int bmp_targets_cmp(const struct bmp_targets
*a
,
138 const struct bmp_targets
*b
)
140 return strcmp(a
->name
, b
->name
);
143 DECLARE_SORTLIST_UNIQ(bmp_targets
, struct bmp_targets
, bti
, bmp_targets_cmp
)
145 DECLARE_LIST(bmp_session
, struct bmp
, bsi
)
147 DECLARE_DLIST(bmp_qlist
, struct bmp_queue_entry
, bli
)
149 static int bmp_qhash_cmp(const struct bmp_queue_entry
*a
,
150 const struct bmp_queue_entry
*b
)
153 if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
&& b
->afi
== AFI_L2VPN
154 && b
->safi
== SAFI_EVPN
) {
155 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
158 } else if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
)
160 else if (b
->afi
== AFI_L2VPN
&& b
->safi
== SAFI_EVPN
)
163 ret
= prefix_cmp(&a
->p
, &b
->p
);
166 ret
= memcmp(&a
->peerid
, &b
->peerid
,
167 offsetof(struct bmp_queue_entry
, refcount
) -
168 offsetof(struct bmp_queue_entry
, peerid
));
172 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
176 key
= prefix_hash_key((void *)&e
->p
);
177 key
= jhash(&e
->peerid
,
178 offsetof(struct bmp_queue_entry
, refcount
)
179 - offsetof(struct bmp_queue_entry
, peerid
),
181 if (e
->afi
== AFI_L2VPN
&& e
->safi
== SAFI_EVPN
)
183 offsetof(struct bmp_queue_entry
, rd
)
184 - offsetof(struct bmp_queue_entry
, refcount
)
185 + PSIZE(e
->rd
.prefixlen
),
191 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
192 bmp_qhash_cmp
, bmp_qhash_hkey
)
194 static int bmp_active_cmp(const struct bmp_active
*a
,
195 const struct bmp_active
*b
)
199 c
= strcmp(a
->hostname
, b
->hostname
);
202 if (a
->port
< b
->port
)
204 if (a
->port
> b
->port
)
209 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
)
211 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
213 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
217 monotime(&new->t_up
);
219 new->socket
= bmp_sock
;
220 new->syncafi
= AFI_MAX
;
222 FOREACH_AFI_SAFI (afi
, safi
) {
223 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
224 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
227 bmp_session_add_tail(&bt
->sessions
, new);
231 static void bmp_free(struct bmp
*bmp
)
233 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
234 XFREE(MTYPE_BMP_CONN
, bmp
);
237 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
240 stream_putl(s
, 0); //dummy message length. will be set later.
241 stream_putc(s
, type
);
244 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
245 uint8_t flags
, const struct timeval
*tv
)
247 char peer_distinguisher
[8];
249 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
250 #define BMP_PEER_TYPE_RD_INSTANCE 1
251 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
253 #define BMP_PEER_FLAG_V (1 << 7)
254 #define BMP_PEER_FLAG_L (1 << 6)
255 #define BMP_PEER_FLAG_A (1 << 5)
258 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
261 if (peer
->su
.sa
.sa_family
== AF_INET6
)
262 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
264 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
265 stream_putc(s
, flags
);
267 /* Peer Distinguisher */
268 memset (&peer_distinguisher
[0], 0, 8);
269 stream_put(s
, &peer_distinguisher
[0], 8);
272 if (peer
->su
.sa
.sa_family
== AF_INET6
)
273 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
274 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
278 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
287 stream_putl(s
, peer
->as
);
290 stream_put_in_addr(s
, &peer
->remote_id
);
294 stream_putl(s
, tv
->tv_sec
);
295 stream_putl(s
, tv
->tv_usec
);
302 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
305 int len
= strlen (string
);
306 stream_putw(s
, type
);
308 stream_put(s
, string
, len
);
311 static int bmp_send_initiation(struct bmp
*bmp
)
315 s
= stream_new(BGP_MAX_PACKET_SIZE
);
316 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
318 #define BMP_INFO_TYPE_SYSDESCR 1
319 #define BMP_INFO_TYPE_SYSNAME 2
320 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
321 FRR_FULL_NAME
" " FRR_VER_SHORT
);
322 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
324 len
= stream_get_endp(s
);
325 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
327 pullwr_write_stream(bmp
->pullwr
, s
);
332 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
335 uint8_t marker
[16] = {
336 0xff, 0xff, 0xff, 0xff,
337 0xff, 0xff, 0xff, 0xff,
338 0xff, 0xff, 0xff, 0xff,
339 0xff, 0xff, 0xff, 0xff,
342 stream_put(s
, marker
, sizeof(marker
));
343 len_pos
= stream_get_endp(s
);
345 stream_putc(s
, BGP_MSG_NOTIFY
);
346 stream_putc(s
, nfy
->code
);
347 stream_putc(s
, nfy
->subcode
);
348 stream_put(s
, nfy
->data
, nfy
->length
);
350 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
354 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
358 struct timeval uptime
, uptime_real
;
360 uptime
.tv_sec
= peer
->uptime
;
362 monotime_to_realtime(&uptime
, &uptime_real
);
364 #define BGP_BMP_MAX_PACKET_SIZE 1024
365 s
= stream_new(BGP_MAX_PACKET_SIZE
);
367 if (peer
->status
== Established
&& !down
) {
368 struct bmp_bgp_peer
*bbpeer
;
370 bmp_common_hdr(s
, BMP_VERSION_3
,
371 BMP_TYPE_PEER_UP_NOTIFICATION
);
372 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
374 /* Local Address (16 bytes) */
375 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
376 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
377 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
381 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
384 /* Local Port, Remote Port */
385 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
386 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
387 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
388 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
389 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
390 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
391 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
392 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
394 static const uint8_t dummy_open
[] = {
395 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
396 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
400 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
402 if (bbpeer
&& bbpeer
->open_tx
)
403 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
405 stream_put(s
, dummy_open
, sizeof(dummy_open
));
406 zlog_warn("bmp: missing TX OPEN message for peer %s",
409 if (bbpeer
&& bbpeer
->open_rx
)
410 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
412 stream_put(s
, dummy_open
, sizeof(dummy_open
));
413 zlog_warn("bmp: missing RX OPEN message for peer %s",
418 bmp_put_info_tlv(s
, 0, peer
->desc
);
423 bmp_common_hdr(s
, BMP_VERSION_3
,
424 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
425 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
427 type_pos
= stream_get_endp(s
);
428 stream_putc(s
, 0); /* placeholder for down reason */
430 switch (peer
->last_reset
) {
431 case PEER_DOWN_NOTIFY_RECEIVED
:
432 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
433 bmp_notify_put(s
, &peer
->notify
);
435 case PEER_DOWN_CLOSE_SESSION
:
436 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
438 case PEER_DOWN_WAITING_NHT
:
439 type
= BMP_PEERDOWN_LOCAL_FSM
;
440 stream_putw(s
, BGP_FSM_TcpConnectionFails
);
443 * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
444 * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
446 * See RFC7854 ss. 4.9
449 type
= BMP_PEERDOWN_LOCAL_FSM
;
450 stream_putw(s
, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE
);
453 stream_putc_at(s
, type_pos
, type
);
456 len
= stream_get_endp(s
);
457 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
462 static int bmp_send_peerup(struct bmp
*bmp
)
465 struct listnode
*node
;
468 /* Walk down all peers */
469 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
470 s
= bmp_peerstate(peer
, false);
471 pullwr_write_stream(bmp
->pullwr
, s
);
478 /* XXX: kludge - filling the pullwr's buffer */
479 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
481 struct bmp_targets
*bt
;
484 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
485 frr_each(bmp_session
, &bt
->sessions
, bmp
)
486 pullwr_write_stream(bmp
->pullwr
, s
);
494 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
495 #define BMP_MIRROR_TLV_TYPE_INFO 1
497 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
498 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
500 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
502 struct bmp_mirrorq
*bmq
;
504 bmq
= bmp
->mirrorpos
;
508 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
511 if (!bmq
->refcount
) {
512 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
513 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
518 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
520 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
521 struct bmp_mirrorq
*bmq
, *inner
;
522 struct bmp_targets
*bt
;
525 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
527 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
530 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
531 if (bmp
->mirrorpos
!= bmq
)
534 while ((inner
= bmp_pull_mirror(bmp
))) {
535 if (!inner
->refcount
)
536 XFREE(MTYPE_BMP_MIRRORQ
,
540 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
542 bmp
->mirror_lost
= true;
543 pullwr_bump(bmp
->pullwr
);
549 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
550 struct stream
*packet
)
552 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
554 struct bmp_mirrorq
*qitem
;
555 struct bmp_targets
*bt
;
558 frrtrace(3, frr_bgp
, bmp_mirror_packet
, peer
, type
, packet
);
560 gettimeofday(&tv
, NULL
);
562 if (type
== BGP_MSG_OPEN
) {
563 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
565 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
567 bbpeer
->open_rx_len
= size
;
568 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
569 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
575 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
576 qitem
->peerid
= peer
->qobj_node
.nid
;
579 memcpy(qitem
->data
, packet
->data
, size
);
581 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
584 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
587 bmp
->mirrorpos
= qitem
;
588 pullwr_bump(bmp
->pullwr
);
591 if (qitem
->refcount
== 0)
592 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
594 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
595 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
597 bmp_mirror_cull(bmpbgp
);
599 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
600 bmpbgp
->mirror_qsize
);
605 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
610 gettimeofday(&tv
, NULL
);
612 s
= stream_new(BGP_MAX_PACKET_SIZE
);
614 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
615 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
617 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
619 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
620 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
622 bmp
->cnt_mirror_overruns
++;
623 pullwr_write_stream(bmp
->pullwr
, s
);
627 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
629 struct bmp_mirrorq
*bmq
;
631 bool written
= false;
633 if (bmp
->mirror_lost
) {
634 bmp_wrmirror_lost(bmp
, pullwr
);
635 bmp
->mirror_lost
= false;
639 bmq
= bmp_pull_mirror(bmp
);
643 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
645 zlog_info("bmp: skipping mirror message for deleted peer");
650 s
= stream_new(BGP_MAX_PACKET_SIZE
);
652 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
653 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
655 /* BMP Mirror TLV. */
656 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
657 stream_putw(s
, bmq
->len
);
658 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
661 pullwr_write_stream(bmp
->pullwr
, s
);
662 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
669 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
673 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
674 struct stream
*packet
)
676 if (type
== BGP_MSG_OPEN
) {
677 frrtrace(2, frr_bgp
, bmp_update_saved_open
, peer
, packet
);
679 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
681 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
683 bbpeer
->open_tx_len
= size
;
684 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
685 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
690 static int bmp_peer_established(struct peer
*peer
)
692 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
694 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
699 /* Check if this peer just went to Established */
700 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
703 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
704 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
706 bbpeer
= bmp_bgp_peer_get(peer
);
707 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
709 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
710 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
712 bbpeer
->open_tx
= bbdopp
->open_tx
;
713 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
714 bbpeer
->open_rx
= bbdopp
->open_rx
;
715 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
717 bmp_peerh_del(&bmp_peerh
, bbdopp
);
718 XFREE(MTYPE_BMP_PEER
, bbdopp
);
722 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
726 static int bmp_peer_backward(struct peer
*peer
)
728 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
729 struct bmp_bgp_peer
*bbpeer
;
731 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
736 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
738 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
739 bbpeer
->open_tx_len
= 0;
740 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
741 bbpeer
->open_rx_len
= 0;
744 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
748 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
751 struct listnode
*node
;
752 struct stream
*s
, *s2
;
754 iana_safi_t pkt_safi
;
756 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
758 s
= stream_new(BGP_MAX_PACKET_SIZE
);
760 /* Make BGP update packet. */
761 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
763 /* Unfeasible Routes Length */
766 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
767 /* Total Path Attribute Length */
770 /* Convert AFI, SAFI to values for packet. */
771 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
773 /* Total Path Attribute Length */
775 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
776 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
778 stream_putw(s
, pkt_afi
);
779 stream_putc(s
, pkt_safi
);
782 bgp_packet_set_size(s
);
784 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
785 if (!peer
->afc_nego
[afi
][safi
])
788 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
790 bmp_common_hdr(s2
, BMP_VERSION_3
,
791 BMP_TYPE_ROUTE_MONITORING
);
792 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
794 stream_putl_at(s2
, BMP_LENGTH_POS
,
795 stream_get_endp(s
) + stream_get_endp(s2
));
798 pullwr_write_stream(bmp
->pullwr
, s2
);
799 pullwr_write_stream(bmp
->pullwr
, s
);
805 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
806 struct peer
*peer
, struct attr
*attr
,
807 afi_t afi
, safi_t safi
)
809 struct bpacket_attr_vec_arr vecarr
;
811 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
812 bgp_size_t total_attr_len
= 0;
814 bpacket_attr_vec_arr_reset(&vecarr
);
816 s
= stream_new(BGP_MAX_PACKET_SIZE
);
817 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
819 /* 2: withdrawn routes length */
822 /* 3: total attributes length - attrlen_pos stores the position */
823 attrlen_pos
= stream_get_endp(s
);
826 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
827 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
828 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
832 /* peer_cap_enhe & add-path removed */
833 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
834 stream_put_prefix(s
, p
);
836 size_t p1
= stream_get_endp(s
);
838 /* MPLS removed for now */
840 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
842 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
844 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
845 total_attr_len
+= stream_get_endp(s
) - p1
;
848 /* set the total attribute length correctly */
849 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
850 bgp_packet_set_size(s
);
854 static struct stream
*bmp_withdraw(const struct prefix
*p
,
855 struct prefix_rd
*prd
, afi_t afi
,
859 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
860 bgp_size_t total_attr_len
= 0;
861 bgp_size_t unfeasible_len
;
863 s
= stream_new(BGP_MAX_PACKET_SIZE
);
865 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
868 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
869 stream_put_prefix(s
, p
);
870 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
871 - BGP_UNFEASIBLE_LEN
;
872 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
875 attrlen_pos
= stream_get_endp(s
);
876 /* total attr length = 0 for now. reevaluate later */
878 mp_start
= stream_get_endp(s
);
879 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
881 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
883 /* Set the mp_unreach attr's length */
884 bgp_packet_mpunreach_end(s
, mplen_pos
);
886 /* Set total path attribute length. */
887 total_attr_len
= stream_get_endp(s
) - mp_start
;
888 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
891 bgp_packet_set_size(s
);
895 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
896 const struct prefix
*p
, struct prefix_rd
*prd
,
897 struct attr
*attr
, afi_t afi
, safi_t safi
,
900 struct stream
*hdr
, *msg
;
901 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
902 struct timeval uptime_real
;
904 monotime_to_realtime(&tv
, &uptime_real
);
906 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
908 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
910 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
911 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
912 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
914 stream_putl_at(hdr
, BMP_LENGTH_POS
,
915 stream_get_endp(hdr
) + stream_get_endp(msg
));
918 pullwr_write_stream(bmp
->pullwr
, hdr
);
919 pullwr_write_stream(bmp
->pullwr
, msg
);
924 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
929 if (bmp
->syncafi
== AFI_MAX
) {
930 FOREACH_AFI_SAFI (afi
, safi
) {
931 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
934 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
937 bmp
->syncsafi
= safi
;
939 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
940 bmp
->syncpos
.family
= afi2family(afi
);
941 bmp
->syncrdpos
= NULL
;
942 zlog_info("bmp[%s] %s %s sending table",
944 afi2str(bmp
->syncafi
),
945 safi2str(bmp
->syncsafi
));
946 /* break does not work here, 2 loops... */
949 if (bmp
->syncafi
== AFI_MAX
)
955 safi
= bmp
->syncsafi
;
957 if (!bmp
->targets
->afimon
[afi
][safi
]) {
958 /* shouldn't happen */
959 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
960 bmp
->syncafi
= AFI_MAX
;
961 bmp
->syncsafi
= SAFI_MAX
;
965 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
967 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
968 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
970 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
971 /* initialize syncrdpos to the first
972 * mid-layer table entry
974 if (!bmp
->syncrdpos
) {
975 bmp
->syncrdpos
= bgp_table_top(table
);
980 /* look for a valid mid-layer table */
982 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
986 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
987 } while (bmp
->syncrdpos
);
989 /* mid-layer table completed */
994 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
997 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
999 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
1000 /* reset bottom-layer pointer */
1001 memset(&bmp
->syncpos
, 0,
1002 sizeof(bmp
->syncpos
));
1003 bmp
->syncpos
.family
= afi2family(afi
);
1004 /* check whethere there is a valid
1005 * next mid-layer table, otherwise
1006 * declare table completed (eor)
1008 for (bmp
->syncrdpos
= bgp_route_next(
1011 bmp
->syncrdpos
= bgp_route_next(
1013 if (bgp_dest_get_bgp_table_info(
1018 zlog_info("bmp[%s] %s %s table completed (EoR)",
1019 bmp
->remote
, afi2str(afi
),
1021 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1022 bmp_eor(bmp
, afi
, safi
, 0);
1024 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1025 bmp
->syncafi
= AFI_MAX
;
1026 bmp
->syncsafi
= SAFI_MAX
;
1029 bmp
->syncpeerid
= 0;
1030 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1033 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1034 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1035 bpiter
= bpiter
->next
) {
1036 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1038 if (bpiter
->peer
->qobj_node
.nid
1041 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1042 > bpi
->peer
->qobj_node
.nid
)
1047 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1048 for (adjiter
= bn
->adj_in
; adjiter
;
1049 adjiter
= adjiter
->next
) {
1050 if (adjiter
->peer
->qobj_node
.nid
1053 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1054 > adjin
->peer
->qobj_node
.nid
)
1066 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1068 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1069 } else if (adjin
&& bpi
1070 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1072 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1074 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1076 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1079 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1080 struct prefix_rd
*prd
= NULL
;
1081 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
1082 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1085 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1086 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1088 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1089 safi
, adjin
->uptime
);
1094 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1096 struct bmp_queue_entry
*bqe
;
1098 bqe
= bmp
->queuepos
;
1102 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1105 if (!bqe
->refcount
) {
1106 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1107 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1112 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1114 struct bmp_queue_entry
*bqe
;
1116 struct bgp_dest
*bn
;
1117 bool written
= false;
1119 bqe
= bmp_pull(bmp
);
1123 afi_t afi
= bqe
->afi
;
1124 safi_t safi
= bqe
->safi
;
1126 switch (bmp
->afistate
[afi
][safi
]) {
1127 case BMP_AFI_INACTIVE
:
1128 case BMP_AFI_NEEDSYNC
:
1131 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1132 /* currently syncing but have already passed this
1133 * prefix => send it. */
1136 /* currently syncing & haven't reached this prefix yet
1137 * => it'll be sent as part of the table sync, no need here */
1143 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1145 zlog_info("bmp: skipping queued item for deleted peer");
1148 if (peer
->status
!= Established
)
1151 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1152 struct prefix_rd
*prd
= NULL
;
1153 if (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
)
1156 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1157 struct bgp_path_info
*bpi
;
1159 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1161 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1163 if (bpi
->peer
== peer
)
1167 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1168 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1169 bpi
? bpi
->uptime
: monotime(NULL
));
1173 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1174 struct bgp_adj_in
*adjin
;
1176 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1177 adjin
= adjin
->next
) {
1178 if (adjin
->peer
== peer
)
1181 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1182 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1183 adjin
? adjin
->uptime
: monotime(NULL
));
1189 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1193 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1195 switch(bmp
->state
) {
1197 bmp_send_peerup(bmp
);
1198 bmp
->state
= BMP_Run
;
1202 if (bmp_wrmirror(bmp
, pullwr
))
1204 if (bmp_wrqueue(bmp
, pullwr
))
1206 if (bmp_wrsync(bmp
, pullwr
))
1212 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1215 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1217 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1218 bmp
->remote
, strerror(errno
));
1224 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1225 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1228 struct bmp_queue_entry
*bqe
, bqeref
;
1231 refcount
= bmp_session_count(&bt
->sessions
);
1235 memset(&bqeref
, 0, sizeof(bqeref
));
1236 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1237 bqeref
.peerid
= peer
->qobj_node
.nid
;
1241 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
)
1242 prefix_copy(&bqeref
.rd
,
1243 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1245 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1247 if (bqe
->refcount
>= refcount
)
1248 /* nothing to do here */
1251 bmp_qlist_del(&bt
->updlist
, bqe
);
1253 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1254 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1256 bmp_qhash_add(&bt
->updhash
, bqe
);
1259 bqe
->refcount
= refcount
;
1260 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1262 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1264 bmp
->queuepos
= bqe
;
1267 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1268 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1270 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1271 struct bmp_targets
*bt
;
1274 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1275 char pfxprint
[PREFIX2STR_BUFFER
];
1277 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1278 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1285 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1286 if (!bt
->afimon
[afi
][safi
])
1289 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1291 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1292 pullwr_bump(bmp
->pullwr
);
1298 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1301 stream_putw(s
, type
);
1303 stream_putl(s
, value
);
1307 static int bmp_stats(struct thread
*thread
)
1309 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1312 struct listnode
*node
;
1316 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1319 gettimeofday(&tv
, NULL
);
1321 /* Walk down all peers */
1322 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1323 size_t count
= 0, count_pos
, len
;
1325 if (peer
->status
!= Established
)
1328 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1329 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1330 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1332 count_pos
= stream_get_endp(s
);
1335 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1336 peer
->stat_pfx_filter
);
1337 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1338 peer
->stat_pfx_aspath_loop
);
1339 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1340 peer
->stat_pfx_originator_loop
);
1341 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1342 peer
->stat_pfx_cluster_loop
);
1343 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1344 peer
->stat_pfx_dup_withdraw
);
1345 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1346 peer
->stat_upd_7606
);
1347 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1348 peer
->stat_pfx_nh_invalid
);
1350 stream_putl_at(s
, count_pos
, count
);
1352 len
= stream_get_endp(s
);
1353 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1355 bmp_send_all(bt
->bmpbgp
, s
);
1360 /* read from the BMP socket to detect session termination */
1361 static int bmp_read(struct thread
*t
)
1363 struct bmp
*bmp
= THREAD_ARG(t
);
1369 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1371 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1372 } else if (n
== 0) {
1373 /* the TCP session was terminated by the far end */
1374 bmp_wrerr(bmp
, NULL
, true);
1376 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1377 /* the TCP session experienced a fatal error, likely a timeout */
1378 bmp_wrerr(bmp
, NULL
, false);
1382 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1387 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1389 union sockunion su
, *sumem
;
1392 struct access_list
*acl
= NULL
;
1393 enum filter_type ret
;
1394 char buf
[SU_ADDRSTRLEN
];
1397 sumem
= sockunion_getpeername(bmp_sock
);
1402 memcpy(&su
, sumem
, sizeof(su
));
1403 sockunion_free(sumem
);
1405 set_nonblocking(bmp_sock
);
1406 set_cloexec(bmp_sock
);
1408 if (!sockunion2hostprefix(&su
, &p
)) {
1416 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1419 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1425 ret
= FILTER_PERMIT
;
1427 ret
= access_list_apply(acl
, &p
);
1430 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1431 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1432 su
.sa
.sa_family
== AF_INET
1433 ? ntohs(su
.sin
.sin_port
)
1434 : ntohs(su
.sin6
.sin6_port
));
1436 if (ret
== FILTER_DENY
) {
1437 bt
->cnt_aclrefused
++;
1438 zlog_info("bmp[%s] connection refused by access-list", buf
);
1444 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1445 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1446 bmp_sock
, safe_strerror(errno
), errno
);
1447 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1448 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1449 bmp_sock
, safe_strerror(errno
), errno
);
1451 zlog_info("bmp[%s] connection established", buf
);
1453 /* Allocate new BMP structure and set up default values. */
1454 bmp
= bmp_new(bt
, bmp_sock
);
1455 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1457 bmp
->state
= BMP_PeerUp
;
1458 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1460 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1461 bmp_send_initiation(bmp
);
1466 /* Accept BMP connection. */
1467 static int bmp_accept(struct thread
*thread
)
1470 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1473 /* We continue hearing BMP socket. */
1474 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1476 memset(&su
, 0, sizeof(union sockunion
));
1478 /* We can handle IPv4 or IPv6 socket. */
1479 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1481 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1484 bmp_open(bl
->targets
, bmp_sock
);
1488 static void bmp_close(struct bmp
*bmp
)
1490 struct bmp_queue_entry
*bqe
;
1491 struct bmp_mirrorq
*bmq
;
1493 THREAD_OFF(bmp
->t_read
);
1496 bmp_active_disconnected(bmp
->active
);
1498 while ((bmq
= bmp_pull_mirror(bmp
)))
1500 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1501 while ((bqe
= bmp_pull(bmp
)))
1503 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1505 THREAD_OFF(bmp
->t_read
);
1506 pullwr_del(bmp
->pullwr
);
1510 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1512 struct bmp_bgp dummy
= { .bgp
= bgp
};
1513 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1516 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1518 struct bmp_bgp
*bmpbgp
;
1520 bmpbgp
= bmp_bgp_find(bgp
);
1524 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1526 bmpbgp
->mirror_qsizelimit
= ~0UL;
1527 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1528 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1533 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1535 struct bmp_targets
*bt
;
1537 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1539 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1540 bmp_targets_put(bt
);
1542 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1543 XFREE(MTYPE_BMP
, bmpbgp
);
1546 static int bmp_bgp_del(struct bgp
*bgp
)
1548 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1551 bmp_bgp_put(bmpbgp
);
1555 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1557 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1558 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1561 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1563 struct bmp_bgp_peer
*bbpeer
;
1565 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1569 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1570 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1571 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1576 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1578 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1579 struct bmp_targets dummy
;
1583 dummy
.name
= (char *)name
;
1584 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1587 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1589 struct bmp_targets
*bt
;
1591 bt
= bmp_targets_find1(bgp
, name
);
1595 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1596 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1598 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1599 bmp_session_init(&bt
->sessions
);
1600 bmp_qhash_init(&bt
->updhash
);
1601 bmp_qlist_init(&bt
->updlist
);
1602 bmp_actives_init(&bt
->actives
);
1603 bmp_listeners_init(&bt
->listeners
);
1605 QOBJ_REG(bt
, bmp_targets
);
1606 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1610 static void bmp_targets_put(struct bmp_targets
*bt
)
1613 struct bmp_active
*ba
;
1615 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1618 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1623 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1626 bmp_listeners_fini(&bt
->listeners
);
1627 bmp_actives_fini(&bt
->actives
);
1628 bmp_qhash_fini(&bt
->updhash
);
1629 bmp_qlist_fini(&bt
->updlist
);
1631 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1632 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1633 bmp_session_fini(&bt
->sessions
);
1635 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1636 XFREE(MTYPE_BMP_TARGETS
, bt
);
1639 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1640 const union sockunion
*su
,
1643 struct bmp_listener dummy
;
1646 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1649 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1650 const union sockunion
*su
,
1653 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1658 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1664 bmp_listeners_add(&bt
->listeners
, bl
);
1668 static void bmp_listener_put(struct bmp_listener
*bl
)
1670 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1671 XFREE(MTYPE_BMP_LISTENER
, bl
);
1674 static void bmp_listener_start(struct bmp_listener
*bl
)
1678 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1682 sockopt_reuseaddr(sock
);
1683 sockopt_reuseport(sock
);
1684 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1687 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1691 ret
= listen(sock
, 3);
1696 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1702 static void bmp_listener_stop(struct bmp_listener
*bl
)
1704 THREAD_OFF(bl
->t_accept
);
1711 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1712 const char *hostname
, int port
)
1714 struct bmp_active dummy
;
1715 dummy
.hostname
= (char *)hostname
;
1717 return bmp_actives_find(&bt
->actives
, &dummy
);
1720 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1721 const char *hostname
, int port
)
1723 struct bmp_active
*ba
;
1725 ba
= bmp_active_find(bt
, hostname
, port
);
1729 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1731 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1733 ba
->minretry
= BMP_DFLT_MINRETRY
;
1734 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1737 bmp_actives_add(&bt
->actives
, ba
);
1741 static void bmp_active_put(struct bmp_active
*ba
)
1743 THREAD_OFF(ba
->t_timer
);
1744 THREAD_OFF(ba
->t_read
);
1745 THREAD_OFF(ba
->t_write
);
1747 bmp_actives_del(&ba
->targets
->actives
, ba
);
1750 ba
->bmp
->active
= NULL
;
1754 if (ba
->socket
!= -1)
1757 XFREE(MTYPE_TMP
, ba
->hostname
);
1758 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1761 static void bmp_active_setup(struct bmp_active
*ba
);
1763 static void bmp_active_connect(struct bmp_active
*ba
)
1765 enum connect_result res
;
1766 char buf
[SU_ADDRSTRLEN
];
1768 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1769 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1770 if (ba
->socket
< 0) {
1771 zlog_warn("bmp[%s]: failed to create socket",
1776 set_nonblocking(ba
->socket
);
1777 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1778 htons(ba
->port
), 0);
1781 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1783 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1784 ba
->hostname
, buf
, ba
->port
);
1788 case connect_success
:
1790 case connect_in_progress
:
1791 bmp_active_setup(ba
);
1796 /* exhausted all addresses */
1797 ba
->curretry
+= ba
->curretry
/ 2;
1798 bmp_active_setup(ba
);
1801 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1802 int numaddrs
, union sockunion
*addr
)
1804 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1807 if (numaddrs
<= 0) {
1808 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1809 ba
->hostname
, errstr
);
1810 ba
->last_err
= errstr
;
1811 ba
->curretry
+= ba
->curretry
/ 2;
1814 bmp_active_setup(ba
);
1818 if (numaddrs
> (int)array_size(ba
->addrs
))
1819 numaddrs
= array_size(ba
->addrs
);
1822 ba
->addrtotal
= numaddrs
;
1823 for (i
= 0; i
< ba
->addrtotal
; i
++)
1824 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1826 bmp_active_connect(ba
);
1829 static int bmp_active_thread(struct thread
*t
)
1831 struct bmp_active
*ba
= THREAD_ARG(t
);
1834 char buf
[SU_ADDRSTRLEN
];
1836 /* all 3 end up here, though only timer or read+write are active
1838 THREAD_OFF(ba
->t_timer
);
1839 THREAD_OFF(ba
->t_read
);
1840 THREAD_OFF(ba
->t_write
);
1842 ba
->last_err
= NULL
;
1844 if (ba
->socket
== -1) {
1845 resolver_resolve(&ba
->resq
, AF_UNSPEC
, ba
->hostname
,
1846 bmp_active_resolved
);
1850 slen
= sizeof(status
);
1851 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1854 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1855 if (ret
< 0 || status
!= 0) {
1856 ba
->last_err
= strerror(status
);
1857 zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
1858 ba
->hostname
, buf
, ba
->port
, ba
->last_err
);
1862 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1863 ba
->hostname
, buf
, ba
->port
);
1865 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1869 ba
->bmp
->active
= ba
;
1871 ba
->curretry
= ba
->minretry
;
1878 bmp_active_connect(ba
);
1882 static void bmp_active_disconnected(struct bmp_active
*ba
)
1885 bmp_active_setup(ba
);
1888 static void bmp_active_setup(struct bmp_active
*ba
)
1890 THREAD_OFF(ba
->t_timer
);
1891 THREAD_OFF(ba
->t_read
);
1892 THREAD_OFF(ba
->t_write
);
1896 if (ba
->resq
.callback
)
1899 if (ba
->curretry
> ba
->maxretry
)
1900 ba
->curretry
= ba
->maxretry
;
1902 if (ba
->socket
== -1)
1903 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1904 ba
->curretry
, &ba
->t_timer
);
1906 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1908 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1913 static struct cmd_node bmp_node
= {
1916 .parent_node
= BGP_NODE
,
1917 .prompt
= "%s(config-bgp-bmp)# "
1920 #define BMP_STR "BGP Monitoring Protocol\n"
1922 #ifndef VTYSH_EXTRACT_PL
1923 #include "bgpd/bgp_bmp_clippy.c"
1926 DEFPY_NOSH(bmp_targets_main
,
1928 "bmp targets BMPTARGETS",
1930 "Create BMP target group\n"
1931 "Name of the BMP target group\n")
1933 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1934 struct bmp_targets
*bt
;
1936 bt
= bmp_targets_get(bgp
, bmptargets
);
1938 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1942 DEFPY(no_bmp_targets_main
,
1944 "no bmp targets BMPTARGETS",
1947 "Delete BMP target group\n"
1948 "Name of the BMP target group\n")
1950 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1951 struct bmp_targets
*bt
;
1953 bt
= bmp_targets_find1(bgp
, bmptargets
);
1955 vty_out(vty
, "%% BMP target group not found\n");
1958 bmp_targets_put(bt
);
1962 DEFPY(bmp_listener_main
,
1964 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1966 "Listen for inbound BMP connections\n"
1967 "IPv6 address to listen on\n"
1968 "IPv4 address to listen on\n"
1970 "TCP Port number\n")
1972 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1973 struct bmp_listener
*bl
;
1975 bl
= bmp_listener_get(bt
, listener
, port
);
1977 bmp_listener_start(bl
);
1982 DEFPY(no_bmp_listener_main
,
1983 no_bmp_listener_cmd
,
1984 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1987 "Create BMP listener\n"
1988 "IPv6 address to listen on\n"
1989 "IPv4 address to listen on\n"
1991 "TCP Port number\n")
1993 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1994 struct bmp_listener
*bl
;
1996 bl
= bmp_listener_find(bt
, listener
, port
);
1998 vty_out(vty
, "%% BMP listener not found\n");
2001 bmp_listener_stop(bl
);
2002 bmp_listener_put(bl
);
2008 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}",
2011 "Actively establish connection to monitoring station\n"
2012 "Monitoring station hostname or address\n"
2015 "Minimum connection retry interval\n"
2016 "Minimum connection retry interval (milliseconds)\n"
2017 "Maximum connection retry interval\n"
2018 "Maximum connection retry interval (milliseconds)\n")
2020 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2021 struct bmp_active
*ba
;
2024 ba
= bmp_active_find(bt
, hostname
, port
);
2026 vty_out(vty
, "%% No such active connection found\n");
2033 ba
= bmp_active_get(bt
, hostname
, port
);
2035 ba
->minretry
= min_retry
;
2037 ba
->maxretry
= max_retry
;
2038 ba
->curretry
= ba
->minretry
;
2039 bmp_active_setup(ba
);
2046 "[no] <ip|ipv6>$af access-list WORD",
2050 "Access list to restrict BMP sessions\n"
2051 "Access list name\n")
2053 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2058 if (!strcmp(af
, "ipv6"))
2059 what
= &bt
->acl6_name
;
2061 what
= &bt
->acl_name
;
2063 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2065 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2070 DEFPY(bmp_stats_cfg
,
2072 "[no] bmp stats [interval (100-86400000)]",
2075 "Send BMP statistics messages\n"
2076 "Specify BMP stats interval\n"
2077 "Interval (milliseconds) to send BMP Stats in\n")
2079 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2081 THREAD_OFF(bt
->t_stats
);
2084 else if (interval_str
)
2085 bt
->stat_msec
= interval
;
2087 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2090 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2095 DEFPY(bmp_monitor_cfg
,
2097 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
2100 "Send BMP route monitoring messages\n"
2101 "Address Family\nAddress Family\nAddress Family\n"
2102 "Address Family\nAddress Family\nAddress Family\n"
2103 "Send state before policy and filter processing\n"
2104 "Send state with policy and filters applied\n")
2111 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2114 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2115 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2117 if (policy
[1] == 'r')
2118 flag
= BMP_MON_PREPOLICY
;
2120 flag
= BMP_MON_POSTPOLICY
;
2122 prev
= bt
->afimon
[afi
][safi
];
2124 bt
->afimon
[afi
][safi
] &= ~flag
;
2126 bt
->afimon
[afi
][safi
] |= flag
;
2128 if (prev
== bt
->afimon
[afi
][safi
])
2131 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2132 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2133 bmp
->syncafi
= AFI_MAX
;
2134 bmp
->syncsafi
= SAFI_MAX
;
2137 if (!bt
->afimon
[afi
][safi
]) {
2138 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2142 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2148 DEFPY(bmp_mirror_cfg
,
2153 "Send BMP route mirroring messages\n")
2155 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2158 if (bt
->mirror
== !no
)
2165 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2166 struct bmp_mirrorq
*bmq
;
2168 while ((bmq
= bmp_pull_mirror(bmp
)))
2170 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2175 DEFPY(bmp_mirror_limit_cfg
,
2176 bmp_mirror_limit_cmd
,
2177 "bmp mirror buffer-limit (0-4294967294)",
2179 "Route Mirroring settings\n"
2180 "Configure maximum memory used for buffered mirroring messages\n"
2183 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2184 struct bmp_bgp
*bmpbgp
;
2186 bmpbgp
= bmp_bgp_get(bgp
);
2187 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2192 DEFPY(no_bmp_mirror_limit_cfg
,
2193 no_bmp_mirror_limit_cmd
,
2194 "no bmp mirror buffer-limit [(0-4294967294)]",
2197 "Route Mirroring settings\n"
2198 "Configure maximum memory used for buffered mirroring messages\n"
2201 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2202 struct bmp_bgp
*bmpbgp
;
2204 bmpbgp
= bmp_bgp_get(bgp
);
2205 bmpbgp
->mirror_qsizelimit
= ~0UL;
2217 struct bmp_bgp
*bmpbgp
;
2218 struct bmp_targets
*bt
;
2219 struct bmp_listener
*bl
;
2220 struct bmp_active
*ba
;
2223 char buf
[SU_ADDRSTRLEN
];
2224 char uptime
[BGP_UPTIME_LEN
];
2227 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2228 vty_out(vty
, "BMP state for BGP %s:\n\n",
2229 bmpbgp
->bgp
->name_pretty
);
2230 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2231 bmpbgp
->mirror_qsize
,
2232 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2233 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2234 bmpbgp
->mirror_qsizemax
);
2235 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2236 vty_out(vty
, " %9zu bytes buffer size limit\n",
2237 bmpbgp
->mirror_qsizelimit
);
2240 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2241 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2242 vty_out(vty
, " Route Mirroring %sabled\n",
2243 bt
->mirror
? "en" : "dis");
2248 FOREACH_AFI_SAFI (afi
, safi
) {
2249 const char *str
= NULL
;
2251 switch (bt
->afimon
[afi
][safi
]) {
2252 case BMP_MON_PREPOLICY
:
2255 case BMP_MON_POSTPOLICY
:
2256 str
= "post-policy";
2258 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2259 str
= "pre-policy and post-policy";
2264 vty_out(vty
, " Route Monitoring %s %s %s\n",
2265 afi2str(afi
), safi2str(safi
), str
);
2268 vty_out(vty
, " Listeners:\n");
2269 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2270 vty_out(vty
, " %s:%d\n",
2271 sockunion2str(&bl
->addr
, buf
,
2272 SU_ADDRSTRLEN
), bl
->port
);
2274 vty_out(vty
, "\n Outbound connections:\n");
2275 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2276 ttable_add_row(tt
, "remote|state||timer");
2277 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2278 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2279 const char *state_str
= "?";
2282 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2283 uptime
, sizeof(uptime
),
2285 ttable_add_row(tt
, "%s:%d|Up|%s|%s",
2286 ba
->hostname
, ba
->port
,
2287 ba
->bmp
->remote
, uptime
);
2294 long trem
= thread_timer_remain_second(
2297 peer_uptime(monotime(NULL
) - trem
,
2298 uptime
, sizeof(uptime
),
2300 state_str
= "RetryWait";
2301 } else if (ba
->t_read
) {
2302 state_str
= "Connecting";
2303 } else if (ba
->resq
.callback
) {
2304 state_str
= "Resolving";
2307 ttable_add_row(tt
, "%s:%d|%s|%s|%s",
2308 ba
->hostname
, ba
->port
,
2310 ba
->last_err
? ba
->last_err
: "",
2314 out
= ttable_dump(tt
, "\n");
2315 vty_out(vty
, "%s", out
);
2316 XFREE(MTYPE_TMP
, out
);
2319 vty_out(vty
, "\n %zu connected clients:\n",
2320 bmp_session_count(&bt
->sessions
));
2321 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2322 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2323 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2325 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2329 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2331 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2332 sizeof(uptime
), false, NULL
);
2334 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2335 bmp
->remote
, uptime
,
2338 bmp
->cnt_mirror_overruns
,
2341 out
= ttable_dump(tt
, "\n");
2342 vty_out(vty
, "%s", out
);
2343 XFREE(MTYPE_TMP
, out
);
2352 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2354 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2355 struct bmp_targets
*bt
;
2356 struct bmp_listener
*bl
;
2357 struct bmp_active
*ba
;
2358 char buf
[SU_ADDRSTRLEN
];
2365 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2366 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2367 bmpbgp
->mirror_qsizelimit
);
2369 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2370 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2373 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2375 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2378 vty_out(vty
, " bmp stats interval %d\n",
2382 vty_out(vty
, " bmp mirror\n");
2384 FOREACH_AFI_SAFI (afi
, safi
) {
2385 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2387 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2388 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2389 afi_str
, safi2str(safi
));
2390 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2391 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2392 afi_str
, safi2str(safi
));
2394 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2395 vty_out(vty
, " \n bmp listener %s port %d\n",
2396 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2399 frr_each (bmp_actives
, &bt
->actives
, ba
)
2400 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2401 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2407 static int bgp_bmp_init(struct thread_master
*tm
)
2409 install_node(&bmp_node
);
2410 install_default(BMP_NODE
);
2411 install_element(BGP_NODE
, &bmp_targets_cmd
);
2412 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2414 install_element(BMP_NODE
, &bmp_listener_cmd
);
2415 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2416 install_element(BMP_NODE
, &bmp_connect_cmd
);
2417 install_element(BMP_NODE
, &bmp_acl_cmd
);
2418 install_element(BMP_NODE
, &bmp_stats_cmd
);
2419 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2420 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2422 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2423 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2425 install_element(VIEW_NODE
, &show_bmp_cmd
);
2431 static int bgp_bmp_module_init(void)
2433 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2434 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2435 hook_register(peer_status_changed
, bmp_peer_established
);
2436 hook_register(peer_backward_transition
, bmp_peer_backward
);
2437 hook_register(bgp_process
, bmp_process
);
2438 hook_register(bgp_inst_config_write
, bmp_config_write
);
2439 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2440 hook_register(frr_late_init
, bgp_bmp_init
);
2444 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2445 .description
= "bgpd BMP module",
2446 .init
= bgp_bmp_module_init
)