]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/rfapi_vty.c
Merge branch 'master' into stylechecker
[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 u_int32_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
1167 && bi->extra->vnc.import.aux_prefix.family) {
1168 const char *sp;
1169
1170 sp = rfapi_ntop(
1171 bi->extra->vnc.import.aux_prefix.family,
1172 &bi->extra->vnc.import.aux_prefix.u.prefix,
1173 buf_ntop, BUFSIZ);
1174 buf_ntop[BUFSIZ - 1] = 0;
1175
1176 if (sp && strcmp(buf_vn, sp) != 0) {
1177 fp(out, " IP: %s", sp);
1178 if (nlines == 1)
1179 nlines++;
1180 }
1181 }
1182 }
1183 if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) {
1184 u_int32_t l = decode_label(&bi->extra->label[0]);
1185 if (!MPLS_LABEL_IS_NULL(l)) {
1186 fp(out, " Label: %d", l);
1187 if (nlines == 1)
1188 nlines++;
1189 }
1190 }
1191 if (nlines > 1)
1192 fp(out, "%s", HVTYNL);
1193
1194 return 1;
1195 }
1196
1197 static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
1198 struct rfapi_import_table *it,
1199 struct prefix *prefix_only,
1200 int show_expiring, /* either/or */
1201 int show_local, int show_remote,
1202 int show_imported, /* either/or */
1203 uint32_t *pLni) /* AFI_L2VPN only */
1204 {
1205 afi_t afi;
1206 int printed_rtlist_hdr = 0;
1207
1208 int (*fp)(void *, const char *, ...);
1209 struct vty *vty;
1210 void *out;
1211 const char *vty_newline;
1212 int total = 0;
1213 int printed = 0;
1214
1215 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1216 return printed;
1217
1218 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1219
1220 struct route_node *rn;
1221
1222 if (!it->imported_vpn[afi])
1223 continue;
1224
1225 for (rn = route_top(it->imported_vpn[afi]); rn;
1226 rn = route_next(rn)) {
1227
1228 struct bgp_info *bi;
1229 int count_only;
1230
1231 /* allow for wider or more narrow mask from user */
1232 if (prefix_only && !prefix_match(prefix_only, &rn->p)
1233 && !prefix_match(&rn->p, prefix_only))
1234 count_only = 1;
1235 else
1236 count_only = 0;
1237
1238 for (bi = rn->info; bi; bi = bi->next) {
1239
1240 if (!show_local && RFAPI_LOCAL_BI(bi)) {
1241
1242 /* local route from RFP */
1243 continue;
1244 }
1245
1246 if (!show_remote && !RFAPI_LOCAL_BI(bi)) {
1247
1248 /* remote route */
1249 continue;
1250 }
1251
1252 if (show_expiring
1253 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
1254 continue;
1255
1256 if (!show_expiring
1257 && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
1258 continue;
1259
1260 if (bi->type == ZEBRA_ROUTE_BGP_DIRECT
1261 || bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
1262 if (!show_imported)
1263 continue;
1264 } else {
1265 if (show_imported)
1266 continue;
1267 }
1268
1269 total++;
1270 if (count_only == 1)
1271 continue;
1272 if (!printed_rtlist_hdr) {
1273 const char *agetype = "";
1274 char *s;
1275 const char *type = "";
1276 if (show_imported) {
1277 type = "Imported";
1278 } else {
1279 if (show_expiring) {
1280 type = "Holddown";
1281 } else {
1282 if (RFAPI_LOCAL_BI(
1283 bi)) {
1284 type = "Local";
1285 } else {
1286 type = "Remote";
1287 }
1288 }
1289 }
1290
1291 s = ecommunity_ecom2str(
1292 it->rt_import_list,
1293 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1294
1295 if (pLni) {
1296 fp(out,
1297 "%s[%s] L2VPN Network 0x%x (%u) RT={%s}",
1298 HVTYNL, type, *pLni,
1299 (*pLni & 0xfff), s);
1300 } else {
1301 fp(out, "%s[%s] Prefix RT={%s}",
1302 HVTYNL, type, s);
1303 }
1304 XFREE(MTYPE_ECOMMUNITY_STR, s);
1305
1306 if (it->rfg && it->rfg->name) {
1307 fp(out, " %s \"%s\"",
1308 (it->rfg->type == RFAPI_GROUP_CFG_VRF
1309 ? "VRF"
1310 : "NVE group"),
1311 it->rfg->name);
1312 }
1313 fp(out, "%s", HVTYNL);
1314 if (show_expiring) {
1315 #if RFAPI_REGISTRATIONS_REPORT_AGE
1316 agetype = "Age";
1317 #else
1318 agetype = "Remaining";
1319 #endif
1320 } else if (show_local) {
1321 agetype = "Age";
1322 }
1323
1324 printed_rtlist_hdr = 1;
1325
1326 fp(out,
1327 "%-20s %-15s %-15s %4s %-10s %-10s%s",
1328 (pLni ? "L2 Address/IP" : "Prefix"),
1329 "VN Address", "UN Address", "Cost",
1330 "Lifetime", agetype, HVTYNL);
1331 }
1332 printed += rfapiPrintRemoteRegBi(bgp, stream,
1333 rn, bi);
1334 }
1335 }
1336 }
1337
1338 if (printed > 0) {
1339
1340 const char *type = "prefixes";
1341
1342 if (show_imported) {
1343 type = "imported prefixes";
1344 } else {
1345 if (show_expiring) {
1346 type = "prefixes in holddown";
1347 } else {
1348 if (show_local && !show_remote) {
1349 type = "locally registered prefixes";
1350 } else if (!show_local && show_remote) {
1351 type = "remotely registered prefixes";
1352 }
1353 }
1354 }
1355
1356 fp(out, "Displayed %d out of %d %s%s", printed, total, type,
1357 HVTYNL);
1358 #if DEBUG_SHOW_EXTRA
1359 fp(out, "IT table above: it=%p%s", it, HVTYNL);
1360 #endif
1361 }
1362 return printed;
1363 }
1364
1365
1366 /*
1367 * rfapiShowRemoteRegistrations
1368 *
1369 * Similar to rfapiShowImportTable() above. This function
1370 * is mean to produce the "remote" portion of the output
1371 * of "show vnc registrations".
1372 */
1373 int rfapiShowRemoteRegistrations(void *stream, struct prefix *prefix_only,
1374 int show_expiring, int show_local,
1375 int show_remote, int show_imported)
1376 {
1377 struct bgp *bgp;
1378 struct rfapi *h;
1379 struct rfapi_import_table *it;
1380 int printed = 0;
1381
1382 bgp = bgp_get_default();
1383 if (!bgp) {
1384 return printed;
1385 }
1386
1387 h = bgp->rfapi;
1388 if (!h) {
1389 return printed;
1390 }
1391
1392 for (it = h->imports; it; it = it->next) {
1393 printed += rfapiShowRemoteRegistrationsIt(
1394 bgp, stream, it, prefix_only, show_expiring, show_local,
1395 show_remote, show_imported, NULL);
1396 }
1397
1398 if (h->import_mac) {
1399 void *cursor = NULL;
1400 int rc;
1401 uintptr_t lni_as_ptr;
1402 uint32_t lni;
1403 uint32_t *pLni;
1404
1405 for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1406 (void **)&it, &cursor);
1407 !rc;
1408 rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1409 (void **)&it, &cursor)) {
1410 pLni = NULL;
1411 if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) {
1412 lni = (uint32_t)(lni_as_ptr & 0xffffffff);
1413 pLni = &lni;
1414 }
1415
1416 printed += rfapiShowRemoteRegistrationsIt(
1417 bgp, stream, it, prefix_only, show_expiring,
1418 show_local, show_remote, show_imported, pLni);
1419 }
1420 }
1421
1422 return printed;
1423 }
1424
1425 /*------------------------------------------
1426 * rfapiRfapiIpAddr2Str
1427 *
1428 * UI helper: generate string from rfapi_ip_addr
1429 *
1430 * input:
1431 * a IP v4/v6 address
1432 *
1433 * output
1434 * buf put string here
1435 * bufsize max space to write
1436 *
1437 * return value:
1438 * NULL conversion failed
1439 * non-NULL pointer to buf
1440 --------------------------------------------*/
1441 const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf,
1442 int bufsize)
1443 {
1444 const char *rc = NULL;
1445
1446 switch (a->addr_family) {
1447 case AF_INET:
1448 rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1449 break;
1450 case AF_INET6:
1451 rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1452 break;
1453 }
1454 return rc;
1455 }
1456
1457 void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a)
1458 {
1459 char buf[BUFSIZ];
1460 const char *rc = NULL;
1461
1462 int (*fp)(void *, const char *, ...);
1463 struct vty *vty;
1464 void *out = NULL;
1465 const char *vty_newline;
1466
1467 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1468 return;
1469
1470 rc = rfapiRfapiIpAddr2Str(a, buf, BUFSIZ);
1471
1472 if (rc)
1473 fp(out, "%s", buf);
1474 }
1475
1476 const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf,
1477 int bufsize)
1478 {
1479 struct rfapi_ip_addr *a = &p->prefix;
1480 const char *rc = NULL;
1481
1482 switch (a->addr_family) {
1483 case AF_INET:
1484 rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1485 break;
1486 case AF_INET6:
1487 rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1488 break;
1489 }
1490
1491 if (rc) {
1492 int alen = strlen(buf);
1493 int remaining = bufsize - alen - 1;
1494 int slen;
1495
1496 if (remaining > 0) {
1497 slen = snprintf(buf + alen, remaining, "/%u",
1498 p->length);
1499 if (slen < remaining) /* see man page for snprintf(3) */
1500 return rc;
1501 }
1502 }
1503
1504 return NULL;
1505 }
1506
1507 void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p)
1508 {
1509 char buf[BUFSIZ];
1510 const char *rc;
1511
1512 int (*fp)(void *, const char *, ...);
1513 struct vty *vty;
1514 void *out = NULL;
1515 const char *vty_newline;
1516
1517 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1518 return;
1519
1520 rc = rfapiRfapiIpPrefix2Str(p, buf, BUFSIZ);
1521
1522 if (rc)
1523 fp(out, "%s:%u", buf, p->cost);
1524 else
1525 fp(out, "?/?:?");
1526 }
1527
1528 void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd)
1529 {
1530 char buf[RD_ADDRSTRLEN];
1531
1532 prefix_rd2str(prd, buf, sizeof(buf));
1533 vty_out(vty, "%s", buf);
1534 }
1535
1536 void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
1537 safi_t safi, struct prefix *p)
1538 {
1539 afi_t afi; /* of the VN address */
1540 struct bgp_node *bn;
1541 struct bgp_info *bi;
1542 uint8_t type = ZEBRA_ROUTE_BGP;
1543 struct bgp *bgp;
1544 int printed = 0;
1545 struct prefix_rd prd0;
1546 struct prefix_rd *prd;
1547
1548 /*
1549 * Find the bgp_info in the RIB corresponding to this
1550 * prefix and rfd
1551 */
1552
1553 afi = family2afi(p->family);
1554 assert(afi == AFI_IP || afi == AFI_IP6);
1555
1556 bgp = bgp_get_default(); /* assume 1 instance for now */
1557 assert(bgp);
1558
1559 if (safi == SAFI_ENCAP) {
1560 memset(&prd0, 0, sizeof(prd0));
1561 prd0.family = AF_UNSPEC;
1562 prd0.prefixlen = 64;
1563 prd = &prd0;
1564 } else {
1565 prd = &rfd->rd;
1566 }
1567 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
1568
1569 vty_out(vty, " bn=%p%s", bn, HVTYNL);
1570
1571 for (bi = bn->info; bi; bi = bi->next) {
1572 if (bi->peer == rfd->peer && bi->type == type
1573 && bi->sub_type == BGP_ROUTE_RFP && bi->extra
1574 && bi->extra->vnc.export.rfapi_handle == (void *)rfd) {
1575
1576 rfapiPrintBi(vty, bi);
1577 printed = 1;
1578 }
1579 }
1580
1581 if (!printed) {
1582 vty_out(vty, " --?--%s", HVTYNL);
1583 return;
1584 }
1585 }
1586
1587 void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd)
1588 {
1589 /* pHD un-addr vn-addr pCB cookie rd lifetime */
1590 /* RT export list */
1591 /* RT import list */
1592 /* list of advertised prefixes */
1593 /* dump import table */
1594
1595 char *s;
1596 void *cursor;
1597 int rc;
1598 afi_t afi;
1599 struct rfapi_adb *adb;
1600 char buf[PREFIX_STRLEN];
1601
1602 vty_out(vty, "%-10p ", rfd);
1603 rfapiPrintRfapiIpAddr(vty, &rfd->un_addr);
1604 vty_out(vty, " ");
1605 rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
1606 vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
1607 rfapiPrintRd(vty, &rfd->rd);
1608 vty_out(vty, " %d", rfd->response_lifetime);
1609 vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
1610 vty_out(vty, "%s", HVTYNL);
1611
1612 vty_out(vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL);
1613
1614 /* export RT list */
1615 if (rfd->rt_export_list) {
1616 s = ecommunity_ecom2str(rfd->rt_export_list,
1617 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1618 vty_out(vty, " Export %s%s", s, HVTYNL);
1619 XFREE(MTYPE_ECOMMUNITY_STR, s);
1620 } else {
1621 vty_out(vty, " Export (nil)%s", HVTYNL);
1622 }
1623
1624 /* import RT list */
1625 if (rfd->import_table) {
1626 s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1627 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1628 vty_out(vty, " Import %s%s", s, HVTYNL);
1629 XFREE(MTYPE_ECOMMUNITY_STR, s);
1630 } else {
1631 vty_out(vty, " Import (nil)%s", HVTYNL);
1632 }
1633
1634 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1635 u_char family;
1636
1637 family = afi2family(afi);
1638 if (!family)
1639 continue;
1640
1641 cursor = NULL;
1642 for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1643 (void **)&adb, &cursor);
1644 rc == 0;
1645 rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1646 (void **)&adb, &cursor)) {
1647
1648 /* group like family prefixes together in output */
1649 if (family != adb->u.s.prefix_ip.family)
1650 continue;
1651
1652 prefix2str(&adb->u.s.prefix_ip, buf, sizeof(buf));
1653
1654 vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL);
1655 rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1656 &adb->u.s.prefix_ip);
1657 }
1658 }
1659 for (rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1660 (void **)&adb, &cursor);
1661 rc == 0; rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1662 (void **)&adb, &cursor)) {
1663
1664 prefix2str(&adb->u.s.prefix_eth, buf, sizeof(buf));
1665
1666 vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL);
1667
1668 /* TBD update the following function to print ethernet info */
1669 /* Also need to pass/use rd */
1670 rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1671 &adb->u.s.prefix_ip);
1672 }
1673 vty_out(vty, "%s", HVTYNL);
1674 }
1675
1676 /*
1677 * test scripts rely on first line for each nve starting in 1st column,
1678 * leading whitespace for additional detail of that nve
1679 */
1680 void rfapiPrintMatchingDescriptors(struct vty *vty, struct prefix *vn_prefix,
1681 struct prefix *un_prefix)
1682 {
1683 struct bgp *bgp;
1684 struct rfapi *h;
1685 struct listnode *ln;
1686 struct rfapi_descriptor *rfd;
1687 int printed = 0;
1688
1689 bgp = bgp_get_default(); /* assume 1 instance for now */
1690 if (!bgp)
1691 return;
1692
1693 h = bgp->rfapi;
1694 assert(h);
1695
1696 for (ln = listhead(&h->descriptors); ln; ln = listnextnode(ln)) {
1697 rfd = listgetdata(ln);
1698
1699 struct prefix pfx;
1700
1701 if (vn_prefix) {
1702 assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
1703 if (!prefix_match(vn_prefix, &pfx))
1704 continue;
1705 }
1706
1707 if (un_prefix) {
1708 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
1709 if (!prefix_match(un_prefix, &pfx))
1710 continue;
1711 }
1712
1713 if (!printed) {
1714 /* print column header */
1715 vty_out(vty, "%s %s %s %s %s %s %s %s%s", "descriptor",
1716 "un-addr", "vn-addr", "callback", "cookie",
1717 "RD", "lifetime", "group", HVTYNL);
1718 }
1719 rfapiPrintDescriptor(vty, rfd);
1720 printed = 1;
1721 }
1722 }
1723
1724
1725 /*
1726 * Parse an address and put into a struct prefix
1727 */
1728 int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, struct prefix *p)
1729 {
1730 if (!str2prefix(str, p)) {
1731 vty_out(vty, "Malformed address \"%s\"%s", str, HVTYNL);
1732 return CMD_WARNING;
1733 }
1734 switch (p->family) {
1735 case AF_INET:
1736 if (p->prefixlen != 32) {
1737 vty_out(vty, "Not a host address: \"%s\"%s", str,
1738 HVTYNL);
1739 return CMD_WARNING;
1740 }
1741 break;
1742 case AF_INET6:
1743 if (p->prefixlen != 128) {
1744 vty_out(vty, "Not a host address: \"%s\"%s", str,
1745 HVTYNL);
1746 return CMD_WARNING;
1747 }
1748 break;
1749 default:
1750 vty_out(vty, "Invalid address \"%s\"%s", str, HVTYNL);
1751 return CMD_WARNING;
1752 }
1753 return 0;
1754 }
1755
1756 int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str,
1757 struct rfapi_ip_addr *hai)
1758 {
1759 struct prefix pfx;
1760 int rc;
1761
1762 rc = rfapiCliGetPrefixAddr(vty, str, &pfx);
1763 if (rc)
1764 return rc;
1765
1766 hai->addr_family = pfx.family;
1767 if (pfx.family == AF_INET)
1768 hai->addr.v4 = pfx.u.prefix4;
1769 else
1770 hai->addr.v6 = pfx.u.prefix6;
1771
1772 return 0;
1773 }
1774
1775 /*
1776 * Note: this function does not flush vty output, so if it is called
1777 * with a stream pointing to a vty, the user will have to type something
1778 * before the callback output shows up
1779 */
1780 void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops)
1781 {
1782 struct rfapi_next_hop_entry *nh;
1783 int count;
1784
1785 int (*fp)(void *, const char *, ...);
1786 struct vty *vty;
1787 void *out;
1788 const char *vty_newline;
1789
1790 #define REMAIN (BUFSIZ - (p-line))
1791 #define INCP {p += (r > REMAIN)? REMAIN: r;}
1792
1793 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1794 return;
1795
1796 for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) {
1797
1798 char line[BUFSIZ];
1799 char *p = line;
1800 int r;
1801
1802 r = snprintf(p, REMAIN, "%3d pfx=", count);
1803 INCP;
1804
1805 if (rfapiRfapiIpPrefix2Str(&nh->prefix, p, REMAIN)) {
1806 /* it fit, so count length */
1807 r = strlen(p);
1808 } else {
1809 /* didn't fit */
1810 goto truncate;
1811 }
1812 INCP;
1813
1814 r = snprintf(p, REMAIN, ", un=");
1815 INCP;
1816
1817 if (rfapiRfapiIpAddr2Str(&nh->un_address, p, REMAIN)) {
1818 /* it fit, so count length */
1819 r = strlen(p);
1820 } else {
1821 /* didn't fit */
1822 goto truncate;
1823 }
1824 INCP;
1825
1826 r = snprintf(p, REMAIN, ", vn=");
1827 INCP;
1828
1829 if (rfapiRfapiIpAddr2Str(&nh->vn_address, p, REMAIN)) {
1830 /* it fit, so count length */
1831 r = strlen(p);
1832 } else {
1833 /* didn't fit */
1834 goto truncate;
1835 }
1836 INCP;
1837
1838 truncate:
1839 line[BUFSIZ - 1] = 0;
1840 fp(out, "%s%s", line, HVTYNL);
1841
1842 /*
1843 * options
1844 */
1845 if (nh->vn_options) {
1846 struct rfapi_vn_option *vo;
1847 char offset[] = " ";
1848
1849 for (vo = nh->vn_options; vo; vo = vo->next) {
1850 char pbuf[100];
1851
1852 switch (vo->type) {
1853 case RFAPI_VN_OPTION_TYPE_L2ADDR:
1854 rfapiEthAddr2Str(&vo->v.l2addr.macaddr,
1855 pbuf, sizeof(pbuf));
1856 fp(out,
1857 "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s",
1858 offset, pbuf,
1859 (vo->v.l2addr.label & 0x00ffffff),
1860 (vo->v.l2addr.logical_net_id
1861 & 0x00ffffff),
1862 vo->v.l2addr.local_nve_id, HVTYNL);
1863 break;
1864
1865 case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP:
1866 prefix2str(&vo->v.local_nexthop.addr,
1867 pbuf, sizeof(pbuf));
1868 fp(out, "%sLNH %s cost=%d%s", offset,
1869 pbuf, vo->v.local_nexthop.cost,
1870 HVTYNL);
1871 break;
1872
1873 default:
1874 fp(out,
1875 "%svn option type %d (unknown)%s",
1876 offset, vo->type, HVTYNL);
1877 break;
1878 }
1879 }
1880 }
1881 if (nh->un_options) {
1882 struct rfapi_un_option *uo;
1883 char offset[] = " ";
1884
1885 for (uo = nh->un_options; uo; uo = uo->next) {
1886 switch (uo->type) {
1887 case RFAPI_UN_OPTION_TYPE_TUNNELTYPE:
1888 rfapi_print_tunneltype_option(
1889 stream, 8, &uo->v.tunnel);
1890 break;
1891 default:
1892 fp(out, "%sUN Option type %d%s", offset,
1893 uo->type, vty_newline);
1894 break;
1895 }
1896 }
1897 }
1898 }
1899 }
1900
1901 /***********************************************************************
1902 * STATIC ROUTES
1903 ***********************************************************************/
1904
1905 /*
1906 * Add another nexthop to the NHL
1907 */
1908 static void rfapiAddDeleteLocalRfpPrefix(struct rfapi_ip_addr *un_addr,
1909 struct rfapi_ip_addr *vn_addr,
1910 struct rfapi_ip_prefix *rprefix,
1911 int is_add,
1912 uint32_t lifetime, /* add only */
1913 struct rfapi_vn_option *vn_options,
1914 struct rfapi_next_hop_entry **head,
1915 struct rfapi_next_hop_entry **tail)
1916 {
1917 struct rfapi_next_hop_entry *new;
1918
1919 /*
1920 * construct NHL
1921 */
1922
1923 new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry));
1924 new->prefix = *rprefix;
1925 new->un_address = *un_addr;
1926 new->vn_address = *vn_addr;
1927
1928 new->vn_options = vn_options;
1929 if (is_add) {
1930 new->lifetime = lifetime;
1931 } else {
1932 new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1933 }
1934
1935 if (*tail)
1936 (*tail)->next = new;
1937 *tail = new;
1938 if (!*head) {
1939 *head = new;
1940 }
1941 }
1942
1943
1944 static int
1945 register_add(struct vty *vty, struct cmd_token *carg_prefix,
1946 struct cmd_token *carg_vn, struct cmd_token *carg_un,
1947 struct cmd_token *carg_cost, /* optional */
1948 struct cmd_token *carg_lifetime, /* optional */
1949 struct cmd_token *carg_macaddr, /* optional */
1950 struct cmd_token
1951 *carg_vni, /* mac present=>mandatory Virtual Network ID */
1952 int argc, struct cmd_token **argv)
1953 {
1954 const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
1955 const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
1956 const char *arg_un = carg_un ? carg_un->arg : NULL;
1957 const char *arg_cost = carg_cost ? carg_cost->arg : NULL;
1958 const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL;
1959 const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL;
1960 const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
1961 struct rfapi_ip_addr vn_address;
1962 struct rfapi_ip_addr un_address;
1963 struct prefix pfx;
1964 struct rfapi_ip_prefix rpfx;
1965 uint32_t cost;
1966 uint32_t lnh_cost;
1967 uint32_t lifetime;
1968 rfapi_handle rfd;
1969 struct rfapi_vn_option optary[10]; /* XXX must be big enough */
1970 struct rfapi_vn_option *opt = NULL;
1971 int opt_next = 0;
1972
1973 int rc = CMD_WARNING_CONFIG_FAILED;
1974 char *endptr;
1975 struct bgp *bgp;
1976 struct rfapi *h;
1977 struct rfapi_cfg *rfapi_cfg;
1978
1979 const char *arg_lnh = NULL;
1980 const char *arg_lnh_cost = NULL;
1981
1982 bgp = bgp_get_default(); /* assume 1 instance for now */
1983 if (!bgp) {
1984 if (vty)
1985 vty_out(vty, "BGP not configured\n");
1986 return CMD_WARNING_CONFIG_FAILED;
1987 }
1988
1989 h = bgp->rfapi;
1990 rfapi_cfg = bgp->rfapi_cfg;
1991 if (!h || !rfapi_cfg) {
1992 if (vty)
1993 vty_out(vty, "RFAPI not configured\n");
1994 return CMD_WARNING_CONFIG_FAILED;
1995 }
1996
1997 for (; argc; --argc, ++argv) {
1998 if (strmatch(argv[0]->text, "local-next-hop")) {
1999 if (arg_lnh) {
2000 vty_out(vty,
2001 "local-next-hop specified more than once\n");
2002 return CMD_WARNING_CONFIG_FAILED;
2003 }
2004 if (argc <= 1) {
2005 vty_out(vty,
2006 "Missing parameter for local-next-hop\n");
2007 return CMD_WARNING_CONFIG_FAILED;
2008 }
2009 ++argv, --argc;
2010 arg_lnh = argv[0]->arg;
2011 }
2012 if (strmatch(argv[0]->text, "local-cost")) {
2013 if (arg_lnh_cost) {
2014 vty_out(vty,
2015 "local-cost specified more than once\n");
2016 return CMD_WARNING_CONFIG_FAILED;
2017 }
2018 if (argc <= 1) {
2019 vty_out(vty,
2020 "Missing parameter for local-cost\n");
2021 return CMD_WARNING_CONFIG_FAILED;
2022 }
2023 ++argv, --argc;
2024 arg_lnh_cost = argv[0]->arg;
2025 }
2026 }
2027
2028 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, &vn_address)))
2029 goto fail;
2030 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, &un_address)))
2031 goto fail;
2032
2033 /* arg_prefix is optional if mac address is given */
2034 if (arg_macaddr && !arg_prefix) {
2035 /*
2036 * fake up a 0/32 or 0/128 prefix
2037 */
2038 switch (vn_address.addr_family) {
2039 case AF_INET:
2040 arg_prefix = "0.0.0.0/32";
2041 break;
2042 case AF_INET6:
2043 arg_prefix = "0::0/128";
2044 break;
2045 default:
2046 vty_out(vty,
2047 "Internal error, unknown VN address family\n");
2048 return CMD_WARNING_CONFIG_FAILED;
2049 }
2050 }
2051
2052 if (!str2prefix(arg_prefix, &pfx)) {
2053 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2054 goto fail;
2055 }
2056 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2057 vty_out(vty, "prefix \"%s\" has invalid address family\n",
2058 arg_prefix);
2059 goto fail;
2060 }
2061
2062
2063 memset(optary, 0, sizeof(optary));
2064
2065 if (arg_cost) {
2066 endptr = NULL;
2067 cost = strtoul(arg_cost, &endptr, 10);
2068 if (*endptr != '\0' || cost > 255) {
2069 vty_out(vty, "%% Invalid %s value\n", "cost");
2070 goto fail;
2071 }
2072 } else {
2073 cost = 255;
2074 }
2075
2076 if (arg_lifetime) {
2077 if (!strcmp(arg_lifetime, "infinite")) {
2078 lifetime = RFAPI_INFINITE_LIFETIME;
2079 } else {
2080 endptr = NULL;
2081 lifetime = strtoul(arg_lifetime, &endptr, 10);
2082 if (*endptr != '\0') {
2083 vty_out(vty, "%% Invalid %s value\n",
2084 "lifetime");
2085 goto fail;
2086 }
2087 }
2088 } else {
2089 lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */
2090 }
2091
2092 if (arg_lnh_cost) {
2093 if (!arg_lnh) {
2094 vty_out(vty,
2095 "%% %s may only be specified with local-next-hop\n",
2096 "local-cost");
2097 goto fail;
2098 }
2099 endptr = NULL;
2100 lnh_cost = strtoul(arg_lnh_cost, &endptr, 10);
2101 if (*endptr != '\0' || lnh_cost > 255) {
2102 vty_out(vty, "%% Invalid %s value\n", "local-cost");
2103 goto fail;
2104 }
2105 } else {
2106 lnh_cost = 255;
2107 }
2108
2109 if (arg_lnh) {
2110 if (!arg_prefix) {
2111 vty_out(vty,
2112 "%% %s may only be specified with prefix\n",
2113 "local-next-hop");
2114 goto fail;
2115 }
2116 if ((rc = rfapiCliGetPrefixAddr(
2117 vty, arg_lnh,
2118 &optary[opt_next].v.local_nexthop.addr))) {
2119
2120 goto fail;
2121 }
2122
2123 optary[opt_next].v.local_nexthop.cost = lnh_cost;
2124 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP;
2125
2126 if (opt_next) {
2127 optary[opt_next - 1].next = optary + opt_next;
2128 } else {
2129 opt = optary;
2130 }
2131 ++opt_next;
2132 }
2133
2134 if (arg_vni && !arg_macaddr) {
2135 vty_out(vty, "%% %s may only be specified with mac address\n",
2136 "virtual-network-identifier");
2137 goto fail;
2138 }
2139
2140 if (arg_macaddr) {
2141 if (!arg_vni) {
2142 vty_out(vty,
2143 "Missing \"vni\" parameter (mandatory with mac)\n");
2144 return CMD_WARNING_CONFIG_FAILED;
2145 }
2146 optary[opt_next].v.l2addr.logical_net_id =
2147 strtoul(arg_vni, NULL, 10);
2148
2149 if ((rc = rfapiStr2EthAddr(
2150 arg_macaddr,
2151 &optary[opt_next].v.l2addr.macaddr))) {
2152 vty_out(vty, "Invalid %s value\n", "mac address");
2153 goto fail;
2154 }
2155 /* TBD label, NVE ID */
2156
2157 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
2158
2159 if (opt_next) {
2160 optary[opt_next - 1].next = optary + opt_next;
2161 } else {
2162 opt = optary;
2163 }
2164 ++opt_next;
2165 }
2166
2167 vnc_zlog_debug_verbose(
2168 "%s: vn=%s, un=%s, prefix=%s, cost=%s, lifetime=%s, lnh=%s",
2169 __func__, arg_vn, arg_un, arg_prefix,
2170 (arg_cost ? arg_cost : "NULL"),
2171 (arg_lifetime ? arg_lifetime : "NULL"),
2172 (arg_lnh ? arg_lnh : "NULL"));
2173
2174 rfapiQprefix2Rprefix(&pfx, &rpfx);
2175
2176 rpfx.cost = cost & 255;
2177
2178 /* look up rf descriptor, call open if it doesn't exist */
2179 rc = rfapi_find_rfd(bgp, &vn_address, &un_address,
2180 (struct rfapi_descriptor **)&rfd);
2181 if (rc) {
2182 if (ENOENT == rc) {
2183 struct rfapi_un_option uo;
2184
2185 /*
2186 * flag descriptor as provisionally opened for static
2187 * route
2188 * registration so that we can fix up the other
2189 * parameters
2190 * when the real open comes along
2191 */
2192 memset(&uo, 0, sizeof(uo));
2193 uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL;
2194
2195 rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp),
2196 &vn_address, &un_address,
2197 &uo, /* flags */
2198 NULL, NULL, /* no userdata */
2199 &rfd);
2200 if (rc) {
2201 vty_out(vty,
2202 "Can't open session for this NVE: %s\n",
2203 rfapi_error_str(rc));
2204 rc = CMD_WARNING_CONFIG_FAILED;
2205 goto fail;
2206 }
2207 } else {
2208 vty_out(vty, "Can't find session for this NVE: %s\n",
2209 rfapi_error_str(rc));
2210 goto fail;
2211 }
2212 }
2213
2214 rc = rfapi_register(rfd, &rpfx, lifetime, NULL, opt,
2215 RFAPI_REGISTER_ADD);
2216 if (!rc) {
2217 struct rfapi_next_hop_entry *head = NULL;
2218 struct rfapi_next_hop_entry *tail = NULL;
2219 struct rfapi_vn_option *vn_opt_new;
2220
2221 vnc_zlog_debug_verbose(
2222 "%s: rfapi_register succeeded, returning 0", __func__);
2223
2224 if (h->rfp_methods.local_cb) {
2225 struct rfapi_descriptor *r =
2226 (struct rfapi_descriptor *)rfd;
2227 vn_opt_new = rfapi_vn_options_dup(opt);
2228
2229 rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
2230 &rpfx, 1, lifetime,
2231 vn_opt_new, &head, &tail);
2232 if (head) {
2233 h->flags |= RFAPI_INCALLBACK;
2234 (*h->rfp_methods.local_cb)(head, r->cookie);
2235 h->flags &= ~RFAPI_INCALLBACK;
2236 }
2237 head = tail = NULL;
2238 }
2239 return 0;
2240 }
2241
2242 vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
2243 vty_out(vty, "\n");
2244 vty_out(vty, "Registration failed.\n");
2245 vty_out(vty,
2246 "Confirm that either the VN or UN address matches a configured NVE group.\n");
2247 return CMD_WARNING_CONFIG_FAILED;
2248
2249 fail:
2250 vnc_zlog_debug_verbose("%s: fail, rc=%d", __func__, rc);
2251 return rc;
2252 }
2253
2254 /************************************************************************
2255 * Add prefix With LNH_OPTIONS...
2256 ************************************************************************/
2257 DEFUN (add_vnc_prefix_cost_life_lnh,
2258 add_vnc_prefix_cost_life_lnh_cmd,
2259 "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...",
2260 "Add registration\n"
2261 "VNC Information\n"
2262 "Add/modify prefix related information\n"
2263 "IPv4 prefix\n"
2264 "IPv6 prefix\n"
2265 "VN address of NVE\n"
2266 "VN IPv4 interface address\n"
2267 "VN IPv6 interface address\n"
2268 "UN address of NVE\n"
2269 "UN IPv4 interface address\n"
2270 "UN IPv6 interface address\n"
2271 "Administrative cost [default: 255]\n"
2272 "Administrative cost\n"
2273 "Registration lifetime [default: infinite]\n"
2274 "Lifetime value in seconds\n"
2275 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2276 {
2277 /* pfx vn un cost life */
2278 return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2279 /* mac vni */
2280 NULL, NULL, argc - 12, argv + 12);
2281 }
2282
2283 DEFUN (add_vnc_prefix_life_cost_lnh,
2284 add_vnc_prefix_life_cost_lnh_cmd,
2285 "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...",
2286 "Add registration\n"
2287 "VNC Information\n"
2288 "Add/modify prefix related information\n"
2289 "IPv4 prefix\n"
2290 "IPv6 prefix\n"
2291 "VN address of NVE\n"
2292 "VN IPv4 interface address\n"
2293 "VN IPv6 interface address\n"
2294 "UN address of NVE\n"
2295 "UN IPv4 interface address\n"
2296 "UN IPv6 interface address\n"
2297 "Registration lifetime [default: infinite]\n"
2298 "Lifetime value in seconds\n"
2299 "Administrative cost [default: 255]\n"
2300 "Administrative cost\n"
2301 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2302 {
2303 /* pfx vn un cost life */
2304 return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2305 /* mac vni */
2306 NULL, NULL, argc - 12, argv + 12);
2307 }
2308
2309 DEFUN (add_vnc_prefix_cost_lnh,
2310 add_vnc_prefix_cost_lnh_cmd,
2311 "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...",
2312 "Add registration\n"
2313 "VNC Information\n"
2314 "Add/modify prefix related information\n"
2315 "IPv4 prefix\n"
2316 "IPv6 prefix\n"
2317 "VN address of NVE\n"
2318 "VN IPv4 interface address\n"
2319 "VN IPv6 interface address\n"
2320 "UN address of NVE\n"
2321 "UN IPv4 interface address\n"
2322 "UN IPv6 interface address\n"
2323 "Administrative cost [default: 255]\n"
2324 "Administrative cost\n"
2325 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2326 {
2327 /* pfx vn un cost life */
2328 return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2329 /* mac vni */
2330 NULL, NULL, argc - 10, argv + 10);
2331 }
2332
2333 DEFUN (add_vnc_prefix_life_lnh,
2334 add_vnc_prefix_life_lnh_cmd,
2335 "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...",
2336 "Add registration\n"
2337 "VNC Information\n"
2338 "Add/modify prefix related information\n"
2339 "IPv4 prefix\n"
2340 "IPv6 prefix\n"
2341 "VN address of NVE\n"
2342 "VN IPv4 interface address\n"
2343 "VN IPv6 interface address\n"
2344 "UN address of NVE\n"
2345 "UN IPv4 interface address\n"
2346 "UN IPv6 interface address\n"
2347 "Registration lifetime [default: infinite]\n"
2348 "Lifetime value in seconds\n"
2349 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2350 {
2351 /* pfx vn un cost life */
2352 return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2353 /* mac vni */
2354 NULL, NULL, argc - 10, argv + 10);
2355 }
2356
2357 DEFUN (add_vnc_prefix_lnh,
2358 add_vnc_prefix_lnh_cmd,
2359 "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...",
2360 "Add registration\n"
2361 "VNC Information\n"
2362 "Add/modify prefix related information\n"
2363 "IPv4 prefix\n"
2364 "IPv6 prefix\n"
2365 "VN address of NVE\n"
2366 "VN IPv4 interface address\n"
2367 "VN IPv6 interface address\n"
2368 "UN address of NVE\n"
2369 "UN IPv4 interface address\n"
2370 "UN IPv6 interface address\n"
2371 "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2372 {
2373 /* pfx vn un cost life */
2374 return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2375 /* mac vni */
2376 NULL, NULL, argc - 8, argv + 8);
2377 }
2378
2379 /************************************************************************
2380 * Add prefix Without LNH_OPTIONS...
2381 ************************************************************************/
2382 DEFUN (add_vnc_prefix_cost_life,
2383 add_vnc_prefix_cost_life_cmd,
2384 "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)",
2385 "Add registration\n"
2386 "VNC Information\n"
2387 "Add/modify prefix related information\n"
2388 "IPv4 prefix\n"
2389 "IPv6 prefix\n"
2390 "VN address of NVE\n"
2391 "VN IPv4 interface address\n"
2392 "VN IPv6 interface address\n"
2393 "UN address of NVE\n"
2394 "UN IPv4 interface address\n"
2395 "UN IPv6 interface address\n"
2396 "Administrative cost [default: 255]\n"
2397 "Administrative cost\n"
2398 "Registration lifetime [default: infinite]\n"
2399 "Lifetime value in seconds\n")
2400 {
2401 /* pfx vn un cost life */
2402 return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2403 /* mac vni */
2404 NULL, NULL, 0, NULL);
2405 }
2406
2407 DEFUN (add_vnc_prefix_life_cost,
2408 add_vnc_prefix_life_cost_cmd,
2409 "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)",
2410 "Add registration\n"
2411 "VNC Information\n"
2412 "Add/modify prefix related information\n"
2413 "IPv4 prefix\n"
2414 "IPv6 prefix\n"
2415 "VN address of NVE\n"
2416 "VN IPv4 interface address\n"
2417 "VN IPv6 interface address\n"
2418 "UN address of NVE\n"
2419 "UN IPv4 interface address\n"
2420 "UN IPv6 interface address\n"
2421 "Registration lifetime [default: infinite]\n"
2422 "Lifetime value in seconds\n"
2423 "Administrative cost [default: 255]\n"
2424 "Administrative cost\n")
2425 {
2426 /* pfx vn un cost life */
2427 return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2428 /* mac vni */
2429 NULL, NULL, 0, NULL);
2430 }
2431
2432 DEFUN (add_vnc_prefix_cost,
2433 add_vnc_prefix_cost_cmd,
2434 "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)",
2435 "Add registration\n"
2436 "VNC Information\n"
2437 "Add/modify prefix related information\n"
2438 "IPv4 prefix\n"
2439 "IPv6 prefix\n"
2440 "VN address of NVE\n"
2441 "VN IPv4 interface address\n"
2442 "VN IPv6 interface address\n"
2443 "UN address of NVE\n"
2444 "UN IPv4 interface address\n"
2445 "UN IPv6 interface address\n"
2446 "Administrative cost [default: 255]\n"
2447 "Administrative cost\n")
2448 {
2449 /* pfx vn un cost life */
2450 return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2451 /* mac vni */
2452 NULL, NULL, 0, NULL);
2453 }
2454
2455 DEFUN (add_vnc_prefix_life,
2456 add_vnc_prefix_life_cmd,
2457 "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)",
2458 "Add registration\n"
2459 "VNC Information\n"
2460 "Add/modify prefix related information\n"
2461 "IPv4 prefix\n"
2462 "IPv6 prefix\n"
2463 "VN address of NVE\n"
2464 "VN IPv4 interface address\n"
2465 "VN IPv6 interface address\n"
2466 "UN address of NVE\n"
2467 "UN IPv4 interface address\n"
2468 "UN IPv6 interface address\n"
2469 "Registration lifetime [default: infinite]\n"
2470 "Lifetime value in seconds\n")
2471 {
2472 /* pfx vn un cost life */
2473 return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2474 /* mac vni */
2475 NULL, NULL, 0, NULL);
2476 }
2477
2478 DEFUN (add_vnc_prefix,
2479 add_vnc_prefix_cmd,
2480 "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>",
2481 "Add registration\n"
2482 "VNC Information\n"
2483 "Add/modify prefix related information\n"
2484 "IPv4 prefix\n"
2485 "IPv6 prefix\n"
2486 "VN address of NVE\n"
2487 "VN IPv4 interface address\n"
2488 "VN IPv6 interface address\n"
2489 "UN address of NVE\n"
2490 "UN IPv4 interface address\n"
2491 "UN IPv6 interface address\n")
2492 {
2493 /* pfx vn un cost life */
2494 return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2495 /* mac vni */
2496 NULL, NULL, 0, NULL);
2497 }
2498
2499 /************************************************************************
2500 * Mac address registrations
2501 ************************************************************************/
2502 DEFUN (add_vnc_mac_vni_prefix_cost_life,
2503 add_vnc_mac_vni_prefix_cost_life_cmd,
2504 "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)",
2505 "Add registration\n"
2506 "VNC Information\n"
2507 "Add/modify mac address information\n"
2508 "MAC address\n"
2509 "Virtual Network Identifier follows\n"
2510 "Virtual Network Identifier\n"
2511 "VN address of NVE\n"
2512 "VN IPv4 interface address\n"
2513 "VN IPv6 interface address\n"
2514 "UN address of NVE\n"
2515 "UN IPv4 interface address\n"
2516 "UN IPv6 interface address\n"
2517 "Add/modify prefix related information\n"
2518 "IPv4 prefix\n"
2519 "IPv6 prefix\n"
2520 "Administrative cost [default: 255]\n"
2521 "Administrative cost\n"
2522 "Registration lifetime [default: infinite]\n"
2523 "Lifetime value in seconds\n")
2524 {
2525 /* pfx vn un cost life */
2526 return register_add(vty, argv[11], argv[7], argv[9], argv[13], argv[15],
2527 /* mac vni */
2528 argv[3], argv[5], 0, NULL);
2529 }
2530
2531
2532 DEFUN (add_vnc_mac_vni_prefix_life,
2533 add_vnc_mac_vni_prefix_life_cmd,
2534 "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)",
2535 "Add registration\n"
2536 "VNC Information\n"
2537 "Add/modify mac address information\n"
2538 "MAC address\n"
2539 "Virtual Network Identifier follows\n"
2540 "Virtual Network Identifier\n"
2541 "VN address of NVE\n"
2542 "VN IPv4 interface address\n"
2543 "VN IPv6 interface address\n"
2544 "UN address of NVE\n"
2545 "UN IPv4 interface address\n"
2546 "UN IPv6 interface address\n"
2547 "Add/modify prefix related information\n"
2548 "IPv4 prefix\n"
2549 "IPv6 prefix\n"
2550 "Registration lifetime [default: infinite]\n"
2551 "Lifetime value in seconds\n")
2552 {
2553 /* pfx vn un cost life */
2554 return register_add(vty, argv[11], argv[7], argv[9], NULL, argv[13],
2555 /* mac vni */
2556 argv[3], argv[5], 0, NULL);
2557 }
2558
2559 DEFUN (add_vnc_mac_vni_prefix_cost,
2560 add_vnc_mac_vni_prefix_cost_cmd,
2561 "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)",
2562 "Add registration\n"
2563 "VNC Information\n"
2564 "Add/modify mac address information\n"
2565 "MAC address\n"
2566 "Virtual Network Identifier follows\n"
2567 "Virtual Network Identifier\n"
2568 "VN address of NVE\n"
2569 "VN IPv4 interface address\n"
2570 "VN IPv6 interface address\n"
2571 "UN address of NVE\n"
2572 "UN IPv4 interface address\n"
2573 "UN IPv6 interface address\n"
2574 "Add/modify prefix related information\n"
2575 "IPv4 prefix\n"
2576 "IPv6 prefix\n"
2577 "Administrative cost [default: 255]\n" "Administrative cost\n")
2578 {
2579 /* pfx vn un cost life */
2580 return register_add(vty, argv[11], argv[7], argv[9], argv[13], NULL,
2581 /* mac vni */
2582 argv[3], argv[5], 0, NULL);
2583 }
2584
2585 DEFUN (add_vnc_mac_vni_prefix,
2586 add_vnc_mac_vni_prefix_cmd,
2587 "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>",
2588 "Add registration\n"
2589 "VNC Information\n"
2590 "Add/modify mac address information\n"
2591 "MAC address\n"
2592 "Virtual Network Identifier follows\n"
2593 "Virtual Network Identifier\n"
2594 "VN address of NVE\n"
2595 "VN IPv4 interface address\n"
2596 "VN IPv6 interface address\n"
2597 "UN address of NVE\n"
2598 "UN IPv4 interface address\n"
2599 "UN IPv6 interface address\n"
2600 "Add/modify prefix related information\n"
2601 "IPv4 prefix\n" "IPv6 prefix\n")
2602 {
2603 /* pfx vn un cost life */
2604 return register_add(vty, argv[11], argv[7], argv[9], NULL, NULL,
2605 /* mac vni */
2606 argv[3], argv[5], 0, NULL);
2607 }
2608
2609 DEFUN (add_vnc_mac_vni_cost_life,
2610 add_vnc_mac_vni_cost_life_cmd,
2611 "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)",
2612 "Add registration\n"
2613 "VNC Information\n"
2614 "Add/modify mac address information\n"
2615 "MAC address\n"
2616 "Virtual Network Identifier follows\n"
2617 "Virtual Network Identifier\n"
2618 "VN address of NVE\n"
2619 "VN IPv4 interface address\n"
2620 "VN IPv6 interface address\n"
2621 "UN address of NVE\n"
2622 "UN IPv4 interface address\n"
2623 "UN IPv6 interface address\n"
2624 "Administrative cost [default: 255]\n"
2625 "Administrative cost\n"
2626 "Registration lifetime [default: infinite]\n"
2627 "Lifetime value in seconds\n")
2628 {
2629 /* pfx vn un cost life */
2630 return register_add(vty, NULL, argv[7], argv[9], argv[11], argv[13],
2631 /* mac vni */
2632 argv[3], argv[5], 0, NULL);
2633 }
2634
2635
2636 DEFUN (add_vnc_mac_vni_cost,
2637 add_vnc_mac_vni_cost_cmd,
2638 "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)",
2639 "Add registration\n"
2640 "VNC Information\n"
2641 "Add/modify mac address information\n"
2642 "MAC address\n"
2643 "Virtual Network Identifier follows\n"
2644 "Virtual Network Identifier\n"
2645 "VN address of NVE\n"
2646 "VN IPv4 interface address\n"
2647 "VN IPv6 interface address\n"
2648 "UN address of NVE\n"
2649 "UN IPv4 interface address\n"
2650 "UN IPv6 interface address\n"
2651 "Administrative cost [default: 255]\n" "Administrative cost\n")
2652 {
2653 /* pfx vn un cost life */
2654 return register_add(vty, NULL, argv[7], argv[9], argv[11], NULL,
2655 /* mac vni */
2656 argv[3], argv[5], 0, NULL);
2657 }
2658
2659
2660 DEFUN (add_vnc_mac_vni_life,
2661 add_vnc_mac_vni_life_cmd,
2662 "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)",
2663 "Add registration\n"
2664 "VNC Information\n"
2665 "Add/modify mac address information\n"
2666 "MAC address\n"
2667 "Virtual Network Identifier follows\n"
2668 "Virtual Network Identifier\n"
2669 "VN address of NVE\n"
2670 "VN IPv4 interface address\n"
2671 "VN IPv6 interface address\n"
2672 "UN address of NVE\n"
2673 "UN IPv4 interface address\n"
2674 "UN IPv6 interface address\n"
2675 "Registration lifetime [default: infinite]\n"
2676 "Lifetime value in seconds\n")
2677 {
2678 /* pfx vn un cost life */
2679 return register_add(vty, NULL, argv[7], argv[9], NULL, argv[11],
2680 /* mac vni */
2681 argv[3], argv[5], 0, NULL);
2682 }
2683
2684
2685 DEFUN (add_vnc_mac_vni,
2686 add_vnc_mac_vni_cmd,
2687 "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>",
2688 "Add registration\n"
2689 "VNC Information\n"
2690 "Add/modify mac address information\n"
2691 "MAC address\n"
2692 "Virtual Network Identifier follows\n"
2693 "Virtual Network Identifier\n"
2694 "VN address of NVE\n"
2695 "VN IPv4 interface address\n"
2696 "VN IPv6 interface address\n"
2697 "UN address of NVE\n"
2698 "UN IPv4 interface address\n" "UN IPv6 interface address\n")
2699 {
2700 /* pfx vn un cost life */
2701 return register_add(vty, NULL, argv[7], argv[9], NULL, NULL,
2702 /* mac vni */
2703 argv[3], argv[5], 0, NULL);
2704 }
2705
2706 /************************************************************************
2707 * Delete prefix
2708 ************************************************************************/
2709
2710 struct rfapi_local_reg_delete_arg {
2711 /*
2712 * match parameters
2713 */
2714 struct bgp *bgp;
2715 struct rfapi_ip_addr un_address; /* AF==0: wildcard */
2716 struct rfapi_ip_addr vn_address; /* AF==0: wildcard */
2717 struct prefix prefix; /* AF==0: wildcard */
2718 struct prefix_rd rd; /* plen!=64: wildcard */
2719 struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */
2720
2721 struct rfapi_l2address_option_match l2o;
2722
2723 /*
2724 * result parameters
2725 */
2726 struct vty *vty;
2727 uint32_t reg_count;
2728 uint32_t pfx_count;
2729 uint32_t query_count;
2730
2731 uint32_t failed_pfx_count;
2732
2733 uint32_t nve_count;
2734 struct skiplist *nves;
2735
2736 uint32_t remote_active_nve_count;
2737 uint32_t remote_active_pfx_count;
2738 uint32_t remote_holddown_nve_count;
2739 uint32_t remote_holddown_pfx_count;
2740 };
2741
2742 struct nve_addr {
2743 struct rfapi_ip_addr vn;
2744 struct rfapi_ip_addr un;
2745 struct rfapi_descriptor *rfd;
2746 struct rfapi_local_reg_delete_arg *cda;
2747 };
2748
2749 static void nve_addr_free(void *hap)
2750 {
2751 ((struct nve_addr *)hap)->cda->nve_count += 1;
2752 XFREE(MTYPE_RFAPI_NVE_ADDR, hap);
2753 }
2754
2755 static int nve_addr_cmp(void *k1, void *k2)
2756 {
2757 struct nve_addr *a = (struct nve_addr *)k1;
2758 struct nve_addr *b = (struct nve_addr *)k2;
2759 int ret = 0;
2760
2761 if (!a || !b) {
2762 return (a - b);
2763 }
2764 if (a->un.addr_family != b->un.addr_family) {
2765 return (a->un.addr_family - b->un.addr_family);
2766 }
2767 if (a->vn.addr_family != b->vn.addr_family) {
2768 return (a->vn.addr_family - b->vn.addr_family);
2769 }
2770 if (a->un.addr_family == AF_INET) {
2771 ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4);
2772 if (ret != 0) {
2773 return ret;
2774 }
2775 } else if (a->un.addr_family == AF_INET6) {
2776 ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6);
2777 if (ret != 0) {
2778 return ret;
2779 }
2780 } else {
2781 assert(0);
2782 }
2783 if (a->vn.addr_family == AF_INET) {
2784 ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4);
2785 if (ret != 0)
2786 return ret;
2787 } else if (a->vn.addr_family == AF_INET6) {
2788 ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6);
2789 if (ret == 0) {
2790 return ret;
2791 }
2792 } else {
2793 assert(0);
2794 }
2795 return 0;
2796 }
2797
2798 static int parse_deleter_args(struct vty *vty, struct bgp *bgp,
2799 const char *arg_prefix, const char *arg_vn,
2800 const char *arg_un, const char *arg_l2addr,
2801 const char *arg_vni, const char *arg_rd,
2802 struct rfapi_nve_group_cfg *arg_rfg,
2803 struct rfapi_local_reg_delete_arg *rcdarg)
2804 {
2805 int rc = CMD_WARNING;
2806
2807 memset(rcdarg, 0, sizeof(struct rfapi_local_reg_delete_arg));
2808
2809 rcdarg->vty = vty;
2810 if (bgp == NULL)
2811 bgp = bgp_get_default();
2812 rcdarg->bgp = bgp;
2813 rcdarg->rfg = arg_rfg; /* may be NULL */
2814
2815 if (arg_vn && strcmp(arg_vn, "*")) {
2816 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn,
2817 &rcdarg->vn_address)))
2818 return rc;
2819 }
2820 if (arg_un && strcmp(arg_un, "*")) {
2821 if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un,
2822 &rcdarg->un_address)))
2823 return rc;
2824 }
2825 if (arg_prefix && strcmp(arg_prefix, "*")) {
2826
2827 if (!str2prefix(arg_prefix, &rcdarg->prefix)) {
2828 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2829 return rc;
2830 }
2831 }
2832
2833 if (arg_l2addr) {
2834 if (!arg_vni) {
2835 vty_out(vty, "Missing VNI\n");
2836 return rc;
2837 }
2838 if (strcmp(arg_l2addr, "*")) {
2839 if ((rc = rfapiStr2EthAddr(arg_l2addr,
2840 &rcdarg->l2o.o.macaddr))) {
2841 vty_out(vty, "Malformed L2 Address \"%s\"\n",
2842 arg_l2addr);
2843 return rc;
2844 }
2845 rcdarg->l2o.flags |= RFAPI_L2O_MACADDR;
2846 }
2847 if (strcmp(arg_vni, "*")) {
2848 rcdarg->l2o.o.logical_net_id =
2849 strtoul(arg_vni, NULL, 10);
2850 rcdarg->l2o.flags |= RFAPI_L2O_LNI;
2851 }
2852 }
2853 if (arg_rd) {
2854 if (!str2prefix_rd(arg_rd, &rcdarg->rd)) {
2855 vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
2856 return rc;
2857 }
2858 }
2859
2860 return CMD_SUCCESS;
2861 }
2862
2863 static int
2864 parse_deleter_tokens(struct vty *vty, struct bgp *bgp,
2865 struct cmd_token *carg_prefix, struct cmd_token *carg_vn,
2866 struct cmd_token *carg_un, struct cmd_token *carg_l2addr,
2867 struct cmd_token *carg_vni, struct cmd_token *carg_rd,
2868 struct rfapi_nve_group_cfg *arg_rfg,
2869 struct rfapi_local_reg_delete_arg *rcdarg)
2870 {
2871 const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
2872 const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
2873 const char *arg_un = carg_un ? carg_un->arg : NULL;
2874 const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL;
2875 const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
2876 const char *arg_rd = carg_rd ? carg_rd->arg : NULL;
2877 return parse_deleter_args(vty, bgp, arg_prefix, arg_vn, arg_un,
2878 arg_l2addr, arg_vni, arg_rd, arg_rfg, rcdarg);
2879 }
2880
2881 static void record_nve_in_cda_list(struct rfapi_local_reg_delete_arg *cda,
2882 struct rfapi_ip_addr *un_address,
2883 struct rfapi_ip_addr *vn_address,
2884 struct rfapi_descriptor *rfd)
2885 {
2886 struct nve_addr ha;
2887 struct nve_addr *hap;
2888
2889 memset(&ha, 0, sizeof(ha));
2890 ha.un = *un_address;
2891 ha.vn = *vn_address;
2892 ha.rfd = rfd;
2893
2894 if (!cda->nves)
2895 cda->nves = skiplist_new(0, nve_addr_cmp, nve_addr_free);
2896
2897 if (skiplist_search(cda->nves, &ha, (void *)&hap)) {
2898 hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, sizeof(struct nve_addr));
2899 assert(hap);
2900 ha.cda = cda;
2901 *hap = ha;
2902 skiplist_insert(cda->nves, hap, hap);
2903 }
2904 }
2905
2906 static void clear_vnc_responses(struct rfapi_local_reg_delete_arg *cda)
2907 {
2908 struct rfapi *h;
2909 struct rfapi_descriptor *rfd;
2910 int query_count = 0;
2911 struct listnode *node;
2912 struct bgp *bgp_default = bgp_get_default();
2913
2914 if (cda->vn_address.addr_family && cda->un_address.addr_family) {
2915 /*
2916 * Single nve case
2917 */
2918 if (rfapi_find_rfd(bgp_default, &cda->vn_address,
2919 &cda->un_address, &rfd))
2920 return;
2921
2922 rfapiRibClear(rfd);
2923 rfapi_query_done_all(rfd, &query_count);
2924 cda->query_count += query_count;
2925
2926 /*
2927 * Track unique nves seen
2928 */
2929 record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2930 return;
2931 }
2932
2933 /*
2934 * wildcard case
2935 */
2936
2937 if (!bgp_default)
2938 return; /* ENXIO */
2939
2940 h = bgp_default->rfapi;
2941
2942 if (!h)
2943 return; /* ENXIO */
2944
2945 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
2946 /*
2947 * match un, vn addresses of NVEs
2948 */
2949 if (cda->un_address.addr_family
2950 && rfapi_ip_addr_cmp(&cda->un_address, &rfd->un_addr)) {
2951 continue;
2952 }
2953 if (cda->vn_address.addr_family
2954 && rfapi_ip_addr_cmp(&cda->vn_address, &rfd->vn_addr)) {
2955 continue;
2956 }
2957
2958 rfapiRibClear(rfd);
2959
2960 rfapi_query_done_all(rfd, &query_count);
2961 cda->query_count += query_count;
2962
2963 /*
2964 * Track unique nves seen
2965 */
2966 record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2967 }
2968 }
2969
2970 /*
2971 * TBD need to count deleted prefixes and nves?
2972 *
2973 * ENXIO BGP or VNC not configured
2974 */
2975 static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
2976 struct rfapi_descriptor *rfd)
2977 {
2978 struct rfapi_ip_addr *pUn; /* NULL = wildcard */
2979 struct rfapi_ip_addr *pVn; /* NULL = wildcard */
2980 struct prefix *pPrefix; /* NULL = wildcard */
2981 struct prefix_rd *pPrd; /* NULL = wildcard */
2982
2983 struct rfapi_ip_prefix rprefix;
2984 struct rfapi_next_hop_entry *head = NULL;
2985 struct rfapi_next_hop_entry *tail = NULL;
2986
2987 #if DEBUG_L2_EXTRA
2988 vnc_zlog_debug_verbose("%s: entry", __func__);
2989 #endif
2990
2991 pUn = (cda->un_address.addr_family ? &cda->un_address : NULL);
2992 pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL);
2993 pPrefix = (cda->prefix.family ? &cda->prefix : NULL);
2994 pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL);
2995
2996 if (pPrefix) {
2997 rfapiQprefix2Rprefix(pPrefix, &rprefix);
2998 }
2999
3000 do /* to preserve old code structure */
3001 {
3002 struct rfapi *h = cda->bgp->rfapi;
3003 ;
3004 struct rfapi_adb *adb;
3005 int rc;
3006 int deleted_from_this_nve;
3007 struct nve_addr ha;
3008 struct nve_addr *hap;
3009
3010 #if DEBUG_L2_EXTRA
3011 vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
3012 #endif
3013
3014 /*
3015 * match un, vn addresses of NVEs
3016 */
3017 if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr)))
3018 continue;
3019 if (pVn && (rfapi_ip_addr_cmp(pVn, &rfd->vn_addr)))
3020 continue;
3021
3022 #if DEBUG_L2_EXTRA
3023 vnc_zlog_debug_verbose("%s: un, vn match", __func__);
3024 #endif
3025
3026 /*
3027 * match prefix
3028 */
3029
3030 deleted_from_this_nve = 0;
3031
3032 {
3033 struct skiplist *sl;
3034 struct rfapi_ip_prefix rp;
3035 void *cursor;
3036 struct list *adb_delete_list;
3037
3038 /*
3039 * The advertisements are stored in a skiplist.
3040 * Withdrawing
3041 * the registration deletes the advertisement from the
3042 * skiplist, which we can't do while iterating over that
3043 * same skiplist using the current skiplist API.
3044 *
3045 * Strategy: iterate over the skiplist and build another
3046 * list containing only the matching ADBs. Then delete
3047 * _everything_ in that second list (which can be done
3048 * using either skiplists or quagga linklists).
3049 */
3050 adb_delete_list = list_new();
3051
3052 /*
3053 * Advertised IP prefixes (not 0/32 or 0/128)
3054 */
3055 sl = rfd->advertised.ipN_by_prefix;
3056
3057 for (cursor = NULL,
3058 rc = skiplist_next(sl, NULL, (void **)&adb,
3059 &cursor);
3060 !rc; rc = skiplist_next(sl, NULL, (void **)&adb,
3061 &cursor)) {
3062
3063 if (pPrefix) {
3064 if (!prefix_same(pPrefix,
3065 &adb->u.s.prefix_ip)) {
3066 #if DEBUG_L2_EXTRA
3067 vnc_zlog_debug_verbose(
3068 "%s: adb=%p, prefix doesn't match, skipping",
3069 __func__, adb);
3070 #endif
3071 continue;
3072 }
3073 }
3074 if (pPrd) {
3075 if (memcmp(pPrd->val, adb->u.s.prd.val,
3076 8)
3077 != 0) {
3078 #if DEBUG_L2_EXTRA
3079 vnc_zlog_debug_verbose(
3080 "%s: adb=%p, RD doesn't match, skipping",
3081 __func__, adb);
3082 #endif
3083 continue;
3084 }
3085 }
3086 if (CHECK_FLAG(cda->l2o.flags,
3087 RFAPI_L2O_MACADDR)) {
3088 if (memcmp(cda->l2o.o.macaddr.octet,
3089 adb->u.s.prefix_eth.u
3090 .prefix_eth.octet,
3091 ETH_ALEN)) {
3092 #if DEBUG_L2_EXTRA
3093 vnc_zlog_debug_verbose(
3094 "%s: adb=%p, macaddr doesn't match, skipping",
3095 __func__, adb);
3096 #endif
3097 continue;
3098 }
3099 }
3100
3101 if (CHECK_FLAG(cda->l2o.flags, RFAPI_L2O_LNI)) {
3102 if (cda->l2o.o.logical_net_id
3103 != adb->l2o.logical_net_id) {
3104 #if DEBUG_L2_EXTRA
3105 vnc_zlog_debug_verbose(
3106 "%s: adb=%p, LNI doesn't match, skipping",
3107 __func__, adb);
3108 #endif
3109 continue;
3110 }
3111 }
3112
3113 #if DEBUG_L2_EXTRA
3114 vnc_zlog_debug_verbose(
3115 "%s: ipN adding adb %p to delete list",
3116 __func__, adb);
3117 #endif
3118
3119 listnode_add(adb_delete_list, adb);
3120 }
3121
3122 struct listnode *node;
3123
3124 for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, adb)) {
3125 int this_advertisement_prefix_count;
3126 struct rfapi_vn_option optary[3];
3127 struct rfapi_vn_option *opt = NULL;
3128 int cur_opt = 0;
3129
3130 this_advertisement_prefix_count = 1;
3131
3132 rfapiQprefix2Rprefix(&adb->u.s.prefix_ip, &rp);
3133
3134 memset(optary, 0, sizeof(optary));
3135
3136 /* if mac addr present in advert, make l2o vn
3137 * option */
3138 if (adb->u.s.prefix_eth.family == AF_ETHERNET) {
3139 if (opt != NULL)
3140 opt->next = &optary[cur_opt];
3141 opt = &optary[cur_opt++];
3142 opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3143 opt->v.l2addr.macaddr =
3144 adb->u.s.prefix_eth.u
3145 .prefix_eth;
3146 ++this_advertisement_prefix_count;
3147 }
3148 /*
3149 * use saved RD value instead of trying to
3150 * invert
3151 * complex RD computation in rfapi_register()
3152 */
3153 if (opt != NULL)
3154 opt->next = &optary[cur_opt];
3155 opt = &optary[cur_opt++];
3156 opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
3157 opt->v.internal_rd = adb->u.s.prd;
3158
3159 #if DEBUG_L2_EXTRA
3160 vnc_zlog_debug_verbose(
3161 "%s: ipN killing reg from adb %p ",
3162 __func__, adb);
3163 #endif
3164
3165 rc = rfapi_register(rfd, &rp, 0, NULL,
3166 (cur_opt ? optary : NULL),
3167 RFAPI_REGISTER_KILL);
3168 if (!rc) {
3169 cda->pfx_count +=
3170 this_advertisement_prefix_count;
3171 cda->reg_count += 1;
3172 deleted_from_this_nve = 1;
3173 }
3174 if (h->rfp_methods.local_cb) {
3175 rfapiAddDeleteLocalRfpPrefix(
3176 &rfd->un_addr, &rfd->vn_addr,
3177 &rp, 0, 0, NULL, &head, &tail);
3178 }
3179 }
3180 list_delete_all_node(adb_delete_list);
3181
3182 if (!(pPrefix && !RFAPI_0_PREFIX(pPrefix))) {
3183 void *cursor;
3184
3185 /*
3186 * Caller didn't specify a prefix, or specified
3187 * (0/32 or 0/128)
3188 */
3189
3190 /*
3191 * Advertised 0/32 and 0/128 (indexed by
3192 * ethernet address)
3193 */
3194 sl = rfd->advertised.ip0_by_ether;
3195
3196 for (cursor = NULL,
3197 rc = skiplist_next(sl, NULL, (void **)&adb,
3198 &cursor);
3199 !rc;
3200 rc = skiplist_next(sl, NULL, (void **)&adb,
3201 &cursor)) {
3202
3203 if (CHECK_FLAG(cda->l2o.flags,
3204 RFAPI_L2O_MACADDR)) {
3205 if (memcmp(cda->l2o.o.macaddr
3206 .octet,
3207 adb->u.s.prefix_eth.u
3208 .prefix_eth
3209 .octet,
3210 ETH_ALEN)) {
3211
3212 continue;
3213 }
3214 }
3215 if (CHECK_FLAG(cda->l2o.flags,
3216 RFAPI_L2O_LNI)) {
3217 if (cda->l2o.o.logical_net_id
3218 != adb->l2o.logical_net_id) {
3219 continue;
3220 }
3221 }
3222 #if DEBUG_L2_EXTRA
3223 vnc_zlog_debug_verbose(
3224 "%s: ip0 adding adb %p to delete list",
3225 __func__, adb);
3226 #endif
3227 listnode_add(adb_delete_list, adb);
3228 }
3229
3230
3231 for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node,
3232 adb)) {
3233
3234 struct rfapi_vn_option vn;
3235
3236 rfapiQprefix2Rprefix(
3237 &adb->u.s.prefix_ip, &rp);
3238
3239 memset(&vn, 0, sizeof(vn));
3240 vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3241 vn.v.l2addr = adb->l2o;
3242
3243 #if DEBUG_L2_EXTRA
3244 vnc_zlog_debug_verbose(
3245 "%s: ip0 killing reg from adb %p ",
3246 __func__, adb);
3247 #endif
3248
3249 rc = rfapi_register(
3250 rfd, &rp, 0, NULL, &vn,
3251 RFAPI_REGISTER_KILL);
3252 if (!rc) {
3253 cda->pfx_count += 1;
3254 cda->reg_count += 1;
3255 deleted_from_this_nve = 1;
3256 }
3257 if (h->rfp_methods.local_cb) {
3258 struct rfapi_vn_option
3259 *vn_opt_new;
3260
3261 vn_opt_new =
3262 rfapi_vn_options_dup(
3263 &vn);
3264 rfapiAddDeleteLocalRfpPrefix(
3265 &rfd->un_addr,
3266 &rfd->vn_addr, &rp, 0,
3267 0, vn_opt_new, &head,
3268 &tail);
3269 }
3270 }
3271 list_delete_all_node(adb_delete_list);
3272 }
3273 list_delete_and_null(&adb_delete_list);
3274 }
3275
3276
3277 if (head) { /* should not be set if (NULL ==
3278 rfapi_cfg->local_cb) */
3279 h->flags |= RFAPI_INCALLBACK;
3280 (*h->rfp_methods.local_cb)(head, rfd->cookie);
3281 h->flags &= ~RFAPI_INCALLBACK;
3282 head = tail = NULL;
3283 }
3284
3285 if (deleted_from_this_nve) {
3286 /*
3287 * track unique NVEs seen
3288 */
3289 memset(&ha, 0, sizeof(ha));
3290 ha.un = rfd->un_addr;
3291 ha.vn = rfd->vn_addr;
3292
3293 if (!cda->nves)
3294 cda->nves = skiplist_new(0, nve_addr_cmp,
3295 nve_addr_free);
3296 if (skiplist_search(cda->nves, &ha, (void **)&hap)) {
3297 hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR,
3298 sizeof(struct nve_addr));
3299 assert(hap);
3300 ha.cda = cda;
3301 *hap = ha;
3302 skiplist_insert(cda->nves, hap, hap);
3303 }
3304 }
3305 } while (0); /* to preserve old code structure */
3306
3307 return 0;
3308 }
3309
3310 static int rfapiDeleteLocalPrefixes(struct rfapi_local_reg_delete_arg *cda)
3311 {
3312 int rc = 0;
3313
3314 if (cda->rfg) {
3315 if (cda->rfg->rfd) /* if not open, nothing to delete */
3316 rc = rfapiDeleteLocalPrefixesByRFD(cda, cda->rfg->rfd);
3317 } else {
3318 struct bgp *bgp = cda->bgp;
3319 struct rfapi *h;
3320 struct rfapi_cfg *rfapi_cfg;
3321
3322 struct listnode *node;
3323 struct rfapi_descriptor *rfd;
3324 if (!bgp)
3325 return ENXIO;
3326 h = bgp->rfapi;
3327 rfapi_cfg = bgp->rfapi_cfg;
3328 if (!h || !rfapi_cfg)
3329 return ENXIO;
3330 vnc_zlog_debug_verbose("%s: starting descriptor loop",
3331 __func__);
3332 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
3333 rc = rfapiDeleteLocalPrefixesByRFD(cda, rfd);
3334 }
3335 }
3336 return rc;
3337 }
3338
3339 /*
3340 * clear_vnc_prefix
3341 *
3342 * Deletes local and remote prefixes that match
3343 */
3344 static void clear_vnc_prefix(struct rfapi_local_reg_delete_arg *cda)
3345 {
3346 struct prefix pfx_un;
3347 struct prefix pfx_vn;
3348
3349 struct prefix *pUN = NULL;
3350 struct prefix *pVN = NULL;
3351 struct prefix *pPrefix = NULL;
3352
3353 struct rfapi_import_table *it = NULL;
3354
3355 /*
3356 * Delete matching remote prefixes in holddown
3357 */
3358 if (cda->vn_address.addr_family) {
3359 if (!rfapiRaddr2Qprefix(&cda->vn_address, &pfx_vn))
3360 pVN = &pfx_vn;
3361 }
3362 if (cda->un_address.addr_family) {
3363 if (!rfapiRaddr2Qprefix(&cda->un_address, &pfx_un))
3364 pUN = &pfx_un;
3365 }
3366 if (cda->prefix.family) {
3367 pPrefix = &cda->prefix;
3368 }
3369 if (cda->rfg) {
3370 it = cda->rfg->rfapi_import_table;
3371 }
3372 rfapiDeleteRemotePrefixes(
3373 pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count,
3374 &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count,
3375 &cda->remote_holddown_nve_count);
3376
3377 /*
3378 * Now do local prefixes
3379 */
3380 rfapiDeleteLocalPrefixes(cda);
3381 }
3382
3383 static void print_cleared_stats(struct rfapi_local_reg_delete_arg *cda)
3384 {
3385 struct vty *vty = cda->vty; /* for benefit of VTYNL */
3386
3387 /* Our special element-deleting function counts nves */
3388 if (cda->nves) {
3389 skiplist_free(cda->nves);
3390 cda->nves = NULL;
3391 }
3392 if (cda->failed_pfx_count)
3393 vty_out(vty, "Failed to delete %d prefixes\n",
3394 cda->failed_pfx_count);
3395
3396 /* left as "prefixes" even in single case for ease of machine parsing */
3397 vty_out(vty,
3398 "[Local] Cleared %u registrations, %u prefixes, %u responses from %d NVEs\n",
3399 cda->reg_count, cda->pfx_count, cda->query_count,
3400 cda->nve_count);
3401
3402 /*
3403 * We don't currently allow deletion of active remote prefixes from
3404 * the command line
3405 */
3406
3407 vty_out(vty, "[Holddown] Cleared %u prefixes from %u NVEs\n",
3408 cda->remote_holddown_pfx_count, cda->remote_holddown_nve_count);
3409 }
3410
3411 /*
3412 * Caller has already deleted registrations and queries for this/these
3413 * NVEs. Now we just have to close their descriptors.
3414 */
3415 static void clear_vnc_nve_closer(struct rfapi_local_reg_delete_arg *cda)
3416 {
3417 struct skiplist *sl = cda->nves; /* contains affected NVEs */
3418 struct nve_addr *pKey;
3419 struct nve_addr *pValue;
3420 void *cursor = NULL;
3421 int rc;
3422
3423 if (!sl)
3424 return;
3425
3426 for (rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, &cursor);
3427 !rc; rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue,
3428 &cursor)) {
3429
3430 if (pValue->rfd) {
3431 ((struct rfapi_descriptor *)pValue->rfd)->flags |=
3432 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY;
3433 rfapi_close(pValue->rfd);
3434 }
3435 }
3436 }
3437
3438 DEFUN (clear_vnc_nve_all,
3439 clear_vnc_nve_all_cmd,
3440 "clear vnc nve *",
3441 "clear\n"
3442 "VNC Information\n"
3443 "Clear per NVE information\n"
3444 "For all NVEs\n")
3445 {
3446
3447 struct rfapi_local_reg_delete_arg cda;
3448 int rc;
3449
3450 if ((rc = parse_deleter_args(vty, NULL, NULL, NULL, NULL, NULL, NULL,
3451 NULL, NULL, &cda)))
3452 return rc;
3453
3454 cda.vty = vty;
3455
3456 clear_vnc_responses(&cda);
3457 clear_vnc_prefix(&cda);
3458 clear_vnc_nve_closer(&cda);
3459
3460 print_cleared_stats(&cda);
3461
3462 return 0;
3463 }
3464
3465 DEFUN (clear_vnc_nve_vn_un,
3466 clear_vnc_nve_vn_un_cmd,
3467 "clear vnc nve vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3468 "clear\n"
3469 "VNC Information\n"
3470 "Clear prefix registration information\n"
3471 "VN address of NVE\n"
3472 "For all NVEs\n"
3473 "VN IPv4 interface address\n"
3474 "VN IPv6 interface address\n"
3475 "UN address of NVE\n"
3476 "For all UN addresses\n"
3477 "UN IPv4 interface address\n"
3478 "UN IPv6 interface address\n")
3479 {
3480 struct rfapi_local_reg_delete_arg cda;
3481 int rc;
3482
3483 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], argv[6], NULL,
3484 NULL, NULL, NULL, &cda)))
3485 return rc;
3486
3487 cda.vty = vty;
3488
3489 clear_vnc_responses(&cda);
3490 clear_vnc_prefix(&cda);
3491 clear_vnc_nve_closer(&cda);
3492
3493 print_cleared_stats(&cda);
3494
3495 return 0;
3496 }
3497
3498 DEFUN (clear_vnc_nve_un_vn,
3499 clear_vnc_nve_un_vn_cmd,
3500 "clear vnc nve un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3501 "clear\n"
3502 "VNC Information\n"
3503 "Clear prefix registration information\n"
3504 "UN address of NVE\n"
3505 "For all un NVEs\n"
3506 "UN IPv4 interface address\n"
3507 "UN IPv6 interface address\n"
3508 "VN address of NVE\n"
3509 "For all vn NVEs\n"
3510 "VN IPv4 interface address\n"
3511 "VN IPv6 interface address\n")
3512 {
3513 struct rfapi_local_reg_delete_arg cda;
3514 int rc;
3515
3516 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[6], argv[4], NULL,
3517 NULL, NULL, NULL, &cda)))
3518 return rc;
3519
3520 cda.vty = vty;
3521
3522 clear_vnc_responses(&cda);
3523 clear_vnc_prefix(&cda);
3524 clear_vnc_nve_closer(&cda);
3525
3526 print_cleared_stats(&cda);
3527
3528 return 0;
3529 }
3530
3531 DEFUN (clear_vnc_nve_vn,
3532 clear_vnc_nve_vn_cmd,
3533 "clear vnc nve vn <*|A.B.C.D|X:X::X:X>",
3534 "clear\n"
3535 "VNC Information\n"
3536 "Clear prefix registration information\n"
3537 "VN address of NVE\n"
3538 "All addresses\n"
3539 "VN IPv4 interface address\n"
3540 "VN IPv6 interface address\n")
3541 {
3542 struct rfapi_local_reg_delete_arg cda;
3543 int rc;
3544
3545 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], NULL, NULL,
3546 NULL, NULL, NULL, &cda)))
3547 return rc;
3548
3549 cda.vty = vty;
3550
3551 clear_vnc_responses(&cda);
3552 clear_vnc_prefix(&cda);
3553 clear_vnc_nve_closer(&cda);
3554
3555 print_cleared_stats(&cda);
3556 return 0;
3557 }
3558
3559 DEFUN (clear_vnc_nve_un,
3560 clear_vnc_nve_un_cmd,
3561 "clear vnc nve un <*|A.B.C.D|X:X::X:X>",
3562 "clear\n"
3563 "VNC Information\n"
3564 "Clear prefix registration information\n"
3565 "UN address of NVE\n"
3566 "All un nves\n"
3567 "UN IPv4 interface address\n"
3568 "UN IPv6 interface address\n")
3569 {
3570 struct rfapi_local_reg_delete_arg cda;
3571 int rc;
3572
3573 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[4], NULL,
3574 NULL, NULL, NULL, &cda)))
3575 return rc;
3576
3577 cda.vty = vty;
3578
3579 clear_vnc_responses(&cda);
3580 clear_vnc_prefix(&cda);
3581 clear_vnc_nve_closer(&cda);
3582
3583 print_cleared_stats(&cda);
3584 return 0;
3585 }
3586
3587 /*-------------------------------------------------
3588 * Clear VNC Prefix
3589 *-------------------------------------------------*/
3590
3591 /*
3592 * This function is defined in this file (rather than in rfp_registration.c)
3593 * because here we have access to all the task handles.
3594 */
3595 DEFUN (clear_vnc_prefix_vn_un,
3596 clear_vnc_prefix_vn_un_cmd,
3597 "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>",
3598 "clear\n"
3599 "VNC Information\n"
3600 "Clear prefix registration information\n"
3601 "All prefixes\n"
3602 "IPv4 prefix\n"
3603 "IPv6 prefix\n"
3604 "VN address of NVE\n"
3605 "All VN addresses\n"
3606 "VN IPv4 interface address\n"
3607 "VN IPv6 interface address\n"
3608 "UN address of NVE\n"
3609 "All UN addresses\n"
3610 "UN IPv4 interface address\n"
3611 "UN IPv6 interface address\n")
3612 {
3613 struct rfapi_local_reg_delete_arg cda;
3614 int rc;
3615
3616 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], argv[7],
3617 NULL, NULL, NULL, NULL, &cda)))
3618 return rc;
3619 cda.vty = vty;
3620 clear_vnc_prefix(&cda);
3621 print_cleared_stats(&cda);
3622 return 0;
3623 }
3624
3625 DEFUN (clear_vnc_prefix_un_vn,
3626 clear_vnc_prefix_un_vn_cmd,
3627 "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>",
3628 "clear\n"
3629 "VNC Information\n"
3630 "Clear prefix registration information\n"
3631 "All prefixes\n"
3632 "IPv4 prefix\n"
3633 "IPv6 prefix\n"
3634 "UN address of NVE\n"
3635 "All UN addresses\n"
3636 "UN IPv4 interface address\n"
3637 "UN IPv6 interface address\n"
3638 "VN address of NVE\n"
3639 "All VN addresses\n"
3640 "VN IPv4 interface address\n"
3641 "VN IPv6 interface address\n")
3642 {
3643 struct rfapi_local_reg_delete_arg cda;
3644 int rc;
3645
3646 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[7], argv[5],
3647 NULL, NULL, NULL, NULL, &cda)))
3648 return rc;
3649 cda.vty = vty;
3650 clear_vnc_prefix(&cda);
3651 print_cleared_stats(&cda);
3652 return 0;
3653 }
3654
3655 DEFUN (clear_vnc_prefix_un,
3656 clear_vnc_prefix_un_cmd,
3657 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X>",
3658 "clear\n"
3659 "VNC Information\n"
3660 "Clear prefix registration information\n"
3661 "All prefixes\n"
3662 "IPv4 prefix\n"
3663 "IPv6 prefix\n"
3664 "UN address of NVE\n"
3665 "All UN addresses\n"
3666 "UN IPv4 interface address\n"
3667 "UN IPv6 interface address\n")
3668 {
3669 struct rfapi_local_reg_delete_arg cda;
3670 int rc;
3671
3672 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, argv[5], NULL,
3673 NULL, NULL, NULL, &cda)))
3674 return rc;
3675 cda.vty = vty;
3676 clear_vnc_prefix(&cda);
3677 print_cleared_stats(&cda);
3678 return 0;
3679 }
3680
3681 DEFUN (clear_vnc_prefix_vn,
3682 clear_vnc_prefix_vn_cmd,
3683 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X>",
3684 "clear\n"
3685 "VNC Information\n"
3686 "Clear prefix registration information\n"
3687 "All prefixes\n"
3688 "IPv4 prefix\n"
3689 "IPv6 prefix\n"
3690 "UN address of NVE\n"
3691 "All VN addresses\n"
3692 "VN IPv4 interface address\n"
3693 "VN IPv6 interface address\n")
3694 {
3695 struct rfapi_local_reg_delete_arg cda;
3696 int rc;
3697
3698 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], NULL, NULL,
3699 NULL, NULL, NULL, &cda)))
3700 return rc;
3701 cda.vty = vty;
3702 clear_vnc_prefix(&cda);
3703 print_cleared_stats(&cda);
3704 return 0;
3705 }
3706
3707 DEFUN (clear_vnc_prefix_all,
3708 clear_vnc_prefix_all_cmd,
3709 "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> *",
3710 "clear\n"
3711 "VNC Information\n"
3712 "Clear prefix registration information\n"
3713 "All prefixes\n"
3714 "IPv4 prefix\n"
3715 "IPv6 prefix\n"
3716 "From any NVE\n")
3717 {
3718 struct rfapi_local_reg_delete_arg cda;
3719 int rc;
3720
3721 if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, NULL, NULL,
3722 NULL, NULL, NULL, &cda)))
3723 return rc;
3724 cda.vty = vty;
3725 clear_vnc_prefix(&cda);
3726 print_cleared_stats(&cda);
3727 return 0;
3728 }
3729
3730 /*-------------------------------------------------
3731 * Clear VNC MAC
3732 *-------------------------------------------------*/
3733
3734 /*
3735 * This function is defined in this file (rather than in rfp_registration.c)
3736 * because here we have access to all the task handles.
3737 */
3738 DEFUN (clear_vnc_mac_vn_un,
3739 clear_vnc_mac_vn_un_cmd,
3740 "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>",
3741 "clear\n"
3742 "VNC Information\n"
3743 "Clear mac registration information\n"
3744 "All macs\n"
3745 "MAC address\n"
3746 "VNI keyword\n"
3747 "Any virtual network identifier\n"
3748 "Virtual network identifier\n"
3749 "VN address of NVE\n"
3750 "All VN addresses\n"
3751 "VN IPv4 interface address\n"
3752 "VN IPv6 interface address\n"
3753 "UN address of NVE\n"
3754 "All UN addresses\n"
3755 "UN IPv4 interface address\n"
3756 "UN IPv6 interface address\n")
3757 {
3758 struct rfapi_local_reg_delete_arg cda;
3759 int rc;
3760
3761 /* pfx vn un L2 VNI */
3762 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], argv[9],
3763 argv[3], argv[5], NULL, NULL, &cda)))
3764 return rc;
3765 cda.vty = vty;
3766 clear_vnc_prefix(&cda);
3767 print_cleared_stats(&cda);
3768 return 0;
3769 }
3770
3771 DEFUN (clear_vnc_mac_un_vn,
3772 clear_vnc_mac_un_vn_cmd,
3773 "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>",
3774 "clear\n"
3775 "VNC Information\n"
3776 "Clear mac registration information\n"
3777 "All macs\n"
3778 "MAC address\n"
3779 "VNI keyword\n"
3780 "Any virtual network identifier\n"
3781 "Virtual network identifier\n"
3782 "UN address of NVE\n"
3783 "All UN addresses\n"
3784 "UN IPv4 interface address\n"
3785 "UN IPv6 interface address\n"
3786 "VN address of NVE\n"
3787 "All VN addresses\n"
3788 "VN IPv4 interface address\n"
3789 "VN IPv6 interface address\n")
3790 {
3791 struct rfapi_local_reg_delete_arg cda;
3792 int rc;
3793
3794 /* pfx vn un L2 VNI */
3795 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[9], argv[7],
3796 argv[3], argv[5], NULL, NULL, &cda)))
3797 return rc;
3798 cda.vty = vty;
3799 clear_vnc_prefix(&cda);
3800 print_cleared_stats(&cda);
3801 return 0;
3802 }
3803
3804 DEFUN (clear_vnc_mac_un,
3805 clear_vnc_mac_un_cmd,
3806 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X>",
3807 "clear\n"
3808 "VNC Information\n"
3809 "Clear mac registration information\n"
3810 "All macs\n"
3811 "MAC address\n"
3812 "VNI keyword\n"
3813 "Any virtual network identifier\n"
3814 "Virtual network identifier\n"
3815 "UN address of NVE\n"
3816 "All UN addresses\n"
3817 "UN IPv4 interface address\n"
3818 "UN IPv6 interface address\n")
3819 {
3820 struct rfapi_local_reg_delete_arg cda;
3821 int rc;
3822
3823 /* pfx vn un L2 VNI */
3824 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[7], argv[3],
3825 argv[5], NULL, NULL, &cda)))
3826 return rc;
3827 cda.vty = vty;
3828 clear_vnc_prefix(&cda);
3829 print_cleared_stats(&cda);
3830 return 0;
3831 }
3832
3833 DEFUN (clear_vnc_mac_vn,
3834 clear_vnc_mac_vn_cmd,
3835 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X>",
3836 "clear\n"
3837 "VNC Information\n"
3838 "Clear mac registration information\n"
3839 "All macs\n"
3840 "MAC address\n"
3841 "VNI keyword\n"
3842 "Any virtual network identifier\n"
3843 "Virtual network identifier\n"
3844 "UN address of NVE\n"
3845 "All VN addresses\n"
3846 "VN IPv4 interface address\n"
3847 "VN IPv6 interface address\n")
3848 {
3849 struct rfapi_local_reg_delete_arg cda;
3850 int rc;
3851
3852 /* pfx vn un L2 VNI */
3853 if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], NULL, argv[3],
3854 argv[5], NULL, NULL, &cda)))
3855 return rc;
3856 cda.vty = vty;
3857 clear_vnc_prefix(&cda);
3858 print_cleared_stats(&cda);
3859 return 0;
3860 }
3861
3862 DEFUN (clear_vnc_mac_all,
3863 clear_vnc_mac_all_cmd,
3864 "clear vnc mac <*|YY:YY:YY:YY:YY:YY> virtual-network-identifier <*|(1-4294967295)> *",
3865 "clear\n"
3866 "VNC Information\n"
3867 "Clear mac registration information\n"
3868 "All macs\n"
3869 "MAC address\n"
3870 "VNI keyword\n"
3871 "Any virtual network identifier\n"
3872 "Virtual network identifier\n"
3873 "From any NVE\n")
3874 {
3875 struct rfapi_local_reg_delete_arg cda;
3876 int rc;
3877
3878 /* pfx vn un L2 VNI */
3879 if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, NULL, argv[3],
3880 argv[5], NULL, NULL, &cda)))
3881 return rc;
3882 cda.vty = vty;
3883 clear_vnc_prefix(&cda);
3884 print_cleared_stats(&cda);
3885 return 0;
3886 }
3887
3888 /*-------------------------------------------------
3889 * Clear VNC MAC PREFIX
3890 *-------------------------------------------------*/
3891
3892 DEFUN (clear_vnc_mac_vn_un_prefix,
3893 clear_vnc_mac_vn_un_prefix_cmd,
3894 "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>",
3895 "clear\n"
3896 "VNC Information\n"
3897 "Clear mac registration information\n"
3898 "All macs\n"
3899 "MAC address\n"
3900 "VNI keyword\n"
3901 "Any virtual network identifier\n"
3902 "Virtual network identifier\n"
3903 "VN address of NVE\n"
3904 "All VN addresses\n"
3905 "VN IPv4 interface address\n"
3906 "VN IPv6 interface address\n"
3907 "UN address of NVE\n"
3908 "All UN addresses\n"
3909 "UN IPv4 interface address\n"
3910 "UN IPv6 interface address\n"
3911 "Clear prefix registration information\n"
3912 "All prefixes\n"
3913 "IPv4 prefix\n"
3914 "IPv6 prefix\n")
3915 {
3916 struct rfapi_local_reg_delete_arg cda;
3917 int rc;
3918
3919 /* pfx vn un L2 VNI */
3920 if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[7], argv[9],
3921 argv[3], argv[5], NULL, NULL, &cda)))
3922 return rc;
3923 cda.vty = vty;
3924 clear_vnc_prefix(&cda);
3925 print_cleared_stats(&cda);
3926 return 0;
3927 }
3928
3929 DEFUN (clear_vnc_mac_un_vn_prefix,
3930 clear_vnc_mac_un_vn_prefix_cmd,
3931 "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>",
3932 "clear\n"
3933 "VNC Information\n"
3934 "Clear mac registration information\n"
3935 "All macs\n"
3936 "MAC address\n"
3937 "VNI keyword\n"
3938 "Any virtual network identifier\n"
3939 "Virtual network identifier\n"
3940 "UN address of NVE\n"
3941 "All UN addresses\n"
3942 "UN IPv4 interface address\n"
3943 "UN IPv6 interface address\n"
3944 "VN address of NVE\n"
3945 "All VN addresses\n"
3946 "VN IPv4 interface address\n"
3947 "VN IPv6 interface address\n"
3948 "Clear prefix registration information\n"
3949 "All prefixes\n"
3950 "IPv4 prefix\n"
3951 "IPv6 prefix\n"
3952 "Clear prefix registration information\n"
3953 "All prefixes\n"
3954 "IPv4 prefix\n"
3955 "IPv6 prefix\n")
3956 {
3957 struct rfapi_local_reg_delete_arg cda;
3958 int rc;
3959
3960 /* pfx vn un L2 VNI */
3961 if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[9], argv[7],
3962 argv[3], argv[5], NULL, NULL, &cda)))
3963 return rc;
3964 cda.vty = vty;
3965 clear_vnc_prefix(&cda);
3966 print_cleared_stats(&cda);
3967 return 0;
3968 }
3969
3970 DEFUN (clear_vnc_mac_un_prefix,
3971 clear_vnc_mac_un_prefix_cmd,
3972 "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>",
3973 "clear\n"
3974 "VNC Information\n"
3975 "Clear mac registration information\n"
3976 "All macs\n"
3977 "MAC address\n"
3978 "VNI keyword\n"
3979 "Any virtual network identifier\n"
3980 "Virtual network identifier\n"
3981 "UN address of NVE\n"
3982 "All UN addresses\n"
3983 "UN IPv4 interface address\n"
3984 "UN IPv6 interface address\n"
3985 "Clear prefix registration information\n"
3986 "All prefixes\n"
3987 "IPv4 Prefix\n"
3988 "IPv6 Prefix\n")
3989 {
3990 struct rfapi_local_reg_delete_arg cda;
3991 int rc;
3992
3993 /* pfx vn un L2 VNI */
3994 if ((rc = parse_deleter_tokens(vty, NULL, argv[9], NULL, argv[7],
3995 argv[3], argv[5], NULL, NULL, &cda)))
3996 return rc;
3997 cda.vty = vty;
3998 clear_vnc_prefix(&cda);
3999 print_cleared_stats(&cda);
4000 return 0;
4001 }
4002
4003 DEFUN (clear_vnc_mac_vn_prefix,
4004 clear_vnc_mac_vn_prefix_cmd,
4005 "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>",
4006 "clear\n"
4007 "VNC Information\n"
4008 "Clear mac registration information\n"
4009 "All macs\n"
4010 "MAC address\n"
4011 "VNI keyword\n"
4012 "Any virtual network identifier\n"
4013 "Virtual network identifier\n"
4014 "UN address of NVE\n"
4015 "All VN addresses\n"
4016 "VN IPv4 interface address\n"
4017 "VN IPv6 interface address\n"
4018 "Clear prefix registration information\n"
4019 "All prefixes\n"
4020 "IPv4 Prefix\n"
4021 "IPv6 Prefix\n")
4022 {
4023 struct rfapi_local_reg_delete_arg cda;
4024 int rc;
4025
4026 /* pfx vn un L2 VNI */
4027 if ((rc = parse_deleter_tokens(vty, NULL, argv[9], argv[7], NULL,
4028 argv[3], argv[5], NULL, NULL, &cda)))
4029 return rc;
4030 cda.vty = vty;
4031 clear_vnc_prefix(&cda);
4032 print_cleared_stats(&cda);
4033 return 0;
4034 }
4035
4036 DEFUN (clear_vnc_mac_all_prefix,
4037 clear_vnc_mac_all_prefix_cmd,
4038 "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>",
4039 "clear\n"
4040 "VNC Information\n"
4041 "Clear mac registration information\n"
4042 "All macs\n"
4043 "MAC address\n"
4044 "VNI keyword\n"
4045 "Any virtual network identifier\n"
4046 "Virtual network identifier\n"
4047 "UN address of NVE\n"
4048 "All VN addresses\n"
4049 "VN IPv4 interface address\n"
4050 "VN IPv6 interface address\n")
4051 {
4052 struct rfapi_local_reg_delete_arg cda;
4053 int rc;
4054
4055 /* pfx vn un L2 VNI */
4056 if ((rc = parse_deleter_tokens(vty, NULL, argv[7], NULL, NULL, argv[3],
4057 argv[5], NULL, NULL, &cda)))
4058 return rc;
4059 cda.vty = vty;
4060 clear_vnc_prefix(&cda);
4061 print_cleared_stats(&cda);
4062 return 0;
4063 }
4064
4065 /************************************************************************
4066 * Show commands
4067 ************************************************************************/
4068
4069
4070 /* copied from rfp_vty.c */
4071 static int check_and_display_is_vnc_running(struct vty *vty)
4072 {
4073 if (bgp_rfapi_is_vnc_configured(NULL) == 0)
4074 return 1; /* is running */
4075
4076 if (vty) {
4077 vty_out(vty, "VNC is not configured.\n");
4078 }
4079 return 0; /* not running */
4080 }
4081
4082 static int rfapi_vty_show_nve_summary(struct vty *vty,
4083 show_nve_summary_t show_type)
4084 {
4085 struct bgp *bgp_default = bgp_get_default();
4086 struct rfapi *h;
4087 int is_vnc_running = (bgp_rfapi_is_vnc_configured(bgp_default) == 0);
4088
4089 int active_local_routes;
4090 int active_remote_routes;
4091 int holddown_remote_routes;
4092 int imported_remote_routes;
4093
4094 if (!bgp_default)
4095 goto notcfg;
4096
4097 h = bgp_default->rfapi;
4098
4099 if (!h)
4100 goto notcfg;
4101
4102 /* don't show local info if not running RFP */
4103 if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) {
4104
4105 switch (show_type) {
4106
4107 case SHOW_NVE_SUMMARY_ACTIVE_NVES:
4108 vty_out(vty, "%-24s ", "NVEs:");
4109 vty_out(vty, "%-8s %-8u ",
4110 "Active:", h->descriptors.count);
4111 vty_out(vty, "%-8s %-8u ",
4112 "Maximum:", h->stat.max_descriptors);
4113 vty_out(vty, "%-8s %-8u",
4114 "Unknown:", h->stat.count_unknown_nves);
4115 break;
4116
4117 case SHOW_NVE_SUMMARY_REGISTERED:
4118 /*
4119 * NB: With the introduction of L2 route support, we no
4120 * longer have a one-to-one correspondence between
4121 * locally-originated route advertisements and routes in
4122 * the import tables that have local origin. This
4123 * discrepancy arises because a single advertisement
4124 * may contain both an IP prefix and a MAC address.
4125 * Such an advertisement results in two import table
4126 * entries: one indexed by IP prefix, the other indexed
4127 * by MAC address.
4128 *
4129 * TBD: update computation and display of registration
4130 * statistics to reflect the underlying semantics.
4131 */
4132 if (is_vnc_running) {
4133 vty_out(vty, "%-24s ", "Registrations:");
4134 vty_out(vty, "%-8s %-8u ", "Active:",
4135 rfapiApCountAll(bgp_default));
4136 vty_out(vty, "%-8s %-8u ", "Failed:",
4137 h->stat.count_registrations_failed);
4138 vty_out(vty, "%-8s %-8u",
4139 "Total:", h->stat.count_registrations);
4140 vty_out(vty, "\n");
4141 }
4142 vty_out(vty, "%-24s ", "Prefixes registered:");
4143 vty_out(vty, "\n");
4144
4145 rfapiCountAllItRoutes(&active_local_routes,
4146 &active_remote_routes,
4147 &holddown_remote_routes,
4148 &imported_remote_routes);
4149
4150 /* local */
4151 if (is_vnc_running) {
4152 vty_out(vty, " %-20s ", "Locally:");
4153 vty_out(vty, "%-8s %-8u ",
4154 "Active:", active_local_routes);
4155 vty_out(vty, "\n");
4156 }
4157
4158
4159 vty_out(vty, " %-20s ", "Remotely:");
4160 vty_out(vty, "%-8s %-8u",
4161 "Active:", active_remote_routes);
4162 vty_out(vty, "\n");
4163 vty_out(vty, " %-20s ", "In Holddown:");
4164 vty_out(vty, "%-8s %-8u",
4165 "Active:", holddown_remote_routes);
4166 vty_out(vty, "\n");
4167 vty_out(vty, " %-20s ", "Imported:");
4168 vty_out(vty, "%-8s %-8u",
4169 "Active:", imported_remote_routes);
4170 break;
4171
4172 case SHOW_NVE_SUMMARY_QUERIES:
4173 vty_out(vty, "%-24s ", "Queries:");
4174 vty_out(vty, "%-8s %-8u ",
4175 "Active:", rfapi_monitor_count(NULL));
4176 vty_out(vty, "%-8s %-8u ",
4177 "Failed:", h->stat.count_queries_failed);
4178 vty_out(vty, "%-8s %-8u",
4179 "Total:", h->stat.count_queries);
4180 break;
4181
4182 case SHOW_NVE_SUMMARY_RESPONSES:
4183 rfapiRibShowResponsesSummary(vty);
4184
4185 default:
4186 break;
4187 }
4188 vty_out(vty, "\n");
4189 }
4190 return 0;
4191
4192 notcfg:
4193 vty_out(vty, "VNC is not configured.\n");
4194 return CMD_WARNING;
4195 }
4196
4197 static int rfapi_show_nves(struct vty *vty, struct prefix *vn_prefix,
4198 struct prefix *un_prefix)
4199 {
4200 // struct hash *rfds;
4201 // struct rfp_rfapi_descriptor_param param;
4202
4203 struct bgp *bgp_default = bgp_get_default();
4204 struct rfapi *h;
4205 struct listnode *node;
4206 struct rfapi_descriptor *rfd;
4207
4208 int total = 0;
4209 int printed = 0;
4210 int rc;
4211
4212 if (!bgp_default)
4213 goto notcfg;
4214
4215 h = bgp_default->rfapi;
4216
4217 if (!h)
4218 goto notcfg;
4219
4220 rc = rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4221 if (rc)
4222 return rc;
4223
4224 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4225 struct prefix pfx;
4226 char vn_addr_buf[INET6_ADDRSTRLEN] = {
4227 0,
4228 };
4229 char un_addr_buf[INET6_ADDRSTRLEN] = {
4230 0,
4231 };
4232 char age[10];
4233
4234 ++total;
4235
4236 if (vn_prefix) {
4237 assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
4238 if (!prefix_match(vn_prefix, &pfx))
4239 continue;
4240 }
4241
4242 if (un_prefix) {
4243 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
4244 if (!prefix_match(un_prefix, &pfx))
4245 continue;
4246 }
4247
4248 rfapiRfapiIpAddr2Str(&rfd->vn_addr, vn_addr_buf,
4249 INET6_ADDRSTRLEN);
4250 rfapiRfapiIpAddr2Str(&rfd->un_addr, un_addr_buf,
4251 INET6_ADDRSTRLEN);
4252
4253 if (!printed) {
4254 /* print out a header */
4255 vty_out(vty,
4256 " Active Next Hops\n");
4257 vty_out(vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n",
4258 "VN Address", "UN Address", "Regis", "Resps",
4259 "Reach", "Remove", "Age");
4260 }
4261
4262 ++printed;
4263
4264 vty_out(vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n",
4265 vn_addr_buf, un_addr_buf, rfapiApCount(rfd),
4266 rfapi_monitor_count(rfd), rfd->stat_count_nh_reachable,
4267 rfd->stat_count_nh_removal,
4268 rfapiFormatAge(rfd->open_time, age, 10));
4269 }
4270
4271 if (printed > 0 || vn_prefix || un_prefix)
4272 vty_out(vty, "Displayed %d out of %d active NVEs\n", printed,
4273 total);
4274
4275 return 0;
4276
4277 notcfg:
4278 vty_out(vty, "VNC is not configured.\n");
4279 return CMD_WARNING;
4280 }
4281
4282
4283 DEFUN (vnc_show_summary,
4284 vnc_show_summary_cmd,
4285 "show vnc summary",
4286 SHOW_STR
4287 VNC_SHOW_STR
4288 "Display VNC status summary\n")
4289 {
4290 if (!check_and_display_is_vnc_running(vty))
4291 return CMD_SUCCESS;
4292 bgp_rfapi_show_summary(bgp_get_default(), vty);
4293 vty_out(vty, "\n");
4294 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4295 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4296 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_RESPONSES);
4297 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4298 return CMD_SUCCESS;
4299 }
4300
4301 DEFUN (vnc_show_nves,
4302 vnc_show_nves_cmd,
4303 "show vnc nves",
4304 SHOW_STR
4305 VNC_SHOW_STR
4306 "List known NVEs\n")
4307 {
4308 rfapi_show_nves(vty, NULL, NULL);
4309 return CMD_SUCCESS;
4310 }
4311
4312 DEFUN (vnc_show_nves_ptct,
4313 vnc_show_nves_ptct_cmd,
4314 "show vnc nves <vn|un> <A.B.C.D|X:X::X:X>",
4315 SHOW_STR
4316 VNC_SHOW_STR
4317 "List known NVEs\n"
4318 "VN address of NVE\n"
4319 "UN address of NVE\n"
4320 "IPv4 interface address\n"
4321 "IPv6 interface address\n")
4322 {
4323 struct prefix pfx;
4324
4325 if (!check_and_display_is_vnc_running(vty))
4326 return CMD_SUCCESS;
4327
4328 if (!str2prefix(argv[4]->arg, &pfx)) {
4329 vty_out(vty, "Malformed address \"%s\"\n", argv[4]->arg);
4330 return CMD_WARNING;
4331 }
4332 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
4333 vty_out(vty, "Invalid address \"%s\"\n", argv[4]->arg);
4334 return CMD_WARNING;
4335 }
4336
4337 if (argv[3]->arg[0] == 'u') {
4338 rfapi_show_nves(vty, NULL, &pfx);
4339 } else {
4340 rfapi_show_nves(vty, &pfx, NULL);
4341 }
4342
4343 return CMD_SUCCESS;
4344 }
4345
4346 /* adapted from rfp_registration_cache_log() */
4347 static void rfapi_show_registrations(struct vty *vty,
4348 struct prefix *restrict_to, int show_local,
4349 int show_remote, int show_holddown,
4350 int show_imported)
4351 {
4352 int printed = 0;
4353
4354 if (!vty)
4355 return;
4356
4357 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4358
4359 if (show_local) {
4360 /* non-expiring, local */
4361 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 1,
4362 0, 0);
4363 }
4364 if (show_remote) {
4365 /* non-expiring, non-local */
4366 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4367 1, 0);
4368 }
4369 if (show_holddown) {
4370 /* expiring, including local */
4371 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 1, 1,
4372 1, 0);
4373 }
4374 if (show_imported) {
4375 /* non-expiring, non-local */
4376 printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4377 1, 1);
4378 }
4379 if (!printed) {
4380 vty_out(vty, "\n");
4381 }
4382 }
4383
4384 DEFUN (vnc_show_registrations_pfx,
4385 vnc_show_registrations_pfx_cmd,
4386 "show vnc registrations [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4387 SHOW_STR
4388 VNC_SHOW_STR
4389 "List active prefix registrations\n"
4390 "Limit output to a particular IPv4 prefix\n"
4391 "Limit output to a particular IPv6 prefix\n"
4392 "Limit output to a particular IPv6 address\n")
4393 {
4394 struct prefix p;
4395 struct prefix *p_addr = NULL;
4396
4397 if (argc > 3) {
4398 if (!str2prefix(argv[3]->arg, &p)) {
4399 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4400 return CMD_SUCCESS;
4401 } else {
4402 p_addr = &p;
4403 }
4404 }
4405
4406 rfapi_show_registrations(vty, p_addr, 1, 1, 1, 1);
4407 return CMD_SUCCESS;
4408 }
4409
4410 DEFUN (vnc_show_registrations_some_pfx,
4411 vnc_show_registrations_some_pfx_cmd,
4412 "show vnc registrations <all|holddown|imported|local|remote> [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4413 SHOW_STR
4414 VNC_SHOW_STR
4415 "List active prefix registrations\n"
4416 "show all registrations\n"
4417 "show only registrations in holddown\n"
4418 "show only imported prefixes\n"
4419 "show only local registrations\n"
4420 "show only remote registrations\n"
4421 "Limit output to a particular prefix or address\n"
4422 "Limit output to a particular prefix or address\n"
4423 "Limit output to a particular prefix or address\n")
4424 {
4425 struct prefix p;
4426 struct prefix *p_addr = NULL;
4427
4428 int show_local = 0;
4429 int show_remote = 0;
4430 int show_holddown = 0;
4431 int show_imported = 0;
4432
4433 if (argc > 4) {
4434 if (!str2prefix(argv[4]->arg, &p)) {
4435 vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4436 return CMD_SUCCESS;
4437 } else {
4438 p_addr = &p;
4439 }
4440 }
4441 switch (argv[3]->arg[0]) {
4442 case 'a':
4443 show_local = 1;
4444 show_remote = 1;
4445 show_holddown = 1;
4446 show_imported = 1;
4447 break;
4448
4449 case 'h':
4450 show_holddown = 1;
4451 break;
4452
4453 case 'i':
4454 show_imported = 1;
4455 break;
4456
4457 case 'l':
4458 show_local = 1;
4459 break;
4460
4461 case 'r':
4462 show_remote = 1;
4463 break;
4464 }
4465
4466 rfapi_show_registrations(vty, p_addr, show_local, show_remote,
4467 show_holddown, show_imported);
4468 return CMD_SUCCESS;
4469 }
4470
4471 DEFUN (vnc_show_responses_pfx,
4472 vnc_show_responses_pfx_cmd,
4473 "show vnc responses [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4474 SHOW_STR
4475 VNC_SHOW_STR
4476 "List recent query responses\n"
4477 "Limit output to a particular IPv4 prefix\n"
4478 "Limit output to a particular IPv6 prefix\n"
4479 "Limit output to a particular IPv6 address\n" )
4480 {
4481 struct prefix p;
4482 struct prefix *p_addr = NULL;
4483
4484 if (argc > 3) {
4485 if (!str2prefix(argv[3]->arg, &p)) {
4486 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4487 return CMD_SUCCESS;
4488 } else {
4489 p_addr = &p;
4490 }
4491 }
4492 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4493
4494 rfapiRibShowResponsesSummary(vty);
4495
4496 rfapiRibShowResponses(vty, p_addr, 0);
4497 rfapiRibShowResponses(vty, p_addr, 1);
4498
4499 return CMD_SUCCESS;
4500 }
4501
4502 DEFUN (vnc_show_responses_some_pfx,
4503 vnc_show_responses_some_pfx_cmd,
4504 "show vnc responses <active|removed> [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4505 SHOW_STR
4506 VNC_SHOW_STR
4507 "List recent query responses\n"
4508 "show only active query responses\n"
4509 "show only removed query responses\n"
4510 "Limit output to a particular IPv4 prefix\n"
4511 "Limit output to a particular IPv6 prefix\n"
4512 "Limit output to a particular IPV6 address\n")
4513 {
4514 struct prefix p;
4515 struct prefix *p_addr = NULL;
4516
4517 int show_active = 0;
4518 int show_removed = 0;
4519
4520 if (!check_and_display_is_vnc_running(vty))
4521 return CMD_SUCCESS;
4522
4523 if (argc > 4) {
4524 if (!str2prefix(argv[4]->arg, &p)) {
4525 vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4526 return CMD_SUCCESS;
4527 } else {
4528 p_addr = &p;
4529 }
4530 }
4531
4532 switch (argv[3]->arg[0]) {
4533 case 'a':
4534 show_active = 1;
4535 break;
4536
4537 case 'r':
4538 show_removed = 1;
4539 break;
4540 }
4541
4542 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4543
4544 rfapiRibShowResponsesSummary(vty);
4545
4546 if (show_active)
4547 rfapiRibShowResponses(vty, p_addr, 0);
4548 if (show_removed)
4549 rfapiRibShowResponses(vty, p_addr, 1);
4550
4551 return CMD_SUCCESS;
4552 }
4553
4554 DEFUN (show_vnc_queries_pfx,
4555 show_vnc_queries_pfx_cmd,
4556 "show vnc queries [<A.B.C.D/M|X:X::X:X/M|YY:YY:YY:YY:YY:YY>]",
4557 SHOW_STR
4558 VNC_SHOW_STR
4559 "List active queries\n"
4560 "Limit output to a particular IPv4 prefix or address\n"
4561 "Limit output to a particular IPv6 prefix\n"
4562 "Limit output to a particualr IPV6 address\n")
4563 {
4564 struct prefix pfx;
4565 struct prefix *p = NULL;
4566
4567 if (argc > 3) {
4568 if (!str2prefix(argv[3]->arg, &pfx)) {
4569 vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4570 return CMD_WARNING;
4571 }
4572 p = &pfx;
4573 }
4574
4575 rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4576
4577 return rfapiShowVncQueries(vty, p);
4578 }
4579
4580 DEFUN (vnc_clear_counters,
4581 vnc_clear_counters_cmd,
4582 "clear vnc counters",
4583 CLEAR_STR
4584 VNC_SHOW_STR
4585 "Reset VNC counters\n")
4586 {
4587 struct bgp *bgp_default = bgp_get_default();
4588 struct rfapi *h;
4589 struct listnode *node;
4590 struct rfapi_descriptor *rfd;
4591
4592 if (!bgp_default)
4593 goto notcfg;
4594
4595 h = bgp_default->rfapi;
4596
4597 if (!h)
4598 goto notcfg;
4599
4600 /* per-rfd */
4601 for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4602 rfd->stat_count_nh_reachable = 0;
4603 rfd->stat_count_nh_removal = 0;
4604 }
4605
4606 /* global */
4607 memset(&h->stat, 0, sizeof(h->stat));
4608
4609 /*
4610 * 151122 per bug 103, set count_registrations = number active.
4611 * Do same for queries
4612 */
4613 h->stat.count_registrations = rfapiApCountAll(bgp_default);
4614 h->stat.count_queries = rfapi_monitor_count(NULL);
4615
4616 rfapiRibShowResponsesSummaryClear();
4617
4618 return CMD_SUCCESS;
4619
4620 notcfg:
4621 vty_out(vty, "VNC is not configured.\n");
4622 return CMD_WARNING;
4623 }
4624
4625 /************************************************************************
4626 * Add prefix with vrf
4627 *
4628 * add [vrf <vrf-name>] prefix <prefix>
4629 * [rd <value>] [label <value>] [local-preference <0-4294967295>]
4630 ************************************************************************/
4631 void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
4632 {
4633 if (rfg->rfd == NULL) { /* need new rfapi_handle */
4634 /* based on rfapi_open */
4635 struct rfapi_descriptor *rfd;
4636
4637 rfd = XCALLOC(MTYPE_RFAPI_DESC,
4638 sizeof(struct rfapi_descriptor));
4639 rfd->bgp = bgp;
4640 rfg->rfd = rfd;
4641 /* leave most fields empty as will get from (dynamic) config
4642 * when needed */
4643 rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
4644 rfd->cookie = rfg;
4645 if (rfg->vn_prefix.family
4646 && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
4647 rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr);
4648 } else {
4649 memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
4650 rfd->vn_addr.addr_family = AF_INET;
4651 rfd->vn_addr.addr.v4 = bgp->router_id;
4652 }
4653 rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for
4654 lookups */
4655 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
4656 rfg->name);
4657 rfapi_init_and_open(bgp, rfd, rfg);
4658 }
4659 }
4660
4661 /* NOTE: this functions parallels vnc_direct_add_rn_group_rd */
4662 static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,
4663 const char *arg_prefix,
4664 const char *arg_rd, /* optional */
4665 const char *arg_label, /* optional */
4666 const char *arg_pref) /* optional */
4667 {
4668 struct bgp *bgp;
4669 struct rfapi_nve_group_cfg *rfg;
4670 struct prefix pfx;
4671 struct rfapi_ip_prefix rpfx;
4672 uint32_t pref = 0;
4673 struct rfapi_vn_option optary[3];
4674 struct rfapi_vn_option *opt = NULL;
4675 int cur_opt = 0;
4676
4677 bgp = bgp_get_default(); /* assume main instance for now */
4678 if (!bgp) {
4679 vty_out(vty, "No BGP process is configured\n");
4680 return CMD_WARNING_CONFIG_FAILED;
4681 }
4682 if (!bgp->rfapi || !bgp->rfapi_cfg) {
4683 vty_out(vty, "VRF support not configured\n");
4684 return CMD_WARNING_CONFIG_FAILED;
4685 }
4686
4687 rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4688 /* arg checks */
4689 if (!rfg) {
4690 vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4691 arg_vrf);
4692 return CMD_WARNING_CONFIG_FAILED;
4693 }
4694 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
4695 vty_out(vty,
4696 "VRF \"%s\" is missing RT import/export RT configuration.\n",
4697 arg_vrf);
4698 return CMD_WARNING_CONFIG_FAILED;
4699 }
4700 if (!rfg->rd.prefixlen && !arg_rd) {
4701 vty_out(vty,
4702 "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n",
4703 arg_vrf);
4704 return CMD_WARNING_CONFIG_FAILED;
4705 }
4706 if (rfg->label > MPLS_LABEL_MAX && !arg_label) {
4707 vty_out(vty,
4708 "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n",
4709 arg_vrf);
4710 return CMD_WARNING_CONFIG_FAILED;
4711 }
4712 if (!str2prefix(arg_prefix, &pfx)) {
4713 vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
4714 return CMD_WARNING_CONFIG_FAILED;
4715 }
4716 rfapiQprefix2Rprefix(&pfx, &rpfx);
4717 memset(optary, 0, sizeof(optary));
4718 if (arg_rd) {
4719 if (opt != NULL)
4720 opt->next = &optary[cur_opt];
4721 opt = &optary[cur_opt++];
4722 opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
4723 if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) {
4724 vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
4725 return CMD_WARNING_CONFIG_FAILED;
4726 }
4727 }
4728 if (rfg->label <= MPLS_LABEL_MAX || arg_label) {
4729 struct rfapi_l2address_option *l2o;
4730 if (opt != NULL)
4731 opt->next = &optary[cur_opt];
4732 opt = &optary[cur_opt++];
4733 opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
4734 l2o = &opt->v.l2addr;
4735 if (arg_label) {
4736 int32_t label;
4737 label = strtoul(arg_label, NULL, 10);
4738 l2o->label = label;
4739 } else
4740 l2o->label = rfg->label;
4741 }
4742 if (arg_pref) {
4743 char *endptr = NULL;
4744 pref = strtoul(arg_pref, &endptr, 10);
4745 if (*endptr != '\0') {
4746 vty_out(vty,
4747 "%% Invalid local-preference value \"%s\"\n",
4748 arg_pref);
4749 return CMD_WARNING_CONFIG_FAILED;
4750 }
4751 }
4752 rpfx.cost = 255 - (pref & 255);
4753 vnc_add_vrf_opener(bgp, rfg);
4754
4755 if (!rfapi_register(rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL,
4756 (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) {
4757 struct rfapi_next_hop_entry *head = NULL;
4758 struct rfapi_next_hop_entry *tail = NULL;
4759 struct rfapi_vn_option *vn_opt_new;
4760
4761 vnc_zlog_debug_verbose("%s: rfapi_register succeeded",
4762 __func__);
4763
4764 if (bgp->rfapi->rfp_methods.local_cb) {
4765 struct rfapi_descriptor *r =
4766 (struct rfapi_descriptor *)rfg->rfd;
4767 vn_opt_new = rfapi_vn_options_dup(opt);
4768
4769 rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
4770 &rpfx, 1,
4771 RFAPI_INFINITE_LIFETIME,
4772 vn_opt_new, &head, &tail);
4773 if (head) {
4774 bgp->rfapi->flags |= RFAPI_INCALLBACK;
4775 (*bgp->rfapi->rfp_methods.local_cb)(head,
4776 r->cookie);
4777 bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
4778 }
4779 head = tail = NULL;
4780 }
4781 vnc_zlog_debug_verbose(
4782 "%s completed, count=%d/%d", __func__,
4783 rfg->rfapi_import_table->local_count[AFI_IP],
4784 rfg->rfapi_import_table->local_count[AFI_IP6]);
4785 return CMD_SUCCESS;
4786 }
4787
4788 vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
4789 vty_out(vty, "Add failed.\n");
4790 return CMD_WARNING_CONFIG_FAILED;
4791 }
4792
4793 DEFUN (add_vrf_prefix_rd_label_pref,
4794 add_vrf_prefix_rd_label_pref_cmd,
4795 "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)}]",
4796 "Add\n"
4797 "To a VRF\n"
4798 "VRF name\n"
4799 "Add/modify prefix related information\n"
4800 "IPv4 prefix\n"
4801 "IPv6 prefix\n"
4802 "Override configured VRF Route Distinguisher\n"
4803 "<as-number>:<number> or <ip-address>:<number>\n"
4804 "Override configured VRF label\n"
4805 "Label Value <0-1048575>\n"
4806 "Set advertised local preference\n"
4807 "local preference (higher=more preferred)\n")
4808 {
4809 char *arg_vrf = argv[2]->arg;
4810 char *arg_prefix = argv[4]->arg;
4811 char *arg_rd = NULL; /* optional */
4812 char *arg_label = NULL; /* optional */
4813 char *arg_pref = NULL; /* optional */
4814 int pargc = 5;
4815 argc--; /* don't parse argument */
4816 while (pargc < argc) {
4817 switch (argv[pargc++]->arg[0]) {
4818 case 'r':
4819 arg_rd = argv[pargc]->arg;
4820 break;
4821 case 'l':
4822 arg_label = argv[pargc]->arg;
4823 break;
4824 case 'p':
4825 arg_pref = argv[pargc]->arg;
4826 break;
4827 default:
4828 break;
4829 }
4830 pargc++;
4831 }
4832
4833 return vnc_add_vrf_prefix(vty, arg_vrf, arg_prefix, arg_rd, arg_label,
4834 arg_pref);
4835 }
4836
4837 /************************************************************************
4838 * del prefix with vrf
4839 *
4840 * clear [vrf <vrf-name>] prefix <prefix> [rd <value>]
4841 ************************************************************************/
4842 static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
4843 {
4844 int count = 0;
4845 afi_t afi = AFI_MAX;
4846 while (afi-- > 0) {
4847 count += rfg->rfapi_import_table->local_count[afi];
4848 }
4849 return count;
4850 }
4851
4852 void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
4853 {
4854 struct rfapi_descriptor *rfd = rfg->rfd;
4855 afi_t afi;
4856
4857 if (rfd == NULL)
4858 return;
4859 /* check if IT is empty */
4860 for (afi = 0;
4861 afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0;
4862 afi++)
4863 ;
4864
4865 if (afi == AFI_MAX) {
4866 vnc_zlog_debug_verbose("%s: closing RFD for VRF %s", __func__,
4867 rfg->name);
4868 rfg->rfd = NULL;
4869 rfapi_close(rfd);
4870 } else {
4871 vnc_zlog_debug_verbose(
4872 "%s: VRF %s afi=%d count=%d", __func__, rfg->name, afi,
4873 rfg->rfapi_import_table->local_count[afi]);
4874 }
4875 }
4876
4877 static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf,
4878 const char *arg_prefix, /* NULL = all */
4879 const char *arg_rd) /* optional */
4880 {
4881 struct rfapi_nve_group_cfg *rfg;
4882 struct rfapi_local_reg_delete_arg cda;
4883 int rc;
4884 int start_count;
4885
4886 if (bgp == NULL)
4887 bgp = bgp_get_default(); /* assume main instance for now */
4888 if (!bgp) {
4889 vty_out(vty, "No BGP process is configured\n");
4890 return CMD_WARNING;
4891 }
4892 if (!bgp->rfapi || !bgp->rfapi_cfg) {
4893 vty_out(vty, "VRF support not configured\n");
4894 return CMD_WARNING;
4895 }
4896 rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4897 /* arg checks */
4898 if (!rfg) {
4899 vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4900 arg_vrf);
4901 return CMD_WARNING;
4902 }
4903 rc = parse_deleter_args(vty, bgp, arg_prefix, NULL, NULL, NULL, NULL,
4904 arg_rd, rfg, &cda);
4905 if (rc != CMD_SUCCESS) /* parse error */
4906 return rc;
4907
4908 start_count = rfapi_cfg_group_it_count(rfg);
4909 clear_vnc_prefix(&cda);
4910 vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count,
4911 start_count);
4912 return CMD_SUCCESS;
4913 }
4914
4915 DEFUN (clear_vrf_prefix_rd,
4916 clear_vrf_prefix_rd_cmd,
4917 "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:NN_OR_IP-ADDRESS]",
4918 "Clear stored data\n"
4919 "From a VRF\n"
4920 "VRF name\n"
4921 "Prefix related information\n"
4922 "IPv4 prefix\n"
4923 "IPv6 prefix\n"
4924 "Specific VRF Route Distinguisher\n"
4925 "<as-number>:<number> or <ip-address>:<number>\n")
4926 {
4927 char *arg_vrf = argv[2]->arg;
4928 char *arg_prefix = NULL; /* optional */
4929 char *arg_rd = NULL; /* optional */
4930 int pargc = 3;
4931 argc--; /* don't check parameter */
4932 while (pargc < argc) {
4933 switch (argv[pargc++]->arg[0]) {
4934 case 'r':
4935 arg_rd = argv[pargc]->arg;
4936 break;
4937 case 'p':
4938 arg_prefix = argv[pargc]->arg;
4939 break;
4940 default:
4941 break;
4942 }
4943 pargc++;
4944 }
4945 return vnc_clear_vrf(vty, NULL, arg_vrf, arg_prefix, arg_rd);
4946 }
4947
4948 DEFUN (clear_vrf_all,
4949 clear_vrf_all_cmd,
4950 "clear vrf NAME all",
4951 "Clear stored data\n"
4952 "From a VRF\n"
4953 "VRF name\n"
4954 "All prefixes\n")
4955 {
4956 char *arg_vrf = argv[2]->arg;
4957 return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL);
4958 }
4959
4960 void rfapi_vty_init()
4961 {
4962 install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd);
4963 install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd);
4964 install_element(ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd);
4965 install_element(ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd);
4966 install_element(ENABLE_NODE, &add_vnc_prefix_lnh_cmd);
4967
4968 install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_cmd);
4969 install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_cmd);
4970 install_element(ENABLE_NODE, &add_vnc_prefix_cost_cmd);
4971 install_element(ENABLE_NODE, &add_vnc_prefix_life_cmd);
4972 install_element(ENABLE_NODE, &add_vnc_prefix_cmd);
4973
4974 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd);
4975 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd);
4976 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd);
4977 install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd);
4978 install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd);
4979 install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_cmd);
4980 install_element(ENABLE_NODE, &add_vnc_mac_vni_life_cmd);
4981 install_element(ENABLE_NODE, &add_vnc_mac_vni_cmd);
4982
4983 install_element(ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd);
4984
4985 install_element(ENABLE_NODE, &clear_vnc_nve_all_cmd);
4986 install_element(ENABLE_NODE, &clear_vnc_nve_vn_un_cmd);
4987 install_element(ENABLE_NODE, &clear_vnc_nve_un_vn_cmd);
4988 install_element(ENABLE_NODE, &clear_vnc_nve_vn_cmd);
4989 install_element(ENABLE_NODE, &clear_vnc_nve_un_cmd);
4990
4991 install_element(ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd);
4992 install_element(ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd);
4993 install_element(ENABLE_NODE, &clear_vnc_prefix_un_cmd);
4994 install_element(ENABLE_NODE, &clear_vnc_prefix_vn_cmd);
4995 install_element(ENABLE_NODE, &clear_vnc_prefix_all_cmd);
4996
4997 install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_cmd);
4998 install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_cmd);
4999 install_element(ENABLE_NODE, &clear_vnc_mac_un_cmd);
5000 install_element(ENABLE_NODE, &clear_vnc_mac_vn_cmd);
5001 install_element(ENABLE_NODE, &clear_vnc_mac_all_cmd);
5002
5003 install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd);
5004 install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd);
5005 install_element(ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd);
5006 install_element(ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd);
5007 install_element(ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd);
5008
5009 install_element(ENABLE_NODE, &clear_vrf_prefix_rd_cmd);
5010 install_element(ENABLE_NODE, &clear_vrf_all_cmd);
5011
5012 install_element(ENABLE_NODE, &vnc_clear_counters_cmd);
5013
5014 install_element(VIEW_NODE, &vnc_show_summary_cmd);
5015 install_element(VIEW_NODE, &vnc_show_nves_cmd);
5016 install_element(VIEW_NODE, &vnc_show_nves_ptct_cmd);
5017
5018 install_element(VIEW_NODE, &vnc_show_registrations_pfx_cmd);
5019 install_element(VIEW_NODE, &vnc_show_registrations_some_pfx_cmd);
5020 install_element(VIEW_NODE, &vnc_show_responses_pfx_cmd);
5021 install_element(VIEW_NODE, &vnc_show_responses_some_pfx_cmd);
5022 install_element(VIEW_NODE, &show_vnc_queries_pfx_cmd);
5023 }