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
,
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
->status
== Established
&& !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_established(struct peer
*peer
)
693 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
695 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
700 /* Check if this peer just went to Established */
701 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
704 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
705 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
707 bbpeer
= bmp_bgp_peer_get(peer
);
708 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
710 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
711 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
713 bbpeer
->open_tx
= bbdopp
->open_tx
;
714 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
715 bbpeer
->open_rx
= bbdopp
->open_rx
;
716 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
718 bmp_peerh_del(&bmp_peerh
, bbdopp
);
719 XFREE(MTYPE_BMP_PEER
, bbdopp
);
723 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
727 static int bmp_peer_backward(struct peer
*peer
)
729 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
730 struct bmp_bgp_peer
*bbpeer
;
732 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
737 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
739 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
740 bbpeer
->open_tx_len
= 0;
741 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
742 bbpeer
->open_rx_len
= 0;
745 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
749 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
752 struct listnode
*node
;
753 struct stream
*s
, *s2
;
755 iana_safi_t pkt_safi
;
757 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
759 s
= stream_new(BGP_MAX_PACKET_SIZE
);
761 /* Make BGP update packet. */
762 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
764 /* Unfeasible Routes Length */
767 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
768 /* Total Path Attribute Length */
771 /* Convert AFI, SAFI to values for packet. */
772 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
774 /* Total Path Attribute Length */
776 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
777 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
779 stream_putw(s
, pkt_afi
);
780 stream_putc(s
, pkt_safi
);
783 bgp_packet_set_size(s
);
785 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
786 if (!peer
->afc_nego
[afi
][safi
])
789 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
791 bmp_common_hdr(s2
, BMP_VERSION_3
,
792 BMP_TYPE_ROUTE_MONITORING
);
793 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
795 stream_putl_at(s2
, BMP_LENGTH_POS
,
796 stream_get_endp(s
) + stream_get_endp(s2
));
799 pullwr_write_stream(bmp
->pullwr
, s2
);
800 pullwr_write_stream(bmp
->pullwr
, s
);
806 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
807 struct peer
*peer
, struct attr
*attr
,
808 afi_t afi
, safi_t safi
)
810 struct bpacket_attr_vec_arr vecarr
;
812 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
813 bgp_size_t total_attr_len
= 0;
815 bpacket_attr_vec_arr_reset(&vecarr
);
817 s
= stream_new(BGP_MAX_PACKET_SIZE
);
818 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
820 /* 2: withdrawn routes length */
823 /* 3: total attributes length - attrlen_pos stores the position */
824 attrlen_pos
= stream_get_endp(s
);
827 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
828 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
829 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
833 /* peer_cap_enhe & add-path removed */
834 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
835 stream_put_prefix(s
, p
);
837 size_t p1
= stream_get_endp(s
);
839 /* MPLS removed for now */
841 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
843 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
845 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
846 total_attr_len
+= stream_get_endp(s
) - p1
;
849 /* set the total attribute length correctly */
850 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
851 bgp_packet_set_size(s
);
855 static struct stream
*bmp_withdraw(const struct prefix
*p
,
856 struct prefix_rd
*prd
, afi_t afi
,
860 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
861 bgp_size_t total_attr_len
= 0;
862 bgp_size_t unfeasible_len
;
864 s
= stream_new(BGP_MAX_PACKET_SIZE
);
866 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
869 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
870 stream_put_prefix(s
, p
);
871 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
872 - BGP_UNFEASIBLE_LEN
;
873 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
876 attrlen_pos
= stream_get_endp(s
);
877 /* total attr length = 0 for now. reevaluate later */
879 mp_start
= stream_get_endp(s
);
880 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
882 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
884 /* Set the mp_unreach attr's length */
885 bgp_packet_mpunreach_end(s
, mplen_pos
);
887 /* Set total path attribute length. */
888 total_attr_len
= stream_get_endp(s
) - mp_start
;
889 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
892 bgp_packet_set_size(s
);
896 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
897 const struct prefix
*p
, struct prefix_rd
*prd
,
898 struct attr
*attr
, afi_t afi
, safi_t safi
,
901 struct stream
*hdr
, *msg
;
902 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
903 struct timeval uptime_real
;
905 monotime_to_realtime(&tv
, &uptime_real
);
907 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
909 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
911 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
912 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
913 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
915 stream_putl_at(hdr
, BMP_LENGTH_POS
,
916 stream_get_endp(hdr
) + stream_get_endp(msg
));
919 pullwr_write_stream(bmp
->pullwr
, hdr
);
920 pullwr_write_stream(bmp
->pullwr
, msg
);
925 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
930 if (bmp
->syncafi
== AFI_MAX
) {
931 FOREACH_AFI_SAFI (afi
, safi
) {
932 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
935 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
938 bmp
->syncsafi
= safi
;
940 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
941 bmp
->syncpos
.family
= afi2family(afi
);
942 bmp
->syncrdpos
= NULL
;
943 zlog_info("bmp[%s] %s %s sending table",
945 afi2str(bmp
->syncafi
),
946 safi2str(bmp
->syncsafi
));
947 /* break does not work here, 2 loops... */
950 if (bmp
->syncafi
== AFI_MAX
)
956 safi
= bmp
->syncsafi
;
958 if (!bmp
->targets
->afimon
[afi
][safi
]) {
959 /* shouldn't happen */
960 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
961 bmp
->syncafi
= AFI_MAX
;
962 bmp
->syncsafi
= SAFI_MAX
;
966 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
968 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
969 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
971 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
972 /* initialize syncrdpos to the first
973 * mid-layer table entry
975 if (!bmp
->syncrdpos
) {
976 bmp
->syncrdpos
= bgp_table_top(table
);
981 /* look for a valid mid-layer table */
983 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
987 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
988 } while (bmp
->syncrdpos
);
990 /* mid-layer table completed */
995 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
998 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
1000 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
1001 /* reset bottom-layer pointer */
1002 memset(&bmp
->syncpos
, 0,
1003 sizeof(bmp
->syncpos
));
1004 bmp
->syncpos
.family
= afi2family(afi
);
1005 /* check whethere there is a valid
1006 * next mid-layer table, otherwise
1007 * declare table completed (eor)
1009 for (bmp
->syncrdpos
= bgp_route_next(
1012 bmp
->syncrdpos
= bgp_route_next(
1014 if (bgp_dest_get_bgp_table_info(
1019 zlog_info("bmp[%s] %s %s table completed (EoR)",
1020 bmp
->remote
, afi2str(afi
),
1022 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1023 bmp_eor(bmp
, afi
, safi
, 0);
1025 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1026 bmp
->syncafi
= AFI_MAX
;
1027 bmp
->syncsafi
= SAFI_MAX
;
1030 bmp
->syncpeerid
= 0;
1031 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1034 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1035 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1036 bpiter
= bpiter
->next
) {
1037 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1039 if (bpiter
->peer
->qobj_node
.nid
1042 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1043 > bpi
->peer
->qobj_node
.nid
)
1048 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1049 for (adjiter
= bn
->adj_in
; adjiter
;
1050 adjiter
= adjiter
->next
) {
1051 if (adjiter
->peer
->qobj_node
.nid
1054 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1055 > adjin
->peer
->qobj_node
.nid
)
1067 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1069 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1070 } else if (adjin
&& bpi
1071 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1073 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1075 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1077 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1080 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1081 struct prefix_rd
*prd
= NULL
;
1082 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
1083 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1086 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1087 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1089 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1090 safi
, adjin
->uptime
);
1095 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1097 struct bmp_queue_entry
*bqe
;
1099 bqe
= bmp
->queuepos
;
1103 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1106 if (!bqe
->refcount
) {
1107 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1108 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1113 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1115 struct bmp_queue_entry
*bqe
;
1117 struct bgp_dest
*bn
;
1118 bool written
= false;
1120 bqe
= bmp_pull(bmp
);
1124 afi_t afi
= bqe
->afi
;
1125 safi_t safi
= bqe
->safi
;
1127 switch (bmp
->afistate
[afi
][safi
]) {
1128 case BMP_AFI_INACTIVE
:
1129 case BMP_AFI_NEEDSYNC
:
1132 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1133 /* currently syncing but have already passed this
1134 * prefix => send it. */
1137 /* currently syncing & haven't reached this prefix yet
1138 * => it'll be sent as part of the table sync, no need here */
1144 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1146 zlog_info("bmp: skipping queued item for deleted peer");
1149 if (peer
->status
!= Established
)
1152 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1153 struct prefix_rd
*prd
= NULL
;
1154 if (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
)
1157 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1158 struct bgp_path_info
*bpi
;
1160 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1162 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1164 if (bpi
->peer
== peer
)
1168 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1169 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1170 bpi
? bpi
->uptime
: monotime(NULL
));
1174 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1175 struct bgp_adj_in
*adjin
;
1177 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1178 adjin
= adjin
->next
) {
1179 if (adjin
->peer
== peer
)
1182 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1183 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1184 adjin
? adjin
->uptime
: monotime(NULL
));
1190 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1194 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1196 switch(bmp
->state
) {
1198 bmp_send_peerup(bmp
);
1199 bmp
->state
= BMP_Run
;
1203 if (bmp_wrmirror(bmp
, pullwr
))
1205 if (bmp_wrqueue(bmp
, pullwr
))
1207 if (bmp_wrsync(bmp
, pullwr
))
1213 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1216 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1218 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1219 bmp
->remote
, strerror(errno
));
1225 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1226 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1229 struct bmp_queue_entry
*bqe
, bqeref
;
1232 refcount
= bmp_session_count(&bt
->sessions
);
1236 memset(&bqeref
, 0, sizeof(bqeref
));
1237 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1238 bqeref
.peerid
= peer
->qobj_node
.nid
;
1242 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
)
1243 prefix_copy(&bqeref
.rd
,
1244 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1246 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1248 if (bqe
->refcount
>= refcount
)
1249 /* nothing to do here */
1252 bmp_qlist_del(&bt
->updlist
, bqe
);
1254 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1255 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1257 bmp_qhash_add(&bt
->updhash
, bqe
);
1260 bqe
->refcount
= refcount
;
1261 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1263 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1265 bmp
->queuepos
= bqe
;
1268 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1269 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1271 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1272 struct bmp_targets
*bt
;
1275 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1276 char pfxprint
[PREFIX2STR_BUFFER
];
1278 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1279 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1286 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1287 if (!bt
->afimon
[afi
][safi
])
1290 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1292 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1293 pullwr_bump(bmp
->pullwr
);
1299 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1302 stream_putw(s
, type
);
1304 stream_putl(s
, value
);
1308 static int bmp_stats(struct thread
*thread
)
1310 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1313 struct listnode
*node
;
1317 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1320 gettimeofday(&tv
, NULL
);
1322 /* Walk down all peers */
1323 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1324 size_t count
= 0, count_pos
, len
;
1326 if (peer
->status
!= Established
)
1329 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1330 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1331 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1333 count_pos
= stream_get_endp(s
);
1336 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1337 peer
->stat_pfx_filter
);
1338 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1339 peer
->stat_pfx_aspath_loop
);
1340 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1341 peer
->stat_pfx_originator_loop
);
1342 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1343 peer
->stat_pfx_cluster_loop
);
1344 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1345 peer
->stat_pfx_dup_withdraw
);
1346 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1347 peer
->stat_upd_7606
);
1348 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1349 peer
->stat_pfx_nh_invalid
);
1351 stream_putl_at(s
, count_pos
, count
);
1353 len
= stream_get_endp(s
);
1354 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1356 bmp_send_all(bt
->bmpbgp
, s
);
1361 /* read from the BMP socket to detect session termination */
1362 static int bmp_read(struct thread
*t
)
1364 struct bmp
*bmp
= THREAD_ARG(t
);
1370 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1372 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1373 } else if (n
== 0) {
1374 /* the TCP session was terminated by the far end */
1375 bmp_wrerr(bmp
, NULL
, true);
1377 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1378 /* the TCP session experienced a fatal error, likely a timeout */
1379 bmp_wrerr(bmp
, NULL
, false);
1383 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1388 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1390 union sockunion su
, *sumem
;
1393 struct access_list
*acl
= NULL
;
1394 enum filter_type ret
;
1395 char buf
[SU_ADDRSTRLEN
];
1398 sumem
= sockunion_getpeername(bmp_sock
);
1403 memcpy(&su
, sumem
, sizeof(su
));
1404 sockunion_free(sumem
);
1406 set_nonblocking(bmp_sock
);
1407 set_cloexec(bmp_sock
);
1409 if (!sockunion2hostprefix(&su
, &p
)) {
1417 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1420 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1426 ret
= FILTER_PERMIT
;
1428 ret
= access_list_apply(acl
, &p
);
1431 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1432 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1433 su
.sa
.sa_family
== AF_INET
1434 ? ntohs(su
.sin
.sin_port
)
1435 : ntohs(su
.sin6
.sin6_port
));
1437 if (ret
== FILTER_DENY
) {
1438 bt
->cnt_aclrefused
++;
1439 zlog_info("bmp[%s] connection refused by access-list", buf
);
1445 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1446 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1447 bmp_sock
, safe_strerror(errno
), errno
);
1448 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1449 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1450 bmp_sock
, safe_strerror(errno
), errno
);
1452 zlog_info("bmp[%s] connection established", buf
);
1454 /* Allocate new BMP structure and set up default values. */
1455 bmp
= bmp_new(bt
, bmp_sock
);
1456 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1458 bmp
->state
= BMP_PeerUp
;
1459 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1461 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1462 bmp_send_initiation(bmp
);
1467 /* Accept BMP connection. */
1468 static int bmp_accept(struct thread
*thread
)
1471 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1474 /* We continue hearing BMP socket. */
1475 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1477 memset(&su
, 0, sizeof(union sockunion
));
1479 /* We can handle IPv4 or IPv6 socket. */
1480 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1482 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1485 bmp_open(bl
->targets
, bmp_sock
);
1489 static void bmp_close(struct bmp
*bmp
)
1491 struct bmp_queue_entry
*bqe
;
1492 struct bmp_mirrorq
*bmq
;
1494 THREAD_OFF(bmp
->t_read
);
1497 bmp_active_disconnected(bmp
->active
);
1499 while ((bmq
= bmp_pull_mirror(bmp
)))
1501 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1502 while ((bqe
= bmp_pull(bmp
)))
1504 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1506 THREAD_OFF(bmp
->t_read
);
1507 pullwr_del(bmp
->pullwr
);
1511 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1513 struct bmp_bgp dummy
= { .bgp
= bgp
};
1514 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1517 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1519 struct bmp_bgp
*bmpbgp
;
1521 bmpbgp
= bmp_bgp_find(bgp
);
1525 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1527 bmpbgp
->mirror_qsizelimit
= ~0UL;
1528 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1529 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1534 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1536 struct bmp_targets
*bt
;
1538 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1540 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1541 bmp_targets_put(bt
);
1543 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1544 XFREE(MTYPE_BMP
, bmpbgp
);
1547 static int bmp_bgp_del(struct bgp
*bgp
)
1549 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1552 bmp_bgp_put(bmpbgp
);
1556 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1558 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1559 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1562 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1564 struct bmp_bgp_peer
*bbpeer
;
1566 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1570 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1571 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1572 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1577 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1579 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1580 struct bmp_targets dummy
;
1584 dummy
.name
= (char *)name
;
1585 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1588 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1590 struct bmp_targets
*bt
;
1592 bt
= bmp_targets_find1(bgp
, name
);
1596 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1597 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1599 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1600 bmp_session_init(&bt
->sessions
);
1601 bmp_qhash_init(&bt
->updhash
);
1602 bmp_qlist_init(&bt
->updlist
);
1603 bmp_actives_init(&bt
->actives
);
1604 bmp_listeners_init(&bt
->listeners
);
1606 QOBJ_REG(bt
, bmp_targets
);
1607 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1611 static void bmp_targets_put(struct bmp_targets
*bt
)
1614 struct bmp_active
*ba
;
1616 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1619 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1624 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1627 bmp_listeners_fini(&bt
->listeners
);
1628 bmp_actives_fini(&bt
->actives
);
1629 bmp_qhash_fini(&bt
->updhash
);
1630 bmp_qlist_fini(&bt
->updlist
);
1632 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1633 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1634 bmp_session_fini(&bt
->sessions
);
1636 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1637 XFREE(MTYPE_BMP_TARGETS
, bt
);
1640 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1641 const union sockunion
*su
,
1644 struct bmp_listener dummy
;
1647 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1650 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1651 const union sockunion
*su
,
1654 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1659 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1665 bmp_listeners_add(&bt
->listeners
, bl
);
1669 static void bmp_listener_put(struct bmp_listener
*bl
)
1671 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1672 XFREE(MTYPE_BMP_LISTENER
, bl
);
1675 static void bmp_listener_start(struct bmp_listener
*bl
)
1679 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1683 sockopt_reuseaddr(sock
);
1684 sockopt_reuseport(sock
);
1685 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1688 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1692 ret
= listen(sock
, 3);
1697 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1703 static void bmp_listener_stop(struct bmp_listener
*bl
)
1705 THREAD_OFF(bl
->t_accept
);
1712 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1713 const char *hostname
, int port
)
1715 struct bmp_active dummy
;
1716 dummy
.hostname
= (char *)hostname
;
1718 return bmp_actives_find(&bt
->actives
, &dummy
);
1721 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1722 const char *hostname
, int port
)
1724 struct bmp_active
*ba
;
1726 ba
= bmp_active_find(bt
, hostname
, port
);
1730 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1732 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1734 ba
->minretry
= BMP_DFLT_MINRETRY
;
1735 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1738 bmp_actives_add(&bt
->actives
, ba
);
1742 static void bmp_active_put(struct bmp_active
*ba
)
1744 THREAD_OFF(ba
->t_timer
);
1745 THREAD_OFF(ba
->t_read
);
1746 THREAD_OFF(ba
->t_write
);
1748 bmp_actives_del(&ba
->targets
->actives
, ba
);
1751 ba
->bmp
->active
= NULL
;
1755 if (ba
->socket
!= -1)
1758 XFREE(MTYPE_TMP
, ba
->hostname
);
1759 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1762 static void bmp_active_setup(struct bmp_active
*ba
);
1764 static void bmp_active_connect(struct bmp_active
*ba
)
1766 enum connect_result res
;
1767 char buf
[SU_ADDRSTRLEN
];
1769 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1770 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1771 if (ba
->socket
< 0) {
1772 zlog_warn("bmp[%s]: failed to create socket",
1777 set_nonblocking(ba
->socket
);
1778 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1779 htons(ba
->port
), 0);
1782 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1784 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1785 ba
->hostname
, buf
, ba
->port
);
1789 case connect_success
:
1791 case connect_in_progress
:
1792 bmp_active_setup(ba
);
1797 /* exhausted all addresses */
1798 ba
->curretry
+= ba
->curretry
/ 2;
1799 bmp_active_setup(ba
);
1802 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1803 int numaddrs
, union sockunion
*addr
)
1805 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1808 if (numaddrs
<= 0) {
1809 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1810 ba
->hostname
, errstr
);
1811 ba
->last_err
= errstr
;
1812 ba
->curretry
+= ba
->curretry
/ 2;
1815 bmp_active_setup(ba
);
1819 if (numaddrs
> (int)array_size(ba
->addrs
))
1820 numaddrs
= array_size(ba
->addrs
);
1823 ba
->addrtotal
= numaddrs
;
1824 for (i
= 0; i
< ba
->addrtotal
; i
++)
1825 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1827 bmp_active_connect(ba
);
1830 static int bmp_active_thread(struct thread
*t
)
1832 struct bmp_active
*ba
= THREAD_ARG(t
);
1835 char buf
[SU_ADDRSTRLEN
];
1837 /* all 3 end up here, though only timer or read+write are active
1839 THREAD_OFF(ba
->t_timer
);
1840 THREAD_OFF(ba
->t_read
);
1841 THREAD_OFF(ba
->t_write
);
1843 ba
->last_err
= NULL
;
1845 if (ba
->socket
== -1) {
1846 resolver_resolve(&ba
->resq
, AF_UNSPEC
, ba
->hostname
,
1847 bmp_active_resolved
);
1851 slen
= sizeof(status
);
1852 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1855 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1856 if (ret
< 0 || status
!= 0) {
1857 ba
->last_err
= strerror(status
);
1858 zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
1859 ba
->hostname
, buf
, ba
->port
, ba
->last_err
);
1863 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1864 ba
->hostname
, buf
, ba
->port
);
1866 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1870 ba
->bmp
->active
= ba
;
1872 ba
->curretry
= ba
->minretry
;
1879 bmp_active_connect(ba
);
1883 static void bmp_active_disconnected(struct bmp_active
*ba
)
1886 bmp_active_setup(ba
);
1889 static void bmp_active_setup(struct bmp_active
*ba
)
1891 THREAD_OFF(ba
->t_timer
);
1892 THREAD_OFF(ba
->t_read
);
1893 THREAD_OFF(ba
->t_write
);
1897 if (ba
->resq
.callback
)
1900 if (ba
->curretry
> ba
->maxretry
)
1901 ba
->curretry
= ba
->maxretry
;
1903 if (ba
->socket
== -1)
1904 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1905 ba
->curretry
, &ba
->t_timer
);
1907 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1909 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1914 static struct cmd_node bmp_node
= {
1917 .parent_node
= BGP_NODE
,
1918 .prompt
= "%s(config-bgp-bmp)# "
1921 #define BMP_STR "BGP Monitoring Protocol\n"
1923 #ifndef VTYSH_EXTRACT_PL
1924 #include "bgpd/bgp_bmp_clippy.c"
1927 DEFPY_NOSH(bmp_targets_main
,
1929 "bmp targets BMPTARGETS",
1931 "Create BMP target group\n"
1932 "Name of the BMP target group\n")
1934 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1935 struct bmp_targets
*bt
;
1937 bt
= bmp_targets_get(bgp
, bmptargets
);
1939 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1943 DEFPY(no_bmp_targets_main
,
1945 "no bmp targets BMPTARGETS",
1948 "Delete BMP target group\n"
1949 "Name of the BMP target group\n")
1951 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1952 struct bmp_targets
*bt
;
1954 bt
= bmp_targets_find1(bgp
, bmptargets
);
1956 vty_out(vty
, "%% BMP target group not found\n");
1959 bmp_targets_put(bt
);
1963 DEFPY(bmp_listener_main
,
1965 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1967 "Listen for inbound BMP connections\n"
1968 "IPv6 address to listen on\n"
1969 "IPv4 address to listen on\n"
1971 "TCP Port number\n")
1973 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1974 struct bmp_listener
*bl
;
1976 bl
= bmp_listener_get(bt
, listener
, port
);
1978 bmp_listener_start(bl
);
1983 DEFPY(no_bmp_listener_main
,
1984 no_bmp_listener_cmd
,
1985 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1988 "Create BMP listener\n"
1989 "IPv6 address to listen on\n"
1990 "IPv4 address to listen on\n"
1992 "TCP Port number\n")
1994 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1995 struct bmp_listener
*bl
;
1997 bl
= bmp_listener_find(bt
, listener
, port
);
1999 vty_out(vty
, "%% BMP listener not found\n");
2002 bmp_listener_stop(bl
);
2003 bmp_listener_put(bl
);
2009 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}",
2012 "Actively establish connection to monitoring station\n"
2013 "Monitoring station hostname or address\n"
2016 "Minimum connection retry interval\n"
2017 "Minimum connection retry interval (milliseconds)\n"
2018 "Maximum connection retry interval\n"
2019 "Maximum connection retry interval (milliseconds)\n")
2021 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2022 struct bmp_active
*ba
;
2025 ba
= bmp_active_find(bt
, hostname
, port
);
2027 vty_out(vty
, "%% No such active connection found\n");
2034 ba
= bmp_active_get(bt
, hostname
, port
);
2036 ba
->minretry
= min_retry
;
2038 ba
->maxretry
= max_retry
;
2039 ba
->curretry
= ba
->minretry
;
2040 bmp_active_setup(ba
);
2047 "[no] <ip|ipv6>$af access-list WORD",
2051 "Access list to restrict BMP sessions\n"
2052 "Access list name\n")
2054 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2059 if (!strcmp(af
, "ipv6"))
2060 what
= &bt
->acl6_name
;
2062 what
= &bt
->acl_name
;
2064 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2066 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2071 DEFPY(bmp_stats_cfg
,
2073 "[no] bmp stats [interval (100-86400000)]",
2076 "Send BMP statistics messages\n"
2077 "Specify BMP stats interval\n"
2078 "Interval (milliseconds) to send BMP Stats in\n")
2080 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2082 THREAD_OFF(bt
->t_stats
);
2085 else if (interval_str
)
2086 bt
->stat_msec
= interval
;
2088 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2091 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2096 DEFPY(bmp_monitor_cfg
,
2098 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
2101 "Send BMP route monitoring messages\n"
2102 "Address Family\nAddress Family\nAddress Family\n"
2103 "Address Family\nAddress Family\nAddress Family\n"
2104 "Send state before policy and filter processing\n"
2105 "Send state with policy and filters applied\n")
2112 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2115 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2116 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2118 if (policy
[1] == 'r')
2119 flag
= BMP_MON_PREPOLICY
;
2121 flag
= BMP_MON_POSTPOLICY
;
2123 prev
= bt
->afimon
[afi
][safi
];
2125 bt
->afimon
[afi
][safi
] &= ~flag
;
2127 bt
->afimon
[afi
][safi
] |= flag
;
2129 if (prev
== bt
->afimon
[afi
][safi
])
2132 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2133 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2134 bmp
->syncafi
= AFI_MAX
;
2135 bmp
->syncsafi
= SAFI_MAX
;
2138 if (!bt
->afimon
[afi
][safi
]) {
2139 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2143 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2149 DEFPY(bmp_mirror_cfg
,
2154 "Send BMP route mirroring messages\n")
2156 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2159 if (bt
->mirror
== !no
)
2166 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2167 struct bmp_mirrorq
*bmq
;
2169 while ((bmq
= bmp_pull_mirror(bmp
)))
2171 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2176 DEFPY(bmp_mirror_limit_cfg
,
2177 bmp_mirror_limit_cmd
,
2178 "bmp mirror buffer-limit (0-4294967294)",
2180 "Route Mirroring settings\n"
2181 "Configure maximum memory used for buffered mirroring messages\n"
2184 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2185 struct bmp_bgp
*bmpbgp
;
2187 bmpbgp
= bmp_bgp_get(bgp
);
2188 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2193 DEFPY(no_bmp_mirror_limit_cfg
,
2194 no_bmp_mirror_limit_cmd
,
2195 "no bmp mirror buffer-limit [(0-4294967294)]",
2198 "Route Mirroring settings\n"
2199 "Configure maximum memory used for buffered mirroring messages\n"
2202 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2203 struct bmp_bgp
*bmpbgp
;
2205 bmpbgp
= bmp_bgp_get(bgp
);
2206 bmpbgp
->mirror_qsizelimit
= ~0UL;
2218 struct bmp_bgp
*bmpbgp
;
2219 struct bmp_targets
*bt
;
2220 struct bmp_listener
*bl
;
2221 struct bmp_active
*ba
;
2224 char buf
[SU_ADDRSTRLEN
];
2225 char uptime
[BGP_UPTIME_LEN
];
2228 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2229 vty_out(vty
, "BMP state for BGP %s:\n\n",
2230 bmpbgp
->bgp
->name_pretty
);
2231 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2232 bmpbgp
->mirror_qsize
,
2233 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2234 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2235 bmpbgp
->mirror_qsizemax
);
2236 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2237 vty_out(vty
, " %9zu bytes buffer size limit\n",
2238 bmpbgp
->mirror_qsizelimit
);
2241 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2242 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2243 vty_out(vty
, " Route Mirroring %sabled\n",
2244 bt
->mirror
? "en" : "dis");
2249 FOREACH_AFI_SAFI (afi
, safi
) {
2250 const char *str
= NULL
;
2252 switch (bt
->afimon
[afi
][safi
]) {
2253 case BMP_MON_PREPOLICY
:
2256 case BMP_MON_POSTPOLICY
:
2257 str
= "post-policy";
2259 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2260 str
= "pre-policy and post-policy";
2265 vty_out(vty
, " Route Monitoring %s %s %s\n",
2266 afi2str(afi
), safi2str(safi
), str
);
2269 vty_out(vty
, " Listeners:\n");
2270 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2271 vty_out(vty
, " %s:%d\n",
2272 sockunion2str(&bl
->addr
, buf
,
2273 SU_ADDRSTRLEN
), bl
->port
);
2275 vty_out(vty
, "\n Outbound connections:\n");
2276 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2277 ttable_add_row(tt
, "remote|state||timer");
2278 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2279 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2280 const char *state_str
= "?";
2283 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2284 uptime
, sizeof(uptime
),
2286 ttable_add_row(tt
, "%s:%d|Up|%s|%s",
2287 ba
->hostname
, ba
->port
,
2288 ba
->bmp
->remote
, uptime
);
2295 long trem
= thread_timer_remain_second(
2298 peer_uptime(monotime(NULL
) - trem
,
2299 uptime
, sizeof(uptime
),
2301 state_str
= "RetryWait";
2302 } else if (ba
->t_read
) {
2303 state_str
= "Connecting";
2304 } else if (ba
->resq
.callback
) {
2305 state_str
= "Resolving";
2308 ttable_add_row(tt
, "%s:%d|%s|%s|%s",
2309 ba
->hostname
, ba
->port
,
2311 ba
->last_err
? ba
->last_err
: "",
2315 out
= ttable_dump(tt
, "\n");
2316 vty_out(vty
, "%s", out
);
2317 XFREE(MTYPE_TMP
, out
);
2320 vty_out(vty
, "\n %zu connected clients:\n",
2321 bmp_session_count(&bt
->sessions
));
2322 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2323 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2324 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2326 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2330 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2332 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2333 sizeof(uptime
), false, NULL
);
2335 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2336 bmp
->remote
, uptime
,
2339 bmp
->cnt_mirror_overruns
,
2342 out
= ttable_dump(tt
, "\n");
2343 vty_out(vty
, "%s", out
);
2344 XFREE(MTYPE_TMP
, out
);
2353 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2355 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2356 struct bmp_targets
*bt
;
2357 struct bmp_listener
*bl
;
2358 struct bmp_active
*ba
;
2359 char buf
[SU_ADDRSTRLEN
];
2366 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2367 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2368 bmpbgp
->mirror_qsizelimit
);
2370 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2371 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2374 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2376 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2379 vty_out(vty
, " bmp stats interval %d\n",
2383 vty_out(vty
, " bmp mirror\n");
2385 FOREACH_AFI_SAFI (afi
, safi
) {
2386 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2388 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2389 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2390 afi_str
, safi2str(safi
));
2391 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2392 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2393 afi_str
, safi2str(safi
));
2395 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2396 vty_out(vty
, " \n bmp listener %s port %d\n",
2397 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2400 frr_each (bmp_actives
, &bt
->actives
, ba
)
2401 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2402 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2408 static int bgp_bmp_init(struct thread_master
*tm
)
2410 install_node(&bmp_node
);
2411 install_default(BMP_NODE
);
2412 install_element(BGP_NODE
, &bmp_targets_cmd
);
2413 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2415 install_element(BMP_NODE
, &bmp_listener_cmd
);
2416 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2417 install_element(BMP_NODE
, &bmp_connect_cmd
);
2418 install_element(BMP_NODE
, &bmp_acl_cmd
);
2419 install_element(BMP_NODE
, &bmp_stats_cmd
);
2420 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2421 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2423 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2424 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2426 install_element(VIEW_NODE
, &show_bmp_cmd
);
2432 static int bgp_bmp_module_init(void)
2434 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2435 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2436 hook_register(peer_status_changed
, bmp_peer_established
);
2437 hook_register(peer_backward_transition
, bmp_peer_backward
);
2438 hook_register(bgp_process
, bmp_process
);
2439 hook_register(bgp_inst_config_write
, bmp_config_write
);
2440 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2441 hook_register(frr_late_init
, bgp_bmp_init
);
2445 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2446 .description
= "bgpd BMP module",
2447 .init
= bgp_bmp_module_init
,