1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 Yasuhiro Ohara
4 * Copyright (C) 2019 David Lamparter for NetDEF, Inc.
11 #include "sockunion.h"
21 #include "lib_errors.h"
24 #include "lib/version.h"
26 #include "termtable.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_dump.h"
33 #include "bgpd/bgp_errors.h"
34 #include "bgpd/bgp_packet.h"
35 #include "bgpd/bgp_bmp.h"
36 #include "bgpd/bgp_fsm.h"
37 #include "bgpd/bgp_updgrp.h"
38 #include "bgpd/bgp_vty.h"
39 #include "bgpd/bgp_trace.h"
40 #include "bgpd/bgp_network.h"
42 static void bmp_close(struct bmp
*bmp
);
43 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
);
44 static void bmp_targets_put(struct bmp_targets
*bt
);
45 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
);
46 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
);
47 static void bmp_active_disconnected(struct bmp_active
*ba
);
48 static void bmp_active_put(struct bmp_active
*ba
);
50 DEFINE_MGROUP(BMP
, "BMP (BGP Monitoring Protocol)");
52 DEFINE_MTYPE_STATIC(BMP
, BMP_CONN
, "BMP connection state");
53 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETS
, "BMP targets");
54 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETSNAME
, "BMP targets name");
55 DEFINE_MTYPE_STATIC(BMP
, BMP_LISTENER
, "BMP listener");
56 DEFINE_MTYPE_STATIC(BMP
, BMP_ACTIVE
, "BMP active connection config");
57 DEFINE_MTYPE_STATIC(BMP
, BMP_ACLNAME
, "BMP access-list name");
58 DEFINE_MTYPE_STATIC(BMP
, BMP_QUEUE
, "BMP update queue item");
59 DEFINE_MTYPE_STATIC(BMP
, BMP
, "BMP instance state");
60 DEFINE_MTYPE_STATIC(BMP
, BMP_MIRRORQ
, "BMP route mirroring buffer");
61 DEFINE_MTYPE_STATIC(BMP
, BMP_PEER
, "BMP per BGP peer data");
62 DEFINE_MTYPE_STATIC(BMP
, BMP_OPEN
, "BMP stored BGP OPEN message");
64 DEFINE_QOBJ_TYPE(bmp_targets
);
66 static int bmp_bgp_cmp(const struct bmp_bgp
*a
, const struct bmp_bgp
*b
)
75 static uint32_t bmp_bgp_hash(const struct bmp_bgp
*e
)
77 return jhash(&e
->bgp
, sizeof(e
->bgp
), 0x55aa5a5a);
80 DECLARE_HASH(bmp_bgph
, struct bmp_bgp
, bbi
, bmp_bgp_cmp
, bmp_bgp_hash
);
82 struct bmp_bgph_head bmp_bgph
;
84 static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer
*a
,
85 const struct bmp_bgp_peer
*b
)
87 if (a
->peerid
< b
->peerid
)
89 if (a
->peerid
> b
->peerid
)
94 static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer
*e
)
99 DECLARE_HASH(bmp_peerh
, struct bmp_bgp_peer
, bpi
,
100 bmp_bgp_peer_cmp
, bmp_bgp_peer_hash
);
102 struct bmp_peerh_head bmp_peerh
;
104 DECLARE_LIST(bmp_mirrorq
, struct bmp_mirrorq
, bmi
);
106 /* listener management */
108 static int bmp_listener_cmp(const struct bmp_listener
*a
,
109 const struct bmp_listener
*b
)
113 c
= sockunion_cmp(&a
->addr
, &b
->addr
);
116 if (a
->port
< b
->port
)
118 if (a
->port
> b
->port
)
123 DECLARE_SORTLIST_UNIQ(bmp_listeners
, struct bmp_listener
, bli
,
126 static void bmp_listener_put(struct bmp_listener
*bl
)
128 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
129 XFREE(MTYPE_BMP_LISTENER
, bl
);
132 static int bmp_targets_cmp(const struct bmp_targets
*a
,
133 const struct bmp_targets
*b
)
135 return strcmp(a
->name
, b
->name
);
138 DECLARE_SORTLIST_UNIQ(bmp_targets
, struct bmp_targets
, bti
, bmp_targets_cmp
);
140 DECLARE_LIST(bmp_session
, struct bmp
, bsi
);
142 DECLARE_DLIST(bmp_qlist
, struct bmp_queue_entry
, bli
);
144 static int bmp_qhash_cmp(const struct bmp_queue_entry
*a
,
145 const struct bmp_queue_entry
*b
)
148 if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
&& b
->afi
== AFI_L2VPN
149 && b
->safi
== SAFI_EVPN
) {
150 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
153 } else if (a
->afi
== AFI_L2VPN
&& a
->safi
== SAFI_EVPN
)
155 else if (b
->afi
== AFI_L2VPN
&& b
->safi
== SAFI_EVPN
)
158 if (a
->afi
== b
->afi
&& a
->safi
== SAFI_MPLS_VPN
&&
159 b
->safi
== SAFI_MPLS_VPN
) {
160 ret
= prefix_cmp(&a
->rd
, &b
->rd
);
163 } else if (a
->safi
== SAFI_MPLS_VPN
)
165 else if (b
->safi
== SAFI_MPLS_VPN
)
168 ret
= prefix_cmp(&a
->p
, &b
->p
);
171 ret
= memcmp(&a
->peerid
, &b
->peerid
,
172 offsetof(struct bmp_queue_entry
, refcount
) -
173 offsetof(struct bmp_queue_entry
, peerid
));
177 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
181 key
= prefix_hash_key((void *)&e
->p
);
182 key
= jhash(&e
->peerid
,
183 offsetof(struct bmp_queue_entry
, refcount
)
184 - offsetof(struct bmp_queue_entry
, peerid
),
186 if ((e
->afi
== AFI_L2VPN
&& e
->safi
== SAFI_EVPN
) ||
187 (e
->safi
== SAFI_MPLS_VPN
))
189 offsetof(struct bmp_queue_entry
, rd
)
190 - offsetof(struct bmp_queue_entry
, refcount
)
191 + PSIZE(e
->rd
.prefixlen
),
197 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
198 bmp_qhash_cmp
, bmp_qhash_hkey
);
200 static int bmp_active_cmp(const struct bmp_active
*a
,
201 const struct bmp_active
*b
)
205 c
= strcmp(a
->hostname
, b
->hostname
);
208 if (a
->port
< b
->port
)
210 if (a
->port
> b
->port
)
215 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
);
217 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
219 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
223 monotime(&new->t_up
);
225 new->socket
= bmp_sock
;
226 new->syncafi
= AFI_MAX
;
228 FOREACH_AFI_SAFI (afi
, safi
) {
229 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
230 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
233 bmp_session_add_tail(&bt
->sessions
, new);
237 static void bmp_free(struct bmp
*bmp
)
239 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
240 XFREE(MTYPE_BMP_CONN
, bmp
);
243 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
246 stream_putl(s
, 0); //dummy message length. will be set later.
247 stream_putc(s
, type
);
250 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
251 uint8_t flags
, const struct timeval
*tv
)
253 char peer_distinguisher
[8];
255 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
256 #define BMP_PEER_TYPE_RD_INSTANCE 1
257 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
259 #define BMP_PEER_FLAG_V (1 << 7)
260 #define BMP_PEER_FLAG_L (1 << 6)
261 #define BMP_PEER_FLAG_A (1 << 5)
264 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
267 if (peer
->su
.sa
.sa_family
== AF_INET6
)
268 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
270 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
271 stream_putc(s
, flags
);
273 /* Peer Distinguisher */
274 memset (&peer_distinguisher
[0], 0, 8);
275 stream_put(s
, &peer_distinguisher
[0], 8);
278 if (peer
->su
.sa
.sa_family
== AF_INET6
)
279 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
280 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
284 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
293 stream_putl(s
, peer
->as
);
296 stream_put_in_addr(s
, &peer
->remote_id
);
300 stream_putl(s
, tv
->tv_sec
);
301 stream_putl(s
, tv
->tv_usec
);
308 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
311 int len
= strlen (string
);
312 stream_putw(s
, type
);
314 stream_put(s
, string
, len
);
317 static int bmp_send_initiation(struct bmp
*bmp
)
321 s
= stream_new(BGP_MAX_PACKET_SIZE
);
322 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
324 #define BMP_INFO_TYPE_SYSDESCR 1
325 #define BMP_INFO_TYPE_SYSNAME 2
326 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
327 FRR_FULL_NAME
" " FRR_VER_SHORT
);
328 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
330 len
= stream_get_endp(s
);
331 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
333 pullwr_write_stream(bmp
->pullwr
, s
);
338 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
341 uint8_t marker
[16] = {
342 0xff, 0xff, 0xff, 0xff,
343 0xff, 0xff, 0xff, 0xff,
344 0xff, 0xff, 0xff, 0xff,
345 0xff, 0xff, 0xff, 0xff,
348 stream_put(s
, marker
, sizeof(marker
));
349 len_pos
= stream_get_endp(s
);
351 stream_putc(s
, BGP_MSG_NOTIFY
);
352 stream_putc(s
, nfy
->code
);
353 stream_putc(s
, nfy
->subcode
);
354 stream_put(s
, nfy
->data
, nfy
->length
);
356 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
360 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
364 struct timeval uptime
, uptime_real
;
366 uptime
.tv_sec
= peer
->uptime
;
368 monotime_to_realtime(&uptime
, &uptime_real
);
370 #define BGP_BMP_MAX_PACKET_SIZE 1024
371 s
= stream_new(BGP_MAX_PACKET_SIZE
);
373 if (peer_established(peer
) && !down
) {
374 struct bmp_bgp_peer
*bbpeer
;
376 bmp_common_hdr(s
, BMP_VERSION_3
,
377 BMP_TYPE_PEER_UP_NOTIFICATION
);
378 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
380 /* Local Address (16 bytes) */
381 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
382 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
383 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
387 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
390 /* Local Port, Remote Port */
391 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
392 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
393 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
394 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
395 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
396 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
397 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
398 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
400 static const uint8_t dummy_open
[] = {
401 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
402 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
406 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
408 if (bbpeer
&& bbpeer
->open_tx
)
409 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
411 stream_put(s
, dummy_open
, sizeof(dummy_open
));
412 zlog_warn("bmp: missing TX OPEN message for peer %s",
415 if (bbpeer
&& bbpeer
->open_rx
)
416 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
418 stream_put(s
, dummy_open
, sizeof(dummy_open
));
419 zlog_warn("bmp: missing RX OPEN message for peer %s",
424 bmp_put_info_tlv(s
, 0, peer
->desc
);
429 bmp_common_hdr(s
, BMP_VERSION_3
,
430 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
431 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
433 type_pos
= stream_get_endp(s
);
434 stream_putc(s
, 0); /* placeholder for down reason */
436 switch (peer
->last_reset
) {
437 case PEER_DOWN_NOTIFY_RECEIVED
:
438 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
439 bmp_notify_put(s
, &peer
->notify
);
441 case PEER_DOWN_CLOSE_SESSION
:
442 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
444 case PEER_DOWN_WAITING_NHT
:
445 type
= BMP_PEERDOWN_LOCAL_FSM
;
446 stream_putw(s
, BGP_FSM_TcpConnectionFails
);
449 * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
450 * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
452 * See RFC7854 ss. 4.9
455 type
= BMP_PEERDOWN_LOCAL_FSM
;
456 stream_putw(s
, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE
);
459 stream_putc_at(s
, type_pos
, type
);
462 len
= stream_get_endp(s
);
463 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
468 static int bmp_send_peerup(struct bmp
*bmp
)
471 struct listnode
*node
;
474 /* Walk down all peers */
475 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
476 s
= bmp_peerstate(peer
, false);
477 pullwr_write_stream(bmp
->pullwr
, s
);
484 /* XXX: kludge - filling the pullwr's buffer */
485 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
487 struct bmp_targets
*bt
;
490 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
491 frr_each(bmp_session
, &bt
->sessions
, bmp
)
492 pullwr_write_stream(bmp
->pullwr
, s
);
500 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
501 #define BMP_MIRROR_TLV_TYPE_INFO 1
503 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
504 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
506 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
508 struct bmp_mirrorq
*bmq
;
510 bmq
= bmp
->mirrorpos
;
514 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
517 if (!bmq
->refcount
) {
518 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
519 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
524 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
526 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
527 struct bmp_mirrorq
*bmq
, *inner
;
528 struct bmp_targets
*bt
;
531 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
533 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
536 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
537 if (bmp
->mirrorpos
!= bmq
)
540 while ((inner
= bmp_pull_mirror(bmp
))) {
541 if (!inner
->refcount
)
542 XFREE(MTYPE_BMP_MIRRORQ
,
546 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
548 bmp
->mirror_lost
= true;
549 pullwr_bump(bmp
->pullwr
);
555 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
556 struct stream
*packet
)
558 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
560 struct bmp_mirrorq
*qitem
;
561 struct bmp_targets
*bt
;
564 frrtrace(3, frr_bgp
, bmp_mirror_packet
, peer
, type
, packet
);
566 gettimeofday(&tv
, NULL
);
568 if (type
== BGP_MSG_OPEN
) {
569 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
571 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
573 bbpeer
->open_rx_len
= size
;
574 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
575 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
581 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
582 qitem
->peerid
= peer
->qobj_node
.nid
;
585 memcpy(qitem
->data
, packet
->data
, size
);
587 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
590 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
593 bmp
->mirrorpos
= qitem
;
594 pullwr_bump(bmp
->pullwr
);
597 if (qitem
->refcount
== 0)
598 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
600 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
601 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
603 bmp_mirror_cull(bmpbgp
);
605 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
606 bmpbgp
->mirror_qsize
);
611 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
616 gettimeofday(&tv
, NULL
);
618 s
= stream_new(BGP_MAX_PACKET_SIZE
);
620 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
621 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
623 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
625 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
626 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
628 bmp
->cnt_mirror_overruns
++;
629 pullwr_write_stream(bmp
->pullwr
, s
);
633 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
635 struct bmp_mirrorq
*bmq
;
637 bool written
= false;
639 if (bmp
->mirror_lost
) {
640 bmp_wrmirror_lost(bmp
, pullwr
);
641 bmp
->mirror_lost
= false;
645 bmq
= bmp_pull_mirror(bmp
);
649 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
651 zlog_info("bmp: skipping mirror message for deleted peer");
656 s
= stream_new(BGP_MAX_PACKET_SIZE
);
658 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
659 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
661 /* BMP Mirror TLV. */
662 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
663 stream_putw(s
, bmq
->len
);
664 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
667 pullwr_write_stream(bmp
->pullwr
, s
);
668 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
675 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
679 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
680 struct stream
*packet
)
682 if (type
== BGP_MSG_OPEN
) {
683 frrtrace(2, frr_bgp
, bmp_update_saved_open
, peer
, packet
);
685 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
687 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
689 bbpeer
->open_tx_len
= size
;
690 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
691 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
696 static int bmp_peer_status_changed(struct peer
*peer
)
698 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
699 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
701 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
706 if (peer
->status
== Deleted
) {
707 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
709 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
710 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
711 bmp_peerh_del(&bmp_peerh
, bbpeer
);
712 XFREE(MTYPE_BMP_PEER
, bbpeer
);
717 /* Check if this peer just went to Established */
718 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
721 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
722 bbpeer
= bmp_bgp_peer_get(peer
);
723 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
725 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
726 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
728 bbpeer
->open_tx
= bbdopp
->open_tx
;
729 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
730 bbpeer
->open_rx
= bbdopp
->open_rx
;
731 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
733 bmp_peerh_del(&bmp_peerh
, bbdopp
);
734 XFREE(MTYPE_BMP_PEER
, bbdopp
);
738 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
742 static int bmp_peer_backward(struct peer
*peer
)
744 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
745 struct bmp_bgp_peer
*bbpeer
;
747 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
752 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
754 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
755 bbpeer
->open_tx_len
= 0;
756 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
757 bbpeer
->open_rx_len
= 0;
760 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
764 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
767 struct listnode
*node
;
768 struct stream
*s
, *s2
;
769 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
770 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
772 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
774 s
= stream_new(BGP_MAX_PACKET_SIZE
);
776 /* Make BGP update packet. */
777 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
779 /* Unfeasible Routes Length */
782 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
783 /* Total Path Attribute Length */
786 /* Convert AFI, SAFI to values for packet. */
787 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
789 /* Total Path Attribute Length */
791 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
792 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
794 stream_putw(s
, pkt_afi
);
795 stream_putc(s
, pkt_safi
);
798 bgp_packet_set_size(s
);
800 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
801 if (!peer
->afc_nego
[afi
][safi
])
804 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
806 bmp_common_hdr(s2
, BMP_VERSION_3
,
807 BMP_TYPE_ROUTE_MONITORING
);
808 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
810 stream_putl_at(s2
, BMP_LENGTH_POS
,
811 stream_get_endp(s
) + stream_get_endp(s2
));
814 pullwr_write_stream(bmp
->pullwr
, s2
);
815 pullwr_write_stream(bmp
->pullwr
, s
);
821 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
822 struct peer
*peer
, struct attr
*attr
,
823 afi_t afi
, safi_t safi
)
825 struct bpacket_attr_vec_arr vecarr
;
827 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
828 bgp_size_t total_attr_len
= 0;
830 bpacket_attr_vec_arr_reset(&vecarr
);
832 s
= stream_new(BGP_MAX_PACKET_SIZE
);
833 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
835 /* 2: withdrawn routes length */
838 /* 3: total attributes length - attrlen_pos stores the position */
839 attrlen_pos
= stream_get_endp(s
);
842 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
844 bgp_packet_attribute(NULL
, peer
, s
, attr
, &vecarr
, NULL
, afi
,
845 safi
, peer
, NULL
, NULL
, 0, 0, 0, NULL
);
849 /* peer_cap_enhe & add-path removed */
850 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
851 stream_put_prefix(s
, p
);
853 size_t p1
= stream_get_endp(s
);
855 /* MPLS removed for now */
857 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
859 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
861 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
862 total_attr_len
+= stream_get_endp(s
) - p1
;
865 /* set the total attribute length correctly */
866 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
867 bgp_packet_set_size(s
);
871 static struct stream
*bmp_withdraw(const struct prefix
*p
,
872 struct prefix_rd
*prd
, afi_t afi
,
876 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
877 bgp_size_t total_attr_len
= 0;
878 bgp_size_t unfeasible_len
;
880 s
= stream_new(BGP_MAX_PACKET_SIZE
);
882 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
885 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
886 stream_put_prefix(s
, p
);
887 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
888 - BGP_UNFEASIBLE_LEN
;
889 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
892 attrlen_pos
= stream_get_endp(s
);
893 /* total attr length = 0 for now. reevaluate later */
895 mp_start
= stream_get_endp(s
);
896 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
898 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
900 /* Set the mp_unreach attr's length */
901 bgp_packet_mpunreach_end(s
, mplen_pos
);
903 /* Set total path attribute length. */
904 total_attr_len
= stream_get_endp(s
) - mp_start
;
905 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
908 bgp_packet_set_size(s
);
912 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
913 const struct prefix
*p
, struct prefix_rd
*prd
,
914 struct attr
*attr
, afi_t afi
, safi_t safi
,
917 struct stream
*hdr
, *msg
;
918 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
919 struct timeval uptime_real
;
921 monotime_to_realtime(&tv
, &uptime_real
);
923 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
925 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
927 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
928 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
929 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
931 stream_putl_at(hdr
, BMP_LENGTH_POS
,
932 stream_get_endp(hdr
) + stream_get_endp(msg
));
935 pullwr_write_stream(bmp
->pullwr
, hdr
);
936 pullwr_write_stream(bmp
->pullwr
, msg
);
941 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
946 if (bmp
->syncafi
== AFI_MAX
) {
947 FOREACH_AFI_SAFI (afi
, safi
) {
948 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
951 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
954 bmp
->syncsafi
= safi
;
956 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
957 bmp
->syncpos
.family
= afi2family(afi
);
958 bmp
->syncrdpos
= NULL
;
959 zlog_info("bmp[%s] %s %s sending table",
961 afi2str(bmp
->syncafi
),
962 safi2str(bmp
->syncsafi
));
963 /* break does not work here, 2 loops... */
966 if (bmp
->syncafi
== AFI_MAX
)
972 safi
= bmp
->syncsafi
;
974 if (!bmp
->targets
->afimon
[afi
][safi
]) {
975 /* shouldn't happen */
976 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
977 bmp
->syncafi
= AFI_MAX
;
978 bmp
->syncsafi
= SAFI_MAX
;
982 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
983 struct bgp_dest
*bn
= NULL
;
984 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
985 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
987 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
988 (safi
== SAFI_MPLS_VPN
)) {
989 /* initialize syncrdpos to the first
990 * mid-layer table entry
992 if (!bmp
->syncrdpos
) {
993 bmp
->syncrdpos
= bgp_table_top(table
);
998 /* look for a valid mid-layer table */
1000 table
= bgp_dest_get_bgp_table_info(bmp
->syncrdpos
);
1004 bmp
->syncrdpos
= bgp_route_next(bmp
->syncrdpos
);
1005 } while (bmp
->syncrdpos
);
1007 /* mid-layer table completed */
1008 if (!bmp
->syncrdpos
)
1012 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
1015 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
1017 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) ||
1018 (safi
== SAFI_MPLS_VPN
)) {
1019 /* reset bottom-layer pointer */
1020 memset(&bmp
->syncpos
, 0,
1021 sizeof(bmp
->syncpos
));
1022 bmp
->syncpos
.family
= afi2family(afi
);
1023 /* check whethere there is a valid
1024 * next mid-layer table, otherwise
1025 * declare table completed (eor)
1027 for (bmp
->syncrdpos
= bgp_route_next(
1030 bmp
->syncrdpos
= bgp_route_next(
1032 if (bgp_dest_get_bgp_table_info(
1037 zlog_info("bmp[%s] %s %s table completed (EoR)",
1038 bmp
->remote
, afi2str(afi
),
1040 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1041 bmp_eor(bmp
, afi
, safi
, 0);
1043 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1044 bmp
->syncafi
= AFI_MAX
;
1045 bmp
->syncsafi
= SAFI_MAX
;
1048 bmp
->syncpeerid
= 0;
1049 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1052 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1053 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1054 bpiter
= bpiter
->next
) {
1055 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1057 if (bpiter
->peer
->qobj_node
.nid
1060 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1061 > bpi
->peer
->qobj_node
.nid
)
1066 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1067 for (adjiter
= bn
->adj_in
; adjiter
;
1068 adjiter
= adjiter
->next
) {
1069 if (adjiter
->peer
->qobj_node
.nid
1072 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1073 > adjin
->peer
->qobj_node
.nid
)
1085 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1087 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1088 } else if (adjin
&& bpi
1089 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1091 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1093 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1095 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1098 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1099 struct prefix_rd
*prd
= NULL
;
1100 if (((afi
== AFI_L2VPN
) && (safi
== SAFI_EVPN
)) ||
1101 (safi
== SAFI_MPLS_VPN
))
1102 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1105 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1106 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1108 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1109 safi
, adjin
->uptime
);
1112 bgp_dest_unlock_node(bn
);
1117 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1119 struct bmp_queue_entry
*bqe
;
1121 bqe
= bmp
->queuepos
;
1125 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1128 if (!bqe
->refcount
) {
1129 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1130 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1135 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1137 struct bmp_queue_entry
*bqe
;
1139 struct bgp_dest
*bn
= NULL
;
1140 bool written
= false;
1142 bqe
= bmp_pull(bmp
);
1146 afi_t afi
= bqe
->afi
;
1147 safi_t safi
= bqe
->safi
;
1149 switch (bmp
->afistate
[afi
][safi
]) {
1150 case BMP_AFI_INACTIVE
:
1151 case BMP_AFI_NEEDSYNC
:
1154 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1155 /* currently syncing but have already passed this
1156 * prefix => send it. */
1159 /* currently syncing & haven't reached this prefix yet
1160 * => it'll be sent as part of the table sync, no need here */
1166 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1168 zlog_info("bmp: skipping queued item for deleted peer");
1171 if (!peer_established(peer
))
1174 bool is_vpn
= (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
) ||
1175 (bqe
->safi
== SAFI_MPLS_VPN
);
1177 struct prefix_rd
*prd
= is_vpn
? &bqe
->rd
: NULL
;
1178 bn
= bgp_afi_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], afi
, safi
,
1182 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1183 struct bgp_path_info
*bpi
;
1185 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1187 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1189 if (bpi
->peer
== peer
)
1193 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1194 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1195 bpi
? bpi
->uptime
: monotime(NULL
));
1199 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1200 struct bgp_adj_in
*adjin
;
1202 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1203 adjin
= adjin
->next
) {
1204 if (adjin
->peer
== peer
)
1207 bmp_monitor(bmp
, peer
, 0, &bqe
->p
, prd
,
1208 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1209 adjin
? adjin
->uptime
: monotime(NULL
));
1215 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1218 bgp_dest_unlock_node(bn
);
1223 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1225 switch(bmp
->state
) {
1227 bmp_send_peerup(bmp
);
1228 bmp
->state
= BMP_Run
;
1232 if (bmp_wrmirror(bmp
, pullwr
))
1234 if (bmp_wrqueue(bmp
, pullwr
))
1236 if (bmp_wrsync(bmp
, pullwr
))
1242 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1245 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1247 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1248 bmp
->remote
, strerror(errno
));
1254 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1255 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1258 struct bmp_queue_entry
*bqe
, bqeref
;
1261 refcount
= bmp_session_count(&bt
->sessions
);
1265 memset(&bqeref
, 0, sizeof(bqeref
));
1266 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1267 bqeref
.peerid
= peer
->qobj_node
.nid
;
1271 if ((afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
) ||
1272 (safi
== SAFI_MPLS_VPN
))
1273 prefix_copy(&bqeref
.rd
,
1274 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1276 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1278 if (bqe
->refcount
>= refcount
)
1279 /* nothing to do here */
1282 bmp_qlist_del(&bt
->updlist
, bqe
);
1284 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1285 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1287 bmp_qhash_add(&bt
->updhash
, bqe
);
1290 bqe
->refcount
= refcount
;
1291 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1293 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1295 bmp
->queuepos
= bqe
;
1298 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1299 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1301 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1302 struct bmp_targets
*bt
;
1305 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1306 char pfxprint
[PREFIX2STR_BUFFER
];
1308 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1309 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1316 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1317 if (!bt
->afimon
[afi
][safi
])
1320 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1322 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1323 pullwr_bump(bmp
->pullwr
);
1329 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1332 stream_putw(s
, type
);
1334 stream_putl(s
, value
);
1338 static void bmp_stats(struct thread
*thread
)
1340 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1343 struct listnode
*node
;
1347 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1350 gettimeofday(&tv
, NULL
);
1352 /* Walk down all peers */
1353 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1354 size_t count
= 0, count_pos
, len
;
1356 if (!peer_established(peer
))
1359 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1360 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1361 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1363 count_pos
= stream_get_endp(s
);
1366 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1367 peer
->stat_pfx_filter
);
1368 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1369 peer
->stat_pfx_aspath_loop
);
1370 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1371 peer
->stat_pfx_originator_loop
);
1372 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1373 peer
->stat_pfx_cluster_loop
);
1374 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1375 peer
->stat_pfx_dup_withdraw
);
1376 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1377 peer
->stat_upd_7606
);
1378 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1379 peer
->stat_pfx_nh_invalid
);
1381 stream_putl_at(s
, count_pos
, count
);
1383 len
= stream_get_endp(s
);
1384 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1386 bmp_send_all(bt
->bmpbgp
, s
);
1390 /* read from the BMP socket to detect session termination */
1391 static void bmp_read(struct thread
*t
)
1393 struct bmp
*bmp
= THREAD_ARG(t
);
1399 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1401 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1402 } else if (n
== 0) {
1403 /* the TCP session was terminated by the far end */
1404 bmp_wrerr(bmp
, NULL
, true);
1406 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1407 /* the TCP session experienced a fatal error, likely a timeout */
1408 bmp_wrerr(bmp
, NULL
, false);
1412 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1415 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1417 union sockunion su
, *sumem
;
1420 struct access_list
*acl
= NULL
;
1421 enum filter_type ret
;
1422 char buf
[SU_ADDRSTRLEN
];
1425 sumem
= sockunion_getpeername(bmp_sock
);
1430 memcpy(&su
, sumem
, sizeof(su
));
1431 sockunion_free(sumem
);
1433 set_nonblocking(bmp_sock
);
1434 set_cloexec(bmp_sock
);
1436 if (!sockunion2hostprefix(&su
, &p
)) {
1444 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1447 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1453 ret
= FILTER_PERMIT
;
1455 ret
= access_list_apply(acl
, &p
);
1458 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1459 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1460 su
.sa
.sa_family
== AF_INET
1461 ? ntohs(su
.sin
.sin_port
)
1462 : ntohs(su
.sin6
.sin6_port
));
1464 if (ret
== FILTER_DENY
) {
1465 bt
->cnt_aclrefused
++;
1466 zlog_info("bmp[%s] connection refused by access-list", buf
);
1472 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1473 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1474 bmp_sock
, safe_strerror(errno
), errno
);
1475 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1476 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1477 bmp_sock
, safe_strerror(errno
), errno
);
1479 zlog_info("bmp[%s] connection established", buf
);
1481 /* Allocate new BMP structure and set up default values. */
1482 bmp
= bmp_new(bt
, bmp_sock
);
1483 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1485 bmp
->state
= BMP_PeerUp
;
1486 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1488 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1489 bmp_send_initiation(bmp
);
1494 /* Accept BMP connection. */
1495 static void bmp_accept(struct thread
*thread
)
1498 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1501 /* We continue hearing BMP socket. */
1502 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1504 memset(&su
, 0, sizeof(union sockunion
));
1506 /* We can handle IPv4 or IPv6 socket. */
1507 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1509 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1512 bmp_open(bl
->targets
, bmp_sock
);
1515 static void bmp_close(struct bmp
*bmp
)
1517 struct bmp_queue_entry
*bqe
;
1518 struct bmp_mirrorq
*bmq
;
1520 THREAD_OFF(bmp
->t_read
);
1523 bmp_active_disconnected(bmp
->active
);
1525 while ((bmq
= bmp_pull_mirror(bmp
)))
1527 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1528 while ((bqe
= bmp_pull(bmp
)))
1530 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1532 THREAD_OFF(bmp
->t_read
);
1533 pullwr_del(bmp
->pullwr
);
1537 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1539 struct bmp_bgp dummy
= { .bgp
= bgp
};
1540 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1543 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1545 struct bmp_bgp
*bmpbgp
;
1547 bmpbgp
= bmp_bgp_find(bgp
);
1551 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1553 bmpbgp
->mirror_qsizelimit
= ~0UL;
1554 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1555 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1560 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1562 struct bmp_targets
*bt
;
1563 struct bmp_listener
*bl
;
1565 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1567 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, bt
) {
1568 frr_each_safe (bmp_listeners
, &bt
->listeners
, bl
)
1569 bmp_listener_put(bl
);
1571 bmp_targets_put(bt
);
1574 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1575 XFREE(MTYPE_BMP
, bmpbgp
);
1578 static int bmp_bgp_del(struct bgp
*bgp
)
1580 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1583 bmp_bgp_put(bmpbgp
);
1587 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1589 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1590 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1593 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1595 struct bmp_bgp_peer
*bbpeer
;
1597 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1601 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1602 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1603 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1608 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1610 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1611 struct bmp_targets dummy
;
1615 dummy
.name
= (char *)name
;
1616 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1619 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1621 struct bmp_targets
*bt
;
1623 bt
= bmp_targets_find1(bgp
, name
);
1627 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1628 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1630 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1631 bmp_session_init(&bt
->sessions
);
1632 bmp_qhash_init(&bt
->updhash
);
1633 bmp_qlist_init(&bt
->updlist
);
1634 bmp_actives_init(&bt
->actives
);
1635 bmp_listeners_init(&bt
->listeners
);
1637 QOBJ_REG(bt
, bmp_targets
);
1638 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1642 static void bmp_targets_put(struct bmp_targets
*bt
)
1645 struct bmp_active
*ba
;
1647 THREAD_OFF(bt
->t_stats
);
1649 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1652 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1657 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1660 bmp_listeners_fini(&bt
->listeners
);
1661 bmp_actives_fini(&bt
->actives
);
1662 bmp_qhash_fini(&bt
->updhash
);
1663 bmp_qlist_fini(&bt
->updlist
);
1665 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1666 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1667 bmp_session_fini(&bt
->sessions
);
1669 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1670 XFREE(MTYPE_BMP_TARGETS
, bt
);
1673 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1674 const union sockunion
*su
,
1677 struct bmp_listener dummy
;
1680 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1683 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1684 const union sockunion
*su
,
1687 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1692 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1698 bmp_listeners_add(&bt
->listeners
, bl
);
1702 static void bmp_listener_start(struct bmp_listener
*bl
)
1706 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1710 sockopt_reuseaddr(sock
);
1711 sockopt_reuseport(sock
);
1712 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1715 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1719 ret
= listen(sock
, 3);
1724 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1730 static void bmp_listener_stop(struct bmp_listener
*bl
)
1732 THREAD_OFF(bl
->t_accept
);
1739 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1740 const char *hostname
, int port
)
1742 struct bmp_active dummy
;
1743 dummy
.hostname
= (char *)hostname
;
1745 return bmp_actives_find(&bt
->actives
, &dummy
);
1748 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1749 const char *hostname
, int port
)
1751 struct bmp_active
*ba
;
1753 ba
= bmp_active_find(bt
, hostname
, port
);
1757 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1759 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1761 ba
->minretry
= BMP_DFLT_MINRETRY
;
1762 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1765 bmp_actives_add(&bt
->actives
, ba
);
1769 static void bmp_active_put(struct bmp_active
*ba
)
1771 THREAD_OFF(ba
->t_timer
);
1772 THREAD_OFF(ba
->t_read
);
1773 THREAD_OFF(ba
->t_write
);
1775 bmp_actives_del(&ba
->targets
->actives
, ba
);
1778 ba
->bmp
->active
= NULL
;
1782 if (ba
->socket
!= -1)
1785 XFREE(MTYPE_TMP
, ba
->ifsrc
);
1786 XFREE(MTYPE_TMP
, ba
->hostname
);
1787 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1790 static void bmp_active_setup(struct bmp_active
*ba
);
1792 static void bmp_active_connect(struct bmp_active
*ba
)
1794 enum connect_result res
;
1795 struct interface
*ifp
;
1796 vrf_id_t vrf_id
= VRF_DEFAULT
;
1799 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1801 if (ba
->targets
&& ba
->targets
->bgp
)
1802 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1804 /* find interface and related */
1805 /* address with same family */
1806 ifp
= if_lookup_by_name(ba
->ifsrc
, vrf_id
);
1808 zlog_warn("bmp[%s]: failed to find interface",
1813 if (bgp_update_address(ifp
, &ba
->addrs
[ba
->addrpos
],
1815 zlog_warn("bmp[%s]: failed to find matching address",
1819 zlog_info("bmp[%s]: selected source address : %pSU",
1820 ba
->ifsrc
, &ba
->addrsrc
);
1823 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1824 if (ba
->socket
< 0) {
1825 zlog_warn("bmp[%s]: failed to create socket",
1830 set_nonblocking(ba
->socket
);
1832 if (!sockunion_is_null(&ba
->addrsrc
)) {
1833 res_bind
= sockunion_bind(ba
->socket
, &ba
->addrsrc
, 0,
1837 "bmp[%s]: no bind currently to source address %pSU:%d",
1838 ba
->hostname
, &ba
->addrsrc
, ba
->port
);
1841 sockunion_init(&ba
->addrsrc
);
1847 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1848 htons(ba
->port
), 0);
1851 zlog_warn("bmp[%s]: failed to connect to %pSU:%d",
1852 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1856 sockunion_init(&ba
->addrsrc
);
1858 case connect_success
:
1859 zlog_info("bmp[%s]: connected to %pSU:%d",
1860 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1863 case connect_in_progress
:
1864 zlog_warn("bmp[%s]: connect in progress %pSU:%d",
1865 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1867 bmp_active_setup(ba
);
1872 /* exhausted all addresses */
1873 ba
->curretry
+= ba
->curretry
/ 2;
1874 bmp_active_setup(ba
);
1877 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1878 int numaddrs
, union sockunion
*addr
)
1880 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1883 if (numaddrs
<= 0) {
1884 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1885 ba
->hostname
, errstr
);
1886 ba
->last_err
= errstr
;
1887 ba
->curretry
+= ba
->curretry
/ 2;
1890 bmp_active_setup(ba
);
1894 if (numaddrs
> (int)array_size(ba
->addrs
))
1895 numaddrs
= array_size(ba
->addrs
);
1898 ba
->addrtotal
= numaddrs
;
1899 for (i
= 0; i
< ba
->addrtotal
; i
++)
1900 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1902 bmp_active_connect(ba
);
1905 static void bmp_active_thread(struct thread
*t
)
1907 struct bmp_active
*ba
= THREAD_ARG(t
);
1912 /* all 3 end up here, though only timer or read+write are active
1914 THREAD_OFF(ba
->t_timer
);
1915 THREAD_OFF(ba
->t_read
);
1916 THREAD_OFF(ba
->t_write
);
1918 ba
->last_err
= NULL
;
1920 if (ba
->socket
== -1) {
1922 if (!ba
->targets
|| !ba
->targets
->bgp
)
1923 vrf_id
= VRF_DEFAULT
;
1925 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1926 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1927 bmp_active_resolved
);
1931 slen
= sizeof(status
);
1932 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1935 if (ret
< 0 || status
!= 0) {
1936 ba
->last_err
= strerror(status
);
1937 zlog_warn("bmp[%s]: failed to connect to %pSU:%d: %s",
1938 ba
->hostname
, &ba
->addrs
[ba
->addrpos
], ba
->port
,
1943 zlog_warn("bmp[%s]: outbound connection to %pSU:%d", ba
->hostname
,
1944 &ba
->addrs
[ba
->addrpos
], ba
->port
);
1946 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1950 ba
->bmp
->active
= ba
;
1952 ba
->curretry
= ba
->minretry
;
1959 bmp_active_connect(ba
);
1962 static void bmp_active_disconnected(struct bmp_active
*ba
)
1965 bmp_active_setup(ba
);
1968 static void bmp_active_setup(struct bmp_active
*ba
)
1970 THREAD_OFF(ba
->t_timer
);
1971 THREAD_OFF(ba
->t_read
);
1972 THREAD_OFF(ba
->t_write
);
1976 if (ba
->resq
.callback
)
1979 if (ba
->curretry
> ba
->maxretry
)
1980 ba
->curretry
= ba
->maxretry
;
1982 if (ba
->socket
== -1)
1983 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1984 ba
->curretry
, &ba
->t_timer
);
1986 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1988 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1993 static struct cmd_node bmp_node
= {
1996 .parent_node
= BGP_NODE
,
1997 .prompt
= "%s(config-bgp-bmp)# "
2000 static void bmp_targets_autocomplete(vector comps
, struct cmd_token
*token
)
2003 struct bmp_targets
*target
;
2004 struct listnode
*node
;
2006 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
2007 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2012 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, target
)
2014 XSTRDUP(MTYPE_COMPLETION
, target
->name
));
2018 static const struct cmd_variable_handler bmp_targets_var_handlers
[] = {
2019 {.tokenname
= "BMPTARGETS", .completions
= bmp_targets_autocomplete
},
2020 {.completions
= NULL
}};
2022 #define BMP_STR "BGP Monitoring Protocol\n"
2024 #include "bgpd/bgp_bmp_clippy.c"
2026 DEFPY_NOSH(bmp_targets_main
,
2028 "bmp targets BMPTARGETS",
2030 "Create BMP target group\n"
2031 "Name of the BMP target group\n")
2033 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2034 struct bmp_targets
*bt
;
2036 bt
= bmp_targets_get(bgp
, bmptargets
);
2038 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
2042 DEFPY(no_bmp_targets_main
,
2044 "no bmp targets BMPTARGETS",
2047 "Delete BMP target group\n"
2048 "Name of the BMP target group\n")
2050 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2051 struct bmp_targets
*bt
;
2053 bt
= bmp_targets_find1(bgp
, bmptargets
);
2055 vty_out(vty
, "%% BMP target group not found\n");
2058 bmp_targets_put(bt
);
2062 DEFPY(bmp_listener_main
,
2064 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2066 "Listen for inbound BMP connections\n"
2067 "IPv6 address to listen on\n"
2068 "IPv4 address to listen on\n"
2070 "TCP Port number\n")
2072 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2073 struct bmp_listener
*bl
;
2075 bl
= bmp_listener_get(bt
, listener
, port
);
2077 bmp_listener_start(bl
);
2082 DEFPY(no_bmp_listener_main
,
2083 no_bmp_listener_cmd
,
2084 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2087 "Create BMP listener\n"
2088 "IPv6 address to listen on\n"
2089 "IPv4 address to listen on\n"
2091 "TCP Port number\n")
2093 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2094 struct bmp_listener
*bl
;
2096 bl
= bmp_listener_find(bt
, listener
, port
);
2098 vty_out(vty
, "%% BMP listener not found\n");
2101 bmp_listener_stop(bl
);
2102 bmp_listener_put(bl
);
2108 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
2111 "Actively establish connection to monitoring station\n"
2112 "Monitoring station hostname or address\n"
2115 "Minimum connection retry interval\n"
2116 "Minimum connection retry interval (milliseconds)\n"
2117 "Maximum connection retry interval\n"
2118 "Maximum connection retry interval (milliseconds)\n"
2119 "Source interface to use\n"
2120 "Define an interface\n")
2122 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2123 struct bmp_active
*ba
;
2126 ba
= bmp_active_find(bt
, hostname
, port
);
2128 vty_out(vty
, "%% No such active connection found\n");
2131 /* connection deletion need same hostname port and interface */
2132 if (ba
->ifsrc
|| srcif
)
2133 if ((!ba
->ifsrc
) || (!srcif
) ||
2134 !strcmp(ba
->ifsrc
, srcif
)) {
2136 "%% No such active connection found\n");
2143 ba
= bmp_active_get(bt
, hostname
, port
);
2145 ba
->ifsrc
= XSTRDUP(MTYPE_TMP
, srcif
);
2147 ba
->minretry
= min_retry
;
2149 ba
->maxretry
= max_retry
;
2150 ba
->curretry
= ba
->minretry
;
2151 bmp_active_setup(ba
);
2158 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2162 "Access list to restrict BMP sessions\n"
2163 "Access list name\n")
2165 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2170 if (!strcmp(af
, "ipv6"))
2171 what
= &bt
->acl6_name
;
2173 what
= &bt
->acl_name
;
2175 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2177 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2182 DEFPY(bmp_stats_cfg
,
2184 "[no] bmp stats [interval (100-86400000)]",
2187 "Send BMP statistics messages\n"
2188 "Specify BMP stats interval\n"
2189 "Interval (milliseconds) to send BMP Stats in\n")
2191 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2193 THREAD_OFF(bt
->t_stats
);
2196 else if (interval_str
)
2197 bt
->stat_msec
= interval
;
2199 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2202 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2207 DEFPY(bmp_monitor_cfg
,
2209 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn|vpn> <pre-policy|post-policy>$policy",
2212 "Send BMP route monitoring messages\n"
2220 "Send state before policy and filter processing\n"
2221 "Send state with policy and filters applied\n")
2228 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2231 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2232 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2234 if (policy
[1] == 'r')
2235 flag
= BMP_MON_PREPOLICY
;
2237 flag
= BMP_MON_POSTPOLICY
;
2239 prev
= bt
->afimon
[afi
][safi
];
2241 bt
->afimon
[afi
][safi
] &= ~flag
;
2243 bt
->afimon
[afi
][safi
] |= flag
;
2245 if (prev
== bt
->afimon
[afi
][safi
])
2248 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2249 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2250 bmp
->syncafi
= AFI_MAX
;
2251 bmp
->syncsafi
= SAFI_MAX
;
2254 if (!bt
->afimon
[afi
][safi
]) {
2255 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2259 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2265 DEFPY(bmp_mirror_cfg
,
2270 "Send BMP route mirroring messages\n")
2272 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2275 if (bt
->mirror
== !no
)
2282 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2283 struct bmp_mirrorq
*bmq
;
2285 while ((bmq
= bmp_pull_mirror(bmp
)))
2287 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2292 DEFPY(bmp_mirror_limit_cfg
,
2293 bmp_mirror_limit_cmd
,
2294 "bmp mirror buffer-limit (0-4294967294)",
2296 "Route Mirroring settings\n"
2297 "Configure maximum memory used for buffered mirroring messages\n"
2300 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2301 struct bmp_bgp
*bmpbgp
;
2303 bmpbgp
= bmp_bgp_get(bgp
);
2304 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2309 DEFPY(no_bmp_mirror_limit_cfg
,
2310 no_bmp_mirror_limit_cmd
,
2311 "no bmp mirror buffer-limit [(0-4294967294)]",
2314 "Route Mirroring settings\n"
2315 "Configure maximum memory used for buffered mirroring messages\n"
2318 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2319 struct bmp_bgp
*bmpbgp
;
2321 bmpbgp
= bmp_bgp_get(bgp
);
2322 bmpbgp
->mirror_qsizelimit
= ~0UL;
2334 struct bmp_bgp
*bmpbgp
;
2335 struct bmp_targets
*bt
;
2336 struct bmp_listener
*bl
;
2337 struct bmp_active
*ba
;
2340 char uptime
[BGP_UPTIME_LEN
];
2343 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2344 vty_out(vty
, "BMP state for BGP %s:\n\n",
2345 bmpbgp
->bgp
->name_pretty
);
2346 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2347 bmpbgp
->mirror_qsize
,
2348 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2349 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2350 bmpbgp
->mirror_qsizemax
);
2351 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2352 vty_out(vty
, " %9zu bytes buffer size limit\n",
2353 bmpbgp
->mirror_qsizelimit
);
2356 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2357 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2358 vty_out(vty
, " Route Mirroring %sabled\n",
2359 bt
->mirror
? "en" : "dis");
2364 FOREACH_AFI_SAFI (afi
, safi
) {
2365 const char *str
= NULL
;
2367 switch (bt
->afimon
[afi
][safi
]) {
2368 case BMP_MON_PREPOLICY
:
2371 case BMP_MON_POSTPOLICY
:
2372 str
= "post-policy";
2374 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2375 str
= "pre-policy and post-policy";
2380 vty_out(vty
, " Route Monitoring %s %s %s\n",
2381 afi2str(afi
), safi2str(safi
), str
);
2384 vty_out(vty
, " Listeners:\n");
2385 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2386 vty_out(vty
, " %pSU:%d\n", &bl
->addr
,
2389 vty_out(vty
, "\n Outbound connections:\n");
2390 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2391 ttable_add_row(tt
, "remote|state||timer|local");
2392 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2393 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2394 const char *state_str
= "?";
2397 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2398 uptime
, sizeof(uptime
),
2401 "%s:%d|Up|%s|%s|%pSU",
2402 ba
->hostname
, ba
->port
,
2403 ba
->bmp
->remote
, uptime
,
2411 long trem
= thread_timer_remain_second(
2414 peer_uptime(monotime(NULL
) - trem
,
2415 uptime
, sizeof(uptime
),
2417 state_str
= "RetryWait";
2418 } else if (ba
->t_read
) {
2419 state_str
= "Connecting";
2420 } else if (ba
->resq
.callback
) {
2421 state_str
= "Resolving";
2424 ttable_add_row(tt
, "%s:%d|%s|%s|%s|%pSU",
2425 ba
->hostname
, ba
->port
,
2427 ba
->last_err
? ba
->last_err
: "",
2428 uptime
, &ba
->addrsrc
);
2431 out
= ttable_dump(tt
, "\n");
2432 vty_out(vty
, "%s", out
);
2433 XFREE(MTYPE_TMP
, out
);
2436 vty_out(vty
, "\n %zu connected clients:\n",
2437 bmp_session_count(&bt
->sessions
));
2438 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2439 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2440 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2442 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2446 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2448 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2449 sizeof(uptime
), false, NULL
);
2451 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2452 bmp
->remote
, uptime
,
2455 bmp
->cnt_mirror_overruns
,
2458 out
= ttable_dump(tt
, "\n");
2459 vty_out(vty
, "%s", out
);
2460 XFREE(MTYPE_TMP
, out
);
2469 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2471 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2472 struct bmp_targets
*bt
;
2473 struct bmp_listener
*bl
;
2474 struct bmp_active
*ba
;
2481 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2482 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2483 bmpbgp
->mirror_qsizelimit
);
2485 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2486 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2489 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2491 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2494 vty_out(vty
, " bmp stats interval %d\n",
2498 vty_out(vty
, " bmp mirror\n");
2500 FOREACH_AFI_SAFI (afi
, safi
) {
2501 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2503 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2504 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2505 afi_str
, safi2str(safi
));
2506 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2507 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2508 afi_str
, safi2str(safi
));
2510 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2511 vty_out(vty
, " \n bmp listener %pSU port %d\n",
2512 &bl
->addr
, bl
->port
);
2514 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2515 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u",
2516 ba
->hostname
, ba
->port
,
2517 ba
->minretry
, ba
->maxretry
);
2520 vty_out(vty
, " source-interface %s\n", ba
->ifsrc
);
2524 vty_out(vty
, " exit\n");
2530 static int bgp_bmp_init(struct thread_master
*tm
)
2532 install_node(&bmp_node
);
2533 install_default(BMP_NODE
);
2535 cmd_variable_handler_register(bmp_targets_var_handlers
);
2537 install_element(BGP_NODE
, &bmp_targets_cmd
);
2538 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2540 install_element(BMP_NODE
, &bmp_listener_cmd
);
2541 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2542 install_element(BMP_NODE
, &bmp_connect_cmd
);
2543 install_element(BMP_NODE
, &bmp_acl_cmd
);
2544 install_element(BMP_NODE
, &bmp_stats_cmd
);
2545 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2546 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2548 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2549 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2551 install_element(VIEW_NODE
, &show_bmp_cmd
);
2557 static int bgp_bmp_module_init(void)
2559 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2560 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2561 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2562 hook_register(peer_backward_transition
, bmp_peer_backward
);
2563 hook_register(bgp_process
, bmp_process
);
2564 hook_register(bgp_inst_config_write
, bmp_config_write
);
2565 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2566 hook_register(frr_late_init
, bgp_bmp_init
);
2570 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2571 .description
= "bgpd BMP module",
2572 .init
= bgp_bmp_module_init
,