Import Upstream version 1.2.2
[quagga-debian.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 "filter.h"
29
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_table.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_packet.h"
34 #include "bgpd/bgp_attr.h"
35 #include "bgpd/bgp_mplsvpn.h"
36 #include "bgpd/bgp_packet.h"
37
38 static u_int16_t
39 decode_rd_type (u_char *pnt)
40 {
41   u_int16_t v;
42   
43   v = ((u_int16_t) *pnt++ << 8);
44   v |= (u_int16_t) *pnt;
45   return v;
46 }
47
48 u_int32_t
49 decode_label (u_char *pnt)
50 {
51   u_int32_t l;
52
53   l = ((u_int32_t) *pnt++ << 12);
54   l |= (u_int32_t) *pnt++ << 4;
55   l |= (u_int32_t) ((*pnt & 0xf0) >> 4);
56   return l;
57 }
58
59 /* type == RD_TYPE_AS */
60 static void
61 decode_rd_as (u_char *pnt, struct rd_as *rd_as)
62 {
63   rd_as->as = (u_int16_t) *pnt++ << 8;
64   rd_as->as |= (u_int16_t) *pnt++;
65   
66   rd_as->val = ((u_int32_t) *pnt++ << 24);
67   rd_as->val |= ((u_int32_t) *pnt++ << 16);
68   rd_as->val |= ((u_int32_t) *pnt++ << 8);
69   rd_as->val |= (u_int32_t) *pnt;
70 }
71
72 /* type == RD_TYPE_AS4 */
73 static void
74 decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
75 {
76   rd_as->as  = (u_int32_t) *pnt++ << 24;
77   rd_as->as |= (u_int32_t) *pnt++ << 16;
78   rd_as->as |= (u_int32_t) *pnt++ << 8;
79   rd_as->as |= (u_int32_t) *pnt++;
80
81   rd_as->val  = ((u_int16_t) *pnt++ << 8);
82   rd_as->val |= (u_int16_t) *pnt;
83 }
84
85 /* type == RD_TYPE_IP */
86 static void
87 decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
88 {
89   memcpy (&rd_ip->ip, pnt, 4);
90   pnt += 4;
91   
92   rd_ip->val = ((u_int16_t) *pnt++ << 8);
93   rd_ip->val |= (u_int16_t) *pnt;
94 }
95
96 int
97 bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, 
98                     struct bgp_nlri *packet)
99 {
100   u_char *pnt;
101   u_char *lim;
102   struct prefix p;
103   int psize = 0;
104   int prefixlen;
105   u_int16_t type;
106   struct rd_as rd_as;
107   struct rd_ip rd_ip;
108   struct prefix_rd prd;
109   u_char *tagpnt;
110
111   /* Check peer status. */
112   if (peer->status != Established)
113     return 0;
114   
115   /* Make prefix_rd */
116   prd.family = AF_UNSPEC;
117   prd.prefixlen = 64;
118
119   pnt = packet->nlri;
120   lim = pnt + packet->length;
121
122 #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
123   for (; pnt < lim; pnt += psize)
124     {
125       /* Clear prefix structure. */
126       memset (&p, 0, sizeof (struct prefix));
127
128       /* Fetch prefix length. */
129       prefixlen = *pnt++;
130       p.family = afi2family (packet->afi);
131       psize = PSIZE (prefixlen);
132       
133       /* sanity check against packet data */
134       if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8)
135         {
136           plog_err (peer->log, 
137                     "%s [Error] Update packet error / VPNv4"
138                      " (prefix length %d less than VPNv4 min length)",
139                     peer->host, prefixlen);
140           return -1;
141         }
142       if ((pnt + psize) > lim)
143         {
144           plog_err (peer->log,
145                     "%s [Error] Update packet error / VPNv4"
146                     " (psize %u exceeds packet size (%u)",
147                     peer->host, 
148                     prefixlen, (uint)(lim-pnt));
149           return -1;
150         }
151       
152       /* sanity check against storage for the IP address portion */
153       if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u))
154         {
155           plog_err (peer->log,
156                     "%s [Error] Update packet error / VPNv4"
157                     " (psize %u exceeds storage size (%zu)",
158                     peer->host,
159                     prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u));
160           return -1;
161         }
162       
163       /* Sanity check against max bitlen of the address family */
164       if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p))
165         {
166           plog_err (peer->log,
167                     "%s [Error] Update packet error / VPNv4"
168                     " (psize %u exceeds family (%u) max byte len %u)",
169                     peer->host,
170                     prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, 
171                     p.family, prefix_blen (&p));
172           return -1;
173         }
174       
175       /* Copyr label to prefix. */
176       tagpnt = pnt;
177
178       /* Copy routing distinguisher to rd. */
179       memcpy (&prd.val, pnt + 3, 8);
180
181       /* Decode RD type. */
182       type = decode_rd_type (pnt + 3);
183
184       switch (type)
185         {
186         case RD_TYPE_AS:
187           decode_rd_as (pnt + 5, &rd_as);
188           break;
189
190         case RD_TYPE_AS4:
191           decode_rd_as4 (pnt + 5, &rd_as);
192           break;
193
194         case RD_TYPE_IP:
195           decode_rd_ip (pnt + 5, &rd_ip);
196           break;
197
198         default:
199           zlog_err ("Unknown RD type %d", type);
200           break;  /* just report */
201       }
202
203       p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
204       memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, 
205               psize - VPN_PREFIXLEN_MIN_BYTES);
206
207       if (attr)
208         bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
209                     ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
210       else
211         bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
212                       ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
213     }
214   /* Packet length consistency check. */
215   if (pnt != lim)
216     {
217       plog_err (peer->log,
218                 "%s [Error] Update packet error / VPNv4"
219                 " (%zu data remaining after parsing)",
220                 peer->host, lim - pnt);
221       return -1;
222     }
223   
224   return 0;
225 #undef VPN_PREFIXLEN_MIN_BYTES
226 }
227
228 int
229 str2prefix_rd (const char *str, struct prefix_rd *prd)
230 {
231   int ret; /* ret of called functions */
232   int lret; /* local ret, of this func */
233   char *p;
234   char *p2;
235   struct stream *s = NULL;
236   char *half = NULL;
237   struct in_addr addr;
238
239   s = stream_new (8);
240
241   prd->family = AF_UNSPEC;
242   prd->prefixlen = 64;
243
244   lret = 0;
245   p = strchr (str, ':');
246   if (! p)
247     goto out;
248
249   if (! all_digit (p + 1))
250     goto out;
251
252   half = XMALLOC (MTYPE_TMP, (p - str) + 1);
253   memcpy (half, str, (p - str));
254   half[p - str] = '\0';
255
256   p2 = strchr (str, '.');
257
258   if (! p2)
259     {
260       if (! all_digit (half))
261         goto out;
262       
263       stream_putw (s, RD_TYPE_AS);
264       stream_putw (s, atoi (half));
265       stream_putl (s, atol (p + 1));
266     }
267   else
268     {
269       ret = inet_aton (half, &addr);
270       if (! ret)
271         goto out;
272       
273       stream_putw (s, RD_TYPE_IP);
274       stream_put_in_addr (s, &addr);
275       stream_putw (s, atol (p + 1));
276     }
277   memcpy (prd->val, s->data, 8);
278   lret = 1;
279
280 out:
281   if (s)
282     stream_free (s);
283   if (half)
284     XFREE(MTYPE_TMP, half);
285   return lret;
286 }
287
288 int
289 str2tag (const char *str, u_char *tag)
290 {
291   unsigned long l;
292   char *endptr;
293   u_int32_t t;
294
295   if (*str == '-')
296     return 0;
297   
298   errno = 0;
299   l = strtoul (str, &endptr, 10);
300
301   if (*endptr != '\0' || errno || l > UINT32_MAX)
302     return 0;
303
304   t = (u_int32_t) l;
305   
306   tag[0] = (u_char)(t >> 12);
307   tag[1] = (u_char)(t >> 4);
308   tag[2] = (u_char)(t << 4);
309
310   return 1;
311 }
312
313 char *
314 prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
315 {
316   u_char *pnt;
317   u_int16_t type;
318   struct rd_as rd_as;
319   struct rd_ip rd_ip;
320
321   if (size < RD_ADDRSTRLEN)
322     return NULL;
323
324   pnt = prd->val;
325
326   type = decode_rd_type (pnt);
327
328   if (type == RD_TYPE_AS)
329     {
330       decode_rd_as (pnt + 2, &rd_as);
331       snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
332       return buf;
333     }
334   else if (type == RD_TYPE_AS4)
335     {
336       decode_rd_as4 (pnt + 2, &rd_as);
337       snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
338       return buf;
339     }
340   else if (type == RD_TYPE_IP)
341     {
342       decode_rd_ip (pnt + 2, &rd_ip);
343       snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
344       return buf;
345     }
346   return NULL;
347 }
348
349 /* For testing purpose, static route of MPLS-VPN. */
350 DEFUN (vpnv4_network,
351        vpnv4_network_cmd,
352        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
353        "Specify a network to announce via BGP\n"
354        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
355        "Specify Route Distinguisher\n"
356        "VPN Route Distinguisher\n"
357        "BGP tag\n"
358        "tag value\n")
359 {
360   return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], NULL);
361 }
362
363 DEFUN (vpnv4_network_route_map,
364        vpnv4_network_route_map_cmd,
365        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD route-map WORD",
366        "Specify a network to announce via BGP\n"
367        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
368        "Specify Route Distinguisher\n"
369        "VPN Route Distinguisher\n"
370        "BGP tag\n"
371        "tag value\n"
372        "route map\n"
373        "route map name\n")
374 {
375   return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], argv[3]);
376 }
377
378 /* For testing purpose, static route of MPLS-VPN. */
379 DEFUN (no_vpnv4_network,
380        no_vpnv4_network_cmd,
381        "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
382        NO_STR
383        "Specify a network to announce via BGP\n"
384        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
385        "Specify Route Distinguisher\n"
386        "VPN Route Distinguisher\n"
387        "BGP tag\n"
388        "tag value\n")
389 {
390   return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2]);
391 }
392
393 static int
394 show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd)
395 {
396   struct bgp *bgp;
397   struct bgp_table *table;
398   struct bgp_node *rn;
399   struct bgp_node *rm;
400   struct attr *attr;
401   int rd_header;
402   int header = 1;
403   char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
404
405   bgp = bgp_get_default ();
406   if (bgp == NULL)
407     {
408       vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
409       return CMD_WARNING;
410     }
411
412   for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn;
413        rn = bgp_route_next (rn))
414     {
415       if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
416         continue;
417
418       if ((table = rn->info) != NULL)
419         {
420           rd_header = 1;
421
422           for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
423             if ((attr = rm->info) != NULL)
424               {
425                 if (header)
426                   {
427                     vty_out (vty, "BGP table version is 0, local router ID is %s%s",
428                              inet_ntoa (bgp->router_id), VTY_NEWLINE);
429                     vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
430                              VTY_NEWLINE);
431                     vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
432                              VTY_NEWLINE, VTY_NEWLINE);
433                     vty_out (vty, v4_header, VTY_NEWLINE);
434                     header = 0;
435                   }
436
437                 if (rd_header)
438                   {
439                     u_int16_t type;
440                     struct rd_as rd_as;
441                     struct rd_ip rd_ip;
442                     u_char *pnt;
443
444                     pnt = rn->p.u.val;
445
446                     /* Decode RD type. */
447                     type = decode_rd_type (pnt);
448                     /* Decode RD value. */
449                     if (type == RD_TYPE_AS)
450                       decode_rd_as (pnt + 2, &rd_as);
451                     else if (type == RD_TYPE_AS4)
452                       decode_rd_as4 (pnt + 2, &rd_as);
453                     else if (type == RD_TYPE_IP)
454                       decode_rd_ip (pnt + 2, &rd_ip);
455
456                     vty_out (vty, "Route Distinguisher: ");
457
458                     if (type == RD_TYPE_AS)
459                       vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
460                     else if (type == RD_TYPE_AS4)
461                       vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
462                     else if (type == RD_TYPE_IP)
463                       vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
464
465                     vty_out (vty, "%s", VTY_NEWLINE);
466                     rd_header = 0;
467                   }
468                 route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN);
469               }
470         }
471     }
472   return CMD_SUCCESS;
473 }
474
475 enum bgp_show_type
476 {
477   bgp_show_type_normal,
478   bgp_show_type_regexp,
479   bgp_show_type_prefix_list,
480   bgp_show_type_filter_list,
481   bgp_show_type_neighbor,
482   bgp_show_type_cidr_only,
483   bgp_show_type_prefix_longer,
484   bgp_show_type_community_all,
485   bgp_show_type_community,
486   bgp_show_type_community_exact,
487   bgp_show_type_community_list,
488   bgp_show_type_community_list_exact
489 };
490
491 static int
492 bgp_show_mpls_vpn(
493     struct vty *vty,
494     afi_t afi,
495     struct prefix_rd *prd,
496     enum bgp_show_type type,
497     void *output_arg,
498     int tags)
499 {
500   struct bgp *bgp;
501   struct bgp_table *table;
502   struct bgp_node *rn;
503   struct bgp_node *rm;
504   struct bgp_info *ri;
505   int rd_header;
506   int header = 1;
507   char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
508   char v4_header_tag[] = "   Network          Next Hop      In tag/Out tag%s";
509
510   unsigned long output_count = 0;
511   unsigned long total_count  = 0;
512
513   bgp = bgp_get_default ();
514   if (bgp == NULL)
515     {
516       vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
517       return CMD_WARNING;
518     }
519   
520   if ((afi != AFI_IP) && (afi != AFI_IP6))
521     {
522       vty_out (vty, "Afi %d not supported%s", afi, VTY_NEWLINE);
523       return CMD_WARNING;
524     }
525
526   for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
527     {
528       if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
529         continue;
530
531       if ((table = rn->info) != NULL)
532         {
533           rd_header = 1;
534
535           for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
536             for (ri = rm->info; ri; ri = ri->next)
537               {
538                 total_count++;
539                 if (type == bgp_show_type_neighbor)
540                   {
541                     union sockunion *su = output_arg;
542
543                     if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
544                       continue;
545                   }
546                 if (header)
547                   {
548                     if (tags)
549                       vty_out (vty, v4_header_tag, VTY_NEWLINE);
550                     else
551                       {
552                         vty_out (vty, "BGP table version is 0, local router ID is %s%s",
553                                  inet_ntoa (bgp->router_id), VTY_NEWLINE);
554                         vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
555                                  VTY_NEWLINE);
556                         vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
557                                  VTY_NEWLINE, VTY_NEWLINE);
558                         vty_out (vty, v4_header, VTY_NEWLINE);
559                       }
560                     header = 0;
561                   }
562
563                 if (rd_header)
564                   {
565                     u_int16_t type;
566                     struct rd_as rd_as;
567                     struct rd_ip rd_ip;
568                     u_char *pnt;
569
570                     pnt = rn->p.u.val;
571
572                     /* Decode RD type. */
573                     type = decode_rd_type (pnt);
574                     /* Decode RD value. */
575                     if (type == RD_TYPE_AS)
576                       decode_rd_as (pnt + 2, &rd_as);
577                     else if (type == RD_TYPE_AS4)
578                       decode_rd_as4 (pnt + 2, &rd_as);
579                     else if (type == RD_TYPE_IP)
580                       decode_rd_ip (pnt + 2, &rd_ip);
581
582                     vty_out (vty, "Route Distinguisher: ");
583
584                     if (type == RD_TYPE_AS)
585                       vty_out (vty, "as2 %u:%d", rd_as.as, rd_as.val);
586                     else if (type == RD_TYPE_AS4)
587                       vty_out (vty, "as4 %u:%d", rd_as.as, rd_as.val);
588                     else if (type == RD_TYPE_IP)
589                       vty_out (vty, "ip %s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
590                   
591                     vty_out (vty, "%s", VTY_NEWLINE);             
592                     rd_header = 0;
593                   }
594                 if (tags)
595                   route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
596                 else
597                   route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
598                 output_count++;
599               }
600         }
601     }
602
603   if (output_count == 0)
604     {
605       vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
606     }
607   else
608     vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
609              VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
610
611   return CMD_SUCCESS;
612 }
613
614 DEFUN (show_bgp_ipv4_vpn,
615        show_bgp_ipv4_vpn_cmd,
616        "show bgp ipv4 vpn",
617        SHOW_STR
618        BGP_STR
619        "Address Family\n"
620        "Display VPN NLRI specific information\n")
621 {
622   return bgp_show_mpls_vpn (vty, AFI_IP, NULL, bgp_show_type_normal, NULL, 0);
623 }
624
625 DEFUN (show_bgp_ipv6_vpn,
626        show_bgp_ipv6_vpn_cmd,
627        "show bgp ipv6 vpn",
628        SHOW_STR
629        BGP_STR
630        "Address Family\n"
631        "Display VPN NLRI specific information\n")
632 {
633   return bgp_show_mpls_vpn (vty, AFI_IP6, NULL, bgp_show_type_normal, NULL, 0);
634 }
635
636 DEFUN (show_bgp_ipv4_vpn_rd,
637        show_bgp_ipv4_vpn_rd_cmd,
638        "show bgp ipv4 vpn rd ASN:nn_or_IP-address:nn",
639        SHOW_STR
640        BGP_STR
641        "Address Family\n"
642        "Display VPN NLRI specific information\n"
643        "Display information for a route distinguisher\n"
644        "VPN Route Distinguisher\n")
645 {
646   int ret;
647   struct prefix_rd prd;
648
649   ret = str2prefix_rd (argv[0], &prd);
650   if (! ret)
651     {
652       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
653       return CMD_WARNING;
654     }
655   return bgp_show_mpls_vpn (vty, AFI_IP, &prd, bgp_show_type_normal, NULL, 0);
656 }
657
658 DEFUN (show_bgp_ipv6_vpn_rd,
659        show_bgp_ipv6_vpn_rd_cmd,
660        "show bgp ipv6 vpn rd ASN:nn_or_IP-address:nn",
661        SHOW_STR
662        BGP_STR
663        "Address Family\n"
664        "Display VPN NLRI specific information\n"
665        "Display information for a route distinguisher\n"
666        "VPN Route Distinguisher\n")
667 {
668   int ret;
669   struct prefix_rd prd;
670
671   ret = str2prefix_rd (argv[0], &prd);
672   if (! ret)
673     {
674       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
675       return CMD_WARNING;
676     }
677   return bgp_show_mpls_vpn (vty, AFI_IP6, &prd, bgp_show_type_normal, NULL, 0);
678 }
679
680
681 DEFUN (show_bgp_ipv4_vpn_tags,
682        show_bgp_ipv4_vpn_tags_cmd,
683        "show bgp ipv4 vpn tags",
684        SHOW_STR
685        BGP_STR
686        "Address Family\n"
687        "Display VPN NLRI specific information\n"
688        "Display BGP tags for prefixes\n")
689 {
690   return bgp_show_mpls_vpn (vty, AFI_IP, NULL, bgp_show_type_normal, NULL,  1);
691 }
692 DEFUN (show_bgp_ipv6_vpn_tags,
693        show_bgp_ipv6_vpn_tags_cmd,
694        "show bgp ipv6 vpn tags",
695        SHOW_STR
696        BGP_STR
697        "Address Family\n"
698        "Display VPN NLRI specific information\n"
699        "Display BGP tags for prefixes\n")
700 {
701   return bgp_show_mpls_vpn (vty, AFI_IP6, NULL, bgp_show_type_normal, NULL,  1);
702 }
703
704 DEFUN (show_bgp_ipv4_vpn_rd_tags,
705        show_bgp_ipv4_vpn_rd_tags_cmd,
706        "show bgp ipv4 vpn rd ASN:nn_or_IP-address:nn tags",
707        SHOW_STR
708        BGP_STR
709        "Address Family\n"
710        "Display VPN NLRI specific information\n"
711        "Display information for a route distinguisher\n"
712        "VPN Route Distinguisher\n"
713        "Display BGP tags for prefixes\n")
714 {
715   int ret;
716   struct prefix_rd prd;
717
718   ret = str2prefix_rd (argv[0], &prd);
719   if (! ret)
720     {
721       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
722       return CMD_WARNING;
723     }
724   return bgp_show_mpls_vpn (vty, AFI_IP, &prd, bgp_show_type_normal, NULL, 1);
725 }
726 DEFUN (show_bgp_ipv6_vpn_rd_tags,
727        show_bgp_ipv6_vpn_rd_tags_cmd,
728        "show bgp ipv6 vpn rd ASN:nn_or_IP-address:nn tags",
729        SHOW_STR
730        BGP_STR
731        "Address Family\n"
732        "Display VPN NLRI specific information\n"
733        "Display information for a route distinguisher\n"
734        "VPN Route Distinguisher\n"
735        "Display BGP tags for prefixes\n")
736 {
737   int ret;
738   struct prefix_rd prd;
739
740   ret = str2prefix_rd (argv[0], &prd);
741   if (! ret)
742     {
743       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
744       return CMD_WARNING;
745     }
746   return bgp_show_mpls_vpn (vty, AFI_IP6, &prd, bgp_show_type_normal, NULL, 1);
747 }
748
749 DEFUN (show_bgp_ipv4_vpn_neighbor_routes,
750        show_bgp_ipv4_vpn_neighbor_routes_cmd,
751        "show bgp ipv4 vpn neighbors (A.B.C.D|X:X::X:X) routes",
752        SHOW_STR
753        BGP_STR
754        "Address Family\n"
755        "Display VPN NLRI specific information\n"
756        "Detailed information on TCP and BGP neighbor connections\n"
757        "Neighbor to display information about\n"
758        "Neighbor to display information about\n"
759        "Display routes learned from neighbor\n")
760 {
761   union sockunion su;
762   struct peer *peer;
763   int ret;
764
765   ret = str2sockunion (argv[0], &su);
766   if (ret < 0)
767     {
768       vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
769       return CMD_WARNING;
770     }
771
772   peer = peer_lookup (NULL, &su);
773   if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
774     {
775       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
776       return CMD_WARNING;
777     }
778
779   return bgp_show_mpls_vpn (vty, AFI_IP, NULL, bgp_show_type_neighbor, &su, 0);
780 }
781
782 DEFUN (show_bgp_ipv6_vpn_neighbor_routes,
783        show_bgp_ipv6_vpn_neighbor_routes_cmd,
784        "show bgp ipv6 vpn neighbors (A.B.C.D|X:X::X:X) routes",
785        SHOW_STR
786        BGP_STR
787        "Address Family\n"
788        "Display VPN NLRI specific information\n"
789        "Detailed information on TCP and BGP neighbor connections\n"
790        "Neighbor to display information about\n"
791        "Neighbor to display information about\n"
792        "Display routes learned from neighbor\n")
793 {
794   union sockunion su;
795   struct peer *peer;
796
797   int ret;
798
799   ret = str2sockunion (argv[0], &su);
800   if (ret < 0)
801     {
802       vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
803       return CMD_WARNING;
804     }
805
806   peer = peer_lookup (NULL, &su);
807   if (! peer || ! peer->afc[AFI_IP6][SAFI_MPLS_VPN])
808     {
809       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
810       return CMD_WARNING;
811     }
812
813   return bgp_show_mpls_vpn (vty, AFI_IP6, NULL, bgp_show_type_neighbor, &su, 0);
814 }
815
816 DEFUN (show_bgp_ipv4_vpn_neighbor_advertised_routes,
817        show_bgp_ipv4_vpn_neighbor_advertised_routes_cmd,
818        "show bgp ipv4 vpn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
819        SHOW_STR
820        BGP_STR
821        "Address Family\n"
822        "Display VPN NLRI specific information\n"
823        "Detailed information on TCP and BGP neighbor connections\n"
824        "Neighbor to display information about\n"
825        "Display the routes advertised to a BGP neighbor\n")
826 {
827   int ret;
828   struct peer *peer;
829   union sockunion su;
830
831   ret = str2sockunion (argv[0], &su);
832   if (ret < 0)
833     {
834       vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
835       return CMD_WARNING;
836     }
837   peer = peer_lookup (NULL, &su);
838   if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
839     {
840       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
841       return CMD_WARNING;
842     }
843
844   return show_adj_route_vpn (vty, peer, NULL);
845 }
846 DEFUN (show_bgp_ipv6_vpn_neighbor_advertised_routes,
847        show_bgp_ipv6_vpn_neighbor_advertised_routes_cmd,
848        "show bgp ipv6 vpn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
849        SHOW_STR
850        BGP_STR
851        "Address Family\n"
852        "Display VPN NLRI specific information\n"
853        "Detailed information on TCP and BGP neighbor connections\n"
854        "Neighbor to display information about\n"
855        "Display the routes advertised to a BGP neighbor\n")
856 {
857   int ret;
858   struct peer *peer;
859   union sockunion su;
860
861   ret = str2sockunion (argv[0], &su);
862   if (ret < 0)
863     {
864       vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
865       return CMD_WARNING;
866     }
867   peer = peer_lookup (NULL, &su);
868   if (! peer || ! peer->afc[AFI_IP6][SAFI_MPLS_VPN])
869     {
870       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
871       return CMD_WARNING;
872     }
873
874   return show_adj_route_vpn (vty, peer, NULL);
875 }
876
877 DEFUN (show_ip_bgp_vpnv4_rd_neighbor_advertised_routes,
878        show_bgp_ipv4_vpn_rd_neighbor_advertised_routes_cmd,
879        "show bgp ipv4 vpn rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
880        SHOW_STR
881        BGP_STR
882        "Address Family\n"
883        "Display VPN NLRI specific information\n"
884        "Display information for a route distinguisher\n"
885        "VPN Route Distinguisher\n"
886        "Detailed information on TCP and BGP neighbor connections\n"
887        "Neighbor to display information about\n"
888        "Neighbor to display information about\n"
889        "Display the routes advertised to a BGP neighbor\n")
890 {
891   int ret;
892   struct peer *peer;
893   struct prefix_rd prd;
894   union sockunion su;
895   ret = str2sockunion (argv[1], &su);
896   if (ret < 0)
897     {
898       vty_out (vty, "%% Malformed address: %s%s", argv[1], VTY_NEWLINE);
899       return CMD_WARNING;
900     }
901   peer = peer_lookup (NULL, &su);
902   if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
903     {
904       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
905       return CMD_WARNING;
906     }
907
908   ret = str2prefix_rd (argv[0], &prd);
909   if (! ret)
910     {
911       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
912       return CMD_WARNING;
913     }
914
915   return show_adj_route_vpn (vty, peer, &prd);
916 }
917 DEFUN (show_ip_bgp_vpnv6_rd_neighbor_advertised_routes,
918        show_bgp_ipv6_vpn_rd_neighbor_advertised_routes_cmd,
919        "show bgp ipv6 vpn rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
920        SHOW_STR
921        BGP_STR
922        "Address Family\n"
923        "Display VPN NLRI specific information\n"
924        "Display information for a route distinguisher\n"
925        "VPN Route Distinguisher\n"
926        "Detailed information on TCP and BGP neighbor connections\n"
927        "Neighbor to display information about\n"
928        "Neighbor to display information about\n"
929        "Display the routes advertised to a BGP neighbor\n")
930 {
931   int ret;
932   struct peer *peer;
933   struct prefix_rd prd;
934   union sockunion su;
935   ret = str2sockunion (argv[1], &su);
936   if (ret < 0)
937     {
938       vty_out (vty, "%% Malformed address: %s%s", argv[1], VTY_NEWLINE);
939       return CMD_WARNING;
940     }
941   peer = peer_lookup (NULL, &su);
942   if (! peer || ! peer->afc[AFI_IP6][SAFI_MPLS_VPN])
943     {
944       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
945       return CMD_WARNING;
946     }
947
948   ret = str2prefix_rd (argv[0], &prd);
949   if (! ret)
950     {
951       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
952       return CMD_WARNING;
953     }
954
955   return show_adj_route_vpn (vty, peer, &prd);
956 }
957
958 DEFUN (show_bgp_ipv4_vpn_rd_neighbor_routes,
959        show_bgp_ipv4_vpn_rd_neighbor_routes_cmd,
960        "show bgp ipv4 vpn rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) routes",
961        SHOW_STR
962        BGP_STR
963        "Address Family\n"
964        "Address Family modifier\n"
965        "Display information for a route distinguisher\n"
966        "VPN Route Distinguisher\n"
967        "Detailed information on TCP and BGP neighbor connections\n"
968        "Neighbor to display information about\n"
969        "Display routes learned from neighbor\n")
970 {
971   int ret;
972   union sockunion su;
973   struct peer *peer;
974   struct prefix_rd prd;
975
976   ret = str2prefix_rd (argv[0], &prd);
977   if (! ret)
978     {
979       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
980       return CMD_WARNING;
981     }
982
983   if (str2sockunion(argv[1], &su))
984     {
985       vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
986                return CMD_WARNING;
987     }
988
989   peer = peer_lookup (NULL, &su);
990   if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
991     {
992       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
993       return CMD_WARNING;
994     }
995
996   return bgp_show_mpls_vpn (vty, AFI_IP, &prd, bgp_show_type_neighbor, &su, 0);
997 }
998 DEFUN (show_bgp_ipv6_vpn_rd_neighbor_routes,
999        show_bgp_ipv6_vpn_rd_neighbor_routes_cmd,
1000        "show bgp ipv6 vpn rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) routes",
1001        SHOW_STR
1002        BGP_STR
1003        "Address Family\n"
1004        "Address Family modifier\n"
1005        "Display information for a route distinguisher\n"
1006        "VPN Route Distinguisher\n"
1007        "Detailed information on TCP and BGP neighbor connections\n"
1008        "Neighbor to display information about\n"
1009        "Display routes learned from neighbor\n")
1010 {
1011   int ret;
1012   union sockunion su;
1013   struct peer *peer;
1014   struct prefix_rd prd;
1015
1016   ret = str2prefix_rd (argv[0], &prd);
1017   if (! ret)
1018     {
1019       vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
1020       return CMD_WARNING;
1021     }
1022
1023   if (str2sockunion(argv[1], &su))
1024     {
1025       vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
1026                return CMD_WARNING;
1027     }
1028
1029   peer = peer_lookup (NULL, &su);
1030   if (! peer || ! peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1031     {
1032       vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
1033       return CMD_WARNING;
1034     }
1035
1036   return bgp_show_mpls_vpn (vty, AFI_IP6, &prd, bgp_show_type_neighbor, &su, 0);
1037 }
1038
1039 void
1040 bgp_mplsvpn_init (void)
1041 {
1042   install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
1043   install_element (BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
1044   install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
1045
1046   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_cmd);
1047   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_rd_cmd);
1048   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_tags_cmd);
1049   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_rd_tags_cmd);
1050   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_neighbor_routes_cmd);
1051   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_neighbor_advertised_routes_cmd);
1052   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_rd_neighbor_advertised_routes_cmd);
1053   install_element (VIEW_NODE, &show_bgp_ipv4_vpn_rd_neighbor_routes_cmd);
1054
1055   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_cmd);
1056   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_rd_cmd);
1057   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_tags_cmd);
1058   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_rd_tags_cmd);
1059   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_neighbor_routes_cmd);
1060   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_neighbor_advertised_routes_cmd);
1061   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_rd_neighbor_advertised_routes_cmd);
1062   install_element (VIEW_NODE, &show_bgp_ipv6_vpn_rd_neighbor_routes_cmd);
1063 }