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