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