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