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