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