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"
53 #include "bgpd/bgp_network.h"
55 static void bmp_close(struct bmp
*bmp
);
56 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
);
57 static void bmp_targets_put(struct bmp_targets
*bt
);
58 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
);
59 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
);
60 static void bmp_active_disconnected(struct bmp_active
*ba
);
61 static void bmp_active_put(struct bmp_active
*ba
);
63 DEFINE_MGROUP(BMP
, "BMP (BGP Monitoring Protocol)");
65 DEFINE_MTYPE_STATIC(BMP
, BMP_CONN
, "BMP connection state");
66 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETS
, "BMP targets");
67 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETSNAME
, "BMP targets name");
68 DEFINE_MTYPE_STATIC(BMP
, BMP_LISTENER
, "BMP listener");
69 DEFINE_MTYPE_STATIC(BMP
, BMP_ACTIVE
, "BMP active connection config");
70 DEFINE_MTYPE_STATIC(BMP
, BMP_ACLNAME
, "BMP access-list name");
71 DEFINE_MTYPE_STATIC(BMP
, BMP_QUEUE
, "BMP update queue item");
72 DEFINE_MTYPE_STATIC(BMP
, BMP
, "BMP instance state");
73 DEFINE_MTYPE_STATIC(BMP
, BMP_MIRRORQ
, "BMP route mirroring buffer");
74 DEFINE_MTYPE_STATIC(BMP
, BMP_PEER
, "BMP per BGP peer data");
75 DEFINE_MTYPE_STATIC(BMP
, BMP_OPEN
, "BMP stored BGP OPEN message");
77 DEFINE_QOBJ_TYPE(bmp_targets
);
79 static int bmp_bgp_cmp(const struct bmp_bgp
*a
, const struct bmp_bgp
*b
)
88 static uint32_t bmp_bgp_hash(const struct bmp_bgp
*e
)
90 return jhash(&e
->bgp
, sizeof(e
->bgp
), 0x55aa5a5a);
93 DECLARE_HASH(bmp_bgph
, struct bmp_bgp
, bbi
, bmp_bgp_cmp
, bmp_bgp_hash
);
95 struct bmp_bgph_head bmp_bgph
;
97 static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer
*a
,
98 const struct bmp_bgp_peer
*b
)
100 if (a
->peerid
< b
->peerid
)
102 if (a
->peerid
> b
->peerid
)
107 static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer
*e
)
112 DECLARE_HASH(bmp_peerh
, struct bmp_bgp_peer
, bpi
,
113 bmp_bgp_peer_cmp
, bmp_bgp_peer_hash
);
115 struct bmp_peerh_head bmp_peerh
;
117 DECLARE_LIST(bmp_mirrorq
, struct bmp_mirrorq
, bmi
);
119 /* listener management */
121 static int bmp_listener_cmp(const struct bmp_listener
*a
,
122 const struct bmp_listener
*b
)
126 c
= sockunion_cmp(&a
->addr
, &b
->addr
);
129 if (a
->port
< b
->port
)
131 if (a
->port
> b
->port
)
136 DECLARE_SORTLIST_UNIQ(bmp_listeners
, struct bmp_listener
, bli
,
139 static void bmp_listener_put(struct bmp_listener
*bl
)
141 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
142 XFREE(MTYPE_BMP_LISTENER
, bl
);
145 static int bmp_targets_cmp(const struct bmp_targets
*a
,
146 const struct bmp_targets
*b
)
148 return strcmp(a
->name
, b
->name
);
151 DECLARE_SORTLIST_UNIQ(bmp_targets
, struct bmp_targets
, bti
, bmp_targets_cmp
);
153 DECLARE_LIST(bmp_session
, struct bmp
, bsi
);
155 DECLARE_DLIST(bmp_qlist
, struct bmp_queue_entry
, bli
);
157 static int bmp_qhash_cmp(const struct bmp_queue_entry
*a
,
158 const struct bmp_queue_entry
*b
)
161 if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
&& b
->afi
== AFI_L2VPN
162 && b
->safi
== SAFI_EVPN
) {
163 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
166 } else if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
)
168 else if (b
->afi
== AFI_L2VPN
&& b
->safi
== SAFI_EVPN
)
171 if (a
->afi
== b
->afi
&& a
->safi
== SAFI_MPLS_VPN
&&
172 b
->safi
== SAFI_MPLS_VPN
) {
173 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
176 } else if (a
->safi
== SAFI_MPLS_VPN
)
178 else if (b
->safi
== SAFI_MPLS_VPN
)
181 ret
= prefix_cmp(&a
->p
, &b
->p
);
184 ret
= memcmp(&a
->peerid
, &b
->peerid
,
185 offsetof(struct bmp_queue_entry
, refcount
) -
186 offsetof(struct bmp_queue_entry
, peerid
));
190 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
194 key
= prefix_hash_key((void *)&e
->p
);
195 key
= jhash(&e
->peerid
,
196 offsetof(struct bmp_queue_entry
, refcount
)
197 - offsetof(struct bmp_queue_entry
, peerid
),
199 if ((e
->afi
== AFI_L2VPN
&& e
->safi
== SAFI_EVPN
) ||
200 (e
->safi
== SAFI_MPLS_VPN
))
202 offsetof(struct bmp_queue_entry
, rd
)
203 - offsetof(struct bmp_queue_entry
, refcount
)
204 + PSIZE(e
->rd
.prefixlen
),
210 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
211 bmp_qhash_cmp
, bmp_qhash_hkey
);
213 static int bmp_active_cmp(const struct bmp_active
*a
,
214 const struct bmp_active
*b
)
218 c
= strcmp(a
->hostname
, b
->hostname
);
221 if (a
->port
< b
->port
)
223 if (a
->port
> b
->port
)
228 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
);
230 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
232 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
236 monotime(&new->t_up
);
238 new->socket
= bmp_sock
;
239 new->syncafi
= AFI_MAX
;
241 FOREACH_AFI_SAFI (afi
, safi
) {
242 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
243 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
246 bmp_session_add_tail(&bt
->sessions
, new);
250 static void bmp_free(struct bmp
*bmp
)
252 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
253 XFREE(MTYPE_BMP_CONN
, bmp
);
256 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
259 stream_putl(s
, 0); //dummy message length. will be set later.
260 stream_putc(s
, type
);
263 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
264 uint8_t flags
, const struct timeval
*tv
)
266 char peer_distinguisher
[8];
268 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
269 #define BMP_PEER_TYPE_RD_INSTANCE 1
270 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
272 #define BMP_PEER_FLAG_V (1 << 7)
273 #define BMP_PEER_FLAG_L (1 << 6)
274 #define BMP_PEER_FLAG_A (1 << 5)
277 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
280 if (peer
->su
.sa
.sa_family
== AF_INET6
)
281 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
283 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
284 stream_putc(s
, flags
);
286 /* Peer Distinguisher */
287 memset (&peer_distinguisher
[0], 0, 8);
288 stream_put(s
, &peer_distinguisher
[0], 8);
291 if (peer
->su
.sa
.sa_family
== AF_INET6
)
292 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
293 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
297 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
306 stream_putl(s
, peer
->as
);
309 stream_put_in_addr(s
, &peer
->remote_id
);
313 stream_putl(s
, tv
->tv_sec
);
314 stream_putl(s
, tv
->tv_usec
);
321 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
324 int len
= strlen (string
);
325 stream_putw(s
, type
);
327 stream_put(s
, string
, len
);
330 static int bmp_send_initiation(struct bmp
*bmp
)
334 s
= stream_new(BGP_MAX_PACKET_SIZE
);
335 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
337 #define BMP_INFO_TYPE_SYSDESCR 1
338 #define BMP_INFO_TYPE_SYSNAME 2
339 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
340 FRR_FULL_NAME
" " FRR_VER_SHORT
);
341 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
343 len
= stream_get_endp(s
);
344 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
346 pullwr_write_stream(bmp
->pullwr
, s
);
351 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
354 uint8_t marker
[16] = {
355 0xff, 0xff, 0xff, 0xff,
356 0xff, 0xff, 0xff, 0xff,
357 0xff, 0xff, 0xff, 0xff,
358 0xff, 0xff, 0xff, 0xff,
361 stream_put(s
, marker
, sizeof(marker
));
362 len_pos
= stream_get_endp(s
);
364 stream_putc(s
, BGP_MSG_NOTIFY
);
365 stream_putc(s
, nfy
->code
);
366 stream_putc(s
, nfy
->subcode
);
367 stream_put(s
, nfy
->data
, nfy
->length
);
369 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
373 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
377 struct timeval uptime
, uptime_real
;
379 uptime
.tv_sec
= peer
->uptime
;
381 monotime_to_realtime(&uptime
, &uptime_real
);
383 #define BGP_BMP_MAX_PACKET_SIZE 1024
384 s
= stream_new(BGP_MAX_PACKET_SIZE
);
386 if (peer_established(peer
) && !down
) {
387 struct bmp_bgp_peer
*bbpeer
;
389 bmp_common_hdr(s
, BMP_VERSION_3
,
390 BMP_TYPE_PEER_UP_NOTIFICATION
);
391 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
393 /* Local Address (16 bytes) */
394 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
395 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
396 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
400 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
403 /* Local Port, Remote Port */
404 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
405 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
406 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
407 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
408 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
409 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
410 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
411 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
413 static const uint8_t dummy_open
[] = {
414 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
415 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
419 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
421 if (bbpeer
&& bbpeer
->open_tx
)
422 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
424 stream_put(s
, dummy_open
, sizeof(dummy_open
));
425 zlog_warn("bmp: missing TX OPEN message for peer %s",
428 if (bbpeer
&& bbpeer
->open_rx
)
429 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
431 stream_put(s
, dummy_open
, sizeof(dummy_open
));
432 zlog_warn("bmp: missing RX OPEN message for peer %s",
437 bmp_put_info_tlv(s
, 0, peer
->desc
);
442 bmp_common_hdr(s
, BMP_VERSION_3
,
443 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
444 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
446 type_pos
= stream_get_endp(s
);
447 stream_putc(s
, 0); /* placeholder for down reason */
449 switch (peer
->last_reset
) {
450 case PEER_DOWN_NOTIFY_RECEIVED
:
451 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
452 bmp_notify_put(s
, &peer
->notify
);
454 case PEER_DOWN_CLOSE_SESSION
:
455 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
457 case PEER_DOWN_WAITING_NHT
:
458 type
= BMP_PEERDOWN_LOCAL_FSM
;
459 stream_putw(s
, BGP_FSM_TcpConnectionFails
);
462 * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
463 * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
465 * See RFC7854 ss. 4.9
468 type
= BMP_PEERDOWN_LOCAL_FSM
;
469 stream_putw(s
, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE
);
472 stream_putc_at(s
, type_pos
, type
);
475 len
= stream_get_endp(s
);
476 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
481 static int bmp_send_peerup(struct bmp
*bmp
)
484 struct listnode
*node
;
487 /* Walk down all peers */
488 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
489 s
= bmp_peerstate(peer
, false);
490 pullwr_write_stream(bmp
->pullwr
, s
);
497 /* XXX: kludge - filling the pullwr's buffer */
498 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
500 struct bmp_targets
*bt
;
503 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
504 frr_each(bmp_session
, &bt
->sessions
, bmp
)
505 pullwr_write_stream(bmp
->pullwr
, s
);
513 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
514 #define BMP_MIRROR_TLV_TYPE_INFO 1
516 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
517 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
519 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
521 struct bmp_mirrorq
*bmq
;
523 bmq
= bmp
->mirrorpos
;
527 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
530 if (!bmq
->refcount
) {
531 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
532 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
537 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
539 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
540 struct bmp_mirrorq
*bmq
, *inner
;
541 struct bmp_targets
*bt
;
544 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
546 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
549 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
550 if (bmp
->mirrorpos
!= bmq
)
553 while ((inner
= bmp_pull_mirror(bmp
))) {
554 if (!inner
->refcount
)
555 XFREE(MTYPE_BMP_MIRRORQ
,
559 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
561 bmp
->mirror_lost
= true;
562 pullwr_bump(bmp
->pullwr
);
568 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
569 struct stream
*packet
)
571 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
573 struct bmp_mirrorq
*qitem
;
574 struct bmp_targets
*bt
;
577 frrtrace(3, frr_bgp
, bmp_mirror_packet
, peer
, type
, packet
);
579 gettimeofday(&tv
, NULL
);
581 if (type
== BGP_MSG_OPEN
) {
582 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
584 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
586 bbpeer
->open_rx_len
= size
;
587 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
588 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
594 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
595 qitem
->peerid
= peer
->qobj_node
.nid
;
598 memcpy(qitem
->data
, packet
->data
, size
);
600 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
603 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
606 bmp
->mirrorpos
= qitem
;
607 pullwr_bump(bmp
->pullwr
);
610 if (qitem
->refcount
== 0)
611 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
613 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
614 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
616 bmp_mirror_cull(bmpbgp
);
618 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
619 bmpbgp
->mirror_qsize
);
624 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
629 gettimeofday(&tv
, NULL
);
631 s
= stream_new(BGP_MAX_PACKET_SIZE
);
633 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
634 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
636 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
638 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
639 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
641 bmp
->cnt_mirror_overruns
++;
642 pullwr_write_stream(bmp
->pullwr
, s
);
646 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
648 struct bmp_mirrorq
*bmq
;
650 bool written
= false;
652 if (bmp
->mirror_lost
) {
653 bmp_wrmirror_lost(bmp
, pullwr
);
654 bmp
->mirror_lost
= false;
658 bmq
= bmp_pull_mirror(bmp
);
662 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
664 zlog_info("bmp: skipping mirror message for deleted peer");
669 s
= stream_new(BGP_MAX_PACKET_SIZE
);
671 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
672 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
674 /* BMP Mirror TLV. */
675 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
676 stream_putw(s
, bmq
->len
);
677 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
680 pullwr_write_stream(bmp
->pullwr
, s
);
681 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
688 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
692 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
693 struct stream
*packet
)
695 if (type
== BGP_MSG_OPEN
) {
696 frrtrace(2, frr_bgp
, bmp_update_saved_open
, peer
, packet
);
698 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
700 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
702 bbpeer
->open_tx_len
= size
;
703 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
704 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
709 static int bmp_peer_status_changed(struct peer
*peer
)
711 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
712 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
714 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
719 if (peer
->status
== Deleted
) {
720 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
722 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
723 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
724 bmp_peerh_del(&bmp_peerh
, bbpeer
);
725 XFREE(MTYPE_BMP_PEER
, bbpeer
);
730 /* Check if this peer just went to Established */
731 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
734 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
735 bbpeer
= bmp_bgp_peer_get(peer
);
736 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
738 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
739 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
741 bbpeer
->open_tx
= bbdopp
->open_tx
;
742 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
743 bbpeer
->open_rx
= bbdopp
->open_rx
;
744 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
746 bmp_peerh_del(&bmp_peerh
, bbdopp
);
747 XFREE(MTYPE_BMP_PEER
, bbdopp
);
751 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
755 static int bmp_peer_backward(struct peer
*peer
)
757 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
758 struct bmp_bgp_peer
*bbpeer
;
760 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
765 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
767 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
768 bbpeer
->open_tx_len
= 0;
769 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
770 bbpeer
->open_rx_len
= 0;
773 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
777 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
780 struct listnode
*node
;
781 struct stream
*s
, *s2
;
782 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
783 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
785 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
787 s
= stream_new(BGP_MAX_PACKET_SIZE
);
789 /* Make BGP update packet. */
790 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
792 /* Unfeasible Routes Length */
795 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
796 /* Total Path Attribute Length */
799 /* Convert AFI, SAFI to values for packet. */
800 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
802 /* Total Path Attribute Length */
804 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
805 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
807 stream_putw(s
, pkt_afi
);
808 stream_putc(s
, pkt_safi
);
811 bgp_packet_set_size(s
);
813 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
814 if (!peer
->afc_nego
[afi
][safi
])
817 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
819 bmp_common_hdr(s2
, BMP_VERSION_3
,
820 BMP_TYPE_ROUTE_MONITORING
);
821 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
823 stream_putl_at(s2
, BMP_LENGTH_POS
,
824 stream_get_endp(s
) + stream_get_endp(s2
));
827 pullwr_write_stream(bmp
->pullwr
, s2
);
828 pullwr_write_stream(bmp
->pullwr
, s
);
834 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
835 struct peer
*peer
, struct attr
*attr
,
836 afi_t afi
, safi_t safi
)
838 struct bpacket_attr_vec_arr vecarr
;
840 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
841 bgp_size_t total_attr_len
= 0;
843 bpacket_attr_vec_arr_reset(&vecarr
);
845 s
= stream_new(BGP_MAX_PACKET_SIZE
);
846 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
848 /* 2: withdrawn routes length */
851 /* 3: total attributes length - attrlen_pos stores the position */
852 attrlen_pos
= stream_get_endp(s
);
855 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
856 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
857 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
861 /* peer_cap_enhe & add-path removed */
862 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
863 stream_put_prefix(s
, p
);
865 size_t p1
= stream_get_endp(s
);
867 /* MPLS removed for now */
869 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
871 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
873 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
874 total_attr_len
+= stream_get_endp(s
) - p1
;
877 /* set the total attribute length correctly */
878 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
879 bgp_packet_set_size(s
);
883 static struct stream
*bmp_withdraw(const struct prefix
*p
,
884 struct prefix_rd
*prd
, afi_t afi
,
888 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
889 bgp_size_t total_attr_len
= 0;
890 bgp_size_t unfeasible_len
;
892 s
= stream_new(BGP_MAX_PACKET_SIZE
);
894 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
897 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
898 stream_put_prefix(s
, p
);
899 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
900 - BGP_UNFEASIBLE_LEN
;
901 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
904 attrlen_pos
= stream_get_endp(s
);
905 /* total attr length = 0 for now. reevaluate later */
907 mp_start
= stream_get_endp(s
);
908 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
910 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
912 /* Set the mp_unreach attr's length */
913 bgp_packet_mpunreach_end(s
, mplen_pos
);
915 /* Set total path attribute length. */
916 total_attr_len
= stream_get_endp(s
) - mp_start
;
917 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
920 bgp_packet_set_size(s
);
924 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
925 const struct prefix
*p
, struct prefix_rd
*prd
,
926 struct attr
*attr
, afi_t afi
, safi_t safi
,
929 struct stream
*hdr
, *msg
;
930 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
931 struct timeval uptime_real
;
933 monotime_to_realtime(&tv
, &uptime_real
);
935 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
937 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
939 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
940 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
941 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
943 stream_putl_at(hdr
, BMP_LENGTH_POS
,
944 stream_get_endp(hdr
) + stream_get_endp(msg
));
947 pullwr_write_stream(bmp
->pullwr
, hdr
);
948 pullwr_write_stream(bmp
->pullwr
, msg
);
953 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
958 if (bmp
->syncafi
== AFI_MAX
) {
959 FOREACH_AFI_SAFI (afi
, safi
) {
960 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
963 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
966 bmp
->syncsafi
= safi
;
968 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
969 bmp
->syncpos
.family
= afi2family(afi
);
970 bmp
->syncrdpos
= NULL
;
971 zlog_info("bmp[%s] %s %s sending table",
973 afi2str(bmp
->syncafi
),
974 safi2str(bmp
->syncsafi
));
975 /* break does not work here, 2 loops... */
978 if (bmp
->syncafi
== AFI_MAX
)
984 safi
= bmp
->syncsafi
;
986 if (!bmp
->targets
->afimon
[afi
][safi
]) {
987 /* shouldn't happen */
988 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
989 bmp
->syncafi
= AFI_MAX
;
990 bmp
->syncsafi
= SAFI_MAX
;
994 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
996 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
997 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
999 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
1000 (safi
== SAFI_MPLS_VPN
)) {
1001 /* initialize syncrdpos to the first
1002 * mid-layer table entry
1004 if (!bmp
->syncrdpos
) {
1005 bmp
->syncrdpos
= bgp_table_top(table
);
1006 if (!bmp
->syncrdpos
)
1010 /* look for a valid mid-layer table */
1012 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
1016 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
1017 } while (bmp
->syncrdpos
);
1019 /* mid-layer table completed */
1020 if (!bmp
->syncrdpos
)
1024 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
1027 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
1029 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
1030 (safi
== SAFI_MPLS_VPN
)) {
1031 /* reset bottom-layer pointer */
1032 memset(&bmp
->syncpos
, 0,
1033 sizeof(bmp
->syncpos
));
1034 bmp
->syncpos
.family
= afi2family(afi
);
1035 /* check whethere there is a valid
1036 * next mid-layer table, otherwise
1037 * declare table completed (eor)
1039 for (bmp
->syncrdpos
= bgp_route_next(
1042 bmp
->syncrdpos
= bgp_route_next(
1044 if (bgp_dest_get_bgp_table_info(
1049 zlog_info("bmp[%s] %s %s table completed (EoR)",
1050 bmp
->remote
, afi2str(afi
),
1052 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1053 bmp_eor(bmp
, afi
, safi
, 0);
1055 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1056 bmp
->syncafi
= AFI_MAX
;
1057 bmp
->syncsafi
= SAFI_MAX
;
1060 bmp
->syncpeerid
= 0;
1061 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1064 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1065 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1066 bpiter
= bpiter
->next
) {
1067 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1069 if (bpiter
->peer
->qobj_node
.nid
1072 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1073 > bpi
->peer
->qobj_node
.nid
)
1078 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1079 for (adjiter
= bn
->adj_in
; adjiter
;
1080 adjiter
= adjiter
->next
) {
1081 if (adjiter
->peer
->qobj_node
.nid
1084 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1085 > adjin
->peer
->qobj_node
.nid
)
1097 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1099 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1100 } else if (adjin
&& bpi
1101 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1103 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1105 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1107 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1110 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1111 struct prefix_rd
*prd
= NULL
;
1112 if (((afi
== AFI_L2VPN
) && (safi
== SAFI_EVPN
)) ||
1113 (safi
== SAFI_MPLS_VPN
))
1114 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1117 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1118 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1120 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1121 safi
, adjin
->uptime
);
1126 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1128 struct bmp_queue_entry
*bqe
;
1130 bqe
= bmp
->queuepos
;
1134 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1137 if (!bqe
->refcount
) {
1138 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1139 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1144 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1146 struct bmp_queue_entry
*bqe
;
1148 struct bgp_dest
*bn
;
1149 bool written
= false;
1151 bqe
= bmp_pull(bmp
);
1155 afi_t afi
= bqe
->afi
;
1156 safi_t safi
= bqe
->safi
;
1158 switch (bmp
->afistate
[afi
][safi
]) {
1159 case BMP_AFI_INACTIVE
:
1160 case BMP_AFI_NEEDSYNC
:
1163 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1164 /* currently syncing but have already passed this
1165 * prefix => send it. */
1168 /* currently syncing & haven't reached this prefix yet
1169 * => it'll be sent as part of the table sync, no need here */
1175 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1177 zlog_info("bmp: skipping queued item for deleted peer");
1180 if (!peer_established(peer
))
1183 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1184 struct prefix_rd
*prd
= NULL
;
1185 if ((bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
) ||
1186 (bqe
->safi
== SAFI_MPLS_VPN
))
1189 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1190 struct bgp_path_info
*bpi
;
1192 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1194 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1196 if (bpi
->peer
== peer
)
1200 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1201 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1202 bpi
? bpi
->uptime
: monotime(NULL
));
1206 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1207 struct bgp_adj_in
*adjin
;
1209 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1210 adjin
= adjin
->next
) {
1211 if (adjin
->peer
== peer
)
1214 bmp_monitor(bmp
, peer
, 0, &bqe
->p
, prd
,
1215 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1216 adjin
? adjin
->uptime
: monotime(NULL
));
1222 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1226 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1228 switch(bmp
->state
) {
1230 bmp_send_peerup(bmp
);
1231 bmp
->state
= BMP_Run
;
1235 if (bmp_wrmirror(bmp
, pullwr
))
1237 if (bmp_wrqueue(bmp
, pullwr
))
1239 if (bmp_wrsync(bmp
, pullwr
))
1245 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1248 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1250 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1251 bmp
->remote
, strerror(errno
));
1257 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1258 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1261 struct bmp_queue_entry
*bqe
, bqeref
;
1264 refcount
= bmp_session_count(&bt
->sessions
);
1268 memset(&bqeref
, 0, sizeof(bqeref
));
1269 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1270 bqeref
.peerid
= peer
->qobj_node
.nid
;
1274 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
) ||
1275 (safi
== SAFI_MPLS_VPN
))
1276 prefix_copy(&bqeref
.rd
,
1277 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1279 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1281 if (bqe
->refcount
>= refcount
)
1282 /* nothing to do here */
1285 bmp_qlist_del(&bt
->updlist
, bqe
);
1287 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1288 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1290 bmp_qhash_add(&bt
->updhash
, bqe
);
1293 bqe
->refcount
= refcount
;
1294 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1296 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1298 bmp
->queuepos
= bqe
;
1301 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1302 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1304 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1305 struct bmp_targets
*bt
;
1308 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1309 char pfxprint
[PREFIX2STR_BUFFER
];
1311 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1312 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1319 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1320 if (!bt
->afimon
[afi
][safi
])
1323 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1325 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1326 pullwr_bump(bmp
->pullwr
);
1332 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1335 stream_putw(s
, type
);
1337 stream_putl(s
, value
);
1341 static void bmp_stats(struct thread
*thread
)
1343 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1346 struct listnode
*node
;
1350 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1353 gettimeofday(&tv
, NULL
);
1355 /* Walk down all peers */
1356 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1357 size_t count
= 0, count_pos
, len
;
1359 if (!peer_established(peer
))
1362 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1363 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1364 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1366 count_pos
= stream_get_endp(s
);
1369 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1370 peer
->stat_pfx_filter
);
1371 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1372 peer
->stat_pfx_aspath_loop
);
1373 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1374 peer
->stat_pfx_originator_loop
);
1375 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1376 peer
->stat_pfx_cluster_loop
);
1377 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1378 peer
->stat_pfx_dup_withdraw
);
1379 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1380 peer
->stat_upd_7606
);
1381 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1382 peer
->stat_pfx_nh_invalid
);
1384 stream_putl_at(s
, count_pos
, count
);
1386 len
= stream_get_endp(s
);
1387 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1389 bmp_send_all(bt
->bmpbgp
, s
);
1393 /* read from the BMP socket to detect session termination */
1394 static void bmp_read(struct thread
*t
)
1396 struct bmp
*bmp
= THREAD_ARG(t
);
1402 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1404 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1405 } else if (n
== 0) {
1406 /* the TCP session was terminated by the far end */
1407 bmp_wrerr(bmp
, NULL
, true);
1409 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1410 /* the TCP session experienced a fatal error, likely a timeout */
1411 bmp_wrerr(bmp
, NULL
, false);
1415 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1418 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1420 union sockunion su
, *sumem
;
1423 struct access_list
*acl
= NULL
;
1424 enum filter_type ret
;
1425 char buf
[SU_ADDRSTRLEN
];
1428 sumem
= sockunion_getpeername(bmp_sock
);
1433 memcpy(&su
, sumem
, sizeof(su
));
1434 sockunion_free(sumem
);
1436 set_nonblocking(bmp_sock
);
1437 set_cloexec(bmp_sock
);
1439 if (!sockunion2hostprefix(&su
, &p
)) {
1447 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1450 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1456 ret
= FILTER_PERMIT
;
1458 ret
= access_list_apply(acl
, &p
);
1461 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1462 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1463 su
.sa
.sa_family
== AF_INET
1464 ? ntohs(su
.sin
.sin_port
)
1465 : ntohs(su
.sin6
.sin6_port
));
1467 if (ret
== FILTER_DENY
) {
1468 bt
->cnt_aclrefused
++;
1469 zlog_info("bmp[%s] connection refused by access-list", buf
);
1475 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1476 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1477 bmp_sock
, safe_strerror(errno
), errno
);
1478 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1479 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1480 bmp_sock
, safe_strerror(errno
), errno
);
1482 zlog_info("bmp[%s] connection established", buf
);
1484 /* Allocate new BMP structure and set up default values. */
1485 bmp
= bmp_new(bt
, bmp_sock
);
1486 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1488 bmp
->state
= BMP_PeerUp
;
1489 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1491 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1492 bmp_send_initiation(bmp
);
1497 /* Accept BMP connection. */
1498 static void bmp_accept(struct thread
*thread
)
1501 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1504 /* We continue hearing BMP socket. */
1505 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1507 memset(&su
, 0, sizeof(union sockunion
));
1509 /* We can handle IPv4 or IPv6 socket. */
1510 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1512 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1515 bmp_open(bl
->targets
, bmp_sock
);
1518 static void bmp_close(struct bmp
*bmp
)
1520 struct bmp_queue_entry
*bqe
;
1521 struct bmp_mirrorq
*bmq
;
1523 THREAD_OFF(bmp
->t_read
);
1526 bmp_active_disconnected(bmp
->active
);
1528 while ((bmq
= bmp_pull_mirror(bmp
)))
1530 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1531 while ((bqe
= bmp_pull(bmp
)))
1533 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1535 THREAD_OFF(bmp
->t_read
);
1536 pullwr_del(bmp
->pullwr
);
1540 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1542 struct bmp_bgp dummy
= { .bgp
= bgp
};
1543 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1546 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1548 struct bmp_bgp
*bmpbgp
;
1550 bmpbgp
= bmp_bgp_find(bgp
);
1554 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1556 bmpbgp
->mirror_qsizelimit
= ~0UL;
1557 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1558 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1563 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1565 struct bmp_targets
*bt
;
1566 struct bmp_listener
*bl
;
1568 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1570 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, bt
) {
1571 frr_each_safe (bmp_listeners
, &bt
->listeners
, bl
)
1572 bmp_listener_put(bl
);
1574 bmp_targets_put(bt
);
1577 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1578 XFREE(MTYPE_BMP
, bmpbgp
);
1581 static int bmp_bgp_del(struct bgp
*bgp
)
1583 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1586 bmp_bgp_put(bmpbgp
);
1590 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1592 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1593 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1596 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1598 struct bmp_bgp_peer
*bbpeer
;
1600 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1604 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1605 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1606 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1611 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1613 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1614 struct bmp_targets dummy
;
1618 dummy
.name
= (char *)name
;
1619 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1622 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1624 struct bmp_targets
*bt
;
1626 bt
= bmp_targets_find1(bgp
, name
);
1630 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1631 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1633 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1634 bmp_session_init(&bt
->sessions
);
1635 bmp_qhash_init(&bt
->updhash
);
1636 bmp_qlist_init(&bt
->updlist
);
1637 bmp_actives_init(&bt
->actives
);
1638 bmp_listeners_init(&bt
->listeners
);
1640 QOBJ_REG(bt
, bmp_targets
);
1641 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1645 static void bmp_targets_put(struct bmp_targets
*bt
)
1648 struct bmp_active
*ba
;
1650 THREAD_OFF(bt
->t_stats
);
1652 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1655 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1660 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1663 bmp_listeners_fini(&bt
->listeners
);
1664 bmp_actives_fini(&bt
->actives
);
1665 bmp_qhash_fini(&bt
->updhash
);
1666 bmp_qlist_fini(&bt
->updlist
);
1668 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1669 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1670 bmp_session_fini(&bt
->sessions
);
1672 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1673 XFREE(MTYPE_BMP_TARGETS
, bt
);
1676 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1677 const union sockunion
*su
,
1680 struct bmp_listener dummy
;
1683 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1686 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1687 const union sockunion
*su
,
1690 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1695 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1701 bmp_listeners_add(&bt
->listeners
, bl
);
1705 static void bmp_listener_start(struct bmp_listener
*bl
)
1709 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1713 sockopt_reuseaddr(sock
);
1714 sockopt_reuseport(sock
);
1715 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1718 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1722 ret
= listen(sock
, 3);
1727 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1733 static void bmp_listener_stop(struct bmp_listener
*bl
)
1735 THREAD_OFF(bl
->t_accept
);
1742 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1743 const char *hostname
, int port
)
1745 struct bmp_active dummy
;
1746 dummy
.hostname
= (char *)hostname
;
1748 return bmp_actives_find(&bt
->actives
, &dummy
);
1751 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1752 const char *hostname
, int port
)
1754 struct bmp_active
*ba
;
1756 ba
= bmp_active_find(bt
, hostname
, port
);
1760 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1762 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1764 ba
->minretry
= BMP_DFLT_MINRETRY
;
1765 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1768 bmp_actives_add(&bt
->actives
, ba
);
1772 static void bmp_active_put(struct bmp_active
*ba
)
1774 THREAD_OFF(ba
->t_timer
);
1775 THREAD_OFF(ba
->t_read
);
1776 THREAD_OFF(ba
->t_write
);
1778 bmp_actives_del(&ba
->targets
->actives
, ba
);
1781 ba
->bmp
->active
= NULL
;
1785 if (ba
->socket
!= -1)
1788 XFREE(MTYPE_TMP
, ba
->ifsrc
);
1789 XFREE(MTYPE_TMP
, ba
->hostname
);
1790 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1793 static void bmp_active_setup(struct bmp_active
*ba
);
1795 static void bmp_active_connect(struct bmp_active
*ba
)
1797 enum connect_result res
;
1798 struct interface
*ifp
;
1799 vrf_id_t vrf_id
= VRF_DEFAULT
;
1802 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1804 if (ba
->targets
&& ba
->targets
->bgp
)
1805 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1807 /* find interface and related */
1808 /* address with same family */
1809 ifp
= if_lookup_by_name(ba
->ifsrc
, vrf_id
);
1811 zlog_warn("bmp[%s]: failed to find interface",
1816 if (bgp_update_address(ifp
, &ba
->addrs
[ba
->addrpos
],
1818 zlog_warn("bmp[%s]: failed to find matching address",
1822 zlog_info("bmp[%s]: selected source address : %pSU",
1823 ba
->ifsrc
, &ba
->addrsrc
);
1826 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1827 if (ba
->socket
< 0) {
1828 zlog_warn("bmp[%s]: failed to create socket",
1833 set_nonblocking(ba
->socket
);
1835 if (!sockunion_is_null(&ba
->addrsrc
)) {
1836 res_bind
= sockunion_bind(ba
->socket
, &ba
->addrsrc
, 0,
1840 "bmp[%s]: no bind currently to source address %pSU:%d",
1841 ba
->hostname
, &ba
->addrsrc
, ba
->port
);
1844 sockunion_init(&ba
->addrsrc
);
1850 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1851 htons(ba
->port
), 0);
1854 zlog_warn("bmp[%s]: failed to connect to %pSU:%d",
1855 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1859 sockunion_init(&ba
->addrsrc
);
1861 case connect_success
:
1862 zlog_info("bmp[%s]: connected to %pSU:%d",
1863 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1866 case connect_in_progress
:
1867 zlog_warn("bmp[%s]: connect in progress %pSU:%d",
1868 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1870 bmp_active_setup(ba
);
1875 /* exhausted all addresses */
1876 ba
->curretry
+= ba
->curretry
/ 2;
1877 bmp_active_setup(ba
);
1880 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1881 int numaddrs
, union sockunion
*addr
)
1883 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1886 if (numaddrs
<= 0) {
1887 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1888 ba
->hostname
, errstr
);
1889 ba
->last_err
= errstr
;
1890 ba
->curretry
+= ba
->curretry
/ 2;
1893 bmp_active_setup(ba
);
1897 if (numaddrs
> (int)array_size(ba
->addrs
))
1898 numaddrs
= array_size(ba
->addrs
);
1901 ba
->addrtotal
= numaddrs
;
1902 for (i
= 0; i
< ba
->addrtotal
; i
++)
1903 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1905 bmp_active_connect(ba
);
1908 static void bmp_active_thread(struct thread
*t
)
1910 struct bmp_active
*ba
= THREAD_ARG(t
);
1915 /* all 3 end up here, though only timer or read+write are active
1917 THREAD_OFF(ba
->t_timer
);
1918 THREAD_OFF(ba
->t_read
);
1919 THREAD_OFF(ba
->t_write
);
1921 ba
->last_err
= NULL
;
1923 if (ba
->socket
== -1) {
1925 if (!ba
->targets
|| !ba
->targets
->bgp
)
1926 vrf_id
= VRF_DEFAULT
;
1928 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1929 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1930 bmp_active_resolved
);
1934 slen
= sizeof(status
);
1935 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1938 if (ret
< 0 || status
!= 0) {
1939 ba
->last_err
= strerror(status
);
1940 zlog_warn("bmp[%s]: failed to connect to %pSU:%d: %s",
1941 ba
->hostname
, &ba
->addrs
[ba
->addrpos
], ba
->port
,
1946 zlog_warn("bmp[%s]: outbound connection to %pSU:%d", ba
->hostname
,
1947 &ba
->addrs
[ba
->addrpos
], ba
->port
);
1949 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1953 ba
->bmp
->active
= ba
;
1955 ba
->curretry
= ba
->minretry
;
1962 bmp_active_connect(ba
);
1965 static void bmp_active_disconnected(struct bmp_active
*ba
)
1968 bmp_active_setup(ba
);
1971 static void bmp_active_setup(struct bmp_active
*ba
)
1973 THREAD_OFF(ba
->t_timer
);
1974 THREAD_OFF(ba
->t_read
);
1975 THREAD_OFF(ba
->t_write
);
1979 if (ba
->resq
.callback
)
1982 if (ba
->curretry
> ba
->maxretry
)
1983 ba
->curretry
= ba
->maxretry
;
1985 if (ba
->socket
== -1)
1986 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1987 ba
->curretry
, &ba
->t_timer
);
1989 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1991 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1996 static struct cmd_node bmp_node
= {
1999 .parent_node
= BGP_NODE
,
2000 .prompt
= "%s(config-bgp-bmp)# "
2003 static void bmp_targets_autocomplete(vector comps
, struct cmd_token
*token
)
2006 struct bmp_targets
*target
;
2007 struct listnode
*node
;
2009 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
2010 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2015 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, target
)
2017 XSTRDUP(MTYPE_COMPLETION
, target
->name
));
2021 static const struct cmd_variable_handler bmp_targets_var_handlers
[] = {
2022 {.tokenname
= "BMPTARGETS", .completions
= bmp_targets_autocomplete
},
2023 {.completions
= NULL
}};
2025 #define BMP_STR "BGP Monitoring Protocol\n"
2027 #ifndef VTYSH_EXTRACT_PL
2028 #include "bgpd/bgp_bmp_clippy.c"
2031 DEFPY_NOSH(bmp_targets_main
,
2033 "bmp targets BMPTARGETS",
2035 "Create BMP target group\n"
2036 "Name of the BMP target group\n")
2038 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2039 struct bmp_targets
*bt
;
2041 bt
= bmp_targets_get(bgp
, bmptargets
);
2043 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
2047 DEFPY(no_bmp_targets_main
,
2049 "no bmp targets BMPTARGETS",
2052 "Delete BMP target group\n"
2053 "Name of the BMP target group\n")
2055 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2056 struct bmp_targets
*bt
;
2058 bt
= bmp_targets_find1(bgp
, bmptargets
);
2060 vty_out(vty
, "%% BMP target group not found\n");
2063 bmp_targets_put(bt
);
2067 DEFPY(bmp_listener_main
,
2069 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2071 "Listen for inbound BMP connections\n"
2072 "IPv6 address to listen on\n"
2073 "IPv4 address to listen on\n"
2075 "TCP Port number\n")
2077 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2078 struct bmp_listener
*bl
;
2080 bl
= bmp_listener_get(bt
, listener
, port
);
2082 bmp_listener_start(bl
);
2087 DEFPY(no_bmp_listener_main
,
2088 no_bmp_listener_cmd
,
2089 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2092 "Create BMP listener\n"
2093 "IPv6 address to listen on\n"
2094 "IPv4 address to listen on\n"
2096 "TCP Port number\n")
2098 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2099 struct bmp_listener
*bl
;
2101 bl
= bmp_listener_find(bt
, listener
, port
);
2103 vty_out(vty
, "%% BMP listener not found\n");
2106 bmp_listener_stop(bl
);
2107 bmp_listener_put(bl
);
2113 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
2116 "Actively establish connection to monitoring station\n"
2117 "Monitoring station hostname or address\n"
2120 "Minimum connection retry interval\n"
2121 "Minimum connection retry interval (milliseconds)\n"
2122 "Maximum connection retry interval\n"
2123 "Maximum connection retry interval (milliseconds)\n"
2124 "Source interface to use\n"
2125 "Define an interface\n")
2127 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2128 struct bmp_active
*ba
;
2131 ba
= bmp_active_find(bt
, hostname
, port
);
2133 vty_out(vty
, "%% No such active connection found\n");
2136 /* connection deletion need same hostname port and interface */
2137 if (ba
->ifsrc
|| srcif
)
2138 if ((!ba
->ifsrc
) || (!srcif
) ||
2139 !strcmp(ba
->ifsrc
, srcif
)) {
2141 "%% No such active connection found\n");
2148 ba
= bmp_active_get(bt
, hostname
, port
);
2150 ba
->ifsrc
= XSTRDUP(MTYPE_TMP
, srcif
);
2152 ba
->minretry
= min_retry
;
2154 ba
->maxretry
= max_retry
;
2155 ba
->curretry
= ba
->minretry
;
2156 bmp_active_setup(ba
);
2163 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2167 "Access list to restrict BMP sessions\n"
2168 "Access list name\n")
2170 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2175 if (!strcmp(af
, "ipv6"))
2176 what
= &bt
->acl6_name
;
2178 what
= &bt
->acl_name
;
2180 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2182 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2187 DEFPY(bmp_stats_cfg
,
2189 "[no] bmp stats [interval (100-86400000)]",
2192 "Send BMP statistics messages\n"
2193 "Specify BMP stats interval\n"
2194 "Interval (milliseconds) to send BMP Stats in\n")
2196 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2198 THREAD_OFF(bt
->t_stats
);
2201 else if (interval_str
)
2202 bt
->stat_msec
= interval
;
2204 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2207 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2212 DEFPY(bmp_monitor_cfg
,
2214 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
2217 "Send BMP route monitoring messages\n"
2225 "Send state before policy and filter processing\n"
2226 "Send state with policy and filters applied\n")
2233 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2236 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2237 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2239 if (policy
[1] == 'r')
2240 flag
= BMP_MON_PREPOLICY
;
2242 flag
= BMP_MON_POSTPOLICY
;
2244 prev
= bt
->afimon
[afi
][safi
];
2246 bt
->afimon
[afi
][safi
] &= ~flag
;
2248 bt
->afimon
[afi
][safi
] |= flag
;
2250 if (prev
== bt
->afimon
[afi
][safi
])
2253 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2254 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2255 bmp
->syncafi
= AFI_MAX
;
2256 bmp
->syncsafi
= SAFI_MAX
;
2259 if (!bt
->afimon
[afi
][safi
]) {
2260 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2264 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2270 DEFPY(bmp_mirror_cfg
,
2275 "Send BMP route mirroring messages\n")
2277 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2280 if (bt
->mirror
== !no
)
2287 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2288 struct bmp_mirrorq
*bmq
;
2290 while ((bmq
= bmp_pull_mirror(bmp
)))
2292 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2297 DEFPY(bmp_mirror_limit_cfg
,
2298 bmp_mirror_limit_cmd
,
2299 "bmp mirror buffer-limit (0-4294967294)",
2301 "Route Mirroring settings\n"
2302 "Configure maximum memory used for buffered mirroring messages\n"
2305 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2306 struct bmp_bgp
*bmpbgp
;
2308 bmpbgp
= bmp_bgp_get(bgp
);
2309 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2314 DEFPY(no_bmp_mirror_limit_cfg
,
2315 no_bmp_mirror_limit_cmd
,
2316 "no bmp mirror buffer-limit [(0-4294967294)]",
2319 "Route Mirroring settings\n"
2320 "Configure maximum memory used for buffered mirroring messages\n"
2323 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2324 struct bmp_bgp
*bmpbgp
;
2326 bmpbgp
= bmp_bgp_get(bgp
);
2327 bmpbgp
->mirror_qsizelimit
= ~0UL;
2339 struct bmp_bgp
*bmpbgp
;
2340 struct bmp_targets
*bt
;
2341 struct bmp_listener
*bl
;
2342 struct bmp_active
*ba
;
2345 char uptime
[BGP_UPTIME_LEN
];
2348 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2349 vty_out(vty
, "BMP state for BGP %s:\n\n",
2350 bmpbgp
->bgp
->name_pretty
);
2351 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2352 bmpbgp
->mirror_qsize
,
2353 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2354 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2355 bmpbgp
->mirror_qsizemax
);
2356 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2357 vty_out(vty
, " %9zu bytes buffer size limit\n",
2358 bmpbgp
->mirror_qsizelimit
);
2361 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2362 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2363 vty_out(vty
, " Route Mirroring %sabled\n",
2364 bt
->mirror
? "en" : "dis");
2369 FOREACH_AFI_SAFI (afi
, safi
) {
2370 const char *str
= NULL
;
2372 switch (bt
->afimon
[afi
][safi
]) {
2373 case BMP_MON_PREPOLICY
:
2376 case BMP_MON_POSTPOLICY
:
2377 str
= "post-policy";
2379 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2380 str
= "pre-policy and post-policy";
2385 vty_out(vty
, " Route Monitoring %s %s %s\n",
2386 afi2str(afi
), safi2str(safi
), str
);
2389 vty_out(vty
, " Listeners:\n");
2390 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2391 vty_out(vty
, " %pSU:%d\n", &bl
->addr
,
2394 vty_out(vty
, "\n Outbound connections:\n");
2395 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2396 ttable_add_row(tt
, "remote|state||timer|local");
2397 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2398 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2399 const char *state_str
= "?";
2402 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2403 uptime
, sizeof(uptime
),
2406 "%s:%d|Up|%s|%s|%pSU",
2407 ba
->hostname
, ba
->port
,
2408 ba
->bmp
->remote
, uptime
,
2416 long trem
= thread_timer_remain_second(
2419 peer_uptime(monotime(NULL
) - trem
,
2420 uptime
, sizeof(uptime
),
2422 state_str
= "RetryWait";
2423 } else if (ba
->t_read
) {
2424 state_str
= "Connecting";
2425 } else if (ba
->resq
.callback
) {
2426 state_str
= "Resolving";
2429 ttable_add_row(tt
, "%s:%d|%s|%s|%s|%pSU",
2430 ba
->hostname
, ba
->port
,
2432 ba
->last_err
? ba
->last_err
: "",
2433 uptime
, &ba
->addrsrc
);
2436 out
= ttable_dump(tt
, "\n");
2437 vty_out(vty
, "%s", out
);
2438 XFREE(MTYPE_TMP
, out
);
2441 vty_out(vty
, "\n %zu connected clients:\n",
2442 bmp_session_count(&bt
->sessions
));
2443 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2444 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2445 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2447 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2451 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2453 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2454 sizeof(uptime
), false, NULL
);
2456 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2457 bmp
->remote
, uptime
,
2460 bmp
->cnt_mirror_overruns
,
2463 out
= ttable_dump(tt
, "\n");
2464 vty_out(vty
, "%s", out
);
2465 XFREE(MTYPE_TMP
, out
);
2474 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2476 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2477 struct bmp_targets
*bt
;
2478 struct bmp_listener
*bl
;
2479 struct bmp_active
*ba
;
2486 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2487 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2488 bmpbgp
->mirror_qsizelimit
);
2490 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2491 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2494 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2496 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2499 vty_out(vty
, " bmp stats interval %d\n",
2503 vty_out(vty
, " bmp mirror\n");
2505 FOREACH_AFI_SAFI (afi
, safi
) {
2506 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2508 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2509 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2510 afi_str
, safi2str(safi
));
2511 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2512 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2513 afi_str
, safi2str(safi
));
2515 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2516 vty_out(vty
, " \n bmp listener %pSU port %d\n",
2517 &bl
->addr
, bl
->port
);
2519 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2520 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u",
2521 ba
->hostname
, ba
->port
,
2522 ba
->minretry
, ba
->maxretry
);
2525 vty_out(vty
, " source-interface %s\n", ba
->ifsrc
);
2529 vty_out(vty
, " exit\n");
2535 static int bgp_bmp_init(struct thread_master
*tm
)
2537 install_node(&bmp_node
);
2538 install_default(BMP_NODE
);
2540 cmd_variable_handler_register(bmp_targets_var_handlers
);
2542 install_element(BGP_NODE
, &bmp_targets_cmd
);
2543 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2545 install_element(BMP_NODE
, &bmp_listener_cmd
);
2546 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2547 install_element(BMP_NODE
, &bmp_connect_cmd
);
2548 install_element(BMP_NODE
, &bmp_acl_cmd
);
2549 install_element(BMP_NODE
, &bmp_stats_cmd
);
2550 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2551 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2553 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2554 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2556 install_element(VIEW_NODE
, &show_bmp_cmd
);
2562 static int bgp_bmp_module_init(void)
2564 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2565 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2566 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2567 hook_register(peer_backward_transition
, bmp_peer_backward
);
2568 hook_register(bgp_process
, bmp_process
);
2569 hook_register(bgp_inst_config_write
, bmp_config_write
);
2570 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2571 hook_register(frr_late_init
, bgp_bmp_init
);
2575 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2576 .description
= "bgpd BMP module",
2577 .init
= bgp_bmp_module_init
,