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 ret
= prefix_cmp(&a
->p
, &b
->p
);
174 ret
= memcmp(&a
->peerid
, &b
->peerid
,
175 offsetof(struct bmp_queue_entry
, refcount
) -
176 offsetof(struct bmp_queue_entry
, peerid
));
180 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
184 key
= prefix_hash_key((void *)&e
->p
);
185 key
= jhash(&e
->peerid
,
186 offsetof(struct bmp_queue_entry
, refcount
)
187 - offsetof(struct bmp_queue_entry
, peerid
),
189 if (e
->afi
== AFI_L2VPN
&& e
->safi
== SAFI_EVPN
)
191 offsetof(struct bmp_queue_entry
, rd
)
192 - offsetof(struct bmp_queue_entry
, refcount
)
193 + PSIZE(e
->rd
.prefixlen
),
199 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
200 bmp_qhash_cmp
, bmp_qhash_hkey
);
202 static int bmp_active_cmp(const struct bmp_active
*a
,
203 const struct bmp_active
*b
)
207 c
= strcmp(a
->hostname
, b
->hostname
);
210 if (a
->port
< b
->port
)
212 if (a
->port
> b
->port
)
217 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
);
219 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
221 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
225 monotime(&new->t_up
);
227 new->socket
= bmp_sock
;
228 new->syncafi
= AFI_MAX
;
230 FOREACH_AFI_SAFI (afi
, safi
) {
231 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
232 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
235 bmp_session_add_tail(&bt
->sessions
, new);
239 static void bmp_free(struct bmp
*bmp
)
241 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
242 XFREE(MTYPE_BMP_CONN
, bmp
);
245 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
248 stream_putl(s
, 0); //dummy message length. will be set later.
249 stream_putc(s
, type
);
252 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
253 uint8_t flags
, const struct timeval
*tv
)
255 char peer_distinguisher
[8];
257 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
258 #define BMP_PEER_TYPE_RD_INSTANCE 1
259 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
261 #define BMP_PEER_FLAG_V (1 << 7)
262 #define BMP_PEER_FLAG_L (1 << 6)
263 #define BMP_PEER_FLAG_A (1 << 5)
266 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
269 if (peer
->su
.sa
.sa_family
== AF_INET6
)
270 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
272 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
273 stream_putc(s
, flags
);
275 /* Peer Distinguisher */
276 memset (&peer_distinguisher
[0], 0, 8);
277 stream_put(s
, &peer_distinguisher
[0], 8);
280 if (peer
->su
.sa
.sa_family
== AF_INET6
)
281 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
282 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
286 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
295 stream_putl(s
, peer
->as
);
298 stream_put_in_addr(s
, &peer
->remote_id
);
302 stream_putl(s
, tv
->tv_sec
);
303 stream_putl(s
, tv
->tv_usec
);
310 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
313 int len
= strlen (string
);
314 stream_putw(s
, type
);
316 stream_put(s
, string
, len
);
319 static int bmp_send_initiation(struct bmp
*bmp
)
323 s
= stream_new(BGP_MAX_PACKET_SIZE
);
324 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
326 #define BMP_INFO_TYPE_SYSDESCR 1
327 #define BMP_INFO_TYPE_SYSNAME 2
328 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
329 FRR_FULL_NAME
" " FRR_VER_SHORT
);
330 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
332 len
= stream_get_endp(s
);
333 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
335 pullwr_write_stream(bmp
->pullwr
, s
);
340 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
343 uint8_t marker
[16] = {
344 0xff, 0xff, 0xff, 0xff,
345 0xff, 0xff, 0xff, 0xff,
346 0xff, 0xff, 0xff, 0xff,
347 0xff, 0xff, 0xff, 0xff,
350 stream_put(s
, marker
, sizeof(marker
));
351 len_pos
= stream_get_endp(s
);
353 stream_putc(s
, BGP_MSG_NOTIFY
);
354 stream_putc(s
, nfy
->code
);
355 stream_putc(s
, nfy
->subcode
);
356 stream_put(s
, nfy
->data
, nfy
->length
);
358 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
362 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
366 struct timeval uptime
, uptime_real
;
368 uptime
.tv_sec
= peer
->uptime
;
370 monotime_to_realtime(&uptime
, &uptime_real
);
372 #define BGP_BMP_MAX_PACKET_SIZE 1024
373 s
= stream_new(BGP_MAX_PACKET_SIZE
);
375 if (peer_established(peer
) && !down
) {
376 struct bmp_bgp_peer
*bbpeer
;
378 bmp_common_hdr(s
, BMP_VERSION_3
,
379 BMP_TYPE_PEER_UP_NOTIFICATION
);
380 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
382 /* Local Address (16 bytes) */
383 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
384 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
385 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
389 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
392 /* Local Port, Remote Port */
393 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
394 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
395 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
396 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
397 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
398 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
399 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
400 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
402 static const uint8_t dummy_open
[] = {
403 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
404 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
408 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
410 if (bbpeer
&& bbpeer
->open_tx
)
411 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
413 stream_put(s
, dummy_open
, sizeof(dummy_open
));
414 zlog_warn("bmp: missing TX OPEN message for peer %s",
417 if (bbpeer
&& bbpeer
->open_rx
)
418 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
420 stream_put(s
, dummy_open
, sizeof(dummy_open
));
421 zlog_warn("bmp: missing RX OPEN message for peer %s",
426 bmp_put_info_tlv(s
, 0, peer
->desc
);
431 bmp_common_hdr(s
, BMP_VERSION_3
,
432 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
433 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
435 type_pos
= stream_get_endp(s
);
436 stream_putc(s
, 0); /* placeholder for down reason */
438 switch (peer
->last_reset
) {
439 case PEER_DOWN_NOTIFY_RECEIVED
:
440 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
441 bmp_notify_put(s
, &peer
->notify
);
443 case PEER_DOWN_CLOSE_SESSION
:
444 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
446 case PEER_DOWN_WAITING_NHT
:
447 type
= BMP_PEERDOWN_LOCAL_FSM
;
448 stream_putw(s
, BGP_FSM_TcpConnectionFails
);
451 * TODO: Map remaining PEER_DOWN_* reasons to RFC event codes.
452 * TODO: Implement BMP_PEERDOWN_LOCAL_NOTIFY.
454 * See RFC7854 ss. 4.9
457 type
= BMP_PEERDOWN_LOCAL_FSM
;
458 stream_putw(s
, BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE
);
461 stream_putc_at(s
, type_pos
, type
);
464 len
= stream_get_endp(s
);
465 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
470 static int bmp_send_peerup(struct bmp
*bmp
)
473 struct listnode
*node
;
476 /* Walk down all peers */
477 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
478 s
= bmp_peerstate(peer
, false);
479 pullwr_write_stream(bmp
->pullwr
, s
);
486 /* XXX: kludge - filling the pullwr's buffer */
487 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
489 struct bmp_targets
*bt
;
492 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
493 frr_each(bmp_session
, &bt
->sessions
, bmp
)
494 pullwr_write_stream(bmp
->pullwr
, s
);
502 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
503 #define BMP_MIRROR_TLV_TYPE_INFO 1
505 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
506 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
508 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
510 struct bmp_mirrorq
*bmq
;
512 bmq
= bmp
->mirrorpos
;
516 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
519 if (!bmq
->refcount
) {
520 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
521 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
526 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
528 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
529 struct bmp_mirrorq
*bmq
, *inner
;
530 struct bmp_targets
*bt
;
533 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
535 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
538 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
539 if (bmp
->mirrorpos
!= bmq
)
542 while ((inner
= bmp_pull_mirror(bmp
))) {
543 if (!inner
->refcount
)
544 XFREE(MTYPE_BMP_MIRRORQ
,
548 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
550 bmp
->mirror_lost
= true;
551 pullwr_bump(bmp
->pullwr
);
557 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
558 struct stream
*packet
)
560 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
562 struct bmp_mirrorq
*qitem
;
563 struct bmp_targets
*bt
;
566 frrtrace(3, frr_bgp
, bmp_mirror_packet
, peer
, type
, packet
);
568 gettimeofday(&tv
, NULL
);
570 if (type
== BGP_MSG_OPEN
) {
571 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
573 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
575 bbpeer
->open_rx_len
= size
;
576 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
577 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
583 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
584 qitem
->peerid
= peer
->qobj_node
.nid
;
587 memcpy(qitem
->data
, packet
->data
, size
);
589 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
592 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
595 bmp
->mirrorpos
= qitem
;
596 pullwr_bump(bmp
->pullwr
);
599 if (qitem
->refcount
== 0)
600 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
602 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
603 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
605 bmp_mirror_cull(bmpbgp
);
607 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
608 bmpbgp
->mirror_qsize
);
613 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
618 gettimeofday(&tv
, NULL
);
620 s
= stream_new(BGP_MAX_PACKET_SIZE
);
622 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
623 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
625 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
627 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
628 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
630 bmp
->cnt_mirror_overruns
++;
631 pullwr_write_stream(bmp
->pullwr
, s
);
635 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
637 struct bmp_mirrorq
*bmq
;
639 bool written
= false;
641 if (bmp
->mirror_lost
) {
642 bmp_wrmirror_lost(bmp
, pullwr
);
643 bmp
->mirror_lost
= false;
647 bmq
= bmp_pull_mirror(bmp
);
651 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
653 zlog_info("bmp: skipping mirror message for deleted peer");
658 s
= stream_new(BGP_MAX_PACKET_SIZE
);
660 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
661 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
663 /* BMP Mirror TLV. */
664 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
665 stream_putw(s
, bmq
->len
);
666 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
669 pullwr_write_stream(bmp
->pullwr
, s
);
670 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
677 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
681 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
682 struct stream
*packet
)
684 if (type
== BGP_MSG_OPEN
) {
685 frrtrace(2, frr_bgp
, bmp_update_saved_open
, peer
, packet
);
687 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
689 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
691 bbpeer
->open_tx_len
= size
;
692 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
693 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
698 static int bmp_peer_status_changed(struct peer
*peer
)
700 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
701 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
703 frrtrace(1, frr_bgp
, bmp_peer_status_changed
, peer
);
708 if (peer
->status
== Deleted
) {
709 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
711 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
712 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
713 bmp_peerh_del(&bmp_peerh
, bbpeer
);
714 XFREE(MTYPE_BMP_PEER
, bbpeer
);
719 /* Check if this peer just went to Established */
720 if ((peer
->ostatus
!= OpenConfirm
) || !(peer_established(peer
)))
723 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
724 bbpeer
= bmp_bgp_peer_get(peer
);
725 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
727 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
728 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
730 bbpeer
->open_tx
= bbdopp
->open_tx
;
731 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
732 bbpeer
->open_rx
= bbdopp
->open_rx
;
733 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
735 bmp_peerh_del(&bmp_peerh
, bbdopp
);
736 XFREE(MTYPE_BMP_PEER
, bbdopp
);
740 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
744 static int bmp_peer_backward(struct peer
*peer
)
746 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
747 struct bmp_bgp_peer
*bbpeer
;
749 frrtrace(1, frr_bgp
, bmp_peer_backward_transition
, peer
);
754 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
756 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
757 bbpeer
->open_tx_len
= 0;
758 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
759 bbpeer
->open_rx_len
= 0;
762 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
766 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
769 struct listnode
*node
;
770 struct stream
*s
, *s2
;
771 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
772 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
774 frrtrace(3, frr_bgp
, bmp_eor
, afi
, safi
, flags
);
776 s
= stream_new(BGP_MAX_PACKET_SIZE
);
778 /* Make BGP update packet. */
779 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
781 /* Unfeasible Routes Length */
784 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
785 /* Total Path Attribute Length */
788 /* Convert AFI, SAFI to values for packet. */
789 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
791 /* Total Path Attribute Length */
793 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
794 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
796 stream_putw(s
, pkt_afi
);
797 stream_putc(s
, pkt_safi
);
800 bgp_packet_set_size(s
);
802 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
803 if (!peer
->afc_nego
[afi
][safi
])
806 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
808 bmp_common_hdr(s2
, BMP_VERSION_3
,
809 BMP_TYPE_ROUTE_MONITORING
);
810 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
812 stream_putl_at(s2
, BMP_LENGTH_POS
,
813 stream_get_endp(s
) + stream_get_endp(s2
));
816 pullwr_write_stream(bmp
->pullwr
, s2
);
817 pullwr_write_stream(bmp
->pullwr
, s
);
823 static struct stream
*bmp_update(const struct prefix
*p
, struct prefix_rd
*prd
,
824 struct peer
*peer
, struct attr
*attr
,
825 afi_t afi
, safi_t safi
)
827 struct bpacket_attr_vec_arr vecarr
;
829 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
830 bgp_size_t total_attr_len
= 0;
832 bpacket_attr_vec_arr_reset(&vecarr
);
834 s
= stream_new(BGP_MAX_PACKET_SIZE
);
835 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
837 /* 2: withdrawn routes length */
840 /* 3: total attributes length - attrlen_pos stores the position */
841 attrlen_pos
= stream_get_endp(s
);
844 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
845 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
846 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
850 /* peer_cap_enhe & add-path removed */
851 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
852 stream_put_prefix(s
, p
);
854 size_t p1
= stream_get_endp(s
);
856 /* MPLS removed for now */
858 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
860 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, NULL
, 0, 0, 0,
862 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
863 total_attr_len
+= stream_get_endp(s
) - p1
;
866 /* set the total attribute length correctly */
867 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
868 bgp_packet_set_size(s
);
872 static struct stream
*bmp_withdraw(const struct prefix
*p
,
873 struct prefix_rd
*prd
, afi_t afi
,
877 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
878 bgp_size_t total_attr_len
= 0;
879 bgp_size_t unfeasible_len
;
881 s
= stream_new(BGP_MAX_PACKET_SIZE
);
883 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
886 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
887 stream_put_prefix(s
, p
);
888 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
889 - BGP_UNFEASIBLE_LEN
;
890 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
893 attrlen_pos
= stream_get_endp(s
);
894 /* total attr length = 0 for now. reevaluate later */
896 mp_start
= stream_get_endp(s
);
897 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
899 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, prd
, NULL
, 0, 0, 0,
901 /* Set the mp_unreach attr's length */
902 bgp_packet_mpunreach_end(s
, mplen_pos
);
904 /* Set total path attribute length. */
905 total_attr_len
= stream_get_endp(s
) - mp_start
;
906 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
909 bgp_packet_set_size(s
);
913 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
914 const struct prefix
*p
, struct prefix_rd
*prd
,
915 struct attr
*attr
, afi_t afi
, safi_t safi
,
918 struct stream
*hdr
, *msg
;
919 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
920 struct timeval uptime_real
;
922 monotime_to_realtime(&tv
, &uptime_real
);
924 msg
= bmp_update(p
, prd
, peer
, attr
, afi
, safi
);
926 msg
= bmp_withdraw(p
, prd
, afi
, safi
);
928 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
929 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
930 bmp_per_peer_hdr(hdr
, peer
, flags
, &uptime_real
);
932 stream_putl_at(hdr
, BMP_LENGTH_POS
,
933 stream_get_endp(hdr
) + stream_get_endp(msg
));
936 pullwr_write_stream(bmp
->pullwr
, hdr
);
937 pullwr_write_stream(bmp
->pullwr
, msg
);
942 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
947 if (bmp
->syncafi
== AFI_MAX
) {
948 FOREACH_AFI_SAFI (afi
, safi
) {
949 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
952 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
955 bmp
->syncsafi
= safi
;
957 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
958 bmp
->syncpos
.family
= afi2family(afi
);
959 bmp
->syncrdpos
= NULL
;
960 zlog_info("bmp[%s] %s %s sending table",
962 afi2str(bmp
->syncafi
),
963 safi2str(bmp
->syncsafi
));
964 /* break does not work here, 2 loops... */
967 if (bmp
->syncafi
== AFI_MAX
)
973 safi
= bmp
->syncsafi
;
975 if (!bmp
->targets
->afimon
[afi
][safi
]) {
976 /* shouldn't happen */
977 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
978 bmp
->syncafi
= AFI_MAX
;
979 bmp
->syncsafi
= SAFI_MAX
;
983 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
985 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
986 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
988 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
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 /* reset bottom-layer pointer */
1019 memset(&bmp
->syncpos
, 0,
1020 sizeof(bmp
->syncpos
));
1021 bmp
->syncpos
.family
= afi2family(afi
);
1022 /* check whethere there is a valid
1023 * next mid-layer table, otherwise
1024 * declare table completed (eor)
1026 for (bmp
->syncrdpos
= bgp_route_next(
1029 bmp
->syncrdpos
= bgp_route_next(
1031 if (bgp_dest_get_bgp_table_info(
1036 zlog_info("bmp[%s] %s %s table completed (EoR)",
1037 bmp
->remote
, afi2str(afi
),
1039 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
1040 bmp_eor(bmp
, afi
, safi
, 0);
1042 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
1043 bmp
->syncafi
= AFI_MAX
;
1044 bmp
->syncsafi
= SAFI_MAX
;
1047 bmp
->syncpeerid
= 0;
1048 prefix_copy(&bmp
->syncpos
, bgp_dest_get_prefix(bn
));
1051 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1052 for (bpiter
= bgp_dest_get_bgp_path_info(bn
); bpiter
;
1053 bpiter
= bpiter
->next
) {
1054 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
1056 if (bpiter
->peer
->qobj_node
.nid
1059 if (bpi
&& bpiter
->peer
->qobj_node
.nid
1060 > bpi
->peer
->qobj_node
.nid
)
1065 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1066 for (adjiter
= bn
->adj_in
; adjiter
;
1067 adjiter
= adjiter
->next
) {
1068 if (adjiter
->peer
->qobj_node
.nid
1071 if (adjin
&& adjiter
->peer
->qobj_node
.nid
1072 > adjin
->peer
->qobj_node
.nid
)
1084 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
1086 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1087 } else if (adjin
&& bpi
1088 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
1090 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1092 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
1094 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
1097 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
1098 struct prefix_rd
*prd
= NULL
;
1099 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
1100 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(bmp
->syncrdpos
);
1103 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, bn_p
, prd
,
1104 bpi
->attr
, afi
, safi
, bpi
->uptime
);
1106 bmp_monitor(bmp
, adjin
->peer
, 0, bn_p
, prd
, adjin
->attr
, afi
,
1107 safi
, adjin
->uptime
);
1112 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1114 struct bmp_queue_entry
*bqe
;
1116 bqe
= bmp
->queuepos
;
1120 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1123 if (!bqe
->refcount
) {
1124 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1125 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1130 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1132 struct bmp_queue_entry
*bqe
;
1134 struct bgp_dest
*bn
;
1135 bool written
= false;
1137 bqe
= bmp_pull(bmp
);
1141 afi_t afi
= bqe
->afi
;
1142 safi_t safi
= bqe
->safi
;
1144 switch (bmp
->afistate
[afi
][safi
]) {
1145 case BMP_AFI_INACTIVE
:
1146 case BMP_AFI_NEEDSYNC
:
1149 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1150 /* currently syncing but have already passed this
1151 * prefix => send it. */
1154 /* currently syncing & haven't reached this prefix yet
1155 * => it'll be sent as part of the table sync, no need here */
1161 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1163 zlog_info("bmp: skipping queued item for deleted peer");
1166 if (!peer_established(peer
))
1169 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1170 struct prefix_rd
*prd
= NULL
;
1171 if (bqe
->afi
== AFI_L2VPN
&& bqe
->safi
== SAFI_EVPN
)
1174 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1175 struct bgp_path_info
*bpi
;
1177 for (bpi
= bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
; bpi
;
1179 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1181 if (bpi
->peer
== peer
)
1185 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
, prd
,
1186 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1187 bpi
? bpi
->uptime
: monotime(NULL
));
1191 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1192 struct bgp_adj_in
*adjin
;
1194 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1195 adjin
= adjin
->next
) {
1196 if (adjin
->peer
== peer
)
1199 bmp_monitor(bmp
, peer
, 0, &bqe
->p
, prd
,
1200 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1201 adjin
? adjin
->uptime
: monotime(NULL
));
1207 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1211 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1213 switch(bmp
->state
) {
1215 bmp_send_peerup(bmp
);
1216 bmp
->state
= BMP_Run
;
1220 if (bmp_wrmirror(bmp
, pullwr
))
1222 if (bmp_wrqueue(bmp
, pullwr
))
1224 if (bmp_wrsync(bmp
, pullwr
))
1230 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1233 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1235 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1236 bmp
->remote
, strerror(errno
));
1242 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
, afi_t afi
,
1243 safi_t safi
, struct bgp_dest
*bn
, struct peer
*peer
)
1246 struct bmp_queue_entry
*bqe
, bqeref
;
1249 refcount
= bmp_session_count(&bt
->sessions
);
1253 memset(&bqeref
, 0, sizeof(bqeref
));
1254 prefix_copy(&bqeref
.p
, bgp_dest_get_prefix(bn
));
1255 bqeref
.peerid
= peer
->qobj_node
.nid
;
1259 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
&& bn
->pdest
)
1260 prefix_copy(&bqeref
.rd
,
1261 (struct prefix_rd
*)bgp_dest_get_prefix(bn
->pdest
));
1263 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1265 if (bqe
->refcount
>= refcount
)
1266 /* nothing to do here */
1269 bmp_qlist_del(&bt
->updlist
, bqe
);
1271 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1272 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1274 bmp_qhash_add(&bt
->updhash
, bqe
);
1277 bqe
->refcount
= refcount
;
1278 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1280 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1282 bmp
->queuepos
= bqe
;
1285 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1286 struct bgp_dest
*bn
, struct peer
*peer
, bool withdraw
)
1288 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1289 struct bmp_targets
*bt
;
1292 if (frrtrace_enabled(frr_bgp
, bmp_process
)) {
1293 char pfxprint
[PREFIX2STR_BUFFER
];
1295 prefix2str(&bn
->p
, pfxprint
, sizeof(pfxprint
));
1296 frrtrace(5, frr_bgp
, bmp_process
, peer
, pfxprint
, afi
, safi
,
1303 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1304 if (!bt
->afimon
[afi
][safi
])
1307 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1309 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1310 pullwr_bump(bmp
->pullwr
);
1316 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1319 stream_putw(s
, type
);
1321 stream_putl(s
, value
);
1325 static void bmp_stats(struct thread
*thread
)
1327 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1330 struct listnode
*node
;
1334 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1337 gettimeofday(&tv
, NULL
);
1339 /* Walk down all peers */
1340 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1341 size_t count
= 0, count_pos
, len
;
1343 if (!peer_established(peer
))
1346 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1347 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1348 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1350 count_pos
= stream_get_endp(s
);
1353 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1354 peer
->stat_pfx_filter
);
1355 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1356 peer
->stat_pfx_aspath_loop
);
1357 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1358 peer
->stat_pfx_originator_loop
);
1359 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1360 peer
->stat_pfx_cluster_loop
);
1361 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1362 peer
->stat_pfx_dup_withdraw
);
1363 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1364 peer
->stat_upd_7606
);
1365 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1366 peer
->stat_pfx_nh_invalid
);
1368 stream_putl_at(s
, count_pos
, count
);
1370 len
= stream_get_endp(s
);
1371 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1373 bmp_send_all(bt
->bmpbgp
, s
);
1377 /* read from the BMP socket to detect session termination */
1378 static void bmp_read(struct thread
*t
)
1380 struct bmp
*bmp
= THREAD_ARG(t
);
1386 n
= read(bmp
->socket
, buf
, sizeof(buf
));
1388 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp
->remote
, n
);
1389 } else if (n
== 0) {
1390 /* the TCP session was terminated by the far end */
1391 bmp_wrerr(bmp
, NULL
, true);
1393 } else if (!(errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
)) {
1394 /* the TCP session experienced a fatal error, likely a timeout */
1395 bmp_wrerr(bmp
, NULL
, false);
1399 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp
->socket
, &bmp
->t_read
);
1402 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1404 union sockunion su
, *sumem
;
1407 struct access_list
*acl
= NULL
;
1408 enum filter_type ret
;
1409 char buf
[SU_ADDRSTRLEN
];
1412 sumem
= sockunion_getpeername(bmp_sock
);
1417 memcpy(&su
, sumem
, sizeof(su
));
1418 sockunion_free(sumem
);
1420 set_nonblocking(bmp_sock
);
1421 set_cloexec(bmp_sock
);
1423 if (!sockunion2hostprefix(&su
, &p
)) {
1431 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1434 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1440 ret
= FILTER_PERMIT
;
1442 ret
= access_list_apply(acl
, &p
);
1445 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1446 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1447 su
.sa
.sa_family
== AF_INET
1448 ? ntohs(su
.sin
.sin_port
)
1449 : ntohs(su
.sin6
.sin6_port
));
1451 if (ret
== FILTER_DENY
) {
1452 bt
->cnt_aclrefused
++;
1453 zlog_info("bmp[%s] connection refused by access-list", buf
);
1459 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1460 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1461 bmp_sock
, safe_strerror(errno
), errno
);
1462 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1463 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1464 bmp_sock
, safe_strerror(errno
), errno
);
1466 zlog_info("bmp[%s] connection established", buf
);
1468 /* Allocate new BMP structure and set up default values. */
1469 bmp
= bmp_new(bt
, bmp_sock
);
1470 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1472 bmp
->state
= BMP_PeerUp
;
1473 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1475 thread_add_read(bm
->master
, bmp_read
, bmp
, bmp_sock
, &bmp
->t_read
);
1476 bmp_send_initiation(bmp
);
1481 /* Accept BMP connection. */
1482 static void bmp_accept(struct thread
*thread
)
1485 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1488 /* We continue hearing BMP socket. */
1489 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1491 memset(&su
, 0, sizeof(union sockunion
));
1493 /* We can handle IPv4 or IPv6 socket. */
1494 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1496 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno
));
1499 bmp_open(bl
->targets
, bmp_sock
);
1502 static void bmp_close(struct bmp
*bmp
)
1504 struct bmp_queue_entry
*bqe
;
1505 struct bmp_mirrorq
*bmq
;
1507 THREAD_OFF(bmp
->t_read
);
1510 bmp_active_disconnected(bmp
->active
);
1512 while ((bmq
= bmp_pull_mirror(bmp
)))
1514 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1515 while ((bqe
= bmp_pull(bmp
)))
1517 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1519 THREAD_OFF(bmp
->t_read
);
1520 pullwr_del(bmp
->pullwr
);
1524 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1526 struct bmp_bgp dummy
= { .bgp
= bgp
};
1527 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1530 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1532 struct bmp_bgp
*bmpbgp
;
1534 bmpbgp
= bmp_bgp_find(bgp
);
1538 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1540 bmpbgp
->mirror_qsizelimit
= ~0UL;
1541 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1542 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1547 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1549 struct bmp_targets
*bt
;
1550 struct bmp_listener
*bl
;
1552 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1554 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, bt
) {
1555 frr_each_safe (bmp_listeners
, &bt
->listeners
, bl
)
1556 bmp_listener_put(bl
);
1558 bmp_targets_put(bt
);
1561 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1562 XFREE(MTYPE_BMP
, bmpbgp
);
1565 static int bmp_bgp_del(struct bgp
*bgp
)
1567 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1570 bmp_bgp_put(bmpbgp
);
1574 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1576 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1577 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1580 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1582 struct bmp_bgp_peer
*bbpeer
;
1584 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1588 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1589 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1590 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1595 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1597 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1598 struct bmp_targets dummy
;
1602 dummy
.name
= (char *)name
;
1603 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1606 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1608 struct bmp_targets
*bt
;
1610 bt
= bmp_targets_find1(bgp
, name
);
1614 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1615 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1617 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1618 bmp_session_init(&bt
->sessions
);
1619 bmp_qhash_init(&bt
->updhash
);
1620 bmp_qlist_init(&bt
->updlist
);
1621 bmp_actives_init(&bt
->actives
);
1622 bmp_listeners_init(&bt
->listeners
);
1624 QOBJ_REG(bt
, bmp_targets
);
1625 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1629 static void bmp_targets_put(struct bmp_targets
*bt
)
1632 struct bmp_active
*ba
;
1634 THREAD_OFF(bt
->t_stats
);
1636 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1639 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1644 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1647 bmp_listeners_fini(&bt
->listeners
);
1648 bmp_actives_fini(&bt
->actives
);
1649 bmp_qhash_fini(&bt
->updhash
);
1650 bmp_qlist_fini(&bt
->updlist
);
1652 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1653 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1654 bmp_session_fini(&bt
->sessions
);
1656 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1657 XFREE(MTYPE_BMP_TARGETS
, bt
);
1660 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1661 const union sockunion
*su
,
1664 struct bmp_listener dummy
;
1667 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1670 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1671 const union sockunion
*su
,
1674 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1679 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1685 bmp_listeners_add(&bt
->listeners
, bl
);
1689 static void bmp_listener_start(struct bmp_listener
*bl
)
1693 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1697 sockopt_reuseaddr(sock
);
1698 sockopt_reuseport(sock
);
1699 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1702 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1706 ret
= listen(sock
, 3);
1711 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1717 static void bmp_listener_stop(struct bmp_listener
*bl
)
1719 THREAD_OFF(bl
->t_accept
);
1726 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1727 const char *hostname
, int port
)
1729 struct bmp_active dummy
;
1730 dummy
.hostname
= (char *)hostname
;
1732 return bmp_actives_find(&bt
->actives
, &dummy
);
1735 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1736 const char *hostname
, int port
)
1738 struct bmp_active
*ba
;
1740 ba
= bmp_active_find(bt
, hostname
, port
);
1744 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1746 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1748 ba
->minretry
= BMP_DFLT_MINRETRY
;
1749 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1752 bmp_actives_add(&bt
->actives
, ba
);
1756 static void bmp_active_put(struct bmp_active
*ba
)
1758 THREAD_OFF(ba
->t_timer
);
1759 THREAD_OFF(ba
->t_read
);
1760 THREAD_OFF(ba
->t_write
);
1762 bmp_actives_del(&ba
->targets
->actives
, ba
);
1765 ba
->bmp
->active
= NULL
;
1769 if (ba
->socket
!= -1)
1772 XFREE(MTYPE_TMP
, ba
->ifsrc
);
1773 XFREE(MTYPE_TMP
, ba
->hostname
);
1774 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1777 static void bmp_active_setup(struct bmp_active
*ba
);
1779 static void bmp_active_connect(struct bmp_active
*ba
)
1781 enum connect_result res
;
1782 struct interface
*ifp
;
1783 vrf_id_t vrf_id
= VRF_DEFAULT
;
1786 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1788 if (ba
->targets
&& ba
->targets
->bgp
)
1789 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1791 /* find interface and related */
1792 /* address with same family */
1793 ifp
= if_lookup_by_name(ba
->ifsrc
, vrf_id
);
1795 zlog_warn("bmp[%s]: failed to find interface",
1800 if (bgp_update_address(ifp
, &ba
->addrs
[ba
->addrpos
],
1802 zlog_warn("bmp[%s]: failed to find matching address",
1806 zlog_info("bmp[%s]: selected source address : %pSU",
1807 ba
->ifsrc
, &ba
->addrsrc
);
1810 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1811 if (ba
->socket
< 0) {
1812 zlog_warn("bmp[%s]: failed to create socket",
1817 set_nonblocking(ba
->socket
);
1819 if (!sockunion_is_null(&ba
->addrsrc
)) {
1820 res_bind
= sockunion_bind(ba
->socket
, &ba
->addrsrc
, 0,
1824 "bmp[%s]: no bind currently to source address %pSU:%d",
1825 ba
->hostname
, &ba
->addrsrc
, ba
->port
);
1828 sockunion_init(&ba
->addrsrc
);
1834 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1835 htons(ba
->port
), 0);
1838 zlog_warn("bmp[%s]: failed to connect to %pSU:%d",
1839 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1843 sockunion_init(&ba
->addrsrc
);
1845 case connect_success
:
1846 zlog_info("bmp[%s]: connected to %pSU:%d",
1847 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1850 case connect_in_progress
:
1851 zlog_warn("bmp[%s]: connect in progress %pSU:%d",
1852 ba
->hostname
, &ba
->addrs
[ba
->addrpos
],
1854 bmp_active_setup(ba
);
1859 /* exhausted all addresses */
1860 ba
->curretry
+= ba
->curretry
/ 2;
1861 bmp_active_setup(ba
);
1864 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1865 int numaddrs
, union sockunion
*addr
)
1867 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1870 if (numaddrs
<= 0) {
1871 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1872 ba
->hostname
, errstr
);
1873 ba
->last_err
= errstr
;
1874 ba
->curretry
+= ba
->curretry
/ 2;
1877 bmp_active_setup(ba
);
1881 if (numaddrs
> (int)array_size(ba
->addrs
))
1882 numaddrs
= array_size(ba
->addrs
);
1885 ba
->addrtotal
= numaddrs
;
1886 for (i
= 0; i
< ba
->addrtotal
; i
++)
1887 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1889 bmp_active_connect(ba
);
1892 static void bmp_active_thread(struct thread
*t
)
1894 struct bmp_active
*ba
= THREAD_ARG(t
);
1899 /* all 3 end up here, though only timer or read+write are active
1901 THREAD_OFF(ba
->t_timer
);
1902 THREAD_OFF(ba
->t_read
);
1903 THREAD_OFF(ba
->t_write
);
1905 ba
->last_err
= NULL
;
1907 if (ba
->socket
== -1) {
1909 if (!ba
->targets
|| !ba
->targets
->bgp
)
1910 vrf_id
= VRF_DEFAULT
;
1912 vrf_id
= ba
->targets
->bgp
->vrf_id
;
1913 resolver_resolve(&ba
->resq
, AF_UNSPEC
, vrf_id
, ba
->hostname
,
1914 bmp_active_resolved
);
1918 slen
= sizeof(status
);
1919 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1922 if (ret
< 0 || status
!= 0) {
1923 ba
->last_err
= strerror(status
);
1924 zlog_warn("bmp[%s]: failed to connect to %pSU:%d: %s",
1925 ba
->hostname
, &ba
->addrs
[ba
->addrpos
], ba
->port
,
1930 zlog_warn("bmp[%s]: outbound connection to %pSU:%d", ba
->hostname
,
1931 &ba
->addrs
[ba
->addrpos
], ba
->port
);
1933 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1937 ba
->bmp
->active
= ba
;
1939 ba
->curretry
= ba
->minretry
;
1946 bmp_active_connect(ba
);
1949 static void bmp_active_disconnected(struct bmp_active
*ba
)
1952 bmp_active_setup(ba
);
1955 static void bmp_active_setup(struct bmp_active
*ba
)
1957 THREAD_OFF(ba
->t_timer
);
1958 THREAD_OFF(ba
->t_read
);
1959 THREAD_OFF(ba
->t_write
);
1963 if (ba
->resq
.callback
)
1966 if (ba
->curretry
> ba
->maxretry
)
1967 ba
->curretry
= ba
->maxretry
;
1969 if (ba
->socket
== -1)
1970 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1971 ba
->curretry
, &ba
->t_timer
);
1973 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1975 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1980 static struct cmd_node bmp_node
= {
1983 .parent_node
= BGP_NODE
,
1984 .prompt
= "%s(config-bgp-bmp)# "
1987 static void bmp_targets_autocomplete(vector comps
, struct cmd_token
*token
)
1990 struct bmp_targets
*target
;
1991 struct listnode
*node
;
1993 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
1994 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1999 frr_each_safe (bmp_targets
, &bmpbgp
->targets
, target
)
2001 XSTRDUP(MTYPE_COMPLETION
, target
->name
));
2005 static const struct cmd_variable_handler bmp_targets_var_handlers
[] = {
2006 {.tokenname
= "BMPTARGETS", .completions
= bmp_targets_autocomplete
},
2007 {.completions
= NULL
}};
2009 #define BMP_STR "BGP Monitoring Protocol\n"
2011 #ifndef VTYSH_EXTRACT_PL
2012 #include "bgpd/bgp_bmp_clippy.c"
2015 DEFPY_NOSH(bmp_targets_main
,
2017 "bmp targets BMPTARGETS",
2019 "Create BMP target group\n"
2020 "Name of the BMP target group\n")
2022 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2023 struct bmp_targets
*bt
;
2025 bt
= bmp_targets_get(bgp
, bmptargets
);
2027 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
2031 DEFPY(no_bmp_targets_main
,
2033 "no bmp targets BMPTARGETS",
2036 "Delete BMP target group\n"
2037 "Name of the BMP target group\n")
2039 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2040 struct bmp_targets
*bt
;
2042 bt
= bmp_targets_find1(bgp
, bmptargets
);
2044 vty_out(vty
, "%% BMP target group not found\n");
2047 bmp_targets_put(bt
);
2051 DEFPY(bmp_listener_main
,
2053 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2055 "Listen for inbound BMP connections\n"
2056 "IPv6 address to listen on\n"
2057 "IPv4 address to listen on\n"
2059 "TCP Port number\n")
2061 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2062 struct bmp_listener
*bl
;
2064 bl
= bmp_listener_get(bt
, listener
, port
);
2066 bmp_listener_start(bl
);
2071 DEFPY(no_bmp_listener_main
,
2072 no_bmp_listener_cmd
,
2073 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
2076 "Create BMP listener\n"
2077 "IPv6 address to listen on\n"
2078 "IPv4 address to listen on\n"
2080 "TCP Port number\n")
2082 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2083 struct bmp_listener
*bl
;
2085 bl
= bmp_listener_find(bt
, listener
, port
);
2087 vty_out(vty
, "%% BMP listener not found\n");
2090 bmp_listener_stop(bl
);
2091 bmp_listener_put(bl
);
2097 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
2100 "Actively establish connection to monitoring station\n"
2101 "Monitoring station hostname or address\n"
2104 "Minimum connection retry interval\n"
2105 "Minimum connection retry interval (milliseconds)\n"
2106 "Maximum connection retry interval\n"
2107 "Maximum connection retry interval (milliseconds)\n"
2108 "Source interface to use\n"
2109 "Define an interface\n")
2111 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2112 struct bmp_active
*ba
;
2115 ba
= bmp_active_find(bt
, hostname
, port
);
2117 vty_out(vty
, "%% No such active connection found\n");
2120 /* connection deletion need same hostname port and interface */
2121 if (ba
->ifsrc
|| srcif
)
2122 if ((!ba
->ifsrc
) || (!srcif
) ||
2123 !strcmp(ba
->ifsrc
, srcif
)) {
2125 "%% No such active connection found\n");
2132 ba
= bmp_active_get(bt
, hostname
, port
);
2134 ba
->ifsrc
= XSTRDUP(MTYPE_TMP
, srcif
);
2136 ba
->minretry
= min_retry
;
2138 ba
->maxretry
= max_retry
;
2139 ba
->curretry
= ba
->minretry
;
2140 bmp_active_setup(ba
);
2147 "[no] <ip|ipv6>$af access-list ACCESSLIST_NAME$access_list",
2151 "Access list to restrict BMP sessions\n"
2152 "Access list name\n")
2154 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2159 if (!strcmp(af
, "ipv6"))
2160 what
= &bt
->acl6_name
;
2162 what
= &bt
->acl_name
;
2164 XFREE(MTYPE_BMP_ACLNAME
, *what
);
2166 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
2171 DEFPY(bmp_stats_cfg
,
2173 "[no] bmp stats [interval (100-86400000)]",
2176 "Send BMP statistics messages\n"
2177 "Specify BMP stats interval\n"
2178 "Interval (milliseconds) to send BMP Stats in\n")
2180 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2182 THREAD_OFF(bt
->t_stats
);
2185 else if (interval_str
)
2186 bt
->stat_msec
= interval
;
2188 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
2191 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
2196 DEFPY(bmp_monitor_cfg
,
2198 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
2201 "Send BMP route monitoring messages\n"
2202 "Address Family\nAddress Family\nAddress Family\n"
2203 "Address Family\nAddress Family\nAddress Family\n"
2204 "Send state before policy and filter processing\n"
2205 "Send state with policy and filters applied\n")
2212 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2215 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
2216 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
2218 if (policy
[1] == 'r')
2219 flag
= BMP_MON_PREPOLICY
;
2221 flag
= BMP_MON_POSTPOLICY
;
2223 prev
= bt
->afimon
[afi
][safi
];
2225 bt
->afimon
[afi
][safi
] &= ~flag
;
2227 bt
->afimon
[afi
][safi
] |= flag
;
2229 if (prev
== bt
->afimon
[afi
][safi
])
2232 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2233 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
2234 bmp
->syncafi
= AFI_MAX
;
2235 bmp
->syncsafi
= SAFI_MAX
;
2238 if (!bt
->afimon
[afi
][safi
]) {
2239 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2243 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2249 DEFPY(bmp_mirror_cfg
,
2254 "Send BMP route mirroring messages\n")
2256 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2259 if (bt
->mirror
== !no
)
2266 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2267 struct bmp_mirrorq
*bmq
;
2269 while ((bmq
= bmp_pull_mirror(bmp
)))
2271 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2276 DEFPY(bmp_mirror_limit_cfg
,
2277 bmp_mirror_limit_cmd
,
2278 "bmp mirror buffer-limit (0-4294967294)",
2280 "Route Mirroring settings\n"
2281 "Configure maximum memory used for buffered mirroring messages\n"
2284 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2285 struct bmp_bgp
*bmpbgp
;
2287 bmpbgp
= bmp_bgp_get(bgp
);
2288 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2293 DEFPY(no_bmp_mirror_limit_cfg
,
2294 no_bmp_mirror_limit_cmd
,
2295 "no bmp mirror buffer-limit [(0-4294967294)]",
2298 "Route Mirroring settings\n"
2299 "Configure maximum memory used for buffered mirroring messages\n"
2302 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2303 struct bmp_bgp
*bmpbgp
;
2305 bmpbgp
= bmp_bgp_get(bgp
);
2306 bmpbgp
->mirror_qsizelimit
= ~0UL;
2318 struct bmp_bgp
*bmpbgp
;
2319 struct bmp_targets
*bt
;
2320 struct bmp_listener
*bl
;
2321 struct bmp_active
*ba
;
2324 char uptime
[BGP_UPTIME_LEN
];
2327 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2328 vty_out(vty
, "BMP state for BGP %s:\n\n",
2329 bmpbgp
->bgp
->name_pretty
);
2330 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2331 bmpbgp
->mirror_qsize
,
2332 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2333 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2334 bmpbgp
->mirror_qsizemax
);
2335 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2336 vty_out(vty
, " %9zu bytes buffer size limit\n",
2337 bmpbgp
->mirror_qsizelimit
);
2340 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2341 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2342 vty_out(vty
, " Route Mirroring %sabled\n",
2343 bt
->mirror
? "en" : "dis");
2348 FOREACH_AFI_SAFI (afi
, safi
) {
2349 const char *str
= NULL
;
2351 switch (bt
->afimon
[afi
][safi
]) {
2352 case BMP_MON_PREPOLICY
:
2355 case BMP_MON_POSTPOLICY
:
2356 str
= "post-policy";
2358 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2359 str
= "pre-policy and post-policy";
2364 vty_out(vty
, " Route Monitoring %s %s %s\n",
2365 afi2str(afi
), safi2str(safi
), str
);
2368 vty_out(vty
, " Listeners:\n");
2369 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2370 vty_out(vty
, " %pSU:%d\n", &bl
->addr
,
2373 vty_out(vty
, "\n Outbound connections:\n");
2374 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2375 ttable_add_row(tt
, "remote|state||timer|local");
2376 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2377 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2378 const char *state_str
= "?";
2381 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2382 uptime
, sizeof(uptime
),
2385 "%s:%d|Up|%s|%s|%pSU",
2386 ba
->hostname
, ba
->port
,
2387 ba
->bmp
->remote
, uptime
,
2395 long trem
= thread_timer_remain_second(
2398 peer_uptime(monotime(NULL
) - trem
,
2399 uptime
, sizeof(uptime
),
2401 state_str
= "RetryWait";
2402 } else if (ba
->t_read
) {
2403 state_str
= "Connecting";
2404 } else if (ba
->resq
.callback
) {
2405 state_str
= "Resolving";
2408 ttable_add_row(tt
, "%s:%d|%s|%s|%s|%pSU",
2409 ba
->hostname
, ba
->port
,
2411 ba
->last_err
? ba
->last_err
: "",
2412 uptime
, &ba
->addrsrc
);
2415 out
= ttable_dump(tt
, "\n");
2416 vty_out(vty
, "%s", out
);
2417 XFREE(MTYPE_TMP
, out
);
2420 vty_out(vty
, "\n %zu connected clients:\n",
2421 bmp_session_count(&bt
->sessions
));
2422 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2423 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2424 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2426 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2430 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2432 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2433 sizeof(uptime
), false, NULL
);
2435 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2436 bmp
->remote
, uptime
,
2439 bmp
->cnt_mirror_overruns
,
2442 out
= ttable_dump(tt
, "\n");
2443 vty_out(vty
, "%s", out
);
2444 XFREE(MTYPE_TMP
, out
);
2453 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2455 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2456 struct bmp_targets
*bt
;
2457 struct bmp_listener
*bl
;
2458 struct bmp_active
*ba
;
2465 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2466 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2467 bmpbgp
->mirror_qsizelimit
);
2469 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2470 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2473 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2475 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2478 vty_out(vty
, " bmp stats interval %d\n",
2482 vty_out(vty
, " bmp mirror\n");
2484 FOREACH_AFI_SAFI (afi
, safi
) {
2485 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2487 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2488 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2489 afi_str
, safi2str(safi
));
2490 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2491 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2492 afi_str
, safi2str(safi
));
2494 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2495 vty_out(vty
, " \n bmp listener %pSU port %d\n",
2496 &bl
->addr
, bl
->port
);
2498 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2499 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u",
2500 ba
->hostname
, ba
->port
,
2501 ba
->minretry
, ba
->maxretry
);
2504 vty_out(vty
, " source-interface %s\n", ba
->ifsrc
);
2508 vty_out(vty
, " exit\n");
2514 static int bgp_bmp_init(struct thread_master
*tm
)
2516 install_node(&bmp_node
);
2517 install_default(BMP_NODE
);
2519 cmd_variable_handler_register(bmp_targets_var_handlers
);
2521 install_element(BGP_NODE
, &bmp_targets_cmd
);
2522 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2524 install_element(BMP_NODE
, &bmp_listener_cmd
);
2525 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2526 install_element(BMP_NODE
, &bmp_connect_cmd
);
2527 install_element(BMP_NODE
, &bmp_acl_cmd
);
2528 install_element(BMP_NODE
, &bmp_stats_cmd
);
2529 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2530 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2532 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2533 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2535 install_element(VIEW_NODE
, &show_bmp_cmd
);
2541 static int bgp_bmp_module_init(void)
2543 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2544 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2545 hook_register(peer_status_changed
, bmp_peer_status_changed
);
2546 hook_register(peer_backward_transition
, bmp_peer_backward
);
2547 hook_register(bgp_process
, bmp_process
);
2548 hook_register(bgp_inst_config_write
, bmp_config_write
);
2549 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2550 hook_register(frr_late_init
, bgp_bmp_init
);
2554 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2555 .description
= "bgpd BMP module",
2556 .init
= bgp_bmp_module_init
,