]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bmp.c
bgpd/bmp: actually print uptime
[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
df9e8ae7
MS
666 /* Check if this peer just went to Established */
667 if ((peer->last_major_event != OpenConfirm) ||
668 !(peer_established(peer)))
669 return 0;
670
ed18356f
DL
671 if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
672 struct bmp_bgp_peer *bbpeer, *bbdopp;
6c29258c 673
ed18356f
DL
674 bbpeer = bmp_bgp_peer_get(peer);
675 bbdopp = bmp_bgp_peer_find(peer->doppelganger->qobj_node.nid);
676 if (bbdopp) {
677 XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx);
678 XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
6c29258c 679
ed18356f
DL
680 bbpeer->open_tx = bbdopp->open_tx;
681 bbpeer->open_tx_len = bbdopp->open_tx_len;
682 bbpeer->open_rx = bbdopp->open_rx;
683 bbpeer->open_rx_len = bbdopp->open_rx_len;
6c29258c 684
ed18356f
DL
685 bmp_peerh_del(&bmp_peerh, bbdopp);
686 XFREE(MTYPE_BMP_PEER, bbdopp);
687 }
6c29258c 688 }
ed18356f
DL
689
690 bmp_send_all(bmpbgp, bmp_peerstate(peer, false));
6c29258c
YO
691 return 0;
692}
693
ed18356f 694static int bmp_peer_backward(struct peer *peer)
6c29258c 695{
ed18356f
DL
696 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
697 struct bmp_bgp_peer *bbpeer;
6c29258c 698
ed18356f
DL
699 if (!bmpbgp)
700 return 0;
6c29258c 701
ed18356f
DL
702 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
703 if (bbpeer) {
704 XFREE(MTYPE_BMP_OPEN, bbpeer->open_tx);
705 bbpeer->open_tx_len = 0;
706 XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
707 bbpeer->open_rx_len = 0;
708 }
6c29258c 709
ed18356f
DL
710 bmp_send_all(bmpbgp, bmp_peerstate(peer, true));
711 return 0;
712}
6c29258c 713
ed18356f
DL
714static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags)
715{
716 struct peer *peer;
717 struct listnode *node;
718 struct stream *s, *s2;
719 iana_afi_t pkt_afi;
720 iana_safi_t pkt_safi;
6c29258c 721
ed18356f 722 s = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 723
ed18356f
DL
724 /* Make BGP update packet. */
725 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
6c29258c 726
ed18356f
DL
727 /* Unfeasible Routes Length */
728 stream_putw(s, 0);
6c29258c 729
ed18356f
DL
730 if (afi == AFI_IP && safi == SAFI_UNICAST) {
731 /* Total Path Attribute Length */
732 stream_putw(s, 0);
733 } else {
734 /* Convert AFI, SAFI to values for packet. */
735 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
736
737 /* Total Path Attribute Length */
738 stream_putw(s, 6);
739 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
740 stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
741 stream_putc(s, 3);
742 stream_putw(s, pkt_afi);
743 stream_putc(s, pkt_safi);
6c29258c
YO
744 }
745
ed18356f 746 bgp_packet_set_size(s);
6c29258c 747
ed18356f
DL
748 for (ALL_LIST_ELEMENTS_RO(bmp->targets->bgp->peer, node, peer)) {
749 if (!peer->afc_nego[afi][safi])
750 continue;
6c29258c 751
ed18356f 752 s2 = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 753
ed18356f
DL
754 bmp_common_hdr(s2, BMP_VERSION_3,
755 BMP_TYPE_ROUTE_MONITORING);
756 bmp_per_peer_hdr(s2, peer, flags, NULL);
6c29258c 757
ed18356f
DL
758 stream_putl_at(s2, BMP_LENGTH_POS,
759 stream_get_endp(s) + stream_get_endp(s2));
6c29258c 760
ed18356f
DL
761 bmp->cnt_update++;
762 pullwr_write_stream(bmp->pullwr, s2);
763 pullwr_write_stream(bmp->pullwr, s);
764 stream_free(s2);
765 }
766 stream_free(s);
6c29258c
YO
767}
768
ed18356f
DL
769static struct stream *bmp_update(struct prefix *p, struct peer *peer,
770 struct attr *attr, afi_t afi, safi_t safi)
6c29258c 771{
ed18356f
DL
772 struct bpacket_attr_vec_arr vecarr;
773 struct stream *s;
774 size_t attrlen_pos = 0, mpattrlen_pos = 0;
775 bgp_size_t total_attr_len = 0;
776
777 bpacket_attr_vec_arr_reset(&vecarr);
778
779 s = stream_new(BGP_MAX_PACKET_SIZE);
780 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
781
782 /* 2: withdrawn routes length */
783 stream_putw(s, 0);
784
785 /* 3: total attributes length - attrlen_pos stores the position */
786 attrlen_pos = stream_get_endp(s);
787 stream_putw(s, 0);
788
789 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
790 total_attr_len = bgp_packet_attribute(NULL, peer, s, attr,
791 &vecarr, NULL, afi, safi, peer, NULL, NULL, 0, 0, 0);
6c29258c 792
ed18356f 793 /* space check? */
6c29258c 794
ed18356f
DL
795 /* peer_cap_enhe & add-path removed */
796 if (afi == AFI_IP && safi == SAFI_UNICAST)
797 stream_put_prefix(s, p);
798 else {
799 size_t p1 = stream_get_endp(s);
6c29258c 800
ed18356f 801 /* MPLS removed for now */
6c29258c 802
ed18356f
DL
803 mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
804 &vecarr, attr);
805 bgp_packet_mpattr_prefix(s, afi, safi, p, NULL, NULL, 0,
806 0, 0, attr);
807 bgp_packet_mpattr_end(s, mpattrlen_pos);
808 total_attr_len += stream_get_endp(s) - p1;
6c29258c
YO
809 }
810
ed18356f
DL
811 /* set the total attribute length correctly */
812 stream_putw_at(s, attrlen_pos, total_attr_len);
813 bgp_packet_set_size(s);
814 return s;
815}
6c29258c 816
ed18356f
DL
817static struct stream *bmp_withdraw(struct prefix *p, afi_t afi, safi_t safi)
818{
819 struct stream *s;
820 size_t attrlen_pos = 0, mp_start, mplen_pos;
821 bgp_size_t total_attr_len = 0;
822 bgp_size_t unfeasible_len;
6c29258c 823
ed18356f 824 s = stream_new(BGP_MAX_PACKET_SIZE);
6c29258c 825
ed18356f
DL
826 bgp_packet_set_marker(s, BGP_MSG_UPDATE);
827 stream_putw(s, 0);
6c29258c 828
ed18356f
DL
829 if (afi == AFI_IP && safi == SAFI_UNICAST) {
830 stream_put_prefix(s, p);
831 unfeasible_len = stream_get_endp(s) - BGP_HEADER_SIZE
832 - BGP_UNFEASIBLE_LEN;
833 stream_putw_at(s, BGP_HEADER_SIZE, unfeasible_len);
834 stream_putw(s, 0);
835 } else {
836 attrlen_pos = stream_get_endp(s);
837 /* total attr length = 0 for now. reevaluate later */
838 stream_putw(s, 0);
839 mp_start = stream_get_endp(s);
840 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
841
842 bgp_packet_mpunreach_prefix(s, p, afi, safi, NULL, NULL, 0,
843 0, 0, NULL);
844 /* Set the mp_unreach attr's length */
845 bgp_packet_mpunreach_end(s, mplen_pos);
846
847 /* Set total path attribute length. */
848 total_attr_len = stream_get_endp(s) - mp_start;
849 stream_putw_at(s, attrlen_pos, total_attr_len);
850 }
851
852 bgp_packet_set_size(s);
853 return s;
854}
855
856static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
857 struct prefix *p, struct attr *attr, afi_t afi,
858 safi_t safi, time_t uptime)
859{
860 struct stream *hdr, *msg;
861 struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
862
863 if (attr)
864 msg = bmp_update(p, peer, attr, afi, safi);
865 else
866 msg = bmp_withdraw(p, afi, safi);
867
868 hdr = stream_new(BGP_MAX_PACKET_SIZE);
869 bmp_common_hdr(hdr, BMP_VERSION_3, BMP_TYPE_ROUTE_MONITORING);
870 bmp_per_peer_hdr(hdr, peer, flags, &tv);
871
872 stream_putl_at(hdr, BMP_LENGTH_POS,
873 stream_get_endp(hdr) + stream_get_endp(msg));
874
875 bmp->cnt_update++;
876 pullwr_write_stream(bmp->pullwr, hdr);
877 pullwr_write_stream(bmp->pullwr, msg);
878 stream_free(hdr);
879 stream_free(msg);
880}
881
882static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr)
883{
884 afi_t afi;
885 safi_t safi;
886
887 if (bmp->syncafi == AFI_MAX) {
888 FOREACH_AFI_SAFI (afi, safi) {
889 if (bmp->afistate[afi][safi] != BMP_AFI_NEEDSYNC)
890 continue;
891
892 bmp->afistate[afi][safi] = BMP_AFI_SYNC;
893
894 bmp->syncafi = afi;
895 bmp->syncsafi = safi;
896 bmp->syncpeerid = 0;
897 memset(&bmp->syncpos, 0, sizeof(bmp->syncpos));
898 bmp->syncpos.family = afi2family(afi);
899 zlog_info("bmp[%s] %s %s sending table",
900 bmp->remote,
901 afi2str(bmp->syncafi),
902 safi2str(bmp->syncsafi));
903 /* break does not work here, 2 loops... */
904 goto afibreak;
6c29258c 905 }
ed18356f
DL
906 if (bmp->syncafi == AFI_MAX)
907 return false;
908 }
6c29258c 909
ed18356f
DL
910afibreak:
911 afi = bmp->syncafi;
912 safi = bmp->syncsafi;
913
914 if (!bmp->targets->afimon[afi][safi]) {
915 /* shouldn't happen */
916 bmp->afistate[afi][safi] = BMP_AFI_INACTIVE;
917 bmp->syncafi = AFI_MAX;
918 bmp->syncsafi = SAFI_MAX;
919 return true;
920 }
921
922 struct bgp_table *table = bmp->targets->bgp->rib[afi][safi];
923 struct bgp_node *bn;
924 struct bgp_path_info *bpi = NULL, *bpiter;
925 struct bgp_adj_in *adjin = NULL, *adjiter;
926
927 bn = bgp_node_lookup(table, &bmp->syncpos);
928 do {
929 if (!bn) {
930 bn = bgp_table_get_next(table, &bmp->syncpos);
931 if (!bn) {
932 zlog_info("bmp[%s] %s %s table completed (EoR)",
933 bmp->remote, afi2str(afi),
934 safi2str(safi));
935 bmp_eor(bmp, afi, safi, BMP_PEER_FLAG_L);
936 bmp_eor(bmp, afi, safi, 0);
937
938 bmp->afistate[afi][safi] = BMP_AFI_LIVE;
939 bmp->syncafi = AFI_MAX;
940 bmp->syncsafi = SAFI_MAX;
941 return true;
942 }
943 bmp->syncpeerid = 0;
944 prefix_copy(&bmp->syncpos, &bn->p);
6c29258c
YO
945 }
946
ed18356f
DL
947 if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
948 for (bpiter = bn->info; bpiter; bpiter = bpiter->next) {
949 if (!CHECK_FLAG(bpiter->flags, BGP_PATH_VALID))
950 continue;
951 if (bpiter->peer->qobj_node.nid
952 <= bmp->syncpeerid)
953 continue;
954 if (bpi && bpiter->peer->qobj_node.nid
955 > bpi->peer->qobj_node.nid)
956 continue;
957 bpi = bpiter;
958 }
959 }
960 if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
961 for (adjiter = bn->adj_in; adjiter;
962 adjiter = adjiter->next) {
963 if (adjiter->peer->qobj_node.nid
964 <= bmp->syncpeerid)
965 continue;
966 if (adjin && adjiter->peer->qobj_node.nid
967 > adjin->peer->qobj_node.nid)
968 continue;
969 adjin = adjiter;
970 }
971 }
972 if (bpi || adjin)
973 break;
974
975 bn = NULL;
976 } while (1);
977
978 if (adjin && bpi
979 && adjin->peer->qobj_node.nid < bpi->peer->qobj_node.nid) {
980 bpi = NULL;
981 bmp->syncpeerid = adjin->peer->qobj_node.nid;
982 } else if (adjin && bpi
983 && adjin->peer->qobj_node.nid > bpi->peer->qobj_node.nid) {
984 adjin = NULL;
985 bmp->syncpeerid = bpi->peer->qobj_node.nid;
986 } else if (bpi) {
987 bmp->syncpeerid = bpi->peer->qobj_node.nid;
988 } else if (adjin) {
989 bmp->syncpeerid = adjin->peer->qobj_node.nid;
990 }
6c29258c 991
ed18356f
DL
992 if (bpi)
993 bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L, &bn->p, bpi->attr,
994 afi, safi, bpi->uptime);
995 if (adjin)
996 bmp_monitor(bmp, adjin->peer, 0, &bn->p, adjin->attr,
997 afi, safi, adjin->uptime);
6c29258c 998
ed18356f 999 return true;
6c29258c
YO
1000}
1001
ed18356f 1002static struct bmp_queue_entry *bmp_pull(struct bmp *bmp)
6c29258c 1003{
ed18356f
DL
1004 struct bmp_queue_entry *bqe;
1005
1006 bqe = bmp->queuepos;
1007 if (!bqe)
1008 return NULL;
1009
1010 bmp->queuepos = bmp_qlist_next(&bmp->targets->updlist, bqe);
1011
1012 bqe->refcount--;
1013 if (!bqe->refcount) {
1014 bmp_qhash_del(&bmp->targets->updhash, bqe);
1015 bmp_qlist_del(&bmp->targets->updlist, bqe);
1016 }
1017 return bqe;
1018}
1019
1020static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
1021{
1022 struct bmp_queue_entry *bqe;
1023 struct peer *peer;
1024 struct bgp_node *bn;
1025 bool written = false;
1026
1027 bqe = bmp_pull(bmp);
1028 if (!bqe)
1029 return false;
1030
1031 afi_t afi = bqe->afi;
1032 safi_t safi = bqe->safi;
1033
1034 switch (bmp->afistate[afi][safi]) {
1035 case BMP_AFI_INACTIVE:
1036 case BMP_AFI_NEEDSYNC:
1037 goto out;
1038 case BMP_AFI_SYNC:
1039 if (prefix_cmp(&bqe->p, &bmp->syncpos) <= 0)
1040 /* currently syncing but have already passed this
1041 * prefix => send it. */
1042 break;
1043
1044 /* currently syncing & haven't reached this prefix yet
1045 * => it'll be sent as part of the table sync, no need here */
1046 goto out;
1047 case BMP_AFI_LIVE:
1048 break;
1049 }
1050
1051 peer = QOBJ_GET_TYPESAFE(bqe->peerid, peer);
1052 if (!peer) {
1053 zlog_info("bmp: skipping queued item for deleted peer");
1054 goto out;
1055 }
1056 if (peer->status != Established)
1057 goto out;
1058
1059 bn = bgp_node_lookup(bmp->targets->bgp->rib[afi][safi], &bqe->p);
1060
1061 if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
1062 struct bgp_path_info *bpi;
1063
1064 for (bpi = bn ? bn->info : NULL; bpi; bpi = bpi->next) {
1065 if (!CHECK_FLAG(bpi->flags, BGP_PATH_VALID))
1066 continue;
1067 if (bpi->peer == peer)
1068 break;
1069 }
1070
1071 bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p,
1072 bpi ? bpi->attr : NULL, afi, safi,
1073 bpi ? bpi->uptime : monotime(NULL));
1074 written = true;
1075 }
1076
1077 if (bmp->targets->afimon[afi][safi] & BMP_MON_PREPOLICY) {
1078 struct bgp_adj_in *adjin;
1079
1080 for (adjin = bn ? bn->adj_in : NULL; adjin;
1081 adjin = adjin->next) {
1082 if (adjin->peer == peer)
1083 break;
1084 }
1085 bmp_monitor(bmp, peer, BMP_PEER_FLAG_L, &bqe->p,
1086 adjin ? adjin->attr : NULL, afi, safi,
1087 adjin ? adjin->uptime : monotime(NULL));
1088 written = true;
1089 }
1090
1091out:
1092 if (!bqe->refcount)
1093 XFREE(MTYPE_BMP_QUEUE, bqe);
1094 return written;
1095}
1096
1097static void bmp_wrfill(struct bmp *bmp, struct pullwr *pullwr)
1098{
1099 switch(bmp->state) {
1100 case BMP_PeerUp:
1101 bmp_send_peerup(bmp);
1102 bmp->state = BMP_Run;
1103 break;
1104
1105 case BMP_Run:
1106 if (bmp_wrmirror(bmp, pullwr))
1107 break;
1108 if (bmp_wrqueue(bmp, pullwr))
1109 break;
1110 if (bmp_wrsync(bmp, pullwr))
1111 break;
1112 break;
1113 }
1114}
1115
1116static void bmp_wrerr(struct bmp *bmp, struct pullwr *pullwr, bool eof)
1117{
1118 if (eof)
1119 zlog_info("bmp[%s] disconnected", bmp->remote);
1120 else
1121 flog_warn(EC_LIB_SYSTEM_CALL, "bmp[%s] connection error: %s",
1122 bmp->remote, strerror(errno));
1123
1124 bmp_close(bmp);
1125 bmp_free(bmp);
1126}
1127
1128static void bmp_process_one(struct bmp_targets *bt, struct bgp *bgp,
1129 afi_t afi, safi_t safi, struct bgp_node *bn, struct peer *peer)
1130{
1131 struct bmp *bmp;
1132 struct bmp_queue_entry *bqe, bqeref;
1133 size_t refcount;
1134 char buf[256];
1135
1136 prefix2str(&bn->p, buf, sizeof(buf));
1137
1138 refcount = bmp_session_count(&bt->sessions);
1139 if (refcount == 0)
1140 return;
1141
1142 memset(&bqeref, 0, sizeof(bqeref));
1143 prefix_copy(&bqeref.p, &bn->p);
1144 bqeref.peerid = peer->qobj_node.nid;
1145 bqeref.afi = afi;
1146 bqeref.safi = safi;
1147
1148 bqe = bmp_qhash_find(&bt->updhash, &bqeref);
1149 if (bqe) {
1150 if (bqe->refcount >= refcount)
1151 /* nothing to do here */
1152 return;
1153
1154 bmp_qlist_del(&bt->updlist, bqe);
1155 } else {
1156 bqe = XMALLOC(MTYPE_BMP_QUEUE, sizeof(*bqe));
1157 memcpy(bqe, &bqeref, sizeof(*bqe));
1158
1159 bmp_qhash_add(&bt->updhash, bqe);
1160 }
1161
1162 bqe->refcount = refcount;
1163 bmp_qlist_add_tail(&bt->updlist, bqe);
1164
1165 frr_each (bmp_session, &bt->sessions, bmp)
1166 if (!bmp->queuepos)
1167 bmp->queuepos = bqe;
1168}
1169
1170static int bmp_process(struct bgp *bgp, afi_t afi, safi_t safi,
1171 struct bgp_node *bn, struct peer *peer, bool withdraw)
1172{
1173 struct bmp_bgp *bmpbgp = bmp_bgp_find(peer->bgp);
1174 struct bmp_targets *bt;
1175 struct bmp *bmp;
1176
1177 if (!bmpbgp)
1178 return 0;
1179
1180 frr_each(bmp_targets, &bmpbgp->targets, bt) {
1181 if (!bt->afimon[afi][safi])
1182 continue;
1183
1184 bmp_process_one(bt, bgp, afi, safi, bn, peer);
1185
1186 frr_each(bmp_session, &bt->sessions, bmp) {
1187 pullwr_bump(bmp->pullwr);
1188 }
1189 }
1190 return 0;
1191}
1192
1193static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type,
1194 uint32_t value)
1195{
1196 stream_putw(s, type);
1197 stream_putw(s, 4);
1198 stream_putl(s, value);
1199 (*cnt)++;
1200}
1201
1202static int bmp_stats(struct thread *thread)
1203{
1204 struct bmp_targets *bt = THREAD_ARG(thread);
1205 struct stream *s;
1206 struct peer *peer;
1207 struct listnode *node;
1208 struct timeval tv;
1209
1210 if (bt->stat_msec)
1211 thread_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec,
1212 &bt->t_stats);
1213
1214 gettimeofday(&tv, NULL);
1215
1216 /* Walk down all peers */
1217 for (ALL_LIST_ELEMENTS_RO(bt->bgp->peer, node, peer)) {
1218 size_t count = 0, count_pos, len;
1219
1220 if (peer->status != Established)
1221 continue;
1222
1223 s = stream_new(BGP_MAX_PACKET_SIZE);
1224 bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_STATISTICS_REPORT);
1225 bmp_per_peer_hdr(s, peer, 0, &tv);
1226
1227 count_pos = stream_get_endp(s);
1228 stream_putl(s, 0);
1229
1230 bmp_stat_put_u32(s, &count, BMP_STATS_PFX_REJECTED,
1231 peer->stat_pfx_filter);
1232 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ASPATH,
1233 peer->stat_pfx_aspath_loop);
1234 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_ORIGINATOR,
1235 peer->stat_pfx_originator_loop);
1236 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_LOOP_CLUSTER,
1237 peer->stat_pfx_cluster_loop);
1238 bmp_stat_put_u32(s, &count, BMP_STATS_PFX_DUP_WITHDRAW,
1239 peer->stat_pfx_dup_withdraw);
1240 bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW,
1241 peer->stat_upd_7606);
1242 bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
1243 peer->stat_pfx_nh_invalid);
1244
1245 stream_putl_at(s, count_pos, count);
1246
1247 len = stream_get_endp(s);
1248 stream_putl_at(s, BMP_LENGTH_POS, len);
1249
1250 bmp_send_all(bt->bmpbgp, s);
1251 }
1252 return 0;
1253}
1254
1255static struct bmp *bmp_open(struct bmp_targets *bt, int bmp_sock)
1256{
1257 union sockunion su, *sumem;
1258 struct prefix p;
1259 int on = 1;
1260 struct access_list *acl = NULL;
1261 enum filter_type ret;
1262 char buf[SU_ADDRSTRLEN];
1263 struct bmp *bmp;
1264
1265 sumem = sockunion_getpeername(bmp_sock);
1266 if (!sumem) {
1267 close(bmp_sock);
1268 return NULL;
1269 }
1270 memcpy(&su, sumem, sizeof(su));
1271 sockunion_free(sumem);
1272
1273 set_nonblocking(bmp_sock);
1274 set_cloexec(bmp_sock);
1275 shutdown(bmp_sock, SHUT_RD);
1276
1277 sockunion2hostprefix(&su, &p);
1278
1279 acl = NULL;
1280 switch (p.family) {
1281 case AF_INET:
1282 acl = access_list_lookup(AFI_IP, bt->acl_name);
1283 break;
1284 case AF_INET6:
1285 acl = access_list_lookup(AFI_IP6, bt->acl6_name);
1286 break;
1287 default:
1288 break;
1289 }
1290
1291 ret = FILTER_PERMIT;
1292 if (acl) {
1293 ret = access_list_apply(acl, &p);
1294 }
1295
1296 sockunion2str(&su, buf, SU_ADDRSTRLEN);
1297 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":%u",
1298 su.sa.sa_family == AF_INET
1299 ? ntohs(su.sin.sin_port)
1300 : ntohs(su.sin6.sin6_port));
1301
1302 if (ret == FILTER_DENY) {
1303 bt->cnt_aclrefused++;
1304 zlog_info("bmp[%s] connection refused by access-list", buf);
1305 close(bmp_sock);
1306 return NULL;
1307 }
1308 bt->cnt_accept++;
1309
d38c6bb1
DS
1310 if (setsockopt(bmp_sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
1311 flog_err(EC_LIB_SOCKET, "bmp: %d can't setsockopt SO_KEEPALIVE: %s(%d)",
1312 bmp_sock, safe_strerror(errno), errno);
1313 if (setsockopt(bmp_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
1314 flog_err(EC_LIB_SOCKET, "bmp: %d can't setsockopt TCP_NODELAY: %s(%d)",
1315 bmp_sock, safe_strerror(errno), errno);
ed18356f
DL
1316
1317 zlog_info("bmp[%s] connection established", buf);
1318
1319 /* Allocate new BMP structure and set up default values. */
1320 bmp = bmp_new(bt, bmp_sock);
1321 strlcpy(bmp->remote, buf, sizeof(bmp->remote));
1322
1323 bmp->state = BMP_PeerUp;
1324 bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill,
1325 bmp_wrerr);
1326 bmp_send_initiation(bmp);
1327
1328 return bmp;
1329}
1330
1331/* Accept BMP connection. */
1332static int bmp_accept(struct thread *thread)
1333{
1334 union sockunion su;
1335 struct bmp_listener *bl = THREAD_ARG(thread);
1336 int bmp_sock;
1337
1338 /* We continue hearing BMP socket. */
1339 thread_add_read(bm->master, bmp_accept, bl, bl->sock, &bl->t_accept);
1340
1341 memset(&su, 0, sizeof(union sockunion));
1342
1343 /* We can handle IPv4 or IPv6 socket. */
1344 bmp_sock = sockunion_accept(bl->sock, &su);
1345 if (bmp_sock < 0) {
1346 zlog_info("bmp: accept_sock failed: %s\n",
1347 safe_strerror (errno));
1348 return -1;
1349 }
1350 bmp_open(bl->targets, bmp_sock);
1351 return 0;
1352}
1353
1354static void bmp_close(struct bmp *bmp)
1355{
1356 struct bmp_queue_entry *bqe;
1357 struct bmp_mirrorq *bmq;
1358
1359 if (bmp->active)
1360 bmp_active_disconnected(bmp->active);
1361
1362 while ((bmq = bmp_pull_mirror(bmp)))
1363 if (!bmq->refcount)
1364 XFREE(MTYPE_BMP_MIRRORQ, bmq);
1365 while ((bqe = bmp_pull(bmp)))
1366 if (!bqe->refcount)
1367 XFREE(MTYPE_BMP_QUEUE, bqe);
1368
1369 THREAD_OFF(bmp->t_read);
1370 pullwr_del(bmp->pullwr);
1371 close(bmp->socket);
1372}
1373
1374static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp)
1375{
1376 struct bmp_bgp dummy = { .bgp = bgp };
1377 return bmp_bgph_find(&bmp_bgph, &dummy);
1378}
1379
1380static struct bmp_bgp *bmp_bgp_get(struct bgp *bgp)
1381{
1382 struct bmp_bgp *bmpbgp;
1383
1384 bmpbgp = bmp_bgp_find(bgp);
1385 if (bmpbgp)
1386 return bmpbgp;
1387
1388 bmpbgp = XCALLOC(MTYPE_BMP, sizeof(*bmpbgp));
1389 bmpbgp->bgp = bgp;
1390 bmpbgp->mirror_qsizelimit = ~0UL;
1391 bmp_mirrorq_init(&bmpbgp->mirrorq);
1392 bmp_bgph_add(&bmp_bgph, bmpbgp);
1393
1394 return bmpbgp;
1395}
1396
1397static void bmp_bgp_put(struct bmp_bgp *bmpbgp)
1398{
1399 struct bmp_targets *bt;
1400
1401 bmp_bgph_del(&bmp_bgph, bmpbgp);
1402
1403 frr_each_safe(bmp_targets, &bmpbgp->targets, bt)
1404 bmp_targets_put(bt);
1405
1406 bmp_mirrorq_fini(&bmpbgp->mirrorq);
1407 XFREE(MTYPE_BMP, bmpbgp);
1408}
1409
1410static int bmp_bgp_del(struct bgp *bgp)
1411{
1412 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1413
1414 if (bmpbgp)
1415 bmp_bgp_put(bmpbgp);
1416 return 0;
1417}
1418
1419static struct bmp_bgp_peer *bmp_bgp_peer_find(uint64_t peerid)
1420{
1421 struct bmp_bgp_peer dummy = { .peerid = peerid };
1422 return bmp_peerh_find(&bmp_peerh, &dummy);
1423}
1424
1425static struct bmp_bgp_peer *bmp_bgp_peer_get(struct peer *peer)
1426{
1427 struct bmp_bgp_peer *bbpeer;
1428
1429 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
1430 if (bbpeer)
1431 return bbpeer;
1432
1433 bbpeer = XCALLOC(MTYPE_BMP_PEER, sizeof(*bbpeer));
1434 bbpeer->peerid = peer->qobj_node.nid;
1435 bmp_peerh_add(&bmp_peerh, bbpeer);
1436
1437 return bbpeer;
1438}
1439
1440static struct bmp_targets *bmp_targets_find1(struct bgp *bgp, const char *name)
1441{
1442 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1443 struct bmp_targets dummy;
1444
1445 if (!bmpbgp)
1446 return NULL;
1447 dummy.name = (char *)name;
1448 return bmp_targets_find(&bmpbgp->targets, &dummy);
1449}
1450
1451static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
1452{
1453 struct bmp_targets *bt;
1454
1455 bt = bmp_targets_find1(bgp, name);
1456 if (bt)
1457 return bt;
1458
1459 bt = XCALLOC(MTYPE_BMP_TARGETS, sizeof(*bt));
1460 bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name);
1461 bt->bgp = bgp;
1462 bt->bmpbgp = bmp_bgp_get(bgp);
1463 bmp_session_init(&bt->sessions);
1464 bmp_qhash_init(&bt->updhash);
1465 bmp_qlist_init(&bt->updlist);
1466 bmp_actives_init(&bt->actives);
1467 bmp_listeners_init(&bt->listeners);
1468
1469 QOBJ_REG(bt, bmp_targets);
1470 bmp_targets_add(&bt->bmpbgp->targets, bt);
1471 return bt;
1472}
1473
1474static void bmp_targets_put(struct bmp_targets *bt)
1475{
1476 struct bmp *bmp;
1477 struct bmp_active *ba;
1478
1479 frr_each_safe (bmp_actives, &bt->actives, ba)
1480 bmp_active_put(ba);
1481
1482 frr_each_safe(bmp_session, &bt->sessions, bmp) {
1483 bmp_close(bmp);
1484 bmp_free(bmp);
1485 }
1486
1487 bmp_targets_del(&bt->bmpbgp->targets, bt);
1488 QOBJ_UNREG(bt);
1489
1490 bmp_listeners_fini(&bt->listeners);
1491 bmp_actives_fini(&bt->actives);
1492 bmp_qhash_fini(&bt->updhash);
1493 bmp_qlist_fini(&bt->updlist);
1494
1495 XFREE(MTYPE_BMP_ACLNAME, bt->acl_name);
1496 XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name);
1497 bmp_session_fini(&bt->sessions);
1498
1499 XFREE(MTYPE_BMP_TARGETSNAME, bt->name);
1500 XFREE(MTYPE_BMP_TARGETS, bt);
1501}
1502
1503static struct bmp_listener *bmp_listener_find(struct bmp_targets *bt,
1504 const union sockunion *su,
1505 int port)
1506{
1507 struct bmp_listener dummy;
1508 dummy.addr = *su;
1509 dummy.port = port;
1510 return bmp_listeners_find(&bt->listeners, &dummy);
1511}
1512
1513static struct bmp_listener *bmp_listener_get(struct bmp_targets *bt,
1514 const union sockunion *su,
1515 int port)
1516{
1517 struct bmp_listener *bl = bmp_listener_find(bt, su, port);
1518
1519 if (bl)
1520 return bl;
1521
1522 bl = XCALLOC(MTYPE_BMP_LISTENER, sizeof(*bl));
1523 bl->targets = bt;
1524 bl->addr = *su;
1525 bl->port = port;
1526 bl->sock = -1;
1527
1528 bmp_listeners_add(&bt->listeners, bl);
1529 return bl;
1530}
1531
1532static void bmp_listener_put(struct bmp_listener *bl)
1533{
1534 bmp_listeners_del(&bl->targets->listeners, bl);
1535 XFREE(MTYPE_BMP_LISTENER, bl);
1536}
1537
1538static void bmp_listener_start(struct bmp_listener *bl)
1539{
1540 int sock, ret;
1541
1542 sock = socket(bl->addr.sa.sa_family, SOCK_STREAM, 0);
1543 if (sock < 0)
1544 return;
1545
1546 sockopt_reuseaddr(sock);
1547 sockopt_reuseport(sock);
1548 sockopt_v6only(bl->addr.sa.sa_family, sock);
1549 set_cloexec(sock);
1550
1551 ret = sockunion_bind(sock, &bl->addr, bl->port, &bl->addr);
1552 if (ret < 0)
1553 goto out_sock;
1554
1555 ret = listen(sock, 3);
1556 if (ret < 0)
1557 goto out_sock;
1558
1559 bl->sock = sock;
1560 thread_add_read(bm->master, bmp_accept, bl, sock, &bl->t_accept);
1561 return;
1562out_sock:
1563 close(sock);
1564}
1565
1566static void bmp_listener_stop(struct bmp_listener *bl)
1567{
1568 THREAD_OFF(bl->t_accept);
1569
1570 if (bl->sock != -1)
1571 close(bl->sock);
1572 bl->sock = -1;
1573}
1574
1575static struct bmp_active *bmp_active_find(struct bmp_targets *bt,
1576 const char *hostname, int port)
1577{
1578 struct bmp_active dummy;
1579 dummy.hostname = (char *)hostname;
1580 dummy.port = port;
1581 return bmp_actives_find(&bt->actives, &dummy);
1582}
1583
1584static struct bmp_active *bmp_active_get(struct bmp_targets *bt,
1585 const char *hostname, int port)
1586{
1587 struct bmp_active *ba;
1588
1589 ba = bmp_active_find(bt, hostname, port);
1590 if (ba)
1591 return ba;
1592
1593 ba = XCALLOC(MTYPE_BMP_ACTIVE, sizeof(*ba));
1594 ba->targets = bt;
1595 ba->hostname = XSTRDUP(MTYPE_TMP, hostname);
1596 ba->port = port;
1597 ba->minretry = BMP_DFLT_MINRETRY;
1598 ba->maxretry = BMP_DFLT_MAXRETRY;
1599 ba->socket = -1;
1600
1601 bmp_actives_add(&bt->actives, ba);
1602 return ba;
1603}
1604
1605static void bmp_active_put(struct bmp_active *ba)
1606{
1607 THREAD_OFF(ba->t_timer);
1608 THREAD_OFF(ba->t_read);
1609 THREAD_OFF(ba->t_write);
1610
1611 bmp_actives_del(&ba->targets->actives, ba);
1612
1613 if (ba->bmp) {
1614 ba->bmp->active = NULL;
1615 bmp_close(ba->bmp);
1616 bmp_free(ba->bmp);
1617 }
1618 if (ba->socket != -1)
1619 close(ba->socket);
1620
1621 XFREE(MTYPE_TMP, ba->hostname);
1622 XFREE(MTYPE_BMP_ACTIVE, ba);
1623}
1624
1625static void bmp_active_setup(struct bmp_active *ba);
1626
1627static void bmp_active_connect(struct bmp_active *ba)
1628{
1629 enum connect_result res;
1630 char buf[SU_ADDRSTRLEN];
1631
1632 for (; ba->addrpos < ba->addrtotal; ba->addrpos++) {
1633 ba->socket = sockunion_socket(&ba->addrs[ba->addrpos]);
1634 if (ba->socket < 0) {
1635 zlog_warn("bmp[%s]: failed to create socket",
1636 ba->hostname);
1637 continue;
1638 }
c258527b 1639
ed18356f
DL
1640 set_nonblocking(ba->socket);
1641 res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos],
1642 htons(ba->port), 0);
1643 switch (res) {
1644 case connect_error:
1645 sockunion2str(&ba->addrs[ba->addrpos], buf,
1646 sizeof(buf));
1647 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1648 ba->hostname, buf, ba->port);
1649 close(ba->socket);
1650 ba->socket = -1;
1651 continue;
1652 case connect_success:
1653 break;
1654 case connect_in_progress:
1655 bmp_active_setup(ba);
1656 return;
1657 }
1658 }
1659
1660 /* exhausted all addresses */
1661 ba->curretry += ba->curretry / 2;
1662 bmp_active_setup(ba);
1663}
1664
1665static void bmp_active_resolved(struct resolver_query *resq, int numaddrs,
1666 union sockunion *addr)
1667{
1668 struct bmp_active *ba = container_of(resq, struct bmp_active, resq);
1669 unsigned i;
1670
1671 if (numaddrs <= 0) {
125dc952
DL
1672 zlog_warn("bmp[%s]: hostname resolution failed", ba->hostname);
1673 ba->curretry += ba->curretry / 2;
a3d04c32 1674 ba->addrpos = 0;
125dc952
DL
1675 ba->addrtotal = 0;
1676 bmp_active_setup(ba);
1677 return;
a3d04c32 1678 }
ed18356f 1679
125dc952
DL
1680 if (numaddrs > (int)array_size(ba->addrs))
1681 numaddrs = array_size(ba->addrs);
1682
1683 ba->addrpos = 0;
1684 ba->addrtotal = numaddrs;
1685 for (i = 0; i < ba->addrtotal; i++)
1686 memcpy(&ba->addrs[i], &addr[i], sizeof(ba->addrs[0]));
1687
ed18356f
DL
1688 bmp_active_connect(ba);
1689}
1690
1691static int bmp_active_thread(struct thread *t)
1692{
1693 struct bmp_active *ba = THREAD_ARG(t);
1694 socklen_t slen;
1695 int status, ret;
1696 char buf[SU_ADDRSTRLEN];
1697
1698 /* all 3 end up here, though only timer or read+write are active
1699 * at a time */
1700 THREAD_OFF(ba->t_timer);
1701 THREAD_OFF(ba->t_read);
1702 THREAD_OFF(ba->t_write);
1703
1704 if (ba->socket == -1) {
1705 resolver_resolve(&ba->resq, AF_UNSPEC, ba->hostname,
1706 bmp_active_resolved);
1707 return 0;
1708 }
1709
1710 slen = sizeof(status);
1711 ret = getsockopt(ba->socket, SOL_SOCKET, SO_ERROR, (void *)&status,
1712 &slen);
1713
1714 sockunion2str(&ba->addrs[ba->addrpos], buf, sizeof(buf));
1715 if (ret < 0 || status != 0) {
1716 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1717 ba->hostname, buf, ba->port);
1718 goto out_next;
1719 }
1720
1721 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1722 ba->hostname, buf, ba->port);
1723
1724 ba->bmp = bmp_open(ba->targets, ba->socket);
1725 if (!ba->bmp)
1726 goto out_next;
1727
1728 ba->bmp->active = ba;
1729 ba->socket = -1;
1730 ba->curretry = ba->minretry;
1731 return 0;
1732
1733out_next:
1734 close(ba->socket);
1735 ba->socket = -1;
1736 ba->addrpos++;
1737 bmp_active_connect(ba);
1738 return 0;
1739}
1740
1741static void bmp_active_disconnected(struct bmp_active *ba)
1742{
1743 ba->bmp = NULL;
1744 bmp_active_setup(ba);
1745}
1746
1747static void bmp_active_setup(struct bmp_active *ba)
1748{
1749 THREAD_OFF(ba->t_timer);
1750 THREAD_OFF(ba->t_read);
1751 THREAD_OFF(ba->t_write);
1752
1753 if (ba->bmp)
1754 return;
1755 if (ba->resq.callback)
1756 return;
1757
1758 if (ba->curretry > ba->maxretry)
1759 ba->curretry = ba->maxretry;
1760
1761 if (ba->socket == -1)
1762 thread_add_timer_msec(bm->master, bmp_active_thread, ba,
1763 ba->curretry, &ba->t_timer);
1764 else {
1765 thread_add_read(bm->master, bmp_active_thread, ba, ba->socket,
1766 &ba->t_read);
1767 thread_add_write(bm->master, bmp_active_thread, ba, ba->socket,
1768 &ba->t_write);
1769 }
1770}
1771
1772static struct cmd_node bmp_node = {BMP_NODE, "%s(config-bgp-bmp)# "};
1773
1774#define BMP_STR "BGP Monitoring Protocol\n"
1775
1776#ifndef VTYSH_EXTRACT_PL
33a9e196 1777#include "bgpd/bgp_bmp_clippy.c"
ed18356f
DL
1778#endif
1779
1780DEFPY_NOSH(bmp_targets_main,
1781 bmp_targets_cmd,
1782 "bmp targets BMPTARGETS",
1783 BMP_STR
1784 "Create BMP target group\n"
1785 "Name of the BMP target group\n")
1786{
1787 VTY_DECLVAR_CONTEXT(bgp, bgp);
1788 struct bmp_targets *bt;
1789
1790 bt = bmp_targets_get(bgp, bmptargets);
1791
1792 VTY_PUSH_CONTEXT_SUB(BMP_NODE, bt);
1793 return CMD_SUCCESS;
1794}
1795
1796DEFPY(no_bmp_targets_main,
1797 no_bmp_targets_cmd,
1798 "no bmp targets BMPTARGETS",
1799 NO_STR
1800 BMP_STR
1801 "Delete BMP target group\n"
1802 "Name of the BMP target group\n")
1803{
1804 VTY_DECLVAR_CONTEXT(bgp, bgp);
1805 struct bmp_targets *bt;
1806
1807 bt = bmp_targets_find1(bgp, bmptargets);
1808 if (!bt) {
1809 vty_out(vty, "%% BMP target group not found\n");
1810 return CMD_WARNING;
1811 }
1812 bmp_targets_put(bt);
1813 return CMD_SUCCESS;
1814}
1815
1816DEFPY(bmp_listener_main,
1817 bmp_listener_cmd,
1818 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1819 BMP_STR
1820 "Listen for inbound BMP connections\n"
1821 "IPv6 address to listen on\n"
1822 "IPv4 address to listen on\n"
1823 "TCP Port number\n"
1824 "TCP Port number\n")
1825{
1826 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1827 struct bmp_listener *bl;
1828
1829 bl = bmp_listener_get(bt, listener, port);
1830 if (bl->sock == -1)
1831 bmp_listener_start(bl);
1832
1833 return CMD_SUCCESS;
1834}
1835
1836DEFPY(no_bmp_listener_main,
1837 no_bmp_listener_cmd,
1838 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1839 NO_STR
1840 BMP_STR
1841 "Create BMP listener\n"
1842 "IPv6 address to listen on\n"
1843 "IPv4 address to listen on\n"
1844 "TCP Port number\n"
1845 "TCP Port number\n")
1846{
1847 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1848 struct bmp_listener *bl;
1849
1850 bl = bmp_listener_find(bt, listener, port);
1851 if (!bl) {
1852 vty_out(vty, "%% BMP listener not found\n");
1853 return CMD_WARNING;
1854 }
1855 bmp_listener_stop(bl);
1856 bmp_listener_put(bl);
1857 return CMD_SUCCESS;
1858}
1859
1860DEFPY(bmp_connect,
1861 bmp_connect_cmd,
1862 "[no] bmp connect HOSTNAME port (1-65535) "
1863 "{min-retry (100-86400000)"
1864 "|max-retry (100-86400000)}",
1865 NO_STR
1866 BMP_STR
1867 "Actively establish connection to monitoring station\n"
1868 "Monitoring station hostname or address\n"
1869 "TCP port\n"
1870 "TCP port\n"
1871 "Minimum connection retry interval\n"
1872 "Minimum connection retry interval (milliseconds)\n"
1873 "Maximum connection retry interval\n"
1874 "Maximum connection retry interval (milliseconds)\n")
1875{
1876 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1877 struct bmp_active *ba;
1878
1879 if (no) {
1880 ba = bmp_active_find(bt, hostname, port);
1881 if (!ba) {
1882 vty_out(vty, "%% No such active connection found\n");
1883 return CMD_WARNING;
1884 }
1885 bmp_active_put(ba);
1886 return CMD_SUCCESS;
1887 }
1888
1889 ba = bmp_active_get(bt, hostname, port);
1890 if (min_retry_str)
1891 ba->minretry = min_retry;
1892 if (max_retry_str)
1893 ba->maxretry = max_retry;
1894 ba->curretry = ba->minretry;
1895 bmp_active_setup(ba);
1896
1897 return CMD_SUCCESS;
1898}
1899
1900DEFPY(bmp_acl,
1901 bmp_acl_cmd,
1902 "[no] <ip|ipv6>$af access-list WORD",
1903 NO_STR
1904 IP_STR
1905 IPV6_STR
1906 "Access list to restrict BMP sessions\n"
1907 "Access list name\n")
1908{
1909 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1910 char **what;
1911
1912 if (no)
1913 access_list = NULL;
1914 if (!strcmp(af, "ipv6"))
1915 what = &bt->acl6_name;
1916 else
1917 what = &bt->acl_name;
1918
1919 XFREE(MTYPE_BMP_ACLNAME, *what);
1920 if (access_list)
1921 *what = XSTRDUP(MTYPE_BMP_ACLNAME, access_list);
1922
1923 return CMD_SUCCESS;
1924}
1925
1926DEFPY(bmp_stats_cfg,
1927 bmp_stats_cmd,
1928 "[no] bmp stats [interval (100-86400000)]",
1929 NO_STR
1930 BMP_STR
1931 "Send BMP statistics messages\n"
1932 "Specify BMP stats interval\n"
1933 "Interval (milliseconds) to send BMP Stats in\n")
1934{
1935 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1936
1937 THREAD_OFF(bt->t_stats);
1938 if (no)
1939 bt->stat_msec = 0;
1940 else if (interval_str)
1941 bt->stat_msec = interval;
1942 else
1943 bt->stat_msec = BMP_STAT_DEFAULT_TIMER;
1944
1945 if (bt->stat_msec)
1946 thread_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec,
1947 &bt->t_stats);
1948 return CMD_SUCCESS;
1949}
1950
1951DEFPY(bmp_monitor_cfg,
1952 bmp_monitor_cmd,
1953 "[no] bmp monitor "BGP_AFI_CMD_STR" <unicast|multicast> <pre-policy|post-policy>$policy",
1954 NO_STR
1955 BMP_STR
1956 "Send BMP route monitoring messages\n"
1957 BGP_AFI_HELP_STR
1958 "Address family modifier\n"
1959 "Address family modifier\n"
1960 "Send state before policy and filter processing\n"
1961 "Send state with policy and filters applied\n")
1962{
1963 int index = 0;
1964 uint8_t flag, prev;
1965 afi_t afi;
1966 safi_t safi;
1967
1968 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1969 struct bmp *bmp;
1970
1971 argv_find_and_parse_afi(argv, argc, &index, &afi);
1972 argv_find_and_parse_safi(argv, argc, &index, &safi);
1973
1974 if (policy[1] == 'r')
1975 flag = BMP_MON_PREPOLICY;
1976 else
1977 flag = BMP_MON_POSTPOLICY;
1978
1979 prev = bt->afimon[afi][safi];
1980 if (no)
1981 bt->afimon[afi][safi] &= ~flag;
1982 else
1983 bt->afimon[afi][safi] |= flag;
1984
1985 if (prev == bt->afimon[afi][safi])
1986 return CMD_SUCCESS;
1987
1988 frr_each (bmp_session, &bt->sessions, bmp) {
1989 if (bmp->syncafi == afi && bmp->syncsafi == safi) {
1990 bmp->syncafi = AFI_MAX;
1991 bmp->syncsafi = SAFI_MAX;
1992 }
1993
1994 if (!bt->afimon[afi][safi]) {
1995 bmp->afistate[afi][safi] = BMP_AFI_INACTIVE;
1996 continue;
1997 }
1998
1999 bmp->afistate[afi][safi] = BMP_AFI_NEEDSYNC;
2000 }
2001
2002 return CMD_SUCCESS;
2003}
2004
2005DEFPY(bmp_mirror_cfg,
2006 bmp_mirror_cmd,
2007 "[no] bmp mirror",
2008 NO_STR
2009 BMP_STR
2010 "Send BMP route mirroring messages\n")
2011{
2012 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2013 struct bmp *bmp;
2014
2015 if (bt->mirror == !no)
2016 return CMD_SUCCESS;
2017
2018 bt->mirror = !no;
2019 if (bt->mirror)
2020 return CMD_SUCCESS;
2021
2022 frr_each (bmp_session, &bt->sessions, bmp) {
2023 struct bmp_mirrorq *bmq;
2024
2025 while ((bmq = bmp_pull_mirror(bmp)))
2026 if (!bmq->refcount)
2027 XFREE(MTYPE_BMP_MIRRORQ, bmq);
2028 }
2029 return CMD_SUCCESS;
2030}
2031
2032DEFPY(bmp_mirror_limit_cfg,
2033 bmp_mirror_limit_cmd,
2034 "bmp mirror buffer-limit (0-4294967294)",
2035 BMP_STR
2036 "Route Mirroring settings\n"
2037 "Configure maximum memory used for buffered mirroring messages\n"
2038 "Limit in bytes\n")
2039{
2040 VTY_DECLVAR_CONTEXT(bgp, bgp);
2041 struct bmp_bgp *bmpbgp;
2042
2043 bmpbgp = bmp_bgp_get(bgp);
2044 bmpbgp->mirror_qsizelimit = buffer_limit;
2045
2046 return CMD_SUCCESS;
2047}
2048
2049DEFPY(no_bmp_mirror_limit_cfg,
2050 no_bmp_mirror_limit_cmd,
2051 "no bmp mirror buffer-limit [(0-4294967294)]",
2052 NO_STR
2053 BMP_STR
2054 "Route Mirroring settings\n"
2055 "Configure maximum memory used for buffered mirroring messages\n"
2056 "Limit in bytes\n")
2057{
2058 VTY_DECLVAR_CONTEXT(bgp, bgp);
2059 struct bmp_bgp *bmpbgp;
2060
2061 bmpbgp = bmp_bgp_get(bgp);
2062 bmpbgp->mirror_qsizelimit = ~0UL;
2063
2064 return CMD_SUCCESS;
2065}
2066
2067
2068DEFPY(show_bmp,
2069 show_bmp_cmd,
2070 "show bmp",
2071 SHOW_STR
2072 BMP_STR)
2073{
2074 struct bmp_bgp *bmpbgp;
2075 struct bmp_targets *bt;
2076 struct bmp_listener *bl;
2077 struct bmp *bmp;
2078 struct ttable *tt;
2079 char buf[SU_ADDRSTRLEN];
2080
2081 frr_each(bmp_bgph, &bmp_bgph, bmpbgp) {
2082 vty_out(vty, "BMP state for BGP %s:\n\n",
2083 bmpbgp->bgp->name_pretty);
2084 vty_out(vty, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2085 bmpbgp->mirror_qsize,
2086 bmp_mirrorq_count(&bmpbgp->mirrorq));
2087 vty_out(vty, " %9zu bytes maximum buffer used\n",
2088 bmpbgp->mirror_qsizemax);
2089 if (bmpbgp->mirror_qsizelimit != ~0UL)
2090 vty_out(vty, " %9zu bytes buffer size limit\n",
2091 bmpbgp->mirror_qsizelimit);
2092 vty_out(vty, "\n");
2093
2094 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2095 vty_out(vty, " Targets \"%s\":\n", bt->name);
2096 vty_out(vty, " Route Mirroring %sabled\n",
2097 bt->mirror ? "en" : "dis");
2098
2099 afi_t afi;
2100 safi_t safi;
2101
2102 FOREACH_AFI_SAFI (afi, safi) {
2103 const char *str = NULL;
2104
2105 switch (bt->afimon[afi][safi]) {
2106 case BMP_MON_PREPOLICY:
2107 str = "pre-policy";
2108 break;
2109 case BMP_MON_POSTPOLICY:
2110 str = "post-policy";
2111 break;
2112 case BMP_MON_PREPOLICY | BMP_MON_POSTPOLICY:
2113 str = "pre-policy and post-policy";
2114 break;
2115 }
2116 if (!str)
2117 continue;
2118 vty_out(vty, " Route Monitoring %s %s %s\n",
2119 afi2str(afi), safi2str(safi), str);
2120 }
2121
2122 vty_out(vty, " Listeners:\n");
2123 frr_each (bmp_listeners, &bt->listeners, bl)
2124 vty_out(vty, " %s:%d\n",
2125 sockunion2str(&bl->addr, buf,
2126 SU_ADDRSTRLEN), bl->port);
2127
2128 vty_out(vty, "\n %zu connected clients:\n",
2129 bmp_session_count(&bt->sessions));
2130 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2131 ttable_add_row(tt, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2132 ttable_rowseps(tt, 0, BOTTOM, true, '-');
2133
2134 frr_each (bmp_session, &bt->sessions, bmp) {
2135 uint64_t total;
9e89da8c 2136 char uptime[BGP_UPTIME_LEN];
ed18356f
DL
2137 size_t q, kq;
2138
2139 pullwr_stats(bmp->pullwr, &total, &q, &kq);
2140
9e89da8c
DL
2141 peer_uptime(bmp->t_up.tv_sec, uptime,
2142 sizeof(uptime), false, NULL);
2143
2144 ttable_add_row(tt, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2145 bmp->remote, uptime,
ed18356f
DL
2146 bmp->cnt_update,
2147 bmp->cnt_mirror,
2148 bmp->cnt_mirror_overruns,
2149 total, q, kq);
2150 }
2151 char *out = ttable_dump(tt, "\n");
2152 vty_out(vty, "%s", out);
2153 XFREE(MTYPE_TMP, out);
2154 ttable_del(tt);
2155 vty_out(vty, "\n");
2156 }
2157 }
2158
2159 return CMD_SUCCESS;
2160}
2161
2162static int bmp_config_write(struct bgp *bgp, struct vty *vty)
2163{
2164 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
2165 struct bmp_targets *bt;
2166 struct bmp_listener *bl;
2167 struct bmp_active *ba;
2168 char buf[SU_ADDRSTRLEN];
2169 afi_t afi;
2170 safi_t safi;
2171
2172 if (!bmpbgp)
2173 return 0;
2174
2175 if (bmpbgp->mirror_qsizelimit != ~0UL)
2176 vty_out(vty, " !\n bmp mirror buffer-limit %zu\n",
2177 bmpbgp->mirror_qsizelimit);
2178
2179 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2180 vty_out(vty, " !\n bmp targets %s\n", bt->name);
2181
2182 if (bt->acl6_name)
2183 vty_out(vty, " ipv6 access-list %s\n", bt->acl6_name);
2184 if (bt->acl_name)
2185 vty_out(vty, " ip access-list %s\n", bt->acl_name);
2186
2187 if (bt->stat_msec)
2188 vty_out(vty, " bmp stats interval %d\n",
2189 bt->stat_msec);
2190
2191 if (bt->mirror)
2192 vty_out(vty, " bmp mirror\n");
2193
2194 FOREACH_AFI_SAFI (afi, safi) {
2195 const char *afi_str = (afi == AFI_IP) ? "ipv4" : "ipv6";
2196
2197 if (bt->afimon[afi][safi] & BMP_MON_PREPOLICY)
2198 vty_out(vty, " bmp monitor %s %s pre-policy\n",
2199 afi_str, safi2str(safi));
2200 if (bt->afimon[afi][safi] & BMP_MON_POSTPOLICY)
2201 vty_out(vty, " bmp monitor %s %s post-policy\n",
2202 afi_str, safi2str(safi));
2203 }
2204 frr_each (bmp_listeners, &bt->listeners, bl)
2205 vty_out(vty, " \n bmp listener %s port %d\n",
2206 sockunion2str(&bl->addr, buf, SU_ADDRSTRLEN),
2207 bl->port);
2208
2209 frr_each (bmp_actives, &bt->actives, ba)
2210 vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n",
2211 ba->hostname, ba->port, ba->minretry, ba->maxretry);
2212 }
2213
2214 return 0;
2215}
2216
2217static int bgp_bmp_init(struct thread_master *tm)
2218{
2219 install_node(&bmp_node, NULL);
2220 install_default(BMP_NODE);
2221 install_element(BGP_NODE, &bmp_targets_cmd);
2222 install_element(BGP_NODE, &no_bmp_targets_cmd);
2223
2224 install_element(BMP_NODE, &bmp_listener_cmd);
2225 install_element(BMP_NODE, &no_bmp_listener_cmd);
2226 install_element(BMP_NODE, &bmp_connect_cmd);
2227 install_element(BMP_NODE, &bmp_acl_cmd);
2228 install_element(BMP_NODE, &bmp_stats_cmd);
2229 install_element(BMP_NODE, &bmp_monitor_cmd);
2230 install_element(BMP_NODE, &bmp_mirror_cmd);
2231
2232 install_element(BGP_NODE, &bmp_mirror_limit_cmd);
2233 install_element(BGP_NODE, &no_bmp_mirror_limit_cmd);
2234
2235 install_element(VIEW_NODE, &show_bmp_cmd);
2236
2237 resolver_init(tm);
0ba4eeec 2238 return 0;
6c29258c
YO
2239}
2240
0ba4eeec
DL
2241static int bgp_bmp_module_init(void)
2242{
2243 hook_register(bgp_packet_dump, bmp_mirror_packet);
ed18356f 2244 hook_register(bgp_packet_send, bmp_outgoing_packet);
df9e8ae7 2245 hook_register(peer_status_changed, bmp_peer_established);
ed18356f
DL
2246 hook_register(peer_backward_transition, bmp_peer_backward);
2247 hook_register(bgp_process, bmp_process);
2248 hook_register(bgp_inst_config_write, bmp_config_write);
2249 hook_register(bgp_inst_delete, bmp_bgp_del);
0ba4eeec
DL
2250 hook_register(frr_late_init, bgp_bmp_init);
2251 return 0;
2252}
6c29258c 2253
0ba4eeec
DL
2254FRR_MODULE_SETUP(.name = "bgpd_bmp", .version = FRR_VERSION,
2255 .description = "bgpd BMP module",
2256 .init = bgp_bmp_module_init)