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"
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"
53 static void bmp_close(struct bmp
*bmp
);
54 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
);
55 static void bmp_targets_put(struct bmp_targets
*bt
);
56 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
);
57 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
);
58 static void bmp_active_disconnected(struct bmp_active
*ba
);
59 static void bmp_active_put(struct bmp_active
*ba
);
61 DEFINE_MGROUP(BMP
, "BMP (BGP Monitoring Protocol)")
63 DEFINE_MTYPE_STATIC(BMP
, BMP_CONN
, "BMP connection state")
64 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETS
, "BMP targets")
65 DEFINE_MTYPE_STATIC(BMP
, BMP_TARGETSNAME
, "BMP targets name")
66 DEFINE_MTYPE_STATIC(BMP
, BMP_LISTENER
, "BMP listener")
67 DEFINE_MTYPE_STATIC(BMP
, BMP_ACTIVE
, "BMP active connection config")
68 DEFINE_MTYPE_STATIC(BMP
, BMP_ACLNAME
, "BMP access-list name")
69 DEFINE_MTYPE_STATIC(BMP
, BMP_QUEUE
, "BMP update queue item")
70 DEFINE_MTYPE_STATIC(BMP
, BMP
, "BMP instance state")
71 DEFINE_MTYPE_STATIC(BMP
, BMP_MIRRORQ
, "BMP route mirroring buffer")
72 DEFINE_MTYPE_STATIC(BMP
, BMP_PEER
, "BMP per BGP peer data")
73 DEFINE_MTYPE_STATIC(BMP
, BMP_OPEN
, "BMP stored BGP OPEN message")
75 DEFINE_QOBJ_TYPE(bmp_targets
)
77 static int bmp_bgp_cmp(const struct bmp_bgp
*a
, const struct bmp_bgp
*b
)
86 static uint32_t bmp_bgp_hash(const struct bmp_bgp
*e
)
88 return jhash(&e
->bgp
, sizeof(e
->bgp
), 0x55aa5a5a);
91 DECLARE_HASH(bmp_bgph
, struct bmp_bgp
, bbi
, bmp_bgp_cmp
, bmp_bgp_hash
)
93 struct bmp_bgph_head bmp_bgph
;
95 static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer
*a
,
96 const struct bmp_bgp_peer
*b
)
98 if (a
->peerid
< b
->peerid
)
100 if (a
->peerid
> b
->peerid
)
105 static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer
*e
)
110 DECLARE_HASH(bmp_peerh
, struct bmp_bgp_peer
, bpi
,
111 bmp_bgp_peer_cmp
, bmp_bgp_peer_hash
)
113 struct bmp_peerh_head bmp_peerh
;
115 DECLARE_LIST(bmp_mirrorq
, struct bmp_mirrorq
, bmi
)
117 /* listener management */
119 static int bmp_listener_cmp(const struct bmp_listener
*a
,
120 const struct bmp_listener
*b
)
124 c
= sockunion_cmp(&a
->addr
, &b
->addr
);
127 if (a
->port
< b
->port
)
129 if (a
->port
> b
->port
)
134 DECLARE_SORTLIST_UNIQ(bmp_listeners
, struct bmp_listener
, bli
, bmp_listener_cmp
)
136 static int bmp_targets_cmp(const struct bmp_targets
*a
,
137 const struct bmp_targets
*b
)
139 return strcmp(a
->name
, b
->name
);
142 DECLARE_SORTLIST_UNIQ(bmp_targets
, struct bmp_targets
, bti
, bmp_targets_cmp
)
144 DECLARE_LIST(bmp_session
, struct bmp
, bsi
)
146 DECLARE_DLIST(bmp_qlist
, struct bmp_queue_entry
, bli
)
148 static int bmp_qhash_cmp(const struct bmp_queue_entry
*a
,
149 const struct bmp_queue_entry
*b
)
152 ret
= prefix_cmp(&a
->p
, &b
->p
);
155 ret
= memcmp(&a
->peerid
, &b
->peerid
,
156 offsetof(struct bmp_queue_entry
, refcount
) -
157 offsetof(struct bmp_queue_entry
, peerid
));
161 static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry
*e
)
165 key
= prefix_hash_key((void *)&e
->p
);
166 key
= jhash(&e
->peerid
,
167 offsetof(struct bmp_queue_entry
, refcount
) -
168 offsetof(struct bmp_queue_entry
, peerid
),
173 DECLARE_HASH(bmp_qhash
, struct bmp_queue_entry
, bhi
,
174 bmp_qhash_cmp
, bmp_qhash_hkey
)
176 static int bmp_active_cmp(const struct bmp_active
*a
,
177 const struct bmp_active
*b
)
181 c
= strcmp(a
->hostname
, b
->hostname
);
184 if (a
->port
< b
->port
)
186 if (a
->port
> b
->port
)
191 DECLARE_SORTLIST_UNIQ(bmp_actives
, struct bmp_active
, bai
, bmp_active_cmp
)
193 static struct bmp
*bmp_new(struct bmp_targets
*bt
, int bmp_sock
)
195 struct bmp
*new = XCALLOC(MTYPE_BMP_CONN
, sizeof(struct bmp
));
199 monotime(&new->t_up
);
201 new->socket
= bmp_sock
;
202 new->syncafi
= AFI_MAX
;
204 FOREACH_AFI_SAFI (afi
, safi
) {
205 new->afistate
[afi
][safi
] = bt
->afimon
[afi
][safi
]
206 ? BMP_AFI_NEEDSYNC
: BMP_AFI_INACTIVE
;
209 bmp_session_add_tail(&bt
->sessions
, new);
213 static void bmp_free(struct bmp
*bmp
)
215 bmp_session_del(&bmp
->targets
->sessions
, bmp
);
216 XFREE(MTYPE_BMP_CONN
, bmp
);
219 static void bmp_common_hdr(struct stream
*s
, uint8_t ver
, uint8_t type
)
222 stream_putl(s
, 0); //dummy message length. will be set later.
223 stream_putc(s
, type
);
226 static void bmp_per_peer_hdr(struct stream
*s
, struct peer
*peer
,
227 uint8_t flags
, const struct timeval
*tv
)
229 char peer_distinguisher
[8];
231 #define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
232 #define BMP_PEER_TYPE_RD_INSTANCE 1
233 #define BMP_PEER_TYPE_LOCAL_INSTANCE 2
235 #define BMP_PEER_FLAG_V (1 << 7)
236 #define BMP_PEER_FLAG_L (1 << 6)
237 #define BMP_PEER_FLAG_A (1 << 5)
240 stream_putc(s
, BMP_PEER_TYPE_GLOBAL_INSTANCE
);
243 if (peer
->su
.sa
.sa_family
== AF_INET6
)
244 SET_FLAG(flags
, BMP_PEER_FLAG_V
);
246 UNSET_FLAG(flags
, BMP_PEER_FLAG_V
);
247 stream_putc(s
, flags
);
249 /* Peer Distinguisher */
250 memset (&peer_distinguisher
[0], 0, 8);
251 stream_put(s
, &peer_distinguisher
[0], 8);
254 if (peer
->su
.sa
.sa_family
== AF_INET6
)
255 stream_put(s
, &peer
->su
.sin6
.sin6_addr
, 16);
256 else if (peer
->su
.sa
.sa_family
== AF_INET
) {
260 stream_put_in_addr(s
, &peer
->su
.sin
.sin_addr
);
269 stream_putl(s
, peer
->as
);
272 stream_put_in_addr(s
, &peer
->remote_id
);
276 stream_putl(s
, tv
->tv_sec
);
277 stream_putl(s
, tv
->tv_usec
);
284 static void bmp_put_info_tlv(struct stream
*s
, uint16_t type
,
287 int len
= strlen (string
);
288 stream_putw(s
, type
);
290 stream_put(s
, string
, len
);
293 static int bmp_send_initiation(struct bmp
*bmp
)
297 s
= stream_new(BGP_MAX_PACKET_SIZE
);
298 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_INITIATION
);
300 #define BMP_INFO_TYPE_SYSDESCR 1
301 #define BMP_INFO_TYPE_SYSNAME 2
302 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSDESCR
,
303 FRR_FULL_NAME
" " FRR_VER_SHORT
);
304 bmp_put_info_tlv(s
, BMP_INFO_TYPE_SYSNAME
, cmd_hostname_get());
306 len
= stream_get_endp(s
);
307 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
309 pullwr_write_stream(bmp
->pullwr
, s
);
314 static void bmp_notify_put(struct stream
*s
, struct bgp_notify
*nfy
)
317 uint8_t marker
[16] = {
318 0xff, 0xff, 0xff, 0xff,
319 0xff, 0xff, 0xff, 0xff,
320 0xff, 0xff, 0xff, 0xff,
321 0xff, 0xff, 0xff, 0xff,
324 stream_put(s
, marker
, sizeof(marker
));
325 len_pos
= stream_get_endp(s
);
327 stream_putc(s
, BGP_MSG_NOTIFY
);
328 stream_putc(s
, nfy
->code
);
329 stream_putc(s
, nfy
->subcode
);
330 stream_put(s
, nfy
->data
, nfy
->length
);
332 stream_putw_at(s
, len_pos
, stream_get_endp(s
) - len_pos
336 static struct stream
*bmp_peerstate(struct peer
*peer
, bool down
)
340 struct timeval uptime
, uptime_real
;
342 uptime
.tv_sec
= peer
->uptime
;
344 monotime_to_realtime(&uptime
, &uptime_real
);
346 #define BGP_BMP_MAX_PACKET_SIZE 1024
347 s
= stream_new(BGP_MAX_PACKET_SIZE
);
349 if (peer
->status
== Established
&& !down
) {
350 struct bmp_bgp_peer
*bbpeer
;
352 bmp_common_hdr(s
, BMP_VERSION_3
,
353 BMP_TYPE_PEER_UP_NOTIFICATION
);
354 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
356 /* Local Address (16 bytes) */
357 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
358 stream_put(s
, &peer
->su_local
->sin6
.sin6_addr
, 16);
359 else if (peer
->su_local
->sa
.sa_family
== AF_INET
) {
363 stream_put_in_addr(s
, &peer
->su_local
->sin
.sin_addr
);
366 /* Local Port, Remote Port */
367 if (peer
->su_local
->sa
.sa_family
== AF_INET6
)
368 stream_putw(s
, peer
->su_local
->sin6
.sin6_port
);
369 else if (peer
->su_local
->sa
.sa_family
== AF_INET
)
370 stream_putw(s
, peer
->su_local
->sin
.sin_port
);
371 if (peer
->su_remote
->sa
.sa_family
== AF_INET6
)
372 stream_putw(s
, peer
->su_remote
->sin6
.sin6_port
);
373 else if (peer
->su_remote
->sa
.sa_family
== AF_INET
)
374 stream_putw(s
, peer
->su_remote
->sin
.sin_port
);
376 static const uint8_t dummy_open
[] = {
377 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
378 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
382 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
384 if (bbpeer
&& bbpeer
->open_tx
)
385 stream_put(s
, bbpeer
->open_tx
, bbpeer
->open_tx_len
);
387 stream_put(s
, dummy_open
, sizeof(dummy_open
));
388 zlog_warn("bmp: missing TX OPEN message for peer %s\n",
391 if (bbpeer
&& bbpeer
->open_rx
)
392 stream_put(s
, bbpeer
->open_rx
, bbpeer
->open_rx_len
);
394 stream_put(s
, dummy_open
, sizeof(dummy_open
));
395 zlog_warn("bmp: missing RX OPEN message for peer %s\n",
400 bmp_put_info_tlv(s
, 0, peer
->desc
);
405 bmp_common_hdr(s
, BMP_VERSION_3
,
406 BMP_TYPE_PEER_DOWN_NOTIFICATION
);
407 bmp_per_peer_hdr(s
, peer
, 0, &uptime_real
);
409 type_pos
= stream_get_endp(s
);
410 stream_putc(s
, 0); /* placeholder for down reason */
412 switch (peer
->last_reset
) {
413 case PEER_DOWN_NOTIFY_RECEIVED
:
414 type
= BMP_PEERDOWN_REMOTE_NOTIFY
;
415 bmp_notify_put(s
, &peer
->notify
);
417 case PEER_DOWN_CLOSE_SESSION
:
418 type
= BMP_PEERDOWN_REMOTE_CLOSE
;
421 type
= BMP_PEERDOWN_LOCAL_NOTIFY
;
422 stream_put(s
, peer
->last_reset_cause
,
423 peer
->last_reset_cause_size
);
426 stream_putc_at(s
, type_pos
, type
);
429 len
= stream_get_endp(s
);
430 stream_putl_at(s
, BMP_LENGTH_POS
, len
); //message length is set.
435 static int bmp_send_peerup(struct bmp
*bmp
)
438 struct listnode
*node
;
441 /* Walk down all peers */
442 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
443 s
= bmp_peerstate(peer
, false);
444 pullwr_write_stream(bmp
->pullwr
, s
);
451 /* XXX: kludge - filling the pullwr's buffer */
452 static void bmp_send_all(struct bmp_bgp
*bmpbgp
, struct stream
*s
)
454 struct bmp_targets
*bt
;
457 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
)
458 frr_each(bmp_session
, &bt
->sessions
, bmp
)
459 pullwr_write_stream(bmp
->pullwr
, s
);
467 #define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
468 #define BMP_MIRROR_TLV_TYPE_INFO 1
470 #define BMP_MIRROR_INFO_CODE_ERRORPDU 0
471 #define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
473 static struct bmp_mirrorq
*bmp_pull_mirror(struct bmp
*bmp
)
475 struct bmp_mirrorq
*bmq
;
477 bmq
= bmp
->mirrorpos
;
481 bmp
->mirrorpos
= bmp_mirrorq_next(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
484 if (!bmq
->refcount
) {
485 bmp
->targets
->bmpbgp
->mirror_qsize
-= sizeof(*bmq
) + bmq
->len
;
486 bmp_mirrorq_del(&bmp
->targets
->bmpbgp
->mirrorq
, bmq
);
491 static void bmp_mirror_cull(struct bmp_bgp
*bmpbgp
)
493 while (bmpbgp
->mirror_qsize
> bmpbgp
->mirror_qsizelimit
) {
494 struct bmp_mirrorq
*bmq
, *inner
;
495 struct bmp_targets
*bt
;
498 bmq
= bmp_mirrorq_first(&bmpbgp
->mirrorq
);
500 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
503 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
504 if (bmp
->mirrorpos
!= bmq
)
507 while ((inner
= bmp_pull_mirror(bmp
))) {
508 if (!inner
->refcount
)
509 XFREE(MTYPE_BMP_MIRRORQ
,
513 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
515 bmp
->mirror_lost
= true;
516 pullwr_bump(bmp
->pullwr
);
522 static int bmp_mirror_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
523 struct stream
*packet
)
525 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
527 struct bmp_mirrorq
*qitem
;
528 struct bmp_targets
*bt
;
531 gettimeofday(&tv
, NULL
);
533 if (type
== BGP_MSG_OPEN
) {
534 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
536 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
538 bbpeer
->open_rx_len
= size
;
539 bbpeer
->open_rx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
540 memcpy(bbpeer
->open_rx
, packet
->data
, size
);
546 qitem
= XCALLOC(MTYPE_BMP_MIRRORQ
, sizeof(*qitem
) + size
);
547 qitem
->peerid
= peer
->qobj_node
.nid
;
550 memcpy(qitem
->data
, packet
->data
, size
);
552 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
555 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
558 bmp
->mirrorpos
= qitem
;
559 pullwr_bump(bmp
->pullwr
);
562 if (qitem
->refcount
== 0)
563 XFREE(MTYPE_BMP_MIRRORQ
, qitem
);
565 bmpbgp
->mirror_qsize
+= sizeof(*qitem
) + size
;
566 bmp_mirrorq_add_tail(&bmpbgp
->mirrorq
, qitem
);
568 bmp_mirror_cull(bmpbgp
);
570 bmpbgp
->mirror_qsizemax
= MAX(bmpbgp
->mirror_qsizemax
,
571 bmpbgp
->mirror_qsize
);
576 static void bmp_wrmirror_lost(struct bmp
*bmp
, struct pullwr
*pullwr
)
581 gettimeofday(&tv
, NULL
);
583 s
= stream_new(BGP_MAX_PACKET_SIZE
);
585 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
586 bmp_per_peer_hdr(s
, bmp
->targets
->bgp
->peer_self
, 0, &tv
);
588 stream_putw(s
, BMP_MIRROR_TLV_TYPE_INFO
);
590 stream_putw(s
, BMP_MIRROR_INFO_CODE_LOSTMSGS
);
591 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
));
593 bmp
->cnt_mirror_overruns
++;
594 pullwr_write_stream(bmp
->pullwr
, s
);
598 static bool bmp_wrmirror(struct bmp
*bmp
, struct pullwr
*pullwr
)
600 struct bmp_mirrorq
*bmq
;
602 bool written
= false;
604 if (bmp
->mirror_lost
) {
605 bmp_wrmirror_lost(bmp
, pullwr
);
606 bmp
->mirror_lost
= false;
610 bmq
= bmp_pull_mirror(bmp
);
614 peer
= QOBJ_GET_TYPESAFE(bmq
->peerid
, peer
);
616 zlog_info("bmp: skipping mirror message for deleted peer");
621 s
= stream_new(BGP_MAX_PACKET_SIZE
);
623 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MIRRORING
);
624 bmp_per_peer_hdr(s
, peer
, 0, &bmq
->tv
);
626 /* BMP Mirror TLV. */
627 stream_putw(s
, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE
);
628 stream_putw(s
, bmq
->len
);
629 stream_putl_at(s
, BMP_LENGTH_POS
, stream_get_endp(s
) + bmq
->len
);
632 pullwr_write_stream(bmp
->pullwr
, s
);
633 pullwr_write(bmp
->pullwr
, bmq
->data
, bmq
->len
);
640 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
644 static int bmp_outgoing_packet(struct peer
*peer
, uint8_t type
, bgp_size_t size
,
645 struct stream
*packet
)
647 if (type
== BGP_MSG_OPEN
) {
648 struct bmp_bgp_peer
*bbpeer
= bmp_bgp_peer_get(peer
);
650 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
652 bbpeer
->open_tx_len
= size
;
653 bbpeer
->open_tx
= XMALLOC(MTYPE_BMP_OPEN
, size
);
654 memcpy(bbpeer
->open_tx
, packet
->data
, size
);
659 static int bmp_peer_established(struct peer
*peer
)
661 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
666 /* Check if this peer just went to Established */
667 if ((peer
->last_major_event
!= OpenConfirm
) ||
668 !(peer_established(peer
)))
671 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
672 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
674 bbpeer
= bmp_bgp_peer_get(peer
);
675 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
677 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
678 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
680 bbpeer
->open_tx
= bbdopp
->open_tx
;
681 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
682 bbpeer
->open_rx
= bbdopp
->open_rx
;
683 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
685 bmp_peerh_del(&bmp_peerh
, bbdopp
);
686 XFREE(MTYPE_BMP_PEER
, bbdopp
);
690 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
694 static int bmp_peer_backward(struct peer
*peer
)
696 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
697 struct bmp_bgp_peer
*bbpeer
;
702 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
704 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
705 bbpeer
->open_tx_len
= 0;
706 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
707 bbpeer
->open_rx_len
= 0;
710 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
714 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
717 struct listnode
*node
;
718 struct stream
*s
, *s2
;
720 iana_safi_t pkt_safi
;
722 s
= stream_new(BGP_MAX_PACKET_SIZE
);
724 /* Make BGP update packet. */
725 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
727 /* Unfeasible Routes Length */
730 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
731 /* Total Path Attribute Length */
734 /* Convert AFI, SAFI to values for packet. */
735 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
737 /* Total Path Attribute Length */
739 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
740 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
742 stream_putw(s
, pkt_afi
);
743 stream_putc(s
, pkt_safi
);
746 bgp_packet_set_size(s
);
748 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
749 if (!peer
->afc_nego
[afi
][safi
])
752 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
754 bmp_common_hdr(s2
, BMP_VERSION_3
,
755 BMP_TYPE_ROUTE_MONITORING
);
756 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
758 stream_putl_at(s2
, BMP_LENGTH_POS
,
759 stream_get_endp(s
) + stream_get_endp(s2
));
762 pullwr_write_stream(bmp
->pullwr
, s2
);
763 pullwr_write_stream(bmp
->pullwr
, s
);
769 static struct stream
*bmp_update(struct prefix
*p
, struct peer
*peer
,
770 struct attr
*attr
, afi_t afi
, safi_t safi
)
772 struct bpacket_attr_vec_arr vecarr
;
774 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
775 bgp_size_t total_attr_len
= 0;
777 bpacket_attr_vec_arr_reset(&vecarr
);
779 s
= stream_new(BGP_MAX_PACKET_SIZE
);
780 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
782 /* 2: withdrawn routes length */
785 /* 3: total attributes length - attrlen_pos stores the position */
786 attrlen_pos
= stream_get_endp(s
);
789 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
790 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
791 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
795 /* peer_cap_enhe & add-path removed */
796 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
797 stream_put_prefix(s
, p
);
799 size_t p1
= stream_get_endp(s
);
801 /* MPLS removed for now */
803 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
805 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, NULL
, NULL
, 0,
807 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
808 total_attr_len
+= stream_get_endp(s
) - p1
;
811 /* set the total attribute length correctly */
812 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
813 bgp_packet_set_size(s
);
817 static struct stream
*bmp_withdraw(struct prefix
*p
, afi_t afi
, safi_t safi
)
820 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
821 bgp_size_t total_attr_len
= 0;
822 bgp_size_t unfeasible_len
;
824 s
= stream_new(BGP_MAX_PACKET_SIZE
);
826 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
829 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
830 stream_put_prefix(s
, p
);
831 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
832 - BGP_UNFEASIBLE_LEN
;
833 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
836 attrlen_pos
= stream_get_endp(s
);
837 /* total attr length = 0 for now. reevaluate later */
839 mp_start
= stream_get_endp(s
);
840 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
842 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, NULL
, NULL
, 0,
844 /* Set the mp_unreach attr's length */
845 bgp_packet_mpunreach_end(s
, mplen_pos
);
847 /* Set total path attribute length. */
848 total_attr_len
= stream_get_endp(s
) - mp_start
;
849 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
852 bgp_packet_set_size(s
);
856 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
857 struct prefix
*p
, struct attr
*attr
, afi_t afi
,
858 safi_t safi
, time_t uptime
)
860 struct stream
*hdr
, *msg
;
861 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
864 msg
= bmp_update(p
, peer
, attr
, afi
, safi
);
866 msg
= bmp_withdraw(p
, afi
, safi
);
868 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
869 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
870 bmp_per_peer_hdr(hdr
, peer
, flags
, &tv
);
872 stream_putl_at(hdr
, BMP_LENGTH_POS
,
873 stream_get_endp(hdr
) + stream_get_endp(msg
));
876 pullwr_write_stream(bmp
->pullwr
, hdr
);
877 pullwr_write_stream(bmp
->pullwr
, msg
);
882 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
887 if (bmp
->syncafi
== AFI_MAX
) {
888 FOREACH_AFI_SAFI (afi
, safi
) {
889 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
892 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
895 bmp
->syncsafi
= safi
;
897 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
898 bmp
->syncpos
.family
= afi2family(afi
);
899 zlog_info("bmp[%s] %s %s sending table",
901 afi2str(bmp
->syncafi
),
902 safi2str(bmp
->syncsafi
));
903 /* break does not work here, 2 loops... */
906 if (bmp
->syncafi
== AFI_MAX
)
912 safi
= bmp
->syncsafi
;
914 if (!bmp
->targets
->afimon
[afi
][safi
]) {
915 /* shouldn't happen */
916 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
917 bmp
->syncafi
= AFI_MAX
;
918 bmp
->syncsafi
= SAFI_MAX
;
922 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
924 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
925 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
927 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
930 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
932 zlog_info("bmp[%s] %s %s table completed (EoR)",
933 bmp
->remote
, afi2str(afi
),
935 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
936 bmp_eor(bmp
, afi
, safi
, 0);
938 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
939 bmp
->syncafi
= AFI_MAX
;
940 bmp
->syncsafi
= SAFI_MAX
;
944 prefix_copy(&bmp
->syncpos
, &bn
->p
);
947 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
948 for (bpiter
= bn
->info
; bpiter
; bpiter
= bpiter
->next
) {
949 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
951 if (bpiter
->peer
->qobj_node
.nid
954 if (bpi
&& bpiter
->peer
->qobj_node
.nid
955 > bpi
->peer
->qobj_node
.nid
)
960 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
961 for (adjiter
= bn
->adj_in
; adjiter
;
962 adjiter
= adjiter
->next
) {
963 if (adjiter
->peer
->qobj_node
.nid
966 if (adjin
&& adjiter
->peer
->qobj_node
.nid
967 > adjin
->peer
->qobj_node
.nid
)
979 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
981 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
982 } else if (adjin
&& bpi
983 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
985 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
987 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
989 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
993 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, &bn
->p
, bpi
->attr
,
994 afi
, safi
, bpi
->uptime
);
996 bmp_monitor(bmp
, adjin
->peer
, 0, &bn
->p
, adjin
->attr
,
997 afi
, safi
, adjin
->uptime
);
1002 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
1004 struct bmp_queue_entry
*bqe
;
1006 bqe
= bmp
->queuepos
;
1010 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1013 if (!bqe
->refcount
) {
1014 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1015 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1020 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1022 struct bmp_queue_entry
*bqe
;
1024 struct bgp_node
*bn
;
1025 bool written
= false;
1027 bqe
= bmp_pull(bmp
);
1031 afi_t afi
= bqe
->afi
;
1032 safi_t safi
= bqe
->safi
;
1034 switch (bmp
->afistate
[afi
][safi
]) {
1035 case BMP_AFI_INACTIVE
:
1036 case BMP_AFI_NEEDSYNC
:
1039 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1040 /* currently syncing but have already passed this
1041 * prefix => send it. */
1044 /* currently syncing & haven't reached this prefix yet
1045 * => it'll be sent as part of the table sync, no need here */
1051 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1053 zlog_info("bmp: skipping queued item for deleted peer");
1056 if (peer
->status
!= Established
)
1059 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1061 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1062 struct bgp_path_info
*bpi
;
1064 for (bpi
= bn
? bn
->info
: NULL
; bpi
; bpi
= bpi
->next
) {
1065 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1067 if (bpi
->peer
== peer
)
1071 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
,
1072 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1073 bpi
? bpi
->uptime
: monotime(NULL
));
1077 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1078 struct bgp_adj_in
*adjin
;
1080 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1081 adjin
= adjin
->next
) {
1082 if (adjin
->peer
== peer
)
1085 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
,
1086 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1087 adjin
? adjin
->uptime
: monotime(NULL
));
1093 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1097 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1099 switch(bmp
->state
) {
1101 bmp_send_peerup(bmp
);
1102 bmp
->state
= BMP_Run
;
1106 if (bmp_wrmirror(bmp
, pullwr
))
1108 if (bmp_wrqueue(bmp
, pullwr
))
1110 if (bmp_wrsync(bmp
, pullwr
))
1116 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1119 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1121 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1122 bmp
->remote
, strerror(errno
));
1128 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
,
1129 afi_t afi
, safi_t safi
, struct bgp_node
*bn
, struct peer
*peer
)
1132 struct bmp_queue_entry
*bqe
, bqeref
;
1136 prefix2str(&bn
->p
, buf
, sizeof(buf
));
1138 refcount
= bmp_session_count(&bt
->sessions
);
1142 memset(&bqeref
, 0, sizeof(bqeref
));
1143 prefix_copy(&bqeref
.p
, &bn
->p
);
1144 bqeref
.peerid
= peer
->qobj_node
.nid
;
1148 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1150 if (bqe
->refcount
>= refcount
)
1151 /* nothing to do here */
1154 bmp_qlist_del(&bt
->updlist
, bqe
);
1156 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1157 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1159 bmp_qhash_add(&bt
->updhash
, bqe
);
1162 bqe
->refcount
= refcount
;
1163 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1165 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1167 bmp
->queuepos
= bqe
;
1170 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1171 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
)
1173 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1174 struct bmp_targets
*bt
;
1180 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1181 if (!bt
->afimon
[afi
][safi
])
1184 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1186 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1187 pullwr_bump(bmp
->pullwr
);
1193 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1196 stream_putw(s
, type
);
1198 stream_putl(s
, value
);
1202 static int bmp_stats(struct thread
*thread
)
1204 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1207 struct listnode
*node
;
1211 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1214 gettimeofday(&tv
, NULL
);
1216 /* Walk down all peers */
1217 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1218 size_t count
= 0, count_pos
, len
;
1220 if (peer
->status
!= Established
)
1223 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1224 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1225 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1227 count_pos
= stream_get_endp(s
);
1230 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1231 peer
->stat_pfx_filter
);
1232 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1233 peer
->stat_pfx_aspath_loop
);
1234 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1235 peer
->stat_pfx_originator_loop
);
1236 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1237 peer
->stat_pfx_cluster_loop
);
1238 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1239 peer
->stat_pfx_dup_withdraw
);
1240 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1241 peer
->stat_upd_7606
);
1242 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1243 peer
->stat_pfx_nh_invalid
);
1245 stream_putl_at(s
, count_pos
, count
);
1247 len
= stream_get_endp(s
);
1248 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1250 bmp_send_all(bt
->bmpbgp
, s
);
1255 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1257 union sockunion su
, *sumem
;
1260 struct access_list
*acl
= NULL
;
1261 enum filter_type ret
;
1262 char buf
[SU_ADDRSTRLEN
];
1265 sumem
= sockunion_getpeername(bmp_sock
);
1270 memcpy(&su
, sumem
, sizeof(su
));
1271 sockunion_free(sumem
);
1273 set_nonblocking(bmp_sock
);
1274 set_cloexec(bmp_sock
);
1275 shutdown(bmp_sock
, SHUT_RD
);
1277 sockunion2hostprefix(&su
, &p
);
1282 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1285 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1291 ret
= FILTER_PERMIT
;
1293 ret
= access_list_apply(acl
, &p
);
1296 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1297 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1298 su
.sa
.sa_family
== AF_INET
1299 ? ntohs(su
.sin
.sin_port
)
1300 : ntohs(su
.sin6
.sin6_port
));
1302 if (ret
== FILTER_DENY
) {
1303 bt
->cnt_aclrefused
++;
1304 zlog_info("bmp[%s] connection refused by access-list", buf
);
1310 setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
));
1311 setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
));
1313 zlog_info("bmp[%s] connection established", buf
);
1315 /* Allocate new BMP structure and set up default values. */
1316 bmp
= bmp_new(bt
, bmp_sock
);
1317 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1319 bmp
->state
= BMP_PeerUp
;
1320 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1322 bmp_send_initiation(bmp
);
1327 /* Accept BMP connection. */
1328 static int bmp_accept(struct thread
*thread
)
1331 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1334 /* We continue hearing BMP socket. */
1335 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1337 memset(&su
, 0, sizeof(union sockunion
));
1339 /* We can handle IPv4 or IPv6 socket. */
1340 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1342 zlog_info("bmp: accept_sock failed: %s\n",
1343 safe_strerror (errno
));
1346 bmp_open(bl
->targets
, bmp_sock
);
1350 static void bmp_close(struct bmp
*bmp
)
1352 struct bmp_queue_entry
*bqe
;
1353 struct bmp_mirrorq
*bmq
;
1356 bmp_active_disconnected(bmp
->active
);
1358 while ((bmq
= bmp_pull_mirror(bmp
)))
1360 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1361 while ((bqe
= bmp_pull(bmp
)))
1363 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1365 THREAD_OFF(bmp
->t_read
);
1366 pullwr_del(bmp
->pullwr
);
1370 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1372 struct bmp_bgp dummy
= { .bgp
= bgp
};
1373 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1376 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1378 struct bmp_bgp
*bmpbgp
;
1380 bmpbgp
= bmp_bgp_find(bgp
);
1384 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1386 bmpbgp
->mirror_qsizelimit
= ~0UL;
1387 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1388 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1393 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1395 struct bmp_targets
*bt
;
1397 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1399 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1400 bmp_targets_put(bt
);
1402 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1403 XFREE(MTYPE_BMP
, bmpbgp
);
1406 static int bmp_bgp_del(struct bgp
*bgp
)
1408 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1411 bmp_bgp_put(bmpbgp
);
1415 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1417 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1418 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1421 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1423 struct bmp_bgp_peer
*bbpeer
;
1425 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1429 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1430 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1431 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1436 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1438 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1439 struct bmp_targets dummy
;
1443 dummy
.name
= (char *)name
;
1444 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1447 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1449 struct bmp_targets
*bt
;
1451 bt
= bmp_targets_find1(bgp
, name
);
1455 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1456 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1458 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1459 bmp_session_init(&bt
->sessions
);
1460 bmp_qhash_init(&bt
->updhash
);
1461 bmp_qlist_init(&bt
->updlist
);
1462 bmp_actives_init(&bt
->actives
);
1463 bmp_listeners_init(&bt
->listeners
);
1465 QOBJ_REG(bt
, bmp_targets
);
1466 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1470 static void bmp_targets_put(struct bmp_targets
*bt
)
1473 struct bmp_active
*ba
;
1475 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1478 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1483 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1486 bmp_listeners_fini(&bt
->listeners
);
1487 bmp_actives_fini(&bt
->actives
);
1488 bmp_qhash_fini(&bt
->updhash
);
1489 bmp_qlist_fini(&bt
->updlist
);
1491 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1492 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1493 bmp_session_fini(&bt
->sessions
);
1495 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1496 XFREE(MTYPE_BMP_TARGETS
, bt
);
1499 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1500 const union sockunion
*su
,
1503 struct bmp_listener dummy
;
1506 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1509 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1510 const union sockunion
*su
,
1513 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1518 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1524 bmp_listeners_add(&bt
->listeners
, bl
);
1528 static void bmp_listener_put(struct bmp_listener
*bl
)
1530 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1531 XFREE(MTYPE_BMP_LISTENER
, bl
);
1534 static void bmp_listener_start(struct bmp_listener
*bl
)
1538 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1542 sockopt_reuseaddr(sock
);
1543 sockopt_reuseport(sock
);
1544 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1547 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1551 ret
= listen(sock
, 3);
1556 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1562 static void bmp_listener_stop(struct bmp_listener
*bl
)
1564 THREAD_OFF(bl
->t_accept
);
1571 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1572 const char *hostname
, int port
)
1574 struct bmp_active dummy
;
1575 dummy
.hostname
= (char *)hostname
;
1577 return bmp_actives_find(&bt
->actives
, &dummy
);
1580 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1581 const char *hostname
, int port
)
1583 struct bmp_active
*ba
;
1585 ba
= bmp_active_find(bt
, hostname
, port
);
1589 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1591 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1593 ba
->minretry
= BMP_DFLT_MINRETRY
;
1594 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1597 bmp_actives_add(&bt
->actives
, ba
);
1601 static void bmp_active_put(struct bmp_active
*ba
)
1603 THREAD_OFF(ba
->t_timer
);
1604 THREAD_OFF(ba
->t_read
);
1605 THREAD_OFF(ba
->t_write
);
1607 bmp_actives_del(&ba
->targets
->actives
, ba
);
1610 ba
->bmp
->active
= NULL
;
1614 if (ba
->socket
!= -1)
1617 XFREE(MTYPE_TMP
, ba
->hostname
);
1618 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1621 static void bmp_active_setup(struct bmp_active
*ba
);
1623 static void bmp_active_connect(struct bmp_active
*ba
)
1625 enum connect_result res
;
1626 char buf
[SU_ADDRSTRLEN
];
1628 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1629 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1630 if (ba
->socket
< 0) {
1631 zlog_warn("bmp[%s]: failed to create socket",
1636 set_nonblocking(ba
->socket
);
1637 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1638 htons(ba
->port
), 0);
1641 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1643 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1644 ba
->hostname
, buf
, ba
->port
);
1648 case connect_success
:
1650 case connect_in_progress
:
1651 bmp_active_setup(ba
);
1656 /* exhausted all addresses */
1657 ba
->curretry
+= ba
->curretry
/ 2;
1658 bmp_active_setup(ba
);
1661 static void bmp_active_resolved(struct resolver_query
*resq
, int numaddrs
,
1662 union sockunion
*addr
)
1664 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1667 if (numaddrs
<= 0) {
1668 zlog_warn("bmp[%s]: hostname resolution failed", ba
->hostname
);
1669 ba
->curretry
+= ba
->curretry
/ 2;
1670 bmp_active_setup(ba
);
1673 if (numaddrs
> (int)array_size(ba
->addrs
))
1674 numaddrs
= array_size(ba
->addrs
);
1677 ba
->addrtotal
= numaddrs
;
1678 for (i
= 0; i
< ba
->addrtotal
; i
++)
1679 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1681 bmp_active_connect(ba
);
1684 static int bmp_active_thread(struct thread
*t
)
1686 struct bmp_active
*ba
= THREAD_ARG(t
);
1689 char buf
[SU_ADDRSTRLEN
];
1691 /* all 3 end up here, though only timer or read+write are active
1693 THREAD_OFF(ba
->t_timer
);
1694 THREAD_OFF(ba
->t_read
);
1695 THREAD_OFF(ba
->t_write
);
1697 if (ba
->socket
== -1) {
1698 resolver_resolve(&ba
->resq
, AF_UNSPEC
, ba
->hostname
,
1699 bmp_active_resolved
);
1703 slen
= sizeof(status
);
1704 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1707 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1708 if (ret
< 0 || status
!= 0) {
1709 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1710 ba
->hostname
, buf
, ba
->port
);
1714 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1715 ba
->hostname
, buf
, ba
->port
);
1717 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1721 ba
->bmp
->active
= ba
;
1723 ba
->curretry
= ba
->minretry
;
1730 bmp_active_connect(ba
);
1734 static void bmp_active_disconnected(struct bmp_active
*ba
)
1737 bmp_active_setup(ba
);
1740 static void bmp_active_setup(struct bmp_active
*ba
)
1742 THREAD_OFF(ba
->t_timer
);
1743 THREAD_OFF(ba
->t_read
);
1744 THREAD_OFF(ba
->t_write
);
1748 if (ba
->resq
.callback
)
1751 if (ba
->curretry
> ba
->maxretry
)
1752 ba
->curretry
= ba
->maxretry
;
1754 if (ba
->socket
== -1)
1755 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1756 ba
->curretry
, &ba
->t_timer
);
1758 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1760 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1765 static struct cmd_node bmp_node
= {BMP_NODE
, "%s(config-bgp-bmp)# "};
1767 #define BMP_STR "BGP Monitoring Protocol\n"
1769 #ifndef VTYSH_EXTRACT_PL
1770 #include "bgp_bmp_clippy.c"
1773 DEFPY_NOSH(bmp_targets_main
,
1775 "bmp targets BMPTARGETS",
1777 "Create BMP target group\n"
1778 "Name of the BMP target group\n")
1780 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1781 struct bmp_targets
*bt
;
1783 bt
= bmp_targets_get(bgp
, bmptargets
);
1785 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1789 DEFPY(no_bmp_targets_main
,
1791 "no bmp targets BMPTARGETS",
1794 "Delete BMP target group\n"
1795 "Name of the BMP target group\n")
1797 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1798 struct bmp_targets
*bt
;
1800 bt
= bmp_targets_find1(bgp
, bmptargets
);
1802 vty_out(vty
, "%% BMP target group not found\n");
1805 bmp_targets_put(bt
);
1809 DEFPY(bmp_listener_main
,
1811 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1813 "Listen for inbound BMP connections\n"
1814 "IPv6 address to listen on\n"
1815 "IPv4 address to listen on\n"
1817 "TCP Port number\n")
1819 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1820 struct bmp_listener
*bl
;
1822 bl
= bmp_listener_get(bt
, listener
, port
);
1824 bmp_listener_start(bl
);
1829 DEFPY(no_bmp_listener_main
,
1830 no_bmp_listener_cmd
,
1831 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1834 "Create BMP listener\n"
1835 "IPv6 address to listen on\n"
1836 "IPv4 address to listen on\n"
1838 "TCP Port number\n")
1840 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1841 struct bmp_listener
*bl
;
1843 bl
= bmp_listener_find(bt
, listener
, port
);
1845 vty_out(vty
, "%% BMP listener not found\n");
1848 bmp_listener_stop(bl
);
1849 bmp_listener_put(bl
);
1855 "[no] bmp connect HOSTNAME port (1-65535) "
1856 "{min-retry (100-86400000)"
1857 "|max-retry (100-86400000)}",
1860 "Actively establish connection to monitoring station\n"
1861 "Monitoring station hostname or address\n"
1864 "Minimum connection retry interval\n"
1865 "Minimum connection retry interval (milliseconds)\n"
1866 "Maximum connection retry interval\n"
1867 "Maximum connection retry interval (milliseconds)\n")
1869 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1870 struct bmp_active
*ba
;
1873 ba
= bmp_active_find(bt
, hostname
, port
);
1875 vty_out(vty
, "%% No such active connection found\n");
1882 ba
= bmp_active_get(bt
, hostname
, port
);
1884 ba
->minretry
= min_retry
;
1886 ba
->maxretry
= max_retry
;
1887 ba
->curretry
= ba
->minretry
;
1888 bmp_active_setup(ba
);
1895 "[no] <ip|ipv6>$af access-list WORD",
1899 "Access list to restrict BMP sessions\n"
1900 "Access list name\n")
1902 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1907 if (!strcmp(af
, "ipv6"))
1908 what
= &bt
->acl6_name
;
1910 what
= &bt
->acl_name
;
1912 XFREE(MTYPE_BMP_ACLNAME
, *what
);
1914 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
1919 DEFPY(bmp_stats_cfg
,
1921 "[no] bmp stats [interval (100-86400000)]",
1924 "Send BMP statistics messages\n"
1925 "Specify BMP stats interval\n"
1926 "Interval (milliseconds) to send BMP Stats in\n")
1928 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1930 THREAD_OFF(bt
->t_stats
);
1933 else if (interval_str
)
1934 bt
->stat_msec
= interval
;
1936 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
1939 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1944 DEFPY(bmp_monitor_cfg
,
1946 "[no] bmp monitor "BGP_AFI_CMD_STR
" <unicast|multicast> <pre-policy|post-policy>$policy",
1949 "Send BMP route monitoring messages\n"
1951 "Address family modifier\n"
1952 "Address family modifier\n"
1953 "Send state before policy and filter processing\n"
1954 "Send state with policy and filters applied\n")
1961 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1964 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
1965 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
1967 if (policy
[1] == 'r')
1968 flag
= BMP_MON_PREPOLICY
;
1970 flag
= BMP_MON_POSTPOLICY
;
1972 prev
= bt
->afimon
[afi
][safi
];
1974 bt
->afimon
[afi
][safi
] &= ~flag
;
1976 bt
->afimon
[afi
][safi
] |= flag
;
1978 if (prev
== bt
->afimon
[afi
][safi
])
1981 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
1982 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
1983 bmp
->syncafi
= AFI_MAX
;
1984 bmp
->syncsafi
= SAFI_MAX
;
1987 if (!bt
->afimon
[afi
][safi
]) {
1988 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
1992 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
1998 DEFPY(bmp_mirror_cfg
,
2003 "Send BMP route mirroring messages\n")
2005 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2008 if (bt
->mirror
== !no
)
2015 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2016 struct bmp_mirrorq
*bmq
;
2018 while ((bmq
= bmp_pull_mirror(bmp
)))
2020 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2025 DEFPY(bmp_mirror_limit_cfg
,
2026 bmp_mirror_limit_cmd
,
2027 "bmp mirror buffer-limit (0-4294967294)",
2029 "Route Mirroring settings\n"
2030 "Configure maximum memory used for buffered mirroring messages\n"
2033 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2034 struct bmp_bgp
*bmpbgp
;
2036 bmpbgp
= bmp_bgp_get(bgp
);
2037 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2042 DEFPY(no_bmp_mirror_limit_cfg
,
2043 no_bmp_mirror_limit_cmd
,
2044 "no bmp mirror buffer-limit [(0-4294967294)]",
2047 "Route Mirroring settings\n"
2048 "Configure maximum memory used for buffered mirroring messages\n"
2051 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2052 struct bmp_bgp
*bmpbgp
;
2054 bmpbgp
= bmp_bgp_get(bgp
);
2055 bmpbgp
->mirror_qsizelimit
= ~0UL;
2067 struct bmp_bgp
*bmpbgp
;
2068 struct bmp_targets
*bt
;
2069 struct bmp_listener
*bl
;
2072 char buf
[SU_ADDRSTRLEN
];
2074 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2075 vty_out(vty
, "BMP state for BGP %s:\n\n",
2076 bmpbgp
->bgp
->name_pretty
);
2077 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2078 bmpbgp
->mirror_qsize
,
2079 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2080 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2081 bmpbgp
->mirror_qsizemax
);
2082 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2083 vty_out(vty
, " %9zu bytes buffer size limit\n",
2084 bmpbgp
->mirror_qsizelimit
);
2087 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2088 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2089 vty_out(vty
, " Route Mirroring %sabled\n",
2090 bt
->mirror
? "en" : "dis");
2095 FOREACH_AFI_SAFI (afi
, safi
) {
2096 const char *str
= NULL
;
2098 switch (bt
->afimon
[afi
][safi
]) {
2099 case BMP_MON_PREPOLICY
:
2102 case BMP_MON_POSTPOLICY
:
2103 str
= "post-policy";
2105 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2106 str
= "pre-policy and post-policy";
2111 vty_out(vty
, " Route Monitoring %s %s %s\n",
2112 afi2str(afi
), safi2str(safi
), str
);
2115 vty_out(vty
, " Listeners:\n");
2116 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2117 vty_out(vty
, " %s:%d\n",
2118 sockunion2str(&bl
->addr
, buf
,
2119 SU_ADDRSTRLEN
), bl
->port
);
2121 vty_out(vty
, "\n %zu connected clients:\n",
2122 bmp_session_count(&bt
->sessions
));
2123 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2124 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2125 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2127 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2131 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2133 ttable_add_row(tt
, "%s|-|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2137 bmp
->cnt_mirror_overruns
,
2140 char *out
= ttable_dump(tt
, "\n");
2141 vty_out(vty
, "%s", out
);
2142 XFREE(MTYPE_TMP
, out
);
2151 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2153 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2154 struct bmp_targets
*bt
;
2155 struct bmp_listener
*bl
;
2156 struct bmp_active
*ba
;
2157 char buf
[SU_ADDRSTRLEN
];
2164 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2165 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2166 bmpbgp
->mirror_qsizelimit
);
2168 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2169 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2172 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2174 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2177 vty_out(vty
, " bmp stats interval %d\n",
2181 vty_out(vty
, " bmp mirror\n");
2183 FOREACH_AFI_SAFI (afi
, safi
) {
2184 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2186 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2187 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2188 afi_str
, safi2str(safi
));
2189 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2190 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2191 afi_str
, safi2str(safi
));
2193 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2194 vty_out(vty
, " \n bmp listener %s port %d\n",
2195 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2198 frr_each (bmp_actives
, &bt
->actives
, ba
)
2199 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2200 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2206 static int bgp_bmp_init(struct thread_master
*tm
)
2208 install_node(&bmp_node
, NULL
);
2209 install_default(BMP_NODE
);
2210 install_element(BGP_NODE
, &bmp_targets_cmd
);
2211 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2213 install_element(BMP_NODE
, &bmp_listener_cmd
);
2214 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2215 install_element(BMP_NODE
, &bmp_connect_cmd
);
2216 install_element(BMP_NODE
, &bmp_acl_cmd
);
2217 install_element(BMP_NODE
, &bmp_stats_cmd
);
2218 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2219 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2221 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2222 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2224 install_element(VIEW_NODE
, &show_bmp_cmd
);
2230 static int bgp_bmp_module_init(void)
2232 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2233 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2234 hook_register(peer_status_changed
, bmp_peer_established
);
2235 hook_register(peer_backward_transition
, bmp_peer_backward
);
2236 hook_register(bgp_process
, bmp_process
);
2237 hook_register(bgp_inst_config_write
, bmp_config_write
);
2238 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2239 hook_register(frr_late_init
, bgp_bmp_init
);
2243 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2244 .description
= "bgpd BMP module",
2245 .init
= bgp_bmp_module_init
)