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