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