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