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