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