]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_mplsvpn.c
Merge branch 'master' into bgpd-ipv4-plus-label-misc3
[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 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
554 char v4_header_tag[] = " Network Next Hop In tag/Out tag%s";
555 unsigned long output_count = 0;
556 unsigned long total_count = 0;
557 json_object *json = NULL;
558 json_object *json_mroute = NULL;
559 json_object *json_nroute = NULL;
560 json_object *json_array = NULL;
561 json_object *json_scode = NULL;
562 json_object *json_ocode = NULL;
563
564 bgp = bgp_get_default ();
565 if (bgp == NULL)
566 {
567 if (!use_json)
568 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
569 return CMD_WARNING;
570 }
571
572 if (use_json)
573 {
574 json_scode = json_object_new_object();
575 json_ocode = json_object_new_object();
576 json = json_object_new_object();
577 json_mroute = json_object_new_object();
578 json_nroute = json_object_new_object();
579
580 json_object_string_add(json_scode, "suppressed", "s");
581 json_object_string_add(json_scode, "damped", "d");
582 json_object_string_add(json_scode, "history", "h");
583 json_object_string_add(json_scode, "valid", "*");
584 json_object_string_add(json_scode, "best", ">");
585 json_object_string_add(json_scode, "internal", "i");
586
587 json_object_string_add(json_ocode, "igp", "i");
588 json_object_string_add(json_ocode, "egp", "e");
589 json_object_string_add(json_ocode, "incomplete", "?");
590 }
591
592 if ((afi != AFI_IP) && (afi != AFI_IP6))
593 {
594 vty_out (vty, "Afi %d not supported%s", afi, VTY_NEWLINE);
595 return CMD_WARNING;
596 }
597
598 for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
599 {
600 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
601 continue;
602
603 if ((table = rn->info) != NULL)
604 {
605 rd_header = 1;
606
607 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
608 {
609 total_count++;
610 if (use_json)
611 json_array = json_object_new_array();
612 else
613 json_array = NULL;
614
615 for (ri = rm->info; ri; ri = ri->next)
616 {
617 if (type == bgp_show_type_neighbor)
618 {
619 union sockunion *su = output_arg;
620
621 if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
622 continue;
623 }
624 if (header)
625 {
626 if (use_json)
627 {
628 if (!tags)
629 {
630 json_object_int_add(json, "bgpTableVersion", 0);
631 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
632 json_object_object_add(json, "bgpStatusCodes", json_scode);
633 json_object_object_add(json, "bgpOriginCodes", json_ocode);
634 }
635 }
636 else
637 {
638 if (tags)
639 vty_out (vty, v4_header_tag, VTY_NEWLINE);
640 else
641 {
642 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
643 inet_ntoa (bgp->router_id), VTY_NEWLINE);
644 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
645 VTY_NEWLINE);
646 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
647 VTY_NEWLINE, VTY_NEWLINE);
648 vty_out (vty, v4_header, VTY_NEWLINE);
649 }
650 }
651 header = 0;
652 }
653
654 if (rd_header)
655 {
656 u_int16_t type;
657 struct rd_as rd_as;
658 struct rd_ip rd_ip = {0};
659 #if ENABLE_BGP_VNC
660 struct rd_vnc_eth rd_vnc_eth = {0};
661 #endif
662 u_char *pnt;
663
664 pnt = rn->p.u.val;
665
666 /* Decode RD type. */
667 type = decode_rd_type (pnt);
668 /* Decode RD value. */
669 if (type == RD_TYPE_AS)
670 decode_rd_as (pnt + 2, &rd_as);
671 else if (type == RD_TYPE_AS4)
672 decode_rd_as4 (pnt + 2, &rd_as);
673 else if (type == RD_TYPE_IP)
674 decode_rd_ip (pnt + 2, &rd_ip);
675 #if ENABLE_BGP_VNC
676 else if (type == RD_TYPE_VNC_ETH)
677 decode_rd_vnc_eth (pnt, &rd_vnc_eth);
678 #endif
679
680 if (use_json)
681 {
682 char buffer[BUFSIZ];
683 if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
684 sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
685 else if (type == RD_TYPE_IP)
686 sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
687 json_object_string_add(json_nroute, "routeDistinguisher", buffer);
688 }
689 else
690 {
691 vty_out (vty, "Route Distinguisher: ");
692
693 if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
694 vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
695 else if (type == RD_TYPE_IP)
696 vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
697 #if ENABLE_BGP_VNC
698 else if (type == RD_TYPE_VNC_ETH)
699 vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x",
700 rd_vnc_eth.local_nve_id,
701 rd_vnc_eth.macaddr.octet[0],
702 rd_vnc_eth.macaddr.octet[1],
703 rd_vnc_eth.macaddr.octet[2],
704 rd_vnc_eth.macaddr.octet[3],
705 rd_vnc_eth.macaddr.octet[4],
706 rd_vnc_eth.macaddr.octet[5]);
707 #endif
708 vty_out (vty, "%s", VTY_NEWLINE);
709 }
710 rd_header = 0;
711 }
712 if (tags)
713 route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN, json_array);
714 else
715 route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN, json_array);
716 output_count++;
717 }
718
719 if (use_json)
720 {
721 struct prefix *p;
722 char buf_a[BUFSIZ];
723 char buf_b[BUFSIZ];
724 p = &rm->p;
725 sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
726 json_object_object_add(json_mroute, buf_a, json_array);
727 }
728 }
729
730 if (use_json)
731 {
732 struct prefix *p;
733 char buf_a[BUFSIZ];
734 char buf_b[BUFSIZ];
735 p = &rn->p;
736 sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
737 json_object_object_add(json_nroute, buf_a, json_mroute);
738 }
739 }
740 }
741
742 if (use_json)
743 {
744 json_object_object_add(json, "routes", json_nroute);
745 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
746 json_object_free(json);
747 }
748 else
749 {
750 if (output_count == 0)
751 vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
752 else
753 vty_out (vty, "%sDisplayed %ld routes and %ld total paths%s",
754 VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
755 }
756
757 return CMD_SUCCESS;
758 }
759
760 DEFUN (show_bgp_ip_vpn_all_rd,
761 show_bgp_ip_vpn_all_rd_cmd,
762 "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]",
763 SHOW_STR
764 IP_STR
765 BGP_STR
766 BGP_VPNVX_HELP_STR
767 "Display VPN NLRI specific information\n"
768 "Display information for a route distinguisher\n"
769 "VPN Route Distinguisher\n"
770 JSON_STR)
771 {
772 int idx_rd = 5;
773 int ret;
774 struct prefix_rd prd;
775 afi_t afi;
776 int idx = 0;
777
778 if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
779 {
780 if (argc >= 7 && argv[idx_rd]->arg)
781 {
782 ret = str2prefix_rd (argv[idx_rd]->arg, &prd);
783 if (! ret)
784 {
785 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
786 return CMD_WARNING;
787 }
788 return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 0, use_json (argc, argv));
789 }
790 else
791 {
792 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, use_json (argc, argv));
793 }
794 }
795 return CMD_SUCCESS;
796 }
797
798 DEFUN (show_ip_bgp_vpn_rd,
799 show_ip_bgp_vpn_rd_cmd,
800 "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:nn_or_IP-address:nn",
801 SHOW_STR
802 IP_STR
803 BGP_STR
804 BGP_AFI_HELP_STR
805 "Address Family modifier\n"
806 "Display information for a route distinguisher\n"
807 "VPN Route Distinguisher\n")
808 {
809 int idx_ext_community = argc-1;
810 int ret;
811 struct prefix_rd prd;
812 afi_t afi;
813 int idx = 0;
814
815 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
816 {
817 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
818 if (! ret)
819 {
820 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
821 return CMD_WARNING;
822 }
823 return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 0, 0);
824 }
825 return CMD_SUCCESS;
826 }
827
828 #ifdef KEEP_OLD_VPN_COMMANDS
829 DEFUN (show_ip_bgp_vpn_all,
830 show_ip_bgp_vpn_all_cmd,
831 "show [ip] bgp <vpnv4|vpnv6>",
832 SHOW_STR
833 IP_STR
834 BGP_STR
835 BGP_VPNVX_HELP_STR)
836 {
837 afi_t afi;
838 int idx = 0;
839
840 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
841 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, 0);
842 return CMD_SUCCESS;
843 }
844
845 DEFUN (show_ip_bgp_vpn_all_tags,
846 show_ip_bgp_vpn_all_tags_cmd,
847 "show [ip] bgp <vpnv4|vpnv6> all tags",
848 SHOW_STR
849 IP_STR
850 BGP_STR
851 BGP_VPNVX_HELP_STR
852 "Display information about all VPNv4/VPNV6 NLRIs\n"
853 "Display BGP tags for prefixes\n")
854 {
855 afi_t afi;
856 int idx = 0;
857
858 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
859 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 1, 0);
860 return CMD_SUCCESS;
861 }
862
863 DEFUN (show_ip_bgp_vpn_rd_tags,
864 show_ip_bgp_vpn_rd_tags_cmd,
865 "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn tags",
866 SHOW_STR
867 IP_STR
868 BGP_STR
869 BGP_VPNVX_HELP_STR
870 "Display information for a route distinguisher\n"
871 "VPN Route Distinguisher\n"
872 "Display BGP tags for prefixes\n")
873 {
874 int idx_ext_community = 5;
875 int ret;
876 struct prefix_rd prd;
877 afi_t afi;
878 int idx = 0;
879
880 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
881 {
882 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
883 if (! ret)
884 {
885 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
886 return CMD_WARNING;
887 }
888 return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 1, 0);
889 }
890 return CMD_SUCCESS;
891 }
892
893 DEFUN (show_ip_bgp_vpn_all_neighbor_routes,
894 show_ip_bgp_vpn_all_neighbor_routes_cmd,
895 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
896 SHOW_STR
897 IP_STR
898 BGP_STR
899 BGP_VPNVX_HELP_STR
900 "Display information about all VPNv4/VPNv6 NLRIs\n"
901 "Detailed information on TCP and BGP neighbor connections\n"
902 "Neighbor to display information about\n"
903 "Display routes learned from neighbor\n"
904 JSON_STR)
905 {
906 int idx_ipv4 = 6;
907 union sockunion su;
908 struct peer *peer;
909 int ret;
910 u_char uj = use_json(argc, argv);
911 afi_t afi;
912 int idx = 0;
913
914 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
915 {
916 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
917 if (ret < 0)
918 {
919 if (uj)
920 {
921 json_object *json_no = NULL;
922 json_no = json_object_new_object();
923 json_object_string_add(json_no, "warning", "Malformed address");
924 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
925 json_object_free(json_no);
926 }
927 else
928 vty_out (vty, "Malformed address: %s%s", argv[idx_ipv4]->arg, VTY_NEWLINE);
929 return CMD_WARNING;
930 }
931
932 peer = peer_lookup (NULL, &su);
933 if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN])
934 {
935 if (uj)
936 {
937 json_object *json_no = NULL;
938 json_no = json_object_new_object();
939 json_object_string_add(json_no, "warning", "No such neighbor or address family");
940 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
941 json_object_free(json_no);
942 }
943 else
944 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
945 return CMD_WARNING;
946 }
947
948 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_neighbor, &su, 0, uj);
949 }
950 return CMD_SUCCESS;
951 }
952
953 DEFUN (show_ip_bgp_vpn_rd_neighbor_routes,
954 show_ip_bgp_vpn_rd_neighbor_routes_cmd,
955 "show [ip] bgp <vpnv4|vpnv6> rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
956 SHOW_STR
957 IP_STR
958 BGP_STR
959 BGP_VPNVX_HELP_STR
960 "Display information for a route distinguisher\n"
961 "VPN Route Distinguisher\n"
962 "Detailed information on TCP and BGP neighbor connections\n"
963 "Neighbor to display information about\n"
964 "Display routes learned from neighbor\n"
965 JSON_STR)
966 {
967 int idx_ext_community = 5;
968 int idx_ipv4 = 7;
969 int ret;
970 union sockunion su;
971 struct peer *peer;
972 struct prefix_rd prd;
973 u_char uj = use_json(argc, argv);
974 afi_t afi;
975 int idx = 0;
976
977 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
978 {
979 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
980 if (! ret)
981 {
982 if (uj)
983 {
984 json_object *json_no = NULL;
985 json_no = json_object_new_object();
986 json_object_string_add(json_no, "warning", "Malformed Route Distinguisher");
987 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
988 json_object_free(json_no);
989 }
990 else
991 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
992 return CMD_WARNING;
993 }
994
995 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
996 if (ret < 0)
997 {
998 if (uj)
999 {
1000 json_object *json_no = NULL;
1001 json_no = json_object_new_object();
1002 json_object_string_add(json_no, "warning", "Malformed address");
1003 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1004 json_object_free(json_no);
1005 }
1006 else
1007 vty_out (vty, "Malformed address: %s%s", argv[idx_ext_community]->arg, VTY_NEWLINE);
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_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1020 json_object_free(json_no);
1021 }
1022 else
1023 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
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_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1064 json_object_free(json_no);
1065 }
1066 else
1067 vty_out (vty, "Malformed address: %s%s", argv[idx_ipv4]->arg, VTY_NEWLINE);
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_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1079 json_object_free(json_no);
1080 }
1081 else
1082 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
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_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1125 json_object_free(json_no);
1126 }
1127 else
1128 vty_out (vty, "Malformed address: %s%s", argv[idx_ext_community]->arg, VTY_NEWLINE);
1129 return CMD_WARNING;
1130 }
1131 peer = peer_lookup (NULL, &su);
1132 if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN])
1133 {
1134 if (uj)
1135 {
1136 json_object *json_no = NULL;
1137 json_no = json_object_new_object();
1138 json_object_string_add(json_no, "warning", "No such neighbor or address family");
1139 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1140 json_object_free(json_no);
1141 }
1142 else
1143 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
1144 return CMD_WARNING;
1145 }
1146
1147 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
1148 if (! ret)
1149 {
1150 if (uj)
1151 {
1152 json_object *json_no = NULL;
1153 json_no = json_object_new_object();
1154 json_object_string_add(json_no, "warning", "Malformed Route Distinguisher");
1155 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
1156 json_object_free(json_no);
1157 }
1158 else
1159 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
1160 return CMD_WARNING;
1161 }
1162
1163 return show_adj_route_vpn (vty, peer, &prd, AFI_IP, SAFI_MPLS_VPN, uj);
1164 }
1165 return CMD_SUCCESS;
1166 }
1167 #endif /* KEEP_OLD_VPN_COMMANDS */
1168
1169 void
1170 bgp_mplsvpn_init (void)
1171 {
1172 install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
1173 install_element (BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
1174 install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
1175
1176 install_element (BGP_VPNV6_NODE, &vpnv6_network_cmd);
1177 install_element (BGP_VPNV6_NODE, &no_vpnv6_network_cmd);
1178
1179 install_element (VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd);
1180 install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_cmd);
1181 #ifdef KEEP_OLD_VPN_COMMANDS
1182 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_cmd);
1183 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd);
1184 install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd);
1185 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd);
1186 install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd);
1187 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd);
1188 install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
1189 #endif /* KEEP_OLD_VPN_COMMANDS */
1190 }