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