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