]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_bmp.c
Merge pull request #4952 from mjstapp/fix_bgp_peer_hook
[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 setsockopt(bmp_sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
1311 setsockopt(bmp_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
1312
1313 zlog_info("bmp[%s] connection established", buf);
1314
1315 /* Allocate new BMP structure and set up default values. */
1316 bmp = bmp_new(bt, bmp_sock);
1317 strlcpy(bmp->remote, buf, sizeof(bmp->remote));
1318
1319 bmp->state = BMP_PeerUp;
1320 bmp->pullwr = pullwr_new(bm->master, bmp_sock, bmp, bmp_wrfill,
1321 bmp_wrerr);
1322 bmp_send_initiation(bmp);
1323
1324 return bmp;
1325 }
1326
1327 /* Accept BMP connection. */
1328 static int bmp_accept(struct thread *thread)
1329 {
1330 union sockunion su;
1331 struct bmp_listener *bl = THREAD_ARG(thread);
1332 int bmp_sock;
1333
1334 /* We continue hearing BMP socket. */
1335 thread_add_read(bm->master, bmp_accept, bl, bl->sock, &bl->t_accept);
1336
1337 memset(&su, 0, sizeof(union sockunion));
1338
1339 /* We can handle IPv4 or IPv6 socket. */
1340 bmp_sock = sockunion_accept(bl->sock, &su);
1341 if (bmp_sock < 0) {
1342 zlog_info("bmp: accept_sock failed: %s\n",
1343 safe_strerror (errno));
1344 return -1;
1345 }
1346 bmp_open(bl->targets, bmp_sock);
1347 return 0;
1348 }
1349
1350 static void bmp_close(struct bmp *bmp)
1351 {
1352 struct bmp_queue_entry *bqe;
1353 struct bmp_mirrorq *bmq;
1354
1355 if (bmp->active)
1356 bmp_active_disconnected(bmp->active);
1357
1358 while ((bmq = bmp_pull_mirror(bmp)))
1359 if (!bmq->refcount)
1360 XFREE(MTYPE_BMP_MIRRORQ, bmq);
1361 while ((bqe = bmp_pull(bmp)))
1362 if (!bqe->refcount)
1363 XFREE(MTYPE_BMP_QUEUE, bqe);
1364
1365 THREAD_OFF(bmp->t_read);
1366 pullwr_del(bmp->pullwr);
1367 close(bmp->socket);
1368 }
1369
1370 static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp)
1371 {
1372 struct bmp_bgp dummy = { .bgp = bgp };
1373 return bmp_bgph_find(&bmp_bgph, &dummy);
1374 }
1375
1376 static struct bmp_bgp *bmp_bgp_get(struct bgp *bgp)
1377 {
1378 struct bmp_bgp *bmpbgp;
1379
1380 bmpbgp = bmp_bgp_find(bgp);
1381 if (bmpbgp)
1382 return bmpbgp;
1383
1384 bmpbgp = XCALLOC(MTYPE_BMP, sizeof(*bmpbgp));
1385 bmpbgp->bgp = bgp;
1386 bmpbgp->mirror_qsizelimit = ~0UL;
1387 bmp_mirrorq_init(&bmpbgp->mirrorq);
1388 bmp_bgph_add(&bmp_bgph, bmpbgp);
1389
1390 return bmpbgp;
1391 }
1392
1393 static void bmp_bgp_put(struct bmp_bgp *bmpbgp)
1394 {
1395 struct bmp_targets *bt;
1396
1397 bmp_bgph_del(&bmp_bgph, bmpbgp);
1398
1399 frr_each_safe(bmp_targets, &bmpbgp->targets, bt)
1400 bmp_targets_put(bt);
1401
1402 bmp_mirrorq_fini(&bmpbgp->mirrorq);
1403 XFREE(MTYPE_BMP, bmpbgp);
1404 }
1405
1406 static int bmp_bgp_del(struct bgp *bgp)
1407 {
1408 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1409
1410 if (bmpbgp)
1411 bmp_bgp_put(bmpbgp);
1412 return 0;
1413 }
1414
1415 static struct bmp_bgp_peer *bmp_bgp_peer_find(uint64_t peerid)
1416 {
1417 struct bmp_bgp_peer dummy = { .peerid = peerid };
1418 return bmp_peerh_find(&bmp_peerh, &dummy);
1419 }
1420
1421 static struct bmp_bgp_peer *bmp_bgp_peer_get(struct peer *peer)
1422 {
1423 struct bmp_bgp_peer *bbpeer;
1424
1425 bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
1426 if (bbpeer)
1427 return bbpeer;
1428
1429 bbpeer = XCALLOC(MTYPE_BMP_PEER, sizeof(*bbpeer));
1430 bbpeer->peerid = peer->qobj_node.nid;
1431 bmp_peerh_add(&bmp_peerh, bbpeer);
1432
1433 return bbpeer;
1434 }
1435
1436 static struct bmp_targets *bmp_targets_find1(struct bgp *bgp, const char *name)
1437 {
1438 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
1439 struct bmp_targets dummy;
1440
1441 if (!bmpbgp)
1442 return NULL;
1443 dummy.name = (char *)name;
1444 return bmp_targets_find(&bmpbgp->targets, &dummy);
1445 }
1446
1447 static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
1448 {
1449 struct bmp_targets *bt;
1450
1451 bt = bmp_targets_find1(bgp, name);
1452 if (bt)
1453 return bt;
1454
1455 bt = XCALLOC(MTYPE_BMP_TARGETS, sizeof(*bt));
1456 bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name);
1457 bt->bgp = bgp;
1458 bt->bmpbgp = bmp_bgp_get(bgp);
1459 bmp_session_init(&bt->sessions);
1460 bmp_qhash_init(&bt->updhash);
1461 bmp_qlist_init(&bt->updlist);
1462 bmp_actives_init(&bt->actives);
1463 bmp_listeners_init(&bt->listeners);
1464
1465 QOBJ_REG(bt, bmp_targets);
1466 bmp_targets_add(&bt->bmpbgp->targets, bt);
1467 return bt;
1468 }
1469
1470 static void bmp_targets_put(struct bmp_targets *bt)
1471 {
1472 struct bmp *bmp;
1473 struct bmp_active *ba;
1474
1475 frr_each_safe (bmp_actives, &bt->actives, ba)
1476 bmp_active_put(ba);
1477
1478 frr_each_safe(bmp_session, &bt->sessions, bmp) {
1479 bmp_close(bmp);
1480 bmp_free(bmp);
1481 }
1482
1483 bmp_targets_del(&bt->bmpbgp->targets, bt);
1484 QOBJ_UNREG(bt);
1485
1486 bmp_listeners_fini(&bt->listeners);
1487 bmp_actives_fini(&bt->actives);
1488 bmp_qhash_fini(&bt->updhash);
1489 bmp_qlist_fini(&bt->updlist);
1490
1491 XFREE(MTYPE_BMP_ACLNAME, bt->acl_name);
1492 XFREE(MTYPE_BMP_ACLNAME, bt->acl6_name);
1493 bmp_session_fini(&bt->sessions);
1494
1495 XFREE(MTYPE_BMP_TARGETSNAME, bt->name);
1496 XFREE(MTYPE_BMP_TARGETS, bt);
1497 }
1498
1499 static struct bmp_listener *bmp_listener_find(struct bmp_targets *bt,
1500 const union sockunion *su,
1501 int port)
1502 {
1503 struct bmp_listener dummy;
1504 dummy.addr = *su;
1505 dummy.port = port;
1506 return bmp_listeners_find(&bt->listeners, &dummy);
1507 }
1508
1509 static struct bmp_listener *bmp_listener_get(struct bmp_targets *bt,
1510 const union sockunion *su,
1511 int port)
1512 {
1513 struct bmp_listener *bl = bmp_listener_find(bt, su, port);
1514
1515 if (bl)
1516 return bl;
1517
1518 bl = XCALLOC(MTYPE_BMP_LISTENER, sizeof(*bl));
1519 bl->targets = bt;
1520 bl->addr = *su;
1521 bl->port = port;
1522 bl->sock = -1;
1523
1524 bmp_listeners_add(&bt->listeners, bl);
1525 return bl;
1526 }
1527
1528 static void bmp_listener_put(struct bmp_listener *bl)
1529 {
1530 bmp_listeners_del(&bl->targets->listeners, bl);
1531 XFREE(MTYPE_BMP_LISTENER, bl);
1532 }
1533
1534 static void bmp_listener_start(struct bmp_listener *bl)
1535 {
1536 int sock, ret;
1537
1538 sock = socket(bl->addr.sa.sa_family, SOCK_STREAM, 0);
1539 if (sock < 0)
1540 return;
1541
1542 sockopt_reuseaddr(sock);
1543 sockopt_reuseport(sock);
1544 sockopt_v6only(bl->addr.sa.sa_family, sock);
1545 set_cloexec(sock);
1546
1547 ret = sockunion_bind(sock, &bl->addr, bl->port, &bl->addr);
1548 if (ret < 0)
1549 goto out_sock;
1550
1551 ret = listen(sock, 3);
1552 if (ret < 0)
1553 goto out_sock;
1554
1555 bl->sock = sock;
1556 thread_add_read(bm->master, bmp_accept, bl, sock, &bl->t_accept);
1557 return;
1558 out_sock:
1559 close(sock);
1560 }
1561
1562 static void bmp_listener_stop(struct bmp_listener *bl)
1563 {
1564 THREAD_OFF(bl->t_accept);
1565
1566 if (bl->sock != -1)
1567 close(bl->sock);
1568 bl->sock = -1;
1569 }
1570
1571 static struct bmp_active *bmp_active_find(struct bmp_targets *bt,
1572 const char *hostname, int port)
1573 {
1574 struct bmp_active dummy;
1575 dummy.hostname = (char *)hostname;
1576 dummy.port = port;
1577 return bmp_actives_find(&bt->actives, &dummy);
1578 }
1579
1580 static struct bmp_active *bmp_active_get(struct bmp_targets *bt,
1581 const char *hostname, int port)
1582 {
1583 struct bmp_active *ba;
1584
1585 ba = bmp_active_find(bt, hostname, port);
1586 if (ba)
1587 return ba;
1588
1589 ba = XCALLOC(MTYPE_BMP_ACTIVE, sizeof(*ba));
1590 ba->targets = bt;
1591 ba->hostname = XSTRDUP(MTYPE_TMP, hostname);
1592 ba->port = port;
1593 ba->minretry = BMP_DFLT_MINRETRY;
1594 ba->maxretry = BMP_DFLT_MAXRETRY;
1595 ba->socket = -1;
1596
1597 bmp_actives_add(&bt->actives, ba);
1598 return ba;
1599 }
1600
1601 static void bmp_active_put(struct bmp_active *ba)
1602 {
1603 THREAD_OFF(ba->t_timer);
1604 THREAD_OFF(ba->t_read);
1605 THREAD_OFF(ba->t_write);
1606
1607 bmp_actives_del(&ba->targets->actives, ba);
1608
1609 if (ba->bmp) {
1610 ba->bmp->active = NULL;
1611 bmp_close(ba->bmp);
1612 bmp_free(ba->bmp);
1613 }
1614 if (ba->socket != -1)
1615 close(ba->socket);
1616
1617 XFREE(MTYPE_TMP, ba->hostname);
1618 XFREE(MTYPE_BMP_ACTIVE, ba);
1619 }
1620
1621 static void bmp_active_setup(struct bmp_active *ba);
1622
1623 static void bmp_active_connect(struct bmp_active *ba)
1624 {
1625 enum connect_result res;
1626 char buf[SU_ADDRSTRLEN];
1627
1628 for (; ba->addrpos < ba->addrtotal; ba->addrpos++) {
1629 ba->socket = sockunion_socket(&ba->addrs[ba->addrpos]);
1630 if (ba->socket < 0) {
1631 zlog_warn("bmp[%s]: failed to create socket",
1632 ba->hostname);
1633 continue;
1634 }
1635
1636 set_nonblocking(ba->socket);
1637 res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos],
1638 htons(ba->port), 0);
1639 switch (res) {
1640 case connect_error:
1641 sockunion2str(&ba->addrs[ba->addrpos], buf,
1642 sizeof(buf));
1643 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1644 ba->hostname, buf, ba->port);
1645 close(ba->socket);
1646 ba->socket = -1;
1647 continue;
1648 case connect_success:
1649 break;
1650 case connect_in_progress:
1651 bmp_active_setup(ba);
1652 return;
1653 }
1654 }
1655
1656 /* exhausted all addresses */
1657 ba->curretry += ba->curretry / 2;
1658 bmp_active_setup(ba);
1659 }
1660
1661 static void bmp_active_resolved(struct resolver_query *resq, int numaddrs,
1662 union sockunion *addr)
1663 {
1664 struct bmp_active *ba = container_of(resq, struct bmp_active, resq);
1665 unsigned i;
1666
1667 if (numaddrs <= 0) {
1668 zlog_warn("bmp[%s]: hostname resolution failed", ba->hostname);
1669 ba->curretry += ba->curretry / 2;
1670 bmp_active_setup(ba);
1671 return;
1672 }
1673 if (numaddrs > (int)array_size(ba->addrs))
1674 numaddrs = array_size(ba->addrs);
1675
1676 ba->addrpos = 0;
1677 ba->addrtotal = numaddrs;
1678 for (i = 0; i < ba->addrtotal; i++)
1679 memcpy(&ba->addrs[i], &addr[i], sizeof(ba->addrs[0]));
1680
1681 bmp_active_connect(ba);
1682 }
1683
1684 static int bmp_active_thread(struct thread *t)
1685 {
1686 struct bmp_active *ba = THREAD_ARG(t);
1687 socklen_t slen;
1688 int status, ret;
1689 char buf[SU_ADDRSTRLEN];
1690
1691 /* all 3 end up here, though only timer or read+write are active
1692 * at a time */
1693 THREAD_OFF(ba->t_timer);
1694 THREAD_OFF(ba->t_read);
1695 THREAD_OFF(ba->t_write);
1696
1697 if (ba->socket == -1) {
1698 resolver_resolve(&ba->resq, AF_UNSPEC, ba->hostname,
1699 bmp_active_resolved);
1700 return 0;
1701 }
1702
1703 slen = sizeof(status);
1704 ret = getsockopt(ba->socket, SOL_SOCKET, SO_ERROR, (void *)&status,
1705 &slen);
1706
1707 sockunion2str(&ba->addrs[ba->addrpos], buf, sizeof(buf));
1708 if (ret < 0 || status != 0) {
1709 zlog_warn("bmp[%s]: failed to connect to %s:%d",
1710 ba->hostname, buf, ba->port);
1711 goto out_next;
1712 }
1713
1714 zlog_warn("bmp[%s]: outbound connection to %s:%d",
1715 ba->hostname, buf, ba->port);
1716
1717 ba->bmp = bmp_open(ba->targets, ba->socket);
1718 if (!ba->bmp)
1719 goto out_next;
1720
1721 ba->bmp->active = ba;
1722 ba->socket = -1;
1723 ba->curretry = ba->minretry;
1724 return 0;
1725
1726 out_next:
1727 close(ba->socket);
1728 ba->socket = -1;
1729 ba->addrpos++;
1730 bmp_active_connect(ba);
1731 return 0;
1732 }
1733
1734 static void bmp_active_disconnected(struct bmp_active *ba)
1735 {
1736 ba->bmp = NULL;
1737 bmp_active_setup(ba);
1738 }
1739
1740 static void bmp_active_setup(struct bmp_active *ba)
1741 {
1742 THREAD_OFF(ba->t_timer);
1743 THREAD_OFF(ba->t_read);
1744 THREAD_OFF(ba->t_write);
1745
1746 if (ba->bmp)
1747 return;
1748 if (ba->resq.callback)
1749 return;
1750
1751 if (ba->curretry > ba->maxretry)
1752 ba->curretry = ba->maxretry;
1753
1754 if (ba->socket == -1)
1755 thread_add_timer_msec(bm->master, bmp_active_thread, ba,
1756 ba->curretry, &ba->t_timer);
1757 else {
1758 thread_add_read(bm->master, bmp_active_thread, ba, ba->socket,
1759 &ba->t_read);
1760 thread_add_write(bm->master, bmp_active_thread, ba, ba->socket,
1761 &ba->t_write);
1762 }
1763 }
1764
1765 static struct cmd_node bmp_node = {BMP_NODE, "%s(config-bgp-bmp)# "};
1766
1767 #define BMP_STR "BGP Monitoring Protocol\n"
1768
1769 #ifndef VTYSH_EXTRACT_PL
1770 #include "bgp_bmp_clippy.c"
1771 #endif
1772
1773 DEFPY_NOSH(bmp_targets_main,
1774 bmp_targets_cmd,
1775 "bmp targets BMPTARGETS",
1776 BMP_STR
1777 "Create BMP target group\n"
1778 "Name of the BMP target group\n")
1779 {
1780 VTY_DECLVAR_CONTEXT(bgp, bgp);
1781 struct bmp_targets *bt;
1782
1783 bt = bmp_targets_get(bgp, bmptargets);
1784
1785 VTY_PUSH_CONTEXT_SUB(BMP_NODE, bt);
1786 return CMD_SUCCESS;
1787 }
1788
1789 DEFPY(no_bmp_targets_main,
1790 no_bmp_targets_cmd,
1791 "no bmp targets BMPTARGETS",
1792 NO_STR
1793 BMP_STR
1794 "Delete BMP target group\n"
1795 "Name of the BMP target group\n")
1796 {
1797 VTY_DECLVAR_CONTEXT(bgp, bgp);
1798 struct bmp_targets *bt;
1799
1800 bt = bmp_targets_find1(bgp, bmptargets);
1801 if (!bt) {
1802 vty_out(vty, "%% BMP target group not found\n");
1803 return CMD_WARNING;
1804 }
1805 bmp_targets_put(bt);
1806 return CMD_SUCCESS;
1807 }
1808
1809 DEFPY(bmp_listener_main,
1810 bmp_listener_cmd,
1811 "bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1812 BMP_STR
1813 "Listen for inbound BMP connections\n"
1814 "IPv6 address to listen on\n"
1815 "IPv4 address to listen on\n"
1816 "TCP Port number\n"
1817 "TCP Port number\n")
1818 {
1819 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1820 struct bmp_listener *bl;
1821
1822 bl = bmp_listener_get(bt, listener, port);
1823 if (bl->sock == -1)
1824 bmp_listener_start(bl);
1825
1826 return CMD_SUCCESS;
1827 }
1828
1829 DEFPY(no_bmp_listener_main,
1830 no_bmp_listener_cmd,
1831 "no bmp listener <X:X::X:X|A.B.C.D> port (1-65535)",
1832 NO_STR
1833 BMP_STR
1834 "Create BMP listener\n"
1835 "IPv6 address to listen on\n"
1836 "IPv4 address to listen on\n"
1837 "TCP Port number\n"
1838 "TCP Port number\n")
1839 {
1840 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1841 struct bmp_listener *bl;
1842
1843 bl = bmp_listener_find(bt, listener, port);
1844 if (!bl) {
1845 vty_out(vty, "%% BMP listener not found\n");
1846 return CMD_WARNING;
1847 }
1848 bmp_listener_stop(bl);
1849 bmp_listener_put(bl);
1850 return CMD_SUCCESS;
1851 }
1852
1853 DEFPY(bmp_connect,
1854 bmp_connect_cmd,
1855 "[no] bmp connect HOSTNAME port (1-65535) "
1856 "{min-retry (100-86400000)"
1857 "|max-retry (100-86400000)}",
1858 NO_STR
1859 BMP_STR
1860 "Actively establish connection to monitoring station\n"
1861 "Monitoring station hostname or address\n"
1862 "TCP port\n"
1863 "TCP port\n"
1864 "Minimum connection retry interval\n"
1865 "Minimum connection retry interval (milliseconds)\n"
1866 "Maximum connection retry interval\n"
1867 "Maximum connection retry interval (milliseconds)\n")
1868 {
1869 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1870 struct bmp_active *ba;
1871
1872 if (no) {
1873 ba = bmp_active_find(bt, hostname, port);
1874 if (!ba) {
1875 vty_out(vty, "%% No such active connection found\n");
1876 return CMD_WARNING;
1877 }
1878 bmp_active_put(ba);
1879 return CMD_SUCCESS;
1880 }
1881
1882 ba = bmp_active_get(bt, hostname, port);
1883 if (min_retry_str)
1884 ba->minretry = min_retry;
1885 if (max_retry_str)
1886 ba->maxretry = max_retry;
1887 ba->curretry = ba->minretry;
1888 bmp_active_setup(ba);
1889
1890 return CMD_SUCCESS;
1891 }
1892
1893 DEFPY(bmp_acl,
1894 bmp_acl_cmd,
1895 "[no] <ip|ipv6>$af access-list WORD",
1896 NO_STR
1897 IP_STR
1898 IPV6_STR
1899 "Access list to restrict BMP sessions\n"
1900 "Access list name\n")
1901 {
1902 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1903 char **what;
1904
1905 if (no)
1906 access_list = NULL;
1907 if (!strcmp(af, "ipv6"))
1908 what = &bt->acl6_name;
1909 else
1910 what = &bt->acl_name;
1911
1912 XFREE(MTYPE_BMP_ACLNAME, *what);
1913 if (access_list)
1914 *what = XSTRDUP(MTYPE_BMP_ACLNAME, access_list);
1915
1916 return CMD_SUCCESS;
1917 }
1918
1919 DEFPY(bmp_stats_cfg,
1920 bmp_stats_cmd,
1921 "[no] bmp stats [interval (100-86400000)]",
1922 NO_STR
1923 BMP_STR
1924 "Send BMP statistics messages\n"
1925 "Specify BMP stats interval\n"
1926 "Interval (milliseconds) to send BMP Stats in\n")
1927 {
1928 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1929
1930 THREAD_OFF(bt->t_stats);
1931 if (no)
1932 bt->stat_msec = 0;
1933 else if (interval_str)
1934 bt->stat_msec = interval;
1935 else
1936 bt->stat_msec = BMP_STAT_DEFAULT_TIMER;
1937
1938 if (bt->stat_msec)
1939 thread_add_timer_msec(bm->master, bmp_stats, bt, bt->stat_msec,
1940 &bt->t_stats);
1941 return CMD_SUCCESS;
1942 }
1943
1944 DEFPY(bmp_monitor_cfg,
1945 bmp_monitor_cmd,
1946 "[no] bmp monitor "BGP_AFI_CMD_STR" <unicast|multicast> <pre-policy|post-policy>$policy",
1947 NO_STR
1948 BMP_STR
1949 "Send BMP route monitoring messages\n"
1950 BGP_AFI_HELP_STR
1951 "Address family modifier\n"
1952 "Address family modifier\n"
1953 "Send state before policy and filter processing\n"
1954 "Send state with policy and filters applied\n")
1955 {
1956 int index = 0;
1957 uint8_t flag, prev;
1958 afi_t afi;
1959 safi_t safi;
1960
1961 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
1962 struct bmp *bmp;
1963
1964 argv_find_and_parse_afi(argv, argc, &index, &afi);
1965 argv_find_and_parse_safi(argv, argc, &index, &safi);
1966
1967 if (policy[1] == 'r')
1968 flag = BMP_MON_PREPOLICY;
1969 else
1970 flag = BMP_MON_POSTPOLICY;
1971
1972 prev = bt->afimon[afi][safi];
1973 if (no)
1974 bt->afimon[afi][safi] &= ~flag;
1975 else
1976 bt->afimon[afi][safi] |= flag;
1977
1978 if (prev == bt->afimon[afi][safi])
1979 return CMD_SUCCESS;
1980
1981 frr_each (bmp_session, &bt->sessions, bmp) {
1982 if (bmp->syncafi == afi && bmp->syncsafi == safi) {
1983 bmp->syncafi = AFI_MAX;
1984 bmp->syncsafi = SAFI_MAX;
1985 }
1986
1987 if (!bt->afimon[afi][safi]) {
1988 bmp->afistate[afi][safi] = BMP_AFI_INACTIVE;
1989 continue;
1990 }
1991
1992 bmp->afistate[afi][safi] = BMP_AFI_NEEDSYNC;
1993 }
1994
1995 return CMD_SUCCESS;
1996 }
1997
1998 DEFPY(bmp_mirror_cfg,
1999 bmp_mirror_cmd,
2000 "[no] bmp mirror",
2001 NO_STR
2002 BMP_STR
2003 "Send BMP route mirroring messages\n")
2004 {
2005 VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
2006 struct bmp *bmp;
2007
2008 if (bt->mirror == !no)
2009 return CMD_SUCCESS;
2010
2011 bt->mirror = !no;
2012 if (bt->mirror)
2013 return CMD_SUCCESS;
2014
2015 frr_each (bmp_session, &bt->sessions, bmp) {
2016 struct bmp_mirrorq *bmq;
2017
2018 while ((bmq = bmp_pull_mirror(bmp)))
2019 if (!bmq->refcount)
2020 XFREE(MTYPE_BMP_MIRRORQ, bmq);
2021 }
2022 return CMD_SUCCESS;
2023 }
2024
2025 DEFPY(bmp_mirror_limit_cfg,
2026 bmp_mirror_limit_cmd,
2027 "bmp mirror buffer-limit (0-4294967294)",
2028 BMP_STR
2029 "Route Mirroring settings\n"
2030 "Configure maximum memory used for buffered mirroring messages\n"
2031 "Limit in bytes\n")
2032 {
2033 VTY_DECLVAR_CONTEXT(bgp, bgp);
2034 struct bmp_bgp *bmpbgp;
2035
2036 bmpbgp = bmp_bgp_get(bgp);
2037 bmpbgp->mirror_qsizelimit = buffer_limit;
2038
2039 return CMD_SUCCESS;
2040 }
2041
2042 DEFPY(no_bmp_mirror_limit_cfg,
2043 no_bmp_mirror_limit_cmd,
2044 "no bmp mirror buffer-limit [(0-4294967294)]",
2045 NO_STR
2046 BMP_STR
2047 "Route Mirroring settings\n"
2048 "Configure maximum memory used for buffered mirroring messages\n"
2049 "Limit in bytes\n")
2050 {
2051 VTY_DECLVAR_CONTEXT(bgp, bgp);
2052 struct bmp_bgp *bmpbgp;
2053
2054 bmpbgp = bmp_bgp_get(bgp);
2055 bmpbgp->mirror_qsizelimit = ~0UL;
2056
2057 return CMD_SUCCESS;
2058 }
2059
2060
2061 DEFPY(show_bmp,
2062 show_bmp_cmd,
2063 "show bmp",
2064 SHOW_STR
2065 BMP_STR)
2066 {
2067 struct bmp_bgp *bmpbgp;
2068 struct bmp_targets *bt;
2069 struct bmp_listener *bl;
2070 struct bmp *bmp;
2071 struct ttable *tt;
2072 char buf[SU_ADDRSTRLEN];
2073
2074 frr_each(bmp_bgph, &bmp_bgph, bmpbgp) {
2075 vty_out(vty, "BMP state for BGP %s:\n\n",
2076 bmpbgp->bgp->name_pretty);
2077 vty_out(vty, " Route Mirroring %9zu bytes (%zu messages) pending\n",
2078 bmpbgp->mirror_qsize,
2079 bmp_mirrorq_count(&bmpbgp->mirrorq));
2080 vty_out(vty, " %9zu bytes maximum buffer used\n",
2081 bmpbgp->mirror_qsizemax);
2082 if (bmpbgp->mirror_qsizelimit != ~0UL)
2083 vty_out(vty, " %9zu bytes buffer size limit\n",
2084 bmpbgp->mirror_qsizelimit);
2085 vty_out(vty, "\n");
2086
2087 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2088 vty_out(vty, " Targets \"%s\":\n", bt->name);
2089 vty_out(vty, " Route Mirroring %sabled\n",
2090 bt->mirror ? "en" : "dis");
2091
2092 afi_t afi;
2093 safi_t safi;
2094
2095 FOREACH_AFI_SAFI (afi, safi) {
2096 const char *str = NULL;
2097
2098 switch (bt->afimon[afi][safi]) {
2099 case BMP_MON_PREPOLICY:
2100 str = "pre-policy";
2101 break;
2102 case BMP_MON_POSTPOLICY:
2103 str = "post-policy";
2104 break;
2105 case BMP_MON_PREPOLICY | BMP_MON_POSTPOLICY:
2106 str = "pre-policy and post-policy";
2107 break;
2108 }
2109 if (!str)
2110 continue;
2111 vty_out(vty, " Route Monitoring %s %s %s\n",
2112 afi2str(afi), safi2str(safi), str);
2113 }
2114
2115 vty_out(vty, " Listeners:\n");
2116 frr_each (bmp_listeners, &bt->listeners, bl)
2117 vty_out(vty, " %s:%d\n",
2118 sockunion2str(&bl->addr, buf,
2119 SU_ADDRSTRLEN), bl->port);
2120
2121 vty_out(vty, "\n %zu connected clients:\n",
2122 bmp_session_count(&bt->sessions));
2123 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2124 ttable_add_row(tt, "remote|uptime|MonSent|MirrSent|MirrLost|ByteSent|ByteQ|ByteQKernel");
2125 ttable_rowseps(tt, 0, BOTTOM, true, '-');
2126
2127 frr_each (bmp_session, &bt->sessions, bmp) {
2128 uint64_t total;
2129 size_t q, kq;
2130
2131 pullwr_stats(bmp->pullwr, &total, &q, &kq);
2132
2133 ttable_add_row(tt, "%s|-|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
2134 bmp->remote,
2135 bmp->cnt_update,
2136 bmp->cnt_mirror,
2137 bmp->cnt_mirror_overruns,
2138 total, q, kq);
2139 }
2140 char *out = ttable_dump(tt, "\n");
2141 vty_out(vty, "%s", out);
2142 XFREE(MTYPE_TMP, out);
2143 ttable_del(tt);
2144 vty_out(vty, "\n");
2145 }
2146 }
2147
2148 return CMD_SUCCESS;
2149 }
2150
2151 static int bmp_config_write(struct bgp *bgp, struct vty *vty)
2152 {
2153 struct bmp_bgp *bmpbgp = bmp_bgp_find(bgp);
2154 struct bmp_targets *bt;
2155 struct bmp_listener *bl;
2156 struct bmp_active *ba;
2157 char buf[SU_ADDRSTRLEN];
2158 afi_t afi;
2159 safi_t safi;
2160
2161 if (!bmpbgp)
2162 return 0;
2163
2164 if (bmpbgp->mirror_qsizelimit != ~0UL)
2165 vty_out(vty, " !\n bmp mirror buffer-limit %zu\n",
2166 bmpbgp->mirror_qsizelimit);
2167
2168 frr_each(bmp_targets, &bmpbgp->targets, bt) {
2169 vty_out(vty, " !\n bmp targets %s\n", bt->name);
2170
2171 if (bt->acl6_name)
2172 vty_out(vty, " ipv6 access-list %s\n", bt->acl6_name);
2173 if (bt->acl_name)
2174 vty_out(vty, " ip access-list %s\n", bt->acl_name);
2175
2176 if (bt->stat_msec)
2177 vty_out(vty, " bmp stats interval %d\n",
2178 bt->stat_msec);
2179
2180 if (bt->mirror)
2181 vty_out(vty, " bmp mirror\n");
2182
2183 FOREACH_AFI_SAFI (afi, safi) {
2184 const char *afi_str = (afi == AFI_IP) ? "ipv4" : "ipv6";
2185
2186 if (bt->afimon[afi][safi] & BMP_MON_PREPOLICY)
2187 vty_out(vty, " bmp monitor %s %s pre-policy\n",
2188 afi_str, safi2str(safi));
2189 if (bt->afimon[afi][safi] & BMP_MON_POSTPOLICY)
2190 vty_out(vty, " bmp monitor %s %s post-policy\n",
2191 afi_str, safi2str(safi));
2192 }
2193 frr_each (bmp_listeners, &bt->listeners, bl)
2194 vty_out(vty, " \n bmp listener %s port %d\n",
2195 sockunion2str(&bl->addr, buf, SU_ADDRSTRLEN),
2196 bl->port);
2197
2198 frr_each (bmp_actives, &bt->actives, ba)
2199 vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n",
2200 ba->hostname, ba->port, ba->minretry, ba->maxretry);
2201 }
2202
2203 return 0;
2204 }
2205
2206 static int bgp_bmp_init(struct thread_master *tm)
2207 {
2208 install_node(&bmp_node, NULL);
2209 install_default(BMP_NODE);
2210 install_element(BGP_NODE, &bmp_targets_cmd);
2211 install_element(BGP_NODE, &no_bmp_targets_cmd);
2212
2213 install_element(BMP_NODE, &bmp_listener_cmd);
2214 install_element(BMP_NODE, &no_bmp_listener_cmd);
2215 install_element(BMP_NODE, &bmp_connect_cmd);
2216 install_element(BMP_NODE, &bmp_acl_cmd);
2217 install_element(BMP_NODE, &bmp_stats_cmd);
2218 install_element(BMP_NODE, &bmp_monitor_cmd);
2219 install_element(BMP_NODE, &bmp_mirror_cmd);
2220
2221 install_element(BGP_NODE, &bmp_mirror_limit_cmd);
2222 install_element(BGP_NODE, &no_bmp_mirror_limit_cmd);
2223
2224 install_element(VIEW_NODE, &show_bmp_cmd);
2225
2226 resolver_init(tm);
2227 return 0;
2228 }
2229
2230 static int bgp_bmp_module_init(void)
2231 {
2232 hook_register(bgp_packet_dump, bmp_mirror_packet);
2233 hook_register(bgp_packet_send, bmp_outgoing_packet);
2234 hook_register(peer_status_changed, bmp_peer_established);
2235 hook_register(peer_backward_transition, bmp_peer_backward);
2236 hook_register(bgp_process, bmp_process);
2237 hook_register(bgp_inst_config_write, bmp_config_write);
2238 hook_register(bgp_inst_delete, bmp_bgp_del);
2239 hook_register(frr_late_init, bgp_bmp_init);
2240 return 0;
2241 }
2242
2243 FRR_MODULE_SETUP(.name = "bgpd_bmp", .version = FRR_VERSION,
2244 .description = "bgpd BMP module",
2245 .init = bgp_bmp_module_init)