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