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
];
995 struct bgp_dest
*bn
= NULL
;
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
);
1124 bgp_dest_unlock_node(bn
);
1129 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1131 struct bmp_queue_entry
*bqe
;
1133 bqe
= bmp
->queuepos
;
1137 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1140 if (!bqe
->refcount
) {
1141 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1142 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1147 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1149 struct bmp_queue_entry
*bqe
;
1151 struct bgp_dest
*bn
= NULL
;
1152 bool written
= false;
1154 bqe
= bmp_pull(bmp
);
1158 afi_t afi
= bqe
->afi
;
1159 safi_t safi
= bqe
->safi
;
1161 switch (bmp
->afistate
[afi
][safi
]) {
1162 case BMP_AFI_INACTIVE
:
1163 case BMP_AFI_NEEDSYNC
:
1166 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1167 /* currently syncing but have already passed this
1168 * prefix => send it. */
1171 /* currently syncing & haven't reached this prefix yet
1172 * => it'll be sent as part of the table sync, no need here */
1178 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1180 zlog_info("bmp: skipping queued item for deleted peer");
1183 if (!peer_established(peer
))
1186 bool is_vpn
= (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
) ||
1187 (bqe
->safi
== SAFI_MPLS_VPN
);
1189 struct prefix_rd
*prd
= is_vpn
? &bqe
->rd
: NULL
;
1190 bn
= bgp_afi_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], afi
, safi
,
1194 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1195 struct bgp_path_info
*bpi
;
1197 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1199 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1201 if (bpi
->peer
== peer
)
1205 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1206 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1207 bpi
? bpi
->uptime
: monotime(NULL
));
1211 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1212 struct bgp_adj_in
*adjin
;
1214 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1215 adjin
= adjin
->next
) {
1216 if (adjin
->peer
== peer
)
1219 bmp_monitor(bmp
, peer
, 0, &bqe
->p
, prd
,
1220 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1221 adjin
? adjin
->uptime
: monotime(NULL
));
1227 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1230 bgp_dest_unlock_node(bn
);
1235 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1237 switch(bmp
->state
) {
1239 bmp_send_peerup(bmp
);
1240 bmp
->state
= BMP_Run
;
1244 if (bmp_wrmirror(bmp
, pullwr
))
1246 if (bmp_wrqueue(bmp
, pullwr
))
1248 if (bmp_wrsync(bmp
, pullwr
))
1254 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1257 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1259 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1260 bmp
->remote
, strerror(errno
));
1266 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1267 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1270 struct bmp_queue_entry
*bqe
, bqeref
;
1273 refcount
= bmp_session_count(&bt
->sessions
);
1277 memset(&bqeref
, 0, sizeof(bqeref
));
1278 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1279 bqeref
.peerid
= peer
->qobj_node
.nid
;
1283 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
) ||
1284 (safi
== SAFI_MPLS_VPN
))
1285 prefix_copy(&bqeref
.rd
,
1286 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1288 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1290 if (bqe
->refcount
>= refcount
)
1291 /* nothing to do here */
1294 bmp_qlist_del(&bt
->updlist
, bqe
);
1296 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1297 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1299 bmp_qhash_add(&bt
->updhash
, bqe
);
1302 bqe
->refcount
= refcount
;
1303 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1305 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1307 bmp
->queuepos
= bqe
;
1310 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1311 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1313 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1314 struct bmp_targets
*bt
;
1317 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1318 char pfxprint
[PREFIX2STR_BUFFER
];
1320 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1321 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1328 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1329 if (!bt
->afimon
[afi
][safi
])
1332 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1334 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1335 pullwr_bump(bmp
->pullwr
);
1341 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1344 stream_putw(s
, type
);
1346 stream_putl(s
, value
);
1350 static void bmp_stats(struct thread
*thread
)
1352 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1355 struct listnode
*node
;
1359 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1362 gettimeofday(&tv
, NULL
);
1364 /* Walk down all peers */
1365 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1366 size_t count
= 0, count_pos
, len
;
1368 if (!peer_established(peer
))
1371 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1372 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1373 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1375 count_pos
= stream_get_endp(s
);
1378 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1379 peer
->stat_pfx_filter
);
1380 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1381 peer
->stat_pfx_aspath_loop
);
1382 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1383 peer
->stat_pfx_originator_loop
);
1384 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1385 peer
->stat_pfx_cluster_loop
);
1386 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1387 peer
->stat_pfx_dup_withdraw
);
1388 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1389 peer
->stat_upd_7606
);
1390 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1391 peer
->stat_pfx_nh_invalid
);
1393 stream_putl_at(s
, count_pos
, count
);
1395 len
= stream_get_endp(s
);
1396 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1398 bmp_send_all(bt
->bmpbgp
, s
);
1402 /* read from the BMP socket to detect session termination */
1403 static void bmp_read(struct thread
*t
)
1405 struct bmp
*bmp
= THREAD_ARG(t
);
1411 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1413 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1414 } else if (n
== 0) {
1415 /* the TCP session was terminated by the far end */
1416 bmp_wrerr(bmp
, NULL
, true);
1418 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1419 /* the TCP session experienced a fatal error, likely a timeout */
1420 bmp_wrerr(bmp
, NULL
, false);
1424 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1427 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1429 union sockunion su
, *sumem
;
1432 struct access_list
*acl
= NULL
;
1433 enum filter_type ret
;
1434 char buf
[SU_ADDRSTRLEN
];
1437 sumem
= sockunion_getpeername(bmp_sock
);
1442 memcpy(&su
, sumem
, sizeof(su
));
1443 sockunion_free(sumem
);
1445 set_nonblocking(bmp_sock
);
1446 set_cloexec(bmp_sock
);
1448 if (!sockunion2hostprefix(&su
, &p
)) {
1456 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1459 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1465 ret
= FILTER_PERMIT
;
1467 ret
= access_list_apply(acl
, &p
);
1470 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1471 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1472 su
.sa
.sa_family
== AF_INET
1473 ? ntohs(su
.sin
.sin_port
)
1474 : ntohs(su
.sin6
.sin6_port
));
1476 if (ret
== FILTER_DENY
) {
1477 bt
->cnt_aclrefused
++;
1478 zlog_info("bmp[%s] connection refused by access-list", buf
);
1484 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1485 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1486 bmp_sock
, safe_strerror(errno
), errno
);
1487 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1488 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1489 bmp_sock
, safe_strerror(errno
), errno
);
1491 zlog_info("bmp[%s] connection established", buf
);
1493 /* Allocate new BMP structure and set up default values. */
1494 bmp
= bmp_new(bt
, bmp_sock
);
1495 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1497 bmp
->state
= BMP_PeerUp
;
1498 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1500 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1501 bmp_send_initiation(bmp
);
1506 /* Accept BMP connection. */
1507 static void bmp_accept(struct thread
*thread
)
1510 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1513 /* We continue hearing BMP socket. */
1514 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1516 memset(&su
, 0, sizeof(union sockunion
));
1518 /* We can handle IPv4 or IPv6 socket. */
1519 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1521 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1524 bmp_open(bl
->targets
, bmp_sock
);
1527 static void bmp_close(struct bmp
*bmp
)
1529 struct bmp_queue_entry
*bqe
;
1530 struct bmp_mirrorq
*bmq
;
1532 THREAD_OFF(bmp
->t_read
);
1535 bmp_active_disconnected(bmp
->active
);
1537 while ((bmq
= bmp_pull_mirror(bmp
)))
1539 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1540 while ((bqe
= bmp_pull(bmp
)))
1542 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1544 THREAD_OFF(bmp
->t_read
);
1545 pullwr_del(bmp
->pullwr
);
1549 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1551 struct bmp_bgp dummy
= { .bgp
= bgp
};
1552 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1555 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1557 struct bmp_bgp
*bmpbgp
;
1559 bmpbgp
= bmp_bgp_find(bgp
);
1563 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1565 bmpbgp
->mirror_qsizelimit
= ~0UL;
1566 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1567 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1572 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1574 struct bmp_targets
*bt
;
1575 struct bmp_listener
*bl
;
1577 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1579 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, bt
) {
1580 frr_each_safe (bmp_listeners
, &bt
->listeners
, bl
)
1581 bmp_listener_put(bl
);
1583 bmp_targets_put(bt
);
1586 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1587 XFREE(MTYPE_BMP
, bmpbgp
);
1590 static int bmp_bgp_del(struct bgp
*bgp
)
1592 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1595 bmp_bgp_put(bmpbgp
);
1599 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1601 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1602 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1605 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1607 struct bmp_bgp_peer
*bbpeer
;
1609 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1613 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1614 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1615 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1620 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1622 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1623 struct bmp_targets dummy
;
1627 dummy
.name
= (char *)name
;
1628 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1631 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1633 struct bmp_targets
*bt
;
1635 bt
= bmp_targets_find1(bgp
, name
);
1639 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1640 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1642 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1643 bmp_session_init(&bt
->sessions
);
1644 bmp_qhash_init(&bt
->updhash
);
1645 bmp_qlist_init(&bt
->updlist
);
1646 bmp_actives_init(&bt
->actives
);
1647 bmp_listeners_init(&bt
->listeners
);
1649 QOBJ_REG(bt
, bmp_targets
);
1650 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1654 static void bmp_targets_put(struct bmp_targets
*bt
)
1657 struct bmp_active
*ba
;
1659 THREAD_OFF(bt
->t_stats
);
1661 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1664 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1669 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1672 bmp_listeners_fini(&bt
->listeners
);
1673 bmp_actives_fini(&bt
->actives
);
1674 bmp_qhash_fini(&bt
->updhash
);
1675 bmp_qlist_fini(&bt
->updlist
);
1677 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1678 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1679 bmp_session_fini(&bt
->sessions
);
1681 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1682 XFREE(MTYPE_BMP_TARGETS
, bt
);
1685 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1686 const union sockunion
*su
,
1689 struct bmp_listener dummy
;
1692 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1695 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1696 const union sockunion
*su
,
1699 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1704 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1710 bmp_listeners_add(&bt
->listeners
, bl
);
1714 static void bmp_listener_start(struct bmp_listener
*bl
)
1718 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1722 sockopt_reuseaddr(sock
);
1723 sockopt_reuseport(sock
);
1724 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1727 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1731 ret
= listen(sock
, 3);
1736 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1742 static void bmp_listener_stop(struct bmp_listener
*bl
)
1744 THREAD_OFF(bl
->t_accept
);
1751 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1752 const char *hostname
, int port
)
1754 struct bmp_active dummy
;
1755 dummy
.hostname
= (char *)hostname
;
1757 return bmp_actives_find(&bt
->actives
, &dummy
);
1760 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1761 const char *hostname
, int port
)
1763 struct bmp_active
*ba
;
1765 ba
= bmp_active_find(bt
, hostname
, port
);
1769 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1771 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1773 ba
->minretry
= BMP_DFLT_MINRETRY
;
1774 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1777 bmp_actives_add(&bt
->actives
, ba
);
1781 static void bmp_active_put(struct bmp_active
*ba
)
1783 THREAD_OFF(ba
->t_timer
);
1784 THREAD_OFF(ba
->t_read
);
1785 THREAD_OFF(ba
->t_write
);
1787 bmp_actives_del(&ba
->targets
->actives
, ba
);
1790 ba
->bmp
->active
= NULL
;
1794 if (ba
->socket
!= -1)
1797 XFREE(MTYPE_TMP
, ba
->ifsrc
);
1798 XFREE(MTYPE_TMP
, ba
->hostname
);
1799 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1802 static void bmp_active_setup(struct bmp_active
*ba
);
1804 static void bmp_active_connect(struct bmp_active
*ba
)
1806 enum connect_result res
;
1807 struct interface
*ifp
;
1808 vrf_id_t vrf_id
= VRF_DEFAULT
;
1811 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1813 if (ba
->targets
&& ba
->targets
->bgp
)
1814 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1816 /* find interface and related */
1817 /* address with same family */
1818 ifp
= if_lookup_by_name(ba
->ifsrc
, vrf_id
);
1820 zlog_warn("bmp[%s]: failed to find interface",
1825 if (bgp_update_address(ifp
, &ba
->addrs
[ba
->addrpos
],
1827 zlog_warn("bmp[%s]: failed to find matching address",
1831 zlog_info("bmp[%s]: selected source address : %pSU",
1832 ba
->ifsrc
, &ba
->addrsrc
);
1835 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1836 if (ba
->socket
< 0) {
1837 zlog_warn("bmp[%s]: failed to create socket",
1842 set_nonblocking(ba
->socket
);
1844 if (!sockunion_is_null(&ba
->addrsrc
)) {
1845 res_bind
= sockunion_bind(ba
->socket
, &ba
->addrsrc
, 0,
1849 "bmp[%s]: no bind currently to source address %pSU:%d",
1850 ba
->hostname
, &ba
->addrsrc
, ba
->port
);
1853 sockunion_init(&ba
->addrsrc
);
1859 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1860 htons(ba
->port
), 0);
1863 zlog_warn("bmp[%s]: failed to connect to %pSU:%d",
1864 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1868 sockunion_init(&ba
->addrsrc
);
1870 case connect_success
:
1871 zlog_info("bmp[%s]: connected to %pSU:%d",
1872 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1875 case connect_in_progress
:
1876 zlog_warn("bmp[%s]: connect in progress %pSU:%d",
1877 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1879 bmp_active_setup(ba
);
1884 /* exhausted all addresses */
1885 ba
->curretry
+= ba
->curretry
/ 2;
1886 bmp_active_setup(ba
);
1889 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1890 int numaddrs
, union sockunion
*addr
)
1892 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1895 if (numaddrs
<= 0) {
1896 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1897 ba
->hostname
, errstr
);
1898 ba
->last_err
= errstr
;
1899 ba
->curretry
+= ba
->curretry
/ 2;
1902 bmp_active_setup(ba
);
1906 if (numaddrs
> (int)array_size(ba
->addrs
))
1907 numaddrs
= array_size(ba
->addrs
);
1910 ba
->addrtotal
= numaddrs
;
1911 for (i
= 0; i
< ba
->addrtotal
; i
++)
1912 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1914 bmp_active_connect(ba
);
1917 static void bmp_active_thread(struct thread
*t
)
1919 struct bmp_active
*ba
= THREAD_ARG(t
);
1924 /* all 3 end up here, though only timer or read+write are active
1926 THREAD_OFF(ba
->t_timer
);
1927 THREAD_OFF(ba
->t_read
);
1928 THREAD_OFF(ba
->t_write
);
1930 ba
->last_err
= NULL
;
1932 if (ba
->socket
== -1) {
1934 if (!ba
->targets
|| !ba
->targets
->bgp
)
1935 vrf_id
= VRF_DEFAULT
;
1937 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1938 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1939 bmp_active_resolved
);
1943 slen
= sizeof(status
);
1944 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1947 if (ret
< 0 || status
!= 0) {
1948 ba
->last_err
= strerror(status
);
1949 zlog_warn("bmp[%s]: failed to connect to %pSU:%d: %s",
1950 ba
->hostname
, &ba
->addrs
[ba
->addrpos
], ba
->port
,
1955 zlog_warn("bmp[%s]: outbound connection to %pSU:%d", ba
->hostname
,
1956 &ba
->addrs
[ba
->addrpos
], ba
->port
);
1958 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1962 ba
->bmp
->active
= ba
;
1964 ba
->curretry
= ba
->minretry
;
1971 bmp_active_connect(ba
);
1974 static void bmp_active_disconnected(struct bmp_active
*ba
)
1977 bmp_active_setup(ba
);
1980 static void bmp_active_setup(struct bmp_active
*ba
)
1982 THREAD_OFF(ba
->t_timer
);
1983 THREAD_OFF(ba
->t_read
);
1984 THREAD_OFF(ba
->t_write
);
1988 if (ba
->resq
.callback
)
1991 if (ba
->curretry
> ba
->maxretry
)
1992 ba
->curretry
= ba
->maxretry
;
1994 if (ba
->socket
== -1)
1995 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1996 ba
->curretry
, &ba
->t_timer
);
1998 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
2000 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
2005 static struct cmd_node bmp_node
= {
2008 .parent_node
= BGP_NODE
,
2009 .prompt
= "%s(config-bgp-bmp)# "
2012 static void bmp_targets_autocomplete(vector comps
, struct cmd_token
*token
)
2015 struct bmp_targets
*target
;
2016 struct listnode
*node
;
2018 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
2019 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2024 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, target
)
2026 XSTRDUP(MTYPE_COMPLETION
, target
->name
));
2030 static const struct cmd_variable_handler bmp_targets_var_handlers
[] = {
2031 {.tokenname
= "BMPTARGETS", .completions
= bmp_targets_autocomplete
},
2032 {.completions
= NULL
}};
2034 #define BMP_STR "BGP Monitoring Protocol\n"
2036 #ifndef VTYSH_EXTRACT_PL
2037 #include "bgpd/bgp_bmp_clippy.c"
2040 DEFPY_NOSH(bmp_targets_main
,
2042 "bmp targets BMPTARGETS",
2044 "Create BMP target group\n"
2045 "Name of the BMP target group\n")
2047 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2048 struct bmp_targets
*bt
;
2050 bt
= bmp_targets_get(bgp
, bmptargets
);
2052 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
2056 DEFPY(no_bmp_targets_main
,
2058 "no bmp targets BMPTARGETS",
2061 "Delete BMP target group\n"
2062 "Name of the BMP target group\n")
2064 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2065 struct bmp_targets
*bt
;
2067 bt
= bmp_targets_find1(bgp
, bmptargets
);
2069 vty_out(vty
, "%% BMP target group not found\n");
2072 bmp_targets_put(bt
);
2076 DEFPY(bmp_listener_main
,
2078 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2080 "Listen for inbound BMP connections\n"
2081 "IPv6 address to listen on\n"
2082 "IPv4 address to listen on\n"
2084 "TCP Port number\n")
2086 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2087 struct bmp_listener
*bl
;
2089 bl
= bmp_listener_get(bt
, listener
, port
);
2091 bmp_listener_start(bl
);
2096 DEFPY(no_bmp_listener_main
,
2097 no_bmp_listener_cmd
,
2098 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2101 "Create BMP listener\n"
2102 "IPv6 address to listen on\n"
2103 "IPv4 address to listen on\n"
2105 "TCP Port number\n")
2107 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2108 struct bmp_listener
*bl
;
2110 bl
= bmp_listener_find(bt
, listener
, port
);
2112 vty_out(vty
, "%% BMP listener not found\n");
2115 bmp_listener_stop(bl
);
2116 bmp_listener_put(bl
);
2122 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
2125 "Actively establish connection to monitoring station\n"
2126 "Monitoring station hostname or address\n"
2129 "Minimum connection retry interval\n"
2130 "Minimum connection retry interval (milliseconds)\n"
2131 "Maximum connection retry interval\n"
2132 "Maximum connection retry interval (milliseconds)\n"
2133 "Source interface to use\n"
2134 "Define an interface\n")
2136 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2137 struct bmp_active
*ba
;
2140 ba
= bmp_active_find(bt
, hostname
, port
);
2142 vty_out(vty
, "%% No such active connection found\n");
2145 /* connection deletion need same hostname port and interface */
2146 if (ba
->ifsrc
|| srcif
)
2147 if ((!ba
->ifsrc
) || (!srcif
) ||
2148 !strcmp(ba
->ifsrc
, srcif
)) {
2150 "%% No such active connection found\n");
2157 ba
= bmp_active_get(bt
, hostname
, port
);
2159 ba
->ifsrc
= XSTRDUP(MTYPE_TMP
, srcif
);
2161 ba
->minretry
= min_retry
;
2163 ba
->maxretry
= max_retry
;
2164 ba
->curretry
= ba
->minretry
;
2165 bmp_active_setup(ba
);
2172 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2176 "Access list to restrict BMP sessions\n"
2177 "Access list name\n")
2179 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2184 if (!strcmp(af
, "ipv6"))
2185 what
= &bt
->acl6_name
;
2187 what
= &bt
->acl_name
;
2189 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2191 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2196 DEFPY(bmp_stats_cfg
,
2198 "[no] bmp stats [interval (100-86400000)]",
2201 "Send BMP statistics messages\n"
2202 "Specify BMP stats interval\n"
2203 "Interval (milliseconds) to send BMP Stats in\n")
2205 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2207 THREAD_OFF(bt
->t_stats
);
2210 else if (interval_str
)
2211 bt
->stat_msec
= interval
;
2213 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2216 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2221 DEFPY(bmp_monitor_cfg
,
2223 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
2226 "Send BMP route monitoring messages\n"
2234 "Send state before policy and filter processing\n"
2235 "Send state with policy and filters applied\n")
2242 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2245 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2246 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2248 if (policy
[1] == 'r')
2249 flag
= BMP_MON_PREPOLICY
;
2251 flag
= BMP_MON_POSTPOLICY
;
2253 prev
= bt
->afimon
[afi
][safi
];
2255 bt
->afimon
[afi
][safi
] &= ~flag
;
2257 bt
->afimon
[afi
][safi
] |= flag
;
2259 if (prev
== bt
->afimon
[afi
][safi
])
2262 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2263 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2264 bmp
->syncafi
= AFI_MAX
;
2265 bmp
->syncsafi
= SAFI_MAX
;
2268 if (!bt
->afimon
[afi
][safi
]) {
2269 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2273 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2279 DEFPY(bmp_mirror_cfg
,
2284 "Send BMP route mirroring messages\n")
2286 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2289 if (bt
->mirror
== !no
)
2296 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2297 struct bmp_mirrorq
*bmq
;
2299 while ((bmq
= bmp_pull_mirror(bmp
)))
2301 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2306 DEFPY(bmp_mirror_limit_cfg
,
2307 bmp_mirror_limit_cmd
,
2308 "bmp mirror buffer-limit (0-4294967294)",
2310 "Route Mirroring settings\n"
2311 "Configure maximum memory used for buffered mirroring messages\n"
2314 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2315 struct bmp_bgp
*bmpbgp
;
2317 bmpbgp
= bmp_bgp_get(bgp
);
2318 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2323 DEFPY(no_bmp_mirror_limit_cfg
,
2324 no_bmp_mirror_limit_cmd
,
2325 "no bmp mirror buffer-limit [(0-4294967294)]",
2328 "Route Mirroring settings\n"
2329 "Configure maximum memory used for buffered mirroring messages\n"
2332 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2333 struct bmp_bgp
*bmpbgp
;
2335 bmpbgp
= bmp_bgp_get(bgp
);
2336 bmpbgp
->mirror_qsizelimit
= ~0UL;
2348 struct bmp_bgp
*bmpbgp
;
2349 struct bmp_targets
*bt
;
2350 struct bmp_listener
*bl
;
2351 struct bmp_active
*ba
;
2354 char uptime
[BGP_UPTIME_LEN
];
2357 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2358 vty_out(vty
, "BMP state for BGP %s:\n\n",
2359 bmpbgp
->bgp
->name_pretty
);
2360 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2361 bmpbgp
->mirror_qsize
,
2362 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2363 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2364 bmpbgp
->mirror_qsizemax
);
2365 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2366 vty_out(vty
, " %9zu bytes buffer size limit\n",
2367 bmpbgp
->mirror_qsizelimit
);
2370 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2371 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2372 vty_out(vty
, " Route Mirroring %sabled\n",
2373 bt
->mirror
? "en" : "dis");
2378 FOREACH_AFI_SAFI (afi
, safi
) {
2379 const char *str
= NULL
;
2381 switch (bt
->afimon
[afi
][safi
]) {
2382 case BMP_MON_PREPOLICY
:
2385 case BMP_MON_POSTPOLICY
:
2386 str
= "post-policy";
2388 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2389 str
= "pre-policy and post-policy";
2394 vty_out(vty
, " Route Monitoring %s %s %s\n",
2395 afi2str(afi
), safi2str(safi
), str
);
2398 vty_out(vty
, " Listeners:\n");
2399 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2400 vty_out(vty
, " %pSU:%d\n", &bl
->addr
,
2403 vty_out(vty
, "\n Outbound connections:\n");
2404 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2405 ttable_add_row(tt
, "remote|state||timer|local");
2406 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2407 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2408 const char *state_str
= "?";
2411 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2412 uptime
, sizeof(uptime
),
2415 "%s:%d|Up|%s|%s|%pSU",
2416 ba
->hostname
, ba
->port
,
2417 ba
->bmp
->remote
, uptime
,
2425 long trem
= thread_timer_remain_second(
2428 peer_uptime(monotime(NULL
) - trem
,
2429 uptime
, sizeof(uptime
),
2431 state_str
= "RetryWait";
2432 } else if (ba
->t_read
) {
2433 state_str
= "Connecting";
2434 } else if (ba
->resq
.callback
) {
2435 state_str
= "Resolving";
2438 ttable_add_row(tt
, "%s:%d|%s|%s|%s|%pSU",
2439 ba
->hostname
, ba
->port
,
2441 ba
->last_err
? ba
->last_err
: "",
2442 uptime
, &ba
->addrsrc
);
2445 out
= ttable_dump(tt
, "\n");
2446 vty_out(vty
, "%s", out
);
2447 XFREE(MTYPE_TMP
, out
);
2450 vty_out(vty
, "\n %zu connected clients:\n",
2451 bmp_session_count(&bt
->sessions
));
2452 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2453 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2454 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2456 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2460 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2462 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2463 sizeof(uptime
), false, NULL
);
2465 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2466 bmp
->remote
, uptime
,
2469 bmp
->cnt_mirror_overruns
,
2472 out
= ttable_dump(tt
, "\n");
2473 vty_out(vty
, "%s", out
);
2474 XFREE(MTYPE_TMP
, out
);
2483 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2485 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2486 struct bmp_targets
*bt
;
2487 struct bmp_listener
*bl
;
2488 struct bmp_active
*ba
;
2495 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2496 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2497 bmpbgp
->mirror_qsizelimit
);
2499 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2500 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2503 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2505 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2508 vty_out(vty
, " bmp stats interval %d\n",
2512 vty_out(vty
, " bmp mirror\n");
2514 FOREACH_AFI_SAFI (afi
, safi
) {
2515 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2517 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2518 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2519 afi_str
, safi2str(safi
));
2520 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2521 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2522 afi_str
, safi2str(safi
));
2524 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2525 vty_out(vty
, " \n bmp listener %pSU port %d\n",
2526 &bl
->addr
, bl
->port
);
2528 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2529 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u",
2530 ba
->hostname
, ba
->port
,
2531 ba
->minretry
, ba
->maxretry
);
2534 vty_out(vty
, " source-interface %s\n", ba
->ifsrc
);
2538 vty_out(vty
, " exit\n");
2544 static int bgp_bmp_init(struct thread_master
*tm
)
2546 install_node(&bmp_node
);
2547 install_default(BMP_NODE
);
2549 cmd_variable_handler_register(bmp_targets_var_handlers
);
2551 install_element(BGP_NODE
, &bmp_targets_cmd
);
2552 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2554 install_element(BMP_NODE
, &bmp_listener_cmd
);
2555 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2556 install_element(BMP_NODE
, &bmp_connect_cmd
);
2557 install_element(BMP_NODE
, &bmp_acl_cmd
);
2558 install_element(BMP_NODE
, &bmp_stats_cmd
);
2559 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2560 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2562 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2563 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2565 install_element(VIEW_NODE
, &show_bmp_cmd
);
2571 static int bgp_bmp_module_init(void)
2573 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2574 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2575 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2576 hook_register(peer_backward_transition
, bmp_peer_backward
);
2577 hook_register(bgp_process
, bmp_process
);
2578 hook_register(bgp_inst_config_write
, bmp_config_write
);
2579 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2580 hook_register(frr_late_init
, bgp_bmp_init
);
2584 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2585 .description
= "bgpd BMP module",
2586 .init
= bgp_bmp_module_init
,