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