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