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 if (setsockopt(bmp_sock
, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof(on
)) < 0)
1311 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1312 bmp_sock
, safe_strerror(errno
), errno
);
1313 if (setsockopt(bmp_sock
, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
1314 flog_err(EC_LIB_SOCKET
, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1315 bmp_sock
, safe_strerror(errno
), errno
);
1317 zlog_info("bmp[%s] connection established", buf
);
1319 /* Allocate new BMP structure and set up default values. */
1320 bmp
= bmp_new(bt
, bmp_sock
);
1321 strlcpy(bmp
->remote
, buf
, sizeof(bmp
->remote
));
1323 bmp
->state
= BMP_PeerUp
;
1324 bmp
->pullwr
= pullwr_new(bm
->master
, bmp_sock
, bmp
, bmp_wrfill
,
1326 bmp_send_initiation(bmp
);
1331 /* Accept BMP connection. */
1332 static int bmp_accept(struct thread
*thread
)
1335 struct bmp_listener
*bl
= THREAD_ARG(thread
);
1338 /* We continue hearing BMP socket. */
1339 thread_add_read(bm
->master
, bmp_accept
, bl
, bl
->sock
, &bl
->t_accept
);
1341 memset(&su
, 0, sizeof(union sockunion
));
1343 /* We can handle IPv4 or IPv6 socket. */
1344 bmp_sock
= sockunion_accept(bl
->sock
, &su
);
1346 zlog_info("bmp: accept_sock failed: %s\n",
1347 safe_strerror (errno
));
1350 bmp_open(bl
->targets
, bmp_sock
);
1354 static void bmp_close(struct bmp
*bmp
)
1356 struct bmp_queue_entry
*bqe
;
1357 struct bmp_mirrorq
*bmq
;
1360 bmp_active_disconnected(bmp
->active
);
1362 while ((bmq
= bmp_pull_mirror(bmp
)))
1364 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
1365 while ((bqe
= bmp_pull(bmp
)))
1367 XFREE(MTYPE_BMP_QUEUE
, bqe
);
1369 THREAD_OFF(bmp
->t_read
);
1370 pullwr_del(bmp
->pullwr
);
1374 static struct bmp_bgp
*bmp_bgp_find(struct bgp
*bgp
)
1376 struct bmp_bgp dummy
= { .bgp
= bgp
};
1377 return bmp_bgph_find(&bmp_bgph
, &dummy
);
1380 static struct bmp_bgp
*bmp_bgp_get(struct bgp
*bgp
)
1382 struct bmp_bgp
*bmpbgp
;
1384 bmpbgp
= bmp_bgp_find(bgp
);
1388 bmpbgp
= XCALLOC(MTYPE_BMP
, sizeof(*bmpbgp
));
1390 bmpbgp
->mirror_qsizelimit
= ~0UL;
1391 bmp_mirrorq_init(&bmpbgp
->mirrorq
);
1392 bmp_bgph_add(&bmp_bgph
, bmpbgp
);
1397 static void bmp_bgp_put(struct bmp_bgp
*bmpbgp
)
1399 struct bmp_targets
*bt
;
1401 bmp_bgph_del(&bmp_bgph
, bmpbgp
);
1403 frr_each_safe(bmp_targets
, &bmpbgp
->targets
, bt
)
1404 bmp_targets_put(bt
);
1406 bmp_mirrorq_fini(&bmpbgp
->mirrorq
);
1407 XFREE(MTYPE_BMP
, bmpbgp
);
1410 static int bmp_bgp_del(struct bgp
*bgp
)
1412 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1415 bmp_bgp_put(bmpbgp
);
1419 static struct bmp_bgp_peer
*bmp_bgp_peer_find(uint64_t peerid
)
1421 struct bmp_bgp_peer dummy
= { .peerid
= peerid
};
1422 return bmp_peerh_find(&bmp_peerh
, &dummy
);
1425 static struct bmp_bgp_peer
*bmp_bgp_peer_get(struct peer
*peer
)
1427 struct bmp_bgp_peer
*bbpeer
;
1429 bbpeer
= bmp_bgp_peer_find(peer
->qobj_node
.nid
);
1433 bbpeer
= XCALLOC(MTYPE_BMP_PEER
, sizeof(*bbpeer
));
1434 bbpeer
->peerid
= peer
->qobj_node
.nid
;
1435 bmp_peerh_add(&bmp_peerh
, bbpeer
);
1440 static struct bmp_targets
*bmp_targets_find1(struct bgp
*bgp
, const char *name
)
1442 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
1443 struct bmp_targets dummy
;
1447 dummy
.name
= (char *)name
;
1448 return bmp_targets_find(&bmpbgp
->targets
, &dummy
);
1451 static struct bmp_targets
*bmp_targets_get(struct bgp
*bgp
, const char *name
)
1453 struct bmp_targets
*bt
;
1455 bt
= bmp_targets_find1(bgp
, name
);
1459 bt
= XCALLOC(MTYPE_BMP_TARGETS
, sizeof(*bt
));
1460 bt
->name
= XSTRDUP(MTYPE_BMP_TARGETSNAME
, name
);
1462 bt
->bmpbgp
= bmp_bgp_get(bgp
);
1463 bmp_session_init(&bt
->sessions
);
1464 bmp_qhash_init(&bt
->updhash
);
1465 bmp_qlist_init(&bt
->updlist
);
1466 bmp_actives_init(&bt
->actives
);
1467 bmp_listeners_init(&bt
->listeners
);
1469 QOBJ_REG(bt
, bmp_targets
);
1470 bmp_targets_add(&bt
->bmpbgp
->targets
, bt
);
1474 static void bmp_targets_put(struct bmp_targets
*bt
)
1477 struct bmp_active
*ba
;
1479 frr_each_safe (bmp_actives
, &bt
->actives
, ba
)
1482 frr_each_safe(bmp_session
, &bt
->sessions
, bmp
) {
1487 bmp_targets_del(&bt
->bmpbgp
->targets
, bt
);
1490 bmp_listeners_fini(&bt
->listeners
);
1491 bmp_actives_fini(&bt
->actives
);
1492 bmp_qhash_fini(&bt
->updhash
);
1493 bmp_qlist_fini(&bt
->updlist
);
1495 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl_name
);
1496 XFREE(MTYPE_BMP_ACLNAME
, bt
->acl6_name
);
1497 bmp_session_fini(&bt
->sessions
);
1499 XFREE(MTYPE_BMP_TARGETSNAME
, bt
->name
);
1500 XFREE(MTYPE_BMP_TARGETS
, bt
);
1503 static struct bmp_listener
*bmp_listener_find(struct bmp_targets
*bt
,
1504 const union sockunion
*su
,
1507 struct bmp_listener dummy
;
1510 return bmp_listeners_find(&bt
->listeners
, &dummy
);
1513 static struct bmp_listener
*bmp_listener_get(struct bmp_targets
*bt
,
1514 const union sockunion
*su
,
1517 struct bmp_listener
*bl
= bmp_listener_find(bt
, su
, port
);
1522 bl
= XCALLOC(MTYPE_BMP_LISTENER
, sizeof(*bl
));
1528 bmp_listeners_add(&bt
->listeners
, bl
);
1532 static void bmp_listener_put(struct bmp_listener
*bl
)
1534 bmp_listeners_del(&bl
->targets
->listeners
, bl
);
1535 XFREE(MTYPE_BMP_LISTENER
, bl
);
1538 static void bmp_listener_start(struct bmp_listener
*bl
)
1542 sock
= socket(bl
->addr
.sa
.sa_family
, SOCK_STREAM
, 0);
1546 sockopt_reuseaddr(sock
);
1547 sockopt_reuseport(sock
);
1548 sockopt_v6only(bl
->addr
.sa
.sa_family
, sock
);
1551 ret
= sockunion_bind(sock
, &bl
->addr
, bl
->port
, &bl
->addr
);
1555 ret
= listen(sock
, 3);
1560 thread_add_read(bm
->master
, bmp_accept
, bl
, sock
, &bl
->t_accept
);
1566 static void bmp_listener_stop(struct bmp_listener
*bl
)
1568 THREAD_OFF(bl
->t_accept
);
1575 static struct bmp_active
*bmp_active_find(struct bmp_targets
*bt
,
1576 const char *hostname
, int port
)
1578 struct bmp_active dummy
;
1579 dummy
.hostname
= (char *)hostname
;
1581 return bmp_actives_find(&bt
->actives
, &dummy
);
1584 static struct bmp_active
*bmp_active_get(struct bmp_targets
*bt
,
1585 const char *hostname
, int port
)
1587 struct bmp_active
*ba
;
1589 ba
= bmp_active_find(bt
, hostname
, port
);
1593 ba
= XCALLOC(MTYPE_BMP_ACTIVE
, sizeof(*ba
));
1595 ba
->hostname
= XSTRDUP(MTYPE_TMP
, hostname
);
1597 ba
->minretry
= BMP_DFLT_MINRETRY
;
1598 ba
->maxretry
= BMP_DFLT_MAXRETRY
;
1601 bmp_actives_add(&bt
->actives
, ba
);
1605 static void bmp_active_put(struct bmp_active
*ba
)
1607 THREAD_OFF(ba
->t_timer
);
1608 THREAD_OFF(ba
->t_read
);
1609 THREAD_OFF(ba
->t_write
);
1611 bmp_actives_del(&ba
->targets
->actives
, ba
);
1614 ba
->bmp
->active
= NULL
;
1618 if (ba
->socket
!= -1)
1621 XFREE(MTYPE_TMP
, ba
->hostname
);
1622 XFREE(MTYPE_BMP_ACTIVE
, ba
);
1625 static void bmp_active_setup(struct bmp_active
*ba
);
1627 static void bmp_active_connect(struct bmp_active
*ba
)
1629 enum connect_result res
;
1630 char buf
[SU_ADDRSTRLEN
];
1632 for (; ba
->addrpos
< ba
->addrtotal
; ba
->addrpos
++) {
1633 ba
->socket
= sockunion_socket(&ba
->addrs
[ba
->addrpos
]);
1634 if (ba
->socket
< 0) {
1635 zlog_warn("bmp[%s]: failed to create socket",
1640 set_nonblocking(ba
->socket
);
1641 res
= sockunion_connect(ba
->socket
, &ba
->addrs
[ba
->addrpos
],
1642 htons(ba
->port
), 0);
1645 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
,
1647 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1648 ba
->hostname
, buf
, ba
->port
);
1652 case connect_success
:
1654 case connect_in_progress
:
1655 bmp_active_setup(ba
);
1660 /* exhausted all addresses */
1661 ba
->curretry
+= ba
->curretry
/ 2;
1662 bmp_active_setup(ba
);
1665 static void bmp_active_resolved(struct resolver_query
*resq
, const char *errstr
,
1666 int numaddrs
, union sockunion
*addr
)
1668 struct bmp_active
*ba
= container_of(resq
, struct bmp_active
, resq
);
1671 if (numaddrs
<= 0) {
1672 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1673 ba
->hostname
, errstr
);
1674 ba
->last_err
= errstr
;
1675 ba
->curretry
+= ba
->curretry
/ 2;
1678 bmp_active_setup(ba
);
1682 if (numaddrs
> (int)array_size(ba
->addrs
))
1683 numaddrs
= array_size(ba
->addrs
);
1686 ba
->addrtotal
= numaddrs
;
1687 for (i
= 0; i
< ba
->addrtotal
; i
++)
1688 memcpy(&ba
->addrs
[i
], &addr
[i
], sizeof(ba
->addrs
[0]));
1690 bmp_active_connect(ba
);
1693 static int bmp_active_thread(struct thread
*t
)
1695 struct bmp_active
*ba
= THREAD_ARG(t
);
1698 char buf
[SU_ADDRSTRLEN
];
1700 /* all 3 end up here, though only timer or read+write are active
1702 THREAD_OFF(ba
->t_timer
);
1703 THREAD_OFF(ba
->t_read
);
1704 THREAD_OFF(ba
->t_write
);
1706 ba
->last_err
= NULL
;
1708 if (ba
->socket
== -1) {
1709 resolver_resolve(&ba
->resq
, AF_UNSPEC
, ba
->hostname
,
1710 bmp_active_resolved
);
1714 slen
= sizeof(status
);
1715 ret
= getsockopt(ba
->socket
, SOL_SOCKET
, SO_ERROR
, (void *)&status
,
1718 sockunion2str(&ba
->addrs
[ba
->addrpos
], buf
, sizeof(buf
));
1719 if (ret
< 0 || status
!= 0) {
1720 ba
->last_err
= strerror(status
);
1721 zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
1722 ba
->hostname
, buf
, ba
->port
, ba
->last_err
);
1726 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1727 ba
->hostname
, buf
, ba
->port
);
1729 ba
->bmp
= bmp_open(ba
->targets
, ba
->socket
);
1733 ba
->bmp
->active
= ba
;
1735 ba
->curretry
= ba
->minretry
;
1742 bmp_active_connect(ba
);
1746 static void bmp_active_disconnected(struct bmp_active
*ba
)
1749 bmp_active_setup(ba
);
1752 static void bmp_active_setup(struct bmp_active
*ba
)
1754 THREAD_OFF(ba
->t_timer
);
1755 THREAD_OFF(ba
->t_read
);
1756 THREAD_OFF(ba
->t_write
);
1760 if (ba
->resq
.callback
)
1763 if (ba
->curretry
> ba
->maxretry
)
1764 ba
->curretry
= ba
->maxretry
;
1766 if (ba
->socket
== -1)
1767 thread_add_timer_msec(bm
->master
, bmp_active_thread
, ba
,
1768 ba
->curretry
, &ba
->t_timer
);
1770 thread_add_read(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1772 thread_add_write(bm
->master
, bmp_active_thread
, ba
, ba
->socket
,
1777 static struct cmd_node bmp_node
= {BMP_NODE
, "%s(config-bgp-bmp)# "};
1779 #define BMP_STR "BGP Monitoring Protocol\n"
1781 #ifndef VTYSH_EXTRACT_PL
1782 #include "bgpd/bgp_bmp_clippy.c"
1785 DEFPY_NOSH(bmp_targets_main
,
1787 "bmp targets BMPTARGETS",
1789 "Create 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_get(bgp
, bmptargets
);
1797 VTY_PUSH_CONTEXT_SUB(BMP_NODE
, bt
);
1801 DEFPY(no_bmp_targets_main
,
1803 "no bmp targets BMPTARGETS",
1806 "Delete BMP target group\n"
1807 "Name of the BMP target group\n")
1809 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
1810 struct bmp_targets
*bt
;
1812 bt
= bmp_targets_find1(bgp
, bmptargets
);
1814 vty_out(vty
, "%% BMP target group not found\n");
1817 bmp_targets_put(bt
);
1821 DEFPY(bmp_listener_main
,
1823 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1825 "Listen for inbound BMP connections\n"
1826 "IPv6 address to listen on\n"
1827 "IPv4 address to listen on\n"
1829 "TCP Port number\n")
1831 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1832 struct bmp_listener
*bl
;
1834 bl
= bmp_listener_get(bt
, listener
, port
);
1836 bmp_listener_start(bl
);
1841 DEFPY(no_bmp_listener_main
,
1842 no_bmp_listener_cmd
,
1843 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1846 "Create BMP listener\n"
1847 "IPv6 address to listen on\n"
1848 "IPv4 address to listen on\n"
1850 "TCP Port number\n")
1852 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1853 struct bmp_listener
*bl
;
1855 bl
= bmp_listener_find(bt
, listener
, port
);
1857 vty_out(vty
, "%% BMP listener not found\n");
1860 bmp_listener_stop(bl
);
1861 bmp_listener_put(bl
);
1867 "[no] bmp connect HOSTNAME port (1-65535) "
1868 "{min-retry (100-86400000)"
1869 "|max-retry (100-86400000)}",
1872 "Actively establish connection to monitoring station\n"
1873 "Monitoring station hostname or address\n"
1876 "Minimum connection retry interval\n"
1877 "Minimum connection retry interval (milliseconds)\n"
1878 "Maximum connection retry interval\n"
1879 "Maximum connection retry interval (milliseconds)\n")
1881 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1882 struct bmp_active
*ba
;
1885 ba
= bmp_active_find(bt
, hostname
, port
);
1887 vty_out(vty
, "%% No such active connection found\n");
1894 ba
= bmp_active_get(bt
, hostname
, port
);
1896 ba
->minretry
= min_retry
;
1898 ba
->maxretry
= max_retry
;
1899 ba
->curretry
= ba
->minretry
;
1900 bmp_active_setup(ba
);
1907 "[no] <ip|ipv6>$af access-list WORD",
1911 "Access list to restrict BMP sessions\n"
1912 "Access list name\n")
1914 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1919 if (!strcmp(af
, "ipv6"))
1920 what
= &bt
->acl6_name
;
1922 what
= &bt
->acl_name
;
1924 XFREE(MTYPE_BMP_ACLNAME
, *what
);
1926 *what
= XSTRDUP(MTYPE_BMP_ACLNAME
, access_list
);
1931 DEFPY(bmp_stats_cfg
,
1933 "[no] bmp stats [interval (100-86400000)]",
1936 "Send BMP statistics messages\n"
1937 "Specify BMP stats interval\n"
1938 "Interval (milliseconds) to send BMP Stats in\n")
1940 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1942 THREAD_OFF(bt
->t_stats
);
1945 else if (interval_str
)
1946 bt
->stat_msec
= interval
;
1948 bt
->stat_msec
= BMP_STAT_DEFAULT_TIMER
;
1951 thread_add_timer_msec(bm
->master
, bmp_stats
, bt
, bt
->stat_msec
,
1956 DEFPY(bmp_monitor_cfg
,
1958 "[no] bmp monitor "BGP_AFI_CMD_STR
" <unicast|multicast> <pre-policy|post-policy>$policy",
1961 "Send BMP route monitoring messages\n"
1963 "Address family modifier\n"
1964 "Address family modifier\n"
1965 "Send state before policy and filter processing\n"
1966 "Send state with policy and filters applied\n")
1973 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
1976 argv_find_and_parse_afi(argv
, argc
, &index
, &afi
);
1977 argv_find_and_parse_safi(argv
, argc
, &index
, &safi
);
1979 if (policy
[1] == 'r')
1980 flag
= BMP_MON_PREPOLICY
;
1982 flag
= BMP_MON_POSTPOLICY
;
1984 prev
= bt
->afimon
[afi
][safi
];
1986 bt
->afimon
[afi
][safi
] &= ~flag
;
1988 bt
->afimon
[afi
][safi
] |= flag
;
1990 if (prev
== bt
->afimon
[afi
][safi
])
1993 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
1994 if (bmp
->syncafi
== afi
&& bmp
->syncsafi
== safi
) {
1995 bmp
->syncafi
= AFI_MAX
;
1996 bmp
->syncsafi
= SAFI_MAX
;
1999 if (!bt
->afimon
[afi
][safi
]) {
2000 bmp
->afistate
[afi
][safi
] = BMP_AFI_INACTIVE
;
2004 bmp
->afistate
[afi
][safi
] = BMP_AFI_NEEDSYNC
;
2010 DEFPY(bmp_mirror_cfg
,
2015 "Send BMP route mirroring messages\n")
2017 VTY_DECLVAR_CONTEXT_SUB(bmp_targets
, bt
);
2020 if (bt
->mirror
== !no
)
2027 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2028 struct bmp_mirrorq
*bmq
;
2030 while ((bmq
= bmp_pull_mirror(bmp
)))
2032 XFREE(MTYPE_BMP_MIRRORQ
, bmq
);
2037 DEFPY(bmp_mirror_limit_cfg
,
2038 bmp_mirror_limit_cmd
,
2039 "bmp mirror buffer-limit (0-4294967294)",
2041 "Route Mirroring settings\n"
2042 "Configure maximum memory used for buffered mirroring messages\n"
2045 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2046 struct bmp_bgp
*bmpbgp
;
2048 bmpbgp
= bmp_bgp_get(bgp
);
2049 bmpbgp
->mirror_qsizelimit
= buffer_limit
;
2054 DEFPY(no_bmp_mirror_limit_cfg
,
2055 no_bmp_mirror_limit_cmd
,
2056 "no bmp mirror buffer-limit [(0-4294967294)]",
2059 "Route Mirroring settings\n"
2060 "Configure maximum memory used for buffered mirroring messages\n"
2063 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
2064 struct bmp_bgp
*bmpbgp
;
2066 bmpbgp
= bmp_bgp_get(bgp
);
2067 bmpbgp
->mirror_qsizelimit
= ~0UL;
2079 struct bmp_bgp
*bmpbgp
;
2080 struct bmp_targets
*bt
;
2081 struct bmp_listener
*bl
;
2082 struct bmp_active
*ba
;
2085 char buf
[SU_ADDRSTRLEN
];
2086 char uptime
[BGP_UPTIME_LEN
];
2089 frr_each(bmp_bgph
, &bmp_bgph
, bmpbgp
) {
2090 vty_out(vty
, "BMP state for BGP %s:\n\n",
2091 bmpbgp
->bgp
->name_pretty
);
2092 vty_out(vty
, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2093 bmpbgp
->mirror_qsize
,
2094 bmp_mirrorq_count(&bmpbgp
->mirrorq
));
2095 vty_out(vty
, " %9zu bytes maximum buffer used\n",
2096 bmpbgp
->mirror_qsizemax
);
2097 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2098 vty_out(vty
, " %9zu bytes buffer size limit\n",
2099 bmpbgp
->mirror_qsizelimit
);
2102 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2103 vty_out(vty
, " Targets \"%s\":\n", bt
->name
);
2104 vty_out(vty
, " Route Mirroring %sabled\n",
2105 bt
->mirror
? "en" : "dis");
2110 FOREACH_AFI_SAFI (afi
, safi
) {
2111 const char *str
= NULL
;
2113 switch (bt
->afimon
[afi
][safi
]) {
2114 case BMP_MON_PREPOLICY
:
2117 case BMP_MON_POSTPOLICY
:
2118 str
= "post-policy";
2120 case BMP_MON_PREPOLICY
| BMP_MON_POSTPOLICY
:
2121 str
= "pre-policy and post-policy";
2126 vty_out(vty
, " Route Monitoring %s %s %s\n",
2127 afi2str(afi
), safi2str(safi
), str
);
2130 vty_out(vty
, " Listeners:\n");
2131 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2132 vty_out(vty
, " %s:%d\n",
2133 sockunion2str(&bl
->addr
, buf
,
2134 SU_ADDRSTRLEN
), bl
->port
);
2136 vty_out(vty
, "\n Outbound connections:\n");
2137 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2138 ttable_add_row(tt
, "remote|state||timer");
2139 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2140 frr_each (bmp_actives
, &bt
->actives
, ba
) {
2141 const char *state_str
= "?";
2144 peer_uptime(ba
->bmp
->t_up
.tv_sec
,
2145 uptime
, sizeof(uptime
),
2147 ttable_add_row(tt
, "%s:%d|Up|%s|%s",
2148 ba
->hostname
, ba
->port
,
2149 ba
->bmp
->remote
, uptime
);
2156 long trem
= thread_timer_remain_second(
2159 peer_uptime(monotime(NULL
) - trem
,
2160 uptime
, sizeof(uptime
),
2162 state_str
= "RetryWait";
2163 } else if (ba
->t_read
) {
2164 state_str
= "Connecting";
2165 } else if (ba
->resq
.callback
) {
2166 state_str
= "Resolving";
2169 ttable_add_row(tt
, "%s:%d|%s|%s|%s",
2170 ba
->hostname
, ba
->port
,
2172 ba
->last_err
? ba
->last_err
: "",
2176 out
= ttable_dump(tt
, "\n");
2177 vty_out(vty
, "%s", out
);
2178 XFREE(MTYPE_TMP
, out
);
2181 vty_out(vty
, "\n %zu connected clients:\n",
2182 bmp_session_count(&bt
->sessions
));
2183 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2184 ttable_add_row(tt
, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2185 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
2187 frr_each (bmp_session
, &bt
->sessions
, bmp
) {
2191 pullwr_stats(bmp
->pullwr
, &total
, &q
, &kq
);
2193 peer_uptime(bmp
->t_up
.tv_sec
, uptime
,
2194 sizeof(uptime
), false, NULL
);
2196 ttable_add_row(tt
, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2197 bmp
->remote
, uptime
,
2200 bmp
->cnt_mirror_overruns
,
2203 out
= ttable_dump(tt
, "\n");
2204 vty_out(vty
, "%s", out
);
2205 XFREE(MTYPE_TMP
, out
);
2214 static int bmp_config_write(struct bgp
*bgp
, struct vty
*vty
)
2216 struct bmp_bgp
*bmpbgp
= bmp_bgp_find(bgp
);
2217 struct bmp_targets
*bt
;
2218 struct bmp_listener
*bl
;
2219 struct bmp_active
*ba
;
2220 char buf
[SU_ADDRSTRLEN
];
2227 if (bmpbgp
->mirror_qsizelimit
!= ~0UL)
2228 vty_out(vty
, " !\n bmp mirror buffer-limit %zu\n",
2229 bmpbgp
->mirror_qsizelimit
);
2231 frr_each(bmp_targets
, &bmpbgp
->targets
, bt
) {
2232 vty_out(vty
, " !\n bmp targets %s\n", bt
->name
);
2235 vty_out(vty
, " ipv6 access-list %s\n", bt
->acl6_name
);
2237 vty_out(vty
, " ip access-list %s\n", bt
->acl_name
);
2240 vty_out(vty
, " bmp stats interval %d\n",
2244 vty_out(vty
, " bmp mirror\n");
2246 FOREACH_AFI_SAFI (afi
, safi
) {
2247 const char *afi_str
= (afi
== AFI_IP
) ? "ipv4" : "ipv6";
2249 if (bt
->afimon
[afi
][safi
] & BMP_MON_PREPOLICY
)
2250 vty_out(vty
, " bmp monitor %s %s pre-policy\n",
2251 afi_str
, safi2str(safi
));
2252 if (bt
->afimon
[afi
][safi
] & BMP_MON_POSTPOLICY
)
2253 vty_out(vty
, " bmp monitor %s %s post-policy\n",
2254 afi_str
, safi2str(safi
));
2256 frr_each (bmp_listeners
, &bt
->listeners
, bl
)
2257 vty_out(vty
, " \n bmp listener %s port %d\n",
2258 sockunion2str(&bl
->addr
, buf
, SU_ADDRSTRLEN
),
2261 frr_each (bmp_actives
, &bt
->actives
, ba
)
2262 vty_out(vty
, " bmp connect %s port %u min-retry %u max-retry %u\n",
2263 ba
->hostname
, ba
->port
, ba
->minretry
, ba
->maxretry
);
2269 static int bgp_bmp_init(struct thread_master
*tm
)
2271 install_node(&bmp_node
, NULL
);
2272 install_default(BMP_NODE
);
2273 install_element(BGP_NODE
, &bmp_targets_cmd
);
2274 install_element(BGP_NODE
, &no_bmp_targets_cmd
);
2276 install_element(BMP_NODE
, &bmp_listener_cmd
);
2277 install_element(BMP_NODE
, &no_bmp_listener_cmd
);
2278 install_element(BMP_NODE
, &bmp_connect_cmd
);
2279 install_element(BMP_NODE
, &bmp_acl_cmd
);
2280 install_element(BMP_NODE
, &bmp_stats_cmd
);
2281 install_element(BMP_NODE
, &bmp_monitor_cmd
);
2282 install_element(BMP_NODE
, &bmp_mirror_cmd
);
2284 install_element(BGP_NODE
, &bmp_mirror_limit_cmd
);
2285 install_element(BGP_NODE
, &no_bmp_mirror_limit_cmd
);
2287 install_element(VIEW_NODE
, &show_bmp_cmd
);
2293 static int bgp_bmp_module_init(void)
2295 hook_register(bgp_packet_dump
, bmp_mirror_packet
);
2296 hook_register(bgp_packet_send
, bmp_outgoing_packet
);
2297 hook_register(peer_status_changed
, bmp_peer_established
);
2298 hook_register(peer_backward_transition
, bmp_peer_backward
);
2299 hook_register(bgp_process
, bmp_process
);
2300 hook_register(bgp_inst_config_write
, bmp_config_write
);
2301 hook_register(bgp_inst_delete
, bmp_bgp_del
);
2302 hook_register(frr_late_init
, bgp_bmp_init
);
2306 FRR_MODULE_SETUP(.name
= "bgpd_bmp", .version
= FRR_VERSION
,
2307 .description
= "bgpd BMP module",
2308 .init
= bgp_bmp_module_init
)