Line data Source code
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 0 : char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len)
70 : {
71 0 : int year, day, hour, min;
72 :
73 0 : if (seconds >= FMT_YEAR) {
74 0 : year = seconds / FMT_YEAR;
75 0 : seconds -= year * FMT_YEAR;
76 : } else
77 : year = 0;
78 :
79 0 : if (seconds >= FMT_DAY) {
80 0 : day = seconds / FMT_DAY;
81 0 : seconds -= day * FMT_DAY;
82 : } else
83 : day = 0;
84 :
85 0 : if (seconds >= FMT_HOUR) {
86 0 : hour = seconds / FMT_HOUR;
87 0 : seconds -= hour * FMT_HOUR;
88 : } else
89 : hour = 0;
90 :
91 0 : if (seconds >= FMT_MIN) {
92 0 : min = seconds / FMT_MIN;
93 0 : seconds -= min * FMT_MIN;
94 : } else
95 : min = 0;
96 :
97 0 : if (year > 0) {
98 0 : snprintf(buf, len, "%dy%dd%dh", year, day, hour);
99 0 : } else if (day > 0) {
100 0 : snprintf(buf, len, "%dd%dh%dm", day, hour, min);
101 : } else {
102 0 : snprintf(buf, len, "%02d:%02d:%02d", hour, min, seconds);
103 : }
104 :
105 0 : return buf;
106 : }
107 :
108 0 : char *rfapiFormatAge(time_t age, char *buf, size_t len)
109 : {
110 0 : time_t now, age_adjusted;
111 :
112 0 : now = monotime(NULL);
113 0 : age_adjusted = now - age;
114 :
115 0 : 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 0 : void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix)
124 : {
125 0 : uint8_t *pnt;
126 0 : int index;
127 0 : int offset;
128 :
129 0 : static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
130 : 0xf8, 0xfc, 0xfe, 0xff};
131 :
132 0 : switch (rprefix->prefix.addr_family) {
133 0 : case AF_INET:
134 0 : index = rprefix->length / 8;
135 0 : if (index < 4) {
136 0 : pnt = (uint8_t *)&rprefix->prefix.addr.v4;
137 0 : offset = rprefix->length % 8;
138 0 : pnt[index] &= maskbit[offset];
139 0 : index++;
140 0 : while (index < 4)
141 0 : pnt[index++] = 0;
142 : }
143 : break;
144 :
145 0 : case AF_INET6:
146 0 : index = rprefix->length / 8;
147 0 : if (index < 16) {
148 0 : pnt = (uint8_t *)&rprefix->prefix.addr.v6;
149 0 : offset = rprefix->length % 8;
150 0 : pnt[index] &= maskbit[offset];
151 0 : index++;
152 0 : while (index < 16)
153 0 : pnt[index++] = 0;
154 : }
155 : break;
156 :
157 : default:
158 0 : assert(0);
159 : }
160 0 : }
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 0 : int rfapiQprefix2Raddr(struct prefix *qprefix, struct rfapi_ip_addr *raddr)
172 : {
173 0 : memset(raddr, 0, sizeof(struct rfapi_ip_addr));
174 0 : raddr->addr_family = qprefix->family;
175 0 : switch (qprefix->family) {
176 0 : case AF_INET:
177 0 : if (qprefix->prefixlen != IPV4_MAX_BITLEN)
178 : return -1;
179 0 : raddr->addr.v4 = qprefix->u.prefix4;
180 0 : break;
181 0 : case AF_INET6:
182 0 : if (qprefix->prefixlen != IPV6_MAX_BITLEN)
183 : return -1;
184 0 : raddr->addr.v6 = qprefix->u.prefix6;
185 0 : 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 0 : void rfapiQprefix2Rprefix(const struct prefix *qprefix,
197 : struct rfapi_ip_prefix *rprefix)
198 : {
199 0 : memset(rprefix, 0, sizeof(struct rfapi_ip_prefix));
200 0 : rprefix->length = qprefix->prefixlen;
201 0 : rprefix->prefix.addr_family = qprefix->family;
202 0 : switch (qprefix->family) {
203 0 : case AF_INET:
204 0 : rprefix->prefix.addr.v4 = qprefix->u.prefix4;
205 0 : break;
206 0 : case AF_INET6:
207 0 : rprefix->prefix.addr.v6 = qprefix->u.prefix6;
208 0 : break;
209 : default:
210 0 : assert(0);
211 : }
212 0 : }
213 :
214 0 : int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix,
215 : struct prefix *qprefix)
216 : {
217 0 : memset(qprefix, 0, sizeof(struct prefix));
218 0 : qprefix->prefixlen = rprefix->length;
219 0 : qprefix->family = rprefix->prefix.addr_family;
220 :
221 0 : switch (rprefix->prefix.addr_family) {
222 0 : case AF_INET:
223 0 : qprefix->u.prefix4 = rprefix->prefix.addr.v4;
224 0 : break;
225 0 : case AF_INET6:
226 0 : qprefix->u.prefix6 = rprefix->prefix.addr.v6;
227 0 : 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 0 : int rfapiRprefixSame(struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2)
242 : {
243 0 : if (hp1->prefix.addr_family != hp2->prefix.addr_family)
244 : return 0;
245 0 : if (hp1->length != hp2->length)
246 : return 0;
247 0 : if (hp1->prefix.addr_family == AF_INET)
248 0 : if (IPV4_ADDR_SAME(&hp1->prefix.addr.v4, &hp2->prefix.addr.v4))
249 : return 1;
250 0 : if (hp1->prefix.addr_family == AF_INET6)
251 0 : if (IPV6_ADDR_SAME(&hp1->prefix.addr.v6, &hp2->prefix.addr.v6))
252 : return 1;
253 : return 0;
254 : }
255 :
256 0 : int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx)
257 : {
258 0 : memset(pfx, 0, sizeof(struct prefix));
259 0 : pfx->family = hia->addr_family;
260 :
261 0 : switch (hia->addr_family) {
262 0 : case AF_INET:
263 0 : pfx->prefixlen = IPV4_MAX_BITLEN;
264 0 : pfx->u.prefix4 = hia->addr.v4;
265 0 : break;
266 0 : case AF_INET6:
267 0 : pfx->prefixlen = IPV6_MAX_BITLEN;
268 0 : pfx->u.prefix6 = hia->addr.v6;
269 0 : break;
270 : default:
271 : return EAFNOSUPPORT;
272 : }
273 : return 0;
274 : }
275 :
276 0 : void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o, struct prefix *pfx)
277 : {
278 0 : memset(pfx, 0, sizeof(struct prefix));
279 0 : pfx->family = AF_ETHERNET;
280 0 : pfx->prefixlen = 48;
281 0 : pfx->u.prefix_eth = l2o->macaddr;
282 0 : }
283 :
284 0 : char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize)
285 : {
286 0 : return prefix_mac2str(ea, buf, bufsize);
287 : }
288 :
289 0 : int rfapiStr2EthAddr(const char *str, struct ethaddr *ea)
290 : {
291 0 : unsigned int a[6];
292 0 : int i;
293 :
294 0 : 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 0 : for (i = 0; i < 6; ++i)
302 0 : ea->octet[i] = a[i] & 0xff;
303 :
304 : return 0;
305 : }
306 :
307 0 : const char *rfapi_ntop(int af, const void *src, char *buf, socklen_t size)
308 : {
309 0 : if (af == AF_ETHERNET) {
310 0 : return rfapiEthAddr2Str((const struct ethaddr *)src, buf, size);
311 : }
312 :
313 0 : return inet_ntop(af, src, buf, size);
314 : }
315 :
316 0 : int rfapiDebugPrintf(void *dummy, const char *format, ...)
317 : {
318 0 : va_list args;
319 0 : va_start(args, format);
320 0 : vzlog(LOG_DEBUG, format, args);
321 0 : va_end(args);
322 0 : return 0;
323 : }
324 :
325 : PRINTFRR(2, 3)
326 0 : static int rfapiStdioPrintf(void *stream, const char *format, ...)
327 : {
328 0 : FILE *file = NULL;
329 :
330 0 : va_list args;
331 0 : va_start(args, format);
332 :
333 0 : switch ((uintptr_t)stream) {
334 0 : case 1:
335 0 : file = stdout;
336 0 : break;
337 0 : case 2:
338 0 : file = stderr;
339 0 : break;
340 : default:
341 0 : assert(0);
342 : }
343 :
344 0 : vfprintf(file, format, args);
345 0 : va_end(args);
346 0 : 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 0 : static const char *str_vty_newline(struct vty *vty)
355 : {
356 0 : if (vty == &vty_dummy_zlog)
357 0 : return "";
358 : return "\n";
359 : }
360 :
361 0 : 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 0 : if (!stream) {
369 0 : vty_dummy_zlog.type = VTY_SHELL; /* for VTYNL */
370 0 : *vty = &vty_dummy_zlog;
371 0 : *fp = (int (*)(void *, const char *, ...))rfapiDebugPrintf;
372 0 : *outstream = NULL;
373 0 : *vty_newline = str_vty_newline(*vty);
374 0 : return 1;
375 : }
376 :
377 0 : if (((uintptr_t)stream == (uintptr_t)1)
378 0 : || ((uintptr_t)stream == (uintptr_t)2)) {
379 :
380 0 : vty_dummy_stdio.type = VTY_SHELL; /* for VTYNL */
381 0 : *vty = &vty_dummy_stdio;
382 0 : *fp = (int (*)(void *, const char *, ...))rfapiStdioPrintf;
383 0 : *outstream = stream;
384 0 : *vty_newline = str_vty_newline(*vty);
385 0 : return 1;
386 : }
387 :
388 0 : *vty = stream; /* VTYNL requires vty to be legit */
389 0 : *fp = (int (*)(void *, const char *, ...))vty_out;
390 0 : *outstream = stream;
391 0 : *vty_newline = str_vty_newline(*vty);
392 0 : return 1;
393 : }
394 :
395 : /* called from bgpd/bgp_vty.c'route_vty_out() */
396 0 : void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
397 : struct bgp_path_info *bpi, safi_t safi)
398 : {
399 0 : char *s;
400 0 : 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 0 : vty_out(vty, " ");
409 :
410 0 : if (safi == SAFI_MPLS_VPN) {
411 0 : struct prefix pfx_un;
412 :
413 0 : if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
414 0 : char buf[BUFSIZ];
415 :
416 0 : vty_out(vty, "UN=%s",
417 0 : inet_ntop(pfx_un.family, pfx_un.u.val, buf,
418 : sizeof(buf)));
419 : }
420 : }
421 :
422 0 : if (bgp_attr_get_ecommunity(bpi->attr)) {
423 0 : s = ecommunity_ecom2str(bgp_attr_get_ecommunity(bpi->attr),
424 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
425 0 : vty_out(vty, " EC{%s}", s);
426 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
427 : }
428 :
429 0 : if (bpi->extra != NULL) {
430 0 : if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
431 0 : vty_out(vty, " label=VRF2VRF");
432 : else
433 0 : vty_out(vty, " label=%u",
434 : decode_label(&bpi->extra->label[0]));
435 :
436 0 : if (bpi->extra->num_sids) {
437 0 : vty_out(vty, " sid=%pI6", &bpi->extra->sid[0].sid);
438 :
439 0 : if (bpi->extra->sid[0].loc_block_len != 0) {
440 0 : vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
441 : bpi->extra->sid[0].loc_block_len,
442 0 : bpi->extra->sid[0].loc_node_len,
443 0 : bpi->extra->sid[0].func_len,
444 0 : bpi->extra->sid[0].arg_len);
445 : }
446 : }
447 : }
448 :
449 0 : if (!rfapiGetVncLifetime(bpi->attr, &lifetime)) {
450 0 : vty_out(vty, " life=%d", lifetime);
451 : }
452 :
453 0 : vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bpi->type),
454 0 : bpi->sub_type);
455 :
456 0 : vty_out(vty, "%s", HVTYNL);
457 0 : }
458 :
459 0 : void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
460 : {
461 0 : int (*fp)(void *, const char *, ...);
462 0 : struct vty *vty;
463 0 : void *out;
464 0 : const char *vty_newline;
465 0 : struct transit *transit;
466 0 : struct cluster_list *cluster;
467 0 : struct ecommunity *ecomm;
468 0 : struct community *comm;
469 :
470 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
471 0 : return;
472 :
473 0 : fp(out, "Attr[%p]:%s", attr, HVTYNL);
474 0 : if (!attr)
475 : return;
476 :
477 : /* IPv4 Nexthop */
478 0 : fp(out, " nexthop=%pI4%s", &attr->nexthop, HVTYNL);
479 :
480 0 : fp(out, " aspath=%p, refcnt=%d%s", attr->aspath,
481 0 : (attr->aspath ? attr->aspath->refcnt : 0), HVTYNL);
482 :
483 0 : comm = bgp_attr_get_community(attr);
484 0 : fp(out, " community=%p, refcnt=%d%s", comm, (comm ? comm->refcnt : 0),
485 : HVTYNL);
486 :
487 0 : ecomm = bgp_attr_get_ecommunity(attr);
488 0 : fp(out, " ecommunity=%p, refcnt=%d%s", ecomm,
489 : (ecomm ? ecomm->refcnt : 0), HVTYNL);
490 :
491 0 : cluster = bgp_attr_get_cluster(attr);
492 0 : fp(out, " cluster=%p, refcnt=%d%s", cluster,
493 : (cluster ? cluster->refcnt : 0), HVTYNL);
494 :
495 0 : transit = bgp_attr_get_transit(attr);
496 0 : 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 0 : void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
504 : {
505 0 : char buf[BUFSIZ];
506 0 : char *s;
507 :
508 0 : int (*fp)(void *, const char *, ...);
509 0 : struct vty *vty;
510 0 : void *out;
511 0 : const char *vty_newline;
512 :
513 0 : char line[BUFSIZ];
514 0 : char *p = line;
515 0 : int r;
516 0 : int has_macaddr = 0;
517 0 : struct ethaddr macaddr = {{0}};
518 0 : struct rfapi_l2address_option l2o_buf;
519 0 : 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 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
525 0 : return;
526 :
527 0 : if (!bpi)
528 : return;
529 :
530 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
531 0 : && bpi->extra->vnc.import.timer) {
532 0 : struct thread *t =
533 : (struct thread *)bpi->extra->vnc.import.timer;
534 0 : r = snprintf(p, REMAIN, " [%4lu] ",
535 : thread_timer_remain_second(t));
536 0 : INCP;
537 :
538 : } else {
539 0 : r = snprintf(p, REMAIN, " ");
540 0 : INCP;
541 : }
542 :
543 0 : if (bpi->extra) {
544 : /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */
545 0 : if (decode_rd_type(bpi->extra->vnc.import.rd.val)
546 : == RD_TYPE_VNC_ETH) {
547 0 : has_macaddr = 1;
548 0 : memcpy(macaddr.octet, bpi->extra->vnc.import.rd.val + 2,
549 : 6);
550 0 : 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 0 : uint32_t lifetime;
563 0 : int printed_1st_gol = 0;
564 0 : struct bgp_attr_encap_subtlv *pEncap;
565 0 : struct prefix pfx_un;
566 0 : int af = BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len);
567 :
568 : /* Nexthop */
569 0 : if (af == AF_INET) {
570 0 : r = snprintfrr(p, REMAIN, "%pI4",
571 : &bpi->attr->mp_nexthop_global_in);
572 0 : INCP;
573 0 : } else if (af == AF_INET6) {
574 0 : r = snprintfrr(p, REMAIN, "%pI6",
575 : &bpi->attr->mp_nexthop_global);
576 0 : INCP;
577 : } else {
578 0 : r = snprintf(p, REMAIN, "?");
579 0 : INCP;
580 : }
581 :
582 : /*
583 : * VNC tunnel subtlv, if present, contains UN address
584 : */
585 0 : if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
586 0 : r = snprintf(p, REMAIN, " un=%s",
587 0 : inet_ntop(pfx_un.family, pfx_un.u.val, buf,
588 : sizeof(buf)));
589 0 : INCP;
590 : }
591 :
592 : /* Lifetime */
593 0 : if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
594 0 : r = snprintf(p, REMAIN, " nolife");
595 0 : INCP;
596 : } else {
597 0 : if (lifetime == 0xffffffff)
598 0 : r = snprintf(p, REMAIN, " %6s", "infini");
599 : else
600 0 : r = snprintf(p, REMAIN, " %6u", lifetime);
601 0 : INCP;
602 : }
603 :
604 : /* RFP option lengths */
605 0 : for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
606 0 : pEncap = pEncap->next) {
607 :
608 0 : if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
609 0 : if (printed_1st_gol) {
610 0 : r = snprintf(p, REMAIN, ",");
611 0 : INCP;
612 : } else {
613 0 : r = snprintf(p, REMAIN,
614 : " "); /* leading space */
615 0 : INCP;
616 : }
617 0 : r = snprintf(p, REMAIN, "%d", pEncap->length);
618 0 : INCP;
619 0 : printed_1st_gol = 1;
620 : }
621 : }
622 :
623 : /* RT list */
624 0 : if (bgp_attr_get_ecommunity(bpi->attr)) {
625 0 : s = ecommunity_ecom2str(bgp_attr_get_ecommunity(bpi->attr),
626 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
627 0 : r = snprintf(p, REMAIN, " %s", s);
628 0 : INCP;
629 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
630 : }
631 :
632 0 : r = snprintf(p, REMAIN, " bpi@%p", bpi);
633 0 : INCP;
634 :
635 0 : r = snprintf(p, REMAIN, " p@%p", bpi->peer);
636 0 : INCP;
637 :
638 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
639 0 : r = snprintf(p, REMAIN, " HD=yes");
640 0 : INCP;
641 : } else {
642 0 : r = snprintf(p, REMAIN, " HD=no");
643 0 : INCP;
644 : }
645 :
646 0 : if (bpi->attr->weight) {
647 0 : r = snprintf(p, REMAIN, " W=%d", bpi->attr->weight);
648 0 : INCP;
649 : }
650 :
651 0 : if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
652 0 : r = snprintf(p, REMAIN, " LP=%d", bpi->attr->local_pref);
653 0 : INCP;
654 : } else {
655 0 : r = snprintf(p, REMAIN, " LP=unset");
656 0 : INCP;
657 : }
658 :
659 0 : r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bpi->type),
660 0 : bpi->sub_type);
661 0 : INCP;
662 :
663 0 : fp(out, "%s%s", line, HVTYNL);
664 :
665 0 : if (has_macaddr) {
666 0 : 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 0 : if (!rfapiGetL2o(bpi->attr, &l2o_buf)) {
673 0 : fp(out,
674 : " L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s",
675 0 : l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1],
676 0 : l2o_buf.macaddr.octet[2], l2o_buf.macaddr.octet[3],
677 0 : l2o_buf.macaddr.octet[4], l2o_buf.macaddr.octet[5],
678 0 : l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id,
679 : HVTYNL);
680 : }
681 0 : if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
682 0 : const char *sp;
683 :
684 0 : sp = rfapi_ntop(bpi->extra->vnc.import.aux_prefix.family,
685 0 : &bpi->extra->vnc.import.aux_prefix.u.prefix,
686 : buf, BUFSIZ);
687 0 : buf[BUFSIZ - 1] = 0;
688 0 : if (sp) {
689 0 : fp(out, " IP: %s%s", sp, HVTYNL);
690 : }
691 : }
692 : {
693 0 : struct rfapi_un_option *uo =
694 0 : rfapi_encap_tlv_to_un_option(bpi->attr);
695 0 : if (uo) {
696 0 : rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel);
697 0 : rfapi_un_options_free(uo);
698 : }
699 : }
700 : }
701 :
702 0 : char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, int size)
703 : {
704 0 : char buf_pfx[BUFSIZ];
705 0 : char buf_vn[BUFSIZ];
706 0 : char buf_un[BUFSIZ];
707 0 : int rc;
708 :
709 0 : rfapiRfapiIpAddr2Str(&m->rfd->un_addr, buf_vn, BUFSIZ);
710 0 : rfapiRfapiIpAddr2Str(&m->rfd->vn_addr, buf_un, BUFSIZ);
711 :
712 0 : 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 0 : inet_ntop(m->p.family, &m->p.u.prefix, buf_pfx,
716 : sizeof(buf_pfx)),
717 0 : m->p.prefixlen, m->node);
718 0 : buf[size - 1] = 0;
719 0 : if (rc >= size)
720 0 : return NULL;
721 : return buf;
722 : }
723 :
724 0 : static void rfapiDebugPrintMonitorVpn(void *stream, struct rfapi_monitor_vpn *m)
725 : {
726 0 : char buf[BUFSIZ];
727 :
728 0 : int (*fp)(void *, const char *, ...);
729 0 : struct vty *vty;
730 0 : void *out;
731 0 : const char *vty_newline;
732 :
733 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
734 0 : return;
735 :
736 0 : rfapiMonitorVpn2Str(m, buf, BUFSIZ);
737 0 : fp(out, " Mon %s%s", buf, HVTYNL);
738 : }
739 :
740 0 : static void rfapiDebugPrintMonitorEncap(void *stream,
741 : struct rfapi_monitor_encap *m)
742 : {
743 0 : int (*fp)(void *, const char *, ...);
744 0 : struct vty *vty;
745 0 : void *out = NULL;
746 0 : const char *vty_newline;
747 :
748 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
749 0 : return;
750 :
751 0 : fp(out, " Mon m=%p, next=%p, node=%p, bpi=%p%s", m, m->next, m->node,
752 0 : m->bpi, HVTYNL);
753 : }
754 :
755 0 : void rfapiShowItNode(void *stream, struct agg_node *rn)
756 : {
757 0 : struct bgp_path_info *bpi;
758 :
759 0 : int (*fp)(void *, const char *, ...);
760 0 : struct vty *vty;
761 0 : void *out;
762 0 : const char *vty_newline;
763 :
764 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
765 0 : return;
766 :
767 0 : fp(out, "%pRN @%p #%d%s", rn, rn, agg_node_get_lock_count(rn), HVTYNL);
768 :
769 0 : for (bpi = rn->info; bpi; bpi = bpi->next) {
770 0 : rfapiPrintBi(stream, bpi);
771 : }
772 :
773 : /* doesn't show montors */
774 : }
775 :
776 0 : void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt,
777 : int isvpn)
778 : {
779 0 : struct agg_node *rn;
780 0 : char buf[BUFSIZ];
781 :
782 0 : int (*fp)(void *, const char *, ...);
783 0 : struct vty *vty;
784 0 : void *out;
785 0 : const char *vty_newline;
786 :
787 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
788 0 : return;
789 :
790 0 : fp(out, "Import Table [%s]%s", label, HVTYNL);
791 :
792 0 : for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
793 0 : struct bgp_path_info *bpi;
794 0 : const struct prefix *p = agg_node_get_prefix(rn);
795 :
796 0 : if (p->family == AF_ETHERNET) {
797 0 : rfapiEthAddr2Str(&p->u.prefix_eth, buf, sizeof(buf));
798 : } else {
799 0 : inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
800 : }
801 :
802 0 : fp(out, "%s/%d @%p #%d%s", buf, p->prefixlen, rn,
803 0 : agg_node_get_lock_count(rn)
804 : - 1, /* account for loop iterator locking */
805 : HVTYNL);
806 :
807 0 : for (bpi = rn->info; bpi; bpi = bpi->next) {
808 0 : rfapiPrintBi(stream, bpi);
809 : }
810 :
811 0 : if (isvpn) {
812 0 : struct rfapi_monitor_vpn *m;
813 0 : for (m = RFAPI_MONITOR_VPN(rn); m; m = m->next) {
814 0 : rfapiDebugPrintMonitorVpn(stream, m);
815 : }
816 : } else {
817 0 : struct rfapi_monitor_encap *m;
818 0 : for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) {
819 0 : rfapiDebugPrintMonitorEncap(stream, m);
820 : }
821 : }
822 : }
823 : }
824 :
825 0 : int rfapiShowVncQueries(void *stream, struct prefix *pfx_match)
826 : {
827 0 : struct bgp *bgp;
828 0 : struct rfapi *h;
829 0 : struct listnode *node;
830 0 : struct rfapi_descriptor *rfd;
831 :
832 0 : int (*fp)(void *, const char *, ...);
833 0 : struct vty *vty;
834 0 : void *out;
835 0 : const char *vty_newline;
836 :
837 0 : int printedheader = 0;
838 :
839 0 : int nves_total = 0;
840 0 : int nves_with_queries = 0;
841 0 : int nves_displayed = 0;
842 :
843 0 : int queries_total = 0;
844 0 : int queries_displayed = 0;
845 :
846 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
847 : return CMD_WARNING;
848 :
849 0 : bgp = bgp_get_default(); /* assume 1 instance for now */
850 0 : if (!bgp) {
851 0 : vty_out(vty, "No BGP instance\n");
852 0 : return CMD_WARNING;
853 : }
854 :
855 0 : h = bgp->rfapi;
856 0 : if (!h) {
857 0 : vty_out(vty, "No RFAPI instance\n");
858 0 : return CMD_WARNING;
859 : }
860 :
861 0 : for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
862 :
863 0 : struct agg_node *rn;
864 0 : int printedquerier = 0;
865 :
866 :
867 0 : ++nves_total;
868 :
869 0 : if (rfd->mon
870 0 : || (rfd->mon_eth && skiplist_count(rfd->mon_eth))) {
871 0 : ++nves_with_queries;
872 : } else {
873 0 : continue;
874 : }
875 :
876 : /*
877 : * IP Queries
878 : */
879 0 : if (rfd->mon) {
880 0 : for (rn = agg_route_top(rfd->mon); rn;
881 0 : rn = agg_route_next(rn)) {
882 0 : const struct prefix *p =
883 0 : agg_node_get_prefix(rn);
884 0 : struct rfapi_monitor_vpn *m;
885 0 : char buf_remain[BUFSIZ];
886 0 : char buf_pfx[BUFSIZ];
887 :
888 0 : if (!rn->info)
889 0 : continue;
890 :
891 0 : m = rn->info;
892 :
893 0 : ++queries_total;
894 :
895 0 : if (pfx_match && !prefix_match(pfx_match, p)
896 0 : && !prefix_match(p, pfx_match))
897 0 : continue;
898 :
899 0 : ++queries_displayed;
900 :
901 0 : if (!printedheader) {
902 0 : ++printedheader;
903 0 : fp(out, "\n");
904 0 : fp(out, "%-15s %-15s %-15s %-10s\n",
905 : "VN Address", "UN Address", "Target",
906 : "Remaining");
907 : }
908 :
909 0 : if (!printedquerier) {
910 0 : char buf_vn[BUFSIZ];
911 0 : char buf_un[BUFSIZ];
912 :
913 0 : rfapiRfapiIpAddr2Str(&rfd->un_addr,
914 : buf_un, BUFSIZ);
915 0 : rfapiRfapiIpAddr2Str(&rfd->vn_addr,
916 : buf_vn, BUFSIZ);
917 :
918 0 : fp(out, "%-15s %-15s", buf_vn, buf_un);
919 0 : printedquerier = 1;
920 :
921 0 : ++nves_displayed;
922 : } else
923 0 : fp(out, "%-15s %-15s", "", "");
924 0 : buf_remain[0] = 0;
925 0 : rfapiFormatSeconds(
926 0 : thread_timer_remain_second(m->timer),
927 : buf_remain, BUFSIZ);
928 0 : fp(out, " %-15s %-10s\n",
929 0 : 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 0 : if (rfd->mon_eth && skiplist_count(rfd->mon_eth)) {
939 :
940 0 : int rc;
941 0 : void *cursor;
942 0 : struct rfapi_monitor_eth *mon_eth;
943 :
944 0 : for (cursor = NULL,
945 0 : rc = skiplist_next(rfd->mon_eth, NULL,
946 : (void **)&mon_eth, &cursor);
947 0 : rc == 0;
948 0 : rc = skiplist_next(rfd->mon_eth, NULL,
949 : (void **)&mon_eth, &cursor)) {
950 :
951 0 : char buf_remain[BUFSIZ];
952 0 : char buf_pfx[BUFSIZ];
953 0 : struct prefix pfx_mac;
954 :
955 0 : ++queries_total;
956 :
957 0 : vnc_zlog_debug_verbose(
958 : "%s: checking rfd=%p mon_eth=%p",
959 : __func__, rfd, mon_eth);
960 :
961 0 : memset((void *)&pfx_mac, 0,
962 : sizeof(struct prefix));
963 0 : pfx_mac.family = AF_ETHERNET;
964 0 : pfx_mac.prefixlen = 48;
965 0 : pfx_mac.u.prefix_eth = mon_eth->macaddr;
966 :
967 0 : if (pfx_match
968 0 : && !prefix_match(pfx_match, &pfx_mac)
969 0 : && !prefix_match(&pfx_mac, pfx_match))
970 0 : continue;
971 :
972 0 : ++queries_displayed;
973 :
974 0 : if (!printedheader) {
975 0 : ++printedheader;
976 0 : fp(out, "\n");
977 0 : fp(out,
978 : "%-15s %-15s %-17s %10s %-10s\n",
979 : "VN Address", "UN Address", "Target",
980 : "LNI", "Remaining");
981 : }
982 :
983 0 : if (!printedquerier) {
984 0 : char buf_vn[BUFSIZ];
985 0 : char buf_un[BUFSIZ];
986 :
987 0 : rfapiRfapiIpAddr2Str(&rfd->un_addr,
988 : buf_un, BUFSIZ);
989 0 : rfapiRfapiIpAddr2Str(&rfd->vn_addr,
990 : buf_vn, BUFSIZ);
991 :
992 0 : fp(out, "%-15s %-15s", buf_vn, buf_un);
993 0 : printedquerier = 1;
994 :
995 0 : ++nves_displayed;
996 : } else
997 0 : fp(out, "%-15s %-15s", "", "");
998 0 : buf_remain[0] = 0;
999 0 : rfapiFormatSeconds(thread_timer_remain_second(
1000 0 : mon_eth->timer),
1001 : buf_remain, BUFSIZ);
1002 0 : fp(out, " %-17s %10d %-10s\n",
1003 0 : rfapi_ntop(pfx_mac.family, &pfx_mac.u.prefix,
1004 : buf_pfx, BUFSIZ),
1005 0 : mon_eth->logical_net_id, buf_remain);
1006 : }
1007 : }
1008 : }
1009 :
1010 0 : if (queries_total) {
1011 0 : fp(out, "\n");
1012 0 : fp(out, "Displayed %d out of %d total queries\n",
1013 : queries_displayed, queries_total);
1014 : }
1015 : return CMD_SUCCESS;
1016 : }
1017 :
1018 0 : static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
1019 : struct agg_node *rn, struct bgp_path_info *bpi)
1020 : {
1021 0 : int (*fp)(void *, const char *, ...);
1022 0 : struct vty *vty;
1023 0 : void *out;
1024 0 : const char *vty_newline;
1025 0 : struct prefix pfx_un;
1026 0 : struct prefix pfx_vn;
1027 0 : uint8_t cost;
1028 0 : uint32_t lifetime;
1029 0 : bgp_encap_types tun_type = BGP_ENCAP_TYPE_MPLS;/*Default tunnel type*/
1030 :
1031 0 : char buf_pfx[BUFSIZ];
1032 0 : char buf_ntop[BUFSIZ];
1033 0 : char buf_un[BUFSIZ];
1034 0 : char buf_vn[BUFSIZ];
1035 0 : char buf_lifetime[BUFSIZ];
1036 0 : int nlines = 0;
1037 0 : const struct prefix *p = agg_node_get_prefix(rn);
1038 :
1039 0 : if (!stream)
1040 : return 0; /* for debug log, print into buf & call output once */
1041 :
1042 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1043 : return 0;
1044 :
1045 : /*
1046 : * Prefix
1047 : */
1048 0 : buf_pfx[0] = 0;
1049 0 : snprintf(
1050 : buf_pfx, sizeof(buf_pfx), "%s/%d",
1051 0 : rfapi_ntop(p->family, &p->u.prefix, buf_ntop, sizeof(buf_ntop)),
1052 0 : p->prefixlen);
1053 0 : buf_pfx[BUFSIZ - 1] = 0;
1054 0 : nlines++;
1055 :
1056 : /*
1057 : * UN addr
1058 : */
1059 0 : buf_un[0] = 0;
1060 0 : if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx_un)) {
1061 0 : snprintf(buf_un, sizeof(buf_un), "%s",
1062 0 : inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop,
1063 : sizeof(buf_ntop)));
1064 : }
1065 :
1066 0 : bgp_attr_extcom_tunnel_type(bpi->attr, &tun_type);
1067 : /*
1068 : * VN addr
1069 : */
1070 0 : buf_vn[0] = 0;
1071 0 : rfapiNexthop2Prefix(bpi->attr, &pfx_vn);
1072 0 : if (tun_type == BGP_ENCAP_TYPE_MPLS) {
1073 : /* MPLS carries un in nrli next hop (same as vn for IP tunnels)
1074 : */
1075 0 : snprintf(buf_un, sizeof(buf_un), "%s",
1076 0 : inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1077 : sizeof(buf_ntop)));
1078 0 : if (bpi->extra) {
1079 0 : uint32_t l = decode_label(&bpi->extra->label[0]);
1080 0 : snprintf(buf_vn, sizeof(buf_vn), "Label: %d", l);
1081 : } else /* should never happen */
1082 : {
1083 0 : snprintf(buf_vn, sizeof(buf_vn), "Label: N/A");
1084 : }
1085 : } else {
1086 0 : snprintf(buf_vn, sizeof(buf_vn), "%s",
1087 0 : inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1088 : sizeof(buf_ntop)));
1089 : }
1090 0 : buf_vn[BUFSIZ - 1] = 0;
1091 0 : 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 0 : uint32_t local_pref;
1099 :
1100 0 : if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1101 0 : local_pref = bpi->attr->local_pref;
1102 : else
1103 : local_pref = 0;
1104 0 : cost = (local_pref > 255) ? 0 : 255 - local_pref;
1105 :
1106 0 : fp(out, "%-20s ", buf_pfx);
1107 0 : fp(out, "%-15s ", buf_vn);
1108 0 : fp(out, "%-15s ", buf_un);
1109 0 : fp(out, "%-4d ", cost);
1110 :
1111 : /* Lifetime */
1112 : /* NB rfapiGetVncLifetime sets infinite value when returning !0 */
1113 0 : if (rfapiGetVncLifetime(bpi->attr, &lifetime)
1114 0 : || (lifetime == RFAPI_INFINITE_LIFETIME)) {
1115 :
1116 0 : fp(out, "%-10s ", "infinite");
1117 : } else {
1118 0 : time_t t_lifetime = lifetime;
1119 0 : rfapiFormatSeconds(t_lifetime, buf_lifetime, BUFSIZ);
1120 0 : fp(out, "%-10s ", buf_lifetime);
1121 : }
1122 :
1123 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
1124 0 : && bpi->extra->vnc.import.timer) {
1125 :
1126 0 : uint32_t remaining;
1127 0 : time_t age;
1128 0 : char buf_age[BUFSIZ];
1129 :
1130 0 : struct thread *t =
1131 : (struct thread *)bpi->extra->vnc.import.timer;
1132 0 : 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 0 : age = remaining;
1146 : #endif
1147 0 : rfapiFormatSeconds(age, buf_age, BUFSIZ);
1148 :
1149 0 : fp(out, "%-10s ", buf_age);
1150 :
1151 0 : } else if (RFAPI_LOCAL_BI(bpi)) {
1152 :
1153 0 : char buf_age[BUFSIZ];
1154 :
1155 0 : if (bpi->extra && bpi->extra->vnc.import.create_time) {
1156 0 : rfapiFormatAge(bpi->extra->vnc.import.create_time,
1157 : buf_age, BUFSIZ);
1158 : } else {
1159 0 : buf_age[0] = '?';
1160 0 : buf_age[1] = 0;
1161 : }
1162 0 : fp(out, "%-10s ", buf_age);
1163 : }
1164 0 : fp(out, "%s", HVTYNL);
1165 :
1166 0 : 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 0 : if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
1173 0 : const char *sp;
1174 :
1175 0 : sp = rfapi_ntop(
1176 : bpi->extra->vnc.import.aux_prefix.family,
1177 0 : &bpi->extra->vnc.import.aux_prefix.u.prefix,
1178 : buf_ntop, BUFSIZ);
1179 0 : buf_ntop[BUFSIZ - 1] = 0;
1180 :
1181 0 : if (sp && strcmp(buf_vn, sp) != 0) {
1182 0 : fp(out, " IP: %s", sp);
1183 0 : if (nlines == 1)
1184 0 : nlines++;
1185 : }
1186 : }
1187 : }
1188 0 : if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) {
1189 0 : uint32_t l = decode_label(&bpi->extra->label[0]);
1190 0 : if (!MPLS_LABEL_IS_NULL(l)) {
1191 0 : fp(out, " Label: %d", l);
1192 0 : if (nlines == 1)
1193 : nlines++;
1194 : }
1195 : }
1196 0 : if (nlines > 1)
1197 0 : fp(out, "%s", HVTYNL);
1198 :
1199 : return 1;
1200 : }
1201 :
1202 0 : 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 0 : afi_t afi;
1211 0 : int printed_rtlist_hdr = 0;
1212 :
1213 0 : int (*fp)(void *, const char *, ...);
1214 0 : struct vty *vty;
1215 0 : void *out;
1216 0 : const char *vty_newline;
1217 0 : int total = 0;
1218 0 : int printed = 0;
1219 :
1220 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1221 : return printed;
1222 :
1223 0 : for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1224 :
1225 0 : struct agg_node *rn;
1226 :
1227 0 : if (!it->imported_vpn[afi])
1228 0 : continue;
1229 :
1230 0 : for (rn = agg_route_top(it->imported_vpn[afi]); rn;
1231 0 : rn = agg_route_next(rn)) {
1232 0 : const struct prefix *p = agg_node_get_prefix(rn);
1233 0 : struct bgp_path_info *bpi;
1234 0 : int count_only;
1235 :
1236 : /* allow for wider or more narrow mask from user */
1237 0 : if (prefix_only && !prefix_match(prefix_only, p)
1238 0 : && !prefix_match(p, prefix_only))
1239 : count_only = 1;
1240 : else
1241 : count_only = 0;
1242 :
1243 0 : for (bpi = rn->info; bpi; bpi = bpi->next) {
1244 :
1245 0 : if (!show_local && RFAPI_LOCAL_BI(bpi)) {
1246 :
1247 : /* local route from RFP */
1248 0 : continue;
1249 : }
1250 :
1251 0 : if (!show_remote && !RFAPI_LOCAL_BI(bpi)) {
1252 :
1253 : /* remote route */
1254 0 : continue;
1255 : }
1256 :
1257 0 : if (show_expiring
1258 0 : && !CHECK_FLAG(bpi->flags,
1259 : BGP_PATH_REMOVED))
1260 0 : continue;
1261 :
1262 : if (!show_expiring
1263 0 : && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1264 0 : continue;
1265 :
1266 0 : if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT
1267 0 : || bpi->type
1268 : == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
1269 0 : if (!show_imported)
1270 0 : continue;
1271 : } else {
1272 0 : if (show_imported)
1273 0 : continue;
1274 : }
1275 :
1276 0 : total++;
1277 0 : if (count_only == 1)
1278 0 : continue;
1279 0 : if (!printed_rtlist_hdr) {
1280 0 : const char *agetype = "";
1281 0 : char *s;
1282 0 : const char *type = "";
1283 0 : if (show_imported) {
1284 : type = "Imported";
1285 : } else {
1286 0 : if (show_expiring) {
1287 : type = "Holddown";
1288 : } else {
1289 0 : if (RFAPI_LOCAL_BI(
1290 : bpi)) {
1291 : type = "Local";
1292 : } else {
1293 0 : type = "Remote";
1294 : }
1295 : }
1296 : }
1297 :
1298 0 : s = ecommunity_ecom2str(
1299 : it->rt_import_list,
1300 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1301 :
1302 0 : if (pLni) {
1303 0 : fp(out,
1304 : "%s[%s] L2VPN Network 0x%x (%u) RT={%s}",
1305 0 : HVTYNL, type, *pLni,
1306 0 : (*pLni & 0xfff), s);
1307 : } else {
1308 0 : fp(out, "%s[%s] Prefix RT={%s}",
1309 0 : HVTYNL, type, s);
1310 : }
1311 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1312 :
1313 0 : if (it->rfg && it->rfg->name) {
1314 0 : fp(out, " %s \"%s\"",
1315 0 : (it->rfg->type == RFAPI_GROUP_CFG_VRF
1316 : ? "VRF"
1317 : : "NVE group"),
1318 : it->rfg->name);
1319 : }
1320 0 : fp(out, "%s", HVTYNL);
1321 0 : if (show_expiring) {
1322 : #ifdef RFAPI_REGISTRATIONS_REPORT_AGE
1323 : agetype = "Age";
1324 : #else
1325 : agetype = "Remaining";
1326 : #endif
1327 0 : } else if (show_local) {
1328 0 : agetype = "Age";
1329 : }
1330 :
1331 0 : printed_rtlist_hdr = 1;
1332 :
1333 0 : 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 0 : printed += rfapiPrintRemoteRegBi(bgp, stream,
1340 : rn, bpi);
1341 : }
1342 : }
1343 : }
1344 :
1345 0 : if (printed > 0) {
1346 :
1347 0 : const char *type = "prefixes";
1348 :
1349 0 : if (show_imported) {
1350 : type = "imported prefixes";
1351 : } else {
1352 0 : if (show_expiring) {
1353 : type = "prefixes in holddown";
1354 : } else {
1355 0 : if (show_local && !show_remote) {
1356 : type = "locally registered prefixes";
1357 0 : } else if (!show_local && show_remote) {
1358 0 : type = "remotely registered prefixes";
1359 : }
1360 : }
1361 : }
1362 :
1363 0 : fp(out, "Displayed %d out of %d %s%s", printed, total, type,
1364 0 : 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 0 : int rfapiShowRemoteRegistrations(void *stream, struct prefix *prefix_only,
1381 : int show_expiring, int show_local,
1382 : int show_remote, int show_imported)
1383 : {
1384 0 : struct bgp *bgp;
1385 0 : struct rfapi *h;
1386 0 : struct rfapi_import_table *it;
1387 0 : int printed = 0;
1388 :
1389 0 : bgp = bgp_get_default();
1390 0 : if (!bgp) {
1391 : return printed;
1392 : }
1393 :
1394 0 : h = bgp->rfapi;
1395 0 : if (!h) {
1396 : return printed;
1397 : }
1398 :
1399 0 : for (it = h->imports; it; it = it->next) {
1400 0 : printed += rfapiShowRemoteRegistrationsIt(
1401 : bgp, stream, it, prefix_only, show_expiring, show_local,
1402 : show_remote, show_imported, NULL);
1403 : }
1404 :
1405 0 : if (h->import_mac) {
1406 0 : void *cursor = NULL;
1407 0 : int rc;
1408 0 : uintptr_t lni_as_ptr;
1409 0 : uint32_t lni;
1410 0 : uint32_t *pLni;
1411 :
1412 0 : for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1413 : (void **)&it, &cursor);
1414 0 : !rc;
1415 0 : rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1416 : (void **)&it, &cursor)) {
1417 0 : pLni = NULL;
1418 0 : if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) {
1419 0 : lni = (uint32_t)(lni_as_ptr & 0xffffffff);
1420 0 : pLni = &lni;
1421 : }
1422 :
1423 0 : 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 0 : const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf,
1449 : int bufsize)
1450 : {
1451 0 : const char *rc = NULL;
1452 :
1453 0 : switch (a->addr_family) {
1454 0 : case AF_INET:
1455 0 : rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1456 0 : break;
1457 0 : case AF_INET6:
1458 0 : rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1459 0 : break;
1460 : }
1461 0 : return rc;
1462 : }
1463 :
1464 0 : void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a)
1465 : {
1466 0 : char buf[BUFSIZ];
1467 0 : const char *rc = NULL;
1468 :
1469 0 : int (*fp)(void *, const char *, ...);
1470 0 : struct vty *vty;
1471 0 : void *out = NULL;
1472 0 : const char *vty_newline;
1473 :
1474 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1475 0 : return;
1476 :
1477 0 : rc = rfapiRfapiIpAddr2Str(a, buf, BUFSIZ);
1478 :
1479 0 : if (rc)
1480 0 : fp(out, "%s", buf);
1481 : }
1482 :
1483 0 : const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf,
1484 : int bufsize)
1485 : {
1486 0 : struct rfapi_ip_addr *a = &p->prefix;
1487 0 : const char *rc = NULL;
1488 :
1489 0 : switch (a->addr_family) {
1490 0 : case AF_INET:
1491 0 : rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1492 0 : break;
1493 0 : case AF_INET6:
1494 0 : rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1495 0 : break;
1496 : }
1497 :
1498 0 : if (rc) {
1499 0 : int alen = strlen(buf);
1500 0 : int remaining = bufsize - alen - 1;
1501 0 : int slen;
1502 :
1503 0 : if (remaining > 0) {
1504 0 : slen = snprintf(buf + alen, remaining, "/%u",
1505 0 : p->length);
1506 0 : if (slen < remaining) /* see man page for snprintf(3) */
1507 : return rc;
1508 : }
1509 : }
1510 :
1511 : return NULL;
1512 : }
1513 :
1514 0 : void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p)
1515 : {
1516 0 : char buf[BUFSIZ];
1517 0 : const char *rc;
1518 :
1519 0 : int (*fp)(void *, const char *, ...);
1520 0 : struct vty *vty;
1521 0 : void *out = NULL;
1522 0 : const char *vty_newline;
1523 :
1524 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1525 0 : return;
1526 :
1527 0 : rc = rfapiRfapiIpPrefix2Str(p, buf, BUFSIZ);
1528 :
1529 0 : if (rc)
1530 0 : fp(out, "%s:%u", buf, p->cost);
1531 : else
1532 0 : fp(out, "?/?:?");
1533 : }
1534 :
1535 0 : void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
1536 : safi_t safi, struct prefix *p)
1537 : {
1538 0 : afi_t afi; /* of the VN address */
1539 0 : struct bgp_dest *bd;
1540 0 : struct bgp_path_info *bpi;
1541 0 : uint8_t type = ZEBRA_ROUTE_BGP;
1542 0 : struct bgp *bgp;
1543 0 : int printed = 0;
1544 0 : struct prefix_rd prd0;
1545 0 : struct prefix_rd *prd;
1546 :
1547 : /*
1548 : * Find the bgp_path in the RIB corresponding to this
1549 : * prefix and rfd
1550 : */
1551 :
1552 0 : afi = family2afi(p->family);
1553 0 : assert(afi == AFI_IP || afi == AFI_IP6);
1554 :
1555 0 : bgp = bgp_get_default(); /* assume 1 instance for now */
1556 0 : assert(bgp);
1557 :
1558 0 : if (safi == SAFI_ENCAP) {
1559 0 : memset(&prd0, 0, sizeof(prd0));
1560 0 : prd0.family = AF_UNSPEC;
1561 0 : prd0.prefixlen = 64;
1562 0 : prd = &prd0;
1563 : } else {
1564 0 : prd = &rfd->rd;
1565 : }
1566 0 : bd = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
1567 :
1568 0 : vty_out(vty, " bd=%p%s", bd, HVTYNL);
1569 :
1570 0 : for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
1571 0 : if (bpi->peer == rfd->peer && bpi->type == type
1572 0 : && bpi->sub_type == BGP_ROUTE_RFP && bpi->extra
1573 0 : && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
1574 :
1575 0 : rfapiPrintBi(vty, bpi);
1576 0 : printed = 1;
1577 : }
1578 : }
1579 :
1580 0 : if (!printed) {
1581 0 : vty_out(vty, " --?--%s", HVTYNL);
1582 0 : return;
1583 : }
1584 : }
1585 :
1586 0 : 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 0 : char *s;
1595 0 : void *cursor;
1596 0 : int rc;
1597 0 : afi_t afi;
1598 0 : struct rfapi_adb *adb;
1599 :
1600 0 : vty_out(vty, "%-10p ", rfd);
1601 0 : rfapiPrintRfapiIpAddr(vty, &rfd->un_addr);
1602 0 : vty_out(vty, " ");
1603 0 : rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
1604 0 : vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
1605 0 : vty_out(vty, "%pRD", &rfd->rd);
1606 0 : vty_out(vty, " %d", rfd->response_lifetime);
1607 0 : vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
1608 0 : vty_out(vty, "%s", HVTYNL);
1609 :
1610 0 : vty_out(vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL);
1611 :
1612 : /* export RT list */
1613 0 : if (rfd->rt_export_list) {
1614 0 : s = ecommunity_ecom2str(rfd->rt_export_list,
1615 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1616 0 : vty_out(vty, " Export %s%s", s, HVTYNL);
1617 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1618 : } else {
1619 0 : vty_out(vty, " Export (nil)%s", HVTYNL);
1620 : }
1621 :
1622 : /* import RT list */
1623 0 : if (rfd->import_table) {
1624 0 : s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1625 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1626 0 : vty_out(vty, " Import %s%s", s, HVTYNL);
1627 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1628 : } else {
1629 0 : vty_out(vty, " Import (nil)%s", HVTYNL);
1630 : }
1631 :
1632 0 : for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1633 0 : uint8_t family;
1634 :
1635 0 : family = afi2family(afi);
1636 0 : if (!family)
1637 0 : continue;
1638 :
1639 0 : cursor = NULL;
1640 0 : for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1641 : (void **)&adb, &cursor);
1642 0 : rc == 0;
1643 0 : rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1644 : (void **)&adb, &cursor)) {
1645 :
1646 : /* group like family prefixes together in output */
1647 0 : if (family != adb->u.s.prefix_ip.family)
1648 0 : continue;
1649 :
1650 0 : vty_out(vty, " Adv Pfx: %pFX%s", &adb->u.s.prefix_ip,
1651 : HVTYNL);
1652 0 : rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1653 0 : &adb->u.s.prefix_ip);
1654 : }
1655 : }
1656 0 : for (rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1657 : (void **)&adb, &cursor);
1658 0 : rc == 0; rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1659 : (void **)&adb, &cursor)) {
1660 0 : 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 0 : rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1665 0 : &adb->u.s.prefix_ip);
1666 : }
1667 0 : vty_out(vty, "%s", HVTYNL);
1668 0 : }
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 0 : void rfapiPrintMatchingDescriptors(struct vty *vty, struct prefix *vn_prefix,
1675 : struct prefix *un_prefix)
1676 : {
1677 0 : struct bgp *bgp;
1678 0 : struct rfapi *h;
1679 0 : struct listnode *ln;
1680 0 : struct rfapi_descriptor *rfd;
1681 0 : int printed = 0;
1682 :
1683 0 : bgp = bgp_get_default(); /* assume 1 instance for now */
1684 0 : if (!bgp)
1685 : return;
1686 :
1687 0 : h = bgp->rfapi;
1688 0 : assert(h);
1689 :
1690 0 : for (ln = listhead(&h->descriptors); ln; ln = listnextnode(ln)) {
1691 0 : rfd = listgetdata(ln);
1692 :
1693 0 : struct prefix pfx;
1694 :
1695 0 : if (vn_prefix) {
1696 0 : assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
1697 0 : if (!prefix_match(vn_prefix, &pfx))
1698 0 : continue;
1699 : }
1700 :
1701 0 : if (un_prefix) {
1702 0 : assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
1703 0 : if (!prefix_match(un_prefix, &pfx))
1704 0 : continue;
1705 : }
1706 :
1707 0 : if (!printed) {
1708 : /* print column header */
1709 0 : 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 0 : rfapiPrintDescriptor(vty, rfd);
1714 0 : printed = 1;
1715 : }
1716 : }
1717 :
1718 :
1719 : /*
1720 : * Parse an address and put into a struct prefix
1721 : */
1722 0 : int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, struct prefix *p)
1723 : {
1724 0 : if (!str2prefix(str, p)) {
1725 0 : vty_out(vty, "Malformed address \"%s\"%s", str ? str : "null",
1726 : HVTYNL);
1727 0 : return CMD_WARNING;
1728 : }
1729 0 : switch (p->family) {
1730 0 : case AF_INET:
1731 0 : if (p->prefixlen != IPV4_MAX_BITLEN) {
1732 0 : vty_out(vty, "Not a host address: \"%s\"%s", str,
1733 : HVTYNL);
1734 0 : return CMD_WARNING;
1735 : }
1736 : break;
1737 0 : case AF_INET6:
1738 0 : if (p->prefixlen != IPV6_MAX_BITLEN) {
1739 0 : vty_out(vty, "Not a host address: \"%s\"%s", str,
1740 : HVTYNL);
1741 0 : return CMD_WARNING;
1742 : }
1743 : break;
1744 0 : default:
1745 0 : vty_out(vty, "Invalid address \"%s\"%s", str, HVTYNL);
1746 0 : return CMD_WARNING;
1747 : }
1748 : return 0;
1749 : }
1750 :
1751 0 : int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str,
1752 : struct rfapi_ip_addr *hai)
1753 : {
1754 0 : struct prefix pfx;
1755 0 : int rc;
1756 :
1757 0 : rc = rfapiCliGetPrefixAddr(vty, str, &pfx);
1758 0 : if (rc)
1759 : return rc;
1760 :
1761 0 : hai->addr_family = pfx.family;
1762 0 : if (pfx.family == AF_INET)
1763 0 : hai->addr.v4 = pfx.u.prefix4;
1764 : else
1765 0 : 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 0 : void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops)
1776 : {
1777 0 : struct rfapi_next_hop_entry *nh;
1778 0 : int count;
1779 :
1780 0 : int (*fp)(void *, const char *, ...);
1781 0 : struct vty *vty;
1782 0 : void *out;
1783 0 : const char *vty_newline;
1784 :
1785 : #define REMAIN (BUFSIZ - (p-line))
1786 : #define INCP {p += (r > REMAIN)? REMAIN: r;}
1787 :
1788 0 : if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1789 0 : return;
1790 :
1791 0 : for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) {
1792 :
1793 0 : char line[BUFSIZ];
1794 0 : char *p = line;
1795 0 : int r;
1796 :
1797 0 : r = snprintf(p, REMAIN, "%3d pfx=", count);
1798 0 : INCP;
1799 :
1800 0 : if (rfapiRfapiIpPrefix2Str(&nh->prefix, p, REMAIN)) {
1801 : /* it fit, so count length */
1802 0 : r = strlen(p);
1803 : } else {
1804 : /* didn't fit */
1805 0 : goto truncate;
1806 : }
1807 0 : INCP;
1808 :
1809 0 : r = snprintf(p, REMAIN, ", un=");
1810 0 : INCP;
1811 :
1812 0 : if (rfapiRfapiIpAddr2Str(&nh->un_address, p, REMAIN)) {
1813 : /* it fit, so count length */
1814 0 : r = strlen(p);
1815 : } else {
1816 : /* didn't fit */
1817 0 : goto truncate;
1818 : }
1819 0 : INCP;
1820 :
1821 0 : r = snprintf(p, REMAIN, ", vn=");
1822 0 : INCP;
1823 :
1824 0 : if (rfapiRfapiIpAddr2Str(&nh->vn_address, p, REMAIN)) {
1825 : /* it fit, so count length */
1826 0 : r = strlen(p);
1827 : } else {
1828 : /* didn't fit */
1829 : goto truncate;
1830 : }
1831 0 : INCP;
1832 :
1833 0 : truncate:
1834 0 : line[BUFSIZ - 1] = 0;
1835 0 : fp(out, "%s%s", line, HVTYNL);
1836 :
1837 : /*
1838 : * options
1839 : */
1840 0 : if (nh->vn_options) {
1841 0 : struct rfapi_vn_option *vo;
1842 0 : char offset[] = " ";
1843 :
1844 0 : for (vo = nh->vn_options; vo; vo = vo->next) {
1845 0 : char pbuf[100];
1846 :
1847 0 : switch (vo->type) {
1848 0 : case RFAPI_VN_OPTION_TYPE_L2ADDR:
1849 0 : rfapiEthAddr2Str(&vo->v.l2addr.macaddr,
1850 : pbuf, sizeof(pbuf));
1851 0 : fp(out,
1852 : "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s",
1853 : offset, pbuf,
1854 0 : (vo->v.l2addr.label & 0x00ffffff),
1855 0 : (vo->v.l2addr.logical_net_id
1856 : & 0x00ffffff),
1857 0 : vo->v.l2addr.local_nve_id, HVTYNL);
1858 0 : break;
1859 :
1860 : case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP:
1861 0 : fp(out, "%sLNH %pFX cost=%d%s", offset,
1862 : &vo->v.local_nexthop.addr,
1863 0 : vo->v.local_nexthop.cost, HVTYNL);
1864 0 : break;
1865 :
1866 : case RFAPI_VN_OPTION_TYPE_INTERNAL_RD:
1867 0 : fp(out,
1868 : "%svn option type %d (unknown)%s",
1869 : offset, vo->type, HVTYNL);
1870 0 : break;
1871 : }
1872 : }
1873 : }
1874 0 : if (nh->un_options) {
1875 0 : struct rfapi_un_option *uo;
1876 0 : char offset[] = " ";
1877 :
1878 0 : for (uo = nh->un_options; uo; uo = uo->next) {
1879 0 : switch (uo->type) {
1880 0 : case RFAPI_UN_OPTION_TYPE_TUNNELTYPE:
1881 0 : rfapi_print_tunneltype_option(
1882 : stream, 8, &uo->v.tunnel);
1883 0 : break;
1884 0 : case RFAPI_UN_OPTION_TYPE_PROVISIONAL:
1885 0 : fp(out, "%sUN Option type %d%s", offset,
1886 : uo->type, vty_newline);
1887 0 : break;
1888 : }
1889 : }
1890 : }
1891 : }
1892 : }
1893 :
1894 : /***********************************************************************
1895 : * STATIC ROUTES
1896 : ***********************************************************************/
1897 :
1898 : /*
1899 : * Add another nexthop to the NHL
1900 : */
1901 0 : 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 0 : struct rfapi_next_hop_entry *new;
1911 :
1912 : /*
1913 : * construct NHL
1914 : */
1915 :
1916 0 : new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry));
1917 0 : new->prefix = *rprefix;
1918 0 : new->un_address = *un_addr;
1919 0 : new->vn_address = *vn_addr;
1920 :
1921 0 : new->vn_options = vn_options;
1922 0 : if (is_add) {
1923 0 : new->lifetime = lifetime;
1924 : } else {
1925 0 : new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1926 : }
1927 :
1928 0 : if (*tail)
1929 0 : (*tail)->next = new;
1930 0 : *tail = new;
1931 0 : if (!*head) {
1932 0 : *head = new;
1933 : }
1934 0 : }
1935 :
1936 :
1937 : static int
1938 0 : 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 0 : const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
1948 0 : const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
1949 0 : const char *arg_un = carg_un ? carg_un->arg : NULL;
1950 0 : const char *arg_cost = carg_cost ? carg_cost->arg : NULL;
1951 0 : const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL;
1952 0 : const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL;
1953 0 : const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
1954 0 : struct rfapi_ip_addr vn_address;
1955 0 : struct rfapi_ip_addr un_address;
1956 0 : struct prefix pfx;
1957 0 : struct rfapi_ip_prefix rpfx;
1958 0 : uint32_t cost;
1959 0 : uint32_t lnh_cost;
1960 0 : uint32_t lifetime;
1961 0 : rfapi_handle rfd;
1962 0 : struct rfapi_vn_option optary[10]; /* XXX must be big enough */
1963 0 : struct rfapi_vn_option *opt = NULL;
1964 0 : int opt_next = 0;
1965 :
1966 0 : int rc = CMD_WARNING_CONFIG_FAILED;
1967 0 : char *endptr;
1968 0 : struct bgp *bgp;
1969 0 : struct rfapi *h;
1970 0 : struct rfapi_cfg *rfapi_cfg;
1971 :
1972 0 : const char *arg_lnh = NULL;
1973 0 : const char *arg_lnh_cost = NULL;
1974 :
1975 0 : bgp = bgp_get_default(); /* assume 1 instance for now */
1976 0 : if (!bgp) {
1977 0 : if (vty)
1978 0 : vty_out(vty, "BGP not configured\n");
1979 0 : return CMD_WARNING_CONFIG_FAILED;
1980 : }
1981 :
1982 0 : h = bgp->rfapi;
1983 0 : rfapi_cfg = bgp->rfapi_cfg;
1984 0 : if (!h || !rfapi_cfg) {
1985 0 : if (vty)
1986 0 : vty_out(vty, "RFAPI not configured\n");
1987 0 : return CMD_WARNING_CONFIG_FAILED;
1988 : }
1989 :
1990 0 : for (; argc; --argc, ++argv) {
1991 0 : if (strmatch(argv[0]->text, "local-next-hop")) {
1992 0 : if (arg_lnh) {
1993 0 : vty_out(vty,
1994 : "local-next-hop specified more than once\n");
1995 0 : return CMD_WARNING_CONFIG_FAILED;
1996 : }
1997 0 : if (argc <= 1) {
1998 0 : vty_out(vty,
1999 : "Missing parameter for local-next-hop\n");
2000 0 : return CMD_WARNING_CONFIG_FAILED;
2001 : }
2002 0 : ++argv;
2003 0 : --argc;
2004 0 : arg_lnh = argv[0]->arg;
2005 : }
2006 0 : if (strmatch(argv[0]->text, "local-cost")) {
2007 0 : if (arg_lnh_cost) {
2008 0 : vty_out(vty,
2009 : "local-cost specified more than once\n");
2010 0 : return CMD_WARNING_CONFIG_FAILED;
2011 : }
2012 0 : if (argc <= 1) {
2013 0 : vty_out(vty,
2014 : "Missing parameter for local-cost\n");
2015 0 : return CMD_WARNING_CONFIG_FAILED;
2016 : }
2017 0 : ++argv;
2018 0 : --argc;
2019 0 : arg_lnh_cost = argv[0]->arg;
2020 : }
2021 : }
2022 :
2023 0 : if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, &vn_address)))
2024 0 : goto fail;
2025 0 : if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, &un_address)))
2026 0 : goto fail;
2027 :
2028 : /* arg_prefix is optional if mac address is given */
2029 0 : if (arg_macaddr && !arg_prefix) {
2030 : /*
2031 : * fake up a 0/32 or 0/128 prefix
2032 : */
2033 0 : switch (vn_address.addr_family) {
2034 : case AF_INET:
2035 : arg_prefix = "0.0.0.0/32";
2036 : break;
2037 0 : case AF_INET6:
2038 0 : arg_prefix = "0::0/128";
2039 0 : break;
2040 0 : default:
2041 0 : vty_out(vty,
2042 : "Internal error, unknown VN address family\n");
2043 0 : return CMD_WARNING_CONFIG_FAILED;
2044 : }
2045 : }
2046 :
2047 0 : if (!str2prefix(arg_prefix, &pfx)) {
2048 0 : vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2049 0 : goto fail;
2050 : }
2051 0 : if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2052 0 : vty_out(vty, "prefix \"%s\" has invalid address family\n",
2053 : arg_prefix);
2054 0 : goto fail;
2055 : }
2056 :
2057 :
2058 0 : memset(optary, 0, sizeof(optary));
2059 :
2060 0 : if (arg_cost) {
2061 0 : endptr = NULL;
2062 0 : cost = strtoul(arg_cost, &endptr, 10);
2063 0 : if (*endptr != '\0' || cost > 255) {
2064 0 : vty_out(vty, "%% Invalid %s value\n", "cost");
2065 0 : goto fail;
2066 : }
2067 : } else {
2068 : cost = 255;
2069 : }
2070 :
2071 0 : if (arg_lifetime) {
2072 0 : if (!strcmp(arg_lifetime, "infinite")) {
2073 : lifetime = RFAPI_INFINITE_LIFETIME;
2074 : } else {
2075 0 : endptr = NULL;
2076 0 : lifetime = strtoul(arg_lifetime, &endptr, 10);
2077 0 : if (*endptr != '\0') {
2078 0 : vty_out(vty, "%% Invalid %s value\n",
2079 : "lifetime");
2080 0 : goto fail;
2081 : }
2082 : }
2083 : } else {
2084 : lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */
2085 : }
2086 :
2087 0 : if (arg_lnh_cost) {
2088 0 : if (!arg_lnh) {
2089 0 : vty_out(vty,
2090 : "%% %s may only be specified with local-next-hop\n",
2091 : "local-cost");
2092 0 : goto fail;
2093 : }
2094 0 : endptr = NULL;
2095 0 : lnh_cost = strtoul(arg_lnh_cost, &endptr, 10);
2096 0 : if (*endptr != '\0' || lnh_cost > 255) {
2097 0 : vty_out(vty, "%% Invalid %s value\n", "local-cost");
2098 0 : goto fail;
2099 : }
2100 : } else {
2101 : lnh_cost = 255;
2102 : }
2103 :
2104 0 : if (arg_lnh) {
2105 0 : if (!arg_prefix) {
2106 0 : vty_out(vty,
2107 : "%% %s may only be specified with prefix\n",
2108 : "local-next-hop");
2109 0 : goto fail;
2110 : }
2111 0 : if ((rc = rfapiCliGetPrefixAddr(
2112 : vty, arg_lnh,
2113 : &optary[opt_next].v.local_nexthop.addr))) {
2114 :
2115 0 : goto fail;
2116 : }
2117 :
2118 0 : optary[opt_next].v.local_nexthop.cost = lnh_cost;
2119 0 : optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP;
2120 :
2121 0 : if (opt_next) {
2122 : optary[opt_next - 1].next = optary + opt_next;
2123 : } else {
2124 0 : opt = optary;
2125 : }
2126 0 : ++opt_next;
2127 : }
2128 :
2129 0 : if (arg_vni && !arg_macaddr) {
2130 0 : vty_out(vty, "%% %s may only be specified with mac address\n",
2131 : "virtual-network-identifier");
2132 0 : goto fail;
2133 : }
2134 :
2135 0 : if (arg_macaddr) {
2136 0 : if (!arg_vni) {
2137 0 : vty_out(vty,
2138 : "Missing \"vni\" parameter (mandatory with mac)\n");
2139 0 : return CMD_WARNING_CONFIG_FAILED;
2140 : }
2141 0 : optary[opt_next].v.l2addr.logical_net_id =
2142 0 : strtoul(arg_vni, NULL, 10);
2143 :
2144 0 : if ((rc = rfapiStr2EthAddr(
2145 : arg_macaddr,
2146 : &optary[opt_next].v.l2addr.macaddr))) {
2147 0 : vty_out(vty, "Invalid %s value\n", "mac address");
2148 0 : goto fail;
2149 : }
2150 : /* TBD label, NVE ID */
2151 :
2152 0 : optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
2153 :
2154 0 : if (opt_next) {
2155 0 : optary[opt_next - 1].next = optary + opt_next;
2156 : } else {
2157 : opt = optary;
2158 : }
2159 0 : ++opt_next;
2160 : }
2161 :
2162 0 : 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 0 : rfapiQprefix2Rprefix(&pfx, &rpfx);
2170 :
2171 0 : rpfx.cost = cost & 255;
2172 :
2173 : /* look up rf descriptor, call open if it doesn't exist */
2174 0 : rc = rfapi_find_rfd(bgp, &vn_address, &un_address,
2175 : (struct rfapi_descriptor **)&rfd);
2176 0 : if (rc) {
2177 0 : if (ENOENT == rc) {
2178 0 : 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 0 : memset(&uo, 0, sizeof(uo));
2188 0 : uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL;
2189 :
2190 0 : 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 0 : if (rc) {
2196 0 : vty_out(vty,
2197 : "Can't open session for this NVE: %s\n",
2198 : rfapi_error_str(rc));
2199 0 : rc = CMD_WARNING_CONFIG_FAILED;
2200 0 : goto fail;
2201 : }
2202 : } else {
2203 0 : vty_out(vty, "Can't find session for this NVE: %s\n",
2204 : rfapi_error_str(rc));
2205 0 : goto fail;
2206 : }
2207 : }
2208 :
2209 0 : rc = rfapi_register(rfd, &rpfx, lifetime, NULL, opt,
2210 : RFAPI_REGISTER_ADD);
2211 0 : if (!rc) {
2212 0 : struct rfapi_next_hop_entry *head = NULL;
2213 0 : struct rfapi_next_hop_entry *tail = NULL;
2214 0 : struct rfapi_vn_option *vn_opt_new;
2215 :
2216 0 : vnc_zlog_debug_verbose(
2217 : "%s: rfapi_register succeeded, returning 0", __func__);
2218 :
2219 0 : if (h->rfp_methods.local_cb) {
2220 0 : struct rfapi_descriptor *r =
2221 : (struct rfapi_descriptor *)rfd;
2222 0 : vn_opt_new = rfapi_vn_options_dup(opt);
2223 :
2224 0 : rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
2225 : &rpfx, 1, lifetime,
2226 : vn_opt_new, &head, &tail);
2227 0 : if (head) {
2228 0 : h->flags |= RFAPI_INCALLBACK;
2229 0 : (*h->rfp_methods.local_cb)(head, r->cookie);
2230 0 : h->flags &= ~RFAPI_INCALLBACK;
2231 : }
2232 0 : head = tail = NULL;
2233 : }
2234 0 : return 0;
2235 : }
2236 :
2237 0 : vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
2238 0 : vty_out(vty, "\n");
2239 0 : vty_out(vty, "Registration failed.\n");
2240 0 : vty_out(vty,
2241 : "Confirm that either the VN or UN address matches a configured NVE group.\n");
2242 0 : return CMD_WARNING_CONFIG_FAILED;
2243 :
2244 0 : fail:
2245 0 : vnc_zlog_debug_verbose("%s: fail, rc=%d", __func__, rc);
2246 : return rc;
2247 : }
2248 :
2249 : /************************************************************************
2250 : * Add prefix With LNH_OPTIONS...
2251 : ************************************************************************/
2252 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2446 : /* mac vni */
2447 : NULL, NULL, 0, NULL);
2448 : }
2449 :
2450 0 : 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 0 : return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2469 : /* mac vni */
2470 : NULL, NULL, 0, NULL);
2471 : }
2472 :
2473 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : static void nve_addr_free(void *hap)
2745 : {
2746 0 : ((struct nve_addr *)hap)->cda->nve_count += 1;
2747 0 : XFREE(MTYPE_RFAPI_NVE_ADDR, hap);
2748 0 : }
2749 :
2750 0 : static int nve_addr_cmp(const void *k1, const void *k2)
2751 : {
2752 0 : const struct nve_addr *a = (struct nve_addr *)k1;
2753 0 : const struct nve_addr *b = (struct nve_addr *)k2;
2754 0 : int ret = 0;
2755 :
2756 0 : if (!a || !b) {
2757 0 : return (a - b);
2758 : }
2759 0 : if (a->un.addr_family != b->un.addr_family) {
2760 0 : return (a->un.addr_family - b->un.addr_family);
2761 : }
2762 0 : if (a->vn.addr_family != b->vn.addr_family) {
2763 0 : return (a->vn.addr_family - b->vn.addr_family);
2764 : }
2765 0 : if (a->un.addr_family == AF_INET) {
2766 0 : ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4);
2767 0 : if (ret != 0) {
2768 : return ret;
2769 : }
2770 0 : } else if (a->un.addr_family == AF_INET6) {
2771 0 : ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6);
2772 0 : if (ret != 0) {
2773 : return ret;
2774 : }
2775 : } else {
2776 0 : assert(0);
2777 : }
2778 0 : if (a->vn.addr_family == AF_INET) {
2779 0 : ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4);
2780 0 : if (ret != 0)
2781 : return ret;
2782 0 : } else if (a->vn.addr_family == AF_INET6) {
2783 0 : ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6);
2784 : if (ret == 0) {
2785 : return ret;
2786 : }
2787 : } else {
2788 0 : assert(0);
2789 : }
2790 : return 0;
2791 : }
2792 :
2793 0 : 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 0 : int rc = CMD_WARNING;
2801 :
2802 0 : memset(rcdarg, 0, sizeof(struct rfapi_local_reg_delete_arg));
2803 :
2804 0 : rcdarg->vty = vty;
2805 0 : if (bgp == NULL)
2806 0 : bgp = bgp_get_default();
2807 0 : rcdarg->bgp = bgp;
2808 0 : rcdarg->rfg = arg_rfg; /* may be NULL */
2809 :
2810 0 : if (arg_vn && strcmp(arg_vn, "*")) {
2811 0 : if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn,
2812 : &rcdarg->vn_address)))
2813 : return rc;
2814 : }
2815 0 : if (arg_un && strcmp(arg_un, "*")) {
2816 0 : if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un,
2817 : &rcdarg->un_address)))
2818 : return rc;
2819 : }
2820 0 : if (arg_prefix && strcmp(arg_prefix, "*")) {
2821 :
2822 0 : if (!str2prefix(arg_prefix, &rcdarg->prefix)) {
2823 0 : vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2824 0 : return rc;
2825 : }
2826 : }
2827 :
2828 0 : if (arg_l2addr) {
2829 0 : if (!arg_vni) {
2830 0 : vty_out(vty, "Missing VNI\n");
2831 0 : return rc;
2832 : }
2833 0 : if (strcmp(arg_l2addr, "*")) {
2834 0 : if ((rc = rfapiStr2EthAddr(arg_l2addr,
2835 : &rcdarg->l2o.o.macaddr))) {
2836 0 : vty_out(vty, "Malformed L2 Address \"%s\"\n",
2837 : arg_l2addr);
2838 0 : return rc;
2839 : }
2840 0 : rcdarg->l2o.flags |= RFAPI_L2O_MACADDR;
2841 : }
2842 0 : if (strcmp(arg_vni, "*")) {
2843 0 : rcdarg->l2o.o.logical_net_id =
2844 0 : strtoul(arg_vni, NULL, 10);
2845 0 : rcdarg->l2o.flags |= RFAPI_L2O_LNI;
2846 : }
2847 : }
2848 0 : if (arg_rd) {
2849 0 : if (!str2prefix_rd(arg_rd, &rcdarg->rd)) {
2850 0 : vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
2851 0 : return rc;
2852 : }
2853 : }
2854 :
2855 : return CMD_SUCCESS;
2856 : }
2857 :
2858 : static int
2859 0 : 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 0 : const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
2867 0 : const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
2868 0 : const char *arg_un = carg_un ? carg_un->arg : NULL;
2869 0 : const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL;
2870 0 : const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
2871 0 : const char *arg_rd = carg_rd ? carg_rd->arg : NULL;
2872 0 : 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 0 : 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 0 : struct nve_addr ha;
2882 0 : struct nve_addr *hap;
2883 :
2884 0 : memset(&ha, 0, sizeof(ha));
2885 0 : ha.un = *un_address;
2886 0 : ha.vn = *vn_address;
2887 0 : ha.rfd = rfd;
2888 :
2889 0 : if (!cda->nves)
2890 0 : cda->nves = skiplist_new(0, nve_addr_cmp, nve_addr_free);
2891 :
2892 0 : if (skiplist_search(cda->nves, &ha, (void *)&hap)) {
2893 0 : hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, sizeof(struct nve_addr));
2894 0 : assert(hap);
2895 0 : ha.cda = cda;
2896 0 : *hap = ha;
2897 0 : skiplist_insert(cda->nves, hap, hap);
2898 : }
2899 0 : }
2900 :
2901 0 : static void clear_vnc_responses(struct rfapi_local_reg_delete_arg *cda)
2902 : {
2903 0 : struct rfapi *h;
2904 0 : struct rfapi_descriptor *rfd;
2905 0 : int query_count = 0;
2906 0 : struct listnode *node;
2907 0 : struct bgp *bgp_default = bgp_get_default();
2908 :
2909 0 : if (cda->vn_address.addr_family && cda->un_address.addr_family) {
2910 : /*
2911 : * Single nve case
2912 : */
2913 0 : if (rfapi_find_rfd(bgp_default, &cda->vn_address,
2914 : &cda->un_address, &rfd))
2915 0 : return;
2916 :
2917 0 : rfapiRibClear(rfd);
2918 0 : rfapi_query_done_all(rfd, &query_count);
2919 0 : cda->query_count += query_count;
2920 :
2921 : /*
2922 : * Track unique nves seen
2923 : */
2924 0 : record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2925 0 : return;
2926 : }
2927 :
2928 : /*
2929 : * wildcard case
2930 : */
2931 :
2932 0 : if (!bgp_default)
2933 : return; /* ENXIO */
2934 :
2935 0 : h = bgp_default->rfapi;
2936 :
2937 0 : if (!h)
2938 : return; /* ENXIO */
2939 :
2940 0 : for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
2941 : /*
2942 : * match un, vn addresses of NVEs
2943 : */
2944 0 : if (cda->un_address.addr_family
2945 0 : && rfapi_ip_addr_cmp(&cda->un_address, &rfd->un_addr)) {
2946 0 : continue;
2947 : }
2948 0 : if (cda->vn_address.addr_family
2949 0 : && rfapi_ip_addr_cmp(&cda->vn_address, &rfd->vn_addr)) {
2950 0 : continue;
2951 : }
2952 :
2953 0 : rfapiRibClear(rfd);
2954 :
2955 0 : rfapi_query_done_all(rfd, &query_count);
2956 0 : cda->query_count += query_count;
2957 :
2958 : /*
2959 : * Track unique nves seen
2960 : */
2961 0 : 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 0 : static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
2971 : struct rfapi_descriptor *rfd)
2972 : {
2973 0 : struct rfapi_ip_addr *pUn; /* NULL = wildcard */
2974 0 : struct rfapi_ip_addr *pVn; /* NULL = wildcard */
2975 0 : struct prefix *pPrefix; /* NULL = wildcard */
2976 0 : struct prefix_rd *pPrd; /* NULL = wildcard */
2977 :
2978 0 : struct rfapi_ip_prefix rprefix;
2979 0 : struct rfapi_next_hop_entry *head = NULL;
2980 0 : 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 0 : pUn = (cda->un_address.addr_family ? &cda->un_address : NULL);
2987 0 : pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL);
2988 0 : pPrefix = (cda->prefix.family ? &cda->prefix : NULL);
2989 0 : pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL);
2990 :
2991 0 : if (pPrefix) {
2992 0 : rfapiQprefix2Rprefix(pPrefix, &rprefix);
2993 : }
2994 :
2995 0 : do /* to preserve old code structure */
2996 0 : {
2997 0 : struct rfapi *h = cda->bgp->rfapi;
2998 0 : ;
2999 0 : struct rfapi_adb *adb;
3000 0 : int rc;
3001 0 : int deleted_from_this_nve;
3002 0 : struct nve_addr ha;
3003 0 : 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 0 : if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr)))
3013 : break;
3014 0 : 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 0 : deleted_from_this_nve = 0;
3026 :
3027 : {
3028 0 : struct skiplist *sl;
3029 0 : struct rfapi_ip_prefix rp;
3030 0 : void *cursor;
3031 0 : 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 0 : adb_delete_list = list_new();
3046 :
3047 : /*
3048 : * Advertised IP prefixes (not 0/32 or 0/128)
3049 : */
3050 0 : sl = rfd->advertised.ipN_by_prefix;
3051 :
3052 0 : for (cursor = NULL,
3053 0 : rc = skiplist_next(sl, NULL, (void **)&adb,
3054 : &cursor);
3055 0 : !rc; rc = skiplist_next(sl, NULL, (void **)&adb,
3056 : &cursor)) {
3057 :
3058 0 : if (pPrefix) {
3059 0 : if (!prefix_same(pPrefix,
3060 0 : &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 0 : continue;
3067 : }
3068 : }
3069 0 : if (pPrd) {
3070 0 : 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 0 : continue;
3079 : }
3080 : }
3081 0 : if (CHECK_FLAG(cda->l2o.flags,
3082 : RFAPI_L2O_MACADDR)) {
3083 0 : if (memcmp(cda->l2o.o.macaddr.octet,
3084 0 : adb->u.s.prefix_eth.u
3085 0 : .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 0 : continue;
3093 : }
3094 : }
3095 :
3096 0 : if (CHECK_FLAG(cda->l2o.flags, RFAPI_L2O_LNI)) {
3097 0 : if (cda->l2o.o.logical_net_id
3098 0 : != 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 0 : 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 0 : listnode_add(adb_delete_list, adb);
3115 : }
3116 :
3117 0 : struct listnode *node;
3118 :
3119 0 : for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, adb)) {
3120 0 : int this_advertisement_prefix_count;
3121 0 : struct rfapi_vn_option optary[3];
3122 0 : struct rfapi_vn_option *opt = NULL;
3123 0 : int cur_opt = 0;
3124 :
3125 0 : this_advertisement_prefix_count = 1;
3126 :
3127 0 : rfapiQprefix2Rprefix(&adb->u.s.prefix_ip, &rp);
3128 :
3129 0 : memset(optary, 0, sizeof(optary));
3130 :
3131 : /* if mac addr present in advert, make l2o vn
3132 : * option */
3133 0 : if (adb->u.s.prefix_eth.family == AF_ETHERNET) {
3134 0 : if (opt != NULL)
3135 : opt->next = &optary[cur_opt];
3136 0 : opt = &optary[cur_opt++];
3137 0 : opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3138 0 : opt->v.l2addr.macaddr =
3139 : adb->u.s.prefix_eth.u
3140 : .prefix_eth;
3141 0 : ++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 0 : if (opt != NULL)
3149 0 : opt->next = &optary[cur_opt];
3150 0 : opt = &optary[cur_opt++];
3151 0 : opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
3152 0 : 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 0 : rc = rfapi_register(rfd, &rp, 0, NULL,
3161 : (cur_opt ? optary : NULL),
3162 : RFAPI_REGISTER_KILL);
3163 0 : if (!rc) {
3164 0 : cda->pfx_count +=
3165 : this_advertisement_prefix_count;
3166 0 : cda->reg_count += 1;
3167 0 : deleted_from_this_nve = 1;
3168 : }
3169 0 : if (h->rfp_methods.local_cb) {
3170 0 : rfapiAddDeleteLocalRfpPrefix(
3171 : &rfd->un_addr, &rfd->vn_addr,
3172 : &rp, 0, 0, NULL, &head, &tail);
3173 : }
3174 : }
3175 0 : list_delete_all_node(adb_delete_list);
3176 :
3177 0 : 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 0 : sl = rfd->advertised.ip0_by_ether;
3188 :
3189 0 : for (cursor = NULL,
3190 0 : rc = skiplist_next(sl, NULL, (void **)&adb,
3191 : &cursor);
3192 0 : !rc;
3193 0 : rc = skiplist_next(sl, NULL, (void **)&adb,
3194 : &cursor)) {
3195 :
3196 0 : if (CHECK_FLAG(cda->l2o.flags,
3197 : RFAPI_L2O_MACADDR)) {
3198 0 : if (memcmp(cda->l2o.o.macaddr
3199 0 : .octet,
3200 0 : adb->u.s.prefix_eth.u
3201 : .prefix_eth
3202 0 : .octet,
3203 : ETH_ALEN)) {
3204 :
3205 0 : continue;
3206 : }
3207 : }
3208 0 : if (CHECK_FLAG(cda->l2o.flags,
3209 : RFAPI_L2O_LNI)) {
3210 0 : if (cda->l2o.o.logical_net_id
3211 0 : != adb->l2o.logical_net_id) {
3212 0 : 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 0 : listnode_add(adb_delete_list, adb);
3221 : }
3222 :
3223 :
3224 0 : for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node,
3225 : adb)) {
3226 :
3227 0 : struct rfapi_vn_option vn;
3228 :
3229 0 : rfapiQprefix2Rprefix(
3230 0 : &adb->u.s.prefix_ip, &rp);
3231 :
3232 0 : memset(&vn, 0, sizeof(vn));
3233 0 : vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3234 0 : 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 0 : rc = rfapi_register(
3243 : rfd, &rp, 0, NULL, &vn,
3244 : RFAPI_REGISTER_KILL);
3245 0 : if (!rc) {
3246 0 : cda->pfx_count += 1;
3247 0 : cda->reg_count += 1;
3248 0 : deleted_from_this_nve = 1;
3249 : }
3250 0 : if (h->rfp_methods.local_cb) {
3251 0 : struct rfapi_vn_option
3252 : *vn_opt_new;
3253 :
3254 0 : vn_opt_new =
3255 0 : rfapi_vn_options_dup(
3256 : &vn);
3257 0 : rfapiAddDeleteLocalRfpPrefix(
3258 : &rfd->un_addr,
3259 : &rfd->vn_addr, &rp, 0,
3260 : 0, vn_opt_new, &head,
3261 : &tail);
3262 : }
3263 : }
3264 0 : list_delete_all_node(adb_delete_list);
3265 : }
3266 0 : list_delete(&adb_delete_list);
3267 : }
3268 :
3269 :
3270 0 : if (head) { /* should not be set if (NULL ==
3271 : rfapi_cfg->local_cb) */
3272 0 : h->flags |= RFAPI_INCALLBACK;
3273 0 : (*h->rfp_methods.local_cb)(head, rfd->cookie);
3274 0 : h->flags &= ~RFAPI_INCALLBACK;
3275 0 : head = tail = NULL;
3276 : }
3277 :
3278 0 : if (deleted_from_this_nve) {
3279 : /*
3280 : * track unique NVEs seen
3281 : */
3282 0 : memset(&ha, 0, sizeof(ha));
3283 0 : ha.un = rfd->un_addr;
3284 0 : ha.vn = rfd->vn_addr;
3285 :
3286 0 : if (!cda->nves)
3287 0 : cda->nves = skiplist_new(0, nve_addr_cmp,
3288 : nve_addr_free);
3289 0 : if (skiplist_search(cda->nves, &ha, (void **)&hap)) {
3290 0 : hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR,
3291 : sizeof(struct nve_addr));
3292 0 : assert(hap);
3293 0 : ha.cda = cda;
3294 0 : *hap = ha;
3295 0 : skiplist_insert(cda->nves, hap, hap);
3296 : }
3297 : }
3298 : } while (0); /* to preserve old code structure */
3299 :
3300 0 : return 0;
3301 : }
3302 :
3303 0 : static int rfapiDeleteLocalPrefixes(struct rfapi_local_reg_delete_arg *cda)
3304 : {
3305 0 : int rc = 0;
3306 :
3307 0 : if (cda->rfg) {
3308 0 : if (cda->rfg->rfd) /* if not open, nothing to delete */
3309 0 : rc = rfapiDeleteLocalPrefixesByRFD(cda, cda->rfg->rfd);
3310 : } else {
3311 0 : struct bgp *bgp = cda->bgp;
3312 0 : struct rfapi *h;
3313 0 : struct rfapi_cfg *rfapi_cfg;
3314 :
3315 0 : struct listnode *node;
3316 0 : struct rfapi_descriptor *rfd;
3317 0 : if (!bgp)
3318 : return ENXIO;
3319 0 : h = bgp->rfapi;
3320 0 : rfapi_cfg = bgp->rfapi_cfg;
3321 0 : if (!h || !rfapi_cfg)
3322 : return ENXIO;
3323 0 : vnc_zlog_debug_verbose("%s: starting descriptor loop",
3324 : __func__);
3325 0 : for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
3326 0 : 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 0 : static void clear_vnc_prefix(struct rfapi_local_reg_delete_arg *cda)
3338 : {
3339 0 : struct prefix pfx_un;
3340 0 : struct prefix pfx_vn;
3341 :
3342 0 : struct prefix *pUN = NULL;
3343 0 : struct prefix *pVN = NULL;
3344 0 : struct prefix *pPrefix = NULL;
3345 :
3346 0 : struct rfapi_import_table *it = NULL;
3347 :
3348 : /*
3349 : * Delete matching remote prefixes in holddown
3350 : */
3351 0 : if (cda->vn_address.addr_family) {
3352 0 : if (!rfapiRaddr2Qprefix(&cda->vn_address, &pfx_vn))
3353 0 : pVN = &pfx_vn;
3354 : }
3355 0 : if (cda->un_address.addr_family) {
3356 0 : if (!rfapiRaddr2Qprefix(&cda->un_address, &pfx_un))
3357 0 : pUN = &pfx_un;
3358 : }
3359 0 : if (cda->prefix.family) {
3360 0 : pPrefix = &cda->prefix;
3361 : }
3362 0 : if (cda->rfg) {
3363 0 : it = cda->rfg->rfapi_import_table;
3364 : }
3365 0 : 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 0 : rfapiDeleteLocalPrefixes(cda);
3374 0 : }
3375 :
3376 0 : static void print_cleared_stats(struct rfapi_local_reg_delete_arg *cda)
3377 : {
3378 0 : struct vty *vty = cda->vty; /* for benefit of VTYNL */
3379 :
3380 : /* Our special element-deleting function counts nves */
3381 0 : if (cda->nves) {
3382 0 : skiplist_free(cda->nves);
3383 0 : cda->nves = NULL;
3384 : }
3385 0 : if (cda->failed_pfx_count)
3386 0 : 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 0 : 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 0 : vty_out(vty, "[Holddown] Cleared %u prefixes from %u NVEs\n",
3401 : cda->remote_holddown_pfx_count, cda->remote_holddown_nve_count);
3402 0 : }
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 0 : static void clear_vnc_nve_closer(struct rfapi_local_reg_delete_arg *cda)
3409 : {
3410 0 : struct skiplist *sl = cda->nves; /* contains affected NVEs */
3411 0 : struct nve_addr *pKey;
3412 0 : struct nve_addr *pValue;
3413 0 : void *cursor = NULL;
3414 0 : int rc;
3415 :
3416 0 : if (!sl)
3417 0 : return;
3418 :
3419 0 : for (rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, &cursor);
3420 0 : !rc; rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue,
3421 : &cursor)) {
3422 :
3423 0 : if (pValue->rfd) {
3424 0 : pValue->rfd->flags |=
3425 : RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY;
3426 0 : rfapi_close(pValue->rfd);
3427 : }
3428 : }
3429 : }
3430 :
3431 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3441 0 : int rc;
3442 :
3443 0 : if ((rc = parse_deleter_args(vty, NULL, NULL, NULL, NULL, NULL, NULL,
3444 : NULL, NULL, &cda)))
3445 : return rc;
3446 :
3447 0 : cda.vty = vty;
3448 :
3449 0 : clear_vnc_responses(&cda);
3450 0 : clear_vnc_prefix(&cda);
3451 0 : clear_vnc_nve_closer(&cda);
3452 :
3453 0 : print_cleared_stats(&cda);
3454 :
3455 0 : return 0;
3456 : }
3457 :
3458 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3474 0 : int rc;
3475 :
3476 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], argv[6], NULL,
3477 : NULL, NULL, NULL, &cda)))
3478 : return rc;
3479 :
3480 0 : cda.vty = vty;
3481 :
3482 0 : clear_vnc_responses(&cda);
3483 0 : clear_vnc_prefix(&cda);
3484 0 : clear_vnc_nve_closer(&cda);
3485 :
3486 0 : print_cleared_stats(&cda);
3487 :
3488 0 : return 0;
3489 : }
3490 :
3491 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3507 0 : int rc;
3508 :
3509 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[6], argv[4], NULL,
3510 : NULL, NULL, NULL, &cda)))
3511 : return rc;
3512 :
3513 0 : cda.vty = vty;
3514 :
3515 0 : clear_vnc_responses(&cda);
3516 0 : clear_vnc_prefix(&cda);
3517 0 : clear_vnc_nve_closer(&cda);
3518 :
3519 0 : print_cleared_stats(&cda);
3520 :
3521 0 : return 0;
3522 : }
3523 :
3524 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3536 0 : int rc;
3537 :
3538 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], NULL, NULL,
3539 : NULL, NULL, NULL, &cda)))
3540 : return rc;
3541 :
3542 0 : cda.vty = vty;
3543 :
3544 0 : clear_vnc_responses(&cda);
3545 0 : clear_vnc_prefix(&cda);
3546 0 : clear_vnc_nve_closer(&cda);
3547 :
3548 0 : print_cleared_stats(&cda);
3549 0 : return 0;
3550 : }
3551 :
3552 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3564 0 : int rc;
3565 :
3566 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[4], NULL,
3567 : NULL, NULL, NULL, &cda)))
3568 : return rc;
3569 :
3570 0 : cda.vty = vty;
3571 :
3572 0 : clear_vnc_responses(&cda);
3573 0 : clear_vnc_prefix(&cda);
3574 0 : clear_vnc_nve_closer(&cda);
3575 :
3576 0 : print_cleared_stats(&cda);
3577 0 : 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 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3607 0 : int rc;
3608 :
3609 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], argv[7],
3610 : NULL, NULL, NULL, NULL, &cda)))
3611 : return rc;
3612 0 : cda.vty = vty;
3613 0 : clear_vnc_prefix(&cda);
3614 0 : print_cleared_stats(&cda);
3615 0 : return 0;
3616 : }
3617 :
3618 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3637 0 : int rc;
3638 :
3639 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[7], argv[5],
3640 : NULL, NULL, NULL, NULL, &cda)))
3641 : return rc;
3642 0 : cda.vty = vty;
3643 0 : clear_vnc_prefix(&cda);
3644 0 : print_cleared_stats(&cda);
3645 0 : return 0;
3646 : }
3647 :
3648 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3663 0 : int rc;
3664 :
3665 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, argv[5], NULL,
3666 : NULL, NULL, NULL, &cda)))
3667 : return rc;
3668 0 : cda.vty = vty;
3669 0 : clear_vnc_prefix(&cda);
3670 0 : print_cleared_stats(&cda);
3671 0 : return 0;
3672 : }
3673 :
3674 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3689 0 : int rc;
3690 :
3691 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], NULL, NULL,
3692 : NULL, NULL, NULL, &cda)))
3693 : return rc;
3694 0 : cda.vty = vty;
3695 0 : clear_vnc_prefix(&cda);
3696 0 : print_cleared_stats(&cda);
3697 0 : return 0;
3698 : }
3699 :
3700 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3712 0 : int rc;
3713 :
3714 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, NULL, NULL,
3715 : NULL, NULL, NULL, &cda)))
3716 : return rc;
3717 0 : cda.vty = vty;
3718 0 : clear_vnc_prefix(&cda);
3719 0 : print_cleared_stats(&cda);
3720 0 : 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 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3752 0 : int rc;
3753 :
3754 : /* pfx vn un L2 VNI */
3755 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], argv[9],
3756 : argv[3], argv[5], NULL, NULL, &cda)))
3757 : return rc;
3758 0 : cda.vty = vty;
3759 0 : clear_vnc_prefix(&cda);
3760 0 : print_cleared_stats(&cda);
3761 0 : return 0;
3762 : }
3763 :
3764 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3785 0 : int rc;
3786 :
3787 : /* pfx vn un L2 VNI */
3788 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[9], argv[7],
3789 : argv[3], argv[5], NULL, NULL, &cda)))
3790 : return rc;
3791 0 : cda.vty = vty;
3792 0 : clear_vnc_prefix(&cda);
3793 0 : print_cleared_stats(&cda);
3794 0 : return 0;
3795 : }
3796 :
3797 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3814 0 : int rc;
3815 :
3816 : /* pfx vn un L2 VNI */
3817 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[7], argv[3],
3818 : argv[5], NULL, NULL, &cda)))
3819 : return rc;
3820 0 : cda.vty = vty;
3821 0 : clear_vnc_prefix(&cda);
3822 0 : print_cleared_stats(&cda);
3823 0 : return 0;
3824 : }
3825 :
3826 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3843 0 : int rc;
3844 :
3845 : /* pfx vn un L2 VNI */
3846 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], NULL, argv[3],
3847 : argv[5], NULL, NULL, &cda)))
3848 : return rc;
3849 0 : cda.vty = vty;
3850 0 : clear_vnc_prefix(&cda);
3851 0 : print_cleared_stats(&cda);
3852 0 : return 0;
3853 : }
3854 :
3855 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3869 0 : int rc;
3870 :
3871 : /* pfx vn un L2 VNI */
3872 0 : if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, NULL, argv[3],
3873 : argv[5], NULL, NULL, &cda)))
3874 : return rc;
3875 0 : cda.vty = vty;
3876 0 : clear_vnc_prefix(&cda);
3877 0 : print_cleared_stats(&cda);
3878 0 : return 0;
3879 : }
3880 :
3881 : /*-------------------------------------------------
3882 : * Clear VNC MAC PREFIX
3883 : *-------------------------------------------------*/
3884 :
3885 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3910 0 : int rc;
3911 :
3912 : /* pfx vn un L2 VNI */
3913 0 : 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 0 : cda.vty = vty;
3917 0 : clear_vnc_prefix(&cda);
3918 0 : print_cleared_stats(&cda);
3919 0 : return 0;
3920 : }
3921 :
3922 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3951 0 : int rc;
3952 :
3953 : /* pfx vn un L2 VNI */
3954 0 : 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 0 : cda.vty = vty;
3958 0 : clear_vnc_prefix(&cda);
3959 0 : print_cleared_stats(&cda);
3960 0 : return 0;
3961 : }
3962 :
3963 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
3984 0 : int rc;
3985 :
3986 : /* pfx vn un L2 VNI */
3987 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[9], NULL, argv[7],
3988 : argv[3], argv[5], NULL, NULL, &cda)))
3989 : return rc;
3990 0 : cda.vty = vty;
3991 0 : clear_vnc_prefix(&cda);
3992 0 : print_cleared_stats(&cda);
3993 0 : return 0;
3994 : }
3995 :
3996 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
4017 0 : int rc;
4018 :
4019 : /* pfx vn un L2 VNI */
4020 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[9], argv[7], NULL,
4021 : argv[3], argv[5], NULL, NULL, &cda)))
4022 : return rc;
4023 0 : cda.vty = vty;
4024 0 : clear_vnc_prefix(&cda);
4025 0 : print_cleared_stats(&cda);
4026 0 : return 0;
4027 : }
4028 :
4029 0 : 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 0 : struct rfapi_local_reg_delete_arg cda;
4046 0 : int rc;
4047 :
4048 : /* pfx vn un L2 VNI */
4049 0 : if ((rc = parse_deleter_tokens(vty, NULL, argv[7], NULL, NULL, argv[3],
4050 : argv[5], NULL, NULL, &cda)))
4051 : return rc;
4052 0 : cda.vty = vty;
4053 0 : clear_vnc_prefix(&cda);
4054 0 : print_cleared_stats(&cda);
4055 0 : return 0;
4056 : }
4057 :
4058 : /************************************************************************
4059 : * Show commands
4060 : ************************************************************************/
4061 :
4062 :
4063 : /* copied from rfp_vty.c */
4064 0 : static int check_and_display_is_vnc_running(struct vty *vty)
4065 : {
4066 0 : if (bgp_rfapi_is_vnc_configured(NULL) == 0)
4067 : return 1; /* is running */
4068 :
4069 0 : if (vty) {
4070 0 : vty_out(vty, "VNC is not configured.\n");
4071 : }
4072 : return 0; /* not running */
4073 : }
4074 :
4075 0 : static int rfapi_vty_show_nve_summary(struct vty *vty,
4076 : show_nve_summary_t show_type)
4077 : {
4078 0 : struct bgp *bgp_default = bgp_get_default();
4079 0 : struct rfapi *h;
4080 0 : int is_vnc_running = (bgp_rfapi_is_vnc_configured(bgp_default) == 0);
4081 :
4082 0 : int active_local_routes;
4083 0 : int active_remote_routes;
4084 0 : int holddown_remote_routes;
4085 0 : int imported_remote_routes;
4086 :
4087 0 : if (!bgp_default)
4088 0 : goto notcfg;
4089 :
4090 0 : h = bgp_default->rfapi;
4091 :
4092 0 : if (!h)
4093 0 : goto notcfg;
4094 :
4095 : /* don't show local info if not running RFP */
4096 0 : if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) {
4097 :
4098 0 : switch (show_type) {
4099 :
4100 0 : case SHOW_NVE_SUMMARY_ACTIVE_NVES:
4101 0 : vty_out(vty, "%-24s ", "NVEs:");
4102 0 : vty_out(vty, "%-8s %-8u ",
4103 : "Active:", h->descriptors.count);
4104 0 : vty_out(vty, "%-8s %-8u ",
4105 : "Maximum:", h->stat.max_descriptors);
4106 0 : vty_out(vty, "%-8s %-8u",
4107 : "Unknown:", h->stat.count_unknown_nves);
4108 0 : break;
4109 :
4110 0 : 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 0 : if (is_vnc_running) {
4126 0 : vty_out(vty, "%-24s ", "Registrations:");
4127 0 : vty_out(vty, "%-8s %-8u ", "Active:",
4128 : rfapiApCountAll(bgp_default));
4129 0 : vty_out(vty, "%-8s %-8u ", "Failed:",
4130 : h->stat.count_registrations_failed);
4131 0 : vty_out(vty, "%-8s %-8u",
4132 : "Total:", h->stat.count_registrations);
4133 0 : vty_out(vty, "\n");
4134 : }
4135 0 : vty_out(vty, "%-24s ", "Prefixes registered:");
4136 0 : vty_out(vty, "\n");
4137 :
4138 0 : rfapiCountAllItRoutes(&active_local_routes,
4139 : &active_remote_routes,
4140 : &holddown_remote_routes,
4141 : &imported_remote_routes);
4142 :
4143 : /* local */
4144 0 : if (is_vnc_running) {
4145 0 : vty_out(vty, " %-20s ", "Locally:");
4146 0 : vty_out(vty, "%-8s %-8u ",
4147 : "Active:", active_local_routes);
4148 0 : vty_out(vty, "\n");
4149 : }
4150 :
4151 :
4152 0 : vty_out(vty, " %-20s ", "Remotely:");
4153 0 : vty_out(vty, "%-8s %-8u",
4154 : "Active:", active_remote_routes);
4155 0 : vty_out(vty, "\n");
4156 0 : vty_out(vty, " %-20s ", "In Holddown:");
4157 0 : vty_out(vty, "%-8s %-8u",
4158 : "Active:", holddown_remote_routes);
4159 0 : vty_out(vty, "\n");
4160 0 : vty_out(vty, " %-20s ", "Imported:");
4161 0 : vty_out(vty, "%-8s %-8u",
4162 : "Active:", imported_remote_routes);
4163 0 : break;
4164 :
4165 0 : case SHOW_NVE_SUMMARY_QUERIES:
4166 0 : vty_out(vty, "%-24s ", "Queries:");
4167 0 : vty_out(vty, "%-8s %-8u ",
4168 : "Active:", rfapi_monitor_count(NULL));
4169 0 : vty_out(vty, "%-8s %-8u ",
4170 : "Failed:", h->stat.count_queries_failed);
4171 0 : vty_out(vty, "%-8s %-8u",
4172 : "Total:", h->stat.count_queries);
4173 0 : break;
4174 :
4175 0 : case SHOW_NVE_SUMMARY_RESPONSES:
4176 0 : rfapiRibShowResponsesSummary(vty);
4177 :
4178 : case SHOW_NVE_SUMMARY_UNKNOWN_NVES:
4179 : case SHOW_NVE_SUMMARY_MAX:
4180 : break;
4181 : }
4182 0 : vty_out(vty, "\n");
4183 : }
4184 : return 0;
4185 :
4186 0 : notcfg:
4187 0 : vty_out(vty, "VNC is not configured.\n");
4188 0 : return CMD_WARNING;
4189 : }
4190 :
4191 0 : static int rfapi_show_nves(struct vty *vty, struct prefix *vn_prefix,
4192 : struct prefix *un_prefix)
4193 : {
4194 : // struct hash *rfds;
4195 : // struct rfp_rfapi_descriptor_param param;
4196 :
4197 0 : struct bgp *bgp_default = bgp_get_default();
4198 0 : struct rfapi *h;
4199 0 : struct listnode *node;
4200 0 : struct rfapi_descriptor *rfd;
4201 :
4202 0 : int total = 0;
4203 0 : int printed = 0;
4204 0 : int rc;
4205 :
4206 0 : if (!bgp_default)
4207 0 : goto notcfg;
4208 :
4209 0 : h = bgp_default->rfapi;
4210 :
4211 0 : if (!h)
4212 0 : goto notcfg;
4213 :
4214 0 : rc = rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4215 0 : if (rc)
4216 : return rc;
4217 :
4218 0 : for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4219 0 : struct prefix pfx;
4220 0 : char vn_addr_buf[INET6_ADDRSTRLEN] = {
4221 : 0,
4222 : };
4223 0 : char un_addr_buf[INET6_ADDRSTRLEN] = {
4224 : 0,
4225 : };
4226 0 : char age[10];
4227 :
4228 0 : ++total;
4229 :
4230 0 : if (vn_prefix) {
4231 0 : assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
4232 0 : if (!prefix_match(vn_prefix, &pfx))
4233 0 : continue;
4234 : }
4235 :
4236 0 : if (un_prefix) {
4237 0 : assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
4238 0 : if (!prefix_match(un_prefix, &pfx))
4239 0 : continue;
4240 : }
4241 :
4242 0 : rfapiRfapiIpAddr2Str(&rfd->vn_addr, vn_addr_buf,
4243 : INET6_ADDRSTRLEN);
4244 0 : rfapiRfapiIpAddr2Str(&rfd->un_addr, un_addr_buf,
4245 : INET6_ADDRSTRLEN);
4246 :
4247 0 : if (!printed) {
4248 : /* print out a header */
4249 0 : vty_out(vty,
4250 : " Active Next Hops\n");
4251 0 : vty_out(vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n",
4252 : "VN Address", "UN Address", "Regis", "Resps",
4253 : "Reach", "Remove", "Age");
4254 : }
4255 :
4256 0 : ++printed;
4257 :
4258 0 : vty_out(vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n",
4259 : vn_addr_buf, un_addr_buf, rfapiApCount(rfd),
4260 : rfapi_monitor_count(rfd), rfd->stat_count_nh_reachable,
4261 : rfd->stat_count_nh_removal,
4262 : rfapiFormatAge(rfd->open_time, age, 10));
4263 : }
4264 :
4265 0 : if (printed > 0 || vn_prefix || un_prefix)
4266 0 : vty_out(vty, "Displayed %d out of %d active NVEs\n", printed,
4267 : total);
4268 :
4269 : return 0;
4270 :
4271 0 : notcfg:
4272 0 : vty_out(vty, "VNC is not configured.\n");
4273 0 : return CMD_WARNING;
4274 : }
4275 :
4276 :
4277 0 : DEFUN (vnc_show_summary,
4278 : vnc_show_summary_cmd,
4279 : "show vnc summary",
4280 : SHOW_STR
4281 : VNC_SHOW_STR
4282 : "Display VNC status summary\n")
4283 : {
4284 0 : if (!check_and_display_is_vnc_running(vty))
4285 : return CMD_SUCCESS;
4286 0 : bgp_rfapi_show_summary(bgp_get_default(), vty);
4287 0 : vty_out(vty, "\n");
4288 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4289 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4290 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_RESPONSES);
4291 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4292 0 : return CMD_SUCCESS;
4293 : }
4294 :
4295 0 : DEFUN (vnc_show_nves,
4296 : vnc_show_nves_cmd,
4297 : "show vnc nves",
4298 : SHOW_STR
4299 : VNC_SHOW_STR
4300 : "List known NVEs\n")
4301 : {
4302 0 : rfapi_show_nves(vty, NULL, NULL);
4303 0 : return CMD_SUCCESS;
4304 : }
4305 :
4306 0 : DEFUN (vnc_show_nves_ptct,
4307 : vnc_show_nves_ptct_cmd,
4308 : "show vnc nves <vn|un> <A.B.C.D|X:X::X:X>",
4309 : SHOW_STR
4310 : VNC_SHOW_STR
4311 : "List known NVEs\n"
4312 : "VN address of NVE\n"
4313 : "UN address of NVE\n"
4314 : "IPv4 interface address\n"
4315 : "IPv6 interface address\n")
4316 : {
4317 0 : struct prefix pfx;
4318 :
4319 0 : if (!check_and_display_is_vnc_running(vty))
4320 : return CMD_SUCCESS;
4321 :
4322 0 : if (!str2prefix(argv[4]->arg, &pfx)) {
4323 0 : vty_out(vty, "Malformed address \"%s\"\n", argv[4]->arg);
4324 0 : return CMD_WARNING;
4325 : }
4326 0 : if (pfx.family != AF_INET && pfx.family != AF_INET6) {
4327 0 : vty_out(vty, "Invalid address \"%s\"\n", argv[4]->arg);
4328 0 : return CMD_WARNING;
4329 : }
4330 :
4331 0 : if (argv[3]->arg[0] == 'u') {
4332 0 : rfapi_show_nves(vty, NULL, &pfx);
4333 : } else {
4334 0 : rfapi_show_nves(vty, &pfx, NULL);
4335 : }
4336 :
4337 : return CMD_SUCCESS;
4338 : }
4339 :
4340 : /* adapted from rfp_registration_cache_log() */
4341 0 : static void rfapi_show_registrations(struct vty *vty,
4342 : struct prefix *restrict_to, int show_local,
4343 : int show_remote, int show_holddown,
4344 : int show_imported)
4345 : {
4346 0 : int printed = 0;
4347 :
4348 0 : if (!vty)
4349 : return;
4350 :
4351 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4352 :
4353 0 : if (show_local) {
4354 : /* non-expiring, local */
4355 0 : printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 1,
4356 : 0, 0);
4357 : }
4358 0 : if (show_remote) {
4359 : /* non-expiring, non-local */
4360 0 : printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4361 : 1, 0);
4362 : }
4363 0 : if (show_holddown) {
4364 : /* expiring, including local */
4365 0 : printed += rfapiShowRemoteRegistrations(vty, restrict_to, 1, 1,
4366 : 1, 0);
4367 : }
4368 0 : if (show_imported) {
4369 : /* non-expiring, non-local */
4370 0 : printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4371 : 1, 1);
4372 : }
4373 0 : if (!printed) {
4374 0 : vty_out(vty, "\n");
4375 : }
4376 : }
4377 :
4378 0 : DEFUN (vnc_show_registrations_pfx,
4379 : vnc_show_registrations_pfx_cmd,
4380 : "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>]",
4381 : SHOW_STR
4382 : VNC_SHOW_STR
4383 : "List active prefix registrations\n"
4384 : "Limit output to a particualr IPV4 address\n"
4385 : "Limit output to a particular IPv4 prefix\n"
4386 : "Limit output to a particualr IPV6 address\n"
4387 : "Limit output to a particular IPv6 prefix\n"
4388 : "Limit output to a particular MAC address\n")
4389 : {
4390 0 : struct prefix p;
4391 0 : struct prefix *p_addr = NULL;
4392 :
4393 0 : if (argc > 3) {
4394 0 : if (!str2prefix(argv[3]->arg, &p)) {
4395 0 : vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4396 0 : return CMD_SUCCESS;
4397 : } else {
4398 : p_addr = &p;
4399 : }
4400 : }
4401 :
4402 0 : rfapi_show_registrations(vty, p_addr, 1, 1, 1, 1);
4403 0 : return CMD_SUCCESS;
4404 : }
4405 :
4406 0 : DEFUN (vnc_show_registrations_some_pfx,
4407 : vnc_show_registrations_some_pfx_cmd,
4408 : "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>]",
4409 : SHOW_STR
4410 : VNC_SHOW_STR
4411 : "List active prefix registrations\n"
4412 : "show all registrations\n"
4413 : "show only registrations in holddown\n"
4414 : "show only imported prefixes\n"
4415 : "show only local registrations\n"
4416 : "show only remote registrations\n"
4417 : "Limit output to a particualr IPV4 address\n"
4418 : "Limit output to a particular IPv4 prefix\n"
4419 : "Limit output to a particualr IPV6 address\n"
4420 : "Limit output to a particular IPv6 prefix\n"
4421 : "Limit output to a particular MAC address\n")
4422 : {
4423 0 : struct prefix p;
4424 0 : struct prefix *p_addr = NULL;
4425 :
4426 0 : int show_local = 0;
4427 0 : int show_remote = 0;
4428 0 : int show_holddown = 0;
4429 0 : int show_imported = 0;
4430 :
4431 0 : if (argc > 4) {
4432 0 : if (!str2prefix(argv[4]->arg, &p)) {
4433 0 : vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4434 0 : return CMD_SUCCESS;
4435 : } else {
4436 : p_addr = &p;
4437 : }
4438 : }
4439 0 : switch (argv[3]->arg[0]) {
4440 : case 'a':
4441 : show_local = 1;
4442 : show_remote = 1;
4443 : show_holddown = 1;
4444 : show_imported = 1;
4445 : break;
4446 :
4447 : case 'h':
4448 : show_holddown = 1;
4449 : break;
4450 :
4451 : case 'i':
4452 : show_imported = 1;
4453 : break;
4454 :
4455 : case 'l':
4456 : show_local = 1;
4457 : break;
4458 :
4459 : case 'r':
4460 : show_remote = 1;
4461 : break;
4462 : }
4463 :
4464 0 : rfapi_show_registrations(vty, p_addr, show_local, show_remote,
4465 : show_holddown, show_imported);
4466 0 : return CMD_SUCCESS;
4467 : }
4468 :
4469 0 : DEFUN (vnc_show_responses_pfx,
4470 : vnc_show_responses_pfx_cmd,
4471 : "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>]",
4472 : SHOW_STR
4473 : VNC_SHOW_STR
4474 : "List recent query responses\n"
4475 : "Limit output to a particualr IPV4 address\n"
4476 : "Limit output to a particular IPv4 prefix\n"
4477 : "Limit output to a particualr IPV6 address\n"
4478 : "Limit output to a particular IPv6 prefix\n"
4479 : "Limit output to a particular MAC address\n" )
4480 : {
4481 0 : struct prefix p;
4482 0 : struct prefix *p_addr = NULL;
4483 :
4484 0 : if (argc > 3) {
4485 0 : if (!str2prefix(argv[3]->arg, &p)) {
4486 0 : vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4487 0 : return CMD_SUCCESS;
4488 : } else {
4489 : p_addr = &p;
4490 : }
4491 : }
4492 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4493 :
4494 0 : rfapiRibShowResponsesSummary(vty);
4495 :
4496 0 : rfapiRibShowResponses(vty, p_addr, 0);
4497 0 : rfapiRibShowResponses(vty, p_addr, 1);
4498 :
4499 0 : return CMD_SUCCESS;
4500 : }
4501 :
4502 0 : DEFUN (vnc_show_responses_some_pfx,
4503 : vnc_show_responses_some_pfx_cmd,
4504 : "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>]",
4505 : SHOW_STR
4506 : VNC_SHOW_STR
4507 : "List recent query responses\n"
4508 : "show only active query responses\n"
4509 : "show only removed query responses\n"
4510 : "Limit output to a particualr IPV4 address\n"
4511 : "Limit output to a particular IPv4 prefix\n"
4512 : "Limit output to a particualr IPV6 address\n"
4513 : "Limit output to a particular IPv6 prefix\n"
4514 : "Limit output to a particular MAC address\n")
4515 : {
4516 0 : struct prefix p;
4517 0 : struct prefix *p_addr = NULL;
4518 :
4519 0 : int show_active = 0;
4520 0 : int show_removed = 0;
4521 :
4522 0 : if (!check_and_display_is_vnc_running(vty))
4523 : return CMD_SUCCESS;
4524 :
4525 0 : if (argc > 4) {
4526 0 : if (!str2prefix(argv[4]->arg, &p)) {
4527 0 : vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4528 0 : return CMD_SUCCESS;
4529 : } else {
4530 : p_addr = &p;
4531 : }
4532 : }
4533 :
4534 0 : switch (argv[3]->arg[0]) {
4535 0 : case 'a':
4536 0 : show_active = 1;
4537 0 : break;
4538 :
4539 0 : case 'r':
4540 0 : show_removed = 1;
4541 0 : break;
4542 : }
4543 :
4544 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4545 :
4546 0 : rfapiRibShowResponsesSummary(vty);
4547 :
4548 0 : if (show_active)
4549 0 : rfapiRibShowResponses(vty, p_addr, 0);
4550 0 : if (show_removed)
4551 0 : rfapiRibShowResponses(vty, p_addr, 1);
4552 :
4553 : return CMD_SUCCESS;
4554 : }
4555 :
4556 0 : DEFUN (show_vnc_queries_pfx,
4557 : show_vnc_queries_pfx_cmd,
4558 : "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>]",
4559 : SHOW_STR
4560 : VNC_SHOW_STR
4561 : "List active queries\n"
4562 : "Limit output to a particualr IPV4 address\n"
4563 : "Limit output to a particular IPv4 prefix\n"
4564 : "Limit output to a particualr IPV6 address\n"
4565 : "Limit output to a particular IPv6 prefix\n"
4566 : "Limit output to a particualr MAC address\n")
4567 : {
4568 0 : struct prefix pfx;
4569 0 : struct prefix *p = NULL;
4570 :
4571 0 : if (argc > 3) {
4572 0 : if (!str2prefix(argv[3]->arg, &pfx)) {
4573 0 : vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4574 0 : return CMD_WARNING;
4575 : }
4576 : p = &pfx;
4577 : }
4578 :
4579 0 : rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4580 :
4581 0 : return rfapiShowVncQueries(vty, p);
4582 : }
4583 :
4584 0 : DEFUN (vnc_clear_counters,
4585 : vnc_clear_counters_cmd,
4586 : "clear vnc counters",
4587 : CLEAR_STR
4588 : VNC_SHOW_STR
4589 : "Reset VNC counters\n")
4590 : {
4591 0 : struct bgp *bgp_default = bgp_get_default();
4592 0 : struct rfapi *h;
4593 0 : struct listnode *node;
4594 0 : struct rfapi_descriptor *rfd;
4595 :
4596 0 : if (!bgp_default)
4597 0 : goto notcfg;
4598 :
4599 0 : h = bgp_default->rfapi;
4600 :
4601 0 : if (!h)
4602 0 : goto notcfg;
4603 :
4604 : /* per-rfd */
4605 0 : for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4606 0 : rfd->stat_count_nh_reachable = 0;
4607 0 : rfd->stat_count_nh_removal = 0;
4608 : }
4609 :
4610 : /* global */
4611 0 : memset(&h->stat, 0, sizeof(h->stat));
4612 :
4613 : /*
4614 : * 151122 per bug 103, set count_registrations = number active.
4615 : * Do same for queries
4616 : */
4617 0 : h->stat.count_registrations = rfapiApCountAll(bgp_default);
4618 0 : h->stat.count_queries = rfapi_monitor_count(NULL);
4619 :
4620 0 : rfapiRibShowResponsesSummaryClear();
4621 :
4622 0 : return CMD_SUCCESS;
4623 :
4624 0 : notcfg:
4625 0 : vty_out(vty, "VNC is not configured.\n");
4626 0 : return CMD_WARNING;
4627 : }
4628 :
4629 : /************************************************************************
4630 : * Add prefix with vrf
4631 : *
4632 : * add [vrf <vrf-name>] prefix <prefix>
4633 : * [rd <value>] [label <value>] [local-preference <0-4294967295>]
4634 : ************************************************************************/
4635 0 : void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
4636 : {
4637 0 : if (rfg->rfd == NULL) { /* need new rfapi_handle */
4638 : /* based on rfapi_open */
4639 0 : struct rfapi_descriptor *rfd;
4640 :
4641 0 : rfd = XCALLOC(MTYPE_RFAPI_DESC,
4642 : sizeof(struct rfapi_descriptor));
4643 0 : rfd->bgp = bgp;
4644 0 : rfg->rfd = rfd;
4645 : /* leave most fields empty as will get from (dynamic) config
4646 : * when needed */
4647 0 : rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
4648 0 : rfd->cookie = rfg;
4649 0 : if (rfg->vn_prefix.family
4650 0 : && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
4651 0 : rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr);
4652 : } else {
4653 0 : memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
4654 0 : rfd->vn_addr.addr_family = AF_INET;
4655 0 : rfd->vn_addr.addr.v4 = bgp->router_id;
4656 : }
4657 0 : rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for
4658 : lookups */
4659 0 : vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
4660 : rfg->name);
4661 0 : rfapi_init_and_open(bgp, rfd, rfg);
4662 : }
4663 0 : }
4664 :
4665 : /* NOTE: this functions parallels vnc_direct_add_rn_group_rd */
4666 0 : static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,
4667 : const char *arg_prefix,
4668 : const char *arg_rd, /* optional */
4669 : const char *arg_label, /* optional */
4670 : const char *arg_pref) /* optional */
4671 : {
4672 0 : struct bgp *bgp;
4673 0 : struct rfapi_nve_group_cfg *rfg;
4674 0 : struct prefix pfx;
4675 0 : struct rfapi_ip_prefix rpfx;
4676 0 : uint32_t pref = 0;
4677 0 : struct rfapi_vn_option optary[3];
4678 0 : struct rfapi_vn_option *opt = NULL;
4679 0 : int cur_opt = 0;
4680 :
4681 0 : bgp = bgp_get_default(); /* assume main instance for now */
4682 0 : if (!bgp) {
4683 0 : vty_out(vty, "No BGP process is configured\n");
4684 0 : return CMD_WARNING_CONFIG_FAILED;
4685 : }
4686 0 : if (!bgp->rfapi || !bgp->rfapi_cfg) {
4687 0 : vty_out(vty, "VRF support not configured\n");
4688 0 : return CMD_WARNING_CONFIG_FAILED;
4689 : }
4690 :
4691 0 : rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4692 : /* arg checks */
4693 0 : if (!rfg) {
4694 0 : vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4695 : arg_vrf);
4696 0 : return CMD_WARNING_CONFIG_FAILED;
4697 : }
4698 0 : if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
4699 0 : vty_out(vty,
4700 : "VRF \"%s\" is missing RT import/export RT configuration.\n",
4701 : arg_vrf);
4702 0 : return CMD_WARNING_CONFIG_FAILED;
4703 : }
4704 0 : if (!rfg->rd.prefixlen && !arg_rd) {
4705 0 : vty_out(vty,
4706 : "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n",
4707 : arg_vrf);
4708 0 : return CMD_WARNING_CONFIG_FAILED;
4709 : }
4710 0 : if (rfg->label > MPLS_LABEL_MAX && !arg_label) {
4711 0 : vty_out(vty,
4712 : "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n",
4713 : arg_vrf);
4714 0 : return CMD_WARNING_CONFIG_FAILED;
4715 : }
4716 0 : if (!str2prefix(arg_prefix, &pfx)) {
4717 0 : vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
4718 0 : return CMD_WARNING_CONFIG_FAILED;
4719 : }
4720 0 : rfapiQprefix2Rprefix(&pfx, &rpfx);
4721 0 : memset(optary, 0, sizeof(optary));
4722 0 : if (arg_rd) {
4723 0 : opt = &optary[cur_opt++];
4724 0 : opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
4725 0 : if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) {
4726 0 : vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
4727 0 : return CMD_WARNING_CONFIG_FAILED;
4728 : }
4729 : }
4730 0 : if (rfg->label <= MPLS_LABEL_MAX || arg_label) {
4731 0 : struct rfapi_l2address_option *l2o;
4732 0 : if (opt != NULL)
4733 0 : opt->next = &optary[cur_opt];
4734 0 : opt = &optary[cur_opt++];
4735 0 : opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
4736 0 : l2o = &opt->v.l2addr;
4737 0 : if (arg_label) {
4738 0 : int32_t label;
4739 0 : label = strtoul(arg_label, NULL, 10);
4740 0 : l2o->label = label;
4741 : } else
4742 0 : l2o->label = rfg->label;
4743 : }
4744 0 : if (arg_pref) {
4745 0 : char *endptr = NULL;
4746 0 : pref = strtoul(arg_pref, &endptr, 10);
4747 0 : if (*endptr != '\0') {
4748 0 : vty_out(vty,
4749 : "%% Invalid local-preference value \"%s\"\n",
4750 : arg_pref);
4751 0 : return CMD_WARNING_CONFIG_FAILED;
4752 : }
4753 : }
4754 0 : rpfx.cost = 255 - (pref & 255);
4755 0 : vnc_add_vrf_opener(bgp, rfg);
4756 :
4757 0 : if (!rfapi_register(rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL,
4758 : (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) {
4759 0 : struct rfapi_next_hop_entry *head = NULL;
4760 0 : struct rfapi_next_hop_entry *tail = NULL;
4761 0 : struct rfapi_vn_option *vn_opt_new;
4762 :
4763 0 : vnc_zlog_debug_verbose("%s: rfapi_register succeeded",
4764 : __func__);
4765 :
4766 0 : if (bgp->rfapi->rfp_methods.local_cb) {
4767 0 : struct rfapi_descriptor *r =
4768 : (struct rfapi_descriptor *)rfg->rfd;
4769 0 : vn_opt_new = rfapi_vn_options_dup(opt);
4770 :
4771 0 : rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
4772 : &rpfx, 1,
4773 : RFAPI_INFINITE_LIFETIME,
4774 : vn_opt_new, &head, &tail);
4775 0 : if (head) {
4776 0 : bgp->rfapi->flags |= RFAPI_INCALLBACK;
4777 0 : (*bgp->rfapi->rfp_methods.local_cb)(head,
4778 : r->cookie);
4779 0 : bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
4780 : }
4781 0 : head = tail = NULL;
4782 : }
4783 0 : vnc_zlog_debug_verbose(
4784 : "%s completed, count=%d/%d", __func__,
4785 : rfg->rfapi_import_table->local_count[AFI_IP],
4786 : rfg->rfapi_import_table->local_count[AFI_IP6]);
4787 0 : return CMD_SUCCESS;
4788 : }
4789 :
4790 0 : vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
4791 0 : vty_out(vty, "Add failed.\n");
4792 0 : return CMD_WARNING_CONFIG_FAILED;
4793 : }
4794 :
4795 0 : DEFUN (add_vrf_prefix_rd_label_pref,
4796 : add_vrf_prefix_rd_label_pref_cmd,
4797 : "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)}]",
4798 : "Add\n"
4799 : "To a VRF\n"
4800 : "VRF name\n"
4801 : "Add/modify prefix related information\n"
4802 : "IPv4 prefix\n"
4803 : "IPv6 prefix\n"
4804 : "Override configured VRF Route Distinguisher\n"
4805 : "<as-number>:<number> or <ip-address>:<number>\n"
4806 : "Override configured VRF label\n"
4807 : "Label Value <0-1048575>\n"
4808 : "Set advertised local preference\n"
4809 : "local preference (higher=more preferred)\n")
4810 : {
4811 0 : char *arg_vrf = argv[2]->arg;
4812 0 : char *arg_prefix = argv[4]->arg;
4813 0 : char *arg_rd = NULL; /* optional */
4814 0 : char *arg_label = NULL; /* optional */
4815 0 : char *arg_pref = NULL; /* optional */
4816 0 : int pargc = 5;
4817 0 : argc--; /* don't parse argument */
4818 0 : while (pargc < argc) {
4819 0 : switch (argv[pargc++]->arg[0]) {
4820 0 : case 'r':
4821 0 : arg_rd = argv[pargc]->arg;
4822 0 : break;
4823 0 : case 'l':
4824 0 : arg_label = argv[pargc]->arg;
4825 0 : break;
4826 0 : case 'p':
4827 0 : arg_pref = argv[pargc]->arg;
4828 0 : break;
4829 : default:
4830 : break;
4831 : }
4832 0 : pargc++;
4833 : }
4834 :
4835 0 : return vnc_add_vrf_prefix(vty, arg_vrf, arg_prefix, arg_rd, arg_label,
4836 : arg_pref);
4837 : }
4838 :
4839 : /************************************************************************
4840 : * del prefix with vrf
4841 : *
4842 : * clear [vrf <vrf-name>] prefix <prefix> [rd <value>]
4843 : ************************************************************************/
4844 0 : static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
4845 : {
4846 0 : int count = 0;
4847 :
4848 0 : if (rfg->rfapi_import_table == NULL)
4849 : return 0;
4850 :
4851 : afi_t afi = AFI_MAX;
4852 0 : while (afi-- > 0) {
4853 0 : count += rfg->rfapi_import_table->local_count[afi];
4854 : }
4855 : return count;
4856 : }
4857 :
4858 0 : void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
4859 : {
4860 0 : struct rfapi_descriptor *rfd = rfg->rfd;
4861 0 : afi_t afi;
4862 :
4863 0 : if (rfd == NULL)
4864 : return;
4865 : /* check if IT is empty */
4866 : for (afi = 0;
4867 0 : afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0;
4868 0 : afi++)
4869 : ;
4870 :
4871 0 : if (afi == AFI_MAX) {
4872 0 : vnc_zlog_debug_verbose("%s: closing RFD for VRF %s", __func__,
4873 : rfg->name);
4874 0 : rfg->rfd = NULL;
4875 0 : rfapi_close(rfd);
4876 : } else {
4877 0 : vnc_zlog_debug_verbose(
4878 : "%s: VRF %s afi=%d count=%d", __func__, rfg->name, afi,
4879 : rfg->rfapi_import_table->local_count[afi]);
4880 : }
4881 : }
4882 :
4883 0 : static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf,
4884 : const char *arg_prefix, /* NULL = all */
4885 : const char *arg_rd) /* optional */
4886 : {
4887 0 : struct rfapi_nve_group_cfg *rfg;
4888 0 : struct rfapi_local_reg_delete_arg cda;
4889 0 : int rc;
4890 0 : int start_count;
4891 :
4892 0 : if (bgp == NULL)
4893 0 : bgp = bgp_get_default(); /* assume main instance for now */
4894 0 : if (!bgp) {
4895 0 : vty_out(vty, "No BGP process is configured\n");
4896 0 : return CMD_WARNING;
4897 : }
4898 0 : if (!bgp->rfapi || !bgp->rfapi_cfg) {
4899 0 : vty_out(vty, "VRF support not configured\n");
4900 0 : return CMD_WARNING;
4901 : }
4902 0 : rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4903 : /* arg checks */
4904 0 : if (!rfg) {
4905 0 : vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4906 : arg_vrf);
4907 0 : return CMD_WARNING;
4908 : }
4909 0 : rc = parse_deleter_args(vty, bgp, arg_prefix, NULL, NULL, NULL, NULL,
4910 : arg_rd, rfg, &cda);
4911 0 : if (rc != CMD_SUCCESS) /* parse error */
4912 : return rc;
4913 :
4914 0 : start_count = rfapi_cfg_group_it_count(rfg);
4915 0 : clear_vnc_prefix(&cda);
4916 0 : vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count,
4917 : start_count);
4918 0 : return CMD_SUCCESS;
4919 : }
4920 :
4921 0 : 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 0 : char *arg_vrf = argv[2]->arg;
4934 0 : char *arg_prefix = NULL; /* optional */
4935 0 : char *arg_rd = NULL; /* optional */
4936 0 : int pargc = 3;
4937 0 : argc--; /* don't check parameter */
4938 0 : while (pargc < argc) {
4939 0 : switch (argv[pargc++]->arg[0]) {
4940 0 : case 'r':
4941 0 : arg_rd = argv[pargc]->arg;
4942 0 : break;
4943 0 : case 'p':
4944 0 : arg_prefix = argv[pargc]->arg;
4945 0 : break;
4946 : default:
4947 : break;
4948 : }
4949 0 : pargc++;
4950 : }
4951 0 : return vnc_clear_vrf(vty, NULL, arg_vrf, arg_prefix, arg_rd);
4952 : }
4953 :
4954 0 : 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 0 : char *arg_vrf = argv[2]->arg;
4963 0 : return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL);
4964 : }
4965 :
4966 3 : void rfapi_vty_init(void)
4967 : {
4968 3 : install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd);
4969 3 : install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd);
4970 3 : install_element(ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd);
4971 3 : install_element(ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd);
4972 3 : install_element(ENABLE_NODE, &add_vnc_prefix_lnh_cmd);
4973 :
4974 3 : install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_cmd);
4975 3 : install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_cmd);
4976 3 : install_element(ENABLE_NODE, &add_vnc_prefix_cost_cmd);
4977 3 : install_element(ENABLE_NODE, &add_vnc_prefix_life_cmd);
4978 3 : install_element(ENABLE_NODE, &add_vnc_prefix_cmd);
4979 :
4980 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd);
4981 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd);
4982 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd);
4983 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd);
4984 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd);
4985 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_cmd);
4986 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_life_cmd);
4987 3 : install_element(ENABLE_NODE, &add_vnc_mac_vni_cmd);
4988 :
4989 3 : install_element(ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd);
4990 :
4991 3 : install_element(ENABLE_NODE, &clear_vnc_nve_all_cmd);
4992 3 : install_element(ENABLE_NODE, &clear_vnc_nve_vn_un_cmd);
4993 3 : install_element(ENABLE_NODE, &clear_vnc_nve_un_vn_cmd);
4994 3 : install_element(ENABLE_NODE, &clear_vnc_nve_vn_cmd);
4995 3 : install_element(ENABLE_NODE, &clear_vnc_nve_un_cmd);
4996 :
4997 3 : install_element(ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd);
4998 3 : install_element(ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd);
4999 3 : install_element(ENABLE_NODE, &clear_vnc_prefix_un_cmd);
5000 3 : install_element(ENABLE_NODE, &clear_vnc_prefix_vn_cmd);
5001 3 : install_element(ENABLE_NODE, &clear_vnc_prefix_all_cmd);
5002 :
5003 3 : install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_cmd);
5004 3 : install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_cmd);
5005 3 : install_element(ENABLE_NODE, &clear_vnc_mac_un_cmd);
5006 3 : install_element(ENABLE_NODE, &clear_vnc_mac_vn_cmd);
5007 3 : install_element(ENABLE_NODE, &clear_vnc_mac_all_cmd);
5008 :
5009 3 : install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd);
5010 3 : install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd);
5011 3 : install_element(ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd);
5012 3 : install_element(ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd);
5013 3 : install_element(ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd);
5014 :
5015 3 : install_element(ENABLE_NODE, &clear_vrf_prefix_rd_cmd);
5016 3 : install_element(ENABLE_NODE, &clear_vrf_all_cmd);
5017 :
5018 3 : install_element(ENABLE_NODE, &vnc_clear_counters_cmd);
5019 :
5020 3 : install_element(VIEW_NODE, &vnc_show_summary_cmd);
5021 3 : install_element(VIEW_NODE, &vnc_show_nves_cmd);
5022 3 : install_element(VIEW_NODE, &vnc_show_nves_ptct_cmd);
5023 :
5024 3 : install_element(VIEW_NODE, &vnc_show_registrations_pfx_cmd);
5025 3 : install_element(VIEW_NODE, &vnc_show_registrations_some_pfx_cmd);
5026 3 : install_element(VIEW_NODE, &vnc_show_responses_pfx_cmd);
5027 3 : install_element(VIEW_NODE, &vnc_show_responses_some_pfx_cmd);
5028 3 : install_element(VIEW_NODE, &show_vnc_queries_pfx_cmd);
5029 3 : }
|