]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/rfapi_vty.c
bgpd: Fix for large AS paths which are split into segments
[mirror_frr.git] / bgpd / rfapi / rfapi_vty.c
1 /*
2 *
3 * Copyright 2009-2016, LabN Consulting, L.L.C.
4 *
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #include <errno.h>
23
24 #include "lib/zebra.h"
25 #include "lib/prefix.h"
26 #include "lib/agg_table.h"
27 #include "lib/vty.h"
28 #include "lib/memory.h"
29 #include "lib/routemap.h"
30 #include "lib/log.h"
31 #include "lib/log_int.h"
32 #include "lib/linklist.h"
33 #include "lib/command.h"
34
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_ecommunity.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_mplsvpn.h"
40
41 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
42 #include "bgpd/rfapi/rfapi.h"
43 #include "bgpd/rfapi/rfapi_backend.h"
44
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_community.h"
48 #include "bgpd/bgp_vnc_types.h"
49 #include "bgpd/bgp_label.h"
50
51 #include "bgpd/rfapi/rfapi_import.h"
52 #include "bgpd/rfapi/rfapi_private.h"
53 #include "bgpd/rfapi/rfapi_monitor.h"
54 #include "bgpd/rfapi/rfapi_rib.h"
55 #include "bgpd/rfapi/rfapi_vty.h"
56 #include "bgpd/rfapi/rfapi_ap.h"
57 #include "bgpd/rfapi/rfapi_encap_tlv.h"
58 #include "bgpd/rfapi/vnc_debug.h"
59
60 #define DEBUG_L2_EXTRA 0
61 #define DEBUG_SHOW_EXTRA 0
62
63 #define VNC_SHOW_STR "VNC information\n"
64
65 /* format related utilies */
66
67
68 #define FMT_MIN 60 /* seconds */
69 #define FMT_HOUR (60 * FMT_MIN)
70 #define FMT_DAY (24 * FMT_HOUR)
71 #define FMT_YEAR (365 * FMT_DAY)
72
73 char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len)
74 {
75 int year, day, hour, min;
76
77 if (seconds >= FMT_YEAR) {
78 year = seconds / FMT_YEAR;
79 seconds -= year * FMT_YEAR;
80 } else
81 year = 0;
82
83 if (seconds >= FMT_DAY) {
84 day = seconds / FMT_DAY;
85 seconds -= day * FMT_DAY;
86 } else
87 day = 0;
88
89 if (seconds >= FMT_HOUR) {
90 hour = seconds / FMT_HOUR;
91 seconds -= hour * FMT_HOUR;
92 } else
93 hour = 0;
94
95 if (seconds >= FMT_MIN) {
96 min = seconds / FMT_MIN;
97 seconds -= min * FMT_MIN;
98 } else
99 min = 0;
100
101 if (year > 0) {
102 snprintf(buf, len, "%dy%dd%dh", year, day, hour);
103 } else if (day > 0) {
104 snprintf(buf, len, "%dd%dh%dm", day, hour, min);
105 } else {
106 snprintf(buf, len, "%02d:%02d:%02d", hour, min, seconds);
107 }
108
109 return buf;
110 }
111
112 char *rfapiFormatAge(time_t age, char *buf, size_t len)
113 {
114 time_t now, age_adjusted;
115
116 now = rfapi_time(NULL);
117 age_adjusted = now - age;
118
119 return rfapiFormatSeconds(age_adjusted, buf, len);
120 }
121
122
123 /*
124 * Reimplementation of quagga/lib/prefix.c function, but
125 * for RFAPI-style prefixes
126 */
127 void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix)
128 {
129 uint8_t *pnt;
130 int index;
131 int offset;
132
133 static uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
134 0xf8, 0xfc, 0xfe, 0xff};
135
136 switch (rprefix->prefix.addr_family) {
137 case AF_INET:
138 index = rprefix->length / 8;
139 if (index < 4) {
140 pnt = (uint8_t *)&rprefix->prefix.addr.v4;
141 offset = rprefix->length % 8;
142 pnt[index] &= maskbit[offset];
143 index++;
144 while (index < 4)
145 pnt[index++] = 0;
146 }
147 break;
148
149 case AF_INET6:
150 index = rprefix->length / 8;
151 if (index < 16) {
152 pnt = (uint8_t *)&rprefix->prefix.addr.v6;
153 offset = rprefix->length % 8;
154 pnt[index] &= maskbit[offset];
155 index++;
156 while (index < 16)
157 pnt[index++] = 0;
158 }
159 break;
160
161 default:
162 assert(0);
163 }
164 }
165
166 /*
167 * translate a quagga prefix into a rfapi IP address. The
168 * prefix is REQUIRED to be 32 bits for IPv4 and 128 bits for IPv6
169 *
170 * RETURNS:
171 *
172 * 0 Success
173 * <0 Error
174 */
175 int rfapiQprefix2Raddr(struct prefix *qprefix, struct rfapi_ip_addr *raddr)
176 {
177 memset(raddr, 0, sizeof(struct rfapi_ip_addr));
178 raddr->addr_family = qprefix->family;
179 switch (qprefix->family) {
180 case AF_INET:
181 if (qprefix->prefixlen != 32)
182 return -1;
183 raddr->addr.v4 = qprefix->u.prefix4;
184 break;
185 case AF_INET6:
186 if (qprefix->prefixlen != 128)
187 return -1;
188 raddr->addr.v6 = qprefix->u.prefix6;
189 break;
190 default:
191 return -1;
192 }
193 return 0;
194 }
195
196 /*
197 * Translate Quagga prefix to RFAPI prefix
198 */
199 /* rprefix->cost set to 0 */
200 void rfapiQprefix2Rprefix(struct prefix *qprefix,
201 struct rfapi_ip_prefix *rprefix)
202 {
203 memset(rprefix, 0, sizeof(struct rfapi_ip_prefix));
204 rprefix->length = qprefix->prefixlen;
205 rprefix->prefix.addr_family = qprefix->family;
206 switch (qprefix->family) {
207 case AF_INET:
208 rprefix->prefix.addr.v4 = qprefix->u.prefix4;
209 break;
210 case AF_INET6:
211 rprefix->prefix.addr.v6 = qprefix->u.prefix6;
212 break;
213 default:
214 assert(0);
215 }
216 }
217
218 int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix,
219 struct prefix *qprefix)
220 {
221 memset(qprefix, 0, sizeof(struct prefix));
222 qprefix->prefixlen = rprefix->length;
223 qprefix->family = rprefix->prefix.addr_family;
224
225 switch (rprefix->prefix.addr_family) {
226 case AF_INET:
227 qprefix->u.prefix4 = rprefix->prefix.addr.v4;
228 break;
229 case AF_INET6:
230 qprefix->u.prefix6 = rprefix->prefix.addr.v6;
231 break;
232 default:
233 return EAFNOSUPPORT;
234 }
235 return 0;
236 }
237
238 /*
239 * returns 1 if prefixes have same addr family, prefix len, and address
240 * Note that host bits matter in this comparison!
241 *
242 * For paralellism with quagga/lib/prefix.c. if we need a comparison
243 * where host bits are ignored, call that function rfapiRprefixCmp.
244 */
245 int rfapiRprefixSame(struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2)
246 {
247 if (hp1->prefix.addr_family != hp2->prefix.addr_family)
248 return 0;
249 if (hp1->length != hp2->length)
250 return 0;
251 if (hp1->prefix.addr_family == AF_INET)
252 if (IPV4_ADDR_SAME(&hp1->prefix.addr.v4, &hp2->prefix.addr.v4))
253 return 1;
254 if (hp1->prefix.addr_family == AF_INET6)
255 if (IPV6_ADDR_SAME(&hp1->prefix.addr.v6, &hp2->prefix.addr.v6))
256 return 1;
257 return 0;
258 }
259
260 int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx)
261 {
262 memset(pfx, 0, sizeof(struct prefix));
263 pfx->family = hia->addr_family;
264
265 switch (hia->addr_family) {
266 case AF_INET:
267 pfx->prefixlen = 32;
268 pfx->u.prefix4 = hia->addr.v4;
269 break;
270 case AF_INET6:
271 pfx->prefixlen = 128;
272 pfx->u.prefix6 = hia->addr.v6;
273 break;
274 default:
275 return EAFNOSUPPORT;
276 }
277 return 0;
278 }
279
280 void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o, struct prefix *pfx)
281 {
282 memset(pfx, 0, sizeof(struct prefix));
283 pfx->family = AF_ETHERNET;
284 pfx->prefixlen = 48;
285 pfx->u.prefix_eth = l2o->macaddr;
286 }
287
288 char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize)
289 {
290 return prefix_mac2str(ea, buf, bufsize);
291 }
292
293 int rfapiStr2EthAddr(const char *str, struct ethaddr *ea)
294 {
295 unsigned int a[6];
296 int i;
297
298 if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3,
299 a + 4, a + 5)
300 != 6) {
301
302 return EINVAL;
303 }
304
305 for (i = 0; i < 6; ++i)
306 ea->octet[i] = a[i] & 0xff;
307
308 return 0;
309 }
310
311 const char *rfapi_ntop(int af, const void *src, char *buf, socklen_t size)
312 {
313 if (af == AF_ETHERNET) {
314 return rfapiEthAddr2Str((const struct ethaddr *)src, buf, size);
315 }
316
317 return inet_ntop(af, src, buf, size);
318 }
319
320 int rfapiDebugPrintf(void *dummy, const char *format, ...)
321 {
322 va_list args;
323 va_start(args, format);
324 vzlog(LOG_DEBUG, format, args);
325 va_end(args);
326 return 0;
327 }
328
329 static int rfapiStdioPrintf(void *stream, const char *format, ...)
330 {
331 FILE *file = NULL;
332
333 va_list args;
334 va_start(args, format);
335
336 switch ((uintptr_t)stream) {
337 case 1:
338 file = stdout;
339 break;
340 case 2:
341 file = stderr;
342 break;
343 default:
344 assert(0);
345 }
346
347 vfprintf(file, format, args);
348 va_end(args);
349 return 0;
350 }
351
352 /* Fake out for debug logging */
353 static struct vty vty_dummy_zlog;
354 static struct vty vty_dummy_stdio;
355 #define HVTYNL ((vty == &vty_dummy_zlog)? "": "\n")
356
357 static const char *str_vty_newline(struct vty *vty)
358 {
359 if (vty == &vty_dummy_zlog)
360 return "";
361 return "\n";
362 }
363
364 int rfapiStream2Vty(void *stream, /* input */
365 int (**fp)(void *, const char *, ...), /* output */
366 struct vty **vty, /* output */
367 void **outstream, /* output */
368 const char **vty_newline) /* output */
369 {
370
371 if (!stream) {
372 vty_dummy_zlog.type = VTY_SHELL; /* for VTYNL */
373 *vty = &vty_dummy_zlog;
374 *fp = (int (*)(void *, const char *, ...))rfapiDebugPrintf;
375 *outstream = NULL;
376 *vty_newline = str_vty_newline(*vty);
377 return (vzlog_test(LOG_DEBUG));
378 }
379
380 if (((uintptr_t)stream == (uintptr_t)1)
381 || ((uintptr_t)stream == (uintptr_t)2)) {
382
383 vty_dummy_stdio.type = VTY_SHELL; /* for VTYNL */
384 *vty = &vty_dummy_stdio;
385 *fp = (int (*)(void *, const char *, ...))rfapiStdioPrintf;
386 *outstream = stream;
387 *vty_newline = str_vty_newline(*vty);
388 return 1;
389 }
390
391 *vty = stream; /* VTYNL requires vty to be legit */
392 *fp = (int (*)(void *, const char *, ...))vty_out;
393 *outstream = stream;
394 *vty_newline = str_vty_newline(*vty);
395 return 1;
396 }
397
398 /* called from bgpd/bgp_vty.c'route_vty_out() */
399 void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
400 struct bgp_info *bi, safi_t safi)
401 {
402 char *s;
403 uint32_t lifetime;
404
405 /*
406 * Print, on an indented line:
407 * UN address [if VPN route and VNC UN addr subtlv]
408 * EC list
409 * VNC lifetime
410 */
411 vty_out(vty, " ");
412
413 if (safi == SAFI_MPLS_VPN) {
414 struct prefix pfx_un;
415
416 if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) {
417 char buf[BUFSIZ];
418 vty_out(vty, "UN=%s",
419 inet_ntop(pfx_un.family, pfx_un.u.val, buf,
420 BUFSIZ));
421 }
422 }
423
424 if (bi->attr && bi->attr->ecommunity) {
425 s = ecommunity_ecom2str(bi->attr->ecommunity,
426 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
427 vty_out(vty, " EC{%s}", s);
428 XFREE(MTYPE_ECOMMUNITY_STR, s);
429 }
430
431 if (bi->extra != NULL) {
432 if (bi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
433 vty_out(vty, " label=VRF2VRF");
434 else
435 vty_out(vty, " label=%u",
436 decode_label(&bi->extra->label[0]));
437 }
438
439 if (!rfapiGetVncLifetime(bi->attr, &lifetime)) {
440 vty_out(vty, " life=%d", lifetime);
441 }
442
443 vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bi->type),
444 bi->sub_type);
445
446 vty_out(vty, "%s", HVTYNL);
447 }
448
449 void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
450 {
451 int (*fp)(void *, const char *, ...);
452 struct vty *vty;
453 void *out;
454 const char *vty_newline;
455
456 char buf[BUFSIZ];
457
458 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
459 return;
460
461 fp(out, "Attr[%p]:%s", attr, HVTYNL);
462 if (!attr)
463 return;
464
465 /* IPv4 Nexthop */
466 inet_ntop(AF_INET, &attr->nexthop, buf, BUFSIZ);
467 fp(out, " nexthop=%s%s", buf, HVTYNL);
468
469 fp(out, " aspath=%p, refcnt=%d%s", attr->aspath,
470 (attr->aspath ? attr->aspath->refcnt : 0), HVTYNL);
471 fp(out, " community=%p, refcnt=%d%s", attr->community,
472 (attr->community ? attr->community->refcnt : 0), HVTYNL);
473
474 fp(out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity,
475 (attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL);
476 fp(out, " cluster=%p, refcnt=%d%s", attr->cluster,
477 (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL);
478 fp(out, " transit=%p, refcnt=%d%s", attr->transit,
479 (attr->transit ? attr->transit->refcnt : 0), HVTYNL);
480 }
481
482 /*
483 * Print BI in an Import Table
484 */
485 void rfapiPrintBi(void *stream, struct bgp_info *bi)
486 {
487 char buf[BUFSIZ];
488 char *s;
489
490 int (*fp)(void *, const char *, ...);
491 struct vty *vty;
492 void *out;
493 const char *vty_newline;
494
495 char line[BUFSIZ];
496 char *p = line;
497 int r;
498 int has_macaddr = 0;
499 struct ethaddr macaddr = {{0}};
500 struct rfapi_l2address_option l2o_buf;
501 uint8_t l2hid = 0; /* valid if has_macaddr */
502
503 #define REMAIN (BUFSIZ - (p-line))
504 #define INCP {p += (r > REMAIN)? REMAIN: r;}
505
506 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
507 return;
508
509 if (!bi)
510 return;
511
512 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra
513 && bi->extra->vnc.import.timer) {
514 struct thread *t = (struct thread *)bi->extra->vnc.import.timer;
515 r = snprintf(p, REMAIN, " [%4lu] ",
516 thread_timer_remain_second(t));
517 INCP;
518
519 } else {
520 r = snprintf(p, REMAIN, " ");
521 INCP;
522 }
523
524 if (bi->extra) {
525 /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */
526 if (decode_rd_type(bi->extra->vnc.import.rd.val)
527 == RD_TYPE_VNC_ETH) {
528 has_macaddr = 1;
529 memcpy(macaddr.octet, bi->extra->vnc.import.rd.val + 2,
530 6);
531 l2hid = bi->extra->vnc.import.rd.val[1];
532 }
533 }
534
535 /*
536 * Print these items:
537 * type/subtype
538 * nexthop address
539 * lifetime
540 * RFP option sizes (they are opaque values)
541 * extended communities (RTs)
542 */
543 if (bi->attr) {
544 uint32_t lifetime;
545 int printed_1st_gol = 0;
546 struct bgp_attr_encap_subtlv *pEncap;
547 struct prefix pfx_un;
548 int af = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len);
549
550 /* Nexthop */
551 if (af == AF_INET) {
552 r = snprintf(p, REMAIN, "%s",
553 inet_ntop(AF_INET,
554 &bi->attr->mp_nexthop_global_in,
555 buf, BUFSIZ));
556 INCP;
557 } else if (af == AF_INET6) {
558 r = snprintf(p, REMAIN, "%s",
559 inet_ntop(AF_INET6,
560 &bi->attr->mp_nexthop_global,
561 buf, BUFSIZ));
562 INCP;
563 } else {
564 r = snprintf(p, REMAIN, "?");
565 INCP;
566 }
567
568 /*
569 * VNC tunnel subtlv, if present, contains UN address
570 */
571 if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) {
572 r = snprintf(p, REMAIN, " un=%s",
573 inet_ntop(pfx_un.family, pfx_un.u.val, buf,
574 BUFSIZ));
575 INCP;
576 }
577
578 /* Lifetime */
579 if (rfapiGetVncLifetime(bi->attr, &lifetime)) {
580 r = snprintf(p, REMAIN, " nolife");
581 INCP;
582 } else {
583 if (lifetime == 0xffffffff)
584 r = snprintf(p, REMAIN, " %6s", "infini");
585 else
586 r = snprintf(p, REMAIN, " %6u", lifetime);
587 INCP;
588 }
589
590 /* RFP option lengths */
591 for (pEncap = bi->attr->vnc_subtlvs; pEncap;
592 pEncap = pEncap->next) {
593
594 if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
595 if (printed_1st_gol) {
596 r = snprintf(p, REMAIN, ",");
597 INCP;
598 } else {
599 r = snprintf(p, REMAIN,
600 " "); /* leading space */
601 INCP;
602 }
603 r = snprintf(p, REMAIN, "%d", pEncap->length);
604 INCP;
605 printed_1st_gol = 1;
606 }
607 }
608
609 /* RT list */
610 if (bi->attr->ecommunity) {
611 s = ecommunity_ecom2str(bi->attr->ecommunity,
612 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
613 r = snprintf(p, REMAIN, " %s", s);
614 INCP;
615 XFREE(MTYPE_ECOMMUNITY_STR, s);
616 }
617 }
618
619 r = snprintf(p, REMAIN, " bi@%p", bi);
620 INCP;
621
622 r = snprintf(p, REMAIN, " p@%p", bi->peer);
623 INCP;
624
625 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
626 r = snprintf(p, REMAIN, " HD=yes");
627 INCP;
628 } else {
629 r = snprintf(p, REMAIN, " HD=no");
630 INCP;
631 }
632
633 if (bi->attr) {
634
635 if (bi->attr->weight) {
636 r = snprintf(p, REMAIN, " W=%d", bi->attr->weight);
637 INCP;
638 }
639
640 if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
641 r = snprintf(p, REMAIN, " LP=%d", bi->attr->local_pref);
642 INCP;
643 } else {
644 r = snprintf(p, REMAIN, " LP=unset");
645 INCP;
646 }
647 }
648
649 r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bi->type),
650 bi->sub_type);
651 INCP;
652
653 fp(out, "%s%s", line, HVTYNL);
654
655 if (has_macaddr) {
656 fp(out, " RD HID=%d ETH=%02x:%02x:%02x:%02x:%02x:%02x%s",
657 l2hid, macaddr.octet[0], macaddr.octet[1], macaddr.octet[2],
658 macaddr.octet[3], macaddr.octet[4], macaddr.octet[5],
659 HVTYNL);
660 }
661
662 if (!rfapiGetL2o(bi->attr, &l2o_buf)) {
663 fp(out,
664 " L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s",
665 l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1],
666 l2o_buf.macaddr.octet[2], l2o_buf.macaddr.octet[3],
667 l2o_buf.macaddr.octet[4], l2o_buf.macaddr.octet[5],
668 l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id,
669 HVTYNL);
670 }
671 if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
672 char buf[BUFSIZ];
673 const char *sp;
674
675 sp = rfapi_ntop(bi->extra->vnc.import.aux_prefix.family,
676 &bi->extra->vnc.import.aux_prefix.u.prefix, buf,
677 BUFSIZ);
678 buf[BUFSIZ - 1] = 0;
679 if (sp) {
680 fp(out, " IP: %s%s", sp, HVTYNL);
681 }
682 }
683 {
684 struct rfapi_un_option *uo =
685 rfapi_encap_tlv_to_un_option(bi->attr);
686 if (uo) {
687 rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel);
688 rfapi_un_options_free(uo);
689 }
690 }
691 }
692
693 char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, int size)
694 {
695 char buf_pfx[BUFSIZ];
696 char buf_vn[BUFSIZ];
697 char buf_un[BUFSIZ];
698 int rc;
699
700 rfapiRfapiIpAddr2Str(&m->rfd->un_addr, buf_vn, BUFSIZ);
701 rfapiRfapiIpAddr2Str(&m->rfd->vn_addr, buf_un, BUFSIZ);
702
703 rc = snprintf(buf, size,
704 "m=%p, next=%p, rfd=%p(vn=%s un=%s), p=%s/%d, node=%p", m,
705 m->next, m->rfd, buf_vn, buf_un,
706 inet_ntop(m->p.family, &m->p.u.prefix, buf_pfx, BUFSIZ),
707 m->p.prefixlen, m->node);
708 buf[size - 1] = 0;
709 if (rc >= size)
710 return NULL;
711 return buf;
712 }
713
714 static void rfapiDebugPrintMonitorVpn(void *stream, struct rfapi_monitor_vpn *m)
715 {
716 char buf[BUFSIZ];
717
718 int (*fp)(void *, const char *, ...);
719 struct vty *vty;
720 void *out;
721 const char *vty_newline;
722
723 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
724 return;
725
726 rfapiMonitorVpn2Str(m, buf, BUFSIZ);
727 fp(out, " Mon %s%s", buf, HVTYNL);
728 }
729
730 static void rfapiDebugPrintMonitorEncap(void *stream,
731 struct rfapi_monitor_encap *m)
732 {
733 int (*fp)(void *, const char *, ...);
734 struct vty *vty;
735 void *out = NULL;
736 const char *vty_newline;
737
738 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
739 return;
740
741 fp(out, " Mon m=%p, next=%p, node=%p, bi=%p%s", m, m->next, m->node,
742 m->bi, HVTYNL);
743 }
744
745 void rfapiShowItNode(void *stream, struct agg_node *rn)
746 {
747 struct bgp_info *bi;
748 char buf[BUFSIZ];
749
750 int (*fp)(void *, const char *, ...);
751 struct vty *vty;
752 void *out;
753 const char *vty_newline;
754
755 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
756 return;
757
758 fp(out, "%s/%d @%p #%d%s",
759 rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
760 rn->p.prefixlen, rn, rn->lock, HVTYNL);
761
762 for (bi = rn->info; bi; bi = bi->next) {
763 rfapiPrintBi(stream, bi);
764 }
765
766 /* doesn't show montors */
767 }
768
769 void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt,
770 int isvpn)
771 {
772 struct agg_node *rn;
773 char buf[BUFSIZ];
774
775 int (*fp)(void *, const char *, ...);
776 struct vty *vty;
777 void *out;
778 const char *vty_newline;
779
780 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
781 return;
782
783 fp(out, "Import Table [%s]%s", label, HVTYNL);
784
785 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
786 struct bgp_info *bi;
787
788 if (rn->p.family == AF_ETHERNET) {
789 rfapiEthAddr2Str(&rn->p.u.prefix_eth, buf, BUFSIZ);
790 } else {
791 inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ);
792 }
793
794 fp(out, "%s/%d @%p #%d%s", buf, rn->p.prefixlen, rn,
795 rn->lock - 1, /* account for loop iterator locking */
796 HVTYNL);
797
798 for (bi = rn->info; bi; bi = bi->next) {
799 rfapiPrintBi(stream, bi);
800 }
801
802 if (isvpn) {
803 struct rfapi_monitor_vpn *m;
804 for (m = RFAPI_MONITOR_VPN(rn); m; m = m->next) {
805 rfapiDebugPrintMonitorVpn(stream, m);
806 }
807 } else {
808 struct rfapi_monitor_encap *m;
809 for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) {
810 rfapiDebugPrintMonitorEncap(stream, m);
811 }
812 }
813 }
814 }
815
816 int rfapiShowVncQueries(void *stream, struct prefix *pfx_match)
817 {
818 struct bgp *bgp;
819 struct rfapi *h;
820 struct listnode *node;
821 struct rfapi_descriptor *rfd;
822
823 int (*fp)(void *, const char *, ...);
824 struct vty *vty;
825 void *out;
826 const char *vty_newline;
827
828 int printedheader = 0;
829
830 int nves_total = 0;
831 int nves_with_queries = 0;
832 int nves_displayed = 0;
833
834 int queries_total = 0;
835 int queries_displayed = 0;
836
837 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
838 return CMD_WARNING;
839
840 bgp = bgp_get_default(); /* assume 1 instance for now */
841 if (!bgp) {
842 vty_out(vty, "No BGP instance\n");
843 return CMD_WARNING;
844 }
845
846 h = bgp->rfapi;
847 if (!h) {
848 vty_out(vty, "No RFAPI instance\n");
849 return CMD_WARNING;
850 }
851
852 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
853
854 struct agg_node *rn;
855 int printedquerier = 0;
856
857
858 ++nves_total;
859
860 if (rfd->mon
861 || (rfd->mon_eth && skiplist_count(rfd->mon_eth))) {
862 ++nves_with_queries;
863 } else {
864 continue;
865 }
866
867 /*
868 * IP Queries
869 */
870 if (rfd->mon) {
871 for (rn = agg_route_top(rfd->mon); rn;
872 rn = agg_route_next(rn)) {
873 struct rfapi_monitor_vpn *m;
874 char buf_remain[BUFSIZ];
875 char buf_pfx[BUFSIZ];
876
877 if (!rn->info)
878 continue;
879
880 m = rn->info;
881
882 ++queries_total;
883
884 if (pfx_match
885 && !prefix_match(pfx_match, &rn->p)
886 && !prefix_match(&rn->p, pfx_match))
887 continue;
888
889 ++queries_displayed;
890
891 if (!printedheader) {
892 ++printedheader;
893 fp(out, "\n");
894 fp(out, "%-15s %-15s %-15s %-10s\n",
895 "VN Address", "UN Address", "Target",
896 "Remaining");
897 }
898
899 if (!printedquerier) {
900 char buf_vn[BUFSIZ];
901 char buf_un[BUFSIZ];
902
903 rfapiRfapiIpAddr2Str(&rfd->un_addr,
904 buf_un, BUFSIZ);
905 rfapiRfapiIpAddr2Str(&rfd->vn_addr,
906 buf_vn, BUFSIZ);
907
908 fp(out, "%-15s %-15s", buf_vn, buf_un);
909 printedquerier = 1;
910
911 ++nves_displayed;
912 } else
913 fp(out, "%-15s %-15s", "", "");
914 buf_remain[0] = 0;
915 if (m->timer) {
916 rfapiFormatSeconds(
917 thread_timer_remain_second(
918 m->timer),
919 buf_remain, BUFSIZ);
920 }
921 fp(out, " %-15s %-10s\n",
922 inet_ntop(m->p.family, &m->p.u.prefix,
923 buf_pfx, BUFSIZ),
924 buf_remain);
925 }
926 }
927
928 /*
929 * Ethernet Queries
930 */
931 if (rfd->mon_eth && skiplist_count(rfd->mon_eth)) {
932
933 int rc;
934 void *cursor;
935 struct rfapi_monitor_eth *mon_eth;
936
937 for (cursor = NULL,
938 rc = skiplist_next(rfd->mon_eth, NULL,
939 (void **)&mon_eth, &cursor);
940 rc == 0;
941 rc = skiplist_next(rfd->mon_eth, NULL,
942 (void **)&mon_eth, &cursor)) {
943
944 char buf_remain[BUFSIZ];
945 char buf_pfx[BUFSIZ];
946 struct prefix pfx_mac;
947
948 ++queries_total;
949
950 vnc_zlog_debug_verbose(
951 "%s: checking rfd=%p mon_eth=%p",
952 __func__, rfd, mon_eth);
953
954 memset((void *)&pfx_mac, 0,
955 sizeof(struct prefix));
956 pfx_mac.family = AF_ETHERNET;
957 pfx_mac.prefixlen = 48;
958 pfx_mac.u.prefix_eth = mon_eth->macaddr;
959
960 if (pfx_match
961 && !prefix_match(pfx_match, &pfx_mac)
962 && !prefix_match(&pfx_mac, pfx_match))
963 continue;
964
965 ++queries_displayed;
966
967 if (!printedheader) {
968 ++printedheader;
969 fp(out, "\n");
970 fp(out,
971 "%-15s %-15s %-17s %10s %-10s\n",
972 "VN Address", "UN Address", "Target",
973 "LNI", "Remaining");
974 }
975
976 if (!printedquerier) {
977 char buf_vn[BUFSIZ];
978 char buf_un[BUFSIZ];
979
980 rfapiRfapiIpAddr2Str(&rfd->un_addr,
981 buf_un, BUFSIZ);
982 rfapiRfapiIpAddr2Str(&rfd->vn_addr,
983 buf_vn, BUFSIZ);
984
985 fp(out, "%-15s %-15s", buf_vn, buf_un);
986 printedquerier = 1;
987
988 ++nves_displayed;
989 } else
990 fp(out, "%-15s %-15s", "", "");
991 buf_remain[0] = 0;
992 if (mon_eth->timer) {
993 rfapiFormatSeconds(
994 thread_timer_remain_second(
995 mon_eth->timer),
996 buf_remain, BUFSIZ);
997 }
998 fp(out, " %-17s %10d %-10s\n",
999 rfapi_ntop(pfx_mac.family, &pfx_mac.u.prefix,
1000 buf_pfx, BUFSIZ),
1001 mon_eth->logical_net_id, buf_remain);
1002 }
1003 }
1004 }
1005
1006 if (queries_total) {
1007 fp(out, "\n");
1008 fp(out, "Displayed %d out of %d total queries\n",
1009 queries_displayed, queries_total);
1010 }
1011 return CMD_SUCCESS;
1012 }
1013
1014 static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
1015 struct agg_node *rn, struct bgp_info *bi)
1016 {
1017 int (*fp)(void *, const char *, ...);
1018 struct vty *vty;
1019 void *out;
1020 const char *vty_newline;
1021 struct prefix pfx_un;
1022 struct prefix pfx_vn;
1023 uint8_t cost;
1024 uint32_t lifetime;
1025 bgp_encap_types tun_type;
1026
1027 char buf_pfx[BUFSIZ];
1028 char buf_ntop[BUFSIZ];
1029 char buf_un[BUFSIZ];
1030 char buf_vn[BUFSIZ];
1031 char buf_lifetime[BUFSIZ];
1032 int nlines = 0;
1033
1034 if (!stream)
1035 return 0; /* for debug log, print into buf & call output once */
1036
1037 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1038 return 0;
1039
1040 /*
1041 * Prefix
1042 */
1043 buf_pfx[0] = 0;
1044 snprintf(buf_pfx, BUFSIZ, "%s/%d",
1045 rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf_ntop, BUFSIZ),
1046 rn->p.prefixlen);
1047 buf_pfx[BUFSIZ - 1] = 0;
1048 nlines++;
1049
1050 /*
1051 * UN addr
1052 */
1053 buf_un[0] = 0;
1054 if (!rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) {
1055 snprintf(buf_un, BUFSIZ, "%s",
1056 inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop,
1057 BUFSIZ));
1058 }
1059
1060 rfapiGetTunnelType(bi->attr, &tun_type);
1061 /*
1062 * VN addr
1063 */
1064 buf_vn[0] = 0;
1065 rfapiNexthop2Prefix(bi->attr, &pfx_vn);
1066 if (tun_type == BGP_ENCAP_TYPE_MPLS) {
1067 /* MPLS carries un in nrli next hop (same as vn for IP tunnels)
1068 */
1069 snprintf(buf_un, BUFSIZ, "%s",
1070 inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1071 BUFSIZ));
1072 if (bi->extra) {
1073 uint32_t l = decode_label(&bi->extra->label[0]);
1074 snprintf(buf_vn, BUFSIZ, "Label: %d", l);
1075 } else /* should never happen */
1076 {
1077 snprintf(buf_vn, BUFSIZ, "Label: N/A");
1078 }
1079 } else {
1080 snprintf(buf_vn, BUFSIZ, "%s",
1081 inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1082 BUFSIZ));
1083 }
1084 buf_vn[BUFSIZ - 1] = 0;
1085 buf_un[BUFSIZ - 1] = 0;
1086
1087 /*
1088 * Cost is encoded in local_pref as (255-cost)
1089 * See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion
1090 * back to cost.
1091 */
1092 if (bi->attr) {
1093 uint32_t local_pref;
1094 if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1095 local_pref = bi->attr->local_pref;
1096 else
1097 local_pref = 0;
1098 cost = (local_pref > 255) ? 0 : 255 - local_pref;
1099 } else {
1100 cost = 0;
1101 }
1102
1103 fp(out, "%-20s ", buf_pfx);
1104 fp(out, "%-15s ", buf_vn);
1105 fp(out, "%-15s ", buf_un);
1106 fp(out, "%-4d ", cost);
1107
1108 /* Lifetime */
1109 /* NB rfapiGetVncLifetime sets infinite value when returning !0 */
1110 if (rfapiGetVncLifetime(bi->attr, &lifetime)
1111 || (lifetime == RFAPI_INFINITE_LIFETIME)) {
1112
1113 fp(out, "%-10s ", "infinite");
1114 } else {
1115 time_t t_lifetime = lifetime;
1116 rfapiFormatSeconds(t_lifetime, buf_lifetime, BUFSIZ);
1117 fp(out, "%-10s ", buf_lifetime);
1118 }
1119
1120 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra
1121 && bi->extra->vnc.import.timer) {
1122
1123 uint32_t remaining;
1124 time_t age;
1125 char buf_age[BUFSIZ];
1126
1127 struct thread *t = (struct thread *)bi->extra->vnc.import.timer;
1128 remaining = thread_timer_remain_second(t);
1129
1130 #if RFAPI_REGISTRATIONS_REPORT_AGE
1131 /*
1132 * Calculate when the timer started. Doing so here saves
1133 * us a timestamp field in "struct bgp_info".
1134 *
1135 * See rfapi_import.c'rfapiBiStartWithdrawTimer() for the
1136 * original calculation.
1137 */
1138 age = rfapiGetHolddownFromLifetime(lifetime, factor)
1139 - remaining;
1140 #else /* report remaining time */
1141 age = remaining;
1142 #endif
1143 rfapiFormatSeconds(age, buf_age, BUFSIZ);
1144
1145 fp(out, "%-10s ", buf_age);
1146
1147 } else if (RFAPI_LOCAL_BI(bi)) {
1148
1149 char buf_age[BUFSIZ];
1150
1151 if (bi->extra && bi->extra->vnc.import.create_time) {
1152 rfapiFormatAge(bi->extra->vnc.import.create_time,
1153 buf_age, BUFSIZ);
1154 } else {
1155 buf_age[0] = '?';
1156 buf_age[1] = 0;
1157 }
1158 fp(out, "%-10s ", buf_age);
1159 }
1160 fp(out, "%s", HVTYNL);
1161
1162 if (rn->p.family == AF_ETHERNET) {
1163 /*
1164 * If there is a corresponding IP address && != VN address,
1165 * print that on the next line
1166 */
1167
1168 if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
1169 const char *sp;
1170
1171 sp = rfapi_ntop(
1172 bi->extra->vnc.import.aux_prefix.family,
1173 &bi->extra->vnc.import.aux_prefix.u.prefix,
1174 buf_ntop, BUFSIZ);
1175 buf_ntop[BUFSIZ - 1] = 0;
1176
1177 if (sp && strcmp(buf_vn, sp) != 0) {
1178 fp(out, " IP: %s", sp);
1179 if (nlines == 1)
1180 nlines++;
1181 }
1182 }
1183 }
1184 if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) {
1185 uint32_t l = decode_label(&bi->extra->label[0]);
1186 if (!MPLS_LABEL_IS_NULL(l)) {
1187 fp(out, " Label: %d", l);
1188 if (nlines == 1)
1189 nlines++;
1190 }
1191 }
1192 if (nlines > 1)
1193 fp(out, "%s", HVTYNL);
1194
1195 return 1;
1196 }
1197
1198 static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
1199 struct rfapi_import_table *it,
1200 struct prefix *prefix_only,
1201 int show_expiring, /* either/or */
1202 int show_local, int show_remote,
1203 int show_imported, /* either/or */
1204 uint32_t *pLni) /* AFI_L2VPN only */
1205 {
1206 afi_t afi;
1207 int printed_rtlist_hdr = 0;
1208
1209 int (*fp)(void *, const char *, ...);
1210 struct vty *vty;
1211 void *out;
1212 const char *vty_newline;
1213 int total = 0;
1214 int printed = 0;
1215
1216 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1217 return printed;
1218
1219 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1220
1221 struct agg_node *rn;
1222
1223 if (!it->imported_vpn[afi])
1224 continue;
1225
1226 for (rn = agg_route_top(it->imported_vpn[afi]); rn;
1227 rn = agg_route_next(rn)) {
1228
1229 struct bgp_info *bi;
1230 int count_only;
1231
1232 /* allow for wider or more narrow mask from user */
1233 if (prefix_only && !prefix_match(prefix_only, &rn->p)
1234 && !prefix_match(&rn->p, prefix_only))
1235 count_only = 1;
1236 else
1237 count_only = 0;
1238
1239 for (bi = rn->info; bi; bi = bi->next) {
1240
1241 if (!show_local && RFAPI_LOCAL_BI(bi)) {
1242
1243 /* local route from RFP */
1244 continue;
1245 }
1246
1247 if (!show_remote && !RFAPI_LOCAL_BI(bi)) {
1248
1249 /* remote route */
1250 continue;
1251 }
1252
1253 if (show_expiring
1254 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
1255 continue;
1256
1257 if (!show_expiring
1258 && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
1259 continue;
1260
1261 if (bi->type == ZEBRA_ROUTE_BGP_DIRECT
1262 || bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
1263 if (!show_imported)
1264 continue;
1265 } else {
1266 if (show_imported)
1267 continue;
1268 }
1269
1270 total++;
1271 if (count_only == 1)
1272 continue;
1273 if (!printed_rtlist_hdr) {
1274 const char *agetype = "";
1275 char *s;
1276 const char *type = "";
1277 if (show_imported) {
1278 type = "Imported";
1279 } else {
1280 if (show_expiring) {
1281 type = "Holddown";
1282 } else {
1283 if (RFAPI_LOCAL_BI(
1284 bi)) {
1285 type = "Local";
1286 } else {
1287 type = "Remote";
1288 }
1289 }
1290 }
1291
1292 s = ecommunity_ecom2str(
1293 it->rt_import_list,
1294 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1295
1296 if (pLni) {
1297 fp(out,
1298 "%s[%s] L2VPN Network 0x%x (%u) RT={%s}",
1299 HVTYNL, type, *pLni,
1300 (*pLni & 0xfff), s);
1301 } else {
1302 fp(out, "%s[%s] Prefix RT={%s}",
1303 HVTYNL, type, s);
1304 }
1305 XFREE(MTYPE_ECOMMUNITY_STR, s);
1306
1307 if (it->rfg && it->rfg->name) {
1308 fp(out, " %s \"%s\"",
1309 (it->rfg->type == RFAPI_GROUP_CFG_VRF
1310 ? "VRF"
1311 : "NVE group"),
1312 it->rfg->name);
1313 }
1314 fp(out, "%s", HVTYNL);
1315 if (show_expiring) {
1316 #if RFAPI_REGISTRATIONS_REPORT_AGE
1317 agetype = "Age";
1318 #else
1319 agetype = "Remaining";
1320 #endif
1321 } else if (show_local) {
1322 agetype = "Age";
1323 }
1324
1325 printed_rtlist_hdr = 1;
1326
1327 fp(out,
1328 "%-20s %-15s %-15s %4s %-10s %-10s%s",
1329 (pLni ? "L2 Address/IP" : "Prefix"),
1330 "VN Address", "UN Address", "Cost",
1331 "Lifetime", agetype, HVTYNL);
1332 }
1333 printed += rfapiPrintRemoteRegBi(bgp, stream,
1334 rn, bi);
1335 }
1336 }
1337 }
1338
1339 if (printed > 0) {
1340
1341 const char *type = "prefixes";
1342
1343 if (show_imported) {
1344 type = "imported prefixes";
1345 } else {
1346 if (show_expiring) {
1347 type = "prefixes in holddown";
1348 } else {
1349 if (show_local && !show_remote) {
1350 type = "locally registered prefixes";
1351 } else if (!show_local && show_remote) {
1352 type = "remotely registered prefixes";
1353 }
1354 }
1355 }
1356
1357 fp(out, "Displayed %d out of %d %s%s", printed, total, type,
1358 HVTYNL);
1359 #if DEBUG_SHOW_EXTRA
1360 fp(out, "IT table above: it=%p%s", it, HVTYNL);
1361 #endif
1362 }
1363 return printed;
1364 }
1365
1366
1367 /*
1368 * rfapiShowRemoteRegistrations
1369 *
1370 * Similar to rfapiShowImportTable() above. This function
1371 * is mean to produce the "remote" portion of the output
1372 * of "show vnc registrations".
1373 */
1374 int rfapiShowRemoteRegistrations(void *stream, struct prefix *prefix_only,
1375 int show_expiring, int show_local,
1376 int show_remote, int show_imported)
1377 {
1378 struct bgp *bgp;
1379 struct rfapi *h;
1380 struct rfapi_import_table *it;
1381 int printed = 0;
1382
1383 bgp = bgp_get_default();
1384 if (!bgp) {
1385 return printed;
1386 }
1387
1388 h = bgp->rfapi;
1389 if (!h) {
1390 return printed;
1391 }
1392
1393 for (it = h->imports; it; it = it->next) {
1394 printed += rfapiShowRemoteRegistrationsIt(
1395 bgp, stream, it, prefix_only, show_expiring, show_local,
1396 show_remote, show_imported, NULL);
1397 }
1398
1399 if (h->import_mac) {
1400 void *cursor = NULL;
1401 int rc;
1402 uintptr_t lni_as_ptr;
1403 uint32_t lni;
1404 uint32_t *pLni;
1405
1406 for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1407 (void **)&it, &cursor);
1408 !rc;
1409 rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1410 (void **)&it, &cursor)) {
1411 pLni = NULL;
1412 if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) {
1413 lni = (uint32_t)(lni_as_ptr & 0xffffffff);
1414 pLni = &lni;
1415 }
1416
1417 printed += rfapiShowRemoteRegistrationsIt(
1418 bgp, stream, it, prefix_only, show_expiring,
1419 show_local, show_remote, show_imported, pLni);
1420 }
1421 }
1422
1423 return printed;
1424 }
1425
1426 /*------------------------------------------
1427 * rfapiRfapiIpAddr2Str
1428 *
1429 * UI helper: generate string from rfapi_ip_addr
1430 *
1431 * input:
1432 * a IP v4/v6 address
1433 *
1434 * output
1435 * buf put string here
1436 * bufsize max space to write
1437 *
1438 * return value:
1439 * NULL conversion failed
1440 * non-NULL pointer to buf
1441 --------------------------------------------*/
1442 const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf,
1443 int bufsize)
1444 {
1445 const char *rc = NULL;
1446
1447 switch (a->addr_family) {
1448 case AF_INET:
1449 rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1450 break;
1451 case AF_INET6:
1452 rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1453 break;
1454 }
1455 return rc;
1456 }
1457
1458 void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a)
1459 {
1460 char buf[BUFSIZ];
1461 const char *rc = NULL;
1462
1463 int (*fp)(void *, const char *, ...);
1464 struct vty *vty;
1465 void *out = NULL;
1466 const char *vty_newline;
1467
1468 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1469 return;
1470
1471 rc = rfapiRfapiIpAddr2Str(a, buf, BUFSIZ);
1472
1473 if (rc)
1474 fp(out, "%s", buf);
1475 }
1476
1477 const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf,
1478 int bufsize)
1479 {
1480 struct rfapi_ip_addr *a = &p->prefix;
1481 const char *rc = NULL;
1482
1483 switch (a->addr_family) {
1484 case AF_INET:
1485 rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1486 break;
1487 case AF_INET6:
1488 rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1489 break;
1490 }
1491
1492 if (rc) {
1493 int alen = strlen(buf);
1494 int remaining = bufsize - alen - 1;
1495 int slen;
1496
1497 if (remaining > 0) {
1498 slen = snprintf(buf + alen, remaining, "/%u",
1499 p->length);
1500 if (slen < remaining) /* see man page for snprintf(3) */
1501 return rc;
1502 }
1503 }
1504
1505 return NULL;
1506 }
1507
1508 void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p)
1509 {
1510 char buf[BUFSIZ];
1511 const char *rc;
1512
1513 int (*fp)(void *, const char *, ...);
1514 struct vty *vty;
1515 void *out = NULL;
1516 const char *vty_newline;
1517
1518 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1519 return;
1520
1521 rc = rfapiRfapiIpPrefix2Str(p, buf, BUFSIZ);
1522
1523 if (rc)
1524 fp(out, "%s:%u", buf, p->cost);
1525 else
1526 fp(out, "?/?:?");
1527 }
1528
1529 void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd)
1530 {
1531 char buf[RD_ADDRSTRLEN];
1532
1533 prefix_rd2str(prd, buf, sizeof(buf));
1534 vty_out(vty, "%s", buf);
1535 }
1536
1537 void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
1538 safi_t safi, struct prefix *p)
1539 {
1540 afi_t afi; /* of the VN address */
1541 struct bgp_node *bn;
1542 struct bgp_info *bi;
1543 uint8_t type = ZEBRA_ROUTE_BGP;
1544 struct bgp *bgp;
1545 int printed = 0;
1546 struct prefix_rd prd0;
1547 struct prefix_rd *prd;
1548
1549 /*
1550 * Find the bgp_info in the RIB corresponding to this
1551 * prefix and rfd
1552 */
1553
1554 afi = family2afi(p->family);
1555 assert(afi == AFI_IP || afi == AFI_IP6);
1556
1557 bgp = bgp_get_default(); /* assume 1 instance for now */
1558 assert(bgp);
1559
1560 if (safi == SAFI_ENCAP) {
1561 memset(&prd0, 0, sizeof(prd0));
1562 prd0.family = AF_UNSPEC;
1563 prd0.prefixlen = 64;
1564 prd = &prd0;
1565 } else {
1566 prd = &rfd->rd;
1567 }
1568 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
1569
1570 vty_out(vty, " bn=%p%s", bn, HVTYNL);
1571
1572 for (bi = bn->info; bi; bi = bi->next) {
1573 if (bi->peer == rfd->peer && bi->type == type
1574 && bi->sub_type == BGP_ROUTE_RFP && bi->extra
1575 && bi->extra->vnc.export.rfapi_handle == (void *)rfd) {
1576
1577 rfapiPrintBi(vty, bi);
1578 printed = 1;
1579 }
1580 }
1581
1582 if (!printed) {
1583 vty_out(vty, " --?--%s", HVTYNL);
1584 return;
1585 }
1586 }
1587
1588 void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd)
1589 {
1590 /* pHD un-addr vn-addr pCB cookie rd lifetime */
1591 /* RT export list */
1592 /* RT import list */
1593 /* list of advertised prefixes */
1594 /* dump import table */
1595
1596 char *s;
1597 void *cursor;
1598 int rc;
1599 afi_t afi;
1600 struct rfapi_adb *adb;
1601 char buf[PREFIX_STRLEN];
1602
1603 vty_out(vty, "%-10p ", rfd);
1604 rfapiPrintRfapiIpAddr(vty, &rfd->un_addr);
1605 vty_out(vty, " ");
1606 rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
1607 vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
1608 rfapiPrintRd(vty, &rfd->rd);
1609 vty_out(vty, " %d", rfd->response_lifetime);
1610 vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
1611 vty_out(vty, "%s", HVTYNL);
1612
1613 vty_out(vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL);
1614
1615 /* export RT list */
1616 if (rfd->rt_export_list) {
1617 s = ecommunity_ecom2str(rfd->rt_export_list,
1618 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1619 vty_out(vty, " Export %s%s", s, HVTYNL);
1620 XFREE(MTYPE_ECOMMUNITY_STR, s);
1621 } else {
1622 vty_out(vty, " Export (nil)%s", HVTYNL);
1623 }
1624
1625 /* import RT list */
1626 if (rfd->import_table) {
1627 s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1628 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1629 vty_out(vty, " Import %s%s", s, HVTYNL);
1630 XFREE(MTYPE_ECOMMUNITY_STR, s);
1631 } else {
1632 vty_out(vty, " Import (nil)%s", HVTYNL);
1633 }
1634
1635 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1636 uint8_t family;
1637
1638 family = afi2family(afi);
1639 if (!family)
1640 continue;
1641
1642 cursor = NULL;
1643 for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1644 (void **)&adb, &cursor);
1645 rc == 0;
1646 rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1647 (void **)&adb, &cursor)) {
1648
1649 /* group like family prefixes together in output */
1650 if (family != adb->u.s.prefix_ip.family)
1651 continue;
1652
1653 prefix2str(&adb->u.s.prefix_ip, buf, sizeof(buf));
1654
1655 vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL);
1656 rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1657 &adb->u.s.prefix_ip);
1658 }
1659 }
1660 for (rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1661 (void **)&adb, &cursor);
1662 rc == 0; rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1663 (void **)&adb, &cursor)) {
1664
1665 prefix2str(&adb->u.s.prefix_eth, buf, sizeof(buf));
1666
1667 vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL);
1668
1669 /* TBD update the following function to print ethernet info */
1670 /* Also need to pass/use rd */
1671 rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1672 &adb->u.s.prefix_ip);
1673 }
1674 vty_out(vty, "%s", HVTYNL);
1675 }
1676
1677 /*
1678 * test scripts rely on first line for each nve starting in 1st column,
1679 * leading whitespace for additional detail of that nve
1680 */
1681 void rfapiPrintMatchingDescriptors(struct vty *vty, struct prefix *vn_prefix,
1682 struct prefix *un_prefix)
1683 {
1684 struct bgp *bgp;
1685 struct rfapi *h;
1686 struct listnode *ln;
1687 struct rfapi_descriptor *rfd;
1688 int printed = 0;
1689
1690 bgp = bgp_get_default(); /* assume 1 instance for now */
1691 if (!bgp)
1692 return;
1693
1694 h = bgp->rfapi;
1695 assert(h);
1696
1697 for (ln = listhead(&h->descriptors); ln; ln = listnextnode(ln)) {
1698 rfd = listgetdata(ln);
1699
1700 struct prefix pfx;
1701
1702 if (vn_prefix) {
1703 assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
1704 if (!prefix_match(vn_prefix, &pfx))
1705 continue;
1706 }
1707
1708 if (un_prefix) {
1709 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
1710 if (!prefix_match(un_prefix, &pfx))
1711 continue;
1712 }
1713
1714 if (!printed) {
1715 /* print column header */
1716 vty_out(vty, "%s %s %s %s %s %s %s %s%s", "descriptor",
1717 "un-addr", "vn-addr", "callback", "cookie",
1718 "RD", "lifetime", "group", HVTYNL);
1719 }
1720 rfapiPrintDescriptor(vty, rfd);
1721 printed = 1;
1722 }
1723 }
1724
1725
1726 /*
1727 * Parse an address and put into a struct prefix
1728 */
1729 int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, struct prefix *p)
1730 {
1731 if (!str2prefix(str, p)) {
1732 vty_out(vty, "Malformed address \"%s\"%s", str ? str : "null",
1733 HVTYNL);
1734 return CMD_WARNING;
1735 }
1736 switch (p->family) {
1737 case AF_INET:
1738 if (p->prefixlen != 32) {
1739 vty_out(vty, "Not a host address: \"%s\"%s", str,
1740 HVTYNL);
1741 return CMD_WARNING;
1742 }
1743 break;
1744 case AF_INET6:
1745 if (p->prefixlen != 128) {
1746 vty_out(vty, "Not a host address: \"%s\"%s", str,
1747 HVTYNL);
1748 return CMD_WARNING;
1749 }
1750 break;
1751 default:
1752 vty_out(vty, "Invalid address \"%s\"%s", str, HVTYNL);
1753 return CMD_WARNING;
1754 }
1755 return 0;
1756 }
1757
1758 int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str,
1759 struct rfapi_ip_addr *hai)
1760 {
1761 struct prefix pfx;
1762 int rc;
1763
1764 rc = rfapiCliGetPrefixAddr(vty, str, &pfx);
1765 if (rc)
1766 return rc;
1767
1768 hai->addr_family = pfx.family;
1769 if (pfx.family == AF_INET)
1770 hai->addr.v4 = pfx.u.prefix4;
1771 else
1772 hai->addr.v6 = pfx.u.prefix6;
1773
1774 return 0;
1775 }
1776
1777 /*
1778 * Note: this function does not flush vty output, so if it is called
1779 * with a stream pointing to a vty, the user will have to type something
1780 * before the callback output shows up
1781 */
1782 void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops)
1783 {
1784 struct rfapi_next_hop_entry *nh;
1785 int count;
1786
1787 int (*fp)(void *, const char *, ...);
1788 struct vty *vty;
1789 void *out;
1790 const char *vty_newline;
1791
1792 #define REMAIN (BUFSIZ - (p-line))
1793 #define INCP {p += (r > REMAIN)? REMAIN: r;}
1794
1795 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1796 return;
1797
1798 for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) {
1799
1800 char line[BUFSIZ];
1801 char *p = line;
1802 int r;
1803
1804 r = snprintf(p, REMAIN, "%3d pfx=", count);
1805 INCP;
1806
1807 if (rfapiRfapiIpPrefix2Str(&nh->prefix, p, REMAIN)) {
1808 /* it fit, so count length */
1809 r = strlen(p);
1810 } else {
1811 /* didn't fit */
1812 goto truncate;
1813 }
1814 INCP;
1815
1816 r = snprintf(p, REMAIN, ", un=");
1817 INCP;
1818
1819 if (rfapiRfapiIpAddr2Str(&nh->un_address, p, REMAIN)) {
1820 /* it fit, so count length */
1821 r = strlen(p);
1822 } else {
1823 /* didn't fit */
1824 goto truncate;
1825 }
1826 INCP;
1827
1828 r = snprintf(p, REMAIN, ", vn=");
1829 INCP;
1830
1831 if (rfapiRfapiIpAddr2Str(&nh->vn_address, p, REMAIN)) {
1832 /* it fit, so count length */
1833 r = strlen(p);
1834 } else {
1835 /* didn't fit */
1836 goto truncate;
1837 }
1838 INCP;
1839
1840 truncate:
1841 line[BUFSIZ - 1] = 0;
1842 fp(out, "%s%s", line, HVTYNL);
1843
1844 /*
1845 * options
1846 */
1847 if (nh->vn_options) {
1848 struct rfapi_vn_option *vo;
1849 char offset[] = " ";
1850
1851 for (vo = nh->vn_options; vo; vo = vo->next) {
1852 char pbuf[100];
1853
1854 switch (vo->type) {
1855 case RFAPI_VN_OPTION_TYPE_L2ADDR:
1856 rfapiEthAddr2Str(&vo->v.l2addr.macaddr,
1857 pbuf, sizeof(pbuf));
1858 fp(out,
1859 "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s",
1860 offset, pbuf,
1861 (vo->v.l2addr.label & 0x00ffffff),
1862 (vo->v.l2addr.logical_net_id
1863 & 0x00ffffff),
1864 vo->v.l2addr.local_nve_id, HVTYNL);
1865 break;
1866
1867 case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP:
1868 prefix2str(&vo->v.local_nexthop.addr,
1869 pbuf, sizeof(pbuf));
1870 fp(out, "%sLNH %s cost=%d%s", offset,
1871 pbuf, vo->v.local_nexthop.cost,
1872 HVTYNL);
1873 break;
1874
1875 default:
1876 fp(out,
1877 "%svn option type %d (unknown)%s",
1878 offset, vo->type, HVTYNL);
1879 break;
1880 }
1881 }
1882 }
1883 if (nh->un_options) {
1884 struct rfapi_un_option *uo;
1885 char offset[] = " ";
1886
1887 for (uo = nh->un_options; uo; uo = uo->next) {
1888 switch (uo->type) {
1889 case RFAPI_UN_OPTION_TYPE_TUNNELTYPE:
1890 rfapi_print_tunneltype_option(
1891 stream, 8, &uo->v.tunnel);
1892 break;
1893 default:
1894 fp(out, "%sUN Option type %d%s", offset,
1895 uo->type, vty_newline);
1896 break;
1897 }
1898 }
1899 }
1900 }
1901 }
1902
1903 /***********************************************************************
1904 * STATIC ROUTES
1905 ***********************************************************************/
1906
1907 /*
1908 * Add another nexthop to the NHL
1909 */
1910 static void rfapiAddDeleteLocalRfpPrefix(struct rfapi_ip_addr *un_addr,
1911 struct rfapi_ip_addr *vn_addr,
1912 struct rfapi_ip_prefix *rprefix,
1913 int is_add,
1914 uint32_t lifetime, /* add only */
1915 struct rfapi_vn_option *vn_options,
1916 struct rfapi_next_hop_entry **head,
1917 struct rfapi_next_hop_entry **tail)
1918 {
1919 struct rfapi_next_hop_entry *new;
1920
1921 /*
1922 * construct NHL
1923 */
1924
1925 new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry));
1926 new->prefix = *rprefix;
1927 new->un_address = *un_addr;
1928 new->vn_address = *vn_addr;
1929
1930 new->vn_options = vn_options;
1931 if (is_add) {
1932 new->lifetime = lifetime;
1933 } else {
1934 new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1935 }
1936
1937 if (*tail)
1938 (*tail)->next = new;
1939 *tail = new;
1940 if (!*head) {
1941 *head = new;
1942 }
1943 }
1944
1945
1946 static int
1947 register_add(struct vty *vty, struct cmd_token *carg_prefix,
1948 struct cmd_token *carg_vn, struct cmd_token *carg_un,
1949 struct cmd_token *carg_cost, /* optional */
1950 struct cmd_token *carg_lifetime, /* optional */
1951 struct cmd_token *carg_macaddr, /* optional */
1952 struct cmd_token
1953 *carg_vni, /* mac present=>mandatory Virtual Network ID */
1954 int argc, struct cmd_token **argv)
1955 {
1956 const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
1957 const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
1958 const char *arg_un = carg_un ? carg_un->arg : NULL;
1959 const char *arg_cost = carg_cost ? carg_cost->arg : NULL;
1960 const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL;
1961 const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL;
1962 const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
1963 struct rfapi_ip_addr vn_address;
1964 struct rfapi_ip_addr un_address;
1965 struct prefix pfx;
1966 struct rfapi_ip_prefix rpfx;
1967 uint32_t cost;
1968 uint32_t lnh_cost;
1969 uint32_t lifetime;
1970 rfapi_handle rfd;
1971 struct rfapi_vn_option optary[10]; /* XXX must be big enough */
1972 struct rfapi_vn_option *opt = NULL;
1973 int opt_next = 0;
1974
1975 int rc = CMD_WARNING_CONFIG_FAILED;
1976 char *endptr;
1977 struct bgp *bgp;
1978 struct rfapi *h;
1979 struct rfapi_cfg *rfapi_cfg;
1980
1981 const char *arg_lnh = NULL;
1982 const char *arg_lnh_cost = NULL;
1983
1984 bgp = bgp_get_default(); /* assume 1 instance for now */
1985 if (!bgp) {
1986 if (vty)
1987 vty_out(vty, "BGP not configured\n");
1988 return CMD_WARNING_CONFIG_FAILED;
1989 }
1990
1991 h = bgp->rfapi;
1992 rfapi_cfg = bgp->rfapi_cfg;
1993 if (!h || !rfapi_cfg) {
1994 if (vty)
1995 vty_out(vty, "RFAPI not configured\n");
1996 return CMD_WARNING_CONFIG_FAILED;
1997 }
1998
1999 for (; argc; --argc, ++argv) {
2000 if (strmatch(argv[0]->text, "local-next-hop")) {
2001 if (arg_lnh) {
2002 vty_out(vty,
2003 "local-next-hop specified more than once\n");
2004 return CMD_WARNING_CONFIG_FAILED;
2005 }
2006 if (argc <= 1) {
2007 vty_out(vty,
2008 "Missing parameter for local-next-hop\n");
2009 return CMD_WARNING_CONFIG_FAILED;
2010 }
2011 ++argv, --argc;
2012 arg_lnh = argv[0]->arg;
2013 }
2014 if (strmatch(argv[0]->text, "local-cost")) {
2015 if (arg_lnh_cost) {
2016 vty_out(vty,
2017 "local-cost specified more than once\n");
2018 return CMD_WARNING_CONFIG_FAILED;
2019 }
2020 if (argc <= 1) {
2021 vty_out(vty,
2022 "Missing parameter for local-cost\n");
2023 return CMD_WARNING_CONFIG_FAILED;
2024 }
2025 ++argv, --argc;
2026 arg_lnh_cost = argv[0]->arg;
2027 }
2028 }
2029
2030 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, &vn_address)))
2031 goto fail;
2032 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, &un_address)))
2033 goto fail;
2034
2035 /* arg_prefix is optional if mac address is given */
2036 if (arg_macaddr && !arg_prefix) {
2037 /*
2038 * fake up a 0/32 or 0/128 prefix
2039 */
2040 switch (vn_address.addr_family) {
2041 case AF_INET:
2042 arg_prefix = "0.0.0.0/32";
2043 break;
2044 case AF_INET6:
2045 arg_prefix = "0::0/128";
2046 break;
2047 default:
2048 vty_out(vty,
2049 "Internal error, unknown VN address family\n");
2050 return CMD_WARNING_CONFIG_FAILED;
2051 }
2052 }
2053
2054 if (!str2prefix(arg_prefix, &pfx)) {
2055 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2056 goto fail;
2057 }
2058 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2059 vty_out(vty, "prefix \"%s\" has invalid address family\n",
2060 arg_prefix);
2061 goto fail;
2062 }
2063
2064
2065 memset(optary, 0, sizeof(optary));
2066
2067 if (arg_cost) {
2068 endptr = NULL;
2069 cost = strtoul(arg_cost, &endptr, 10);
2070 if (*endptr != '\0' || cost > 255) {
2071 vty_out(vty, "%% Invalid %s value\n", "cost");
2072 goto fail;
2073 }
2074 } else {
2075 cost = 255;
2076 }
2077
2078 if (arg_lifetime) {
2079 if (!strcmp(arg_lifetime, "infinite")) {
2080 lifetime = RFAPI_INFINITE_LIFETIME;
2081 } else {
2082 endptr = NULL;
2083 lifetime = strtoul(arg_lifetime, &endptr, 10);
2084 if (*endptr != '\0') {
2085 vty_out(vty, "%% Invalid %s value\n",
2086 "lifetime");
2087 goto fail;
2088 }
2089 }
2090 } else {
2091 lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */
2092 }
2093
2094 if (arg_lnh_cost) {
2095 if (!arg_lnh) {
2096 vty_out(vty,
2097 "%% %s may only be specified with local-next-hop\n",
2098 "local-cost");
2099 goto fail;
2100 }
2101 endptr = NULL;
2102 lnh_cost = strtoul(arg_lnh_cost, &endptr, 10);
2103 if (*endptr != '\0' || lnh_cost > 255) {
2104 vty_out(vty, "%% Invalid %s value\n", "local-cost");
2105 goto fail;
2106 }
2107 } else {
2108 lnh_cost = 255;
2109 }
2110
2111 if (arg_lnh) {
2112 if (!arg_prefix) {
2113 vty_out(vty,
2114 "%% %s may only be specified with prefix\n",
2115 "local-next-hop");
2116 goto fail;
2117 }
2118 if ((rc = rfapiCliGetPrefixAddr(
2119 vty, arg_lnh,
2120 &optary[opt_next].v.local_nexthop.addr))) {
2121
2122 goto fail;
2123 }
2124
2125 optary[opt_next].v.local_nexthop.cost = lnh_cost;
2126 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP;
2127
2128 if (opt_next) {
2129 optary[opt_next - 1].next = optary + opt_next;
2130 } else {
2131 opt = optary;
2132 }
2133 ++opt_next;
2134 }
2135
2136 if (arg_vni && !arg_macaddr) {
2137 vty_out(vty, "%% %s may only be specified with mac address\n",
2138 "virtual-network-identifier");
2139 goto fail;
2140 }
2141
2142 if (arg_macaddr) {
2143 if (!arg_vni) {
2144 vty_out(vty,
2145 "Missing \"vni\" parameter (mandatory with mac)\n");
2146 return CMD_WARNING_CONFIG_FAILED;
2147 }
2148 optary[opt_next].v.l2addr.logical_net_id =
2149 strtoul(arg_vni, NULL, 10);
2150
2151 if ((rc = rfapiStr2EthAddr(
2152 arg_macaddr,
2153 &optary[opt_next].v.l2addr.macaddr))) {
2154 vty_out(vty, "Invalid %s value\n", "mac address");
2155 goto fail;
2156 }
2157 /* TBD label, NVE ID */
2158
2159 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
2160
2161 if (opt_next) {
2162 optary[opt_next - 1].next = optary + opt_next;
2163 } else {
2164 opt = optary;
2165 }
2166 ++opt_next;
2167 }
2168
2169 vnc_zlog_debug_verbose(
2170 "%s: vn=%s, un=%s, prefix=%s, cost=%s, lifetime=%s, lnh=%s",
2171 __func__, arg_vn, arg_un, arg_prefix,
2172 (arg_cost ? arg_cost : "NULL"),
2173 (arg_lifetime ? arg_lifetime : "NULL"),
2174 (arg_lnh ? arg_lnh : "NULL"));
2175
2176 rfapiQprefix2Rprefix(&pfx, &rpfx);
2177
2178 rpfx.cost = cost & 255;
2179
2180 /* look up rf descriptor, call open if it doesn't exist */
2181 rc = rfapi_find_rfd(bgp, &vn_address, &un_address,
2182 (struct rfapi_descriptor **)&rfd);
2183 if (rc) {
2184 if (ENOENT == rc) {
2185 struct rfapi_un_option uo;
2186
2187 /*
2188 * flag descriptor as provisionally opened for static
2189 * route
2190 * registration so that we can fix up the other
2191 * parameters
2192 * when the real open comes along
2193 */
2194 memset(&uo, 0, sizeof(uo));
2195 uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL;
2196
2197 rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp),
2198 &vn_address, &un_address,
2199 &uo, /* flags */
2200 NULL, NULL, /* no userdata */
2201 &rfd);
2202 if (rc) {
2203 vty_out(vty,
2204 "Can't open session for this NVE: %s\n",
2205 rfapi_error_str(rc));
2206 rc = CMD_WARNING_CONFIG_FAILED;
2207 goto fail;
2208 }
2209 } else {
2210 vty_out(vty, "Can't find session for this NVE: %s\n",
2211 rfapi_error_str(rc));
2212 goto fail;
2213 }
2214 }
2215
2216 rc = rfapi_register(rfd, &rpfx, lifetime, NULL, opt,
2217 RFAPI_REGISTER_ADD);
2218 if (!rc) {
2219 struct rfapi_next_hop_entry *head = NULL;
2220 struct rfapi_next_hop_entry *tail = NULL;
2221 struct rfapi_vn_option *vn_opt_new;
2222
2223 vnc_zlog_debug_verbose(
2224 "%s: rfapi_register succeeded, returning 0", __func__);
2225
2226 if (h->rfp_methods.local_cb) {
2227 struct rfapi_descriptor *r =
2228 (struct rfapi_descriptor *)rfd;
2229 vn_opt_new = rfapi_vn_options_dup(opt);
2230
2231 rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
2232 &rpfx, 1, lifetime,
2233 vn_opt_new, &head, &tail);
2234 if (head) {
2235 h->flags |= RFAPI_INCALLBACK;
2236 (*h->rfp_methods.local_cb)(head, r->cookie);
2237 h->flags &= ~RFAPI_INCALLBACK;
2238 }
2239 head = tail = NULL;
2240 }
2241 return 0;
2242 }
2243
2244 vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
2245 vty_out(vty, "\n");
2246 vty_out(vty, "Registration failed.\n");
2247 vty_out(vty,
2248 "Confirm that either the VN or UN address matches a configured NVE group.\n");
2249 return CMD_WARNING_CONFIG_FAILED;
2250
2251 fail:
2252 vnc_zlog_debug_verbose("%s: fail, rc=%d", __func__, rc);
2253 return rc;
2254 }
2255
2256 /************************************************************************
2257 * Add prefix With LNH_OPTIONS...
2258 ************************************************************************/
2259 DEFUN (add_vnc_prefix_cost_life_lnh,
2260 add_vnc_prefix_cost_life_lnh_cmd,
2261 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295) LNH_OPTIONS...",
2262 "Add registration\n"
2263 "VNC Information\n"
2264 "Add/modify prefix related information\n"
2265 "IPv4 prefix\n"
2266 "IPv6 prefix\n"
2267 "VN address of NVE\n"
2268 "VN IPv4 interface address\n"
2269 "VN IPv6 interface address\n"
2270 "UN address of NVE\n"
2271 "UN IPv4 interface address\n"
2272 "UN IPv6 interface address\n"
2273 "Administrative cost [default: 255]\n"
2274 "Administrative cost\n"
2275 "Registration lifetime [default: infinite]\n"
2276 "Lifetime value in seconds\n"
2277 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2278 {
2279 /* pfx vn un cost life */
2280 return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2281 /* mac vni */
2282 NULL, NULL, argc - 12, argv + 12);
2283 }
2284
2285 DEFUN (add_vnc_prefix_life_cost_lnh,
2286 add_vnc_prefix_life_cost_lnh_cmd,
2287 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255) LNH_OPTIONS...",
2288 "Add registration\n"
2289 "VNC Information\n"
2290 "Add/modify prefix related information\n"
2291 "IPv4 prefix\n"
2292 "IPv6 prefix\n"
2293 "VN address of NVE\n"
2294 "VN IPv4 interface address\n"
2295 "VN IPv6 interface address\n"
2296 "UN address of NVE\n"
2297 "UN IPv4 interface address\n"
2298 "UN IPv6 interface address\n"
2299 "Registration lifetime [default: infinite]\n"
2300 "Lifetime value in seconds\n"
2301 "Administrative cost [default: 255]\n"
2302 "Administrative cost\n"
2303 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2304 {
2305 /* pfx vn un cost life */
2306 return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2307 /* mac vni */
2308 NULL, NULL, argc - 12, argv + 12);
2309 }
2310
2311 DEFUN (add_vnc_prefix_cost_lnh,
2312 add_vnc_prefix_cost_lnh_cmd,
2313 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) LNH_OPTIONS...",
2314 "Add registration\n"
2315 "VNC Information\n"
2316 "Add/modify prefix related information\n"
2317 "IPv4 prefix\n"
2318 "IPv6 prefix\n"
2319 "VN address of NVE\n"
2320 "VN IPv4 interface address\n"
2321 "VN IPv6 interface address\n"
2322 "UN address of NVE\n"
2323 "UN IPv4 interface address\n"
2324 "UN IPv6 interface address\n"
2325 "Administrative cost [default: 255]\n"
2326 "Administrative cost\n"
2327 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2328 {
2329 /* pfx vn un cost life */
2330 return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2331 /* mac vni */
2332 NULL, NULL, argc - 10, argv + 10);
2333 }
2334
2335 DEFUN (add_vnc_prefix_life_lnh,
2336 add_vnc_prefix_life_lnh_cmd,
2337 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) LNH_OPTIONS...",
2338 "Add registration\n"
2339 "VNC Information\n"
2340 "Add/modify prefix related information\n"
2341 "IPv4 prefix\n"
2342 "IPv6 prefix\n"
2343 "VN address of NVE\n"
2344 "VN IPv4 interface address\n"
2345 "VN IPv6 interface address\n"
2346 "UN address of NVE\n"
2347 "UN IPv4 interface address\n"
2348 "UN IPv6 interface address\n"
2349 "Registration lifetime [default: infinite]\n"
2350 "Lifetime value in seconds\n"
2351 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2352 {
2353 /* pfx vn un cost life */
2354 return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2355 /* mac vni */
2356 NULL, NULL, argc - 10, argv + 10);
2357 }
2358
2359 DEFUN (add_vnc_prefix_lnh,
2360 add_vnc_prefix_lnh_cmd,
2361 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> LNH_OPTIONS...",
2362 "Add registration\n"
2363 "VNC Information\n"
2364 "Add/modify prefix related information\n"
2365 "IPv4 prefix\n"
2366 "IPv6 prefix\n"
2367 "VN address of NVE\n"
2368 "VN IPv4 interface address\n"
2369 "VN IPv6 interface address\n"
2370 "UN address of NVE\n"
2371 "UN IPv4 interface address\n"
2372 "UN IPv6 interface address\n"
2373 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2374 {
2375 /* pfx vn un cost life */
2376 return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2377 /* mac vni */
2378 NULL, NULL, argc - 8, argv + 8);
2379 }
2380
2381 /************************************************************************
2382 * Add prefix Without LNH_OPTIONS...
2383 ************************************************************************/
2384 DEFUN (add_vnc_prefix_cost_life,
2385 add_vnc_prefix_cost_life_cmd,
2386 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
2387 "Add registration\n"
2388 "VNC Information\n"
2389 "Add/modify prefix related information\n"
2390 "IPv4 prefix\n"
2391 "IPv6 prefix\n"
2392 "VN address of NVE\n"
2393 "VN IPv4 interface address\n"
2394 "VN IPv6 interface address\n"
2395 "UN address of NVE\n"
2396 "UN IPv4 interface address\n"
2397 "UN IPv6 interface address\n"
2398 "Administrative cost [default: 255]\n"
2399 "Administrative cost\n"
2400 "Registration lifetime [default: infinite]\n"
2401 "Lifetime value in seconds\n")
2402 {
2403 /* pfx vn un cost life */
2404 return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2405 /* mac vni */
2406 NULL, NULL, 0, NULL);
2407 }
2408
2409 DEFUN (add_vnc_prefix_life_cost,
2410 add_vnc_prefix_life_cost_cmd,
2411 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255)",
2412 "Add registration\n"
2413 "VNC Information\n"
2414 "Add/modify prefix related information\n"
2415 "IPv4 prefix\n"
2416 "IPv6 prefix\n"
2417 "VN address of NVE\n"
2418 "VN IPv4 interface address\n"
2419 "VN IPv6 interface address\n"
2420 "UN address of NVE\n"
2421 "UN IPv4 interface address\n"
2422 "UN IPv6 interface address\n"
2423 "Registration lifetime [default: infinite]\n"
2424 "Lifetime value in seconds\n"
2425 "Administrative cost [default: 255]\n"
2426 "Administrative cost\n")
2427 {
2428 /* pfx vn un cost life */
2429 return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2430 /* mac vni */
2431 NULL, NULL, 0, NULL);
2432 }
2433
2434 DEFUN (add_vnc_prefix_cost,
2435 add_vnc_prefix_cost_cmd,
2436 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
2437 "Add registration\n"
2438 "VNC Information\n"
2439 "Add/modify prefix related information\n"
2440 "IPv4 prefix\n"
2441 "IPv6 prefix\n"
2442 "VN address of NVE\n"
2443 "VN IPv4 interface address\n"
2444 "VN IPv6 interface address\n"
2445 "UN address of NVE\n"
2446 "UN IPv4 interface address\n"
2447 "UN IPv6 interface address\n"
2448 "Administrative cost [default: 255]\n"
2449 "Administrative cost\n")
2450 {
2451 /* pfx vn un cost life */
2452 return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2453 /* mac vni */
2454 NULL, NULL, 0, NULL);
2455 }
2456
2457 DEFUN (add_vnc_prefix_life,
2458 add_vnc_prefix_life_cmd,
2459 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
2460 "Add registration\n"
2461 "VNC Information\n"
2462 "Add/modify prefix related information\n"
2463 "IPv4 prefix\n"
2464 "IPv6 prefix\n"
2465 "VN address of NVE\n"
2466 "VN IPv4 interface address\n"
2467 "VN IPv6 interface address\n"
2468 "UN address of NVE\n"
2469 "UN IPv4 interface address\n"
2470 "UN IPv6 interface address\n"
2471 "Registration lifetime [default: infinite]\n"
2472 "Lifetime value in seconds\n")
2473 {
2474 /* pfx vn un cost life */
2475 return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2476 /* mac vni */
2477 NULL, NULL, 0, NULL);
2478 }
2479
2480 DEFUN (add_vnc_prefix,
2481 add_vnc_prefix_cmd,
2482 "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2483 "Add registration\n"
2484 "VNC Information\n"
2485 "Add/modify prefix related information\n"
2486 "IPv4 prefix\n"
2487 "IPv6 prefix\n"
2488 "VN address of NVE\n"
2489 "VN IPv4 interface address\n"
2490 "VN IPv6 interface address\n"
2491 "UN address of NVE\n"
2492 "UN IPv4 interface address\n"
2493 "UN IPv6 interface address\n")
2494 {
2495 /* pfx vn un cost life */
2496 return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2497 /* mac vni */
2498 NULL, NULL, 0, NULL);
2499 }
2500
2501 /************************************************************************
2502 * Mac address registrations
2503 ************************************************************************/
2504 DEFUN (add_vnc_mac_vni_prefix_cost_life,
2505 add_vnc_mac_vni_prefix_cost_life_cmd,
2506 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255) lifetime (1-4294967295)",
2507 "Add registration\n"
2508 "VNC Information\n"
2509 "Add/modify mac address information\n"
2510 "MAC address\n"
2511 "Virtual Network Identifier follows\n"
2512 "Virtual Network Identifier\n"
2513 "VN address of NVE\n"
2514 "VN IPv4 interface address\n"
2515 "VN IPv6 interface address\n"
2516 "UN address of NVE\n"
2517 "UN IPv4 interface address\n"
2518 "UN IPv6 interface address\n"
2519 "Add/modify prefix related information\n"
2520 "IPv4 prefix\n"
2521 "IPv6 prefix\n"
2522 "Administrative cost [default: 255]\n"
2523 "Administrative cost\n"
2524 "Registration lifetime [default: infinite]\n"
2525 "Lifetime value in seconds\n")
2526 {
2527 /* pfx vn un cost life */
2528 return register_add(vty, argv[11], argv[7], argv[9], argv[13], argv[15],
2529 /* mac vni */
2530 argv[3], argv[5], 0, NULL);
2531 }
2532
2533
2534 DEFUN (add_vnc_mac_vni_prefix_life,
2535 add_vnc_mac_vni_prefix_life_cmd,
2536 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime (1-4294967295)",
2537 "Add registration\n"
2538 "VNC Information\n"
2539 "Add/modify mac address information\n"
2540 "MAC address\n"
2541 "Virtual Network Identifier follows\n"
2542 "Virtual Network Identifier\n"
2543 "VN address of NVE\n"
2544 "VN IPv4 interface address\n"
2545 "VN IPv6 interface address\n"
2546 "UN address of NVE\n"
2547 "UN IPv4 interface address\n"
2548 "UN IPv6 interface address\n"
2549 "Add/modify prefix related information\n"
2550 "IPv4 prefix\n"
2551 "IPv6 prefix\n"
2552 "Registration lifetime [default: infinite]\n"
2553 "Lifetime value in seconds\n")
2554 {
2555 /* pfx vn un cost life */
2556 return register_add(vty, argv[11], argv[7], argv[9], NULL, argv[13],
2557 /* mac vni */
2558 argv[3], argv[5], 0, NULL);
2559 }
2560
2561 DEFUN (add_vnc_mac_vni_prefix_cost,
2562 add_vnc_mac_vni_prefix_cost_cmd,
2563 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255)",
2564 "Add registration\n"
2565 "VNC Information\n"
2566 "Add/modify mac address information\n"
2567 "MAC address\n"
2568 "Virtual Network Identifier follows\n"
2569 "Virtual Network Identifier\n"
2570 "VN address of NVE\n"
2571 "VN IPv4 interface address\n"
2572 "VN IPv6 interface address\n"
2573 "UN address of NVE\n"
2574 "UN IPv4 interface address\n"
2575 "UN IPv6 interface address\n"
2576 "Add/modify prefix related information\n"
2577 "IPv4 prefix\n"
2578 "IPv6 prefix\n"
2579 "Administrative cost [default: 255]\n" "Administrative cost\n")
2580 {
2581 /* pfx vn un cost life */
2582 return register_add(vty, argv[11], argv[7], argv[9], argv[13], NULL,
2583 /* mac vni */
2584 argv[3], argv[5], 0, NULL);
2585 }
2586
2587 DEFUN (add_vnc_mac_vni_prefix,
2588 add_vnc_mac_vni_prefix_cmd,
2589 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M>",
2590 "Add registration\n"
2591 "VNC Information\n"
2592 "Add/modify mac address information\n"
2593 "MAC address\n"
2594 "Virtual Network Identifier follows\n"
2595 "Virtual Network Identifier\n"
2596 "VN address of NVE\n"
2597 "VN IPv4 interface address\n"
2598 "VN IPv6 interface address\n"
2599 "UN address of NVE\n"
2600 "UN IPv4 interface address\n"
2601 "UN IPv6 interface address\n"
2602 "Add/modify prefix related information\n"
2603 "IPv4 prefix\n" "IPv6 prefix\n")
2604 {
2605 /* pfx vn un cost life */
2606 return register_add(vty, argv[11], argv[7], argv[9], NULL, NULL,
2607 /* mac vni */
2608 argv[3], argv[5], 0, NULL);
2609 }
2610
2611 DEFUN (add_vnc_mac_vni_cost_life,
2612 add_vnc_mac_vni_cost_life_cmd,
2613 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
2614 "Add registration\n"
2615 "VNC Information\n"
2616 "Add/modify mac address information\n"
2617 "MAC address\n"
2618 "Virtual Network Identifier follows\n"
2619 "Virtual Network Identifier\n"
2620 "VN address of NVE\n"
2621 "VN IPv4 interface address\n"
2622 "VN IPv6 interface address\n"
2623 "UN address of NVE\n"
2624 "UN IPv4 interface address\n"
2625 "UN IPv6 interface address\n"
2626 "Administrative cost [default: 255]\n"
2627 "Administrative cost\n"
2628 "Registration lifetime [default: infinite]\n"
2629 "Lifetime value in seconds\n")
2630 {
2631 /* pfx vn un cost life */
2632 return register_add(vty, NULL, argv[7], argv[9], argv[11], argv[13],
2633 /* mac vni */
2634 argv[3], argv[5], 0, NULL);
2635 }
2636
2637
2638 DEFUN (add_vnc_mac_vni_cost,
2639 add_vnc_mac_vni_cost_cmd,
2640 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
2641 "Add registration\n"
2642 "VNC Information\n"
2643 "Add/modify mac address information\n"
2644 "MAC address\n"
2645 "Virtual Network Identifier follows\n"
2646 "Virtual Network Identifier\n"
2647 "VN address of NVE\n"
2648 "VN IPv4 interface address\n"
2649 "VN IPv6 interface address\n"
2650 "UN address of NVE\n"
2651 "UN IPv4 interface address\n"
2652 "UN IPv6 interface address\n"
2653 "Administrative cost [default: 255]\n" "Administrative cost\n")
2654 {
2655 /* pfx vn un cost life */
2656 return register_add(vty, NULL, argv[7], argv[9], argv[11], NULL,
2657 /* mac vni */
2658 argv[3], argv[5], 0, NULL);
2659 }
2660
2661
2662 DEFUN (add_vnc_mac_vni_life,
2663 add_vnc_mac_vni_life_cmd,
2664 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
2665 "Add registration\n"
2666 "VNC Information\n"
2667 "Add/modify mac address information\n"
2668 "MAC address\n"
2669 "Virtual Network Identifier follows\n"
2670 "Virtual Network Identifier\n"
2671 "VN address of NVE\n"
2672 "VN IPv4 interface address\n"
2673 "VN IPv6 interface address\n"
2674 "UN address of NVE\n"
2675 "UN IPv4 interface address\n"
2676 "UN IPv6 interface address\n"
2677 "Registration lifetime [default: infinite]\n"
2678 "Lifetime value in seconds\n")
2679 {
2680 /* pfx vn un cost life */
2681 return register_add(vty, NULL, argv[7], argv[9], NULL, argv[11],
2682 /* mac vni */
2683 argv[3], argv[5], 0, NULL);
2684 }
2685
2686
2687 DEFUN (add_vnc_mac_vni,
2688 add_vnc_mac_vni_cmd,
2689 "add vnc mac YY:YY:YY:YY:YY:YY virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2690 "Add registration\n"
2691 "VNC Information\n"
2692 "Add/modify mac address information\n"
2693 "MAC address\n"
2694 "Virtual Network Identifier follows\n"
2695 "Virtual Network Identifier\n"
2696 "VN address of NVE\n"
2697 "VN IPv4 interface address\n"
2698 "VN IPv6 interface address\n"
2699 "UN address of NVE\n"
2700 "UN IPv4 interface address\n" "UN IPv6 interface address\n")
2701 {
2702 /* pfx vn un cost life */
2703 return register_add(vty, NULL, argv[7], argv[9], NULL, NULL,
2704 /* mac vni */
2705 argv[3], argv[5], 0, NULL);
2706 }
2707
2708 /************************************************************************
2709 * Delete prefix
2710 ************************************************************************/
2711
2712 struct rfapi_local_reg_delete_arg {
2713 /*
2714 * match parameters
2715 */
2716 struct bgp *bgp;
2717 struct rfapi_ip_addr un_address; /* AF==0: wildcard */
2718 struct rfapi_ip_addr vn_address; /* AF==0: wildcard */
2719 struct prefix prefix; /* AF==0: wildcard */
2720 struct prefix_rd rd; /* plen!=64: wildcard */
2721 struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */
2722
2723 struct rfapi_l2address_option_match l2o;
2724
2725 /*
2726 * result parameters
2727 */
2728 struct vty *vty;
2729 uint32_t reg_count;
2730 uint32_t pfx_count;
2731 uint32_t query_count;
2732
2733 uint32_t failed_pfx_count;
2734
2735 uint32_t nve_count;
2736 struct skiplist *nves;
2737
2738 uint32_t remote_active_nve_count;
2739 uint32_t remote_active_pfx_count;
2740 uint32_t remote_holddown_nve_count;
2741 uint32_t remote_holddown_pfx_count;
2742 };
2743
2744 struct nve_addr {
2745 struct rfapi_ip_addr vn;
2746 struct rfapi_ip_addr un;
2747 struct rfapi_descriptor *rfd;
2748 struct rfapi_local_reg_delete_arg *cda;
2749 };
2750
2751 static void nve_addr_free(void *hap)
2752 {
2753 ((struct nve_addr *)hap)->cda->nve_count += 1;
2754 XFREE(MTYPE_RFAPI_NVE_ADDR, hap);
2755 }
2756
2757 static int nve_addr_cmp(void *k1, void *k2)
2758 {
2759 struct nve_addr *a = (struct nve_addr *)k1;
2760 struct nve_addr *b = (struct nve_addr *)k2;
2761 int ret = 0;
2762
2763 if (!a || !b) {
2764 return (a - b);
2765 }
2766 if (a->un.addr_family != b->un.addr_family) {
2767 return (a->un.addr_family - b->un.addr_family);
2768 }
2769 if (a->vn.addr_family != b->vn.addr_family) {
2770 return (a->vn.addr_family - b->vn.addr_family);
2771 }
2772 if (a->un.addr_family == AF_INET) {
2773 ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4);
2774 if (ret != 0) {
2775 return ret;
2776 }
2777 } else if (a->un.addr_family == AF_INET6) {
2778 ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6);
2779 if (ret != 0) {
2780 return ret;
2781 }
2782 } else {
2783 assert(0);
2784 }
2785 if (a->vn.addr_family == AF_INET) {
2786 ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4);
2787 if (ret != 0)
2788 return ret;
2789 } else if (a->vn.addr_family == AF_INET6) {
2790 ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6);
2791 if (ret == 0) {
2792 return ret;
2793 }
2794 } else {
2795 assert(0);
2796 }
2797 return 0;
2798 }
2799
2800 static int parse_deleter_args(struct vty *vty, struct bgp *bgp,
2801 const char *arg_prefix, const char *arg_vn,
2802 const char *arg_un, const char *arg_l2addr,
2803 const char *arg_vni, const char *arg_rd,
2804 struct rfapi_nve_group_cfg *arg_rfg,
2805 struct rfapi_local_reg_delete_arg *rcdarg)
2806 {
2807 int rc = CMD_WARNING;
2808
2809 memset(rcdarg, 0, sizeof(struct rfapi_local_reg_delete_arg));
2810
2811 rcdarg->vty = vty;
2812 if (bgp == NULL)
2813 bgp = bgp_get_default();
2814 rcdarg->bgp = bgp;
2815 rcdarg->rfg = arg_rfg; /* may be NULL */
2816
2817 if (arg_vn && strcmp(arg_vn, "*")) {
2818 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn,
2819 &rcdarg->vn_address)))
2820 return rc;
2821 }
2822 if (arg_un && strcmp(arg_un, "*")) {
2823 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un,
2824 &rcdarg->un_address)))
2825 return rc;
2826 }
2827 if (arg_prefix && strcmp(arg_prefix, "*")) {
2828
2829 if (!str2prefix(arg_prefix, &rcdarg->prefix)) {
2830 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2831 return rc;
2832 }
2833 }
2834
2835 if (arg_l2addr) {
2836 if (!arg_vni) {
2837 vty_out(vty, "Missing VNI\n");
2838 return rc;
2839 }
2840 if (strcmp(arg_l2addr, "*")) {
2841 if ((rc = rfapiStr2EthAddr(arg_l2addr,
2842 &rcdarg->l2o.o.macaddr))) {
2843 vty_out(vty, "Malformed L2 Address \"%s\"\n",
2844 arg_l2addr);
2845 return rc;
2846 }
2847 rcdarg->l2o.flags |= RFAPI_L2O_MACADDR;
2848 }
2849 if (strcmp(arg_vni, "*")) {
2850 rcdarg->l2o.o.logical_net_id =
2851 strtoul(arg_vni, NULL, 10);
2852 rcdarg->l2o.flags |= RFAPI_L2O_LNI;
2853 }
2854 }
2855 if (arg_rd) {
2856 if (!str2prefix_rd(arg_rd, &rcdarg->rd)) {
2857 vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
2858 return rc;
2859 }
2860 }
2861
2862 return CMD_SUCCESS;
2863 }
2864
2865 static int
2866 parse_deleter_tokens(struct vty *vty, struct bgp *bgp,
2867 struct cmd_token *carg_prefix, struct cmd_token *carg_vn,
2868 struct cmd_token *carg_un, struct cmd_token *carg_l2addr,
2869 struct cmd_token *carg_vni, struct cmd_token *carg_rd,
2870 struct rfapi_nve_group_cfg *arg_rfg,
2871 struct rfapi_local_reg_delete_arg *rcdarg)
2872 {
2873 const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
2874 const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
2875 const char *arg_un = carg_un ? carg_un->arg : NULL;
2876 const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL;
2877 const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
2878 const char *arg_rd = carg_rd ? carg_rd->arg : NULL;
2879 return parse_deleter_args(vty, bgp, arg_prefix, arg_vn, arg_un,
2880 arg_l2addr, arg_vni, arg_rd, arg_rfg, rcdarg);
2881 }
2882
2883 static void record_nve_in_cda_list(struct rfapi_local_reg_delete_arg *cda,
2884 struct rfapi_ip_addr *un_address,
2885 struct rfapi_ip_addr *vn_address,
2886 struct rfapi_descriptor *rfd)
2887 {
2888 struct nve_addr ha;
2889 struct nve_addr *hap;
2890
2891 memset(&ha, 0, sizeof(ha));
2892 ha.un = *un_address;
2893 ha.vn = *vn_address;
2894 ha.rfd = rfd;
2895
2896 if (!cda->nves)
2897 cda->nves = skiplist_new(0, nve_addr_cmp, nve_addr_free);
2898
2899 if (skiplist_search(cda->nves, &ha, (void *)&hap)) {
2900 hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, sizeof(struct nve_addr));
2901 assert(hap);
2902 ha.cda = cda;
2903 *hap = ha;
2904 skiplist_insert(cda->nves, hap, hap);
2905 }
2906 }
2907
2908 static void clear_vnc_responses(struct rfapi_local_reg_delete_arg *cda)
2909 {
2910 struct rfapi *h;
2911 struct rfapi_descriptor *rfd;
2912 int query_count = 0;
2913 struct listnode *node;
2914 struct bgp *bgp_default = bgp_get_default();
2915
2916 if (cda->vn_address.addr_family && cda->un_address.addr_family) {
2917 /*
2918 * Single nve case
2919 */
2920 if (rfapi_find_rfd(bgp_default, &cda->vn_address,
2921 &cda->un_address, &rfd))
2922 return;
2923
2924 rfapiRibClear(rfd);
2925 rfapi_query_done_all(rfd, &query_count);
2926 cda->query_count += query_count;
2927
2928 /*
2929 * Track unique nves seen
2930 */
2931 record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2932 return;
2933 }
2934
2935 /*
2936 * wildcard case
2937 */
2938
2939 if (!bgp_default)
2940 return; /* ENXIO */
2941
2942 h = bgp_default->rfapi;
2943
2944 if (!h)
2945 return; /* ENXIO */
2946
2947 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
2948 /*
2949 * match un, vn addresses of NVEs
2950 */
2951 if (cda->un_address.addr_family
2952 && rfapi_ip_addr_cmp(&cda->un_address, &rfd->un_addr)) {
2953 continue;
2954 }
2955 if (cda->vn_address.addr_family
2956 && rfapi_ip_addr_cmp(&cda->vn_address, &rfd->vn_addr)) {
2957 continue;
2958 }
2959
2960 rfapiRibClear(rfd);
2961
2962 rfapi_query_done_all(rfd, &query_count);
2963 cda->query_count += query_count;
2964
2965 /*
2966 * Track unique nves seen
2967 */
2968 record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2969 }
2970 }
2971
2972 /*
2973 * TBD need to count deleted prefixes and nves?
2974 *
2975 * ENXIO BGP or VNC not configured
2976 */
2977 static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
2978 struct rfapi_descriptor *rfd)
2979 {
2980 struct rfapi_ip_addr *pUn; /* NULL = wildcard */
2981 struct rfapi_ip_addr *pVn; /* NULL = wildcard */
2982 struct prefix *pPrefix; /* NULL = wildcard */
2983 struct prefix_rd *pPrd; /* NULL = wildcard */
2984
2985 struct rfapi_ip_prefix rprefix;
2986 struct rfapi_next_hop_entry *head = NULL;
2987 struct rfapi_next_hop_entry *tail = NULL;
2988
2989 #if DEBUG_L2_EXTRA
2990 vnc_zlog_debug_verbose("%s: entry", __func__);
2991 #endif
2992
2993 pUn = (cda->un_address.addr_family ? &cda->un_address : NULL);
2994 pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL);
2995 pPrefix = (cda->prefix.family ? &cda->prefix : NULL);
2996 pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL);
2997
2998 if (pPrefix) {
2999 rfapiQprefix2Rprefix(pPrefix, &rprefix);
3000 }
3001
3002 do /* to preserve old code structure */
3003 {
3004 struct rfapi *h = cda->bgp->rfapi;
3005 ;
3006 struct rfapi_adb *adb;
3007 int rc;
3008 int deleted_from_this_nve;
3009 struct nve_addr ha;
3010 struct nve_addr *hap;
3011
3012 #if DEBUG_L2_EXTRA
3013 vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
3014 #endif
3015
3016 /*
3017 * match un, vn addresses of NVEs
3018 */
3019 if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr)))
3020 break;
3021 if (pVn && (rfapi_ip_addr_cmp(pVn, &rfd->vn_addr)))
3022 break;
3023
3024 #if DEBUG_L2_EXTRA
3025 vnc_zlog_debug_verbose("%s: un, vn match", __func__);
3026 #endif
3027
3028 /*
3029 * match prefix
3030 */
3031
3032 deleted_from_this_nve = 0;
3033
3034 {
3035 struct skiplist *sl;
3036 struct rfapi_ip_prefix rp;
3037 void *cursor;
3038 struct list *adb_delete_list;
3039
3040 /*
3041 * The advertisements are stored in a skiplist.
3042 * Withdrawing
3043 * the registration deletes the advertisement from the
3044 * skiplist, which we can't do while iterating over that
3045 * same skiplist using the current skiplist API.
3046 *
3047 * Strategy: iterate over the skiplist and build another
3048 * list containing only the matching ADBs. Then delete
3049 * _everything_ in that second list (which can be done
3050 * using either skiplists or quagga linklists).
3051 */
3052 adb_delete_list = list_new();
3053
3054 /*
3055 * Advertised IP prefixes (not 0/32 or 0/128)
3056 */
3057 sl = rfd->advertised.ipN_by_prefix;
3058
3059 for (cursor = NULL,
3060 rc = skiplist_next(sl, NULL, (void **)&adb,
3061 &cursor);
3062 !rc; rc = skiplist_next(sl, NULL, (void **)&adb,
3063 &cursor)) {
3064
3065 if (pPrefix) {
3066 if (!prefix_same(pPrefix,
3067 &adb->u.s.prefix_ip)) {
3068 #if DEBUG_L2_EXTRA
3069 vnc_zlog_debug_verbose(
3070 "%s: adb=%p, prefix doesn't match, skipping",
3071 __func__, adb);
3072 #endif
3073 continue;
3074 }
3075 }
3076 if (pPrd) {
3077 if (memcmp(pPrd->val, adb->u.s.prd.val,
3078 8)
3079 != 0) {
3080 #if DEBUG_L2_EXTRA
3081 vnc_zlog_debug_verbose(
3082 "%s: adb=%p, RD doesn't match, skipping",
3083 __func__, adb);
3084 #endif
3085 continue;
3086 }
3087 }
3088 if (CHECK_FLAG(cda->l2o.flags,
3089 RFAPI_L2O_MACADDR)) {
3090 if (memcmp(cda->l2o.o.macaddr.octet,
3091 adb->u.s.prefix_eth.u
3092 .prefix_eth.octet,
3093 ETH_ALEN)) {
3094 #if DEBUG_L2_EXTRA
3095 vnc_zlog_debug_verbose(
3096 "%s: adb=%p, macaddr doesn't match, skipping",
3097 __func__, adb);
3098 #endif
3099 continue;
3100 }
3101 }
3102
3103 if (CHECK_FLAG(cda->l2o.flags, RFAPI_L2O_LNI)) {
3104 if (cda->l2o.o.logical_net_id
3105 != adb->l2o.logical_net_id) {
3106 #if DEBUG_L2_EXTRA
3107 vnc_zlog_debug_verbose(
3108 "%s: adb=%p, LNI doesn't match, skipping",
3109 __func__, adb);
3110 #endif
3111 continue;
3112 }
3113 }
3114
3115 #if DEBUG_L2_EXTRA
3116 vnc_zlog_debug_verbose(
3117 "%s: ipN adding adb %p to delete list",
3118 __func__, adb);
3119 #endif
3120
3121 listnode_add(adb_delete_list, adb);
3122 }
3123
3124 struct listnode *node;
3125
3126 for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, adb)) {
3127 int this_advertisement_prefix_count;
3128 struct rfapi_vn_option optary[3];
3129 struct rfapi_vn_option *opt = NULL;
3130 int cur_opt = 0;
3131
3132 this_advertisement_prefix_count = 1;
3133
3134 rfapiQprefix2Rprefix(&adb->u.s.prefix_ip, &rp);
3135
3136 memset(optary, 0, sizeof(optary));
3137
3138 /* if mac addr present in advert, make l2o vn
3139 * option */
3140 if (adb->u.s.prefix_eth.family == AF_ETHERNET) {
3141 if (opt != NULL)
3142 opt->next = &optary[cur_opt];
3143 opt = &optary[cur_opt++];
3144 opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3145 opt->v.l2addr.macaddr =
3146 adb->u.s.prefix_eth.u
3147 .prefix_eth;
3148 ++this_advertisement_prefix_count;
3149 }
3150 /*
3151 * use saved RD value instead of trying to
3152 * invert
3153 * complex RD computation in rfapi_register()
3154 */
3155 if (opt != NULL)
3156 opt->next = &optary[cur_opt];
3157 opt = &optary[cur_opt++];
3158 opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
3159 opt->v.internal_rd = adb->u.s.prd;
3160
3161 #if DEBUG_L2_EXTRA
3162 vnc_zlog_debug_verbose(
3163 "%s: ipN killing reg from adb %p ",
3164 __func__, adb);
3165 #endif
3166
3167 rc = rfapi_register(rfd, &rp, 0, NULL,
3168 (cur_opt ? optary : NULL),
3169 RFAPI_REGISTER_KILL);
3170 if (!rc) {
3171 cda->pfx_count +=
3172 this_advertisement_prefix_count;
3173 cda->reg_count += 1;
3174 deleted_from_this_nve = 1;
3175 }
3176 if (h->rfp_methods.local_cb) {
3177 rfapiAddDeleteLocalRfpPrefix(
3178 &rfd->un_addr, &rfd->vn_addr,
3179 &rp, 0, 0, NULL, &head, &tail);
3180 }
3181 }
3182 list_delete_all_node(adb_delete_list);
3183
3184 if (!(pPrefix && !RFAPI_0_PREFIX(pPrefix))) {
3185 void *cursor;
3186
3187 /*
3188 * Caller didn't specify a prefix, or specified
3189 * (0/32 or 0/128)
3190 */
3191
3192 /*
3193 * Advertised 0/32 and 0/128 (indexed by
3194 * ethernet address)
3195 */
3196 sl = rfd->advertised.ip0_by_ether;
3197
3198 for (cursor = NULL,
3199 rc = skiplist_next(sl, NULL, (void **)&adb,
3200 &cursor);
3201 !rc;
3202 rc = skiplist_next(sl, NULL, (void **)&adb,
3203 &cursor)) {
3204
3205 if (CHECK_FLAG(cda->l2o.flags,
3206 RFAPI_L2O_MACADDR)) {
3207 if (memcmp(cda->l2o.o.macaddr
3208 .octet,
3209 adb->u.s.prefix_eth.u
3210 .prefix_eth
3211 .octet,
3212 ETH_ALEN)) {
3213
3214 continue;
3215 }
3216 }
3217 if (CHECK_FLAG(cda->l2o.flags,
3218 RFAPI_L2O_LNI)) {
3219 if (cda->l2o.o.logical_net_id
3220 != adb->l2o.logical_net_id) {
3221 continue;
3222 }
3223 }
3224 #if DEBUG_L2_EXTRA
3225 vnc_zlog_debug_verbose(
3226 "%s: ip0 adding adb %p to delete list",
3227 __func__, adb);
3228 #endif
3229 listnode_add(adb_delete_list, adb);
3230 }
3231
3232
3233 for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node,
3234 adb)) {
3235
3236 struct rfapi_vn_option vn;
3237
3238 rfapiQprefix2Rprefix(
3239 &adb->u.s.prefix_ip, &rp);
3240
3241 memset(&vn, 0, sizeof(vn));
3242 vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3243 vn.v.l2addr = adb->l2o;
3244
3245 #if DEBUG_L2_EXTRA
3246 vnc_zlog_debug_verbose(
3247 "%s: ip0 killing reg from adb %p ",
3248 __func__, adb);
3249 #endif
3250
3251 rc = rfapi_register(
3252 rfd, &rp, 0, NULL, &vn,
3253 RFAPI_REGISTER_KILL);
3254 if (!rc) {
3255 cda->pfx_count += 1;
3256 cda->reg_count += 1;
3257 deleted_from_this_nve = 1;
3258 }
3259 if (h->rfp_methods.local_cb) {
3260 struct rfapi_vn_option
3261 *vn_opt_new;
3262
3263 vn_opt_new =
3264 rfapi_vn_options_dup(
3265 &vn);
3266 rfapiAddDeleteLocalRfpPrefix(
3267 &rfd->un_addr,
3268 &rfd->vn_addr, &rp, 0,
3269 0, vn_opt_new, &head,
3270 &tail);
3271 }
3272 }
3273 list_delete_all_node(adb_delete_list);
3274 }
3275 list_delete_and_null(&adb_delete_list);
3276 }
3277
3278
3279 if (head) { /* should not be set if (NULL ==
3280 rfapi_cfg->local_cb) */
3281 h->flags |= RFAPI_INCALLBACK;
3282 (*h->rfp_methods.local_cb)(head, rfd->cookie);
3283 h->flags &= ~RFAPI_INCALLBACK;
3284 head = tail = NULL;
3285 }
3286
3287 if (deleted_from_this_nve) {
3288 /*
3289 * track unique NVEs seen
3290 */
3291 memset(&ha, 0, sizeof(ha));
3292 ha.un = rfd->un_addr;
3293 ha.vn = rfd->vn_addr;
3294
3295 if (!cda->nves)
3296 cda->nves = skiplist_new(0, nve_addr_cmp,
3297 nve_addr_free);
3298 if (skiplist_search(cda->nves, &ha, (void **)&hap)) {
3299 hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR,
3300 sizeof(struct nve_addr));
3301 assert(hap);
3302 ha.cda = cda;
3303 *hap = ha;
3304 skiplist_insert(cda->nves, hap, hap);
3305 }
3306 }
3307 } while (0); /* to preserve old code structure */
3308
3309 return 0;
3310 }
3311
3312 static int rfapiDeleteLocalPrefixes(struct rfapi_local_reg_delete_arg *cda)
3313 {
3314 int rc = 0;
3315
3316 if (cda->rfg) {
3317 if (cda->rfg->rfd) /* if not open, nothing to delete */
3318 rc = rfapiDeleteLocalPrefixesByRFD(cda, cda->rfg->rfd);
3319 } else {
3320 struct bgp *bgp = cda->bgp;
3321 struct rfapi *h;
3322 struct rfapi_cfg *rfapi_cfg;
3323
3324 struct listnode *node;
3325 struct rfapi_descriptor *rfd;
3326 if (!bgp)
3327 return ENXIO;
3328 h = bgp->rfapi;
3329 rfapi_cfg = bgp->rfapi_cfg;
3330 if (!h || !rfapi_cfg)
3331 return ENXIO;
3332 vnc_zlog_debug_verbose("%s: starting descriptor loop",
3333 __func__);
3334 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
3335 rc = rfapiDeleteLocalPrefixesByRFD(cda, rfd);
3336 }
3337 }
3338 return rc;
3339 }
3340
3341 /*
3342 * clear_vnc_prefix
3343 *
3344 * Deletes local and remote prefixes that match
3345 */
3346 static void clear_vnc_prefix(struct rfapi_local_reg_delete_arg *cda)
3347 {
3348 struct prefix pfx_un;
3349 struct prefix pfx_vn;
3350
3351 struct prefix *pUN = NULL;
3352 struct prefix *pVN = NULL;
3353 struct prefix *pPrefix = NULL;
3354
3355 struct rfapi_import_table *it = NULL;
3356
3357 /*
3358 * Delete matching remote prefixes in holddown
3359 */
3360 if (cda->vn_address.addr_family) {
3361 if (!rfapiRaddr2Qprefix(&cda->vn_address, &pfx_vn))
3362 pVN = &pfx_vn;
3363 }
3364 if (cda->un_address.addr_family) {
3365 if (!rfapiRaddr2Qprefix(&cda->un_address, &pfx_un))
3366 pUN = &pfx_un;
3367 }
3368 if (cda->prefix.family) {
3369 pPrefix = &cda->prefix;
3370 }
3371 if (cda->rfg) {
3372 it = cda->rfg->rfapi_import_table;
3373 }
3374 rfapiDeleteRemotePrefixes(
3375 pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count,
3376 &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count,
3377 &cda->remote_holddown_nve_count);
3378
3379 /*
3380 * Now do local prefixes
3381 */
3382 rfapiDeleteLocalPrefixes(cda);
3383 }
3384
3385 static void print_cleared_stats(struct rfapi_local_reg_delete_arg *cda)
3386 {
3387 struct vty *vty = cda->vty; /* for benefit of VTYNL */
3388
3389 /* Our special element-deleting function counts nves */
3390 if (cda->nves) {
3391 skiplist_free(cda->nves);
3392 cda->nves = NULL;
3393 }
3394 if (cda->failed_pfx_count)
3395 vty_out(vty, "Failed to delete %d prefixes\n",
3396 cda->failed_pfx_count);
3397
3398 /* left as "prefixes" even in single case for ease of machine parsing */
3399 vty_out(vty,
3400 "[Local] Cleared %u registrations, %u prefixes, %u responses from %d NVEs\n",
3401 cda->reg_count, cda->pfx_count, cda->query_count,
3402 cda->nve_count);
3403
3404 /*
3405 * We don't currently allow deletion of active remote prefixes from
3406 * the command line
3407 */
3408
3409 vty_out(vty, "[Holddown] Cleared %u prefixes from %u NVEs\n",
3410 cda->remote_holddown_pfx_count, cda->remote_holddown_nve_count);
3411 }
3412
3413 /*
3414 * Caller has already deleted registrations and queries for this/these
3415 * NVEs. Now we just have to close their descriptors.
3416 */
3417 static void clear_vnc_nve_closer(struct rfapi_local_reg_delete_arg *cda)
3418 {
3419 struct skiplist *sl = cda->nves; /* contains affected NVEs */
3420 struct nve_addr *pKey;
3421 struct nve_addr *pValue;
3422 void *cursor = NULL;
3423 int rc;
3424
3425 if (!sl)
3426 return;
3427
3428 for (rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, &cursor);
3429 !rc; rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue,
3430 &cursor)) {
3431
3432 if (pValue->rfd) {
3433 ((struct rfapi_descriptor *)pValue->rfd)->flags |=
3434 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY;
3435 rfapi_close(pValue->rfd);
3436 }
3437 }
3438 }
3439
3440 DEFUN (clear_vnc_nve_all,
3441 clear_vnc_nve_all_cmd,
3442 "clear vnc nve *",
3443 "clear\n"
3444 "VNC Information\n"
3445 "Clear per NVE information\n"
3446 "For all NVEs\n")
3447 {
3448
3449 struct rfapi_local_reg_delete_arg cda;
3450 int rc;
3451
3452 if ((rc = parse_deleter_args(vty, NULL, NULL, NULL, NULL, NULL, NULL,
3453 NULL, NULL, &cda)))
3454 return rc;
3455
3456 cda.vty = vty;
3457
3458 clear_vnc_responses(&cda);
3459 clear_vnc_prefix(&cda);
3460 clear_vnc_nve_closer(&cda);
3461
3462 print_cleared_stats(&cda);
3463
3464 return 0;
3465 }
3466
3467 DEFUN (clear_vnc_nve_vn_un,
3468 clear_vnc_nve_vn_un_cmd,
3469 "clear vnc nve vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3470 "clear\n"
3471 "VNC Information\n"
3472 "Clear prefix registration information\n"
3473 "VN address of NVE\n"
3474 "For all NVEs\n"
3475 "VN IPv4 interface address\n"
3476 "VN IPv6 interface address\n"
3477 "UN address of NVE\n"
3478 "For all UN addresses\n"
3479 "UN IPv4 interface address\n"
3480 "UN IPv6 interface address\n")
3481 {
3482 struct rfapi_local_reg_delete_arg cda;
3483 int rc;
3484
3485 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], argv[6], NULL,
3486 NULL, NULL, NULL, &cda)))
3487 return rc;
3488
3489 cda.vty = vty;
3490
3491 clear_vnc_responses(&cda);
3492 clear_vnc_prefix(&cda);
3493 clear_vnc_nve_closer(&cda);
3494
3495 print_cleared_stats(&cda);
3496
3497 return 0;
3498 }
3499
3500 DEFUN (clear_vnc_nve_un_vn,
3501 clear_vnc_nve_un_vn_cmd,
3502 "clear vnc nve un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3503 "clear\n"
3504 "VNC Information\n"
3505 "Clear prefix registration information\n"
3506 "UN address of NVE\n"
3507 "For all un NVEs\n"
3508 "UN IPv4 interface address\n"
3509 "UN IPv6 interface address\n"
3510 "VN address of NVE\n"
3511 "For all vn NVEs\n"
3512 "VN IPv4 interface address\n"
3513 "VN IPv6 interface address\n")
3514 {
3515 struct rfapi_local_reg_delete_arg cda;
3516 int rc;
3517
3518 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[6], argv[4], NULL,
3519 NULL, NULL, NULL, &cda)))
3520 return rc;
3521
3522 cda.vty = vty;
3523
3524 clear_vnc_responses(&cda);
3525 clear_vnc_prefix(&cda);
3526 clear_vnc_nve_closer(&cda);
3527
3528 print_cleared_stats(&cda);
3529
3530 return 0;
3531 }
3532
3533 DEFUN (clear_vnc_nve_vn,
3534 clear_vnc_nve_vn_cmd,
3535 "clear vnc nve vn <*|A.B.C.D|X:X::X:X>",
3536 "clear\n"
3537 "VNC Information\n"
3538 "Clear prefix registration information\n"
3539 "VN address of NVE\n"
3540 "All addresses\n"
3541 "VN IPv4 interface address\n"
3542 "VN IPv6 interface address\n")
3543 {
3544 struct rfapi_local_reg_delete_arg cda;
3545 int rc;
3546
3547 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], NULL, NULL,
3548 NULL, NULL, NULL, &cda)))
3549 return rc;
3550
3551 cda.vty = vty;
3552
3553 clear_vnc_responses(&cda);
3554 clear_vnc_prefix(&cda);
3555 clear_vnc_nve_closer(&cda);
3556
3557 print_cleared_stats(&cda);
3558 return 0;
3559 }
3560
3561 DEFUN (clear_vnc_nve_un,
3562 clear_vnc_nve_un_cmd,
3563 "clear vnc nve un <*|A.B.C.D|X:X::X:X>",
3564 "clear\n"
3565 "VNC Information\n"
3566 "Clear prefix registration information\n"
3567 "UN address of NVE\n"
3568 "All un nves\n"
3569 "UN IPv4 interface address\n"
3570 "UN IPv6 interface address\n")
3571 {
3572 struct rfapi_local_reg_delete_arg cda;
3573 int rc;
3574
3575 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[4], NULL,
3576 NULL, NULL, NULL, &cda)))
3577 return rc;
3578
3579 cda.vty = vty;
3580
3581 clear_vnc_responses(&cda);
3582 clear_vnc_prefix(&cda);
3583 clear_vnc_nve_closer(&cda);
3584
3585 print_cleared_stats(&cda);
3586 return 0;
3587 }
3588
3589 /*-------------------------------------------------
3590 * Clear VNC Prefix
3591 *-------------------------------------------------*/
3592
3593 /*
3594 * This function is defined in this file (rather than in rfp_registration.c)
3595 * because here we have access to all the task handles.
3596 */
3597 DEFUN (clear_vnc_prefix_vn_un,
3598 clear_vnc_prefix_vn_un_cmd,
3599 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3600 "clear\n"
3601 "VNC Information\n"
3602 "Clear prefix registration information\n"
3603 "All prefixes\n"
3604 "IPv4 prefix\n"
3605 "IPv6 prefix\n"
3606 "VN address of NVE\n"
3607 "All VN addresses\n"
3608 "VN IPv4 interface address\n"
3609 "VN IPv6 interface address\n"
3610 "UN address of NVE\n"
3611 "All UN addresses\n"
3612 "UN IPv4 interface address\n"
3613 "UN IPv6 interface address\n")
3614 {
3615 struct rfapi_local_reg_delete_arg cda;
3616 int rc;
3617
3618 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], argv[7],
3619 NULL, NULL, NULL, NULL, &cda)))
3620 return rc;
3621 cda.vty = vty;
3622 clear_vnc_prefix(&cda);
3623 print_cleared_stats(&cda);
3624 return 0;
3625 }
3626
3627 DEFUN (clear_vnc_prefix_un_vn,
3628 clear_vnc_prefix_un_vn_cmd,
3629 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3630 "clear\n"
3631 "VNC Information\n"
3632 "Clear prefix registration information\n"
3633 "All prefixes\n"
3634 "IPv4 prefix\n"
3635 "IPv6 prefix\n"
3636 "UN address of NVE\n"
3637 "All UN addresses\n"
3638 "UN IPv4 interface address\n"
3639 "UN IPv6 interface address\n"
3640 "VN address of NVE\n"
3641 "All VN addresses\n"
3642 "VN IPv4 interface address\n"
3643 "VN IPv6 interface address\n")
3644 {
3645 struct rfapi_local_reg_delete_arg cda;
3646 int rc;
3647
3648 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[7], argv[5],
3649 NULL, NULL, NULL, NULL, &cda)))
3650 return rc;
3651 cda.vty = vty;
3652 clear_vnc_prefix(&cda);
3653 print_cleared_stats(&cda);
3654 return 0;
3655 }
3656
3657 DEFUN (clear_vnc_prefix_un,
3658 clear_vnc_prefix_un_cmd,
3659 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X>",
3660 "clear\n"
3661 "VNC Information\n"
3662 "Clear prefix registration information\n"
3663 "All prefixes\n"
3664 "IPv4 prefix\n"
3665 "IPv6 prefix\n"
3666 "UN address of NVE\n"
3667 "All UN addresses\n"
3668 "UN IPv4 interface address\n"
3669 "UN IPv6 interface address\n")
3670 {
3671 struct rfapi_local_reg_delete_arg cda;
3672 int rc;
3673
3674 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, argv[5], NULL,
3675 NULL, NULL, NULL, &cda)))
3676 return rc;
3677 cda.vty = vty;
3678 clear_vnc_prefix(&cda);
3679 print_cleared_stats(&cda);
3680 return 0;
3681 }
3682
3683 DEFUN (clear_vnc_prefix_vn,
3684 clear_vnc_prefix_vn_cmd,
3685 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X>",
3686 "clear\n"
3687 "VNC Information\n"
3688 "Clear prefix registration information\n"
3689 "All prefixes\n"
3690 "IPv4 prefix\n"
3691 "IPv6 prefix\n"
3692 "UN address of NVE\n"
3693 "All VN addresses\n"
3694 "VN IPv4 interface address\n"
3695 "VN IPv6 interface address\n")
3696 {
3697 struct rfapi_local_reg_delete_arg cda;
3698 int rc;
3699
3700 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], NULL, NULL,
3701 NULL, NULL, NULL, &cda)))
3702 return rc;
3703 cda.vty = vty;
3704 clear_vnc_prefix(&cda);
3705 print_cleared_stats(&cda);
3706 return 0;
3707 }
3708
3709 DEFUN (clear_vnc_prefix_all,
3710 clear_vnc_prefix_all_cmd,
3711 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> *",
3712 "clear\n"
3713 "VNC Information\n"
3714 "Clear prefix registration information\n"
3715 "All prefixes\n"
3716 "IPv4 prefix\n"
3717 "IPv6 prefix\n"
3718 "From any NVE\n")
3719 {
3720 struct rfapi_local_reg_delete_arg cda;
3721 int rc;
3722
3723 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, NULL, NULL,
3724 NULL, NULL, NULL, &cda)))
3725 return rc;
3726 cda.vty = vty;
3727 clear_vnc_prefix(&cda);
3728 print_cleared_stats(&cda);
3729 return 0;
3730 }
3731
3732 /*-------------------------------------------------
3733 * Clear VNC MAC
3734 *-------------------------------------------------*/
3735
3736 /*
3737 * This function is defined in this file (rather than in rfp_registration.c)
3738 * because here we have access to all the task handles.
3739 */
3740 DEFUN (clear_vnc_mac_vn_un,
3741 clear_vnc_mac_vn_un_cmd,
3742 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3743 "clear\n"
3744 "VNC Information\n"
3745 "Clear mac registration information\n"
3746 "All macs\n"
3747 "MAC address\n"
3748 "VNI keyword\n"
3749 "Any virtual network identifier\n"
3750 "Virtual network identifier\n"
3751 "VN address of NVE\n"
3752 "All VN addresses\n"
3753 "VN IPv4 interface address\n"
3754 "VN IPv6 interface address\n"
3755 "UN address of NVE\n"
3756 "All UN addresses\n"
3757 "UN IPv4 interface address\n"
3758 "UN IPv6 interface address\n")
3759 {
3760 struct rfapi_local_reg_delete_arg cda;
3761 int rc;
3762
3763 /* pfx vn un L2 VNI */
3764 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], argv[9],
3765 argv[3], argv[5], NULL, NULL, &cda)))
3766 return rc;
3767 cda.vty = vty;
3768 clear_vnc_prefix(&cda);
3769 print_cleared_stats(&cda);
3770 return 0;
3771 }
3772
3773 DEFUN (clear_vnc_mac_un_vn,
3774 clear_vnc_mac_un_vn_cmd,
3775 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3776 "clear\n"
3777 "VNC Information\n"
3778 "Clear mac registration information\n"
3779 "All macs\n"
3780 "MAC address\n"
3781 "VNI keyword\n"
3782 "Any virtual network identifier\n"
3783 "Virtual network identifier\n"
3784 "UN address of NVE\n"
3785 "All UN addresses\n"
3786 "UN IPv4 interface address\n"
3787 "UN IPv6 interface address\n"
3788 "VN address of NVE\n"
3789 "All VN addresses\n"
3790 "VN IPv4 interface address\n"
3791 "VN IPv6 interface address\n")
3792 {
3793 struct rfapi_local_reg_delete_arg cda;
3794 int rc;
3795
3796 /* pfx vn un L2 VNI */
3797 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[9], argv[7],
3798 argv[3], argv[5], NULL, NULL, &cda)))
3799 return rc;
3800 cda.vty = vty;
3801 clear_vnc_prefix(&cda);
3802 print_cleared_stats(&cda);
3803 return 0;
3804 }
3805
3806 DEFUN (clear_vnc_mac_un,
3807 clear_vnc_mac_un_cmd,
3808 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X>",
3809 "clear\n"
3810 "VNC Information\n"
3811 "Clear mac registration information\n"
3812 "All macs\n"
3813 "MAC address\n"
3814 "VNI keyword\n"
3815 "Any virtual network identifier\n"
3816 "Virtual network identifier\n"
3817 "UN address of NVE\n"
3818 "All UN addresses\n"
3819 "UN IPv4 interface address\n"
3820 "UN IPv6 interface address\n")
3821 {
3822 struct rfapi_local_reg_delete_arg cda;
3823 int rc;
3824
3825 /* pfx vn un L2 VNI */
3826 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[7], argv[3],
3827 argv[5], NULL, NULL, &cda)))
3828 return rc;
3829 cda.vty = vty;
3830 clear_vnc_prefix(&cda);
3831 print_cleared_stats(&cda);
3832 return 0;
3833 }
3834
3835 DEFUN (clear_vnc_mac_vn,
3836 clear_vnc_mac_vn_cmd,
3837 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X>",
3838 "clear\n"
3839 "VNC Information\n"
3840 "Clear mac registration information\n"
3841 "All macs\n"
3842 "MAC address\n"
3843 "VNI keyword\n"
3844 "Any virtual network identifier\n"
3845 "Virtual network identifier\n"
3846 "UN address of NVE\n"
3847 "All VN addresses\n"
3848 "VN IPv4 interface address\n"
3849 "VN IPv6 interface address\n")
3850 {
3851 struct rfapi_local_reg_delete_arg cda;
3852 int rc;
3853
3854 /* pfx vn un L2 VNI */
3855 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], NULL, argv[3],
3856 argv[5], NULL, NULL, &cda)))
3857 return rc;
3858 cda.vty = vty;
3859 clear_vnc_prefix(&cda);
3860 print_cleared_stats(&cda);
3861 return 0;
3862 }
3863
3864 DEFUN (clear_vnc_mac_all,
3865 clear_vnc_mac_all_cmd,
3866 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> *",
3867 "clear\n"
3868 "VNC Information\n"
3869 "Clear mac registration information\n"
3870 "All macs\n"
3871 "MAC address\n"
3872 "VNI keyword\n"
3873 "Any virtual network identifier\n"
3874 "Virtual network identifier\n"
3875 "From any NVE\n")
3876 {
3877 struct rfapi_local_reg_delete_arg cda;
3878 int rc;
3879
3880 /* pfx vn un L2 VNI */
3881 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, NULL, argv[3],
3882 argv[5], NULL, NULL, &cda)))
3883 return rc;
3884 cda.vty = vty;
3885 clear_vnc_prefix(&cda);
3886 print_cleared_stats(&cda);
3887 return 0;
3888 }
3889
3890 /*-------------------------------------------------
3891 * Clear VNC MAC PREFIX
3892 *-------------------------------------------------*/
3893
3894 DEFUN (clear_vnc_mac_vn_un_prefix,
3895 clear_vnc_mac_vn_un_prefix_cmd,
3896 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3897 "clear\n"
3898 "VNC Information\n"
3899 "Clear mac registration information\n"
3900 "All macs\n"
3901 "MAC address\n"
3902 "VNI keyword\n"
3903 "Any virtual network identifier\n"
3904 "Virtual network identifier\n"
3905 "VN address of NVE\n"
3906 "All VN addresses\n"
3907 "VN IPv4 interface address\n"
3908 "VN IPv6 interface address\n"
3909 "UN address of NVE\n"
3910 "All UN addresses\n"
3911 "UN IPv4 interface address\n"
3912 "UN IPv6 interface address\n"
3913 "Clear prefix registration information\n"
3914 "All prefixes\n"
3915 "IPv4 prefix\n"
3916 "IPv6 prefix\n")
3917 {
3918 struct rfapi_local_reg_delete_arg cda;
3919 int rc;
3920
3921 /* pfx vn un L2 VNI */
3922 if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[7], argv[9],
3923 argv[3], argv[5], NULL, NULL, &cda)))
3924 return rc;
3925 cda.vty = vty;
3926 clear_vnc_prefix(&cda);
3927 print_cleared_stats(&cda);
3928 return 0;
3929 }
3930
3931 DEFUN (clear_vnc_mac_un_vn_prefix,
3932 clear_vnc_mac_un_vn_prefix_cmd,
3933 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3934 "clear\n"
3935 "VNC Information\n"
3936 "Clear mac registration information\n"
3937 "All macs\n"
3938 "MAC address\n"
3939 "VNI keyword\n"
3940 "Any virtual network identifier\n"
3941 "Virtual network identifier\n"
3942 "UN address of NVE\n"
3943 "All UN addresses\n"
3944 "UN IPv4 interface address\n"
3945 "UN IPv6 interface address\n"
3946 "VN address of NVE\n"
3947 "All VN addresses\n"
3948 "VN IPv4 interface address\n"
3949 "VN IPv6 interface address\n"
3950 "Clear prefix registration information\n"
3951 "All prefixes\n"
3952 "IPv4 prefix\n"
3953 "IPv6 prefix\n"
3954 "Clear prefix registration information\n"
3955 "All prefixes\n"
3956 "IPv4 prefix\n"
3957 "IPv6 prefix\n")
3958 {
3959 struct rfapi_local_reg_delete_arg cda;
3960 int rc;
3961
3962 /* pfx vn un L2 VNI */
3963 if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[9], argv[7],
3964 argv[3], argv[5], NULL, NULL, &cda)))
3965 return rc;
3966 cda.vty = vty;
3967 clear_vnc_prefix(&cda);
3968 print_cleared_stats(&cda);
3969 return 0;
3970 }
3971
3972 DEFUN (clear_vnc_mac_un_prefix,
3973 clear_vnc_mac_un_prefix_cmd,
3974 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3975 "clear\n"
3976 "VNC Information\n"
3977 "Clear mac registration information\n"
3978 "All macs\n"
3979 "MAC address\n"
3980 "VNI keyword\n"
3981 "Any virtual network identifier\n"
3982 "Virtual network identifier\n"
3983 "UN address of NVE\n"
3984 "All UN addresses\n"
3985 "UN IPv4 interface address\n"
3986 "UN IPv6 interface address\n"
3987 "Clear prefix registration information\n"
3988 "All prefixes\n"
3989 "IPv4 Prefix\n"
3990 "IPv6 Prefix\n")
3991 {
3992 struct rfapi_local_reg_delete_arg cda;
3993 int rc;
3994
3995 /* pfx vn un L2 VNI */
3996 if ((rc = parse_deleter_tokens(vty, NULL, argv[9], NULL, argv[7],
3997 argv[3], argv[5], NULL, NULL, &cda)))
3998 return rc;
3999 cda.vty = vty;
4000 clear_vnc_prefix(&cda);
4001 print_cleared_stats(&cda);
4002 return 0;
4003 }
4004
4005 DEFUN (clear_vnc_mac_vn_prefix,
4006 clear_vnc_mac_vn_prefix_cmd,
4007 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
4008 "clear\n"
4009 "VNC Information\n"
4010 "Clear mac registration information\n"
4011 "All macs\n"
4012 "MAC address\n"
4013 "VNI keyword\n"
4014 "Any virtual network identifier\n"
4015 "Virtual network identifier\n"
4016 "UN address of NVE\n"
4017 "All VN addresses\n"
4018 "VN IPv4 interface address\n"
4019 "VN IPv6 interface address\n"
4020 "Clear prefix registration information\n"
4021 "All prefixes\n"
4022 "IPv4 Prefix\n"
4023 "IPv6 Prefix\n")
4024 {
4025 struct rfapi_local_reg_delete_arg cda;
4026 int rc;
4027
4028 /* pfx vn un L2 VNI */
4029 if ((rc = parse_deleter_tokens(vty, NULL, argv[9], argv[7], NULL,
4030 argv[3], argv[5], NULL, NULL, &cda)))
4031 return rc;
4032 cda.vty = vty;
4033 clear_vnc_prefix(&cda);
4034 print_cleared_stats(&cda);
4035 return 0;
4036 }
4037
4038 DEFUN (clear_vnc_mac_all_prefix,
4039 clear_vnc_mac_all_prefix_cmd,
4040 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> prefix <*|A.B.C.D/M|X:X::X:X/M>",
4041 "clear\n"
4042 "VNC Information\n"
4043 "Clear mac registration information\n"
4044 "All macs\n"
4045 "MAC address\n"
4046 "VNI keyword\n"
4047 "Any virtual network identifier\n"
4048 "Virtual network identifier\n"
4049 "UN address of NVE\n"
4050 "All VN addresses\n"
4051 "VN IPv4 interface address\n"
4052 "VN IPv6 interface address\n")
4053 {
4054 struct rfapi_local_reg_delete_arg cda;
4055 int rc;
4056
4057 /* pfx vn un L2 VNI */
4058 if ((rc = parse_deleter_tokens(vty, NULL, argv[7], NULL, NULL, argv[3],
4059 argv[5], NULL, NULL, &cda)))
4060 return rc;
4061 cda.vty = vty;
4062 clear_vnc_prefix(&cda);
4063 print_cleared_stats(&cda);
4064 return 0;
4065 }
4066
4067 /************************************************************************
4068 * Show commands
4069 ************************************************************************/
4070
4071
4072 /* copied from rfp_vty.c */
4073 static int check_and_display_is_vnc_running(struct vty *vty)
4074 {
4075 if (bgp_rfapi_is_vnc_configured(NULL) == 0)
4076 return 1; /* is running */
4077
4078 if (vty) {
4079 vty_out(vty, "VNC is not configured.\n");
4080 }
4081 return 0; /* not running */
4082 }
4083
4084 static int rfapi_vty_show_nve_summary(struct vty *vty,
4085 show_nve_summary_t show_type)
4086 {
4087 struct bgp *bgp_default = bgp_get_default();
4088 struct rfapi *h;
4089 int is_vnc_running = (bgp_rfapi_is_vnc_configured(bgp_default) == 0);
4090
4091 int active_local_routes;
4092 int active_remote_routes;
4093 int holddown_remote_routes;
4094 int imported_remote_routes;
4095
4096 if (!bgp_default)
4097 goto notcfg;
4098
4099 h = bgp_default->rfapi;
4100
4101 if (!h)
4102 goto notcfg;
4103
4104 /* don't show local info if not running RFP */
4105 if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) {
4106
4107 switch (show_type) {
4108
4109 case SHOW_NVE_SUMMARY_ACTIVE_NVES:
4110 vty_out(vty, "%-24s ", "NVEs:");
4111 vty_out(vty, "%-8s %-8u ",
4112 "Active:", h->descriptors.count);
4113 vty_out(vty, "%-8s %-8u ",
4114 "Maximum:", h->stat.max_descriptors);
4115 vty_out(vty, "%-8s %-8u",
4116 "Unknown:", h->stat.count_unknown_nves);
4117 break;
4118
4119 case SHOW_NVE_SUMMARY_REGISTERED:
4120 /*
4121 * NB: With the introduction of L2 route support, we no
4122 * longer have a one-to-one correspondence between
4123 * locally-originated route advertisements and routes in
4124 * the import tables that have local origin. This
4125 * discrepancy arises because a single advertisement
4126 * may contain both an IP prefix and a MAC address.
4127 * Such an advertisement results in two import table
4128 * entries: one indexed by IP prefix, the other indexed
4129 * by MAC address.
4130 *
4131 * TBD: update computation and display of registration
4132 * statistics to reflect the underlying semantics.
4133 */
4134 if (is_vnc_running) {
4135 vty_out(vty, "%-24s ", "Registrations:");
4136 vty_out(vty, "%-8s %-8u ", "Active:",
4137 rfapiApCountAll(bgp_default));
4138 vty_out(vty, "%-8s %-8u ", "Failed:",
4139 h->stat.count_registrations_failed);
4140 vty_out(vty, "%-8s %-8u",
4141 "Total:", h->stat.count_registrations);
4142 vty_out(vty, "\n");
4143 }
4144 vty_out(vty, "%-24s ", "Prefixes registered:");
4145 vty_out(vty, "\n");
4146
4147 rfapiCountAllItRoutes(&active_local_routes,
4148 &active_remote_routes,
4149 &holddown_remote_routes,
4150 &imported_remote_routes);
4151
4152 /* local */
4153 if (is_vnc_running) {
4154 vty_out(vty, " %-20s ", "Locally:");
4155 vty_out(vty, "%-8s %-8u ",
4156 "Active:", active_local_routes);
4157 vty_out(vty, "\n");
4158 }
4159
4160
4161 vty_out(vty, " %-20s ", "Remotely:");
4162 vty_out(vty, "%-8s %-8u",
4163 "Active:", active_remote_routes);
4164 vty_out(vty, "\n");
4165 vty_out(vty, " %-20s ", "In Holddown:");
4166 vty_out(vty, "%-8s %-8u",
4167 "Active:", holddown_remote_routes);
4168 vty_out(vty, "\n");
4169 vty_out(vty, " %-20s ", "Imported:");
4170 vty_out(vty, "%-8s %-8u",
4171 "Active:", imported_remote_routes);
4172 break;
4173
4174 case SHOW_NVE_SUMMARY_QUERIES:
4175 vty_out(vty, "%-24s ", "Queries:");
4176 vty_out(vty, "%-8s %-8u ",
4177 "Active:", rfapi_monitor_count(NULL));
4178 vty_out(vty, "%-8s %-8u ",
4179 "Failed:", h->stat.count_queries_failed);
4180 vty_out(vty, "%-8s %-8u",
4181 "Total:", h->stat.count_queries);
4182 break;
4183
4184 case SHOW_NVE_SUMMARY_RESPONSES:
4185 rfapiRibShowResponsesSummary(vty);
4186
4187 default:
4188 break;
4189 }
4190 vty_out(vty, "\n");
4191 }
4192 return 0;
4193
4194 notcfg:
4195 vty_out(vty, "VNC is not configured.\n");
4196 return CMD_WARNING;
4197 }
4198
4199 static int rfapi_show_nves(struct vty *vty, struct prefix *vn_prefix,
4200 struct prefix *un_prefix)
4201 {
4202 // struct hash *rfds;
4203 // struct rfp_rfapi_descriptor_param param;
4204
4205 struct bgp *bgp_default = bgp_get_default();
4206 struct rfapi *h;
4207 struct listnode *node;
4208 struct rfapi_descriptor *rfd;
4209
4210 int total = 0;
4211 int printed = 0;
4212 int rc;
4213
4214 if (!bgp_default)
4215 goto notcfg;
4216
4217 h = bgp_default->rfapi;
4218
4219 if (!h)
4220 goto notcfg;
4221
4222 rc = rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4223 if (rc)
4224 return rc;
4225
4226 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4227 struct prefix pfx;
4228 char vn_addr_buf[INET6_ADDRSTRLEN] = {
4229 0,
4230 };
4231 char un_addr_buf[INET6_ADDRSTRLEN] = {
4232 0,
4233 };
4234 char age[10];
4235
4236 ++total;
4237
4238 if (vn_prefix) {
4239 assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
4240 if (!prefix_match(vn_prefix, &pfx))
4241 continue;
4242 }
4243
4244 if (un_prefix) {
4245 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
4246 if (!prefix_match(un_prefix, &pfx))
4247 continue;
4248 }
4249
4250 rfapiRfapiIpAddr2Str(&rfd->vn_addr, vn_addr_buf,
4251 INET6_ADDRSTRLEN);
4252 rfapiRfapiIpAddr2Str(&rfd->un_addr, un_addr_buf,
4253 INET6_ADDRSTRLEN);
4254
4255 if (!printed) {
4256 /* print out a header */
4257 vty_out(vty,
4258 " Active Next Hops\n");
4259 vty_out(vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n",
4260 "VN Address", "UN Address", "Regis", "Resps",
4261 "Reach", "Remove", "Age");
4262 }
4263
4264 ++printed;
4265
4266 vty_out(vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n",
4267 vn_addr_buf, un_addr_buf, rfapiApCount(rfd),
4268 rfapi_monitor_count(rfd), rfd->stat_count_nh_reachable,
4269 rfd->stat_count_nh_removal,
4270 rfapiFormatAge(rfd->open_time, age, 10));
4271 }
4272
4273 if (printed > 0 || vn_prefix || un_prefix)
4274 vty_out(vty, "Displayed %d out of %d active NVEs\n", printed,
4275 total);
4276
4277 return 0;
4278
4279 notcfg:
4280 vty_out(vty, "VNC is not configured.\n");
4281 return CMD_WARNING;
4282 }
4283
4284
4285 DEFUN (vnc_show_summary,
4286 vnc_show_summary_cmd,
4287 "show vnc summary",
4288 SHOW_STR
4289 VNC_SHOW_STR
4290 "Display VNC status summary\n")
4291 {
4292 if (!check_and_display_is_vnc_running(vty))
4293 return CMD_SUCCESS;
4294 bgp_rfapi_show_summary(bgp_get_default(), vty);
4295 vty_out(vty, "\n");
4296 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4297 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4298 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_RESPONSES);
4299 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4300 return CMD_SUCCESS;
4301 }
4302
4303 DEFUN (vnc_show_nves,
4304 vnc_show_nves_cmd,
4305 "show vnc nves",
4306 SHOW_STR
4307 VNC_SHOW_STR
4308 "List known NVEs\n")
4309 {
4310 rfapi_show_nves(vty, NULL, NULL);
4311 return CMD_SUCCESS;
4312 }
4313
4314 DEFUN (vnc_show_nves_ptct,
4315 vnc_show_nves_ptct_cmd,
4316 "show vnc nves <vn|un> <A.B.C.D|X:X::X:X>",
4317 SHOW_STR
4318 VNC_SHOW_STR
4319 "List known NVEs\n"
4320 "VN address of NVE\n"
4321 "UN address of NVE\n"
4322 "IPv4 interface address\n"
4323 "IPv6 interface address\n")
4324 {
4325 struct prefix pfx;
4326
4327 if (!check_and_display_is_vnc_running(vty))
4328 return CMD_SUCCESS;
4329
4330 if (!str2prefix(argv[4]->arg, &pfx)) {
4331 vty_out(vty, "Malformed address \"%s\"\n", argv[4]->arg);
4332 return CMD_WARNING;
4333 }
4334 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
4335 vty_out(vty, "Invalid address \"%s\"\n", argv[4]->arg);
4336 return CMD_WARNING;
4337 }
4338
4339 if (argv[3]->arg[0] == 'u') {
4340 rfapi_show_nves(vty, NULL, &pfx);
4341 } else {
4342 rfapi_show_nves(vty, &pfx, NULL);
4343 }
4344
4345 return CMD_SUCCESS;
4346 }
4347
4348 /* adapted from rfp_registration_cache_log() */
4349 static void rfapi_show_registrations(struct vty *vty,
4350 struct prefix *restrict_to, int show_local,
4351 int show_remote, int show_holddown,
4352 int show_imported)
4353 {
4354 int printed = 0;
4355
4356 if (!vty)
4357 return;
4358
4359 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4360
4361 if (show_local) {
4362 /* non-expiring, local */
4363 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 1,
4364 0, 0);
4365 }
4366 if (show_remote) {
4367 /* non-expiring, non-local */
4368 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4369 1, 0);
4370 }
4371 if (show_holddown) {
4372 /* expiring, including local */
4373 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 1, 1,
4374 1, 0);
4375 }
4376 if (show_imported) {
4377 /* non-expiring, non-local */
4378 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4379 1, 1);
4380 }
4381 if (!printed) {
4382 vty_out(vty, "\n");
4383 }
4384 }
4385
4386 DEFUN (vnc_show_registrations_pfx,
4387 vnc_show_registrations_pfx_cmd,
4388 "show vnc registrations [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4389 SHOW_STR
4390 VNC_SHOW_STR
4391 "List active prefix registrations\n"
4392 "Limit output to a particular IPv4 prefix\n"
4393 "Limit output to a particular IPv6 prefix\n"
4394 "Limit output to a particular IPv6 address\n")
4395 {
4396 struct prefix p;
4397 struct prefix *p_addr = NULL;
4398
4399 if (argc > 3) {
4400 if (!str2prefix(argv[3]->arg, &p)) {
4401 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4402 return CMD_SUCCESS;
4403 } else {
4404 p_addr = &p;
4405 }
4406 }
4407
4408 rfapi_show_registrations(vty, p_addr, 1, 1, 1, 1);
4409 return CMD_SUCCESS;
4410 }
4411
4412 DEFUN (vnc_show_registrations_some_pfx,
4413 vnc_show_registrations_some_pfx_cmd,
4414 "show vnc registrations <all|holddown|imported|local|remote> [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4415 SHOW_STR
4416 VNC_SHOW_STR
4417 "List active prefix registrations\n"
4418 "show all registrations\n"
4419 "show only registrations in holddown\n"
4420 "show only imported prefixes\n"
4421 "show only local registrations\n"
4422 "show only remote registrations\n"
4423 "Limit output to a particular prefix or address\n"
4424 "Limit output to a particular prefix or address\n"
4425 "Limit output to a particular prefix or address\n")
4426 {
4427 struct prefix p;
4428 struct prefix *p_addr = NULL;
4429
4430 int show_local = 0;
4431 int show_remote = 0;
4432 int show_holddown = 0;
4433 int show_imported = 0;
4434
4435 if (argc > 4) {
4436 if (!str2prefix(argv[4]->arg, &p)) {
4437 vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4438 return CMD_SUCCESS;
4439 } else {
4440 p_addr = &p;
4441 }
4442 }
4443 switch (argv[3]->arg[0]) {
4444 case 'a':
4445 show_local = 1;
4446 show_remote = 1;
4447 show_holddown = 1;
4448 show_imported = 1;
4449 break;
4450
4451 case 'h':
4452 show_holddown = 1;
4453 break;
4454
4455 case 'i':
4456 show_imported = 1;
4457 break;
4458
4459 case 'l':
4460 show_local = 1;
4461 break;
4462
4463 case 'r':
4464 show_remote = 1;
4465 break;
4466 }
4467
4468 rfapi_show_registrations(vty, p_addr, show_local, show_remote,
4469 show_holddown, show_imported);
4470 return CMD_SUCCESS;
4471 }
4472
4473 DEFUN (vnc_show_responses_pfx,
4474 vnc_show_responses_pfx_cmd,
4475 "show vnc responses [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4476 SHOW_STR
4477 VNC_SHOW_STR
4478 "List recent query responses\n"
4479 "Limit output to a particular IPv4 prefix\n"
4480 "Limit output to a particular IPv6 prefix\n"
4481 "Limit output to a particular IPv6 address\n" )
4482 {
4483 struct prefix p;
4484 struct prefix *p_addr = NULL;
4485
4486 if (argc > 3) {
4487 if (!str2prefix(argv[3]->arg, &p)) {
4488 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4489 return CMD_SUCCESS;
4490 } else {
4491 p_addr = &p;
4492 }
4493 }
4494 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4495
4496 rfapiRibShowResponsesSummary(vty);
4497
4498 rfapiRibShowResponses(vty, p_addr, 0);
4499 rfapiRibShowResponses(vty, p_addr, 1);
4500
4501 return CMD_SUCCESS;
4502 }
4503
4504 DEFUN (vnc_show_responses_some_pfx,
4505 vnc_show_responses_some_pfx_cmd,
4506 "show vnc responses <active|removed> [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4507 SHOW_STR
4508 VNC_SHOW_STR
4509 "List recent query responses\n"
4510 "show only active query responses\n"
4511 "show only removed query responses\n"
4512 "Limit output to a particular IPv4 prefix\n"
4513 "Limit output to a particular IPv6 prefix\n"
4514 "Limit output to a particular IPV6 address\n")
4515 {
4516 struct prefix p;
4517 struct prefix *p_addr = NULL;
4518
4519 int show_active = 0;
4520 int show_removed = 0;
4521
4522 if (!check_and_display_is_vnc_running(vty))
4523 return CMD_SUCCESS;
4524
4525 if (argc > 4) {
4526 if (!str2prefix(argv[4]->arg, &p)) {
4527 vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4528 return CMD_SUCCESS;
4529 } else {
4530 p_addr = &p;
4531 }
4532 }
4533
4534 switch (argv[3]->arg[0]) {
4535 case 'a':
4536 show_active = 1;
4537 break;
4538
4539 case 'r':
4540 show_removed = 1;
4541 break;
4542 }
4543
4544 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4545
4546 rfapiRibShowResponsesSummary(vty);
4547
4548 if (show_active)
4549 rfapiRibShowResponses(vty, p_addr, 0);
4550 if (show_removed)
4551 rfapiRibShowResponses(vty, p_addr, 1);
4552
4553 return CMD_SUCCESS;
4554 }
4555
4556 DEFUN (show_vnc_queries_pfx,
4557 show_vnc_queries_pfx_cmd,
4558 "show vnc queries [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4559 SHOW_STR
4560 VNC_SHOW_STR
4561 "List active queries\n"
4562 "Limit output to a particular IPv4 prefix or address\n"
4563 "Limit output to a particular IPv6 prefix\n"
4564 "Limit output to a particualr IPV6 address\n")
4565 {
4566 struct prefix pfx;
4567 struct prefix *p = NULL;
4568
4569 if (argc > 3) {
4570 if (!str2prefix(argv[3]->arg, &pfx)) {
4571 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4572 return CMD_WARNING;
4573 }
4574 p = &pfx;
4575 }
4576
4577 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4578
4579 return rfapiShowVncQueries(vty, p);
4580 }
4581
4582 DEFUN (vnc_clear_counters,
4583 vnc_clear_counters_cmd,
4584 "clear vnc counters",
4585 CLEAR_STR
4586 VNC_SHOW_STR
4587 "Reset VNC counters\n")
4588 {
4589 struct bgp *bgp_default = bgp_get_default();
4590 struct rfapi *h;
4591 struct listnode *node;
4592 struct rfapi_descriptor *rfd;
4593
4594 if (!bgp_default)
4595 goto notcfg;
4596
4597 h = bgp_default->rfapi;
4598
4599 if (!h)
4600 goto notcfg;
4601
4602 /* per-rfd */
4603 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4604 rfd->stat_count_nh_reachable = 0;
4605 rfd->stat_count_nh_removal = 0;
4606 }
4607
4608 /* global */
4609 memset(&h->stat, 0, sizeof(h->stat));
4610
4611 /*
4612 * 151122 per bug 103, set count_registrations = number active.
4613 * Do same for queries
4614 */
4615 h->stat.count_registrations = rfapiApCountAll(bgp_default);
4616 h->stat.count_queries = rfapi_monitor_count(NULL);
4617
4618 rfapiRibShowResponsesSummaryClear();
4619
4620 return CMD_SUCCESS;
4621
4622 notcfg:
4623 vty_out(vty, "VNC is not configured.\n");
4624 return CMD_WARNING;
4625 }
4626
4627 /************************************************************************
4628 * Add prefix with vrf
4629 *
4630 * add [vrf <vrf-name>] prefix <prefix>
4631 * [rd <value>] [label <value>] [local-preference <0-4294967295>]
4632 ************************************************************************/
4633 void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
4634 {
4635 if (rfg->rfd == NULL) { /* need new rfapi_handle */
4636 /* based on rfapi_open */
4637 struct rfapi_descriptor *rfd;
4638
4639 rfd = XCALLOC(MTYPE_RFAPI_DESC,
4640 sizeof(struct rfapi_descriptor));
4641 rfd->bgp = bgp;
4642 rfg->rfd = rfd;
4643 /* leave most fields empty as will get from (dynamic) config
4644 * when needed */
4645 rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
4646 rfd->cookie = rfg;
4647 if (rfg->vn_prefix.family
4648 && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
4649 rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr);
4650 } else {
4651 memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
4652 rfd->vn_addr.addr_family = AF_INET;
4653 rfd->vn_addr.addr.v4 = bgp->router_id;
4654 }
4655 rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for
4656 lookups */
4657 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
4658 rfg->name);
4659 rfapi_init_and_open(bgp, rfd, rfg);
4660 }
4661 }
4662
4663 /* NOTE: this functions parallels vnc_direct_add_rn_group_rd */
4664 static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,
4665 const char *arg_prefix,
4666 const char *arg_rd, /* optional */
4667 const char *arg_label, /* optional */
4668 const char *arg_pref) /* optional */
4669 {
4670 struct bgp *bgp;
4671 struct rfapi_nve_group_cfg *rfg;
4672 struct prefix pfx;
4673 struct rfapi_ip_prefix rpfx;
4674 uint32_t pref = 0;
4675 struct rfapi_vn_option optary[3];
4676 struct rfapi_vn_option *opt = NULL;
4677 int cur_opt = 0;
4678
4679 bgp = bgp_get_default(); /* assume main instance for now */
4680 if (!bgp) {
4681 vty_out(vty, "No BGP process is configured\n");
4682 return CMD_WARNING_CONFIG_FAILED;
4683 }
4684 if (!bgp->rfapi || !bgp->rfapi_cfg) {
4685 vty_out(vty, "VRF support not configured\n");
4686 return CMD_WARNING_CONFIG_FAILED;
4687 }
4688
4689 rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4690 /* arg checks */
4691 if (!rfg) {
4692 vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4693 arg_vrf);
4694 return CMD_WARNING_CONFIG_FAILED;
4695 }
4696 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
4697 vty_out(vty,
4698 "VRF \"%s\" is missing RT import/export RT configuration.\n",
4699 arg_vrf);
4700 return CMD_WARNING_CONFIG_FAILED;
4701 }
4702 if (!rfg->rd.prefixlen && !arg_rd) {
4703 vty_out(vty,
4704 "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n",
4705 arg_vrf);
4706 return CMD_WARNING_CONFIG_FAILED;
4707 }
4708 if (rfg->label > MPLS_LABEL_MAX && !arg_label) {
4709 vty_out(vty,
4710 "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n",
4711 arg_vrf);
4712 return CMD_WARNING_CONFIG_FAILED;
4713 }
4714 if (!str2prefix(arg_prefix, &pfx)) {
4715 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
4716 return CMD_WARNING_CONFIG_FAILED;
4717 }
4718 rfapiQprefix2Rprefix(&pfx, &rpfx);
4719 memset(optary, 0, sizeof(optary));
4720 if (arg_rd) {
4721 if (opt != NULL)
4722 opt->next = &optary[cur_opt];
4723 opt = &optary[cur_opt++];
4724 opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
4725 if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) {
4726 vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
4727 return CMD_WARNING_CONFIG_FAILED;
4728 }
4729 }
4730 if (rfg->label <= MPLS_LABEL_MAX || arg_label) {
4731 struct rfapi_l2address_option *l2o;
4732 if (opt != NULL)
4733 opt->next = &optary[cur_opt];
4734 opt = &optary[cur_opt++];
4735 opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
4736 l2o = &opt->v.l2addr;
4737 if (arg_label) {
4738 int32_t label;
4739 label = strtoul(arg_label, NULL, 10);
4740 l2o->label = label;
4741 } else
4742 l2o->label = rfg->label;
4743 }
4744 if (arg_pref) {
4745 char *endptr = NULL;
4746 pref = strtoul(arg_pref, &endptr, 10);
4747 if (*endptr != '\0') {
4748 vty_out(vty,
4749 "%% Invalid local-preference value \"%s\"\n",
4750 arg_pref);
4751 return CMD_WARNING_CONFIG_FAILED;
4752 }
4753 }
4754 rpfx.cost = 255 - (pref & 255);
4755 vnc_add_vrf_opener(bgp, rfg);
4756
4757 if (!rfapi_register(rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL,
4758 (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) {
4759 struct rfapi_next_hop_entry *head = NULL;
4760 struct rfapi_next_hop_entry *tail = NULL;
4761 struct rfapi_vn_option *vn_opt_new;
4762
4763 vnc_zlog_debug_verbose("%s: rfapi_register succeeded",
4764 __func__);
4765
4766 if (bgp->rfapi->rfp_methods.local_cb) {
4767 struct rfapi_descriptor *r =
4768 (struct rfapi_descriptor *)rfg->rfd;
4769 vn_opt_new = rfapi_vn_options_dup(opt);
4770
4771 rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
4772 &rpfx, 1,
4773 RFAPI_INFINITE_LIFETIME,
4774 vn_opt_new, &head, &tail);
4775 if (head) {
4776 bgp->rfapi->flags |= RFAPI_INCALLBACK;
4777 (*bgp->rfapi->rfp_methods.local_cb)(head,
4778 r->cookie);
4779 bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
4780 }
4781 head = tail = NULL;
4782 }
4783 vnc_zlog_debug_verbose(
4784 "%s completed, count=%d/%d", __func__,
4785 rfg->rfapi_import_table->local_count[AFI_IP],
4786 rfg->rfapi_import_table->local_count[AFI_IP6]);
4787 return CMD_SUCCESS;
4788 }
4789
4790 vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
4791 vty_out(vty, "Add failed.\n");
4792 return CMD_WARNING_CONFIG_FAILED;
4793 }
4794
4795 DEFUN (add_vrf_prefix_rd_label_pref,
4796 add_vrf_prefix_rd_label_pref_cmd,
4797 "add vrf NAME prefix <A.B.C.D/M|X:X::X:X/M> [{rd ASN:NN_OR_IP-ADDRESS|label (0-1048575)|preference (0-4294967295)}]",
4798 "Add\n"
4799 "To a VRF\n"
4800 "VRF name\n"
4801 "Add/modify prefix related information\n"
4802 "IPv4 prefix\n"
4803 "IPv6 prefix\n"
4804 "Override configured VRF Route Distinguisher\n"
4805 "<as-number>:<number> or <ip-address>:<number>\n"
4806 "Override configured VRF label\n"
4807 "Label Value <0-1048575>\n"
4808 "Set advertised local preference\n"
4809 "local preference (higher=more preferred)\n")
4810 {
4811 char *arg_vrf = argv[2]->arg;
4812 char *arg_prefix = argv[4]->arg;
4813 char *arg_rd = NULL; /* optional */
4814 char *arg_label = NULL; /* optional */
4815 char *arg_pref = NULL; /* optional */
4816 int pargc = 5;
4817 argc--; /* don't parse argument */
4818 while (pargc < argc) {
4819 switch (argv[pargc++]->arg[0]) {
4820 case 'r':
4821 arg_rd = argv[pargc]->arg;
4822 break;
4823 case 'l':
4824 arg_label = argv[pargc]->arg;
4825 break;
4826 case 'p':
4827 arg_pref = argv[pargc]->arg;
4828 break;
4829 default:
4830 break;
4831 }
4832 pargc++;
4833 }
4834
4835 return vnc_add_vrf_prefix(vty, arg_vrf, arg_prefix, arg_rd, arg_label,
4836 arg_pref);
4837 }
4838
4839 /************************************************************************
4840 * del prefix with vrf
4841 *
4842 * clear [vrf <vrf-name>] prefix <prefix> [rd <value>]
4843 ************************************************************************/
4844 static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
4845 {
4846 int count = 0;
4847 afi_t afi = AFI_MAX;
4848 while (afi-- > 0) {
4849 count += rfg->rfapi_import_table->local_count[afi];
4850 }
4851 return count;
4852 }
4853
4854 void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
4855 {
4856 struct rfapi_descriptor *rfd = rfg->rfd;
4857 afi_t afi;
4858
4859 if (rfd == NULL)
4860 return;
4861 /* check if IT is empty */
4862 for (afi = 0;
4863 afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0;
4864 afi++)
4865 ;
4866
4867 if (afi == AFI_MAX) {
4868 vnc_zlog_debug_verbose("%s: closing RFD for VRF %s", __func__,
4869 rfg->name);
4870 rfg->rfd = NULL;
4871 rfapi_close(rfd);
4872 } else {
4873 vnc_zlog_debug_verbose(
4874 "%s: VRF %s afi=%d count=%d", __func__, rfg->name, afi,
4875 rfg->rfapi_import_table->local_count[afi]);
4876 }
4877 }
4878
4879 static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf,
4880 const char *arg_prefix, /* NULL = all */
4881 const char *arg_rd) /* optional */
4882 {
4883 struct rfapi_nve_group_cfg *rfg;
4884 struct rfapi_local_reg_delete_arg cda;
4885 int rc;
4886 int start_count;
4887
4888 if (bgp == NULL)
4889 bgp = bgp_get_default(); /* assume main instance for now */
4890 if (!bgp) {
4891 vty_out(vty, "No BGP process is configured\n");
4892 return CMD_WARNING;
4893 }
4894 if (!bgp->rfapi || !bgp->rfapi_cfg) {
4895 vty_out(vty, "VRF support not configured\n");
4896 return CMD_WARNING;
4897 }
4898 rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4899 /* arg checks */
4900 if (!rfg) {
4901 vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4902 arg_vrf);
4903 return CMD_WARNING;
4904 }
4905 rc = parse_deleter_args(vty, bgp, arg_prefix, NULL, NULL, NULL, NULL,
4906 arg_rd, rfg, &cda);
4907 if (rc != CMD_SUCCESS) /* parse error */
4908 return rc;
4909
4910 start_count = rfapi_cfg_group_it_count(rfg);
4911 clear_vnc_prefix(&cda);
4912 vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count,
4913 start_count);
4914 return CMD_SUCCESS;
4915 }
4916
4917 DEFUN (clear_vrf_prefix_rd,
4918 clear_vrf_prefix_rd_cmd,
4919 "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:NN_OR_IP-ADDRESS]",
4920 "Clear stored data\n"
4921 "From a VRF\n"
4922 "VRF name\n"
4923 "Prefix related information\n"
4924 "IPv4 prefix\n"
4925 "IPv6 prefix\n"
4926 "Specific VRF Route Distinguisher\n"
4927 "<as-number>:<number> or <ip-address>:<number>\n")
4928 {
4929 char *arg_vrf = argv[2]->arg;
4930 char *arg_prefix = NULL; /* optional */
4931 char *arg_rd = NULL; /* optional */
4932 int pargc = 3;
4933 argc--; /* don't check parameter */
4934 while (pargc < argc) {
4935 switch (argv[pargc++]->arg[0]) {
4936 case 'r':
4937 arg_rd = argv[pargc]->arg;
4938 break;
4939 case 'p':
4940 arg_prefix = argv[pargc]->arg;
4941 break;
4942 default:
4943 break;
4944 }
4945 pargc++;
4946 }
4947 return vnc_clear_vrf(vty, NULL, arg_vrf, arg_prefix, arg_rd);
4948 }
4949
4950 DEFUN (clear_vrf_all,
4951 clear_vrf_all_cmd,
4952 "clear vrf NAME all",
4953 "Clear stored data\n"
4954 "From a VRF\n"
4955 "VRF name\n"
4956 "All prefixes\n")
4957 {
4958 char *arg_vrf = argv[2]->arg;
4959 return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL);
4960 }
4961
4962 void rfapi_vty_init()
4963 {
4964 install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd);
4965 install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd);
4966 install_element(ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd);
4967 install_element(ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd);
4968 install_element(ENABLE_NODE, &add_vnc_prefix_lnh_cmd);
4969
4970 install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_cmd);
4971 install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_cmd);
4972 install_element(ENABLE_NODE, &add_vnc_prefix_cost_cmd);
4973 install_element(ENABLE_NODE, &add_vnc_prefix_life_cmd);
4974 install_element(ENABLE_NODE, &add_vnc_prefix_cmd);
4975
4976 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd);
4977 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd);
4978 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd);
4979 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd);
4980 install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd);
4981 install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_cmd);
4982 install_element(ENABLE_NODE, &add_vnc_mac_vni_life_cmd);
4983 install_element(ENABLE_NODE, &add_vnc_mac_vni_cmd);
4984
4985 install_element(ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd);
4986
4987 install_element(ENABLE_NODE, &clear_vnc_nve_all_cmd);
4988 install_element(ENABLE_NODE, &clear_vnc_nve_vn_un_cmd);
4989 install_element(ENABLE_NODE, &clear_vnc_nve_un_vn_cmd);
4990 install_element(ENABLE_NODE, &clear_vnc_nve_vn_cmd);
4991 install_element(ENABLE_NODE, &clear_vnc_nve_un_cmd);
4992
4993 install_element(ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd);
4994 install_element(ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd);
4995 install_element(ENABLE_NODE, &clear_vnc_prefix_un_cmd);
4996 install_element(ENABLE_NODE, &clear_vnc_prefix_vn_cmd);
4997 install_element(ENABLE_NODE, &clear_vnc_prefix_all_cmd);
4998
4999 install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_cmd);
5000 install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_cmd);
5001 install_element(ENABLE_NODE, &clear_vnc_mac_un_cmd);
5002 install_element(ENABLE_NODE, &clear_vnc_mac_vn_cmd);
5003 install_element(ENABLE_NODE, &clear_vnc_mac_all_cmd);
5004
5005 install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd);
5006 install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd);
5007 install_element(ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd);
5008 install_element(ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd);
5009 install_element(ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd);
5010
5011 install_element(ENABLE_NODE, &clear_vrf_prefix_rd_cmd);
5012 install_element(ENABLE_NODE, &clear_vrf_all_cmd);
5013
5014 install_element(ENABLE_NODE, &vnc_clear_counters_cmd);
5015
5016 install_element(VIEW_NODE, &vnc_show_summary_cmd);
5017 install_element(VIEW_NODE, &vnc_show_nves_cmd);
5018 install_element(VIEW_NODE, &vnc_show_nves_ptct_cmd);
5019
5020 install_element(VIEW_NODE, &vnc_show_registrations_pfx_cmd);
5021 install_element(VIEW_NODE, &vnc_show_registrations_some_pfx_cmd);
5022 install_element(VIEW_NODE, &vnc_show_responses_pfx_cmd);
5023 install_element(VIEW_NODE, &vnc_show_responses_some_pfx_cmd);
5024 install_element(VIEW_NODE, &show_vnc_queries_pfx_cmd);
5025 }