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. */
857 bgp_packet_attribute(NULL
, peer
, s
, attr
, &vecarr
, NULL
, afi
,
858 safi
, peer
, NULL
, NULL
, 0, 0, 0, NULL
);
862 /* peer_cap_enhe & add-path removed */
863 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
864 stream_put_prefix(s
, p
);
866 size_t p1
= stream_get_endp(s
);
868 /* MPLS removed for now */
870 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
872 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
874 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
875 total_attr_len
+= stream_get_endp(s
) - p1
;
878 /* set the total attribute length correctly */
879 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
880 bgp_packet_set_size(s
);
884 static struct stream
*bmp_withdraw(const struct prefix
*p
,
885 struct prefix_rd
*prd
, afi_t afi
,
889 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
890 bgp_size_t total_attr_len
= 0;
891 bgp_size_t unfeasible_len
;
893 s
= stream_new(BGP_MAX_PACKET_SIZE
);
895 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
898 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
899 stream_put_prefix(s
, p
);
900 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
901 - BGP_UNFEASIBLE_LEN
;
902 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
905 attrlen_pos
= stream_get_endp(s
);
906 /* total attr length = 0 for now. reevaluate later */
908 mp_start
= stream_get_endp(s
);
909 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
911 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
913 /* Set the mp_unreach attr's length */
914 bgp_packet_mpunreach_end(s
, mplen_pos
);
916 /* Set total path attribute length. */
917 total_attr_len
= stream_get_endp(s
) - mp_start
;
918 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
921 bgp_packet_set_size(s
);
925 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
926 const struct prefix
*p
, struct prefix_rd
*prd
,
927 struct attr
*attr
, afi_t afi
, safi_t safi
,
930 struct stream
*hdr
, *msg
;
931 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
932 struct timeval uptime_real
;
934 monotime_to_realtime(&tv
, &uptime_real
);
936 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
938 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
940 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
941 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
942 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
944 stream_putl_at(hdr
, BMP_LENGTH_POS
,
945 stream_get_endp(hdr
) + stream_get_endp(msg
));
948 pullwr_write_stream(bmp
->pullwr
, hdr
);
949 pullwr_write_stream(bmp
->pullwr
, msg
);
954 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
959 if (bmp
->syncafi
== AFI_MAX
) {
960 FOREACH_AFI_SAFI (afi
, safi
) {
961 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
964 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
967 bmp
->syncsafi
= safi
;
969 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
970 bmp
->syncpos
.family
= afi2family(afi
);
971 bmp
->syncrdpos
= NULL
;
972 zlog_info("bmp[%s] %s %s sending table",
974 afi2str(bmp
->syncafi
),
975 safi2str(bmp
->syncsafi
));
976 /* break does not work here, 2 loops... */
979 if (bmp
->syncafi
== AFI_MAX
)
985 safi
= bmp
->syncsafi
;
987 if (!bmp
->targets
->afimon
[afi
][safi
]) {
988 /* shouldn't happen */
989 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
990 bmp
->syncafi
= AFI_MAX
;
991 bmp
->syncsafi
= SAFI_MAX
;
995 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
996 struct bgp_dest
*bn
= NULL
;
997 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
998 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
1000 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
1001 (safi
== SAFI_MPLS_VPN
)) {
1002 /* initialize syncrdpos to the first
1003 * mid-layer table entry
1005 if (!bmp
->syncrdpos
) {
1006 bmp
->syncrdpos
= bgp_table_top(table
);
1007 if (!bmp
->syncrdpos
)
1011 /* look for a valid mid-layer table */
1013 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
1017 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
1018 } while (bmp
->syncrdpos
);
1020 /* mid-layer table completed */
1021 if (!bmp
->syncrdpos
)
1025 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
1028 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
1030 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
1031 (safi
== SAFI_MPLS_VPN
)) {
1032 /* reset bottom-layer pointer */
1033 memset(&bmp
->syncpos
, 0,
1034 sizeof(bmp
->syncpos
));
1035 bmp
->syncpos
.family
= afi2family(afi
);
1036 /* check whethere there is a valid
1037 * next mid-layer table, otherwise
1038 * declare table completed (eor)
1040 for (bmp
->syncrdpos
= bgp_route_next(
1043 bmp
->syncrdpos
= bgp_route_next(
1045 if (bgp_dest_get_bgp_table_info(
1050 zlog_info("bmp[%s] %s %s table completed (EoR)",
1051 bmp
->remote
, afi2str(afi
),
1053 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1054 bmp_eor(bmp
, afi
, safi
, 0);
1056 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1057 bmp
->syncafi
= AFI_MAX
;
1058 bmp
->syncsafi
= SAFI_MAX
;
1061 bmp
->syncpeerid
= 0;
1062 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1065 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1066 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1067 bpiter
= bpiter
->next
) {
1068 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1070 if (bpiter
->peer
->qobj_node
.nid
1073 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1074 > bpi
->peer
->qobj_node
.nid
)
1079 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1080 for (adjiter
= bn
->adj_in
; adjiter
;
1081 adjiter
= adjiter
->next
) {
1082 if (adjiter
->peer
->qobj_node
.nid
1085 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1086 > adjin
->peer
->qobj_node
.nid
)
1098 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1100 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1101 } else if (adjin
&& bpi
1102 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1104 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1106 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1108 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1111 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1112 struct prefix_rd
*prd
= NULL
;
1113 if (((afi
== AFI_L2VPN
) && (safi
== SAFI_EVPN
)) ||
1114 (safi
== SAFI_MPLS_VPN
))
1115 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1118 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1119 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1121 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1122 safi
, adjin
->uptime
);
1125 bgp_dest_unlock_node(bn
);
1130 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1132 struct bmp_queue_entry
*bqe
;
1134 bqe
= bmp
->queuepos
;
1138 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1141 if (!bqe
->refcount
) {
1142 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1143 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1148 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1150 struct bmp_queue_entry
*bqe
;
1152 struct bgp_dest
*bn
= NULL
;
1153 bool written
= false;
1155 bqe
= bmp_pull(bmp
);
1159 afi_t afi
= bqe
->afi
;
1160 safi_t safi
= bqe
->safi
;
1162 switch (bmp
->afistate
[afi
][safi
]) {
1163 case BMP_AFI_INACTIVE
:
1164 case BMP_AFI_NEEDSYNC
:
1167 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1168 /* currently syncing but have already passed this
1169 * prefix => send it. */
1172 /* currently syncing & haven't reached this prefix yet
1173 * => it'll be sent as part of the table sync, no need here */
1179 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1181 zlog_info("bmp: skipping queued item for deleted peer");
1184 if (!peer_established(peer
))
1187 bool is_vpn
= (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
) ||
1188 (bqe
->safi
== SAFI_MPLS_VPN
);
1190 struct prefix_rd
*prd
= is_vpn
? &bqe
->rd
: NULL
;
1191 bn
= bgp_afi_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], afi
, safi
,
1195 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1196 struct bgp_path_info
*bpi
;
1198 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1200 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1202 if (bpi
->peer
== peer
)
1206 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1207 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1208 bpi
? bpi
->uptime
: monotime(NULL
));
1212 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1213 struct bgp_adj_in
*adjin
;
1215 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1216 adjin
= adjin
->next
) {
1217 if (adjin
->peer
== peer
)
1220 bmp_monitor(bmp
, peer
, 0, &bqe
->p
, prd
,
1221 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1222 adjin
? adjin
->uptime
: monotime(NULL
));
1228 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1231 bgp_dest_unlock_node(bn
);
1236 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1238 switch(bmp
->state
) {
1240 bmp_send_peerup(bmp
);
1241 bmp
->state
= BMP_Run
;
1245 if (bmp_wrmirror(bmp
, pullwr
))
1247 if (bmp_wrqueue(bmp
, pullwr
))
1249 if (bmp_wrsync(bmp
, pullwr
))
1255 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1258 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1260 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1261 bmp
->remote
, strerror(errno
));
1267 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1268 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1271 struct bmp_queue_entry
*bqe
, bqeref
;
1274 refcount
= bmp_session_count(&bt
->sessions
);
1278 memset(&bqeref
, 0, sizeof(bqeref
));
1279 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1280 bqeref
.peerid
= peer
->qobj_node
.nid
;
1284 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
) ||
1285 (safi
== SAFI_MPLS_VPN
))
1286 prefix_copy(&bqeref
.rd
,
1287 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1289 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1291 if (bqe
->refcount
>= refcount
)
1292 /* nothing to do here */
1295 bmp_qlist_del(&bt
->updlist
, bqe
);
1297 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1298 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1300 bmp_qhash_add(&bt
->updhash
, bqe
);
1303 bqe
->refcount
= refcount
;
1304 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1306 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1308 bmp
->queuepos
= bqe
;
1311 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1312 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1314 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1315 struct bmp_targets
*bt
;
1318 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1319 char pfxprint
[PREFIX2STR_BUFFER
];
1321 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1322 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1329 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1330 if (!bt
->afimon
[afi
][safi
])
1333 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1335 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1336 pullwr_bump(bmp
->pullwr
);
1342 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1345 stream_putw(s
, type
);
1347 stream_putl(s
, value
);
1351 static void bmp_stats(struct thread
*thread
)
1353 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1356 struct listnode
*node
;
1360 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1363 gettimeofday(&tv
, NULL
);
1365 /* Walk down all peers */
1366 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1367 size_t count
= 0, count_pos
, len
;
1369 if (!peer_established(peer
))
1372 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1373 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1374 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1376 count_pos
= stream_get_endp(s
);
1379 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1380 peer
->stat_pfx_filter
);
1381 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1382 peer
->stat_pfx_aspath_loop
);
1383 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1384 peer
->stat_pfx_originator_loop
);
1385 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1386 peer
->stat_pfx_cluster_loop
);
1387 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1388 peer
->stat_pfx_dup_withdraw
);
1389 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1390 peer
->stat_upd_7606
);
1391 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1392 peer
->stat_pfx_nh_invalid
);
1394 stream_putl_at(s
, count_pos
, count
);
1396 len
= stream_get_endp(s
);
1397 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1399 bmp_send_all(bt
->bmpbgp
, s
);
1403 /* read from the BMP socket to detect session termination */
1404 static void bmp_read(struct thread
*t
)
1406 struct bmp
*bmp
= THREAD_ARG(t
);
1412 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1414 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1415 } else if (n
== 0) {
1416 /* the TCP session was terminated by the far end */
1417 bmp_wrerr(bmp
, NULL
, true);
1419 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1420 /* the TCP session experienced a fatal error, likely a timeout */
1421 bmp_wrerr(bmp
, NULL
, false);
1425 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1428 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1430 union sockunion su
, *sumem
;
1433 struct access_list
*acl
= NULL
;
1434 enum filter_type ret
;
1435 char buf
[SU_ADDRSTRLEN
];
1438 sumem
= sockunion_getpeername(bmp_sock
);
1443 memcpy(&su
, sumem
, sizeof(su
));
1444 sockunion_free(sumem
);
1446 set_nonblocking(bmp_sock
);
1447 set_cloexec(bmp_sock
);
1449 if (!sockunion2hostprefix(&su
, &p
)) {
1457 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1460 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1466 ret
= FILTER_PERMIT
;
1468 ret
= access_list_apply(acl
, &p
);
1471 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1472 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1473 su
.sa
.sa_family
== AF_INET
1474 ? ntohs(su
.sin
.sin_port
)
1475 : ntohs(su
.sin6
.sin6_port
));
1477 if (ret
== FILTER_DENY
) {
1478 bt
->cnt_aclrefused
++;
1479 zlog_info("bmp[%s] connection refused by access-list", buf
);
1485 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1486 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1487 bmp_sock
, safe_strerror(errno
), errno
);
1488 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1489 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1490 bmp_sock
, safe_strerror(errno
), errno
);
1492 zlog_info("bmp[%s] connection established", buf
);
1494 /* Allocate new BMP structure and set up default values. */
1495 bmp
= bmp_new(bt
, bmp_sock
);
1496 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1498 bmp
->state
= BMP_PeerUp
;
1499 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1501 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1502 bmp_send_initiation(bmp
);
1507 /* Accept BMP connection. */
1508 static void bmp_accept(struct thread
*thread
)
1511 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1514 /* We continue hearing BMP socket. */
1515 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1517 memset(&su
, 0, sizeof(union sockunion
));
1519 /* We can handle IPv4 or IPv6 socket. */
1520 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1522 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1525 bmp_open(bl
->targets
, bmp_sock
);
1528 static void bmp_close(struct bmp
*bmp
)
1530 struct bmp_queue_entry
*bqe
;
1531 struct bmp_mirrorq
*bmq
;
1533 THREAD_OFF(bmp
->t_read
);
1536 bmp_active_disconnected(bmp
->active
);
1538 while ((bmq
= bmp_pull_mirror(bmp
)))
1540 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1541 while ((bqe
= bmp_pull(bmp
)))
1543 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1545 THREAD_OFF(bmp
->t_read
);
1546 pullwr_del(bmp
->pullwr
);
1550 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1552 struct bmp_bgp dummy
= { .bgp
= bgp
};
1553 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1556 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1558 struct bmp_bgp
*bmpbgp
;
1560 bmpbgp
= bmp_bgp_find(bgp
);
1564 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1566 bmpbgp
->mirror_qsizelimit
= ~0UL;
1567 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1568 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1573 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1575 struct bmp_targets
*bt
;
1576 struct bmp_listener
*bl
;
1578 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1580 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, bt
) {
1581 frr_each_safe (bmp_listeners
, &bt
->listeners
, bl
)
1582 bmp_listener_put(bl
);
1584 bmp_targets_put(bt
);
1587 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1588 XFREE(MTYPE_BMP
, bmpbgp
);
1591 static int bmp_bgp_del(struct bgp
*bgp
)
1593 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1596 bmp_bgp_put(bmpbgp
);
1600 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1602 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1603 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1606 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1608 struct bmp_bgp_peer
*bbpeer
;
1610 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1614 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1615 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1616 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1621 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1623 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1624 struct bmp_targets dummy
;
1628 dummy
.name
= (char *)name
;
1629 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1632 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1634 struct bmp_targets
*bt
;
1636 bt
= bmp_targets_find1(bgp
, name
);
1640 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1641 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1643 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1644 bmp_session_init(&bt
->sessions
);
1645 bmp_qhash_init(&bt
->updhash
);
1646 bmp_qlist_init(&bt
->updlist
);
1647 bmp_actives_init(&bt
->actives
);
1648 bmp_listeners_init(&bt
->listeners
);
1650 QOBJ_REG(bt
, bmp_targets
);
1651 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1655 static void bmp_targets_put(struct bmp_targets
*bt
)
1658 struct bmp_active
*ba
;
1660 THREAD_OFF(bt
->t_stats
);
1662 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1665 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1670 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1673 bmp_listeners_fini(&bt
->listeners
);
1674 bmp_actives_fini(&bt
->actives
);
1675 bmp_qhash_fini(&bt
->updhash
);
1676 bmp_qlist_fini(&bt
->updlist
);
1678 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1679 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1680 bmp_session_fini(&bt
->sessions
);
1682 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1683 XFREE(MTYPE_BMP_TARGETS
, bt
);
1686 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1687 const union sockunion
*su
,
1690 struct bmp_listener dummy
;
1693 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1696 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1697 const union sockunion
*su
,
1700 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1705 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1711 bmp_listeners_add(&bt
->listeners
, bl
);
1715 static void bmp_listener_start(struct bmp_listener
*bl
)
1719 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1723 sockopt_reuseaddr(sock
);
1724 sockopt_reuseport(sock
);
1725 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1728 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1732 ret
= listen(sock
, 3);
1737 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1743 static void bmp_listener_stop(struct bmp_listener
*bl
)
1745 THREAD_OFF(bl
->t_accept
);
1752 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1753 const char *hostname
, int port
)
1755 struct bmp_active dummy
;
1756 dummy
.hostname
= (char *)hostname
;
1758 return bmp_actives_find(&bt
->actives
, &dummy
);
1761 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1762 const char *hostname
, int port
)
1764 struct bmp_active
*ba
;
1766 ba
= bmp_active_find(bt
, hostname
, port
);
1770 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1772 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1774 ba
->minretry
= BMP_DFLT_MINRETRY
;
1775 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1778 bmp_actives_add(&bt
->actives
, ba
);
1782 static void bmp_active_put(struct bmp_active
*ba
)
1784 THREAD_OFF(ba
->t_timer
);
1785 THREAD_OFF(ba
->t_read
);
1786 THREAD_OFF(ba
->t_write
);
1788 bmp_actives_del(&ba
->targets
->actives
, ba
);
1791 ba
->bmp
->active
= NULL
;
1795 if (ba
->socket
!= -1)
1798 XFREE(MTYPE_TMP
, ba
->ifsrc
);
1799 XFREE(MTYPE_TMP
, ba
->hostname
);
1800 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1803 static void bmp_active_setup(struct bmp_active
*ba
);
1805 static void bmp_active_connect(struct bmp_active
*ba
)
1807 enum connect_result res
;
1808 struct interface
*ifp
;
1809 vrf_id_t vrf_id
= VRF_DEFAULT
;
1812 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1814 if (ba
->targets
&& ba
->targets
->bgp
)
1815 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1817 /* find interface and related */
1818 /* address with same family */
1819 ifp
= if_lookup_by_name(ba
->ifsrc
, vrf_id
);
1821 zlog_warn("bmp[%s]: failed to find interface",
1826 if (bgp_update_address(ifp
, &ba
->addrs
[ba
->addrpos
],
1828 zlog_warn("bmp[%s]: failed to find matching address",
1832 zlog_info("bmp[%s]: selected source address : %pSU",
1833 ba
->ifsrc
, &ba
->addrsrc
);
1836 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1837 if (ba
->socket
< 0) {
1838 zlog_warn("bmp[%s]: failed to create socket",
1843 set_nonblocking(ba
->socket
);
1845 if (!sockunion_is_null(&ba
->addrsrc
)) {
1846 res_bind
= sockunion_bind(ba
->socket
, &ba
->addrsrc
, 0,
1850 "bmp[%s]: no bind currently to source address %pSU:%d",
1851 ba
->hostname
, &ba
->addrsrc
, ba
->port
);
1854 sockunion_init(&ba
->addrsrc
);
1860 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1861 htons(ba
->port
), 0);
1864 zlog_warn("bmp[%s]: failed to connect to %pSU:%d",
1865 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1869 sockunion_init(&ba
->addrsrc
);
1871 case connect_success
:
1872 zlog_info("bmp[%s]: connected to %pSU:%d",
1873 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1876 case connect_in_progress
:
1877 zlog_warn("bmp[%s]: connect in progress %pSU:%d",
1878 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1880 bmp_active_setup(ba
);
1885 /* exhausted all addresses */
1886 ba
->curretry
+= ba
->curretry
/ 2;
1887 bmp_active_setup(ba
);
1890 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1891 int numaddrs
, union sockunion
*addr
)
1893 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1896 if (numaddrs
<= 0) {
1897 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1898 ba
->hostname
, errstr
);
1899 ba
->last_err
= errstr
;
1900 ba
->curretry
+= ba
->curretry
/ 2;
1903 bmp_active_setup(ba
);
1907 if (numaddrs
> (int)array_size(ba
->addrs
))
1908 numaddrs
= array_size(ba
->addrs
);
1911 ba
->addrtotal
= numaddrs
;
1912 for (i
= 0; i
< ba
->addrtotal
; i
++)
1913 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1915 bmp_active_connect(ba
);
1918 static void bmp_active_thread(struct thread
*t
)
1920 struct bmp_active
*ba
= THREAD_ARG(t
);
1925 /* all 3 end up here, though only timer or read+write are active
1927 THREAD_OFF(ba
->t_timer
);
1928 THREAD_OFF(ba
->t_read
);
1929 THREAD_OFF(ba
->t_write
);
1931 ba
->last_err
= NULL
;
1933 if (ba
->socket
== -1) {
1935 if (!ba
->targets
|| !ba
->targets
->bgp
)
1936 vrf_id
= VRF_DEFAULT
;
1938 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1939 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1940 bmp_active_resolved
);
1944 slen
= sizeof(status
);
1945 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1948 if (ret
< 0 || status
!= 0) {
1949 ba
->last_err
= strerror(status
);
1950 zlog_warn("bmp[%s]: failed to connect to %pSU:%d: %s",
1951 ba
->hostname
, &ba
->addrs
[ba
->addrpos
], ba
->port
,
1956 zlog_warn("bmp[%s]: outbound connection to %pSU:%d", ba
->hostname
,
1957 &ba
->addrs
[ba
->addrpos
], ba
->port
);
1959 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1963 ba
->bmp
->active
= ba
;
1965 ba
->curretry
= ba
->minretry
;
1972 bmp_active_connect(ba
);
1975 static void bmp_active_disconnected(struct bmp_active
*ba
)
1978 bmp_active_setup(ba
);
1981 static void bmp_active_setup(struct bmp_active
*ba
)
1983 THREAD_OFF(ba
->t_timer
);
1984 THREAD_OFF(ba
->t_read
);
1985 THREAD_OFF(ba
->t_write
);
1989 if (ba
->resq
.callback
)
1992 if (ba
->curretry
> ba
->maxretry
)
1993 ba
->curretry
= ba
->maxretry
;
1995 if (ba
->socket
== -1)
1996 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1997 ba
->curretry
, &ba
->t_timer
);
1999 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
2001 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
2006 static struct cmd_node bmp_node
= {
2009 .parent_node
= BGP_NODE
,
2010 .prompt
= "%s(config-bgp-bmp)# "
2013 static void bmp_targets_autocomplete(vector comps
, struct cmd_token
*token
)
2016 struct bmp_targets
*target
;
2017 struct listnode
*node
;
2019 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
2020 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2025 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, target
)
2027 XSTRDUP(MTYPE_COMPLETION
, target
->name
));
2031 static const struct cmd_variable_handler bmp_targets_var_handlers
[] = {
2032 {.tokenname
= "BMPTARGETS", .completions
= bmp_targets_autocomplete
},
2033 {.completions
= NULL
}};
2035 #define BMP_STR "BGP Monitoring Protocol\n"
2037 #include "bgpd/bgp_bmp_clippy.c"
2039 DEFPY_NOSH(bmp_targets_main
,
2041 "bmp targets BMPTARGETS",
2043 "Create BMP target group\n"
2044 "Name of the BMP target group\n")
2046 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2047 struct bmp_targets
*bt
;
2049 bt
= bmp_targets_get(bgp
, bmptargets
);
2051 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
2055 DEFPY(no_bmp_targets_main
,
2057 "no bmp targets BMPTARGETS",
2060 "Delete BMP target group\n"
2061 "Name of the BMP target group\n")
2063 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2064 struct bmp_targets
*bt
;
2066 bt
= bmp_targets_find1(bgp
, bmptargets
);
2068 vty_out(vty
, "%% BMP target group not found\n");
2071 bmp_targets_put(bt
);
2075 DEFPY(bmp_listener_main
,
2077 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2079 "Listen for inbound BMP connections\n"
2080 "IPv6 address to listen on\n"
2081 "IPv4 address to listen on\n"
2083 "TCP Port number\n")
2085 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2086 struct bmp_listener
*bl
;
2088 bl
= bmp_listener_get(bt
, listener
, port
);
2090 bmp_listener_start(bl
);
2095 DEFPY(no_bmp_listener_main
,
2096 no_bmp_listener_cmd
,
2097 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2100 "Create BMP listener\n"
2101 "IPv6 address to listen on\n"
2102 "IPv4 address to listen on\n"
2104 "TCP Port number\n")
2106 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2107 struct bmp_listener
*bl
;
2109 bl
= bmp_listener_find(bt
, listener
, port
);
2111 vty_out(vty
, "%% BMP listener not found\n");
2114 bmp_listener_stop(bl
);
2115 bmp_listener_put(bl
);
2121 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
2124 "Actively establish connection to monitoring station\n"
2125 "Monitoring station hostname or address\n"
2128 "Minimum connection retry interval\n"
2129 "Minimum connection retry interval (milliseconds)\n"
2130 "Maximum connection retry interval\n"
2131 "Maximum connection retry interval (milliseconds)\n"
2132 "Source interface to use\n"
2133 "Define an interface\n")
2135 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2136 struct bmp_active
*ba
;
2139 ba
= bmp_active_find(bt
, hostname
, port
);
2141 vty_out(vty
, "%% No such active connection found\n");
2144 /* connection deletion need same hostname port and interface */
2145 if (ba
->ifsrc
|| srcif
)
2146 if ((!ba
->ifsrc
) || (!srcif
) ||
2147 !strcmp(ba
->ifsrc
, srcif
)) {
2149 "%% No such active connection found\n");
2156 ba
= bmp_active_get(bt
, hostname
, port
);
2158 ba
->ifsrc
= XSTRDUP(MTYPE_TMP
, srcif
);
2160 ba
->minretry
= min_retry
;
2162 ba
->maxretry
= max_retry
;
2163 ba
->curretry
= ba
->minretry
;
2164 bmp_active_setup(ba
);
2171 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2175 "Access list to restrict BMP sessions\n"
2176 "Access list name\n")
2178 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2183 if (!strcmp(af
, "ipv6"))
2184 what
= &bt
->acl6_name
;
2186 what
= &bt
->acl_name
;
2188 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2190 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2195 DEFPY(bmp_stats_cfg
,
2197 "[no] bmp stats [interval (100-86400000)]",
2200 "Send BMP statistics messages\n"
2201 "Specify BMP stats interval\n"
2202 "Interval (milliseconds) to send BMP Stats in\n")
2204 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2206 THREAD_OFF(bt
->t_stats
);
2209 else if (interval_str
)
2210 bt
->stat_msec
= interval
;
2212 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2215 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2220 DEFPY(bmp_monitor_cfg
,
2222 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
2225 "Send BMP route monitoring messages\n"
2233 "Send state before policy and filter processing\n"
2234 "Send state with policy and filters applied\n")
2241 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2244 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2245 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2247 if (policy
[1] == 'r')
2248 flag
= BMP_MON_PREPOLICY
;
2250 flag
= BMP_MON_POSTPOLICY
;
2252 prev
= bt
->afimon
[afi
][safi
];
2254 bt
->afimon
[afi
][safi
] &= ~flag
;
2256 bt
->afimon
[afi
][safi
] |= flag
;
2258 if (prev
== bt
->afimon
[afi
][safi
])
2261 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2262 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2263 bmp
->syncafi
= AFI_MAX
;
2264 bmp
->syncsafi
= SAFI_MAX
;
2267 if (!bt
->afimon
[afi
][safi
]) {
2268 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2272 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2278 DEFPY(bmp_mirror_cfg
,
2283 "Send BMP route mirroring messages\n")
2285 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2288 if (bt
->mirror
== !no
)
2295 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2296 struct bmp_mirrorq
*bmq
;
2298 while ((bmq
= bmp_pull_mirror(bmp
)))
2300 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2305 DEFPY(bmp_mirror_limit_cfg
,
2306 bmp_mirror_limit_cmd
,
2307 "bmp mirror buffer-limit (0-4294967294)",
2309 "Route Mirroring settings\n"
2310 "Configure maximum memory used for buffered mirroring messages\n"
2313 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2314 struct bmp_bgp
*bmpbgp
;
2316 bmpbgp
= bmp_bgp_get(bgp
);
2317 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2322 DEFPY(no_bmp_mirror_limit_cfg
,
2323 no_bmp_mirror_limit_cmd
,
2324 "no bmp mirror buffer-limit [(0-4294967294)]",
2327 "Route Mirroring settings\n"
2328 "Configure maximum memory used for buffered mirroring messages\n"
2331 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2332 struct bmp_bgp
*bmpbgp
;
2334 bmpbgp
= bmp_bgp_get(bgp
);
2335 bmpbgp
->mirror_qsizelimit
= ~0UL;
2347 struct bmp_bgp
*bmpbgp
;
2348 struct bmp_targets
*bt
;
2349 struct bmp_listener
*bl
;
2350 struct bmp_active
*ba
;
2353 char uptime
[BGP_UPTIME_LEN
];
2356 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2357 vty_out(vty
, "BMP state for BGP %s:\n\n",
2358 bmpbgp
->bgp
->name_pretty
);
2359 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2360 bmpbgp
->mirror_qsize
,
2361 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2362 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2363 bmpbgp
->mirror_qsizemax
);
2364 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2365 vty_out(vty
, " %9zu bytes buffer size limit\n",
2366 bmpbgp
->mirror_qsizelimit
);
2369 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2370 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2371 vty_out(vty
, " Route Mirroring %sabled\n",
2372 bt
->mirror
? "en" : "dis");
2377 FOREACH_AFI_SAFI (afi
, safi
) {
2378 const char *str
= NULL
;
2380 switch (bt
->afimon
[afi
][safi
]) {
2381 case BMP_MON_PREPOLICY
:
2384 case BMP_MON_POSTPOLICY
:
2385 str
= "post-policy";
2387 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2388 str
= "pre-policy and post-policy";
2393 vty_out(vty
, " Route Monitoring %s %s %s\n",
2394 afi2str(afi
), safi2str(safi
), str
);
2397 vty_out(vty
, " Listeners:\n");
2398 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2399 vty_out(vty
, " %pSU:%d\n", &bl
->addr
,
2402 vty_out(vty
, "\n Outbound connections:\n");
2403 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2404 ttable_add_row(tt
, "remote|state||timer|local");
2405 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2406 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2407 const char *state_str
= "?";
2410 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2411 uptime
, sizeof(uptime
),
2414 "%s:%d|Up|%s|%s|%pSU",
2415 ba
->hostname
, ba
->port
,
2416 ba
->bmp
->remote
, uptime
,
2424 long trem
= thread_timer_remain_second(
2427 peer_uptime(monotime(NULL
) - trem
,
2428 uptime
, sizeof(uptime
),
2430 state_str
= "RetryWait";
2431 } else if (ba
->t_read
) {
2432 state_str
= "Connecting";
2433 } else if (ba
->resq
.callback
) {
2434 state_str
= "Resolving";
2437 ttable_add_row(tt
, "%s:%d|%s|%s|%s|%pSU",
2438 ba
->hostname
, ba
->port
,
2440 ba
->last_err
? ba
->last_err
: "",
2441 uptime
, &ba
->addrsrc
);
2444 out
= ttable_dump(tt
, "\n");
2445 vty_out(vty
, "%s", out
);
2446 XFREE(MTYPE_TMP
, out
);
2449 vty_out(vty
, "\n %zu connected clients:\n",
2450 bmp_session_count(&bt
->sessions
));
2451 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2452 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2453 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2455 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2459 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2461 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2462 sizeof(uptime
), false, NULL
);
2464 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2465 bmp
->remote
, uptime
,
2468 bmp
->cnt_mirror_overruns
,
2471 out
= ttable_dump(tt
, "\n");
2472 vty_out(vty
, "%s", out
);
2473 XFREE(MTYPE_TMP
, out
);
2482 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2484 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2485 struct bmp_targets
*bt
;
2486 struct bmp_listener
*bl
;
2487 struct bmp_active
*ba
;
2494 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2495 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2496 bmpbgp
->mirror_qsizelimit
);
2498 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2499 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2502 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2504 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2507 vty_out(vty
, " bmp stats interval %d\n",
2511 vty_out(vty
, " bmp mirror\n");
2513 FOREACH_AFI_SAFI (afi
, safi
) {
2514 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2516 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2517 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2518 afi_str
, safi2str(safi
));
2519 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2520 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2521 afi_str
, safi2str(safi
));
2523 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2524 vty_out(vty
, " \n bmp listener %pSU port %d\n",
2525 &bl
->addr
, bl
->port
);
2527 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2528 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u",
2529 ba
->hostname
, ba
->port
,
2530 ba
->minretry
, ba
->maxretry
);
2533 vty_out(vty
, " source-interface %s\n", ba
->ifsrc
);
2537 vty_out(vty
, " exit\n");
2543 static int bgp_bmp_init(struct thread_master
*tm
)
2545 install_node(&bmp_node
);
2546 install_default(BMP_NODE
);
2548 cmd_variable_handler_register(bmp_targets_var_handlers
);
2550 install_element(BGP_NODE
, &bmp_targets_cmd
);
2551 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2553 install_element(BMP_NODE
, &bmp_listener_cmd
);
2554 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2555 install_element(BMP_NODE
, &bmp_connect_cmd
);
2556 install_element(BMP_NODE
, &bmp_acl_cmd
);
2557 install_element(BMP_NODE
, &bmp_stats_cmd
);
2558 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2559 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2561 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2562 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2564 install_element(VIEW_NODE
, &show_bmp_cmd
);
2570 static int bgp_bmp_module_init(void)
2572 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2573 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2574 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2575 hook_register(peer_backward_transition
, bmp_peer_backward
);
2576 hook_register(bgp_process
, bmp_process
);
2577 hook_register(bgp_inst_config_write
, bmp_config_write
);
2578 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2579 hook_register(frr_late_init
, bgp_bmp_init
);
2583 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2584 .description
= "bgpd BMP module",
2585 .init
= bgp_bmp_module_init
,