]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bmp.c
zebra: add support for DF delay timer
[mirror_frr.git] / bgpd / bgp_bmp.c
CommitLineData
6c29258c
YO
1/* BMP support.
2 * Copyright (C) 2018 Yasuhiro Ohara
ed18356f 3 * Copyright (C) 2019 David Lamparter for NetDEF, Inc.
6c29258c 4 *
ed18356f
DL
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)
8 * any later version.
6c29258c 9 *
ed18356f
DL
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
13 * more details.
6c29258c
YO
14 *
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
18 */
19
20#include <zebra.h>
21
22#include "log.h"
23#include "stream.h"
24#include "sockunion.h"
25#include "command.h"
26#include "prefix.h"
27#include "thread.h"
28#include "linklist.h"
29#include "queue.h"
ed18356f 30#include "pullwr.h"
6c29258c
YO
31#include "memory.h"
32#include "network.h"
33#include "filter.h"
34#include "lib_errors.h"
35#include "stream.h"
0ba4eeec
DL
36#include "libfrr.h"
37#include "version.h"
ed18356f
DL
38#include "jhash.h"
39#include "termtable.h"
6c29258c
YO
40
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"
d35a6c28 47#include "bgpd/bgp_packet.h"
6c29258c 48#include "bgpd/bgp_bmp.h"
ed18356f
DL
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_updgrp.h"
51#include "bgpd/bgp_vty.h"
52
53static void bmp_close(struct bmp *bmp);
54static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp);
55static void bmp_targets_put(struct bmp_targets *bt);
56static struct bmp_bgp_peer *bmp_bgp_peer_find(uint64_t peerid);
57static struct bmp_bgp_peer *bmp_bgp_peer_get(struct peer *peer);
58static void bmp_active_disconnected(struct bmp_active *ba);
59static void bmp_active_put(struct bmp_active *ba);
60
61DEFINE_MGROUP(BMP, "BMP (BGP Monitoring Protocol)")
62
63DEFINE_MTYPE_STATIC(BMP, BMP_CONN, "BMP connection state")
64DEFINE_MTYPE_STATIC(BMP, BMP_TARGETS, "BMP targets")
65DEFINE_MTYPE_STATIC(BMP, BMP_TARGETSNAME, "BMP targets name")
66DEFINE_MTYPE_STATIC(BMP, BMP_LISTENER, "BMP listener")
67DEFINE_MTYPE_STATIC(BMP, BMP_ACTIVE, "BMP active connection config")
68DEFINE_MTYPE_STATIC(BMP, BMP_ACLNAME, "BMP access-list name")
69DEFINE_MTYPE_STATIC(BMP, BMP_QUEUE, "BMP update queue item")
70DEFINE_MTYPE_STATIC(BMP, BMP, "BMP instance state")
71DEFINE_MTYPE_STATIC(BMP, BMP_MIRRORQ, "BMP route mirroring buffer")
72DEFINE_MTYPE_STATIC(BMP, BMP_PEER, "BMP per BGP peer data")
73DEFINE_MTYPE_STATIC(BMP, BMP_OPEN, "BMP stored BGP OPEN message")
74
75DEFINE_QOBJ_TYPE(bmp_targets)
76
77static int bmp_bgp_cmp(const struct bmp_bgp *a, const struct bmp_bgp *b)
78{
79 if (a->bgp < b->bgp)
80 return -1;
81 if (a->bgp > b->bgp)
82 return 1;
83 return 0;
84}
85
86static uint32_t bmp_bgp_hash(const struct bmp_bgp *e)
87{
88 return jhash(&e->bgp, sizeof(e->bgp), 0x55aa5a5a);
89}
6c29258c 90
ed18356f
DL
91DECLARE_HASH(bmp_bgph, struct bmp_bgp, bbi, bmp_bgp_cmp, bmp_bgp_hash)
92
93struct bmp_bgph_head bmp_bgph;
94
95static int bmp_bgp_peer_cmp(const struct bmp_bgp_peer *a,
96 const struct bmp_bgp_peer *b)
97{
98 if (a->peerid < b->peerid)
99 return -1;
100 if (a->peerid > b->peerid)
101 return 1;
102 return 0;
103}
104
105static uint32_t bmp_bgp_peer_hash(const struct bmp_bgp_peer *e)
106{
107 return e->peerid;
108}
6c29258c 109
ed18356f
DL
110DECLARE_HASH(bmp_peerh, struct bmp_bgp_peer, bpi,
111 bmp_bgp_peer_cmp, bmp_bgp_peer_hash)
6c29258c 112
ed18356f 113struct bmp_peerh_head bmp_peerh;
6c29258c 114
ed18356f 115DECLARE_LIST(bmp_mirrorq, struct bmp_mirrorq, bmi)
6c29258c 116
ed18356f 117/* listener management */
6c29258c 118
ed18356f
DL
119static int bmp_listener_cmp(const struct bmp_listener *a,
120 const struct bmp_listener *b)
6c29258c 121{
ed18356f 122 int c;
6c29258c 123
ed18356f
DL
124 c = sockunion_cmp(&a->addr, &b->addr);
125 if (c)
126 return c;
127 if (a->port < b->port)
128 return -1;
129 if (a->port > b->port)
130 return 1;
131 return 0;
132}
6c29258c 133
ed18356f
DL
134DECLARE_SORTLIST_UNIQ(bmp_listeners, struct bmp_listener, bli, bmp_listener_cmp)
135
136static int bmp_targets_cmp(const struct bmp_targets *a,
137 const struct bmp_targets *b)
138{
139 return strcmp(a->name, b->name);
6c29258c
YO
140}
141
ed18356f
DL
142DECLARE_SORTLIST_UNIQ(bmp_targets, struct bmp_targets, bti, bmp_targets_cmp)
143
144DECLARE_LIST(bmp_session, struct bmp, bsi)
145
146DECLARE_DLIST(bmp_qlist, struct bmp_queue_entry, bli)
147
148static int bmp_qhash_cmp(const struct bmp_queue_entry *a,
149 const struct bmp_queue_entry *b)
6c29258c 150{
ed18356f 151 int ret;
87102aa0 152 if (a->afi == AFI_L2VPN && a->safi == SAFI_EVPN && b->afi == AFI_L2VPN
153 && b->safi == SAFI_EVPN) {
154 ret = prefix_cmp(&a->rd, &b->rd);
155 if (ret)
156 return ret;
157 } else if (a->afi == AFI_L2VPN && a->safi == SAFI_EVPN)
158 return 1;
159 else if (b->afi == AFI_L2VPN && b->safi == SAFI_EVPN)
160 return -1;
161
ed18356f
DL
162 ret = prefix_cmp(&a->p, &b->p);
163 if (ret)
164 return ret;
165 ret = memcmp(&a->peerid, &b->peerid,
166 offsetof(struct bmp_queue_entry, refcount) -
167 offsetof(struct bmp_queue_entry, peerid));
168 return ret;
6c29258c
YO
169}
170
ed18356f 171static uint32_t bmp_qhash_hkey(const struct bmp_queue_entry *e)
6c29258c 172{
ed18356f
DL
173 uint32_t key;
174
175 key = prefix_hash_key((void *)&e->p);
176 key = jhash(&e->peerid,
87102aa0 177 offsetof(struct bmp_queue_entry, refcount)
178 - offsetof(struct bmp_queue_entry, peerid),
179 key);
180 if (e->afi == AFI_L2VPN && e->safi == SAFI_EVPN)
181 key = jhash(&e->rd,
182 offsetof(struct bmp_queue_entry, rd)
183 - offsetof(struct bmp_queue_entry, refcount)
184 + PSIZE(e->rd.prefixlen),
185 key);
186
ed18356f
DL
187 return key;
188}
6c29258c 189
ed18356f
DL
190DECLARE_HASH(bmp_qhash, struct bmp_queue_entry, bhi,
191 bmp_qhash_cmp, bmp_qhash_hkey)
6c29258c 192
ed18356f
DL
193static int bmp_active_cmp(const struct bmp_active *a,
194 const struct bmp_active *b)
195{
196 int c;
197
198 c = strcmp(a->hostname, b->hostname);
199 if (c)
200 return c;
201 if (a->port < b->port)
202 return -1;
203 if (a->port > b->port)
204 return 1;
6c29258c
YO
205 return 0;
206}
207
ed18356f
DL
208DECLARE_SORTLIST_UNIQ(bmp_actives, struct bmp_active, bai, bmp_active_cmp)
209
210static struct bmp *bmp_new(struct bmp_targets *bt, int bmp_sock)
6c29258c 211{
ed18356f
DL
212 struct bmp *new = XCALLOC(MTYPE_BMP_CONN, sizeof(struct bmp));
213 afi_t afi;
214 safi_t safi;
215
216 monotime(&new->t_up);
217 new->targets = bt;
218 new->socket = bmp_sock;
219 new->syncafi = AFI_MAX;
220
221 FOREACH_AFI_SAFI (afi, safi) {
222 new->afistate[afi][safi] = bt->afimon[afi][safi]
223 ? BMP_AFI_NEEDSYNC : BMP_AFI_INACTIVE;
224 }
225
226 bmp_session_add_tail(&bt->sessions, new);
227 return new;
6c29258c 228}
6c29258c 229
ed18356f 230static void bmp_free(struct bmp *bmp)
6c29258c 231{
ed18356f
DL
232 bmp_session_del(&bmp->targets->sessions, bmp);
233 XFREE(MTYPE_BMP_CONN, bmp);
6c29258c
YO
234}
235
236static void bmp_common_hdr(struct stream *s, uint8_t ver, uint8_t type)
237{
238 stream_putc(s, ver);
239 stream_putl(s, 0); //dummy message length. will be set later.
240 stream_putc(s, type);
241}
242
ed18356f
DL
243static void bmp_per_peer_hdr(struct stream *s, struct peer *peer,
244 uint8_t flags, const struct timeval *tv)
6c29258c 245{
6c29258c
YO
246 char peer_distinguisher[8];
247
248#define BMP_PEER_TYPE_GLOBAL_INSTANCE 0
249#define BMP_PEER_TYPE_RD_INSTANCE 1
250#define BMP_PEER_TYPE_LOCAL_INSTANCE 2
251
252#define BMP_PEER_FLAG_V (1 << 7)
253#define BMP_PEER_FLAG_L (1 << 6)
254#define BMP_PEER_FLAG_A (1 << 5)
255
256 /* Peer Type */
257 stream_putc(s, BMP_PEER_TYPE_GLOBAL_INSTANCE);
258
259 /* Peer Flags */
ed18356f
DL
260 if (peer->su.sa.sa_family == AF_INET6)
261 SET_FLAG(flags, BMP_PEER_FLAG_V);
262 else
263 UNSET_FLAG(flags, BMP_PEER_FLAG_V);
264 stream_putc(s, flags);
6c29258c
YO
265
266 /* Peer Distinguisher */
267 memset (&peer_distinguisher[0], 0, 8);
268 stream_put(s, &peer_distinguisher[0], 8);
269
270 /* Peer Address */
ed18356f
DL
271 if (peer->su.sa.sa_family == AF_INET6)
272 stream_put(s, &peer->su.sin6.sin6_addr, 16);
273 else if (peer->su.sa.sa_family == AF_INET) {
274 stream_putl(s, 0);
275 stream_putl(s, 0);
276 stream_putl(s, 0);
277 stream_put_in_addr(s, &peer->su.sin.sin_addr);
278 } else {
279 stream_putl(s, 0);
6c29258c
YO
280 stream_putl(s, 0);
281 stream_putl(s, 0);
282 stream_putl(s, 0);
6c29258c
YO
283 }
284
285 /* Peer AS */
286 stream_putl(s, peer->as);
287
288 /* Peer BGP ID */
289 stream_put_in_addr(s, &peer->remote_id);
290
291 /* Timestamp */
ed18356f
DL
292 if (tv) {
293 stream_putl(s, tv->tv_sec);
294 stream_putl(s, tv->tv_usec);
295 } else {
296 stream_putl(s, 0);
297 stream_putl(s, 0);
298 }
6c29258c
YO
299}
300
ed18356f
DL
301static void bmp_put_info_tlv(struct stream *s, uint16_t type,
302 const char *string)
6c29258c
YO
303{
304 int len = strlen (string);
305 stream_putw(s, type);
306 stream_putw(s, len);
307 stream_put(s, string, len);
308}
309
310static int bmp_send_initiation(struct bmp *bmp)
311{
312 int len;
313 struct stream *s;
314 s = stream_new(BGP_MAX_PACKET_SIZE);
315 bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_INITIATION);
316
317#define BMP_INFO_TYPE_SYSDESCR 1
318#define BMP_INFO_TYPE_SYSNAME 2
ed18356f
DL
319 bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSDESCR,
320 FRR_FULL_NAME " " FRR_VER_SHORT);
321 bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSNAME, cmd_hostname_get());
6c29258c
YO
322
323 len = stream_get_endp(s);
324 stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
325
ed18356f
DL
326 pullwr_write_stream(bmp->pullwr, s);
327 stream_free(s);
6c29258c
YO
328 return 0;
329}
330
ed18356f
DL
331static void bmp_notify_put(struct stream *s, struct bgp_notify *nfy)
332{
333 size_t len_pos;
334 uint8_t marker[16] = {
335 0xff, 0xff, 0xff, 0xff,
336 0xff, 0xff, 0xff, 0xff,
337 0xff, 0xff, 0xff, 0xff,
338 0xff, 0xff, 0xff, 0xff,
339 };
340
341 stream_put(s, marker, sizeof(marker));
342 len_pos = stream_get_endp(s);
343 stream_putw(s, 0);
344 stream_putc(s, BGP_MSG_NOTIFY);
345 stream_putc(s, nfy->code);
346 stream_putc(s, nfy->subcode);
347 stream_put(s, nfy->data, nfy->length);
348
349 stream_putw_at(s, len_pos, stream_get_endp(s) - len_pos
350 + sizeof(marker));
351}
352
353static struct stream *bmp_peerstate(struct peer *peer, bool down)
6c29258c 354{
6c29258c 355 struct stream *s;
ed18356f
DL
356 size_t len;
357 struct timeval uptime, uptime_real;
6c29258c 358
ed18356f
DL
359 uptime.tv_sec = peer->uptime;
360 uptime.tv_usec = 0;
361 monotime_to_realtime(&uptime, &uptime_real);
6c29258c 362
ed18356f 363#define BGP_BMP_MAX_PACKET_SIZE 1024
6c29258c 364 s = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 365
ed18356f
DL
366 if (peer->status == Established && !down) {
367 struct bmp_bgp_peer *bbpeer;
6c29258c 368
ed18356f
DL
369 bmp_common_hdr(s, BMP_VERSION_3,
370 BMP_TYPE_PEER_UP_NOTIFICATION);
371 bmp_per_peer_hdr(s, peer, 0, &uptime_real);
6c29258c
YO
372
373 /* Local Address (16 bytes) */
374 if (peer->su_local->sa.sa_family == AF_INET6)
375 stream_put(s, &peer->su_local->sin6.sin6_addr, 16);
376 else if (peer->su_local->sa.sa_family == AF_INET) {
377 stream_putl(s, 0);
378 stream_putl(s, 0);
379 stream_putl(s, 0);
380 stream_put_in_addr(s, &peer->su_local->sin.sin_addr);
381 }
382
383 /* Local Port, Remote Port */
384 if (peer->su_local->sa.sa_family == AF_INET6)
385 stream_putw(s, peer->su_local->sin6.sin6_port);
386 else if (peer->su_local->sa.sa_family == AF_INET)
387 stream_putw(s, peer->su_local->sin.sin_port);
388 if (peer->su_remote->sa.sa_family == AF_INET6)
389 stream_putw(s, peer->su_remote->sin6.sin6_port);
390 else if (peer->su_remote->sa.sa_family == AF_INET)
391 stream_putw(s, peer->su_remote->sin.sin_port);
392
ed18356f
DL
393 static const uint8_t dummy_open[] = {
394 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
395 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
396 0x00, 0x13, 0x01,
397 };
6c29258c 398
ed18356f 399 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
6c29258c 400
ed18356f
DL
401 if (bbpeer && bbpeer->open_tx)
402 stream_put(s, bbpeer->open_tx, bbpeer->open_tx_len);
403 else {
404 stream_put(s, dummy_open, sizeof(dummy_open));
63efca0e
DL
405 zlog_warn("bmp: missing TX OPEN message for peer %s",
406 peer->host);
ed18356f
DL
407 }
408 if (bbpeer && bbpeer->open_rx)
409 stream_put(s, bbpeer->open_rx, bbpeer->open_rx_len);
410 else {
411 stream_put(s, dummy_open, sizeof(dummy_open));
63efca0e
DL
412 zlog_warn("bmp: missing RX OPEN message for peer %s",
413 peer->host);
ed18356f 414 }
6c29258c 415
ed18356f
DL
416 if (peer->desc)
417 bmp_put_info_tlv(s, 0, peer->desc);
418 } else {
419 uint8_t type;
420 size_t type_pos;
421
422 bmp_common_hdr(s, BMP_VERSION_3,
423 BMP_TYPE_PEER_DOWN_NOTIFICATION);
424 bmp_per_peer_hdr(s, peer, 0, &uptime_real);
425
426 type_pos = stream_get_endp(s);
427 stream_putc(s, 0); /* placeholder for down reason */
428
429 switch (peer->last_reset) {
430 case PEER_DOWN_NOTIFY_RECEIVED:
431 type = BMP_PEERDOWN_REMOTE_NOTIFY;
432 bmp_notify_put(s, &peer->notify);
433 break;
434 case PEER_DOWN_CLOSE_SESSION:
435 type = BMP_PEERDOWN_REMOTE_CLOSE;
436 break;
437 default:
438 type = BMP_PEERDOWN_LOCAL_NOTIFY;
439 stream_put(s, peer->last_reset_cause,
440 peer->last_reset_cause_size);
441 break;
6c29258c 442 }
ed18356f 443 stream_putc_at(s, type_pos, type);
6c29258c
YO
444 }
445
ed18356f
DL
446 len = stream_get_endp(s);
447 stream_putl_at(s, BMP_LENGTH_POS, len); //message length is set.
448 return s;
449}
450
451
452static int bmp_send_peerup(struct bmp *bmp)
453{
454 struct peer *peer;
455 struct listnode *node;
456 struct stream *s;
457
458 /* Walk down all peers */
459 for (ALL_LIST_ELEMENTS_RO(bmp->targets->bgp->peer, node, peer)) {
460 s = bmp_peerstate(peer, false);
461 pullwr_write_stream(bmp->pullwr, s);
462 stream_free(s);
463 }
6c29258c
YO
464
465 return 0;
466}
467
ed18356f
DL
468/* XXX: kludge - filling the pullwr's buffer */
469static void bmp_send_all(struct bmp_bgp *bmpbgp, struct stream *s)
470{
471 struct bmp_targets *bt;
472 struct bmp *bmp;
473
474 frr_each(bmp_targets, &bmpbgp->targets, bt)
475 frr_each(bmp_session, &bt->sessions, bmp)
476 pullwr_write_stream(bmp->pullwr, s);
477 stream_free(s);
478}
479
480/*
481 * Route Mirroring
482 */
483
484#define BMP_MIRROR_TLV_TYPE_BGP_MESSAGE 0
485#define BMP_MIRROR_TLV_TYPE_INFO 1
486
487#define BMP_MIRROR_INFO_CODE_ERRORPDU 0
488#define BMP_MIRROR_INFO_CODE_LOSTMSGS 1
489
490static struct bmp_mirrorq *bmp_pull_mirror(struct bmp *bmp)
491{
492 struct bmp_mirrorq *bmq;
493
494 bmq = bmp->mirrorpos;
495 if (!bmq)
496 return NULL;
497
498 bmp->mirrorpos = bmp_mirrorq_next(&bmp->targets->bmpbgp->mirrorq, bmq);
499
500 bmq->refcount--;
501 if (!bmq->refcount) {
502 bmp->targets->bmpbgp->mirror_qsize -= sizeof(*bmq) + bmq->len;
503 bmp_mirrorq_del(&bmp->targets->bmpbgp->mirrorq, bmq);
504 }
505 return bmq;
506}
507
508static void bmp_mirror_cull(struct bmp_bgp *bmpbgp)
509{
510 while (bmpbgp->mirror_qsize > bmpbgp->mirror_qsizelimit) {
511 struct bmp_mirrorq *bmq, *inner;
512 struct bmp_targets *bt;
513 struct bmp *bmp;
514
515 bmq = bmp_mirrorq_first(&bmpbgp->mirrorq);
516
517 frr_each(bmp_targets, &bmpbgp->targets, bt) {
518 if (!bt->mirror)
519 continue;
520 frr_each(bmp_session, &bt->sessions, bmp) {
521 if (bmp->mirrorpos != bmq)
522 continue;
523
524 while ((inner = bmp_pull_mirror(bmp))) {
525 if (!inner->refcount)
526 XFREE(MTYPE_BMP_MIRRORQ,
527 inner);
528 }
529
530 zlog_warn("bmp[%s] lost mirror messages due to buffer size limit",
531 bmp->remote);
532 bmp->mirror_lost = true;
533 pullwr_bump(bmp->pullwr);
534 }
535 }
536 }
537}
538
d35a6c28
DL
539static int bmp_mirror_packet(struct peer *peer, uint8_t type, bgp_size_t size,
540 struct stream *packet)
6c29258c 541{
ed18356f
DL
542 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
543 struct timeval tv;
544 struct bmp_mirrorq *qitem;
545 struct bmp_targets *bt;
6c29258c 546 struct bmp *bmp;
6c29258c 547
ed18356f
DL
548 gettimeofday(&tv, NULL);
549
550 if (type == BGP_MSG_OPEN) {
551 struct bmp_bgp_peer *bbpeer = bmp_bgp_peer_get(peer);
552
553 XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
554
555 bbpeer->open_rx_len = size;
556 bbpeer->open_rx = XMALLOC(MTYPE_BMP_OPEN, size);
557 memcpy(bbpeer->open_rx, packet->data, size);
558 }
559
560 if (!bmpbgp)
d35a6c28 561 return 0;
6c29258c 562
ed18356f
DL
563 qitem = XCALLOC(MTYPE_BMP_MIRRORQ, sizeof(*qitem) + size);
564 qitem->peerid = peer->qobj_node.nid;
565 qitem->tv = tv;
566 qitem->len = size;
567 memcpy(qitem->data, packet->data, size);
568
569 frr_each(bmp_targets, &bmpbgp->targets, bt) {
570 if (!bt->mirror)
571 continue;
572 frr_each(bmp_session, &bt->sessions, bmp) {
573 qitem->refcount++;
574 if (!bmp->mirrorpos)
575 bmp->mirrorpos = qitem;
576 pullwr_bump(bmp->pullwr);
577 }
578 }
579 if (qitem->refcount == 0)
580 XFREE(MTYPE_BMP_MIRRORQ, qitem);
581 else {
582 bmpbgp->mirror_qsize += sizeof(*qitem) + size;
583 bmp_mirrorq_add_tail(&bmpbgp->mirrorq, qitem);
584
585 bmp_mirror_cull(bmpbgp);
586
587 bmpbgp->mirror_qsizemax = MAX(bmpbgp->mirror_qsizemax,
588 bmpbgp->mirror_qsize);
589 }
590 return 0;
591}
592
593static void bmp_wrmirror_lost(struct bmp *bmp, struct pullwr *pullwr)
594{
595 struct stream *s;
596 struct timeval tv;
597
598 gettimeofday(&tv, NULL);
599
600 s = stream_new(BGP_MAX_PACKET_SIZE);
601
602 bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
603 bmp_per_peer_hdr(s, bmp->targets->bgp->peer_self, 0, &tv);
604
605 stream_putw(s, BMP_MIRROR_TLV_TYPE_INFO);
606 stream_putw(s, 2);
607 stream_putw(s, BMP_MIRROR_INFO_CODE_LOSTMSGS);
608 stream_putl_at(s, BMP_LENGTH_POS, stream_get_endp(s));
609
610 bmp->cnt_mirror_overruns++;
611 pullwr_write_stream(bmp->pullwr, s);
612 stream_free(s);
613}
614
615static bool bmp_wrmirror(struct bmp *bmp, struct pullwr *pullwr)
616{
617 struct bmp_mirrorq *bmq;
618 struct peer *peer;
619 bool written = false;
620
621 if (bmp->mirror_lost) {
622 bmp_wrmirror_lost(bmp, pullwr);
623 bmp->mirror_lost = false;
624 return true;
625 }
626
627 bmq = bmp_pull_mirror(bmp);
628 if (!bmq)
629 return false;
630
631 peer = QOBJ_GET_TYPESAFE(bmq->peerid, peer);
632 if (!peer) {
633 zlog_info("bmp: skipping mirror message for deleted peer");
634 goto out;
635 }
636
637 struct stream *s;
6c29258c
YO
638 s = stream_new(BGP_MAX_PACKET_SIZE);
639
640 bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_ROUTE_MIRRORING);
ed18356f 641 bmp_per_peer_hdr(s, peer, 0, &bmq->tv);
6c29258c
YO
642
643 /* BMP Mirror TLV. */
6c29258c 644 stream_putw(s, BMP_MIRROR_TLV_TYPE_BGP_MESSAGE);
ed18356f
DL
645 stream_putw(s, bmq->len);
646 stream_putl_at(s, BMP_LENGTH_POS, stream_get_endp(s) + bmq->len);
6c29258c 647
ed18356f
DL
648 bmp->cnt_mirror++;
649 pullwr_write_stream(bmp->pullwr, s);
650 pullwr_write(bmp->pullwr, bmq->data, bmq->len);
6c29258c 651
ed18356f
DL
652 stream_free(s);
653 written = true;
6c29258c 654
ed18356f
DL
655out:
656 if (!bmq->refcount)
657 XFREE(MTYPE_BMP_MIRRORQ, bmq);
658 return written;
6c29258c
YO
659}
660
ed18356f
DL
661static int bmp_outgoing_packet(struct peer *peer, uint8_t type, bgp_size_t size,
662 struct stream *packet)
6c29258c 663{
ed18356f
DL
664 if (type == BGP_MSG_OPEN) {
665 struct bmp_bgp_peer *bbpeer = bmp_bgp_peer_get(peer);
6c29258c 666
ed18356f 667 XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx);
6c29258c 668
ed18356f
DL
669 bbpeer->open_tx_len = size;
670 bbpeer->open_tx = XMALLOC(MTYPE_BMP_OPEN, size);
671 memcpy(bbpeer->open_tx, packet->data, size);
672 }
673 return 0;
674}
6c29258c 675
ed18356f
DL
676static int bmp_peer_established(struct peer *peer)
677{
678 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
6c29258c 679
ed18356f
DL
680 if (!bmpbgp)
681 return 0;
6c29258c 682
df9e8ae7 683 /* Check if this peer just went to Established */
fd2e2db6 684 if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
df9e8ae7
MS
685 return 0;
686
ed18356f
DL
687 if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
688 struct bmp_bgp_peer *bbpeer, *bbdopp;
6c29258c 689
ed18356f
DL
690 bbpeer = bmp_bgp_peer_get(peer);
691 bbdopp = bmp_bgp_peer_find(peer->doppelganger->qobj_node.nid);
692 if (bbdopp) {
693 XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx);
694 XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
6c29258c 695
ed18356f
DL
696 bbpeer->open_tx = bbdopp->open_tx;
697 bbpeer->open_tx_len = bbdopp->open_tx_len;
698 bbpeer->open_rx = bbdopp->open_rx;
699 bbpeer->open_rx_len = bbdopp->open_rx_len;
6c29258c 700
ed18356f
DL
701 bmp_peerh_del(&bmp_peerh, bbdopp);
702 XFREE(MTYPE_BMP_PEER, bbdopp);
703 }
6c29258c 704 }
ed18356f
DL
705
706 bmp_send_all(bmpbgp, bmp_peerstate(peer, false));
6c29258c
YO
707 return 0;
708}
709
ed18356f 710static int bmp_peer_backward(struct peer *peer)
6c29258c 711{
ed18356f
DL
712 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
713 struct bmp_bgp_peer *bbpeer;
6c29258c 714
ed18356f
DL
715 if (!bmpbgp)
716 return 0;
6c29258c 717
ed18356f
DL
718 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
719 if (bbpeer) {
720 XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx);
721 bbpeer->open_tx_len = 0;
722 XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
723 bbpeer->open_rx_len = 0;
724 }
6c29258c 725
ed18356f
DL
726 bmp_send_all(bmpbgp, bmp_peerstate(peer, true));
727 return 0;
728}
6c29258c 729
ed18356f
DL
730static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
731{
732 struct peer *peer;
733 struct listnode *node;
734 struct stream *s, *s2;
735 iana_afi_t pkt_afi;
736 iana_safi_t pkt_safi;
6c29258c 737
ed18356f 738 s = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 739
ed18356f
DL
740 /* Make BGP update packet. */
741 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
6c29258c 742
ed18356f
DL
743 /* Unfeasible Routes Length */
744 stream_putw(s, 0);
6c29258c 745
ed18356f
DL
746 if (afi == AFI_IP && safi == SAFI_UNICAST) {
747 /* Total Path Attribute Length */
748 stream_putw(s, 0);
749 } else {
750 /* Convert AFI, SAFI to values for packet. */
751 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
752
753 /* Total Path Attribute Length */
754 stream_putw(s, 6);
755 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
756 stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
757 stream_putc(s, 3);
758 stream_putw(s, pkt_afi);
759 stream_putc(s, pkt_safi);
6c29258c
YO
760 }
761
ed18356f 762 bgp_packet_set_size(s);
6c29258c 763
ed18356f
DL
764 for (ALL_LIST_ELEMENTS_RO(bmp->targets->bgp->peer, node, peer)) {
765 if (!peer->afc_nego[afi][safi])
766 continue;
6c29258c 767
ed18356f 768 s2 = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 769
ed18356f
DL
770 bmp_common_hdr(s2, BMP_VERSION_3,
771 BMP_TYPE_ROUTE_MONITORING);
772 bmp_per_peer_hdr(s2, peer, flags, NULL);
6c29258c 773
ed18356f
DL
774 stream_putl_at(s2, BMP_LENGTH_POS,
775 stream_get_endp(s) + stream_get_endp(s2));
6c29258c 776
ed18356f
DL
777 bmp->cnt_update++;
778 pullwr_write_stream(bmp->pullwr, s2);
779 pullwr_write_stream(bmp->pullwr, s);
780 stream_free(s2);
781 }
782 stream_free(s);
6c29258c
YO
783}
784
87102aa0 785static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
786 struct peer *peer, struct attr *attr,
787 afi_t afi, safi_t safi)
6c29258c 788{
ed18356f
DL
789 struct bpacket_attr_vec_arr vecarr;
790 struct stream *s;
791 size_t attrlen_pos = 0, mpattrlen_pos = 0;
792 bgp_size_t total_attr_len = 0;
793
794 bpacket_attr_vec_arr_reset(&vecarr);
795
796 s = stream_new(BGP_MAX_PACKET_SIZE);
797 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
798
799 /* 2: withdrawn routes length */
800 stream_putw(s, 0);
801
802 /* 3: total attributes length - attrlen_pos stores the position */
803 attrlen_pos = stream_get_endp(s);
804 stream_putw(s, 0);
805
806 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
807 total_attr_len = bgp_packet_attribute(NULL, peer, s, attr,
808 &vecarr, NULL, afi, safi, peer, NULL, NULL, 0, 0, 0);
6c29258c 809
ed18356f 810 /* space check? */
6c29258c 811
ed18356f
DL
812 /* peer_cap_enhe & add-path removed */
813 if (afi == AFI_IP && safi == SAFI_UNICAST)
814 stream_put_prefix(s, p);
815 else {
816 size_t p1 = stream_get_endp(s);
6c29258c 817
ed18356f 818 /* MPLS removed for now */
6c29258c 819
ed18356f
DL
820 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
821 &vecarr, attr);
87102aa0 822 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, NULL, 0, 0, 0,
823 attr);
ed18356f
DL
824 bgp_packet_mpattr_end(s, mpattrlen_pos);
825 total_attr_len += stream_get_endp(s) - p1;
6c29258c
YO
826 }
827
ed18356f
DL
828 /* set the total attribute length correctly */
829 stream_putw_at(s, attrlen_pos, total_attr_len);
830 bgp_packet_set_size(s);
831 return s;
832}
6c29258c 833
87102aa0 834static struct stream *bmp_withdraw(const struct prefix *p,
835 struct prefix_rd *prd, afi_t afi,
5f040085 836 safi_t safi)
ed18356f
DL
837{
838 struct stream *s;
839 size_t attrlen_pos = 0, mp_start, mplen_pos;
840 bgp_size_t total_attr_len = 0;
841 bgp_size_t unfeasible_len;
6c29258c 842
ed18356f 843 s = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 844
ed18356f
DL
845 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
846 stream_putw(s, 0);
6c29258c 847
ed18356f
DL
848 if (afi == AFI_IP && safi == SAFI_UNICAST) {
849 stream_put_prefix(s, p);
850 unfeasible_len = stream_get_endp(s) - BGP_HEADER_SIZE
851 - BGP_UNFEASIBLE_LEN;
852 stream_putw_at(s, BGP_HEADER_SIZE, unfeasible_len);
853 stream_putw(s, 0);
854 } else {
855 attrlen_pos = stream_get_endp(s);
856 /* total attr length = 0 for now. reevaluate later */
857 stream_putw(s, 0);
858 mp_start = stream_get_endp(s);
859 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
860
87102aa0 861 bgp_packet_mpunreach_prefix(s, p, afi, safi, prd, NULL, 0, 0, 0,
862 NULL);
ed18356f
DL
863 /* Set the mp_unreach attr's length */
864 bgp_packet_mpunreach_end(s, mplen_pos);
865
866 /* Set total path attribute length. */
867 total_attr_len = stream_get_endp(s) - mp_start;
868 stream_putw_at(s, attrlen_pos, total_attr_len);
869 }
870
871 bgp_packet_set_size(s);
872 return s;
873}
874
875static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
87102aa0 876 const struct prefix *p, struct prefix_rd *prd,
877 struct attr *attr, afi_t afi, safi_t safi,
878 time_t uptime)
ed18356f
DL
879{
880 struct stream *hdr, *msg;
881 struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
02cee158 882 struct timeval uptime_real;
ed18356f 883
02cee158 884 monotime_to_realtime(&tv, &uptime_real);
ed18356f 885 if (attr)
87102aa0 886 msg = bmp_update(p, prd, peer, attr, afi, safi);
ed18356f 887 else
87102aa0 888 msg = bmp_withdraw(p, prd, afi, safi);
ed18356f
DL
889
890 hdr = stream_new(BGP_MAX_PACKET_SIZE);
891 bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
02cee158 892 bmp_per_peer_hdr(hdr, peer, flags, &uptime_real);
ed18356f
DL
893
894 stream_putl_at(hdr, BMP_LENGTH_POS,
895 stream_get_endp(hdr) + stream_get_endp(msg));
896
897 bmp->cnt_update++;
898 pullwr_write_stream(bmp->pullwr, hdr);
899 pullwr_write_stream(bmp->pullwr, msg);
900 stream_free(hdr);
901 stream_free(msg);
902}
903
904static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr)
905{
906 afi_t afi;
907 safi_t safi;
908
909 if (bmp->syncafi == AFI_MAX) {
910 FOREACH_AFI_SAFI (afi, safi) {
911 if (bmp->afistate[afi][safi] != BMP_AFI_NEEDSYNC)
912 continue;
913
914 bmp->afistate[afi][safi] = BMP_AFI_SYNC;
915
916 bmp->syncafi = afi;
917 bmp->syncsafi = safi;
918 bmp->syncpeerid = 0;
919 memset(&bmp->syncpos, 0, sizeof(bmp->syncpos));
920 bmp->syncpos.family = afi2family(afi);
87102aa0 921 bmp->syncrdpos = NULL;
ed18356f
DL
922 zlog_info("bmp[%s] %s %s sending table",
923 bmp->remote,
924 afi2str(bmp->syncafi),
925 safi2str(bmp->syncsafi));
926 /* break does not work here, 2 loops... */
927 goto afibreak;
6c29258c 928 }
ed18356f
DL
929 if (bmp->syncafi == AFI_MAX)
930 return false;
931 }
6c29258c 932
ed18356f
DL
933afibreak:
934 afi = bmp->syncafi;
935 safi = bmp->syncsafi;
936
937 if (!bmp->targets->afimon[afi][safi]) {
938 /* shouldn't happen */
939 bmp->afistate[afi][safi] = BMP_AFI_INACTIVE;
940 bmp->syncafi = AFI_MAX;
941 bmp->syncsafi = SAFI_MAX;
942 return true;
943 }
944
945 struct bgp_table *table = bmp->targets->bgp->rib[afi][safi];
9bcb3eef 946 struct bgp_dest *bn;
ed18356f
DL
947 struct bgp_path_info *bpi = NULL, *bpiter;
948 struct bgp_adj_in *adjin = NULL, *adjiter;
949
87102aa0 950 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
951 /* initialize syncrdpos to the first
952 * mid-layer table entry
953 */
7b3a3805 954 if (!bmp->syncrdpos) {
87102aa0 955 bmp->syncrdpos = bgp_table_top(table);
7b3a3805
DS
956 if (!bmp->syncrdpos)
957 goto eor;
958 }
87102aa0 959
960 /* look for a valid mid-layer table */
961 do {
962 table = bgp_dest_get_bgp_table_info(bmp->syncrdpos);
963 if (table) {
964 break;
965 }
966 bmp->syncrdpos = bgp_route_next(bmp->syncrdpos);
967 } while (bmp->syncrdpos);
968
969 /* mid-layer table completed */
970 if (!bmp->syncrdpos)
971 goto eor;
972 }
973
ed18356f
DL
974 bn = bgp_node_lookup(table, &bmp->syncpos);
975 do {
976 if (!bn) {
977 bn = bgp_table_get_next(table, &bmp->syncpos);
978 if (!bn) {
87102aa0 979 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
980 /* reset bottom-layer pointer */
981 memset(&bmp->syncpos, 0,
982 sizeof(bmp->syncpos));
983 bmp->syncpos.family = afi2family(afi);
984 /* check whethere there is a valid
985 * next mid-layer table, otherwise
986 * declare table completed (eor)
987 */
988 for (bmp->syncrdpos = bgp_route_next(
989 bmp->syncrdpos);
990 bmp->syncrdpos;
991 bmp->syncrdpos = bgp_route_next(
992 bmp->syncrdpos))
993 if (bgp_dest_get_bgp_table_info(
994 bmp->syncrdpos))
995 return true;
996 }
997 eor:
ed18356f
DL
998 zlog_info("bmp[%s] %s %s table completed (EoR)",
999 bmp->remote, afi2str(afi),
1000 safi2str(safi));
1001 bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L);
1002 bmp_eor(bmp, afi, safi, 0);
1003
1004 bmp->afistate[afi][safi] = BMP_AFI_LIVE;
1005 bmp->syncafi = AFI_MAX;
1006 bmp->syncsafi = SAFI_MAX;
1007 return true;
1008 }
1009 bmp->syncpeerid = 0;
9bcb3eef 1010 prefix_copy(&bmp->syncpos, bgp_dest_get_prefix(bn));
6c29258c
YO
1011 }
1012
ed18356f 1013 if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
87102aa0 1014 for (bpiter = bgp_dest_get_bgp_path_info(bn); bpiter;
1015 bpiter = bpiter->next) {
ed18356f
DL
1016 if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID))
1017 continue;
1018 if (bpiter->peer->qobj_node.nid
1019 <= bmp->syncpeerid)
1020 continue;
1021 if (bpi && bpiter->peer->qobj_node.nid
1022 > bpi->peer->qobj_node.nid)
1023 continue;
1024 bpi = bpiter;
1025 }
1026 }
1027 if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
1028 for (adjiter = bn->adj_in; adjiter;
1029 adjiter = adjiter->next) {
1030 if (adjiter->peer->qobj_node.nid
1031 <= bmp->syncpeerid)
1032 continue;
1033 if (adjin && adjiter->peer->qobj_node.nid
1034 > adjin->peer->qobj_node.nid)
1035 continue;
1036 adjin = adjiter;
1037 }
1038 }
1039 if (bpi || adjin)
1040 break;
1041
1042 bn = NULL;
1043 } while (1);
1044
1045 if (adjin && bpi
1046 && adjin->peer->qobj_node.nid < bpi->peer->qobj_node.nid) {
1047 bpi = NULL;
1048 bmp->syncpeerid = adjin->peer->qobj_node.nid;
1049 } else if (adjin && bpi
1050 && adjin->peer->qobj_node.nid > bpi->peer->qobj_node.nid) {
1051 adjin = NULL;
1052 bmp->syncpeerid = bpi->peer->qobj_node.nid;
1053 } else if (bpi) {
1054 bmp->syncpeerid = bpi->peer->qobj_node.nid;
1055 } else if (adjin) {
1056 bmp->syncpeerid = adjin->peer->qobj_node.nid;
1057 }
6c29258c 1058
9bcb3eef 1059 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
87102aa0 1060 struct prefix_rd *prd = NULL;
1061 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
1062 prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
b54892e0 1063
ed18356f 1064 if (bpi)
87102aa0 1065 bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, bn_p, prd,
1066 bpi->attr, afi, safi, bpi->uptime);
ed18356f 1067 if (adjin)
87102aa0 1068 bmp_monitor(bmp, adjin->peer, 0, bn_p, prd, adjin->attr, afi,
1069 safi, adjin->uptime);
6c29258c 1070
ed18356f 1071 return true;
6c29258c
YO
1072}
1073
ed18356f 1074static struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
6c29258c 1075{
ed18356f
DL
1076 struct bmp_queue_entry *bqe;
1077
1078 bqe = bmp->queuepos;
1079 if (!bqe)
1080 return NULL;
1081
1082 bmp->queuepos = bmp_qlist_next(&bmp->targets->updlist, bqe);
1083
1084 bqe->refcount--;
1085 if (!bqe->refcount) {
1086 bmp_qhash_del(&bmp->targets->updhash, bqe);
1087 bmp_qlist_del(&bmp->targets->updlist, bqe);
1088 }
1089 return bqe;
1090}
1091
1092static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
1093{
1094 struct bmp_queue_entry *bqe;
1095 struct peer *peer;
9bcb3eef 1096 struct bgp_dest *bn;
ed18356f
DL
1097 bool written = false;
1098
1099 bqe = bmp_pull(bmp);
1100 if (!bqe)
1101 return false;
1102
1103 afi_t afi = bqe->afi;
1104 safi_t safi = bqe->safi;
1105
1106 switch (bmp->afistate[afi][safi]) {
1107 case BMP_AFI_INACTIVE:
1108 case BMP_AFI_NEEDSYNC:
1109 goto out;
1110 case BMP_AFI_SYNC:
1111 if (prefix_cmp(&bqe->p, &bmp->syncpos) <= 0)
1112 /* currently syncing but have already passed this
1113 * prefix => send it. */
1114 break;
1115
1116 /* currently syncing & haven't reached this prefix yet
1117 * => it'll be sent as part of the table sync, no need here */
1118 goto out;
1119 case BMP_AFI_LIVE:
1120 break;
1121 }
1122
1123 peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer);
1124 if (!peer) {
1125 zlog_info("bmp: skipping queued item for deleted peer");
1126 goto out;
1127 }
1128 if (peer->status != Established)
1129 goto out;
1130
1131 bn = bgp_node_lookup(bmp->targets->bgp->rib[afi][safi], &bqe->p);
87102aa0 1132 struct prefix_rd *prd = NULL;
1133 if (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN)
1134 prd = &bqe->rd;
ed18356f
DL
1135
1136 if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
1137 struct bgp_path_info *bpi;
1138
87102aa0 1139 for (bpi = bn ? bgp_dest_get_bgp_path_info(bn) : NULL; bpi;
1140 bpi = bpi->next) {
ed18356f
DL
1141 if (!CHECK_FLAG(bpi->flags, BGP_PATH_VALID))
1142 continue;
1143 if (bpi->peer == peer)
1144 break;
1145 }
1146
87102aa0 1147 bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
ed18356f
DL
1148 bpi ? bpi->attr : NULL, afi, safi,
1149 bpi ? bpi->uptime : monotime(NULL));
1150 written = true;
1151 }
1152
1153 if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
1154 struct bgp_adj_in *adjin;
1155
1156 for (adjin = bn ? bn->adj_in : NULL; adjin;
1157 adjin = adjin->next) {
1158 if (adjin->peer == peer)
1159 break;
1160 }
87102aa0 1161 bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p, prd,
ed18356f
DL
1162 adjin ? adjin->attr : NULL, afi, safi,
1163 adjin ? adjin->uptime : monotime(NULL));
1164 written = true;
1165 }
1166
1167out:
1168 if (!bqe->refcount)
1169 XFREE(MTYPE_BMP_QUEUE, bqe);
1170 return written;
1171}
1172
1173static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr)
1174{
1175 switch(bmp->state) {
1176 case BMP_PeerUp:
1177 bmp_send_peerup(bmp);
1178 bmp->state = BMP_Run;
1179 break;
1180
1181 case BMP_Run:
1182 if (bmp_wrmirror(bmp, pullwr))
1183 break;
1184 if (bmp_wrqueue(bmp, pullwr))
1185 break;
1186 if (bmp_wrsync(bmp, pullwr))
1187 break;
1188 break;
1189 }
1190}
1191
1192static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof)
1193{
1194 if (eof)
1195 zlog_info("bmp[%s] disconnected", bmp->remote);
1196 else
1197 flog_warn(EC_LIB_SYSTEM_CALL, "bmp[%s] connection error: %s",
1198 bmp->remote, strerror(errno));
1199
1200 bmp_close(bmp);
1201 bmp_free(bmp);
1202}
1203
9bcb3eef
DS
1204static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp, afi_t afi,
1205 safi_t safi, struct bgp_dest *bn, struct peer *peer)
ed18356f
DL
1206{
1207 struct bmp *bmp;
1208 struct bmp_queue_entry *bqe, bqeref;
1209 size_t refcount;
ed18356f
DL
1210
1211 refcount = bmp_session_count(&bt->sessions);
1212 if (refcount == 0)
1213 return;
1214
1215 memset(&bqeref, 0, sizeof(bqeref));
9bcb3eef 1216 prefix_copy(&bqeref.p, bgp_dest_get_prefix(bn));
ed18356f
DL
1217 bqeref.peerid = peer->qobj_node.nid;
1218 bqeref.afi = afi;
1219 bqeref.safi = safi;
1220
87102aa0 1221 if (afi == AFI_L2VPN && safi == SAFI_EVPN && bn->pdest)
1222 prefix_copy(&bqeref.rd,
1223 (struct prefix_rd *)bgp_dest_get_prefix(bn->pdest));
1224
ed18356f
DL
1225 bqe = bmp_qhash_find(&bt->updhash, &bqeref);
1226 if (bqe) {
1227 if (bqe->refcount >= refcount)
1228 /* nothing to do here */
1229 return;
1230
1231 bmp_qlist_del(&bt->updlist, bqe);
1232 } else {
1233 bqe = XMALLOC(MTYPE_BMP_QUEUE, sizeof(*bqe));
1234 memcpy(bqe, &bqeref, sizeof(*bqe));
1235
1236 bmp_qhash_add(&bt->updhash, bqe);
1237 }
1238
1239 bqe->refcount = refcount;
1240 bmp_qlist_add_tail(&bt->updlist, bqe);
1241
1242 frr_each (bmp_session, &bt->sessions, bmp)
1243 if (!bmp->queuepos)
1244 bmp->queuepos = bqe;
1245}
1246
1247static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
9bcb3eef 1248 struct bgp_dest *bn, struct peer *peer, bool withdraw)
ed18356f
DL
1249{
1250 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
1251 struct bmp_targets *bt;
1252 struct bmp *bmp;
1253
1254 if (!bmpbgp)
1255 return 0;
1256
1257 frr_each(bmp_targets, &bmpbgp->targets, bt) {
1258 if (!bt->afimon[afi][safi])
1259 continue;
1260
1261 bmp_process_one(bt, bgp, afi, safi, bn, peer);
1262
1263 frr_each(bmp_session, &bt->sessions, bmp) {
1264 pullwr_bump(bmp->pullwr);
1265 }
1266 }
1267 return 0;
1268}
1269
1270static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type,
1271 uint32_t value)
1272{
1273 stream_putw(s, type);
1274 stream_putw(s, 4);
1275 stream_putl(s, value);
1276 (*cnt)++;
1277}
1278
1279static int bmp_stats(struct thread *thread)
1280{
1281 struct bmp_targets *bt = THREAD_ARG(thread);
1282 struct stream *s;
1283 struct peer *peer;
1284 struct listnode *node;
1285 struct timeval tv;
1286
1287 if (bt->stat_msec)
1288 thread_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec,
1289 &bt->t_stats);
1290
1291 gettimeofday(&tv, NULL);
1292
1293 /* Walk down all peers */
1294 for (ALL_LIST_ELEMENTS_RO(bt->bgp->peer, node, peer)) {
1295 size_t count = 0, count_pos, len;
1296
1297 if (peer->status != Established)
1298 continue;
1299
1300 s = stream_new(BGP_MAX_PACKET_SIZE);
1301 bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT);
1302 bmp_per_peer_hdr(s, peer, 0, &tv);
1303
1304 count_pos = stream_get_endp(s);
1305 stream_putl(s, 0);
1306
1307 bmp_stat_put_u32(s, &count, BMP_STATS_PFX_REJECTED,
1308 peer->stat_pfx_filter);
1309 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ASPATH,
1310 peer->stat_pfx_aspath_loop);
1311 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ORIGINATOR,
1312 peer->stat_pfx_originator_loop);
1313 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER,
1314 peer->stat_pfx_cluster_loop);
1315 bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW,
1316 peer->stat_pfx_dup_withdraw);
1317 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW,
1318 peer->stat_upd_7606);
1319 bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
1320 peer->stat_pfx_nh_invalid);
1321
1322 stream_putl_at(s, count_pos, count);
1323
1324 len = stream_get_endp(s);
1325 stream_putl_at(s, BMP_LENGTH_POS, len);
1326
1327 bmp_send_all(bt->bmpbgp, s);
1328 }
1329 return 0;
1330}
1331
8252b477
AL
1332/* read from the BMP socket to detect session termination */
1333static int bmp_read(struct thread *t)
1334{
1335 struct bmp *bmp = THREAD_ARG(t);
1336 char buf[1024];
1337 ssize_t n;
1338
1339 bmp->t_read = NULL;
1340
1341 n = read(bmp->socket, buf, sizeof(buf));
1342 if (n >= 1) {
1343 zlog_info("bmp[%s]: unexpectedly received %zu bytes", bmp->remote, n);
1344 } else if (n == 0) {
1345 /* the TCP session was terminated by the far end */
1346 bmp_wrerr(bmp, NULL, true);
1347 return 0;
1348 } else if (!(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
1349 /* the TCP session experienced a fatal error, likely a timeout */
1350 bmp_wrerr(bmp, NULL, false);
1351 return -1;
1352 }
1353
1354 thread_add_read(bm->master, bmp_read, bmp, bmp->socket, &bmp->t_read);
1355
1356 return 0;
1357}
1358
ed18356f
DL
1359static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock)
1360{
1361 union sockunion su, *sumem;
1362 struct prefix p;
1363 int on = 1;
1364 struct access_list *acl = NULL;
1365 enum filter_type ret;
1366 char buf[SU_ADDRSTRLEN];
1367 struct bmp *bmp;
1368
1369 sumem = sockunion_getpeername(bmp_sock);
1370 if (!sumem) {
1371 close(bmp_sock);
1372 return NULL;
1373 }
1374 memcpy(&su, sumem, sizeof(su));
1375 sockunion_free(sumem);
1376
1377 set_nonblocking(bmp_sock);
1378 set_cloexec(bmp_sock);
ed18356f 1379
0154d8ce
DS
1380 if (!sockunion2hostprefix(&su, &p)) {
1381 close(bmp_sock);
1382 return NULL;
1383 }
ed18356f
DL
1384
1385 acl = NULL;
1386 switch (p.family) {
1387 case AF_INET:
1388 acl = access_list_lookup(AFI_IP, bt->acl_name);
1389 break;
1390 case AF_INET6:
1391 acl = access_list_lookup(AFI_IP6, bt->acl6_name);
1392 break;
1393 default:
1394 break;
1395 }
1396
1397 ret = FILTER_PERMIT;
1398 if (acl) {
1399 ret = access_list_apply(acl, &p);
1400 }
1401
1402 sockunion2str(&su, buf, SU_ADDRSTRLEN);
1403 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":%u",
1404 su.sa.sa_family == AF_INET
1405 ? ntohs(su.sin.sin_port)
1406 : ntohs(su.sin6.sin6_port));
1407
1408 if (ret == FILTER_DENY) {
1409 bt->cnt_aclrefused++;
1410 zlog_info("bmp[%s] connection refused by access-list", buf);
1411 close(bmp_sock);
1412 return NULL;
1413 }
1414 bt->cnt_accept++;
1415
d38c6bb1
DS
1416 if (setsockopt(bmp_sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
1417 flog_err(EC_LIB_SOCKET, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1418 bmp_sock, safe_strerror(errno), errno);
1419 if (setsockopt(bmp_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
1420 flog_err(EC_LIB_SOCKET, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1421 bmp_sock, safe_strerror(errno), errno);
ed18356f
DL
1422
1423 zlog_info("bmp[%s] connection established", buf);
1424
1425 /* Allocate new BMP structure and set up default values. */
1426 bmp = bmp_new(bt, bmp_sock);
1427 strlcpy(bmp->remote, buf, sizeof(bmp->remote));
1428
1429 bmp->state = BMP_PeerUp;
1430 bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill,
1431 bmp_wrerr);
8252b477 1432 thread_add_read(bm->master, bmp_read, bmp, bmp_sock, &bmp->t_read);
ed18356f
DL
1433 bmp_send_initiation(bmp);
1434
1435 return bmp;
1436}
1437
1438/* Accept BMP connection. */
1439static int bmp_accept(struct thread *thread)
1440{
1441 union sockunion su;
1442 struct bmp_listener *bl = THREAD_ARG(thread);
1443 int bmp_sock;
1444
1445 /* We continue hearing BMP socket. */
1446 thread_add_read(bm->master, bmp_accept, bl, bl->sock, &bl->t_accept);
1447
1448 memset(&su, 0, sizeof(union sockunion));
1449
1450 /* We can handle IPv4 or IPv6 socket. */
1451 bmp_sock = sockunion_accept(bl->sock, &su);
1452 if (bmp_sock < 0) {
63efca0e 1453 zlog_info("bmp: accept_sock failed: %s", safe_strerror(errno));
ed18356f
DL
1454 return -1;
1455 }
1456 bmp_open(bl->targets, bmp_sock);
1457 return 0;
1458}
1459
1460static void bmp_close(struct bmp *bmp)
1461{
1462 struct bmp_queue_entry *bqe;
1463 struct bmp_mirrorq *bmq;
1464
8252b477
AL
1465 THREAD_OFF(bmp->t_read);
1466
ed18356f
DL
1467 if (bmp->active)
1468 bmp_active_disconnected(bmp->active);
1469
1470 while ((bmq = bmp_pull_mirror(bmp)))
1471 if (!bmq->refcount)
1472 XFREE(MTYPE_BMP_MIRRORQ, bmq);
1473 while ((bqe = bmp_pull(bmp)))
1474 if (!bqe->refcount)
1475 XFREE(MTYPE_BMP_QUEUE, bqe);
1476
1477 THREAD_OFF(bmp->t_read);
1478 pullwr_del(bmp->pullwr);
1479 close(bmp->socket);
1480}
1481
1482static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp)
1483{
1484 struct bmp_bgp dummy = { .bgp = bgp };
1485 return bmp_bgph_find(&bmp_bgph, &dummy);
1486}
1487
1488static struct bmp_bgp *bmp_bgp_get(struct bgp *bgp)
1489{
1490 struct bmp_bgp *bmpbgp;
1491
1492 bmpbgp = bmp_bgp_find(bgp);
1493 if (bmpbgp)
1494 return bmpbgp;
1495
1496 bmpbgp = XCALLOC(MTYPE_BMP, sizeof(*bmpbgp));
1497 bmpbgp->bgp = bgp;
1498 bmpbgp->mirror_qsizelimit = ~0UL;
1499 bmp_mirrorq_init(&bmpbgp->mirrorq);
1500 bmp_bgph_add(&bmp_bgph, bmpbgp);
1501
1502 return bmpbgp;
1503}
1504
1505static void bmp_bgp_put(struct bmp_bgp *bmpbgp)
1506{
1507 struct bmp_targets *bt;
1508
1509 bmp_bgph_del(&bmp_bgph, bmpbgp);
1510
1511 frr_each_safe(bmp_targets, &bmpbgp->targets, bt)
1512 bmp_targets_put(bt);
1513
1514 bmp_mirrorq_fini(&bmpbgp->mirrorq);
1515 XFREE(MTYPE_BMP, bmpbgp);
1516}
1517
1518static int bmp_bgp_del(struct bgp *bgp)
1519{
1520 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1521
1522 if (bmpbgp)
1523 bmp_bgp_put(bmpbgp);
1524 return 0;
1525}
1526
1527static struct bmp_bgp_peer *bmp_bgp_peer_find(uint64_t peerid)
1528{
1529 struct bmp_bgp_peer dummy = { .peerid = peerid };
1530 return bmp_peerh_find(&bmp_peerh, &dummy);
1531}
1532
1533static struct bmp_bgp_peer *bmp_bgp_peer_get(struct peer *peer)
1534{
1535 struct bmp_bgp_peer *bbpeer;
1536
1537 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
1538 if (bbpeer)
1539 return bbpeer;
1540
1541 bbpeer = XCALLOC(MTYPE_BMP_PEER, sizeof(*bbpeer));
1542 bbpeer->peerid = peer->qobj_node.nid;
1543 bmp_peerh_add(&bmp_peerh, bbpeer);
1544
1545 return bbpeer;
1546}
1547
1548static struct bmp_targets *bmp_targets_find1(struct bgp *bgp, const char *name)
1549{
1550 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1551 struct bmp_targets dummy;
1552
1553 if (!bmpbgp)
1554 return NULL;
1555 dummy.name = (char *)name;
1556 return bmp_targets_find(&bmpbgp->targets, &dummy);
1557}
1558
1559static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
1560{
1561 struct bmp_targets *bt;
1562
1563 bt = bmp_targets_find1(bgp, name);
1564 if (bt)
1565 return bt;
1566
1567 bt = XCALLOC(MTYPE_BMP_TARGETS, sizeof(*bt));
1568 bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name);
1569 bt->bgp = bgp;
1570 bt->bmpbgp = bmp_bgp_get(bgp);
1571 bmp_session_init(&bt->sessions);
1572 bmp_qhash_init(&bt->updhash);
1573 bmp_qlist_init(&bt->updlist);
1574 bmp_actives_init(&bt->actives);
1575 bmp_listeners_init(&bt->listeners);
1576
1577 QOBJ_REG(bt, bmp_targets);
1578 bmp_targets_add(&bt->bmpbgp->targets, bt);
1579 return bt;
1580}
1581
1582static void bmp_targets_put(struct bmp_targets *bt)
1583{
1584 struct bmp *bmp;
1585 struct bmp_active *ba;
1586
1587 frr_each_safe (bmp_actives, &bt->actives, ba)
1588 bmp_active_put(ba);
1589
1590 frr_each_safe(bmp_session, &bt->sessions, bmp) {
1591 bmp_close(bmp);
1592 bmp_free(bmp);
1593 }
1594
1595 bmp_targets_del(&bt->bmpbgp->targets, bt);
1596 QOBJ_UNREG(bt);
1597
1598 bmp_listeners_fini(&bt->listeners);
1599 bmp_actives_fini(&bt->actives);
1600 bmp_qhash_fini(&bt->updhash);
1601 bmp_qlist_fini(&bt->updlist);
1602
1603 XFREE(MTYPE_BMP_ACLNAME, bt->acl_name);
1604 XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name);
1605 bmp_session_fini(&bt->sessions);
1606
1607 XFREE(MTYPE_BMP_TARGETSNAME, bt->name);
1608 XFREE(MTYPE_BMP_TARGETS, bt);
1609}
1610
1611static struct bmp_listener *bmp_listener_find(struct bmp_targets *bt,
1612 const union sockunion *su,
1613 int port)
1614{
1615 struct bmp_listener dummy;
1616 dummy.addr = *su;
1617 dummy.port = port;
1618 return bmp_listeners_find(&bt->listeners, &dummy);
1619}
1620
1621static struct bmp_listener *bmp_listener_get(struct bmp_targets *bt,
1622 const union sockunion *su,
1623 int port)
1624{
1625 struct bmp_listener *bl = bmp_listener_find(bt, su, port);
1626
1627 if (bl)
1628 return bl;
1629
1630 bl = XCALLOC(MTYPE_BMP_LISTENER, sizeof(*bl));
1631 bl->targets = bt;
1632 bl->addr = *su;
1633 bl->port = port;
1634 bl->sock = -1;
1635
1636 bmp_listeners_add(&bt->listeners, bl);
1637 return bl;
1638}
1639
1640static void bmp_listener_put(struct bmp_listener *bl)
1641{
1642 bmp_listeners_del(&bl->targets->listeners, bl);
1643 XFREE(MTYPE_BMP_LISTENER, bl);
1644}
1645
1646static void bmp_listener_start(struct bmp_listener *bl)
1647{
1648 int sock, ret;
1649
1650 sock = socket(bl->addr.sa.sa_family, SOCK_STREAM, 0);
1651 if (sock < 0)
1652 return;
1653
1654 sockopt_reuseaddr(sock);
1655 sockopt_reuseport(sock);
1656 sockopt_v6only(bl->addr.sa.sa_family, sock);
1657 set_cloexec(sock);
1658
1659 ret = sockunion_bind(sock, &bl->addr, bl->port, &bl->addr);
1660 if (ret < 0)
1661 goto out_sock;
1662
1663 ret = listen(sock, 3);
1664 if (ret < 0)
1665 goto out_sock;
1666
1667 bl->sock = sock;
1668 thread_add_read(bm->master, bmp_accept, bl, sock, &bl->t_accept);
1669 return;
1670out_sock:
1671 close(sock);
1672}
1673
1674static void bmp_listener_stop(struct bmp_listener *bl)
1675{
1676 THREAD_OFF(bl->t_accept);
1677
1678 if (bl->sock != -1)
1679 close(bl->sock);
1680 bl->sock = -1;
1681}
1682
1683static struct bmp_active *bmp_active_find(struct bmp_targets *bt,
1684 const char *hostname, int port)
1685{
1686 struct bmp_active dummy;
1687 dummy.hostname = (char *)hostname;
1688 dummy.port = port;
1689 return bmp_actives_find(&bt->actives, &dummy);
1690}
1691
1692static struct bmp_active *bmp_active_get(struct bmp_targets *bt,
1693 const char *hostname, int port)
1694{
1695 struct bmp_active *ba;
1696
1697 ba = bmp_active_find(bt, hostname, port);
1698 if (ba)
1699 return ba;
1700
1701 ba = XCALLOC(MTYPE_BMP_ACTIVE, sizeof(*ba));
1702 ba->targets = bt;
1703 ba->hostname = XSTRDUP(MTYPE_TMP, hostname);
1704 ba->port = port;
1705 ba->minretry = BMP_DFLT_MINRETRY;
1706 ba->maxretry = BMP_DFLT_MAXRETRY;
1707 ba->socket = -1;
1708
1709 bmp_actives_add(&bt->actives, ba);
1710 return ba;
1711}
1712
1713static void bmp_active_put(struct bmp_active *ba)
1714{
1715 THREAD_OFF(ba->t_timer);
1716 THREAD_OFF(ba->t_read);
1717 THREAD_OFF(ba->t_write);
1718
1719 bmp_actives_del(&ba->targets->actives, ba);
1720
1721 if (ba->bmp) {
1722 ba->bmp->active = NULL;
1723 bmp_close(ba->bmp);
1724 bmp_free(ba->bmp);
1725 }
1726 if (ba->socket != -1)
1727 close(ba->socket);
1728
1729 XFREE(MTYPE_TMP, ba->hostname);
1730 XFREE(MTYPE_BMP_ACTIVE, ba);
1731}
1732
1733static void bmp_active_setup(struct bmp_active *ba);
1734
1735static void bmp_active_connect(struct bmp_active *ba)
1736{
1737 enum connect_result res;
1738 char buf[SU_ADDRSTRLEN];
1739
1740 for (; ba->addrpos < ba->addrtotal; ba->addrpos++) {
1741 ba->socket = sockunion_socket(&ba->addrs[ba->addrpos]);
1742 if (ba->socket < 0) {
1743 zlog_warn("bmp[%s]: failed to create socket",
1744 ba->hostname);
1745 continue;
1746 }
c258527b 1747
ed18356f
DL
1748 set_nonblocking(ba->socket);
1749 res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos],
1750 htons(ba->port), 0);
1751 switch (res) {
1752 case connect_error:
1753 sockunion2str(&ba->addrs[ba->addrpos], buf,
1754 sizeof(buf));
1755 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1756 ba->hostname, buf, ba->port);
1757 close(ba->socket);
1758 ba->socket = -1;
1759 continue;
1760 case connect_success:
1761 break;
1762 case connect_in_progress:
1763 bmp_active_setup(ba);
1764 return;
1765 }
1766 }
1767
1768 /* exhausted all addresses */
1769 ba->curretry += ba->curretry / 2;
1770 bmp_active_setup(ba);
1771}
1772
3286ca07
DL
1773static void bmp_active_resolved(struct resolver_query *resq, const char *errstr,
1774 int numaddrs, union sockunion *addr)
ed18356f
DL
1775{
1776 struct bmp_active *ba = container_of(resq, struct bmp_active, resq);
1777 unsigned i;
1778
1779 if (numaddrs <= 0) {
3286ca07
DL
1780 zlog_warn("bmp[%s]: hostname resolution failed: %s",
1781 ba->hostname, errstr);
1782 ba->last_err = errstr;
125dc952 1783 ba->curretry += ba->curretry / 2;
a3d04c32 1784 ba->addrpos = 0;
125dc952
DL
1785 ba->addrtotal = 0;
1786 bmp_active_setup(ba);
1787 return;
a3d04c32 1788 }
ed18356f 1789
125dc952
DL
1790 if (numaddrs > (int)array_size(ba->addrs))
1791 numaddrs = array_size(ba->addrs);
1792
1793 ba->addrpos = 0;
1794 ba->addrtotal = numaddrs;
1795 for (i = 0; i < ba->addrtotal; i++)
1796 memcpy(&ba->addrs[i], &addr[i], sizeof(ba->addrs[0]));
1797
ed18356f
DL
1798 bmp_active_connect(ba);
1799}
1800
1801static int bmp_active_thread(struct thread *t)
1802{
1803 struct bmp_active *ba = THREAD_ARG(t);
1804 socklen_t slen;
1805 int status, ret;
1806 char buf[SU_ADDRSTRLEN];
1807
1808 /* all 3 end up here, though only timer or read+write are active
1809 * at a time */
1810 THREAD_OFF(ba->t_timer);
1811 THREAD_OFF(ba->t_read);
1812 THREAD_OFF(ba->t_write);
1813
3286ca07
DL
1814 ba->last_err = NULL;
1815
ed18356f
DL
1816 if (ba->socket == -1) {
1817 resolver_resolve(&ba->resq, AF_UNSPEC, ba->hostname,
1818 bmp_active_resolved);
1819 return 0;
1820 }
1821
1822 slen = sizeof(status);
1823 ret = getsockopt(ba->socket, SOL_SOCKET, SO_ERROR, (void *)&status,
1824 &slen);
1825
1826 sockunion2str(&ba->addrs[ba->addrpos], buf, sizeof(buf));
1827 if (ret < 0 || status != 0) {
3286ca07
DL
1828 ba->last_err = strerror(status);
1829 zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
1830 ba->hostname, buf, ba->port, ba->last_err);
ed18356f
DL
1831 goto out_next;
1832 }
1833
1834 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1835 ba->hostname, buf, ba->port);
1836
1837 ba->bmp = bmp_open(ba->targets, ba->socket);
1838 if (!ba->bmp)
1839 goto out_next;
1840
1841 ba->bmp->active = ba;
1842 ba->socket = -1;
1843 ba->curretry = ba->minretry;
1844 return 0;
1845
1846out_next:
1847 close(ba->socket);
1848 ba->socket = -1;
1849 ba->addrpos++;
1850 bmp_active_connect(ba);
1851 return 0;
1852}
1853
1854static void bmp_active_disconnected(struct bmp_active *ba)
1855{
1856 ba->bmp = NULL;
1857 bmp_active_setup(ba);
1858}
1859
1860static void bmp_active_setup(struct bmp_active *ba)
1861{
1862 THREAD_OFF(ba->t_timer);
1863 THREAD_OFF(ba->t_read);
1864 THREAD_OFF(ba->t_write);
1865
1866 if (ba->bmp)
1867 return;
1868 if (ba->resq.callback)
1869 return;
1870
1871 if (ba->curretry > ba->maxretry)
1872 ba->curretry = ba->maxretry;
1873
1874 if (ba->socket == -1)
1875 thread_add_timer_msec(bm->master, bmp_active_thread, ba,
1876 ba->curretry, &ba->t_timer);
1877 else {
1878 thread_add_read(bm->master, bmp_active_thread, ba, ba->socket,
1879 &ba->t_read);
1880 thread_add_write(bm->master, bmp_active_thread, ba, ba->socket,
1881 &ba->t_write);
1882 }
1883}
1884
62b346ee 1885static struct cmd_node bmp_node = {
f4b8291f 1886 .name = "bmp",
62b346ee 1887 .node = BMP_NODE,
24389580 1888 .parent_node = BGP_NODE,
62b346ee
DL
1889 .prompt = "%s(config-bgp-bmp)# "
1890};
ed18356f
DL
1891
1892#define BMP_STR "BGP Monitoring Protocol\n"
1893
1894#ifndef VTYSH_EXTRACT_PL
33a9e196 1895#include "bgpd/bgp_bmp_clippy.c"
ed18356f
DL
1896#endif
1897
1898DEFPY_NOSH(bmp_targets_main,
1899 bmp_targets_cmd,
1900 "bmp targets BMPTARGETS",
1901 BMP_STR
1902 "Create BMP target group\n"
1903 "Name of the BMP target group\n")
1904{
1905 VTY_DECLVAR_CONTEXT(bgp, bgp);
1906 struct bmp_targets *bt;
1907
1908 bt = bmp_targets_get(bgp, bmptargets);
1909
1910 VTY_PUSH_CONTEXT_SUB(BMP_NODE, bt);
1911 return CMD_SUCCESS;
1912}
1913
1914DEFPY(no_bmp_targets_main,
1915 no_bmp_targets_cmd,
1916 "no bmp targets BMPTARGETS",
1917 NO_STR
1918 BMP_STR
1919 "Delete BMP target group\n"
1920 "Name of the BMP target group\n")
1921{
1922 VTY_DECLVAR_CONTEXT(bgp, bgp);
1923 struct bmp_targets *bt;
1924
1925 bt = bmp_targets_find1(bgp, bmptargets);
1926 if (!bt) {
1927 vty_out(vty, "%% BMP target group not found\n");
1928 return CMD_WARNING;
1929 }
1930 bmp_targets_put(bt);
1931 return CMD_SUCCESS;
1932}
1933
1934DEFPY(bmp_listener_main,
1935 bmp_listener_cmd,
1936 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1937 BMP_STR
1938 "Listen for inbound BMP connections\n"
1939 "IPv6 address to listen on\n"
1940 "IPv4 address to listen on\n"
1941 "TCP Port number\n"
1942 "TCP Port number\n")
1943{
1944 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1945 struct bmp_listener *bl;
1946
1947 bl = bmp_listener_get(bt, listener, port);
1948 if (bl->sock == -1)
1949 bmp_listener_start(bl);
1950
1951 return CMD_SUCCESS;
1952}
1953
1954DEFPY(no_bmp_listener_main,
1955 no_bmp_listener_cmd,
1956 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1957 NO_STR
1958 BMP_STR
1959 "Create BMP listener\n"
1960 "IPv6 address to listen on\n"
1961 "IPv4 address to listen on\n"
1962 "TCP Port number\n"
1963 "TCP Port number\n")
1964{
1965 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1966 struct bmp_listener *bl;
1967
1968 bl = bmp_listener_find(bt, listener, port);
1969 if (!bl) {
1970 vty_out(vty, "%% BMP listener not found\n");
1971 return CMD_WARNING;
1972 }
1973 bmp_listener_stop(bl);
1974 bmp_listener_put(bl);
1975 return CMD_SUCCESS;
1976}
1977
1978DEFPY(bmp_connect,
1979 bmp_connect_cmd,
3efd0893 1980 "[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}",
ed18356f
DL
1981 NO_STR
1982 BMP_STR
1983 "Actively establish connection to monitoring station\n"
1984 "Monitoring station hostname or address\n"
1985 "TCP port\n"
1986 "TCP port\n"
1987 "Minimum connection retry interval\n"
1988 "Minimum connection retry interval (milliseconds)\n"
1989 "Maximum connection retry interval\n"
1990 "Maximum connection retry interval (milliseconds)\n")
1991{
1992 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1993 struct bmp_active *ba;
1994
1995 if (no) {
1996 ba = bmp_active_find(bt, hostname, port);
1997 if (!ba) {
1998 vty_out(vty, "%% No such active connection found\n");
1999 return CMD_WARNING;
2000 }
2001 bmp_active_put(ba);
2002 return CMD_SUCCESS;
2003 }
2004
2005 ba = bmp_active_get(bt, hostname, port);
2006 if (min_retry_str)
2007 ba->minretry = min_retry;
2008 if (max_retry_str)
2009 ba->maxretry = max_retry;
2010 ba->curretry = ba->minretry;
2011 bmp_active_setup(ba);
2012
2013 return CMD_SUCCESS;
2014}
2015
2016DEFPY(bmp_acl,
2017 bmp_acl_cmd,
2018 "[no] <ip|ipv6>$af access-list WORD",
2019 NO_STR
2020 IP_STR
2021 IPV6_STR
2022 "Access list to restrict BMP sessions\n"
2023 "Access list name\n")
2024{
2025 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2026 char **what;
2027
2028 if (no)
2029 access_list = NULL;
2030 if (!strcmp(af, "ipv6"))
2031 what = &bt->acl6_name;
2032 else
2033 what = &bt->acl_name;
2034
2035 XFREE(MTYPE_BMP_ACLNAME, *what);
2036 if (access_list)
2037 *what = XSTRDUP(MTYPE_BMP_ACLNAME, access_list);
2038
2039 return CMD_SUCCESS;
2040}
2041
2042DEFPY(bmp_stats_cfg,
2043 bmp_stats_cmd,
2044 "[no] bmp stats [interval (100-86400000)]",
2045 NO_STR
2046 BMP_STR
2047 "Send BMP statistics messages\n"
2048 "Specify BMP stats interval\n"
2049 "Interval (milliseconds) to send BMP Stats in\n")
2050{
2051 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2052
2053 THREAD_OFF(bt->t_stats);
2054 if (no)
2055 bt->stat_msec = 0;
2056 else if (interval_str)
2057 bt->stat_msec = interval;
2058 else
2059 bt->stat_msec = BMP_STAT_DEFAULT_TIMER;
2060
2061 if (bt->stat_msec)
2062 thread_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec,
2063 &bt->t_stats);
2064 return CMD_SUCCESS;
2065}
2066
2067DEFPY(bmp_monitor_cfg,
2068 bmp_monitor_cmd,
87102aa0 2069 "[no] bmp monitor <ipv4|ipv6|l2vpn> <unicast|multicast|evpn> <pre-policy|post-policy>$policy",
ed18356f
DL
2070 NO_STR
2071 BMP_STR
2072 "Send BMP route monitoring messages\n"
87102aa0 2073 "Address Family\nAddress Family\nAddress Family\n"
2074 "Address Family\nAddress Family\nAddress Family\n"
ed18356f
DL
2075 "Send state before policy and filter processing\n"
2076 "Send state with policy and filters applied\n")
2077{
2078 int index = 0;
2079 uint8_t flag, prev;
2080 afi_t afi;
2081 safi_t safi;
2082
2083 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2084 struct bmp *bmp;
2085
2086 argv_find_and_parse_afi(argv, argc, &index, &afi);
2087 argv_find_and_parse_safi(argv, argc, &index, &safi);
2088
2089 if (policy[1] == 'r')
2090 flag = BMP_MON_PREPOLICY;
2091 else
2092 flag = BMP_MON_POSTPOLICY;
2093
2094 prev = bt->afimon[afi][safi];
2095 if (no)
2096 bt->afimon[afi][safi] &= ~flag;
2097 else
2098 bt->afimon[afi][safi] |= flag;
2099
2100 if (prev == bt->afimon[afi][safi])
2101 return CMD_SUCCESS;
2102
2103 frr_each (bmp_session, &bt->sessions, bmp) {
2104 if (bmp->syncafi == afi && bmp->syncsafi == safi) {
2105 bmp->syncafi = AFI_MAX;
2106 bmp->syncsafi = SAFI_MAX;
2107 }
2108
2109 if (!bt->afimon[afi][safi]) {
2110 bmp->afistate[afi][safi] = BMP_AFI_INACTIVE;
2111 continue;
2112 }
2113
2114 bmp->afistate[afi][safi] = BMP_AFI_NEEDSYNC;
2115 }
2116
2117 return CMD_SUCCESS;
2118}
2119
2120DEFPY(bmp_mirror_cfg,
2121 bmp_mirror_cmd,
2122 "[no] bmp mirror",
2123 NO_STR
2124 BMP_STR
2125 "Send BMP route mirroring messages\n")
2126{
2127 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2128 struct bmp *bmp;
2129
2130 if (bt->mirror == !no)
2131 return CMD_SUCCESS;
2132
2133 bt->mirror = !no;
2134 if (bt->mirror)
2135 return CMD_SUCCESS;
2136
2137 frr_each (bmp_session, &bt->sessions, bmp) {
2138 struct bmp_mirrorq *bmq;
2139
2140 while ((bmq = bmp_pull_mirror(bmp)))
2141 if (!bmq->refcount)
2142 XFREE(MTYPE_BMP_MIRRORQ, bmq);
2143 }
2144 return CMD_SUCCESS;
2145}
2146
2147DEFPY(bmp_mirror_limit_cfg,
2148 bmp_mirror_limit_cmd,
2149 "bmp mirror buffer-limit (0-4294967294)",
2150 BMP_STR
2151 "Route Mirroring settings\n"
2152 "Configure maximum memory used for buffered mirroring messages\n"
2153 "Limit in bytes\n")
2154{
2155 VTY_DECLVAR_CONTEXT(bgp, bgp);
2156 struct bmp_bgp *bmpbgp;
2157
2158 bmpbgp = bmp_bgp_get(bgp);
2159 bmpbgp->mirror_qsizelimit = buffer_limit;
2160
2161 return CMD_SUCCESS;
2162}
2163
2164DEFPY(no_bmp_mirror_limit_cfg,
2165 no_bmp_mirror_limit_cmd,
2166 "no bmp mirror buffer-limit [(0-4294967294)]",
2167 NO_STR
2168 BMP_STR
2169 "Route Mirroring settings\n"
2170 "Configure maximum memory used for buffered mirroring messages\n"
2171 "Limit in bytes\n")
2172{
2173 VTY_DECLVAR_CONTEXT(bgp, bgp);
2174 struct bmp_bgp *bmpbgp;
2175
2176 bmpbgp = bmp_bgp_get(bgp);
2177 bmpbgp->mirror_qsizelimit = ~0UL;
2178
2179 return CMD_SUCCESS;
2180}
2181
2182
2183DEFPY(show_bmp,
2184 show_bmp_cmd,
2185 "show bmp",
2186 SHOW_STR
2187 BMP_STR)
2188{
2189 struct bmp_bgp *bmpbgp;
2190 struct bmp_targets *bt;
2191 struct bmp_listener *bl;
150470da 2192 struct bmp_active *ba;
ed18356f
DL
2193 struct bmp *bmp;
2194 struct ttable *tt;
2195 char buf[SU_ADDRSTRLEN];
150470da
DL
2196 char uptime[BGP_UPTIME_LEN];
2197 char *out;
ed18356f
DL
2198
2199 frr_each(bmp_bgph, &bmp_bgph, bmpbgp) {
2200 vty_out(vty, "BMP state for BGP %s:\n\n",
2201 bmpbgp->bgp->name_pretty);
2202 vty_out(vty, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2203 bmpbgp->mirror_qsize,
2204 bmp_mirrorq_count(&bmpbgp->mirrorq));
2205 vty_out(vty, " %9zu bytes maximum buffer used\n",
2206 bmpbgp->mirror_qsizemax);
2207 if (bmpbgp->mirror_qsizelimit != ~0UL)
2208 vty_out(vty, " %9zu bytes buffer size limit\n",
2209 bmpbgp->mirror_qsizelimit);
2210 vty_out(vty, "\n");
2211
2212 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2213 vty_out(vty, " Targets \"%s\":\n", bt->name);
2214 vty_out(vty, " Route Mirroring %sabled\n",
2215 bt->mirror ? "en" : "dis");
2216
2217 afi_t afi;
2218 safi_t safi;
2219
2220 FOREACH_AFI_SAFI (afi, safi) {
2221 const char *str = NULL;
2222
2223 switch (bt->afimon[afi][safi]) {
2224 case BMP_MON_PREPOLICY:
2225 str = "pre-policy";
2226 break;
2227 case BMP_MON_POSTPOLICY:
2228 str = "post-policy";
2229 break;
2230 case BMP_MON_PREPOLICY | BMP_MON_POSTPOLICY:
2231 str = "pre-policy and post-policy";
2232 break;
2233 }
2234 if (!str)
2235 continue;
2236 vty_out(vty, " Route Monitoring %s %s %s\n",
2237 afi2str(afi), safi2str(safi), str);
2238 }
2239
2240 vty_out(vty, " Listeners:\n");
2241 frr_each (bmp_listeners, &bt->listeners, bl)
2242 vty_out(vty, " %s:%d\n",
2243 sockunion2str(&bl->addr, buf,
2244 SU_ADDRSTRLEN), bl->port);
2245
150470da
DL
2246 vty_out(vty, "\n Outbound connections:\n");
2247 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2248 ttable_add_row(tt, "remote|state||timer");
2249 ttable_rowseps(tt, 0, BOTTOM, true, '-');
2250 frr_each (bmp_actives, &bt->actives, ba) {
2251 const char *state_str = "?";
2252
2253 if (ba->bmp) {
2254 peer_uptime(ba->bmp->t_up.tv_sec,
2255 uptime, sizeof(uptime),
2256 false, NULL);
2257 ttable_add_row(tt, "%s:%d|Up|%s|%s",
2258 ba->hostname, ba->port,
2259 ba->bmp->remote, uptime);
2260 continue;
2261 }
2262
2263 uptime[0] = '\0';
2264
2265 if (ba->t_timer) {
2266 long trem = thread_timer_remain_second(
2267 ba->t_timer);
2268
2269 peer_uptime(monotime(NULL) - trem,
2270 uptime, sizeof(uptime),
2271 false, NULL);
2272 state_str = "RetryWait";
2273 } else if (ba->t_read) {
2274 state_str = "Connecting";
2275 } else if (ba->resq.callback) {
2276 state_str = "Resolving";
2277 }
2278
2279 ttable_add_row(tt, "%s:%d|%s|%s|%s",
2280 ba->hostname, ba->port,
2281 state_str,
2282 ba->last_err ? ba->last_err : "",
2283 uptime);
2284 continue;
2285 }
2286 out = ttable_dump(tt, "\n");
2287 vty_out(vty, "%s", out);
2288 XFREE(MTYPE_TMP, out);
2289 ttable_del(tt);
2290
ed18356f
DL
2291 vty_out(vty, "\n %zu connected clients:\n",
2292 bmp_session_count(&bt->sessions));
2293 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2294 ttable_add_row(tt, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2295 ttable_rowseps(tt, 0, BOTTOM, true, '-');
2296
2297 frr_each (bmp_session, &bt->sessions, bmp) {
2298 uint64_t total;
2299 size_t q, kq;
2300
2301 pullwr_stats(bmp->pullwr, &total, &q, &kq);
2302
9e89da8c
DL
2303 peer_uptime(bmp->t_up.tv_sec, uptime,
2304 sizeof(uptime), false, NULL);
2305
2306 ttable_add_row(tt, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2307 bmp->remote, uptime,
ed18356f
DL
2308 bmp->cnt_update,
2309 bmp->cnt_mirror,
2310 bmp->cnt_mirror_overruns,
2311 total, q, kq);
2312 }
150470da 2313 out = ttable_dump(tt, "\n");
ed18356f
DL
2314 vty_out(vty, "%s", out);
2315 XFREE(MTYPE_TMP, out);
2316 ttable_del(tt);
2317 vty_out(vty, "\n");
2318 }
2319 }
2320
2321 return CMD_SUCCESS;
2322}
2323
2324static int bmp_config_write(struct bgp *bgp, struct vty *vty)
2325{
2326 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
2327 struct bmp_targets *bt;
2328 struct bmp_listener *bl;
2329 struct bmp_active *ba;
2330 char buf[SU_ADDRSTRLEN];
2331 afi_t afi;
2332 safi_t safi;
2333
2334 if (!bmpbgp)
2335 return 0;
2336
2337 if (bmpbgp->mirror_qsizelimit != ~0UL)
2338 vty_out(vty, " !\n bmp mirror buffer-limit %zu\n",
2339 bmpbgp->mirror_qsizelimit);
2340
2341 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2342 vty_out(vty, " !\n bmp targets %s\n", bt->name);
2343
2344 if (bt->acl6_name)
2345 vty_out(vty, " ipv6 access-list %s\n", bt->acl6_name);
2346 if (bt->acl_name)
2347 vty_out(vty, " ip access-list %s\n", bt->acl_name);
2348
2349 if (bt->stat_msec)
2350 vty_out(vty, " bmp stats interval %d\n",
2351 bt->stat_msec);
2352
2353 if (bt->mirror)
2354 vty_out(vty, " bmp mirror\n");
2355
2356 FOREACH_AFI_SAFI (afi, safi) {
2357 const char *afi_str = (afi == AFI_IP) ? "ipv4" : "ipv6";
2358
2359 if (bt->afimon[afi][safi] & BMP_MON_PREPOLICY)
2360 vty_out(vty, " bmp monitor %s %s pre-policy\n",
2361 afi_str, safi2str(safi));
2362 if (bt->afimon[afi][safi] & BMP_MON_POSTPOLICY)
2363 vty_out(vty, " bmp monitor %s %s post-policy\n",
2364 afi_str, safi2str(safi));
2365 }
2366 frr_each (bmp_listeners, &bt->listeners, bl)
2367 vty_out(vty, " \n bmp listener %s port %d\n",
2368 sockunion2str(&bl->addr, buf, SU_ADDRSTRLEN),
2369 bl->port);
2370
2371 frr_each (bmp_actives, &bt->actives, ba)
2372 vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n",
2373 ba->hostname, ba->port, ba->minretry, ba->maxretry);
2374 }
2375
2376 return 0;
2377}
2378
2379static int bgp_bmp_init(struct thread_master *tm)
2380{
612c2c15 2381 install_node(&bmp_node);
ed18356f
DL
2382 install_default(BMP_NODE);
2383 install_element(BGP_NODE, &bmp_targets_cmd);
2384 install_element(BGP_NODE, &no_bmp_targets_cmd);
2385
2386 install_element(BMP_NODE, &bmp_listener_cmd);
2387 install_element(BMP_NODE, &no_bmp_listener_cmd);
2388 install_element(BMP_NODE, &bmp_connect_cmd);
2389 install_element(BMP_NODE, &bmp_acl_cmd);
2390 install_element(BMP_NODE, &bmp_stats_cmd);
2391 install_element(BMP_NODE, &bmp_monitor_cmd);
2392 install_element(BMP_NODE, &bmp_mirror_cmd);
2393
2394 install_element(BGP_NODE, &bmp_mirror_limit_cmd);
2395 install_element(BGP_NODE, &no_bmp_mirror_limit_cmd);
2396
2397 install_element(VIEW_NODE, &show_bmp_cmd);
2398
2399 resolver_init(tm);
0ba4eeec 2400 return 0;
6c29258c
YO
2401}
2402
0ba4eeec
DL
2403static int bgp_bmp_module_init(void)
2404{
2405 hook_register(bgp_packet_dump, bmp_mirror_packet);
ed18356f 2406 hook_register(bgp_packet_send, bmp_outgoing_packet);
df9e8ae7 2407 hook_register(peer_status_changed, bmp_peer_established);
ed18356f
DL
2408 hook_register(peer_backward_transition, bmp_peer_backward);
2409 hook_register(bgp_process, bmp_process);
2410 hook_register(bgp_inst_config_write, bmp_config_write);
2411 hook_register(bgp_inst_delete, bmp_bgp_del);
0ba4eeec
DL
2412 hook_register(frr_late_init, bgp_bmp_init);
2413 return 0;
2414}
6c29258c 2415
0ba4eeec
DL
2416FRR_MODULE_SETUP(.name = "bgpd_bmp", .version = FRR_VERSION,
2417 .description = "bgpd BMP module",
2418 .init = bgp_bmp_module_init)