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