blob: 135a1187acb39ea963467a455f401cc322759b5f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* MPLS-VPN
2 Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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
29#include "bgpd/bgpd.h"
30#include "bgpd/bgp_table.h"
31#include "bgpd/bgp_route.h"
32#include "bgpd/bgp_attr.h"
33#include "bgpd/bgp_mplsvpn.h"
34
paul718e3742002-12-13 20:15:29 +000035u_int16_t
36decode_rd_type (u_char *pnt)
37{
38 u_int16_t v;
39
40 v = ((u_int16_t) *pnt++ << 8);
41 v |= (u_int16_t) *pnt;
42 return v;
43}
44
45u_int32_t
46decode_label (u_char *pnt)
47{
48 u_int32_t l;
49
50 l = ((u_int32_t) *pnt++ << 12);
51 l |= (u_int32_t) *pnt++ << 4;
52 l |= (u_int32_t) ((*pnt & 0xf0) >> 4);
53 return l;
54}
55
56void
57decode_rd_as (u_char *pnt, struct rd_as *rd_as)
58{
59 rd_as->as = (u_int16_t) *pnt++ << 8;
60 rd_as->as |= (u_int16_t) *pnt++;
61
62 rd_as->val = ((u_int32_t) *pnt++ << 24);
63 rd_as->val |= ((u_int32_t) *pnt++ << 16);
64 rd_as->val |= ((u_int32_t) *pnt++ << 8);
65 rd_as->val |= (u_int32_t) *pnt;
66}
67
68void
69decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
70{
71 memcpy (&rd_ip->ip, pnt, 4);
72 pnt += 4;
73
74 rd_ip->val = ((u_int16_t) *pnt++ << 8);
75 rd_ip->val |= (u_int16_t) *pnt;
76}
77
78int bgp_update (struct peer *, struct prefix *, struct attr *,
79 afi_t, safi_t, int, int, struct prefix_rd *, u_char *);
80
81int bgp_withdraw (struct peer *, struct prefix *, struct attr *,
82 int, int, int, int, struct prefix_rd *, u_char *);
83int
84bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
85 struct bgp_nlri *packet)
86{
87 u_char *pnt;
88 u_char *lim;
89 struct prefix p;
90 int psize;
91 int prefixlen;
92 u_int32_t label;
93 u_int16_t type;
94 struct rd_as rd_as;
95 struct rd_ip rd_ip;
96 struct prefix_rd prd;
97 u_char *tagpnt;
98
99 /* Check peer status. */
100 if (peer->status != Established)
101 return 0;
102
103 /* Make prefix_rd */
104 prd.family = AF_UNSPEC;
105 prd.prefixlen = 64;
106
107 pnt = packet->nlri;
108 lim = pnt + packet->length;
109
110 for (; pnt < lim; pnt += psize)
111 {
112 /* Clear prefix structure. */
113 memset (&p, 0, sizeof (struct prefix));
114
115 /* Fetch prefix length. */
116 prefixlen = *pnt++;
117 p.family = AF_INET;
118 psize = PSIZE (prefixlen);
119
120 if (prefixlen < 88)
121 {
122 zlog_err ("prefix length is less than 88: %d", prefixlen);
123 return -1;
124 }
125
126 label = decode_label (pnt);
127
128 /* Copyr label to prefix. */
129 tagpnt = pnt;;
130
131 /* Copy routing distinguisher to rd. */
132 memcpy (&prd.val, pnt + 3, 8);
133
134 /* Decode RD type. */
135 type = decode_rd_type (pnt + 3);
136
137 /* Decode RD value. */
138 if (type == RD_TYPE_AS)
139 decode_rd_as (pnt + 5, &rd_as);
140 else if (type == RD_TYPE_IP)
141 decode_rd_ip (pnt + 5, &rd_ip);
142 else
143 {
144 zlog_err ("Invalid RD type %d", type);
145 return -1;
146 }
147
148 p.prefixlen = prefixlen - 88;
149 memcpy (&p.u.prefix, pnt + 11, psize - 11);
150
151#if 0
152 if (type == RD_TYPE_AS)
153 zlog_info ("prefix %ld:%ld:%ld:%s/%d", label, rd_as.as, rd_as.val,
154 inet_ntoa (p.u.prefix4), p.prefixlen);
155 else if (type == RD_TYPE_IP)
156 zlog_info ("prefix %ld:%s:%ld:%s/%d", label, inet_ntoa (rd_ip.ip),
157 rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen);
158#endif /* 0 */
159
160 if (pnt + psize > lim)
161 return -1;
162
163 if (attr)
164 bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
165 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
166 else
167 bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
168 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
169 }
170
171 /* Packet length consistency check. */
172 if (pnt != lim)
173 return -1;
174
175 return 0;
176}
177
178int
paulfd79ac92004-10-13 05:06:08 +0000179str2prefix_rd (const char *str, struct prefix_rd *prd)
paul718e3742002-12-13 20:15:29 +0000180{
181 int ret;
paul5228ad22004-06-04 17:58:18 +0000182 char *p;
183 char *p2;
paul718e3742002-12-13 20:15:29 +0000184 struct stream *s;
paul5228ad22004-06-04 17:58:18 +0000185 char *half;
paul718e3742002-12-13 20:15:29 +0000186 struct in_addr addr;
187
188 s = stream_new (8);
189
190 prd->family = AF_UNSPEC;
191 prd->prefixlen = 64;
192
193 p = strchr (str, ':');
194 if (! p)
195 return 0;
196
197 if (! all_digit (p + 1))
198 return 0;
199
200 half = XMALLOC (MTYPE_TMP, (p - str) + 1);
201 memcpy (half, str, (p - str));
202 half[p - str] = '\0';
203
204 p2 = strchr (str, '.');
205
206 if (! p2)
207 {
208 if (! all_digit (half))
209 {
210 XFREE (MTYPE_TMP, half);
211 return 0;
212 }
213 stream_putw (s, RD_TYPE_AS);
214 stream_putw (s, atoi (half));
215 stream_putl (s, atol (p + 1));
216 }
217 else
218 {
219 ret = inet_aton (half, &addr);
220 if (! ret)
221 {
222 XFREE (MTYPE_TMP, half);
223 return 0;
224 }
225 stream_putw (s, RD_TYPE_IP);
226 stream_put_in_addr (s, &addr);
227 stream_putw (s, atol (p + 1));
228 }
229 memcpy (prd->val, s->data, 8);
230
231 return 1;
232}
233
234int
paulfd79ac92004-10-13 05:06:08 +0000235str2tag (const char *str, u_char *tag)
paul718e3742002-12-13 20:15:29 +0000236{
paulfd79ac92004-10-13 05:06:08 +0000237 unsigned long l;
238 char *endptr;
239 u_int32_t t;
paul718e3742002-12-13 20:15:29 +0000240
paulfd79ac92004-10-13 05:06:08 +0000241 l = strtoul (str, &endptr, 10);
242
243 if (*endptr == '\0' || l == ULONG_MAX || l > UINT32_MAX)
244 return 0;
paul718e3742002-12-13 20:15:29 +0000245
paulfd79ac92004-10-13 05:06:08 +0000246 t = (u_int32_t) l;
247
248 tag[0] = (u_char)(t >> 12);
249 tag[1] = (u_char)(t >> 4);
250 tag[2] = (u_char)(t << 4);
paul718e3742002-12-13 20:15:29 +0000251
252 return 1;
253}
254
255char *
256prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
257{
258 u_char *pnt;
259 u_int16_t type;
260 struct rd_as rd_as;
261 struct rd_ip rd_ip;
262
263 if (size < RD_ADDRSTRLEN)
264 return NULL;
265
266 pnt = prd->val;
267
268 type = decode_rd_type (pnt);
269
270 if (type == RD_TYPE_AS)
271 {
272 decode_rd_as (pnt + 2, &rd_as);
273 snprintf (buf, size, "%d:%d", rd_as.as, rd_as.val);
274 return buf;
275 }
276 else if (type == RD_TYPE_IP)
277 {
278 decode_rd_ip (pnt + 2, &rd_ip);
279 snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
280 return buf;
281 }
282
283 return NULL;
284}
285
286/* For testing purpose, static route of MPLS-VPN. */
287DEFUN (vpnv4_network,
288 vpnv4_network_cmd,
289 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
290 "Specify a network to announce via BGP\n"
291 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
292 "Specify Route Distinguisher\n"
293 "VPN Route Distinguisher\n"
294 "BGP tag\n"
295 "tag value\n")
296{
297 return bgp_static_set_vpnv4 (vty, argv[0], argv[1], argv[2]);
298}
299
300/* For testing purpose, static route of MPLS-VPN. */
301DEFUN (no_vpnv4_network,
302 no_vpnv4_network_cmd,
303 "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
304 NO_STR
305 "Specify a network to announce via BGP\n"
306 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
307 "Specify Route Distinguisher\n"
308 "VPN Route Distinguisher\n"
309 "BGP tag\n"
310 "tag value\n")
311{
312 return bgp_static_unset_vpnv4 (vty, argv[0], argv[1], argv[2]);
313}
314
315int
316show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd)
317{
318 struct bgp *bgp;
319 struct bgp_table *table;
320 struct bgp_node *rn;
321 struct bgp_node *rm;
322 struct attr *attr;
323 int rd_header;
324 int header = 1;
325 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
326
327 bgp = bgp_get_default ();
328 if (bgp == NULL)
329 {
330 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
331 return CMD_WARNING;
332 }
333
334 for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn;
335 rn = bgp_route_next (rn))
336 {
337 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
338 continue;
339
340 if ((table = rn->info) != NULL)
341 {
342 rd_header = 1;
343
344 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
345 if ((attr = rm->info) != NULL)
346 {
347 if (header)
348 {
349 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
350 inet_ntoa (bgp->router_id), VTY_NEWLINE);
351 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
352 VTY_NEWLINE);
353 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
354 VTY_NEWLINE, VTY_NEWLINE);
355 vty_out (vty, v4_header, VTY_NEWLINE);
356 header = 0;
357 }
358
359 if (rd_header)
360 {
361 u_int16_t type;
362 struct rd_as rd_as;
363 struct rd_ip rd_ip;
364 u_char *pnt;
365
366 pnt = rn->p.u.val;
367
368 /* Decode RD type. */
369 type = decode_rd_type (pnt);
370 /* Decode RD value. */
371 if (type == RD_TYPE_AS)
372 decode_rd_as (pnt + 2, &rd_as);
373 else if (type == RD_TYPE_IP)
374 decode_rd_ip (pnt + 2, &rd_ip);
375
376 vty_out (vty, "Route Distinguisher: ");
377
378 if (type == RD_TYPE_AS)
379 vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
380 else if (type == RD_TYPE_IP)
381 vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
382
383 vty_out (vty, "%s", VTY_NEWLINE);
384 rd_header = 0;
385 }
386 route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN);
387 }
388 }
389 }
390 return CMD_SUCCESS;
391}
392
393enum bgp_show_type
394{
395 bgp_show_type_normal,
396 bgp_show_type_regexp,
397 bgp_show_type_prefix_list,
398 bgp_show_type_filter_list,
399 bgp_show_type_neighbor,
400 bgp_show_type_cidr_only,
401 bgp_show_type_prefix_longer,
402 bgp_show_type_community_all,
403 bgp_show_type_community,
404 bgp_show_type_community_exact,
405 bgp_show_type_community_list,
406 bgp_show_type_community_list_exact
407};
408
409int
410bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
411 void *output_arg, int tags)
412{
413 struct bgp *bgp;
414 struct bgp_table *table;
415 struct bgp_node *rn;
416 struct bgp_node *rm;
417 struct bgp_info *ri;
418 int rd_header;
419 int header = 1;
420 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
421 char v4_header_tag[] = " Network Next Hop In tag/Out tag%s";
422
423 bgp = bgp_get_default ();
424 if (bgp == NULL)
425 {
426 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
427 return CMD_WARNING;
428 }
429
430 for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
431 {
432 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
433 continue;
434
435 if ((table = rn->info) != NULL)
436 {
437 rd_header = 1;
438
439 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
440 for (ri = rm->info; ri; ri = ri->next)
441 {
442 if (type == bgp_show_type_neighbor)
443 {
444 union sockunion *su = output_arg;
445
446 if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
447 continue;
448 }
449 if (header)
450 {
451 if (tags)
452 vty_out (vty, v4_header_tag, VTY_NEWLINE);
453 else
454 {
455 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
456 inet_ntoa (bgp->router_id), VTY_NEWLINE);
457 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
458 VTY_NEWLINE);
459 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
460 VTY_NEWLINE, VTY_NEWLINE);
461 vty_out (vty, v4_header, VTY_NEWLINE);
462 }
463 header = 0;
464 }
465
466 if (rd_header)
467 {
468 u_int16_t type;
469 struct rd_as rd_as;
470 struct rd_ip rd_ip;
471 u_char *pnt;
472
473 pnt = rn->p.u.val;
474
475 /* Decode RD type. */
476 type = decode_rd_type (pnt);
477 /* Decode RD value. */
478 if (type == RD_TYPE_AS)
479 decode_rd_as (pnt + 2, &rd_as);
480 else if (type == RD_TYPE_IP)
481 decode_rd_ip (pnt + 2, &rd_ip);
482
483 vty_out (vty, "Route Distinguisher: ");
484
485 if (type == RD_TYPE_AS)
486 vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
487 else if (type == RD_TYPE_IP)
488 vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
489
490 vty_out (vty, "%s", VTY_NEWLINE);
491 rd_header = 0;
492 }
493 if (tags)
494 route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
495 else
496 route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
497 }
498 }
499 }
500 return CMD_SUCCESS;
501}
502
503DEFUN (show_ip_bgp_vpnv4_all,
504 show_ip_bgp_vpnv4_all_cmd,
505 "show ip bgp vpnv4 all",
506 SHOW_STR
507 IP_STR
508 BGP_STR
509 "Display VPNv4 NLRI specific information\n"
510 "Display information about all VPNv4 NLRIs\n")
511{
512 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL, 0);
513}
514
515DEFUN (show_ip_bgp_vpnv4_rd,
516 show_ip_bgp_vpnv4_rd_cmd,
517 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn",
518 SHOW_STR
519 IP_STR
520 BGP_STR
521 "Display VPNv4 NLRI specific information\n"
522 "Display information for a route distinguisher\n"
523 "VPN Route Distinguisher\n")
524{
525 int ret;
526 struct prefix_rd prd;
527
528 ret = str2prefix_rd (argv[0], &prd);
529 if (! ret)
530 {
531 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
532 return CMD_WARNING;
533 }
534 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 0);
535}
536
537DEFUN (show_ip_bgp_vpnv4_all_tags,
538 show_ip_bgp_vpnv4_all_tags_cmd,
539 "show ip bgp vpnv4 all tags",
540 SHOW_STR
541 IP_STR
542 BGP_STR
543 "Display VPNv4 NLRI specific information\n"
544 "Display information about all VPNv4 NLRIs\n"
545 "Display BGP tags for prefixes\n")
546{
547 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL, 1);
548}
549
550DEFUN (show_ip_bgp_vpnv4_rd_tags,
551 show_ip_bgp_vpnv4_rd_tags_cmd,
552 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn tags",
553 SHOW_STR
554 IP_STR
555 BGP_STR
556 "Display VPNv4 NLRI specific information\n"
557 "Display information for a route distinguisher\n"
558 "VPN Route Distinguisher\n"
559 "Display BGP tags for prefixes\n")
560{
561 int ret;
562 struct prefix_rd prd;
563
564 ret = str2prefix_rd (argv[0], &prd);
565 if (! ret)
566 {
567 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
568 return CMD_WARNING;
569 }
570 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 1);
571}
572
573DEFUN (show_ip_bgp_vpnv4_all_neighbor_routes,
574 show_ip_bgp_vpnv4_all_neighbor_routes_cmd,
575 "show ip bgp vpnv4 all neighbors A.B.C.D routes",
576 SHOW_STR
577 IP_STR
578 BGP_STR
579 "Display VPNv4 NLRI specific information\n"
580 "Display information about all VPNv4 NLRIs\n"
581 "Detailed information on TCP and BGP neighbor connections\n"
582 "Neighbor to display information about\n"
583 "Display routes learned from neighbor\n")
584{
585 union sockunion *su;
586 struct peer *peer;
587
588 su = sockunion_str2su (argv[0]);
589 if (su == NULL)
590 {
591 vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
592 return CMD_WARNING;
593 }
594
595 peer = peer_lookup (NULL, su);
596 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
597 {
598 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
599 return CMD_WARNING;
600 }
601
602 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_neighbor, su, 0);
603}
604
605DEFUN (show_ip_bgp_vpnv4_rd_neighbor_routes,
606 show_ip_bgp_vpnv4_rd_neighbor_routes_cmd,
607 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes",
608 SHOW_STR
609 IP_STR
610 BGP_STR
611 "Display VPNv4 NLRI specific information\n"
612 "Display information for a route distinguisher\n"
613 "VPN Route Distinguisher\n"
614 "Detailed information on TCP and BGP neighbor connections\n"
615 "Neighbor to display information about\n"
616 "Display routes learned from neighbor\n")
617{
618 int ret;
619 union sockunion *su;
620 struct peer *peer;
621 struct prefix_rd prd;
622
623 ret = str2prefix_rd (argv[0], &prd);
624 if (! ret)
625 {
626 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
627 return CMD_WARNING;
628 }
629
630 su = sockunion_str2su (argv[1]);
631 if (su == NULL)
632 {
633 vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
634 return CMD_WARNING;
635 }
636
637 peer = peer_lookup (NULL, su);
638 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
639 {
640 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
641 return CMD_WARNING;
642 }
643
644 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_neighbor, su, 0);
645}
646
647DEFUN (show_ip_bgp_vpnv4_all_neighbor_advertised_routes,
648 show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd,
649 "show ip bgp vpnv4 all neighbors A.B.C.D advertised-routes",
650 SHOW_STR
651 IP_STR
652 BGP_STR
653 "Display VPNv4 NLRI specific information\n"
654 "Display information about all VPNv4 NLRIs\n"
655 "Detailed information on TCP and BGP neighbor connections\n"
656 "Neighbor to display information about\n"
657 "Display the routes advertised to a BGP neighbor\n")
658{
659 int ret;
660 struct peer *peer;
661 union sockunion su;
662
663 ret = str2sockunion (argv[0], &su);
664 if (ret < 0)
665 {
666 vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
667 return CMD_WARNING;
668 }
669 peer = peer_lookup (NULL, &su);
670 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
671 {
672 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
673 return CMD_WARNING;
674 }
675
676 return show_adj_route_vpn (vty, peer, NULL);
677}
678
679DEFUN (show_ip_bgp_vpnv4_rd_neighbor_advertised_routes,
680 show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd,
681 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes",
682 SHOW_STR
683 IP_STR
684 BGP_STR
685 "Display VPNv4 NLRI specific information\n"
686 "Display information for a route distinguisher\n"
687 "VPN Route Distinguisher\n"
688 "Detailed information on TCP and BGP neighbor connections\n"
689 "Neighbor to display information about\n"
690 "Display the routes advertised to a BGP neighbor\n")
691{
692 int ret;
693 struct peer *peer;
694 struct prefix_rd prd;
695 union sockunion su;
696
697 ret = str2sockunion (argv[1], &su);
698 if (ret < 0)
699 {
700 vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
701 return CMD_WARNING;
702 }
703 peer = peer_lookup (NULL, &su);
704 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
705 {
706 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
707 return CMD_WARNING;
708 }
709
710 ret = str2prefix_rd (argv[0], &prd);
711 if (! ret)
712 {
713 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
714 return CMD_WARNING;
715 }
716
717 return show_adj_route_vpn (vty, peer, &prd);
718}
719
720void
721bgp_mplsvpn_init ()
722{
723 install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
724 install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
725
726
727 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_cmd);
728 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_cmd);
729 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
730 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
731 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
732 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
733 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
734 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
735
736 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_cmd);
737 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_cmd);
738 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
739 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
740 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
741 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
742 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
743 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
744}