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