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"
37 #include "lib/version.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
,
138 static int bmp_targets_cmp(const struct bmp_targets
*a
,
139 const struct bmp_targets
*b
)
141 return strcmp(a
->name
, b
->name
);
144 DECLARE_SORTLIST_UNIQ(bmp_targets
, struct bmp_targets
, bti
, bmp_targets_cmp
);
146 DECLARE_LIST(bmp_session
, struct bmp
, bsi
);
148 DECLARE_DLIST(bmp_qlist
, struct bmp_queue_entry
, bli
);
150 static int bmp_qhash_cmp(const struct bmp_queue_entry
*a
,
151 const struct bmp_queue_entry
*b
)
154 if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
&& b
->afi
== AFI_L2VPN
155 && b
->safi
== SAFI_EVPN
) {
156 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
159 } else if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
)
161 else if (b
->afi
== AFI_L2VPN
&& b
->safi
== SAFI_EVPN
)
164 ret
= prefix_cmp(&a
->p
, &b
->p
);
167 ret
= memcmp(&a
->peerid
, &b
->peerid
,
168 offsetof(struct bmp_queue_entry
, refcount
) -
169 offsetof(struct bmp_queue_entry
, peerid
));
173 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
177 key
= prefix_hash_key((void *)&e
->p
);
178 key
= jhash(&e
->peerid
,
179 offsetof(struct bmp_queue_entry
, refcount
)
180 - offsetof(struct bmp_queue_entry
, peerid
),
182 if (e
->afi
== AFI_L2VPN
&& e
->safi
== SAFI_EVPN
)
184 offsetof(struct bmp_queue_entry
, rd
)
185 - offsetof(struct bmp_queue_entry
, refcount
)
186 + PSIZE(e
->rd
.prefixlen
),
192 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
193 bmp_qhash_cmp
, bmp_qhash_hkey
);
195 static int bmp_active_cmp(const struct bmp_active
*a
,
196 const struct bmp_active
*b
)
200 c
= strcmp(a
->hostname
, b
->hostname
);
203 if (a
->port
< b
->port
)
205 if (a
->port
> b
->port
)
210 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
);
212 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
214 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
218 monotime(&new->t_up
);
220 new->socket
= bmp_sock
;
221 new->syncafi
= AFI_MAX
;
223 FOREACH_AFI_SAFI (afi
, safi
) {
224 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
225 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
228 bmp_session_add_tail(&bt
->sessions
, new);
232 static void bmp_free(struct bmp
*bmp
)
234 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
235 XFREE(MTYPE_BMP_CONN
, bmp
);
238 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
241 stream_putl(s
, 0); //dummy message length. will be set later.
242 stream_putc(s
, type
);
245 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
246 uint8_t flags
, const struct timeval
*tv
)
248 char peer_distinguisher
[8];
250 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
251 #define BMP_PEER_TYPE_RD_INSTANCE 1
252 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
254 #define BMP_PEER_FLAG_V (1 << 7)
255 #define BMP_PEER_FLAG_L (1 << 6)
256 #define BMP_PEER_FLAG_A (1 << 5)
259 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
262 if (peer
->su
.sa
.sa_family
== AF_INET6
)
263 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
265 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
266 stream_putc(s
, flags
);
268 /* Peer Distinguisher */
269 memset (&peer_distinguisher
[0], 0, 8);
270 stream_put(s
, &peer_distinguisher
[0], 8);
273 if (peer
->su
.sa
.sa_family
== AF_INET6
)
274 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
275 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
279 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
288 stream_putl(s
, peer
->as
);
291 stream_put_in_addr(s
, &peer
->remote_id
);
295 stream_putl(s
, tv
->tv_sec
);
296 stream_putl(s
, tv
->tv_usec
);
303 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
306 int len
= strlen (string
);
307 stream_putw(s
, type
);
309 stream_put(s
, string
, len
);
312 static int bmp_send_initiation(struct bmp
*bmp
)
316 s
= stream_new(BGP_MAX_PACKET_SIZE
);
317 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
319 #define BMP_INFO_TYPE_SYSDESCR 1
320 #define BMP_INFO_TYPE_SYSNAME 2
321 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
322 FRR_FULL_NAME
" " FRR_VER_SHORT
);
323 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
325 len
= stream_get_endp(s
);
326 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
328 pullwr_write_stream(bmp
->pullwr
, s
);
333 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
336 uint8_t marker
[16] = {
337 0xff, 0xff, 0xff, 0xff,
338 0xff, 0xff, 0xff, 0xff,
339 0xff, 0xff, 0xff, 0xff,
340 0xff, 0xff, 0xff, 0xff,
343 stream_put(s
, marker
, sizeof(marker
));
344 len_pos
= stream_get_endp(s
);
346 stream_putc(s
, BGP_MSG_NOTIFY
);
347 stream_putc(s
, nfy
->code
);
348 stream_putc(s
, nfy
->subcode
);
349 stream_put(s
, nfy
->data
, nfy
->length
);
351 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
355 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
359 struct timeval uptime
, uptime_real
;
361 uptime
.tv_sec
= peer
->uptime
;
363 monotime_to_realtime(&uptime
, &uptime_real
);
365 #define BGP_BMP_MAX_PACKET_SIZE 1024
366 s
= stream_new(BGP_MAX_PACKET_SIZE
);
368 if (peer_established(peer
) && !down
) {
369 struct bmp_bgp_peer
*bbpeer
;
371 bmp_common_hdr(s
, BMP_VERSION_3
,
372 BMP_TYPE_PEER_UP_NOTIFICATION
);
373 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
375 /* Local Address (16 bytes) */
376 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
377 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
378 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
382 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
385 /* Local Port, Remote Port */
386 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
387 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
388 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
389 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
390 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
391 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
392 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
393 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
395 static const uint8_t dummy_open
[] = {
396 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
397 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
401 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
403 if (bbpeer
&& bbpeer
->open_tx
)
404 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
406 stream_put(s
, dummy_open
, sizeof(dummy_open
));
407 zlog_warn("bmp: missing TX OPEN message for peer %s",
410 if (bbpeer
&& bbpeer
->open_rx
)
411 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
413 stream_put(s
, dummy_open
, sizeof(dummy_open
));
414 zlog_warn("bmp: missing RX OPEN message for peer %s",
419 bmp_put_info_tlv(s
, 0, peer
->desc
);
424 bmp_common_hdr(s
, BMP_VERSION_3
,
425 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
426 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
428 type_pos
= stream_get_endp(s
);
429 stream_putc(s
, 0); /* placeholder for down reason */
431 switch (peer
->last_reset
) {
432 case PEER_DOWN_NOTIFY_RECEIVED
:
433 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
434 bmp_notify_put(s
, &peer
->notify
);
436 case PEER_DOWN_CLOSE_SESSION
:
437 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
439 case PEER_DOWN_WAITING_NHT
:
440 type
= BMP_PEERDOWN_LOCAL_FSM
;
441 stream_putw(s
, BGP_FSM_TcpConnectionFails
);
444 * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
445 * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
447 * See RFC7854 ss. 4.9
450 type
= BMP_PEERDOWN_LOCAL_FSM
;
451 stream_putw(s
, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE
);
454 stream_putc_at(s
, type_pos
, type
);
457 len
= stream_get_endp(s
);
458 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
463 static int bmp_send_peerup(struct bmp
*bmp
)
466 struct listnode
*node
;
469 /* Walk down all peers */
470 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
471 s
= bmp_peerstate(peer
, false);
472 pullwr_write_stream(bmp
->pullwr
, s
);
479 /* XXX: kludge - filling the pullwr's buffer */
480 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
482 struct bmp_targets
*bt
;
485 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
486 frr_each(bmp_session
, &bt
->sessions
, bmp
)
487 pullwr_write_stream(bmp
->pullwr
, s
);
495 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
496 #define BMP_MIRROR_TLV_TYPE_INFO 1
498 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
499 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
501 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
503 struct bmp_mirrorq
*bmq
;
505 bmq
= bmp
->mirrorpos
;
509 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
512 if (!bmq
->refcount
) {
513 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
514 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
519 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
521 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
522 struct bmp_mirrorq
*bmq
, *inner
;
523 struct bmp_targets
*bt
;
526 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
528 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
531 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
532 if (bmp
->mirrorpos
!= bmq
)
535 while ((inner
= bmp_pull_mirror(bmp
))) {
536 if (!inner
->refcount
)
537 XFREE(MTYPE_BMP_MIRRORQ
,
541 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
543 bmp
->mirror_lost
= true;
544 pullwr_bump(bmp
->pullwr
);
550 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
551 struct stream
*packet
)
553 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
555 struct bmp_mirrorq
*qitem
;
556 struct bmp_targets
*bt
;
559 frrtrace(3, frr_bgp
, bmp_mirror_packet
, peer
, type
, packet
);
561 gettimeofday(&tv
, NULL
);
563 if (type
== BGP_MSG_OPEN
) {
564 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
566 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
568 bbpeer
->open_rx_len
= size
;
569 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
570 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
576 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
577 qitem
->peerid
= peer
->qobj_node
.nid
;
580 memcpy(qitem
->data
, packet
->data
, size
);
582 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
585 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
588 bmp
->mirrorpos
= qitem
;
589 pullwr_bump(bmp
->pullwr
);
592 if (qitem
->refcount
== 0)
593 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
595 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
596 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
598 bmp_mirror_cull(bmpbgp
);
600 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
601 bmpbgp
->mirror_qsize
);
606 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
611 gettimeofday(&tv
, NULL
);
613 s
= stream_new(BGP_MAX_PACKET_SIZE
);
615 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
616 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
618 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
620 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
621 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
623 bmp
->cnt_mirror_overruns
++;
624 pullwr_write_stream(bmp
->pullwr
, s
);
628 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
630 struct bmp_mirrorq
*bmq
;
632 bool written
= false;
634 if (bmp
->mirror_lost
) {
635 bmp_wrmirror_lost(bmp
, pullwr
);
636 bmp
->mirror_lost
= false;
640 bmq
= bmp_pull_mirror(bmp
);
644 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
646 zlog_info("bmp: skipping mirror message for deleted peer");
651 s
= stream_new(BGP_MAX_PACKET_SIZE
);
653 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
654 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
656 /* BMP Mirror TLV. */
657 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
658 stream_putw(s
, bmq
->len
);
659 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
662 pullwr_write_stream(bmp
->pullwr
, s
);
663 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
670 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
674 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
675 struct stream
*packet
)
677 if (type
== BGP_MSG_OPEN
) {
678 frrtrace(2, frr_bgp
, bmp_update_saved_open
, peer
, packet
);
680 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
682 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
684 bbpeer
->open_tx_len
= size
;
685 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
686 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
691 static int bmp_peer_status_changed(struct peer
*peer
)
693 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
694 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
696 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
701 if (peer
->status
== Deleted
) {
702 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
704 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
705 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
706 bmp_peerh_del(&bmp_peerh
, bbpeer
);
707 XFREE(MTYPE_BMP_PEER
, bbpeer
);
712 /* Check if this peer just went to Established */
713 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
716 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
717 bbpeer
= bmp_bgp_peer_get(peer
);
718 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
720 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
721 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
723 bbpeer
->open_tx
= bbdopp
->open_tx
;
724 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
725 bbpeer
->open_rx
= bbdopp
->open_rx
;
726 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
728 bmp_peerh_del(&bmp_peerh
, bbdopp
);
729 XFREE(MTYPE_BMP_PEER
, bbdopp
);
733 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
737 static int bmp_peer_backward(struct peer
*peer
)
739 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
740 struct bmp_bgp_peer
*bbpeer
;
742 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
747 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
749 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
750 bbpeer
->open_tx_len
= 0;
751 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
752 bbpeer
->open_rx_len
= 0;
755 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
759 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
762 struct listnode
*node
;
763 struct stream
*s
, *s2
;
765 iana_safi_t pkt_safi
;
767 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
769 s
= stream_new(BGP_MAX_PACKET_SIZE
);
771 /* Make BGP update packet. */
772 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
774 /* Unfeasible Routes Length */
777 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
778 /* Total Path Attribute Length */
781 /* Convert AFI, SAFI to values for packet. */
782 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
784 /* Total Path Attribute Length */
786 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
787 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
789 stream_putw(s
, pkt_afi
);
790 stream_putc(s
, pkt_safi
);
793 bgp_packet_set_size(s
);
795 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
796 if (!peer
->afc_nego
[afi
][safi
])
799 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
801 bmp_common_hdr(s2
, BMP_VERSION_3
,
802 BMP_TYPE_ROUTE_MONITORING
);
803 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
805 stream_putl_at(s2
, BMP_LENGTH_POS
,
806 stream_get_endp(s
) + stream_get_endp(s2
));
809 pullwr_write_stream(bmp
->pullwr
, s2
);
810 pullwr_write_stream(bmp
->pullwr
, s
);
816 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
817 struct peer
*peer
, struct attr
*attr
,
818 afi_t afi
, safi_t safi
)
820 struct bpacket_attr_vec_arr vecarr
;
822 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
823 bgp_size_t total_attr_len
= 0;
825 bpacket_attr_vec_arr_reset(&vecarr
);
827 s
= stream_new(BGP_MAX_PACKET_SIZE
);
828 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
830 /* 2: withdrawn routes length */
833 /* 3: total attributes length - attrlen_pos stores the position */
834 attrlen_pos
= stream_get_endp(s
);
837 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
838 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
839 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
843 /* peer_cap_enhe & add-path removed */
844 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
845 stream_put_prefix(s
, p
);
847 size_t p1
= stream_get_endp(s
);
849 /* MPLS removed for now */
851 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
853 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
855 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
856 total_attr_len
+= stream_get_endp(s
) - p1
;
859 /* set the total attribute length correctly */
860 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
861 bgp_packet_set_size(s
);
865 static struct stream
*bmp_withdraw(const struct prefix
*p
,
866 struct prefix_rd
*prd
, afi_t afi
,
870 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
871 bgp_size_t total_attr_len
= 0;
872 bgp_size_t unfeasible_len
;
874 s
= stream_new(BGP_MAX_PACKET_SIZE
);
876 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
879 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
880 stream_put_prefix(s
, p
);
881 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
882 - BGP_UNFEASIBLE_LEN
;
883 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
886 attrlen_pos
= stream_get_endp(s
);
887 /* total attr length = 0 for now. reevaluate later */
889 mp_start
= stream_get_endp(s
);
890 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
892 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
894 /* Set the mp_unreach attr's length */
895 bgp_packet_mpunreach_end(s
, mplen_pos
);
897 /* Set total path attribute length. */
898 total_attr_len
= stream_get_endp(s
) - mp_start
;
899 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
902 bgp_packet_set_size(s
);
906 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
907 const struct prefix
*p
, struct prefix_rd
*prd
,
908 struct attr
*attr
, afi_t afi
, safi_t safi
,
911 struct stream
*hdr
, *msg
;
912 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
913 struct timeval uptime_real
;
915 monotime_to_realtime(&tv
, &uptime_real
);
917 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
919 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
921 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
922 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
923 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
925 stream_putl_at(hdr
, BMP_LENGTH_POS
,
926 stream_get_endp(hdr
) + stream_get_endp(msg
));
929 pullwr_write_stream(bmp
->pullwr
, hdr
);
930 pullwr_write_stream(bmp
->pullwr
, msg
);
935 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
940 if (bmp
->syncafi
== AFI_MAX
) {
941 FOREACH_AFI_SAFI (afi
, safi
) {
942 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
945 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
948 bmp
->syncsafi
= safi
;
950 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
951 bmp
->syncpos
.family
= afi2family(afi
);
952 bmp
->syncrdpos
= NULL
;
953 zlog_info("bmp[%s] %s %s sending table",
955 afi2str(bmp
->syncafi
),
956 safi2str(bmp
->syncsafi
));
957 /* break does not work here, 2 loops... */
960 if (bmp
->syncafi
== AFI_MAX
)
966 safi
= bmp
->syncsafi
;
968 if (!bmp
->targets
->afimon
[afi
][safi
]) {
969 /* shouldn't happen */
970 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
971 bmp
->syncafi
= AFI_MAX
;
972 bmp
->syncsafi
= SAFI_MAX
;
976 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
978 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
979 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
981 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
982 /* initialize syncrdpos to the first
983 * mid-layer table entry
985 if (!bmp
->syncrdpos
) {
986 bmp
->syncrdpos
= bgp_table_top(table
);
991 /* look for a valid mid-layer table */
993 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
997 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
998 } while (bmp
->syncrdpos
);
1000 /* mid-layer table completed */
1001 if (!bmp
->syncrdpos
)
1005 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
1008 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
1010 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
1011 /* reset bottom-layer pointer */
1012 memset(&bmp
->syncpos
, 0,
1013 sizeof(bmp
->syncpos
));
1014 bmp
->syncpos
.family
= afi2family(afi
);
1015 /* check whethere there is a valid
1016 * next mid-layer table, otherwise
1017 * declare table completed (eor)
1019 for (bmp
->syncrdpos
= bgp_route_next(
1022 bmp
->syncrdpos
= bgp_route_next(
1024 if (bgp_dest_get_bgp_table_info(
1029 zlog_info("bmp[%s] %s %s table completed (EoR)",
1030 bmp
->remote
, afi2str(afi
),
1032 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1033 bmp_eor(bmp
, afi
, safi
, 0);
1035 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1036 bmp
->syncafi
= AFI_MAX
;
1037 bmp
->syncsafi
= SAFI_MAX
;
1040 bmp
->syncpeerid
= 0;
1041 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1044 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1045 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1046 bpiter
= bpiter
->next
) {
1047 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1049 if (bpiter
->peer
->qobj_node
.nid
1052 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1053 > bpi
->peer
->qobj_node
.nid
)
1058 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1059 for (adjiter
= bn
->adj_in
; adjiter
;
1060 adjiter
= adjiter
->next
) {
1061 if (adjiter
->peer
->qobj_node
.nid
1064 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1065 > adjin
->peer
->qobj_node
.nid
)
1077 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1079 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1080 } else if (adjin
&& bpi
1081 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1083 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1085 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1087 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1090 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1091 struct prefix_rd
*prd
= NULL
;
1092 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
1093 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1096 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1097 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1099 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1100 safi
, adjin
->uptime
);
1105 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1107 struct bmp_queue_entry
*bqe
;
1109 bqe
= bmp
->queuepos
;
1113 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1116 if (!bqe
->refcount
) {
1117 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1118 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1123 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1125 struct bmp_queue_entry
*bqe
;
1127 struct bgp_dest
*bn
;
1128 bool written
= false;
1130 bqe
= bmp_pull(bmp
);
1134 afi_t afi
= bqe
->afi
;
1135 safi_t safi
= bqe
->safi
;
1137 switch (bmp
->afistate
[afi
][safi
]) {
1138 case BMP_AFI_INACTIVE
:
1139 case BMP_AFI_NEEDSYNC
:
1142 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1143 /* currently syncing but have already passed this
1144 * prefix => send it. */
1147 /* currently syncing & haven't reached this prefix yet
1148 * => it'll be sent as part of the table sync, no need here */
1154 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1156 zlog_info("bmp: skipping queued item for deleted peer");
1159 if (!peer_established(peer
))
1162 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1163 struct prefix_rd
*prd
= NULL
;
1164 if (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
)
1167 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1168 struct bgp_path_info
*bpi
;
1170 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1172 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1174 if (bpi
->peer
== peer
)
1178 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1179 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1180 bpi
? bpi
->uptime
: monotime(NULL
));
1184 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1185 struct bgp_adj_in
*adjin
;
1187 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1188 adjin
= adjin
->next
) {
1189 if (adjin
->peer
== peer
)
1192 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1193 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1194 adjin
? adjin
->uptime
: monotime(NULL
));
1200 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1204 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1206 switch(bmp
->state
) {
1208 bmp_send_peerup(bmp
);
1209 bmp
->state
= BMP_Run
;
1213 if (bmp_wrmirror(bmp
, pullwr
))
1215 if (bmp_wrqueue(bmp
, pullwr
))
1217 if (bmp_wrsync(bmp
, pullwr
))
1223 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1226 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1228 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1229 bmp
->remote
, strerror(errno
));
1235 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1236 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1239 struct bmp_queue_entry
*bqe
, bqeref
;
1242 refcount
= bmp_session_count(&bt
->sessions
);
1246 memset(&bqeref
, 0, sizeof(bqeref
));
1247 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1248 bqeref
.peerid
= peer
->qobj_node
.nid
;
1252 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
)
1253 prefix_copy(&bqeref
.rd
,
1254 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1256 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1258 if (bqe
->refcount
>= refcount
)
1259 /* nothing to do here */
1262 bmp_qlist_del(&bt
->updlist
, bqe
);
1264 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1265 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1267 bmp_qhash_add(&bt
->updhash
, bqe
);
1270 bqe
->refcount
= refcount
;
1271 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1273 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1275 bmp
->queuepos
= bqe
;
1278 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1279 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1281 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1282 struct bmp_targets
*bt
;
1285 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1286 char pfxprint
[PREFIX2STR_BUFFER
];
1288 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1289 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1296 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1297 if (!bt
->afimon
[afi
][safi
])
1300 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1302 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1303 pullwr_bump(bmp
->pullwr
);
1309 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1312 stream_putw(s
, type
);
1314 stream_putl(s
, value
);
1318 static void bmp_stats(struct thread
*thread
)
1320 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1323 struct listnode
*node
;
1327 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1330 gettimeofday(&tv
, NULL
);
1332 /* Walk down all peers */
1333 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1334 size_t count
= 0, count_pos
, len
;
1336 if (!peer_established(peer
))
1339 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1340 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1341 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1343 count_pos
= stream_get_endp(s
);
1346 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1347 peer
->stat_pfx_filter
);
1348 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1349 peer
->stat_pfx_aspath_loop
);
1350 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1351 peer
->stat_pfx_originator_loop
);
1352 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1353 peer
->stat_pfx_cluster_loop
);
1354 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1355 peer
->stat_pfx_dup_withdraw
);
1356 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1357 peer
->stat_upd_7606
);
1358 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1359 peer
->stat_pfx_nh_invalid
);
1361 stream_putl_at(s
, count_pos
, count
);
1363 len
= stream_get_endp(s
);
1364 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1366 bmp_send_all(bt
->bmpbgp
, s
);
1370 /* read from the BMP socket to detect session termination */
1371 static void bmp_read(struct thread
*t
)
1373 struct bmp
*bmp
= THREAD_ARG(t
);
1379 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1381 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1382 } else if (n
== 0) {
1383 /* the TCP session was terminated by the far end */
1384 bmp_wrerr(bmp
, NULL
, true);
1386 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1387 /* the TCP session experienced a fatal error, likely a timeout */
1388 bmp_wrerr(bmp
, NULL
, false);
1392 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1395 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1397 union sockunion su
, *sumem
;
1400 struct access_list
*acl
= NULL
;
1401 enum filter_type ret
;
1402 char buf
[SU_ADDRSTRLEN
];
1405 sumem
= sockunion_getpeername(bmp_sock
);
1410 memcpy(&su
, sumem
, sizeof(su
));
1411 sockunion_free(sumem
);
1413 set_nonblocking(bmp_sock
);
1414 set_cloexec(bmp_sock
);
1416 if (!sockunion2hostprefix(&su
, &p
)) {
1424 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1427 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1433 ret
= FILTER_PERMIT
;
1435 ret
= access_list_apply(acl
, &p
);
1438 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1439 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1440 su
.sa
.sa_family
== AF_INET
1441 ? ntohs(su
.sin
.sin_port
)
1442 : ntohs(su
.sin6
.sin6_port
));
1444 if (ret
== FILTER_DENY
) {
1445 bt
->cnt_aclrefused
++;
1446 zlog_info("bmp[%s] connection refused by access-list", buf
);
1452 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1453 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1454 bmp_sock
, safe_strerror(errno
), errno
);
1455 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1456 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1457 bmp_sock
, safe_strerror(errno
), errno
);
1459 zlog_info("bmp[%s] connection established", buf
);
1461 /* Allocate new BMP structure and set up default values. */
1462 bmp
= bmp_new(bt
, bmp_sock
);
1463 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1465 bmp
->state
= BMP_PeerUp
;
1466 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1468 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1469 bmp_send_initiation(bmp
);
1474 /* Accept BMP connection. */
1475 static void bmp_accept(struct thread
*thread
)
1478 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1481 /* We continue hearing BMP socket. */
1482 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1484 memset(&su
, 0, sizeof(union sockunion
));
1486 /* We can handle IPv4 or IPv6 socket. */
1487 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1489 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1492 bmp_open(bl
->targets
, bmp_sock
);
1495 static void bmp_close(struct bmp
*bmp
)
1497 struct bmp_queue_entry
*bqe
;
1498 struct bmp_mirrorq
*bmq
;
1500 THREAD_OFF(bmp
->t_read
);
1503 bmp_active_disconnected(bmp
->active
);
1505 while ((bmq
= bmp_pull_mirror(bmp
)))
1507 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1508 while ((bqe
= bmp_pull(bmp
)))
1510 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1512 THREAD_OFF(bmp
->t_read
);
1513 pullwr_del(bmp
->pullwr
);
1517 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1519 struct bmp_bgp dummy
= { .bgp
= bgp
};
1520 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1523 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1525 struct bmp_bgp
*bmpbgp
;
1527 bmpbgp
= bmp_bgp_find(bgp
);
1531 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1533 bmpbgp
->mirror_qsizelimit
= ~0UL;
1534 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1535 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1540 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1542 struct bmp_targets
*bt
;
1544 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1546 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1547 bmp_targets_put(bt
);
1549 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1550 XFREE(MTYPE_BMP
, bmpbgp
);
1553 static int bmp_bgp_del(struct bgp
*bgp
)
1555 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1558 bmp_bgp_put(bmpbgp
);
1562 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1564 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1565 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1568 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1570 struct bmp_bgp_peer
*bbpeer
;
1572 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1576 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1577 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1578 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1583 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1585 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1586 struct bmp_targets dummy
;
1590 dummy
.name
= (char *)name
;
1591 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1594 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1596 struct bmp_targets
*bt
;
1598 bt
= bmp_targets_find1(bgp
, name
);
1602 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1603 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1605 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1606 bmp_session_init(&bt
->sessions
);
1607 bmp_qhash_init(&bt
->updhash
);
1608 bmp_qlist_init(&bt
->updlist
);
1609 bmp_actives_init(&bt
->actives
);
1610 bmp_listeners_init(&bt
->listeners
);
1612 QOBJ_REG(bt
, bmp_targets
);
1613 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1617 static void bmp_targets_put(struct bmp_targets
*bt
)
1620 struct bmp_active
*ba
;
1622 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1625 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1630 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1633 bmp_listeners_fini(&bt
->listeners
);
1634 bmp_actives_fini(&bt
->actives
);
1635 bmp_qhash_fini(&bt
->updhash
);
1636 bmp_qlist_fini(&bt
->updlist
);
1638 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1639 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1640 bmp_session_fini(&bt
->sessions
);
1642 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1643 XFREE(MTYPE_BMP_TARGETS
, bt
);
1646 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1647 const union sockunion
*su
,
1650 struct bmp_listener dummy
;
1653 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1656 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1657 const union sockunion
*su
,
1660 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1665 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1671 bmp_listeners_add(&bt
->listeners
, bl
);
1675 static void bmp_listener_put(struct bmp_listener
*bl
)
1677 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1678 XFREE(MTYPE_BMP_LISTENER
, bl
);
1681 static void bmp_listener_start(struct bmp_listener
*bl
)
1685 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1689 sockopt_reuseaddr(sock
);
1690 sockopt_reuseport(sock
);
1691 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1694 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1698 ret
= listen(sock
, 3);
1703 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1709 static void bmp_listener_stop(struct bmp_listener
*bl
)
1711 THREAD_OFF(bl
->t_accept
);
1718 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1719 const char *hostname
, int port
)
1721 struct bmp_active dummy
;
1722 dummy
.hostname
= (char *)hostname
;
1724 return bmp_actives_find(&bt
->actives
, &dummy
);
1727 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1728 const char *hostname
, int port
)
1730 struct bmp_active
*ba
;
1732 ba
= bmp_active_find(bt
, hostname
, port
);
1736 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1738 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1740 ba
->minretry
= BMP_DFLT_MINRETRY
;
1741 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1744 bmp_actives_add(&bt
->actives
, ba
);
1748 static void bmp_active_put(struct bmp_active
*ba
)
1750 THREAD_OFF(ba
->t_timer
);
1751 THREAD_OFF(ba
->t_read
);
1752 THREAD_OFF(ba
->t_write
);
1754 bmp_actives_del(&ba
->targets
->actives
, ba
);
1757 ba
->bmp
->active
= NULL
;
1761 if (ba
->socket
!= -1)
1764 XFREE(MTYPE_TMP
, ba
->hostname
);
1765 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1768 static void bmp_active_setup(struct bmp_active
*ba
);
1770 static void bmp_active_connect(struct bmp_active
*ba
)
1772 enum connect_result res
;
1773 char buf
[SU_ADDRSTRLEN
];
1775 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1776 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1777 if (ba
->socket
< 0) {
1778 zlog_warn("bmp[%s]: failed to create socket",
1783 set_nonblocking(ba
->socket
);
1784 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1785 htons(ba
->port
), 0);
1788 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1790 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1791 ba
->hostname
, buf
, ba
->port
);
1795 case connect_success
:
1797 case connect_in_progress
:
1798 bmp_active_setup(ba
);
1803 /* exhausted all addresses */
1804 ba
->curretry
+= ba
->curretry
/ 2;
1805 bmp_active_setup(ba
);
1808 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1809 int numaddrs
, union sockunion
*addr
)
1811 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1814 if (numaddrs
<= 0) {
1815 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1816 ba
->hostname
, errstr
);
1817 ba
->last_err
= errstr
;
1818 ba
->curretry
+= ba
->curretry
/ 2;
1821 bmp_active_setup(ba
);
1825 if (numaddrs
> (int)array_size(ba
->addrs
))
1826 numaddrs
= array_size(ba
->addrs
);
1829 ba
->addrtotal
= numaddrs
;
1830 for (i
= 0; i
< ba
->addrtotal
; i
++)
1831 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1833 bmp_active_connect(ba
);
1836 static void bmp_active_thread(struct thread
*t
)
1838 struct bmp_active
*ba
= THREAD_ARG(t
);
1841 char buf
[SU_ADDRSTRLEN
];
1844 /* all 3 end up here, though only timer or read+write are active
1846 THREAD_OFF(ba
->t_timer
);
1847 THREAD_OFF(ba
->t_read
);
1848 THREAD_OFF(ba
->t_write
);
1850 ba
->last_err
= NULL
;
1852 if (ba
->socket
== -1) {
1854 if (!ba
->targets
|| !ba
->targets
->bgp
)
1855 vrf_id
= VRF_DEFAULT
;
1857 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1858 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1859 bmp_active_resolved
);
1863 slen
= sizeof(status
);
1864 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1867 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1868 if (ret
< 0 || status
!= 0) {
1869 ba
->last_err
= strerror(status
);
1870 zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
1871 ba
->hostname
, buf
, ba
->port
, ba
->last_err
);
1875 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1876 ba
->hostname
, buf
, ba
->port
);
1878 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1882 ba
->bmp
->active
= ba
;
1884 ba
->curretry
= ba
->minretry
;
1891 bmp_active_connect(ba
);
1894 static void bmp_active_disconnected(struct bmp_active
*ba
)
1897 bmp_active_setup(ba
);
1900 static void bmp_active_setup(struct bmp_active
*ba
)
1902 THREAD_OFF(ba
->t_timer
);
1903 THREAD_OFF(ba
->t_read
);
1904 THREAD_OFF(ba
->t_write
);
1908 if (ba
->resq
.callback
)
1911 if (ba
->curretry
> ba
->maxretry
)
1912 ba
->curretry
= ba
->maxretry
;
1914 if (ba
->socket
== -1)
1915 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1916 ba
->curretry
, &ba
->t_timer
);
1918 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1920 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1925 static struct cmd_node bmp_node
= {
1928 .parent_node
= BGP_NODE
,
1929 .prompt
= "%s(config-bgp-bmp)# "
1932 #define BMP_STR "BGP Monitoring Protocol\n"
1934 #ifndef VTYSH_EXTRACT_PL
1935 #include "bgpd/bgp_bmp_clippy.c"
1938 DEFPY_NOSH(bmp_targets_main
,
1940 "bmp targets BMPTARGETS",
1942 "Create BMP target group\n"
1943 "Name of the BMP target group\n")
1945 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1946 struct bmp_targets
*bt
;
1948 bt
= bmp_targets_get(bgp
, bmptargets
);
1950 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1954 DEFPY(no_bmp_targets_main
,
1956 "no bmp targets BMPTARGETS",
1959 "Delete BMP target group\n"
1960 "Name of the BMP target group\n")
1962 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1963 struct bmp_targets
*bt
;
1965 bt
= bmp_targets_find1(bgp
, bmptargets
);
1967 vty_out(vty
, "%% BMP target group not found\n");
1970 bmp_targets_put(bt
);
1974 DEFPY(bmp_listener_main
,
1976 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1978 "Listen for inbound BMP connections\n"
1979 "IPv6 address to listen on\n"
1980 "IPv4 address to listen on\n"
1982 "TCP Port number\n")
1984 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1985 struct bmp_listener
*bl
;
1987 bl
= bmp_listener_get(bt
, listener
, port
);
1989 bmp_listener_start(bl
);
1994 DEFPY(no_bmp_listener_main
,
1995 no_bmp_listener_cmd
,
1996 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1999 "Create BMP listener\n"
2000 "IPv6 address to listen on\n"
2001 "IPv4 address to listen on\n"
2003 "TCP Port number\n")
2005 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2006 struct bmp_listener
*bl
;
2008 bl
= bmp_listener_find(bt
, listener
, port
);
2010 vty_out(vty
, "%% BMP listener not found\n");
2013 bmp_listener_stop(bl
);
2014 bmp_listener_put(bl
);
2020 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}",
2023 "Actively establish connection to monitoring station\n"
2024 "Monitoring station hostname or address\n"
2027 "Minimum connection retry interval\n"
2028 "Minimum connection retry interval (milliseconds)\n"
2029 "Maximum connection retry interval\n"
2030 "Maximum connection retry interval (milliseconds)\n")
2032 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2033 struct bmp_active
*ba
;
2036 ba
= bmp_active_find(bt
, hostname
, port
);
2038 vty_out(vty
, "%% No such active connection found\n");
2045 ba
= bmp_active_get(bt
, hostname
, port
);
2047 ba
->minretry
= min_retry
;
2049 ba
->maxretry
= max_retry
;
2050 ba
->curretry
= ba
->minretry
;
2051 bmp_active_setup(ba
);
2058 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2062 "Access list to restrict BMP sessions\n"
2063 "Access list name\n")
2065 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2070 if (!strcmp(af
, "ipv6"))
2071 what
= &bt
->acl6_name
;
2073 what
= &bt
->acl_name
;
2075 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2077 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2082 DEFPY(bmp_stats_cfg
,
2084 "[no] bmp stats [interval (100-86400000)]",
2087 "Send BMP statistics messages\n"
2088 "Specify BMP stats interval\n"
2089 "Interval (milliseconds) to send BMP Stats in\n")
2091 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2093 THREAD_OFF(bt
->t_stats
);
2096 else if (interval_str
)
2097 bt
->stat_msec
= interval
;
2099 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2102 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2107 DEFPY(bmp_monitor_cfg
,
2109 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
2112 "Send BMP route monitoring messages\n"
2113 "Address Family\nAddress Family\nAddress Family\n"
2114 "Address Family\nAddress Family\nAddress Family\n"
2115 "Send state before policy and filter processing\n"
2116 "Send state with policy and filters applied\n")
2123 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2126 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2127 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2129 if (policy
[1] == 'r')
2130 flag
= BMP_MON_PREPOLICY
;
2132 flag
= BMP_MON_POSTPOLICY
;
2134 prev
= bt
->afimon
[afi
][safi
];
2136 bt
->afimon
[afi
][safi
] &= ~flag
;
2138 bt
->afimon
[afi
][safi
] |= flag
;
2140 if (prev
== bt
->afimon
[afi
][safi
])
2143 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2144 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2145 bmp
->syncafi
= AFI_MAX
;
2146 bmp
->syncsafi
= SAFI_MAX
;
2149 if (!bt
->afimon
[afi
][safi
]) {
2150 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2154 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2160 DEFPY(bmp_mirror_cfg
,
2165 "Send BMP route mirroring messages\n")
2167 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2170 if (bt
->mirror
== !no
)
2177 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2178 struct bmp_mirrorq
*bmq
;
2180 while ((bmq
= bmp_pull_mirror(bmp
)))
2182 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2187 DEFPY(bmp_mirror_limit_cfg
,
2188 bmp_mirror_limit_cmd
,
2189 "bmp mirror buffer-limit (0-4294967294)",
2191 "Route Mirroring settings\n"
2192 "Configure maximum memory used for buffered mirroring messages\n"
2195 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2196 struct bmp_bgp
*bmpbgp
;
2198 bmpbgp
= bmp_bgp_get(bgp
);
2199 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2204 DEFPY(no_bmp_mirror_limit_cfg
,
2205 no_bmp_mirror_limit_cmd
,
2206 "no bmp mirror buffer-limit [(0-4294967294)]",
2209 "Route Mirroring settings\n"
2210 "Configure maximum memory used for buffered mirroring messages\n"
2213 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2214 struct bmp_bgp
*bmpbgp
;
2216 bmpbgp
= bmp_bgp_get(bgp
);
2217 bmpbgp
->mirror_qsizelimit
= ~0UL;
2229 struct bmp_bgp
*bmpbgp
;
2230 struct bmp_targets
*bt
;
2231 struct bmp_listener
*bl
;
2232 struct bmp_active
*ba
;
2235 char buf
[SU_ADDRSTRLEN
];
2236 char uptime
[BGP_UPTIME_LEN
];
2239 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2240 vty_out(vty
, "BMP state for BGP %s:\n\n",
2241 bmpbgp
->bgp
->name_pretty
);
2242 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2243 bmpbgp
->mirror_qsize
,
2244 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2245 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2246 bmpbgp
->mirror_qsizemax
);
2247 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2248 vty_out(vty
, " %9zu bytes buffer size limit\n",
2249 bmpbgp
->mirror_qsizelimit
);
2252 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2253 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2254 vty_out(vty
, " Route Mirroring %sabled\n",
2255 bt
->mirror
? "en" : "dis");
2260 FOREACH_AFI_SAFI (afi
, safi
) {
2261 const char *str
= NULL
;
2263 switch (bt
->afimon
[afi
][safi
]) {
2264 case BMP_MON_PREPOLICY
:
2267 case BMP_MON_POSTPOLICY
:
2268 str
= "post-policy";
2270 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2271 str
= "pre-policy and post-policy";
2276 vty_out(vty
, " Route Monitoring %s %s %s\n",
2277 afi2str(afi
), safi2str(safi
), str
);
2280 vty_out(vty
, " Listeners:\n");
2281 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2282 vty_out(vty
, " %s:%d\n",
2283 sockunion2str(&bl
->addr
, buf
,
2284 SU_ADDRSTRLEN
), bl
->port
);
2286 vty_out(vty
, "\n Outbound connections:\n");
2287 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2288 ttable_add_row(tt
, "remote|state||timer");
2289 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2290 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2291 const char *state_str
= "?";
2294 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2295 uptime
, sizeof(uptime
),
2297 ttable_add_row(tt
, "%s:%d|Up|%s|%s",
2298 ba
->hostname
, ba
->port
,
2299 ba
->bmp
->remote
, uptime
);
2306 long trem
= thread_timer_remain_second(
2309 peer_uptime(monotime(NULL
) - trem
,
2310 uptime
, sizeof(uptime
),
2312 state_str
= "RetryWait";
2313 } else if (ba
->t_read
) {
2314 state_str
= "Connecting";
2315 } else if (ba
->resq
.callback
) {
2316 state_str
= "Resolving";
2319 ttable_add_row(tt
, "%s:%d|%s|%s|%s",
2320 ba
->hostname
, ba
->port
,
2322 ba
->last_err
? ba
->last_err
: "",
2326 out
= ttable_dump(tt
, "\n");
2327 vty_out(vty
, "%s", out
);
2328 XFREE(MTYPE_TMP
, out
);
2331 vty_out(vty
, "\n %zu connected clients:\n",
2332 bmp_session_count(&bt
->sessions
));
2333 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2334 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2335 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2337 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2341 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2343 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2344 sizeof(uptime
), false, NULL
);
2346 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2347 bmp
->remote
, uptime
,
2350 bmp
->cnt_mirror_overruns
,
2353 out
= ttable_dump(tt
, "\n");
2354 vty_out(vty
, "%s", out
);
2355 XFREE(MTYPE_TMP
, out
);
2364 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2366 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2367 struct bmp_targets
*bt
;
2368 struct bmp_listener
*bl
;
2369 struct bmp_active
*ba
;
2370 char buf
[SU_ADDRSTRLEN
];
2377 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2378 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2379 bmpbgp
->mirror_qsizelimit
);
2381 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2382 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2385 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2387 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2390 vty_out(vty
, " bmp stats interval %d\n",
2394 vty_out(vty
, " bmp mirror\n");
2396 FOREACH_AFI_SAFI (afi
, safi
) {
2397 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2399 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2400 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2401 afi_str
, safi2str(safi
));
2402 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2403 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2404 afi_str
, safi2str(safi
));
2406 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2407 vty_out(vty
, " \n bmp listener %s port %d\n",
2408 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2411 frr_each (bmp_actives
, &bt
->actives
, ba
)
2412 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2413 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2415 vty_out(vty
, " exit\n");
2421 static int bgp_bmp_init(struct thread_master
*tm
)
2423 install_node(&bmp_node
);
2424 install_default(BMP_NODE
);
2425 install_element(BGP_NODE
, &bmp_targets_cmd
);
2426 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2428 install_element(BMP_NODE
, &bmp_listener_cmd
);
2429 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2430 install_element(BMP_NODE
, &bmp_connect_cmd
);
2431 install_element(BMP_NODE
, &bmp_acl_cmd
);
2432 install_element(BMP_NODE
, &bmp_stats_cmd
);
2433 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2434 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2436 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2437 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2439 install_element(VIEW_NODE
, &show_bmp_cmd
);
2445 static int bgp_bmp_module_init(void)
2447 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2448 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2449 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2450 hook_register(peer_backward_transition
, bmp_peer_backward
);
2451 hook_register(bgp_process
, bmp_process
);
2452 hook_register(bgp_inst_config_write
, bmp_config_write
);
2453 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2454 hook_register(frr_late_init
, bgp_bmp_init
);
2458 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2459 .description
= "bgpd BMP module",
2460 .init
= bgp_bmp_module_init
,