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