]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_mplsvpn.c
4dacf39fb4b6d93f9e978b134e2611f5cacc2c74
[mirror_frr.git] / bgpd / bgp_mplsvpn.c
1 /* MPLS-VPN
2 Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
3
4 This file is part of GNU Zebra.
5
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "prefix.h"
25 #include "log.h"
26 #include "memory.h"
27 #include "stream.h"
28 #include "queue.h"
29 #include "filter.h"
30
31 #include "lib/json.h"
32 #include "bgpd/bgpd.h"
33 #include "bgpd/bgp_table.h"
34 #include "bgpd/bgp_route.h"
35 #include "bgpd/bgp_attr.h"
36 #include "bgpd/bgp_mplsvpn.h"
37 #include "bgpd/bgp_packet.h"
38 #include "bgpd/bgp_vty.h"
39 #include "bgpd/bgp_vpn.h"
40
41 #if ENABLE_BGP_VNC
42 #include "bgpd/rfapi/rfapi_backend.h"
43 #endif
44
45 extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
46 int *index, afi_t *afi)
47 {
48 int ret = 0;
49 if (argv_find(argv, argc, "vpnv4", index)) {
50 ret = 1;
51 if (afi)
52 *afi = AFI_IP;
53 } else if (argv_find(argv, argc, "vpnv6", index)) {
54 ret = 1;
55 if (afi)
56 *afi = AFI_IP6;
57 }
58 return ret;
59 }
60
61 u_int16_t decode_rd_type(u_char *pnt)
62 {
63 u_int16_t v;
64
65 v = ((u_int16_t)*pnt++ << 8);
66 #if ENABLE_BGP_VNC
67 /*
68 * VNC L2 stores LHI in lower byte, so omit it
69 */
70 if (v != RD_TYPE_VNC_ETH)
71 v |= (u_int16_t)*pnt;
72 #else /* duplicate code for clarity */
73 v |= (u_int16_t)*pnt;
74 #endif
75
76 return v;
77 }
78
79 void encode_rd_type(u_int16_t v, u_char *pnt)
80 {
81 *((u_int16_t *)pnt) = htons(v);
82 }
83
84 u_int32_t decode_label(u_char *pnt)
85 {
86 u_int32_t l;
87
88 l = ((u_int32_t)*pnt++ << 12);
89 l |= (u_int32_t)*pnt++ << 4;
90 l |= (u_int32_t)((*pnt & 0xf0) >> 4);
91 return l;
92 }
93
94 void encode_label(u_int32_t label, u_char *pnt)
95 {
96 if (pnt == NULL)
97 return;
98 *pnt++ = (label >> 12) & 0xff;
99 *pnt++ = (label >> 4) & 0xff;
100 *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */
101 }
102
103 /* type == RD_TYPE_AS */
104 void decode_rd_as(u_char *pnt, struct rd_as *rd_as)
105 {
106 rd_as->as = (u_int16_t)*pnt++ << 8;
107 rd_as->as |= (u_int16_t)*pnt++;
108
109 rd_as->val = ((u_int32_t)*pnt++ << 24);
110 rd_as->val |= ((u_int32_t)*pnt++ << 16);
111 rd_as->val |= ((u_int32_t)*pnt++ << 8);
112 rd_as->val |= (u_int32_t)*pnt;
113 }
114
115 /* type == RD_TYPE_AS4 */
116 void decode_rd_as4(u_char *pnt, struct rd_as *rd_as)
117 {
118 rd_as->as = (u_int32_t)*pnt++ << 24;
119 rd_as->as |= (u_int32_t)*pnt++ << 16;
120 rd_as->as |= (u_int32_t)*pnt++ << 8;
121 rd_as->as |= (u_int32_t)*pnt++;
122
123 rd_as->val = ((u_int16_t)*pnt++ << 8);
124 rd_as->val |= (u_int16_t)*pnt;
125 }
126
127 /* type == RD_TYPE_IP */
128 void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip)
129 {
130 memcpy(&rd_ip->ip, pnt, 4);
131 pnt += 4;
132
133 rd_ip->val = ((u_int16_t)*pnt++ << 8);
134 rd_ip->val |= (u_int16_t)*pnt;
135 }
136
137 #if ENABLE_BGP_VNC
138 /* type == RD_TYPE_VNC_ETH */
139 void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
140 {
141 rd_vnc_eth->type = RD_TYPE_VNC_ETH;
142 rd_vnc_eth->local_nve_id = pnt[1];
143 memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
144 }
145 #endif
146
147 int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
148 struct bgp_nlri *packet)
149 {
150 u_char *pnt;
151 u_char *lim;
152 struct prefix p;
153 int psize = 0;
154 int prefixlen;
155 u_int16_t type;
156 struct rd_as rd_as;
157 struct rd_ip rd_ip;
158 struct prefix_rd prd;
159 u_char *tagpnt;
160 afi_t afi;
161 safi_t safi;
162 int addpath_encoded;
163 u_int32_t addpath_id;
164
165 /* Check peer status. */
166 if (peer->status != Established)
167 return 0;
168
169 /* Make prefix_rd */
170 prd.family = AF_UNSPEC;
171 prd.prefixlen = 64;
172
173 pnt = packet->nlri;
174 lim = pnt + packet->length;
175 afi = packet->afi;
176 safi = packet->safi;
177 addpath_id = 0;
178
179 addpath_encoded =
180 (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
181 && CHECK_FLAG(peer->af_cap[afi][safi],
182 PEER_CAP_ADDPATH_AF_TX_RCV));
183
184 #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
185 for (; pnt < lim; pnt += psize) {
186 /* Clear prefix structure. */
187 memset(&p, 0, sizeof(struct prefix));
188
189 if (addpath_encoded) {
190
191 /* When packet overflow occurs return immediately. */
192 if (pnt + BGP_ADDPATH_ID_LEN > lim)
193 return -1;
194
195 addpath_id = ntohl(*((uint32_t *)pnt));
196 pnt += BGP_ADDPATH_ID_LEN;
197 }
198
199 /* Fetch prefix length. */
200 prefixlen = *pnt++;
201 p.family = afi2family(packet->afi);
202 psize = PSIZE(prefixlen);
203
204 if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) {
205 zlog_err(
206 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
207 peer->host, prefixlen);
208 return -1;
209 }
210
211 /* sanity check against packet data */
212 if ((pnt + psize) > lim) {
213 zlog_err(
214 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
215 peer->host, prefixlen, (uint)(lim - pnt));
216 return -1;
217 }
218
219 /* sanity check against storage for the IP address portion */
220 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) {
221 zlog_err(
222 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
223 peer->host,
224 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
225 sizeof(p.u));
226 return -1;
227 }
228
229 /* Sanity check against max bitlen of the address family */
230 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) {
231 zlog_err(
232 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
233 peer->host,
234 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
235 p.family, prefix_blen(&p));
236 return -1;
237 }
238
239 /* Copyr label to prefix. */
240 tagpnt = pnt;
241
242 /* Copy routing distinguisher to rd. */
243 memcpy(&prd.val, pnt + 3, 8);
244
245 /* Decode RD type. */
246 type = decode_rd_type(pnt + 3);
247
248 switch (type) {
249 case RD_TYPE_AS:
250 decode_rd_as(pnt + 5, &rd_as);
251 break;
252
253 case RD_TYPE_AS4:
254 decode_rd_as4(pnt + 5, &rd_as);
255 break;
256
257 case RD_TYPE_IP:
258 decode_rd_ip(pnt + 5, &rd_ip);
259 break;
260
261 #if ENABLE_BGP_VNC
262 case RD_TYPE_VNC_ETH:
263 break;
264 #endif
265
266 default:
267 zlog_err("Unknown RD type %d", type);
268 break; /* just report */
269 }
270
271 p.prefixlen =
272 prefixlen
273 - VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */
274 memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
275 psize - VPN_PREFIXLEN_MIN_BYTES);
276
277 if (attr) {
278 bgp_update(peer, &p, addpath_id, attr, packet->afi,
279 SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
280 BGP_ROUTE_NORMAL, &prd, tagpnt, 0, NULL);
281 } else {
282 bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
283 SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
284 BGP_ROUTE_NORMAL, &prd, tagpnt, NULL);
285 }
286 }
287 /* Packet length consistency check. */
288 if (pnt != lim) {
289 zlog_err(
290 "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
291 peer->host, lim - pnt);
292 return -1;
293 }
294
295 return 0;
296 #undef VPN_PREFIXLEN_MIN_BYTES
297 }
298
299 int str2prefix_rd(const char *str, struct prefix_rd *prd)
300 {
301 int ret; /* ret of called functions */
302 int lret; /* local ret, of this func */
303 char *p;
304 char *p2;
305 struct stream *s = NULL;
306 char *half = NULL;
307 struct in_addr addr;
308
309 s = stream_new(8);
310
311 prd->family = AF_UNSPEC;
312 prd->prefixlen = 64;
313
314 lret = 0;
315 p = strchr(str, ':');
316 if (!p)
317 goto out;
318
319 if (!all_digit(p + 1))
320 goto out;
321
322 half = XMALLOC(MTYPE_TMP, (p - str) + 1);
323 memcpy(half, str, (p - str));
324 half[p - str] = '\0';
325
326 p2 = strchr(str, '.');
327
328 if (!p2) {
329 unsigned long as_val;
330
331 if (!all_digit(half))
332 goto out;
333
334 as_val = atol(half);
335 if (as_val > 0xffff) {
336 stream_putw(s, RD_TYPE_AS4);
337 stream_putl(s, as_val);
338 stream_putw(s, atol(p + 1));
339 } else {
340 stream_putw(s, RD_TYPE_AS);
341 stream_putw(s, as_val);
342 stream_putl(s, atol(p + 1));
343 }
344 } else {
345 ret = inet_aton(half, &addr);
346 if (!ret)
347 goto out;
348
349 stream_putw(s, RD_TYPE_IP);
350 stream_put_in_addr(s, &addr);
351 stream_putw(s, atol(p + 1));
352 }
353 memcpy(prd->val, s->data, 8);
354 lret = 1;
355
356 out:
357 if (s)
358 stream_free(s);
359 if (half)
360 XFREE(MTYPE_TMP, half);
361 return lret;
362 }
363
364 char *prefix_rd2str(struct prefix_rd *prd, char *buf, size_t size)
365 {
366 u_char *pnt;
367 u_int16_t type;
368 struct rd_as rd_as;
369 struct rd_ip rd_ip;
370
371 if (size < RD_ADDRSTRLEN)
372 return NULL;
373
374 pnt = prd->val;
375
376 type = decode_rd_type(pnt);
377
378 if (type == RD_TYPE_AS) {
379 decode_rd_as(pnt + 2, &rd_as);
380 snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
381 return buf;
382 } else if (type == RD_TYPE_AS4) {
383 decode_rd_as4(pnt + 2, &rd_as);
384 snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
385 return buf;
386 } else if (type == RD_TYPE_IP) {
387 decode_rd_ip(pnt + 2, &rd_ip);
388 snprintf(buf, size, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val);
389 return buf;
390 }
391 #if ENABLE_BGP_VNC
392 else if (type == RD_TYPE_VNC_ETH) {
393 snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
394 *(pnt + 1), /* LHI */
395 *(pnt + 2), /* MAC[0] */
396 *(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
397 *(pnt + 7));
398
399 return buf;
400 }
401 #endif
402 return NULL;
403 }
404
405 /* For testing purpose, static route of MPLS-VPN. */
406 DEFUN (vpnv4_network,
407 vpnv4_network_cmd,
408 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
409 "Specify a network to announce via BGP\n"
410 "IPv4 prefix\n"
411 "Specify Route Distinguisher\n"
412 "VPN Route Distinguisher\n"
413 "VPN NLRI label (tag)\n"
414 "VPN NLRI label (tag)\n"
415 "Label value\n")
416 {
417 int idx_ipv4_prefixlen = 1;
418 int idx_ext_community = 3;
419 int idx_label = 5;
420 return bgp_static_set_safi(
421 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
422 argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0,
423 NULL, NULL, NULL, NULL);
424 }
425
426 DEFUN (vpnv4_network_route_map,
427 vpnv4_network_route_map_cmd,
428 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) route-map WORD",
429 "Specify a network to announce via BGP\n"
430 "IPv4 prefix\n"
431 "Specify Route Distinguisher\n"
432 "VPN Route Distinguisher\n"
433 "VPN NLRI label (tag)\n"
434 "VPN NLRI label (tag)\n"
435 "Label value\n"
436 "route map\n"
437 "route map name\n")
438 {
439 int idx_ipv4_prefixlen = 1;
440 int idx_ext_community = 3;
441 int idx_label = 5;
442 int idx_word_2 = 7;
443 return bgp_static_set_safi(
444 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
445 argv[idx_ext_community]->arg, argv[idx_label]->arg,
446 argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
447 }
448
449 /* For testing purpose, static route of MPLS-VPN. */
450 DEFUN (no_vpnv4_network,
451 no_vpnv4_network_cmd,
452 "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
453 NO_STR
454 "Specify a network to announce via BGP\n"
455 "IPv4 prefix\n"
456 "Specify Route Distinguisher\n"
457 "VPN Route Distinguisher\n"
458 "VPN NLRI label (tag)\n"
459 "VPN NLRI label (tag)\n"
460 "Label value\n")
461 {
462 int idx_ipv4_prefixlen = 2;
463 int idx_ext_community = 4;
464 int idx_label = 6;
465 return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty,
466 argv[idx_ipv4_prefixlen]->arg,
467 argv[idx_ext_community]->arg,
468 argv[idx_label]->arg, 0, NULL, NULL, NULL);
469 }
470
471 DEFUN (vpnv6_network,
472 vpnv6_network_cmd,
473 "network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) [route-map WORD]",
474 "Specify a network to announce via BGP\n"
475 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
476 "Specify Route Distinguisher\n"
477 "VPN Route Distinguisher\n"
478 "VPN NLRI label (tag)\n"
479 "VPN NLRI label (tag)\n"
480 "Label value\n"
481 "route map\n"
482 "route map name\n")
483 {
484 int idx_ipv6_prefix = 1;
485 int idx_ext_community = 3;
486 int idx_label = 5;
487 int idx_word_2 = 7;
488 if (argc == 8)
489 return bgp_static_set_safi(
490 AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
491 argv[idx_ext_community]->arg, argv[idx_label]->arg,
492 argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
493 else
494 return bgp_static_set_safi(
495 AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
496 argv[idx_ext_community]->arg, argv[idx_label]->arg,
497 NULL, 0, NULL, NULL, NULL, NULL);
498 }
499
500 /* For testing purpose, static route of MPLS-VPN. */
501 DEFUN (no_vpnv6_network,
502 no_vpnv6_network_cmd,
503 "no network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
504 NO_STR
505 "Specify a network to announce via BGP\n"
506 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
507 "Specify Route Distinguisher\n"
508 "VPN Route Distinguisher\n"
509 "VPN NLRI label (tag)\n"
510 "VPN NLRI label (tag)\n"
511 "Label value\n")
512 {
513 int idx_ipv6_prefix = 2;
514 int idx_ext_community = 4;
515 int idx_label = 6;
516 return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty,
517 argv[idx_ipv6_prefix]->arg,
518 argv[idx_ext_community]->arg,
519 argv[idx_label]->arg, 0, NULL, NULL, NULL);
520 }
521
522 int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
523 enum bgp_show_type type, void *output_arg, int tags,
524 u_char use_json)
525 {
526 struct bgp *bgp;
527 struct bgp_table *table;
528 struct bgp_node *rn;
529 struct bgp_node *rm;
530 struct bgp_info *ri;
531 int rd_header;
532 int header = 1;
533 char v4_header[] =
534 " Network Next Hop Metric LocPrf Weight Path%s";
535 char v4_header_tag[] =
536 " Network Next Hop In tag/Out tag%s";
537 unsigned long output_count = 0;
538 unsigned long total_count = 0;
539 json_object *json = NULL;
540 json_object *json_mroute = NULL;
541 json_object *json_nroute = NULL;
542 json_object *json_array = NULL;
543 json_object *json_scode = NULL;
544 json_object *json_ocode = NULL;
545
546 bgp = bgp_get_default();
547 if (bgp == NULL) {
548 if (!use_json)
549 vty_out(vty, "No BGP process is configured%s",
550 VTY_NEWLINE);
551 return CMD_WARNING;
552 }
553
554 if (use_json) {
555 json_scode = json_object_new_object();
556 json_ocode = json_object_new_object();
557 json = json_object_new_object();
558 json_mroute = json_object_new_object();
559 json_nroute = json_object_new_object();
560
561 json_object_string_add(json_scode, "suppressed", "s");
562 json_object_string_add(json_scode, "damped", "d");
563 json_object_string_add(json_scode, "history", "h");
564 json_object_string_add(json_scode, "valid", "*");
565 json_object_string_add(json_scode, "best", ">");
566 json_object_string_add(json_scode, "internal", "i");
567
568 json_object_string_add(json_ocode, "igp", "i");
569 json_object_string_add(json_ocode, "egp", "e");
570 json_object_string_add(json_ocode, "incomplete", "?");
571 }
572
573 if ((afi != AFI_IP) && (afi != AFI_IP6)) {
574 vty_out(vty, "Afi %d not supported%s", afi, VTY_NEWLINE);
575 return CMD_WARNING;
576 }
577
578 for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
579 rn = bgp_route_next(rn)) {
580 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
581 continue;
582
583 if ((table = rn->info) != NULL) {
584 rd_header = 1;
585
586 for (rm = bgp_table_top(table); rm;
587 rm = bgp_route_next(rm)) {
588 total_count++;
589 if (use_json)
590 json_array = json_object_new_array();
591 else
592 json_array = NULL;
593
594 for (ri = rm->info; ri; ri = ri->next) {
595 if (type == bgp_show_type_neighbor) {
596 union sockunion *su =
597 output_arg;
598
599 if (ri->peer->su_remote == NULL
600 || !sockunion_same(
601 ri->peer->su_remote,
602 su))
603 continue;
604 }
605 if (header) {
606 if (use_json) {
607 if (!tags) {
608 json_object_int_add(
609 json,
610 "bgpTableVersion",
611 0);
612 json_object_string_add(
613 json,
614 "bgpLocalRouterId",
615 inet_ntoa(
616 bgp->router_id));
617 json_object_object_add(
618 json,
619 "bgpStatusCodes",
620 json_scode);
621 json_object_object_add(
622 json,
623 "bgpOriginCodes",
624 json_ocode);
625 }
626 } else {
627 if (tags)
628 vty_out(vty,
629 v4_header_tag,
630 VTY_NEWLINE);
631 else {
632 vty_out(vty,
633 "BGP table version is 0, local router ID is %s%s",
634 inet_ntoa(
635 bgp->router_id),
636 VTY_NEWLINE);
637 vty_out(vty,
638 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
639 VTY_NEWLINE);
640 vty_out(vty,
641 "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
642 VTY_NEWLINE,
643 VTY_NEWLINE);
644 vty_out(vty,
645 v4_header,
646 VTY_NEWLINE);
647 }
648 }
649 header = 0;
650 }
651
652 if (rd_header) {
653 u_int16_t type;
654 struct rd_as rd_as;
655 struct rd_ip rd_ip = {0};
656 #if ENABLE_BGP_VNC
657 struct rd_vnc_eth rd_vnc_eth = {
658 0};
659 #endif
660 u_char *pnt;
661
662 pnt = rn->p.u.val;
663
664 /* Decode RD type. */
665 type = decode_rd_type(pnt);
666 /* Decode RD value. */
667 if (type == RD_TYPE_AS)
668 decode_rd_as(pnt + 2,
669 &rd_as);
670 else if (type == RD_TYPE_AS4)
671 decode_rd_as4(pnt + 2,
672 &rd_as);
673 else if (type == RD_TYPE_IP)
674 decode_rd_ip(pnt + 2,
675 &rd_ip);
676 #if ENABLE_BGP_VNC
677 else if (type
678 == RD_TYPE_VNC_ETH)
679 decode_rd_vnc_eth(
680 pnt,
681 &rd_vnc_eth);
682 #endif
683
684 if (use_json) {
685 char buffer[BUFSIZ];
686 if (type == RD_TYPE_AS
687 || type == RD_TYPE_AS4)
688 sprintf(buffer,
689 "%u:%d",
690 rd_as.as,
691 rd_as.val);
692 else if (type
693 == RD_TYPE_IP)
694 sprintf(buffer,
695 "%s:%d",
696 inet_ntoa(
697 rd_ip.ip),
698 rd_ip.val);
699 json_object_string_add(
700 json_nroute,
701 "routeDistinguisher",
702 buffer);
703 } else {
704 vty_out(vty,
705 "Route Distinguisher: ");
706
707 if (type == RD_TYPE_AS
708 || type == RD_TYPE_AS4)
709 vty_out(vty,
710 "%u:%d",
711 rd_as.as,
712 rd_as.val);
713 else if (type
714 == RD_TYPE_IP)
715 vty_out(vty,
716 "%s:%d",
717 inet_ntoa(
718 rd_ip.ip),
719 rd_ip.val);
720 #if ENABLE_BGP_VNC
721 else if (
722 type
723 == RD_TYPE_VNC_ETH)
724 vty_out(vty,
725 "%u:%02x:%02x:%02x:%02x:%02x:%02x",
726 rd_vnc_eth
727 .local_nve_id,
728 rd_vnc_eth
729 .macaddr
730 .octet[0],
731 rd_vnc_eth
732 .macaddr
733 .octet[1],
734 rd_vnc_eth
735 .macaddr
736 .octet[2],
737 rd_vnc_eth
738 .macaddr
739 .octet[3],
740 rd_vnc_eth
741 .macaddr
742 .octet[4],
743 rd_vnc_eth
744 .macaddr
745 .octet[5]);
746 #endif
747 vty_out(vty, "%s",
748 VTY_NEWLINE);
749 }
750 rd_header = 0;
751 }
752 if (tags)
753 route_vty_out_tag(vty, &rm->p,
754 ri, 0,
755 SAFI_MPLS_VPN,
756 json_array);
757 else
758 route_vty_out(vty, &rm->p, ri,
759 0, SAFI_MPLS_VPN,
760 json_array);
761 output_count++;
762 }
763
764 if (use_json) {
765 struct prefix *p;
766 char buf_a[BUFSIZ];
767 char buf_b[BUFSIZ];
768 p = &rm->p;
769 sprintf(buf_a, "%s/%d",
770 inet_ntop(p->family,
771 &p->u.prefix, buf_b,
772 BUFSIZ),
773 p->prefixlen);
774 json_object_object_add(
775 json_mroute, buf_a, json_array);
776 }
777 }
778
779 if (use_json) {
780 struct prefix *p;
781 char buf_a[BUFSIZ];
782 char buf_b[BUFSIZ];
783 p = &rn->p;
784 sprintf(buf_a, "%s/%d",
785 inet_ntop(p->family, &p->u.prefix,
786 buf_b, BUFSIZ),
787 p->prefixlen);
788 json_object_object_add(json_nroute, buf_a,
789 json_mroute);
790 }
791 }
792 }
793
794 if (use_json) {
795 json_object_object_add(json, "routes", json_nroute);
796 vty_out(vty, "%s%s", json_object_to_json_string_ext(
797 json, JSON_C_TO_STRING_PRETTY),
798 VTY_NEWLINE);
799 json_object_free(json);
800 } else {
801 if (output_count == 0)
802 vty_out(vty, "No prefixes displayed, %ld exist%s",
803 total_count, VTY_NEWLINE);
804 else
805 vty_out(vty,
806 "%sDisplayed %ld routes and %ld total paths%s",
807 VTY_NEWLINE, output_count, total_count,
808 VTY_NEWLINE);
809 }
810
811 return CMD_SUCCESS;
812 }
813
814 DEFUN (show_bgp_ip_vpn_all_rd,
815 show_bgp_ip_vpn_all_rd_cmd,
816 "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]",
817 SHOW_STR
818 IP_STR
819 BGP_STR
820 BGP_VPNVX_HELP_STR
821 "Display VPN NLRI specific information\n"
822 "Display information for a route distinguisher\n"
823 "VPN Route Distinguisher\n"
824 JSON_STR)
825 {
826 int idx_rd = 5;
827 int ret;
828 struct prefix_rd prd;
829 afi_t afi;
830 int idx = 0;
831
832 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
833 if (argc >= 7 && argv[idx_rd]->arg) {
834 ret = str2prefix_rd(argv[idx_rd]->arg, &prd);
835 if (!ret) {
836 vty_out(vty,
837 "%% Malformed Route Distinguisher%s",
838 VTY_NEWLINE);
839 return CMD_WARNING;
840 }
841 return bgp_show_mpls_vpn(vty, afi, &prd,
842 bgp_show_type_normal, NULL, 0,
843 use_json(argc, argv));
844 } else {
845 return bgp_show_mpls_vpn(vty, afi, NULL,
846 bgp_show_type_normal, NULL, 0,
847 use_json(argc, argv));
848 }
849 }
850 return CMD_SUCCESS;
851 }
852
853 DEFUN (show_ip_bgp_vpn_rd,
854 show_ip_bgp_vpn_rd_cmd,
855 "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:nn_or_IP-address:nn",
856 SHOW_STR
857 IP_STR
858 BGP_STR
859 BGP_AFI_HELP_STR
860 "Address Family modifier\n"
861 "Display information for a route distinguisher\n"
862 "VPN Route Distinguisher\n")
863 {
864 int idx_ext_community = argc - 1;
865 int ret;
866 struct prefix_rd prd;
867 afi_t afi;
868 int idx = 0;
869
870 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
871 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
872 if (!ret) {
873 vty_out(vty, "%% Malformed Route Distinguisher%s",
874 VTY_NEWLINE);
875 return CMD_WARNING;
876 }
877 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
878 NULL, 0, 0);
879 }
880 return CMD_SUCCESS;
881 }
882
883 #ifdef KEEP_OLD_VPN_COMMANDS
884 DEFUN (show_ip_bgp_vpn_all,
885 show_ip_bgp_vpn_all_cmd,
886 "show [ip] bgp <vpnv4|vpnv6>",
887 SHOW_STR
888 IP_STR
889 BGP_STR
890 BGP_VPNVX_HELP_STR)
891 {
892 afi_t afi;
893 int idx = 0;
894
895 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
896 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
897 NULL, 0, 0);
898 return CMD_SUCCESS;
899 }
900
901 DEFUN (show_ip_bgp_vpn_all_tags,
902 show_ip_bgp_vpn_all_tags_cmd,
903 "show [ip] bgp <vpnv4|vpnv6> all tags",
904 SHOW_STR
905 IP_STR
906 BGP_STR
907 BGP_VPNVX_HELP_STR
908 "Display information about all VPNv4/VPNV6 NLRIs\n"
909 "Display BGP tags for prefixes\n")
910 {
911 afi_t afi;
912 int idx = 0;
913
914 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
915 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
916 NULL, 1, 0);
917 return CMD_SUCCESS;
918 }
919
920 DEFUN (show_ip_bgp_vpn_rd_tags,
921 show_ip_bgp_vpn_rd_tags_cmd,
922 "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn tags",
923 SHOW_STR
924 IP_STR
925 BGP_STR
926 BGP_VPNVX_HELP_STR
927 "Display information for a route distinguisher\n"
928 "VPN Route Distinguisher\n"
929 "Display BGP tags for prefixes\n")
930 {
931 int idx_ext_community = 5;
932 int ret;
933 struct prefix_rd prd;
934 afi_t afi;
935 int idx = 0;
936
937 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
938 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
939 if (!ret) {
940 vty_out(vty, "%% Malformed Route Distinguisher%s",
941 VTY_NEWLINE);
942 return CMD_WARNING;
943 }
944 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
945 NULL, 1, 0);
946 }
947 return CMD_SUCCESS;
948 }
949
950 DEFUN (show_ip_bgp_vpn_all_neighbor_routes,
951 show_ip_bgp_vpn_all_neighbor_routes_cmd,
952 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
953 SHOW_STR
954 IP_STR
955 BGP_STR
956 BGP_VPNVX_HELP_STR
957 "Display information about all VPNv4/VPNv6 NLRIs\n"
958 "Detailed information on TCP and BGP neighbor connections\n"
959 "Neighbor to display information about\n"
960 "Display routes learned from neighbor\n"
961 JSON_STR)
962 {
963 int idx_ipv4 = 6;
964 union sockunion su;
965 struct peer *peer;
966 int ret;
967 u_char uj = use_json(argc, argv);
968 afi_t afi;
969 int idx = 0;
970
971 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
972 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
973 if (ret < 0) {
974 if (uj) {
975 json_object *json_no = NULL;
976 json_no = json_object_new_object();
977 json_object_string_add(json_no, "warning",
978 "Malformed address");
979 vty_out(vty, "%s%s",
980 json_object_to_json_string(json_no),
981 VTY_NEWLINE);
982 json_object_free(json_no);
983 } else
984 vty_out(vty, "Malformed address: %s%s",
985 argv[idx_ipv4]->arg, VTY_NEWLINE);
986 return CMD_WARNING;
987 }
988
989 peer = peer_lookup(NULL, &su);
990 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
991 if (uj) {
992 json_object *json_no = NULL;
993 json_no = json_object_new_object();
994 json_object_string_add(
995 json_no, "warning",
996 "No such neighbor or address family");
997 vty_out(vty, "%s%s",
998 json_object_to_json_string(json_no),
999 VTY_NEWLINE);
1000 json_object_free(json_no);
1001 } else
1002 vty_out(vty,
1003 "%% No such neighbor or address family%s",
1004 VTY_NEWLINE);
1005 return CMD_WARNING;
1006 }
1007
1008 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor,
1009 &su, 0, uj);
1010 }
1011 return CMD_SUCCESS;
1012 }
1013
1014 DEFUN (show_ip_bgp_vpn_rd_neighbor_routes,
1015 show_ip_bgp_vpn_rd_neighbor_routes_cmd,
1016 "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
1017 SHOW_STR
1018 IP_STR
1019 BGP_STR
1020 BGP_VPNVX_HELP_STR
1021 "Display information for a route distinguisher\n"
1022 "VPN Route Distinguisher\n"
1023 "Detailed information on TCP and BGP neighbor connections\n"
1024 "Neighbor to display information about\n"
1025 "Display routes learned from neighbor\n"
1026 JSON_STR)
1027 {
1028 int idx_ext_community = 5;
1029 int idx_ipv4 = 7;
1030 int ret;
1031 union sockunion su;
1032 struct peer *peer;
1033 struct prefix_rd prd;
1034 u_char uj = use_json(argc, argv);
1035 afi_t afi;
1036 int idx = 0;
1037
1038 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1039 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1040 if (!ret) {
1041 if (uj) {
1042 json_object *json_no = NULL;
1043 json_no = json_object_new_object();
1044 json_object_string_add(
1045 json_no, "warning",
1046 "Malformed Route Distinguisher");
1047 vty_out(vty, "%s%s",
1048 json_object_to_json_string(json_no),
1049 VTY_NEWLINE);
1050 json_object_free(json_no);
1051 } else
1052 vty_out(vty,
1053 "%% Malformed Route Distinguisher%s",
1054 VTY_NEWLINE);
1055 return CMD_WARNING;
1056 }
1057
1058 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1059 if (ret < 0) {
1060 if (uj) {
1061 json_object *json_no = NULL;
1062 json_no = json_object_new_object();
1063 json_object_string_add(json_no, "warning",
1064 "Malformed address");
1065 vty_out(vty, "%s%s",
1066 json_object_to_json_string(json_no),
1067 VTY_NEWLINE);
1068 json_object_free(json_no);
1069 } else
1070 vty_out(vty, "Malformed address: %s%s",
1071 argv[idx_ext_community]->arg,
1072 VTY_NEWLINE);
1073 return CMD_WARNING;
1074 }
1075
1076 peer = peer_lookup(NULL, &su);
1077 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1078 if (uj) {
1079 json_object *json_no = NULL;
1080 json_no = json_object_new_object();
1081 json_object_string_add(
1082 json_no, "warning",
1083 "No such neighbor or address family");
1084 vty_out(vty, "%s%s",
1085 json_object_to_json_string(json_no),
1086 VTY_NEWLINE);
1087 json_object_free(json_no);
1088 } else
1089 vty_out(vty,
1090 "%% No such neighbor or address family%s",
1091 VTY_NEWLINE);
1092 return CMD_WARNING;
1093 }
1094
1095 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_neighbor,
1096 &su, 0, uj);
1097 }
1098 return CMD_SUCCESS;
1099 }
1100
1101 DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes,
1102 show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd,
1103 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
1104 SHOW_STR
1105 IP_STR
1106 BGP_STR
1107 BGP_VPNVX_HELP_STR
1108 "Display information about all VPNv4/VPNv6 NLRIs\n"
1109 "Detailed information on TCP and BGP neighbor connections\n"
1110 "Neighbor to display information about\n"
1111 "Display the routes advertised to a BGP neighbor\n"
1112 JSON_STR)
1113 {
1114 int idx_ipv4 = 6;
1115 int ret;
1116 struct peer *peer;
1117 union sockunion su;
1118 u_char uj = use_json(argc, argv);
1119 afi_t afi;
1120 int idx = 0;
1121
1122 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1123 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1124 if (ret < 0) {
1125 if (uj) {
1126 json_object *json_no = NULL;
1127 json_no = json_object_new_object();
1128 json_object_string_add(json_no, "warning",
1129 "Malformed address");
1130 vty_out(vty, "%s%s",
1131 json_object_to_json_string(json_no),
1132 VTY_NEWLINE);
1133 json_object_free(json_no);
1134 } else
1135 vty_out(vty, "Malformed address: %s%s",
1136 argv[idx_ipv4]->arg, VTY_NEWLINE);
1137 return CMD_WARNING;
1138 }
1139 peer = peer_lookup(NULL, &su);
1140 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1141 if (uj) {
1142 json_object *json_no = NULL;
1143 json_no = json_object_new_object();
1144 json_object_string_add(
1145 json_no, "warning",
1146 "No such neighbor or address family");
1147 vty_out(vty, "%s%s",
1148 json_object_to_json_string(json_no),
1149 VTY_NEWLINE);
1150 json_object_free(json_no);
1151 } else
1152 vty_out(vty,
1153 "%% No such neighbor or address family%s",
1154 VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
1157 return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
1158 SAFI_MPLS_VPN, uj);
1159 }
1160 return CMD_SUCCESS;
1161 }
1162
1163 DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes,
1164 show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd,
1165 "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
1166 SHOW_STR
1167 IP_STR
1168 BGP_STR
1169 BGP_VPNVX_HELP_STR
1170 "Display information for a route distinguisher\n"
1171 "VPN Route Distinguisher\n"
1172 "Detailed information on TCP and BGP neighbor connections\n"
1173 "Neighbor to display information about\n"
1174 "Display the routes advertised to a BGP neighbor\n"
1175 JSON_STR)
1176 {
1177 int idx_ext_community = 5;
1178 int idx_ipv4 = 7;
1179 int ret;
1180 struct peer *peer;
1181 struct prefix_rd prd;
1182 union sockunion su;
1183 u_char uj = use_json(argc, argv);
1184 afi_t afi;
1185 int idx = 0;
1186
1187 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1188 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1189 if (ret < 0) {
1190 if (uj) {
1191 json_object *json_no = NULL;
1192 json_no = json_object_new_object();
1193 json_object_string_add(json_no, "warning",
1194 "Malformed address");
1195 vty_out(vty, "%s%s",
1196 json_object_to_json_string(json_no),
1197 VTY_NEWLINE);
1198 json_object_free(json_no);
1199 } else
1200 vty_out(vty, "Malformed address: %s%s",
1201 argv[idx_ext_community]->arg,
1202 VTY_NEWLINE);
1203 return CMD_WARNING;
1204 }
1205 peer = peer_lookup(NULL, &su);
1206 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1207 if (uj) {
1208 json_object *json_no = NULL;
1209 json_no = json_object_new_object();
1210 json_object_string_add(
1211 json_no, "warning",
1212 "No such neighbor or address family");
1213 vty_out(vty, "%s%s",
1214 json_object_to_json_string(json_no),
1215 VTY_NEWLINE);
1216 json_object_free(json_no);
1217 } else
1218 vty_out(vty,
1219 "%% No such neighbor or address family%s",
1220 VTY_NEWLINE);
1221 return CMD_WARNING;
1222 }
1223
1224 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1225 if (!ret) {
1226 if (uj) {
1227 json_object *json_no = NULL;
1228 json_no = json_object_new_object();
1229 json_object_string_add(
1230 json_no, "warning",
1231 "Malformed Route Distinguisher");
1232 vty_out(vty, "%s%s",
1233 json_object_to_json_string(json_no),
1234 VTY_NEWLINE);
1235 json_object_free(json_no);
1236 } else
1237 vty_out(vty,
1238 "%% Malformed Route Distinguisher%s",
1239 VTY_NEWLINE);
1240 return CMD_WARNING;
1241 }
1242
1243 return show_adj_route_vpn(vty, peer, &prd, AFI_IP,
1244 SAFI_MPLS_VPN, uj);
1245 }
1246 return CMD_SUCCESS;
1247 }
1248 #endif /* KEEP_OLD_VPN_COMMANDS */
1249
1250 void bgp_mplsvpn_init(void)
1251 {
1252 install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd);
1253 install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
1254 install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
1255
1256 install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd);
1257 install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd);
1258
1259 install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd);
1260 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd);
1261 #ifdef KEEP_OLD_VPN_COMMANDS
1262 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd);
1263 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd);
1264 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd);
1265 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd);
1266 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd);
1267 install_element(VIEW_NODE,
1268 &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd);
1269 install_element(VIEW_NODE,
1270 &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
1271 #endif /* KEEP_OLD_VPN_COMMANDS */
1272 }