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