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