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