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