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 if (peer
->doppelganger
&& (peer
->doppelganger
->status
!= Deleted
)) {
667 struct bmp_bgp_peer
*bbpeer
, *bbdopp
;
669 bbpeer
= bmp_bgp_peer_get(peer
);
670 bbdopp
= bmp_bgp_peer_find(peer
->doppelganger
->qobj_node
.nid
);
672 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
673 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
675 bbpeer
->open_tx
= bbdopp
->open_tx
;
676 bbpeer
->open_tx_len
= bbdopp
->open_tx_len
;
677 bbpeer
->open_rx
= bbdopp
->open_rx
;
678 bbpeer
->open_rx_len
= bbdopp
->open_rx_len
;
680 bmp_peerh_del(&bmp_peerh
, bbdopp
);
681 XFREE(MTYPE_BMP_PEER
, bbdopp
);
685 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, false));
689 static int bmp_peer_backward(struct peer
*peer
)
691 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
692 struct bmp_bgp_peer
*bbpeer
;
697 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
699 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_tx
);
700 bbpeer
->open_tx_len
= 0;
701 XFREE(MTYPE_BMP_OPEN
, bbpeer
->open_rx
);
702 bbpeer
->open_rx_len
= 0;
705 bmp_send_all(bmpbgp
, bmp_peerstate(peer
, true));
709 static void bmp_eor(struct bmp
*bmp
, afi_t afi
, safi_t safi
, uint8_t flags
)
712 struct listnode
*node
;
713 struct stream
*s
, *s2
;
715 iana_safi_t pkt_safi
;
717 s
= stream_new(BGP_MAX_PACKET_SIZE
);
719 /* Make BGP update packet. */
720 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
722 /* Unfeasible Routes Length */
725 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
726 /* Total Path Attribute Length */
729 /* Convert AFI, SAFI to values for packet. */
730 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
732 /* Total Path Attribute Length */
734 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
735 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
737 stream_putw(s
, pkt_afi
);
738 stream_putc(s
, pkt_safi
);
741 bgp_packet_set_size(s
);
743 for (ALL_LIST_ELEMENTS_RO(bmp
->targets
->bgp
->peer
, node
, peer
)) {
744 if (!peer
->afc_nego
[afi
][safi
])
747 s2
= stream_new(BGP_MAX_PACKET_SIZE
);
749 bmp_common_hdr(s2
, BMP_VERSION_3
,
750 BMP_TYPE_ROUTE_MONITORING
);
751 bmp_per_peer_hdr(s2
, peer
, flags
, NULL
);
753 stream_putl_at(s2
, BMP_LENGTH_POS
,
754 stream_get_endp(s
) + stream_get_endp(s2
));
757 pullwr_write_stream(bmp
->pullwr
, s2
);
758 pullwr_write_stream(bmp
->pullwr
, s
);
764 static struct stream
*bmp_update(struct prefix
*p
, struct peer
*peer
,
765 struct attr
*attr
, afi_t afi
, safi_t safi
)
767 struct bpacket_attr_vec_arr vecarr
;
769 size_t attrlen_pos
= 0, mpattrlen_pos
= 0;
770 bgp_size_t total_attr_len
= 0;
772 bpacket_attr_vec_arr_reset(&vecarr
);
774 s
= stream_new(BGP_MAX_PACKET_SIZE
);
775 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
777 /* 2: withdrawn routes length */
780 /* 3: total attributes length - attrlen_pos stores the position */
781 attrlen_pos
= stream_get_endp(s
);
784 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
785 total_attr_len
= bgp_packet_attribute(NULL
, peer
, s
, attr
,
786 &vecarr
, NULL
, afi
, safi
, peer
, NULL
, NULL
, 0, 0, 0);
790 /* peer_cap_enhe & add-path removed */
791 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
792 stream_put_prefix(s
, p
);
794 size_t p1
= stream_get_endp(s
);
796 /* MPLS removed for now */
798 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
800 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, NULL
, NULL
, 0,
802 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
803 total_attr_len
+= stream_get_endp(s
) - p1
;
806 /* set the total attribute length correctly */
807 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
808 bgp_packet_set_size(s
);
812 static struct stream
*bmp_withdraw(struct prefix
*p
, afi_t afi
, safi_t safi
)
815 size_t attrlen_pos
= 0, mp_start
, mplen_pos
;
816 bgp_size_t total_attr_len
= 0;
817 bgp_size_t unfeasible_len
;
819 s
= stream_new(BGP_MAX_PACKET_SIZE
);
821 bgp_packet_set_marker(s
, BGP_MSG_UPDATE
);
824 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
825 stream_put_prefix(s
, p
);
826 unfeasible_len
= stream_get_endp(s
) - BGP_HEADER_SIZE
827 - BGP_UNFEASIBLE_LEN
;
828 stream_putw_at(s
, BGP_HEADER_SIZE
, unfeasible_len
);
831 attrlen_pos
= stream_get_endp(s
);
832 /* total attr length = 0 for now. reevaluate later */
834 mp_start
= stream_get_endp(s
);
835 mplen_pos
= bgp_packet_mpunreach_start(s
, afi
, safi
);
837 bgp_packet_mpunreach_prefix(s
, p
, afi
, safi
, NULL
, NULL
, 0,
839 /* Set the mp_unreach attr's length */
840 bgp_packet_mpunreach_end(s
, mplen_pos
);
842 /* Set total path attribute length. */
843 total_attr_len
= stream_get_endp(s
) - mp_start
;
844 stream_putw_at(s
, attrlen_pos
, total_attr_len
);
847 bgp_packet_set_size(s
);
851 static void bmp_monitor(struct bmp
*bmp
, struct peer
*peer
, uint8_t flags
,
852 struct prefix
*p
, struct attr
*attr
, afi_t afi
,
853 safi_t safi
, time_t uptime
)
855 struct stream
*hdr
, *msg
;
856 struct timeval tv
= { .tv_sec
= uptime
, .tv_usec
= 0 };
859 msg
= bmp_update(p
, peer
, attr
, afi
, safi
);
861 msg
= bmp_withdraw(p
, afi
, safi
);
863 hdr
= stream_new(BGP_MAX_PACKET_SIZE
);
864 bmp_common_hdr(hdr
, BMP_VERSION_3
, BMP_TYPE_ROUTE_MONITORING
);
865 bmp_per_peer_hdr(hdr
, peer
, flags
, &tv
);
867 stream_putl_at(hdr
, BMP_LENGTH_POS
,
868 stream_get_endp(hdr
) + stream_get_endp(msg
));
871 pullwr_write_stream(bmp
->pullwr
, hdr
);
872 pullwr_write_stream(bmp
->pullwr
, msg
);
877 static bool bmp_wrsync(struct bmp
*bmp
, struct pullwr
*pullwr
)
882 if (bmp
->syncafi
== AFI_MAX
) {
883 FOREACH_AFI_SAFI (afi
, safi
) {
884 if (bmp
->afistate
[afi
][safi
] != BMP_AFI_NEEDSYNC
)
887 bmp
->afistate
[afi
][safi
] = BMP_AFI_SYNC
;
890 bmp
->syncsafi
= safi
;
892 memset(&bmp
->syncpos
, 0, sizeof(bmp
->syncpos
));
893 bmp
->syncpos
.family
= afi2family(afi
);
894 zlog_info("bmp[%s] %s %s sending table",
896 afi2str(bmp
->syncafi
),
897 safi2str(bmp
->syncsafi
));
898 /* break does not work here, 2 loops... */
901 if (bmp
->syncafi
== AFI_MAX
)
907 safi
= bmp
->syncsafi
;
909 if (!bmp
->targets
->afimon
[afi
][safi
]) {
910 /* shouldn't happen */
911 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
912 bmp
->syncafi
= AFI_MAX
;
913 bmp
->syncsafi
= SAFI_MAX
;
917 struct bgp_table
*table
= bmp
->targets
->bgp
->rib
[afi
][safi
];
919 struct bgp_path_info
*bpi
= NULL
, *bpiter
;
920 struct bgp_adj_in
*adjin
= NULL
, *adjiter
;
922 bn
= bgp_node_lookup(table
, &bmp
->syncpos
);
925 bn
= bgp_table_get_next(table
, &bmp
->syncpos
);
927 zlog_info("bmp[%s] %s %s table completed (EoR)",
928 bmp
->remote
, afi2str(afi
),
930 bmp_eor(bmp
, afi
, safi
, BMP_PEER_FLAG_L
);
931 bmp_eor(bmp
, afi
, safi
, 0);
933 bmp
->afistate
[afi
][safi
] = BMP_AFI_LIVE
;
934 bmp
->syncafi
= AFI_MAX
;
935 bmp
->syncsafi
= SAFI_MAX
;
939 prefix_copy(&bmp
->syncpos
, &bn
->p
);
942 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
943 for (bpiter
= bn
->info
; bpiter
; bpiter
= bpiter
->next
) {
944 if (!CHECK_FLAG(bpiter
->flags
, BGP_PATH_VALID
))
946 if (bpiter
->peer
->qobj_node
.nid
949 if (bpi
&& bpiter
->peer
->qobj_node
.nid
950 > bpi
->peer
->qobj_node
.nid
)
955 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
956 for (adjiter
= bn
->adj_in
; adjiter
;
957 adjiter
= adjiter
->next
) {
958 if (adjiter
->peer
->qobj_node
.nid
961 if (adjin
&& adjiter
->peer
->qobj_node
.nid
962 > adjin
->peer
->qobj_node
.nid
)
974 && adjin
->peer
->qobj_node
.nid
< bpi
->peer
->qobj_node
.nid
) {
976 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
977 } else if (adjin
&& bpi
978 && adjin
->peer
->qobj_node
.nid
> bpi
->peer
->qobj_node
.nid
) {
980 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
982 bmp
->syncpeerid
= bpi
->peer
->qobj_node
.nid
;
984 bmp
->syncpeerid
= adjin
->peer
->qobj_node
.nid
;
988 bmp_monitor(bmp
, bpi
->peer
, BMP_PEER_FLAG_L
, &bn
->p
, bpi
->attr
,
989 afi
, safi
, bpi
->uptime
);
991 bmp_monitor(bmp
, adjin
->peer
, 0, &bn
->p
, adjin
->attr
,
992 afi
, safi
, adjin
->uptime
);
997 static struct bmp_queue_entry
*bmp_pull(struct bmp
*bmp
)
999 struct bmp_queue_entry
*bqe
;
1001 bqe
= bmp
->queuepos
;
1005 bmp
->queuepos
= bmp_qlist_next(&bmp
->targets
->updlist
, bqe
);
1008 if (!bqe
->refcount
) {
1009 bmp_qhash_del(&bmp
->targets
->updhash
, bqe
);
1010 bmp_qlist_del(&bmp
->targets
->updlist
, bqe
);
1015 static bool bmp_wrqueue(struct bmp
*bmp
, struct pullwr
*pullwr
)
1017 struct bmp_queue_entry
*bqe
;
1019 struct bgp_node
*bn
;
1020 bool written
= false;
1022 bqe
= bmp_pull(bmp
);
1026 afi_t afi
= bqe
->afi
;
1027 safi_t safi
= bqe
->safi
;
1029 switch (bmp
->afistate
[afi
][safi
]) {
1030 case BMP_AFI_INACTIVE
:
1031 case BMP_AFI_NEEDSYNC
:
1034 if (prefix_cmp(&bqe
->p
, &bmp
->syncpos
) <= 0)
1035 /* currently syncing but have already passed this
1036 * prefix => send it. */
1039 /* currently syncing & haven't reached this prefix yet
1040 * => it'll be sent as part of the table sync, no need here */
1046 peer
= QOBJ_GET_TYPESAFE(bqe
->peerid
, peer
);
1048 zlog_info("bmp: skipping queued item for deleted peer");
1051 if (peer
->status
!= Established
)
1054 bn
= bgp_node_lookup(bmp
->targets
->bgp
->rib
[afi
][safi
], &bqe
->p
);
1056 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
) {
1057 struct bgp_path_info
*bpi
;
1059 for (bpi
= bn
? bn
->info
: NULL
; bpi
; bpi
= bpi
->next
) {
1060 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_VALID
))
1062 if (bpi
->peer
== peer
)
1066 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
,
1067 bpi
? bpi
->attr
: NULL
, afi
, safi
,
1068 bpi
? bpi
->uptime
: monotime(NULL
));
1072 if (bmp
->targets
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
) {
1073 struct bgp_adj_in
*adjin
;
1075 for (adjin
= bn
? bn
->adj_in
: NULL
; adjin
;
1076 adjin
= adjin
->next
) {
1077 if (adjin
->peer
== peer
)
1080 bmp_monitor(bmp
, peer
, BMP_PEER_FLAG_L
, &bqe
->p
,
1081 adjin
? adjin
->attr
: NULL
, afi
, safi
,
1082 adjin
? adjin
->uptime
: monotime(NULL
));
1088 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1092 static void bmp_wrfill(struct bmp
*bmp
, struct pullwr
*pullwr
)
1094 switch(bmp
->state
) {
1096 bmp_send_peerup(bmp
);
1097 bmp
->state
= BMP_Run
;
1101 if (bmp_wrmirror(bmp
, pullwr
))
1103 if (bmp_wrqueue(bmp
, pullwr
))
1105 if (bmp_wrsync(bmp
, pullwr
))
1111 static void bmp_wrerr(struct bmp
*bmp
, struct pullwr
*pullwr
, bool eof
)
1114 zlog_info("bmp[%s] disconnected", bmp
->remote
);
1116 flog_warn(EC_LIB_SYSTEM_CALL
, "bmp[%s] connection error: %s",
1117 bmp
->remote
, strerror(errno
));
1123 static void bmp_process_one(struct bmp_targets
*bt
, struct bgp
*bgp
,
1124 afi_t afi
, safi_t safi
, struct bgp_node
*bn
, struct peer
*peer
)
1127 struct bmp_queue_entry
*bqe
, bqeref
;
1131 prefix2str(&bn
->p
, buf
, sizeof(buf
));
1133 refcount
= bmp_session_count(&bt
->sessions
);
1137 memset(&bqeref
, 0, sizeof(bqeref
));
1138 prefix_copy(&bqeref
.p
, &bn
->p
);
1139 bqeref
.peerid
= peer
->qobj_node
.nid
;
1143 bqe
= bmp_qhash_find(&bt
->updhash
, &bqeref
);
1145 if (bqe
->refcount
>= refcount
)
1146 /* nothing to do here */
1149 bmp_qlist_del(&bt
->updlist
, bqe
);
1151 bqe
= XMALLOC(MTYPE_BMP_QUEUE
, sizeof(*bqe
));
1152 memcpy(bqe
, &bqeref
, sizeof(*bqe
));
1154 bmp_qhash_add(&bt
->updhash
, bqe
);
1157 bqe
->refcount
= refcount
;
1158 bmp_qlist_add_tail(&bt
->updlist
, bqe
);
1160 frr_each (bmp_session
, &bt
->sessions
, bmp
)
1162 bmp
->queuepos
= bqe
;
1165 static int bmp_process(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1166 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
)
1168 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(peer
->bgp
);
1169 struct bmp_targets
*bt
;
1175 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
1176 if (!bt
->afimon
[afi
][safi
])
1179 bmp_process_one(bt
, bgp
, afi
, safi
, bn
, peer
);
1181 frr_each(bmp_session
, &bt
->sessions
, bmp
) {
1182 pullwr_bump(bmp
->pullwr
);
1188 static void bmp_stat_put_u32(struct stream
*s
, size_t *cnt
, uint16_t type
,
1191 stream_putw(s
, type
);
1193 stream_putl(s
, value
);
1197 static int bmp_stats(struct thread
*thread
)
1199 struct bmp_targets
*bt
= THREAD_ARG(thread
);
1202 struct listnode
*node
;
1206 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1209 gettimeofday(&tv
, NULL
);
1211 /* Walk down all peers */
1212 for (ALL_LIST_ELEMENTS_RO(bt
->bgp
->peer
, node
, peer
)) {
1213 size_t count
= 0, count_pos
, len
;
1215 if (peer
->status
!= Established
)
1218 s
= stream_new(BGP_MAX_PACKET_SIZE
);
1219 bmp_common_hdr(s
, BMP_VERSION_3
, BMP_TYPE_STATISTICS_REPORT
);
1220 bmp_per_peer_hdr(s
, peer
, 0, &tv
);
1222 count_pos
= stream_get_endp(s
);
1225 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_REJECTED
,
1226 peer
->stat_pfx_filter
);
1227 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ASPATH
,
1228 peer
->stat_pfx_aspath_loop
);
1229 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_ORIGINATOR
,
1230 peer
->stat_pfx_originator_loop
);
1231 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_LOOP_CLUSTER
,
1232 peer
->stat_pfx_cluster_loop
);
1233 bmp_stat_put_u32(s
, &count
, BMP_STATS_PFX_DUP_WITHDRAW
,
1234 peer
->stat_pfx_dup_withdraw
);
1235 bmp_stat_put_u32(s
, &count
, BMP_STATS_UPD_7606_WITHDRAW
,
1236 peer
->stat_upd_7606
);
1237 bmp_stat_put_u32(s
, &count
, BMP_STATS_FRR_NH_INVALID
,
1238 peer
->stat_pfx_nh_invalid
);
1240 stream_putl_at(s
, count_pos
, count
);
1242 len
= stream_get_endp(s
);
1243 stream_putl_at(s
, BMP_LENGTH_POS
, len
);
1245 bmp_send_all(bt
->bmpbgp
, s
);
1250 static struct bmp
*bmp_open(struct bmp_targets
*bt
, int bmp_sock
)
1252 union sockunion su
, *sumem
;
1255 struct access_list
*acl
= NULL
;
1256 enum filter_type ret
;
1257 char buf
[SU_ADDRSTRLEN
];
1260 sumem
= sockunion_getpeername(bmp_sock
);
1265 memcpy(&su
, sumem
, sizeof(su
));
1266 sockunion_free(sumem
);
1268 set_nonblocking(bmp_sock
);
1269 set_cloexec(bmp_sock
);
1270 shutdown(bmp_sock
, SHUT_RD
);
1272 sockunion2hostprefix(&su
, &p
);
1277 acl
= access_list_lookup(AFI_IP
, bt
->acl_name
);
1280 acl
= access_list_lookup(AFI_IP6
, bt
->acl6_name
);
1286 ret
= FILTER_PERMIT
;
1288 ret
= access_list_apply(acl
, &p
);
1291 sockunion2str(&su
, buf
, SU_ADDRSTRLEN
);
1292 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), ":%u",
1293 su
.sa
.sa_family
== AF_INET
1294 ? ntohs(su
.sin
.sin_port
)
1295 : ntohs(su
.sin6
.sin6_port
));
1297 if (ret
== FILTER_DENY
) {
1298 bt
->cnt_aclrefused
++;
1299 zlog_info("bmp[%s] connection refused by access-list", buf
);
1305 setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
));
1306 setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
));
1308 zlog_info("bmp[%s] connection established", buf
);
1310 /* Allocate new BMP structure and set up default values. */
1311 bmp
= bmp_new(bt
, bmp_sock
);
1312 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1314 bmp
->state
= BMP_PeerUp
;
1315 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1317 bmp_send_initiation(bmp
);
1322 /* Accept BMP connection. */
1323 static int bmp_accept(struct thread
*thread
)
1326 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1329 /* We continue hearing BMP socket. */
1330 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1332 memset(&su
, 0, sizeof(union sockunion
));
1334 /* We can handle IPv4 or IPv6 socket. */
1335 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1337 zlog_info("bmp: accept_sock failed: %s\n",
1338 safe_strerror (errno
));
1341 bmp_open(bl
->targets
, bmp_sock
);
1345 static void bmp_close(struct bmp
*bmp
)
1347 struct bmp_queue_entry
*bqe
;
1348 struct bmp_mirrorq
*bmq
;
1351 bmp_active_disconnected(bmp
->active
);
1353 while ((bmq
= bmp_pull_mirror(bmp
)))
1355 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1356 while ((bqe
= bmp_pull(bmp
)))
1358 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1360 THREAD_OFF(bmp
->t_read
);
1361 pullwr_del(bmp
->pullwr
);
1365 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1367 struct bmp_bgp dummy
= { .bgp
= bgp
};
1368 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1371 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1373 struct bmp_bgp
*bmpbgp
;
1375 bmpbgp
= bmp_bgp_find(bgp
);
1379 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1381 bmpbgp
->mirror_qsizelimit
= ~0UL;
1382 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1383 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1388 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1390 struct bmp_targets
*bt
;
1392 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1394 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1395 bmp_targets_put(bt
);
1397 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1398 XFREE(MTYPE_BMP
, bmpbgp
);
1401 static int bmp_bgp_del(struct bgp
*bgp
)
1403 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1406 bmp_bgp_put(bmpbgp
);
1410 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1412 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1413 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1416 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1418 struct bmp_bgp_peer
*bbpeer
;
1420 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1424 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1425 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1426 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1431 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1433 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1434 struct bmp_targets dummy
;
1438 dummy
.name
= (char *)name
;
1439 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1442 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1444 struct bmp_targets
*bt
;
1446 bt
= bmp_targets_find1(bgp
, name
);
1450 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1451 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1453 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1454 bmp_session_init(&bt
->sessions
);
1455 bmp_qhash_init(&bt
->updhash
);
1456 bmp_qlist_init(&bt
->updlist
);
1457 bmp_actives_init(&bt
->actives
);
1458 bmp_listeners_init(&bt
->listeners
);
1460 QOBJ_REG(bt
, bmp_targets
);
1461 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1465 static void bmp_targets_put(struct bmp_targets
*bt
)
1468 struct bmp_active
*ba
;
1470 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1473 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1478 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1481 bmp_listeners_fini(&bt
->listeners
);
1482 bmp_actives_fini(&bt
->actives
);
1483 bmp_qhash_fini(&bt
->updhash
);
1484 bmp_qlist_fini(&bt
->updlist
);
1486 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1487 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1488 bmp_session_fini(&bt
->sessions
);
1490 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1491 XFREE(MTYPE_BMP_TARGETS
, bt
);
1494 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1495 const union sockunion
*su
,
1498 struct bmp_listener dummy
;
1501 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1504 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1505 const union sockunion
*su
,
1508 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1513 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1519 bmp_listeners_add(&bt
->listeners
, bl
);
1523 static void bmp_listener_put(struct bmp_listener
*bl
)
1525 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1526 XFREE(MTYPE_BMP_LISTENER
, bl
);
1529 static void bmp_listener_start(struct bmp_listener
*bl
)
1533 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1537 sockopt_reuseaddr(sock
);
1538 sockopt_reuseport(sock
);
1539 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1542 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1546 ret
= listen(sock
, 3);
1551 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1557 static void bmp_listener_stop(struct bmp_listener
*bl
)
1559 THREAD_OFF(bl
->t_accept
);
1566 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1567 const char *hostname
, int port
)
1569 struct bmp_active dummy
;
1570 dummy
.hostname
= (char *)hostname
;
1572 return bmp_actives_find(&bt
->actives
, &dummy
);
1575 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1576 const char *hostname
, int port
)
1578 struct bmp_active
*ba
;
1580 ba
= bmp_active_find(bt
, hostname
, port
);
1584 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1586 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1588 ba
->minretry
= BMP_DFLT_MINRETRY
;
1589 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1592 bmp_actives_add(&bt
->actives
, ba
);
1596 static void bmp_active_put(struct bmp_active
*ba
)
1598 THREAD_OFF(ba
->t_timer
);
1599 THREAD_OFF(ba
->t_read
);
1600 THREAD_OFF(ba
->t_write
);
1602 bmp_actives_del(&ba
->targets
->actives
, ba
);
1605 ba
->bmp
->active
= NULL
;
1609 if (ba
->socket
!= -1)
1612 XFREE(MTYPE_TMP
, ba
->hostname
);
1613 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1616 static void bmp_active_setup(struct bmp_active
*ba
);
1618 static void bmp_active_connect(struct bmp_active
*ba
)
1620 enum connect_result res
;
1621 char buf
[SU_ADDRSTRLEN
];
1623 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1624 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1625 if (ba
->socket
< 0) {
1626 zlog_warn("bmp[%s]: failed to create socket",
1631 set_nonblocking(ba
->socket
);
1632 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1633 htons(ba
->port
), 0);
1636 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1638 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1639 ba
->hostname
, buf
, ba
->port
);
1643 case connect_success
:
1645 case connect_in_progress
:
1646 bmp_active_setup(ba
);
1651 /* exhausted all addresses */
1652 ba
->curretry
+= ba
->curretry
/ 2;
1653 bmp_active_setup(ba
);
1656 static void bmp_active_resolved(struct resolver_query
*resq
, int numaddrs
,
1657 union sockunion
*addr
)
1659 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1662 if (numaddrs
<= 0) {
1663 zlog_warn("bmp[%s]: hostname resolution failed", ba
->hostname
);
1664 ba
->curretry
+= ba
->curretry
/ 2;
1665 bmp_active_setup(ba
);
1668 if (numaddrs
> (int)array_size(ba
->addrs
))
1669 numaddrs
= array_size(ba
->addrs
);
1672 ba
->addrtotal
= numaddrs
;
1673 for (i
= 0; i
< ba
->addrtotal
; i
++)
1674 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1676 bmp_active_connect(ba
);
1679 static int bmp_active_thread(struct thread
*t
)
1681 struct bmp_active
*ba
= THREAD_ARG(t
);
1684 char buf
[SU_ADDRSTRLEN
];
1686 /* all 3 end up here, though only timer or read+write are active
1688 THREAD_OFF(ba
->t_timer
);
1689 THREAD_OFF(ba
->t_read
);
1690 THREAD_OFF(ba
->t_write
);
1692 if (ba
->socket
== -1) {
1693 resolver_resolve(&ba
->resq
, AF_UNSPEC
, ba
->hostname
,
1694 bmp_active_resolved
);
1698 slen
= sizeof(status
);
1699 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1702 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1703 if (ret
< 0 || status
!= 0) {
1704 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1705 ba
->hostname
, buf
, ba
->port
);
1709 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1710 ba
->hostname
, buf
, ba
->port
);
1712 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1716 ba
->bmp
->active
= ba
;
1718 ba
->curretry
= ba
->minretry
;
1725 bmp_active_connect(ba
);
1729 static void bmp_active_disconnected(struct bmp_active
*ba
)
1732 bmp_active_setup(ba
);
1735 static void bmp_active_setup(struct bmp_active
*ba
)
1737 THREAD_OFF(ba
->t_timer
);
1738 THREAD_OFF(ba
->t_read
);
1739 THREAD_OFF(ba
->t_write
);
1743 if (ba
->resq
.callback
)
1746 if (ba
->curretry
> ba
->maxretry
)
1747 ba
->curretry
= ba
->maxretry
;
1749 if (ba
->socket
== -1)
1750 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1751 ba
->curretry
, &ba
->t_timer
);
1753 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1755 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1760 static struct cmd_node bmp_node
= {BMP_NODE
, "%s(config-bgp-bmp)# "};
1762 #define BMP_STR "BGP Monitoring Protocol\n"
1764 #ifndef VTYSH_EXTRACT_PL
1765 #include "bgp_bmp_clippy.c"
1768 DEFPY_NOSH(bmp_targets_main
,
1770 "bmp targets BMPTARGETS",
1772 "Create BMP target group\n"
1773 "Name of the BMP target group\n")
1775 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1776 struct bmp_targets
*bt
;
1778 bt
= bmp_targets_get(bgp
, bmptargets
);
1780 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1784 DEFPY(no_bmp_targets_main
,
1786 "no bmp targets BMPTARGETS",
1789 "Delete BMP target group\n"
1790 "Name of the BMP target group\n")
1792 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1793 struct bmp_targets
*bt
;
1795 bt
= bmp_targets_find1(bgp
, bmptargets
);
1797 vty_out(vty
, "%% BMP target group not found\n");
1800 bmp_targets_put(bt
);
1804 DEFPY(bmp_listener_main
,
1806 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1808 "Listen for inbound BMP connections\n"
1809 "IPv6 address to listen on\n"
1810 "IPv4 address to listen on\n"
1812 "TCP Port number\n")
1814 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1815 struct bmp_listener
*bl
;
1817 bl
= bmp_listener_get(bt
, listener
, port
);
1819 bmp_listener_start(bl
);
1824 DEFPY(no_bmp_listener_main
,
1825 no_bmp_listener_cmd
,
1826 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1829 "Create BMP listener\n"
1830 "IPv6 address to listen on\n"
1831 "IPv4 address to listen on\n"
1833 "TCP Port number\n")
1835 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1836 struct bmp_listener
*bl
;
1838 bl
= bmp_listener_find(bt
, listener
, port
);
1840 vty_out(vty
, "%% BMP listener not found\n");
1843 bmp_listener_stop(bl
);
1844 bmp_listener_put(bl
);
1850 "[no] bmp connect HOSTNAME port (1-65535) "
1851 "{min-retry (100-86400000)"
1852 "|max-retry (100-86400000)}",
1855 "Actively establish connection to monitoring station\n"
1856 "Monitoring station hostname or address\n"
1859 "Minimum connection retry interval\n"
1860 "Minimum connection retry interval (milliseconds)\n"
1861 "Maximum connection retry interval\n"
1862 "Maximum connection retry interval (milliseconds)\n")
1864 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1865 struct bmp_active
*ba
;
1868 ba
= bmp_active_find(bt
, hostname
, port
);
1870 vty_out(vty
, "%% No such active connection found\n");
1877 ba
= bmp_active_get(bt
, hostname
, port
);
1879 ba
->minretry
= min_retry
;
1881 ba
->maxretry
= max_retry
;
1882 ba
->curretry
= ba
->minretry
;
1883 bmp_active_setup(ba
);
1890 "[no] <ip|ipv6>$af access-list WORD",
1894 "Access list to restrict BMP sessions\n"
1895 "Access list name\n")
1897 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1902 if (!strcmp(af
, "ipv6"))
1903 what
= &bt
->acl6_name
;
1905 what
= &bt
->acl_name
;
1907 XFREE(MTYPE_BMP_ACLNAME
, *what
);
1909 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
1914 DEFPY(bmp_stats_cfg
,
1916 "[no] bmp stats [interval (100-86400000)]",
1919 "Send BMP statistics messages\n"
1920 "Specify BMP stats interval\n"
1921 "Interval (milliseconds) to send BMP Stats in\n")
1923 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1925 THREAD_OFF(bt
->t_stats
);
1928 else if (interval_str
)
1929 bt
->stat_msec
= interval
;
1931 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
1934 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1939 DEFPY(bmp_monitor_cfg
,
1941 "[no] bmp monitor "BGP_AFI_CMD_STR
" <unicast|multicast> <pre-policy|post-policy>$policy",
1944 "Send BMP route monitoring messages\n"
1946 "Address family modifier\n"
1947 "Address family modifier\n"
1948 "Send state before policy and filter processing\n"
1949 "Send state with policy and filters applied\n")
1956 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1959 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
1960 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
1962 if (policy
[1] == 'r')
1963 flag
= BMP_MON_PREPOLICY
;
1965 flag
= BMP_MON_POSTPOLICY
;
1967 prev
= bt
->afimon
[afi
][safi
];
1969 bt
->afimon
[afi
][safi
] &= ~flag
;
1971 bt
->afimon
[afi
][safi
] |= flag
;
1973 if (prev
== bt
->afimon
[afi
][safi
])
1976 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
1977 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
1978 bmp
->syncafi
= AFI_MAX
;
1979 bmp
->syncsafi
= SAFI_MAX
;
1982 if (!bt
->afimon
[afi
][safi
]) {
1983 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
1987 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
1993 DEFPY(bmp_mirror_cfg
,
1998 "Send BMP route mirroring messages\n")
2000 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2003 if (bt
->mirror
== !no
)
2010 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2011 struct bmp_mirrorq
*bmq
;
2013 while ((bmq
= bmp_pull_mirror(bmp
)))
2015 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2020 DEFPY(bmp_mirror_limit_cfg
,
2021 bmp_mirror_limit_cmd
,
2022 "bmp mirror buffer-limit (0-4294967294)",
2024 "Route Mirroring settings\n"
2025 "Configure maximum memory used for buffered mirroring messages\n"
2028 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2029 struct bmp_bgp
*bmpbgp
;
2031 bmpbgp
= bmp_bgp_get(bgp
);
2032 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2037 DEFPY(no_bmp_mirror_limit_cfg
,
2038 no_bmp_mirror_limit_cmd
,
2039 "no bmp mirror buffer-limit [(0-4294967294)]",
2042 "Route Mirroring settings\n"
2043 "Configure maximum memory used for buffered mirroring messages\n"
2046 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2047 struct bmp_bgp
*bmpbgp
;
2049 bmpbgp
= bmp_bgp_get(bgp
);
2050 bmpbgp
->mirror_qsizelimit
= ~0UL;
2062 struct bmp_bgp
*bmpbgp
;
2063 struct bmp_targets
*bt
;
2064 struct bmp_listener
*bl
;
2067 char buf
[SU_ADDRSTRLEN
];
2069 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2070 vty_out(vty
, "BMP state for BGP %s:\n\n",
2071 bmpbgp
->bgp
->name_pretty
);
2072 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2073 bmpbgp
->mirror_qsize
,
2074 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2075 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2076 bmpbgp
->mirror_qsizemax
);
2077 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2078 vty_out(vty
, " %9zu bytes buffer size limit\n",
2079 bmpbgp
->mirror_qsizelimit
);
2082 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2083 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2084 vty_out(vty
, " Route Mirroring %sabled\n",
2085 bt
->mirror
? "en" : "dis");
2090 FOREACH_AFI_SAFI (afi
, safi
) {
2091 const char *str
= NULL
;
2093 switch (bt
->afimon
[afi
][safi
]) {
2094 case BMP_MON_PREPOLICY
:
2097 case BMP_MON_POSTPOLICY
:
2098 str
= "post-policy";
2100 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2101 str
= "pre-policy and post-policy";
2106 vty_out(vty
, " Route Monitoring %s %s %s\n",
2107 afi2str(afi
), safi2str(safi
), str
);
2110 vty_out(vty
, " Listeners:\n");
2111 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2112 vty_out(vty
, " %s:%d\n",
2113 sockunion2str(&bl
->addr
, buf
,
2114 SU_ADDRSTRLEN
), bl
->port
);
2116 vty_out(vty
, "\n %zu connected clients:\n",
2117 bmp_session_count(&bt
->sessions
));
2118 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2119 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2120 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2122 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2126 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2128 ttable_add_row(tt
, "%s|-|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2132 bmp
->cnt_mirror_overruns
,
2135 char *out
= ttable_dump(tt
, "\n");
2136 vty_out(vty
, "%s", out
);
2137 XFREE(MTYPE_TMP
, out
);
2146 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2148 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2149 struct bmp_targets
*bt
;
2150 struct bmp_listener
*bl
;
2151 struct bmp_active
*ba
;
2152 char buf
[SU_ADDRSTRLEN
];
2159 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2160 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2161 bmpbgp
->mirror_qsizelimit
);
2163 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2164 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2167 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2169 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2172 vty_out(vty
, " bmp stats interval %d\n",
2176 vty_out(vty
, " bmp mirror\n");
2178 FOREACH_AFI_SAFI (afi
, safi
) {
2179 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2181 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2182 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2183 afi_str
, safi2str(safi
));
2184 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2185 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2186 afi_str
, safi2str(safi
));
2188 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2189 vty_out(vty
, " \n bmp listener %s port %d\n",
2190 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2193 frr_each (bmp_actives
, &bt
->actives
, ba
)
2194 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2195 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2201 static int bgp_bmp_init(struct thread_master
*tm
)
2203 install_node(&bmp_node
, NULL
);
2204 install_default(BMP_NODE
);
2205 install_element(BGP_NODE
, &bmp_targets_cmd
);
2206 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2208 install_element(BMP_NODE
, &bmp_listener_cmd
);
2209 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2210 install_element(BMP_NODE
, &bmp_connect_cmd
);
2211 install_element(BMP_NODE
, &bmp_acl_cmd
);
2212 install_element(BMP_NODE
, &bmp_stats_cmd
);
2213 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2214 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2216 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2217 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2219 install_element(VIEW_NODE
, &show_bmp_cmd
);
2225 static int bgp_bmp_module_init(void)
2227 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2228 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2229 hook_register(peer_established
, bmp_peer_established
);
2230 hook_register(peer_backward_transition
, bmp_peer_backward
);
2231 hook_register(bgp_process
, bmp_process
);
2232 hook_register(bgp_inst_config_write
, bmp_config_write
);
2233 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2234 hook_register(frr_late_init
, bgp_bmp_init
);
2238 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2239 .description
= "bgpd BMP module",
2240 .init
= bgp_bmp_module_init
)