]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_mplsvpn.c
2004-06-04 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 (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 (char *str, u_char *tag)
240 {
241 u_int32_t l;
242
243 l = atol (str);
244
245 tag[0] = (u_char)(l >> 12);
246 tag[1] = (u_char)(l >> 4);
247 tag[2] = (u_char)(l << 4);
248
249 return 1;
250 }
251
252 char *
253 prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
254 {
255 u_char *pnt;
256 u_int16_t type;
257 struct rd_as rd_as;
258 struct rd_ip rd_ip;
259
260 if (size < RD_ADDRSTRLEN)
261 return NULL;
262
263 pnt = prd->val;
264
265 type = decode_rd_type (pnt);
266
267 if (type == RD_TYPE_AS)
268 {
269 decode_rd_as (pnt + 2, &rd_as);
270 snprintf (buf, size, "%d:%d", rd_as.as, rd_as.val);
271 return buf;
272 }
273 else if (type == RD_TYPE_IP)
274 {
275 decode_rd_ip (pnt + 2, &rd_ip);
276 snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
277 return buf;
278 }
279
280 return NULL;
281 }
282
283 /* For testing purpose, static route of MPLS-VPN. */
284 DEFUN (vpnv4_network,
285 vpnv4_network_cmd,
286 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
287 "Specify a network to announce via BGP\n"
288 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
289 "Specify Route Distinguisher\n"
290 "VPN Route Distinguisher\n"
291 "BGP tag\n"
292 "tag value\n")
293 {
294 return bgp_static_set_vpnv4 (vty, argv[0], argv[1], argv[2]);
295 }
296
297 /* For testing purpose, static route of MPLS-VPN. */
298 DEFUN (no_vpnv4_network,
299 no_vpnv4_network_cmd,
300 "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
301 NO_STR
302 "Specify a network to announce via BGP\n"
303 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
304 "Specify Route Distinguisher\n"
305 "VPN Route Distinguisher\n"
306 "BGP tag\n"
307 "tag value\n")
308 {
309 return bgp_static_unset_vpnv4 (vty, argv[0], argv[1], argv[2]);
310 }
311
312 int
313 show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd)
314 {
315 struct bgp *bgp;
316 struct bgp_table *table;
317 struct bgp_node *rn;
318 struct bgp_node *rm;
319 struct attr *attr;
320 int rd_header;
321 int header = 1;
322 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
323
324 bgp = bgp_get_default ();
325 if (bgp == NULL)
326 {
327 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
328 return CMD_WARNING;
329 }
330
331 for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn;
332 rn = bgp_route_next (rn))
333 {
334 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
335 continue;
336
337 if ((table = rn->info) != NULL)
338 {
339 rd_header = 1;
340
341 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
342 if ((attr = rm->info) != NULL)
343 {
344 if (header)
345 {
346 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
347 inet_ntoa (bgp->router_id), VTY_NEWLINE);
348 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
349 VTY_NEWLINE);
350 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
351 VTY_NEWLINE, VTY_NEWLINE);
352 vty_out (vty, v4_header, VTY_NEWLINE);
353 header = 0;
354 }
355
356 if (rd_header)
357 {
358 u_int16_t type;
359 struct rd_as rd_as;
360 struct rd_ip rd_ip;
361 u_char *pnt;
362
363 pnt = rn->p.u.val;
364
365 /* Decode RD type. */
366 type = decode_rd_type (pnt);
367 /* Decode RD value. */
368 if (type == RD_TYPE_AS)
369 decode_rd_as (pnt + 2, &rd_as);
370 else if (type == RD_TYPE_IP)
371 decode_rd_ip (pnt + 2, &rd_ip);
372
373 vty_out (vty, "Route Distinguisher: ");
374
375 if (type == RD_TYPE_AS)
376 vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
377 else if (type == RD_TYPE_IP)
378 vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
379
380 vty_out (vty, "%s", VTY_NEWLINE);
381 rd_header = 0;
382 }
383 route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN);
384 }
385 }
386 }
387 return CMD_SUCCESS;
388 }
389
390 enum bgp_show_type
391 {
392 bgp_show_type_normal,
393 bgp_show_type_regexp,
394 bgp_show_type_prefix_list,
395 bgp_show_type_filter_list,
396 bgp_show_type_neighbor,
397 bgp_show_type_cidr_only,
398 bgp_show_type_prefix_longer,
399 bgp_show_type_community_all,
400 bgp_show_type_community,
401 bgp_show_type_community_exact,
402 bgp_show_type_community_list,
403 bgp_show_type_community_list_exact
404 };
405
406 int
407 bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
408 void *output_arg, int tags)
409 {
410 struct bgp *bgp;
411 struct bgp_table *table;
412 struct bgp_node *rn;
413 struct bgp_node *rm;
414 struct bgp_info *ri;
415 int rd_header;
416 int header = 1;
417 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
418 char v4_header_tag[] = " Network Next Hop In tag/Out tag%s";
419
420 bgp = bgp_get_default ();
421 if (bgp == NULL)
422 {
423 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
424 return CMD_WARNING;
425 }
426
427 for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
428 {
429 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
430 continue;
431
432 if ((table = rn->info) != NULL)
433 {
434 rd_header = 1;
435
436 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
437 for (ri = rm->info; ri; ri = ri->next)
438 {
439 if (type == bgp_show_type_neighbor)
440 {
441 union sockunion *su = output_arg;
442
443 if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
444 continue;
445 }
446 if (header)
447 {
448 if (tags)
449 vty_out (vty, v4_header_tag, VTY_NEWLINE);
450 else
451 {
452 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
453 inet_ntoa (bgp->router_id), VTY_NEWLINE);
454 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
455 VTY_NEWLINE);
456 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
457 VTY_NEWLINE, VTY_NEWLINE);
458 vty_out (vty, v4_header, VTY_NEWLINE);
459 }
460 header = 0;
461 }
462
463 if (rd_header)
464 {
465 u_int16_t type;
466 struct rd_as rd_as;
467 struct rd_ip rd_ip;
468 u_char *pnt;
469
470 pnt = rn->p.u.val;
471
472 /* Decode RD type. */
473 type = decode_rd_type (pnt);
474 /* Decode RD value. */
475 if (type == RD_TYPE_AS)
476 decode_rd_as (pnt + 2, &rd_as);
477 else if (type == RD_TYPE_IP)
478 decode_rd_ip (pnt + 2, &rd_ip);
479
480 vty_out (vty, "Route Distinguisher: ");
481
482 if (type == RD_TYPE_AS)
483 vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
484 else if (type == RD_TYPE_IP)
485 vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
486
487 vty_out (vty, "%s", VTY_NEWLINE);
488 rd_header = 0;
489 }
490 if (tags)
491 route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
492 else
493 route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
494 }
495 }
496 }
497 return CMD_SUCCESS;
498 }
499
500 DEFUN (show_ip_bgp_vpnv4_all,
501 show_ip_bgp_vpnv4_all_cmd,
502 "show ip bgp vpnv4 all",
503 SHOW_STR
504 IP_STR
505 BGP_STR
506 "Display VPNv4 NLRI specific information\n"
507 "Display information about all VPNv4 NLRIs\n")
508 {
509 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL, 0);
510 }
511
512 DEFUN (show_ip_bgp_vpnv4_rd,
513 show_ip_bgp_vpnv4_rd_cmd,
514 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn",
515 SHOW_STR
516 IP_STR
517 BGP_STR
518 "Display VPNv4 NLRI specific information\n"
519 "Display information for a route distinguisher\n"
520 "VPN Route Distinguisher\n")
521 {
522 int ret;
523 struct prefix_rd prd;
524
525 ret = str2prefix_rd (argv[0], &prd);
526 if (! ret)
527 {
528 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
529 return CMD_WARNING;
530 }
531 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 0);
532 }
533
534 DEFUN (show_ip_bgp_vpnv4_all_tags,
535 show_ip_bgp_vpnv4_all_tags_cmd,
536 "show ip bgp vpnv4 all tags",
537 SHOW_STR
538 IP_STR
539 BGP_STR
540 "Display VPNv4 NLRI specific information\n"
541 "Display information about all VPNv4 NLRIs\n"
542 "Display BGP tags for prefixes\n")
543 {
544 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL, 1);
545 }
546
547 DEFUN (show_ip_bgp_vpnv4_rd_tags,
548 show_ip_bgp_vpnv4_rd_tags_cmd,
549 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn tags",
550 SHOW_STR
551 IP_STR
552 BGP_STR
553 "Display VPNv4 NLRI specific information\n"
554 "Display information for a route distinguisher\n"
555 "VPN Route Distinguisher\n"
556 "Display BGP tags for prefixes\n")
557 {
558 int ret;
559 struct prefix_rd prd;
560
561 ret = str2prefix_rd (argv[0], &prd);
562 if (! ret)
563 {
564 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
565 return CMD_WARNING;
566 }
567 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 1);
568 }
569
570 DEFUN (show_ip_bgp_vpnv4_all_neighbor_routes,
571 show_ip_bgp_vpnv4_all_neighbor_routes_cmd,
572 "show ip bgp vpnv4 all neighbors A.B.C.D routes",
573 SHOW_STR
574 IP_STR
575 BGP_STR
576 "Display VPNv4 NLRI specific information\n"
577 "Display information about all VPNv4 NLRIs\n"
578 "Detailed information on TCP and BGP neighbor connections\n"
579 "Neighbor to display information about\n"
580 "Display routes learned from neighbor\n")
581 {
582 union sockunion *su;
583 struct peer *peer;
584
585 su = sockunion_str2su (argv[0]);
586 if (su == NULL)
587 {
588 vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
589 return CMD_WARNING;
590 }
591
592 peer = peer_lookup (NULL, su);
593 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
594 {
595 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
596 return CMD_WARNING;
597 }
598
599 return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_neighbor, su, 0);
600 }
601
602 DEFUN (show_ip_bgp_vpnv4_rd_neighbor_routes,
603 show_ip_bgp_vpnv4_rd_neighbor_routes_cmd,
604 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes",
605 SHOW_STR
606 IP_STR
607 BGP_STR
608 "Display VPNv4 NLRI specific information\n"
609 "Display information for a route distinguisher\n"
610 "VPN Route Distinguisher\n"
611 "Detailed information on TCP and BGP neighbor connections\n"
612 "Neighbor to display information about\n"
613 "Display routes learned from neighbor\n")
614 {
615 int ret;
616 union sockunion *su;
617 struct peer *peer;
618 struct prefix_rd prd;
619
620 ret = str2prefix_rd (argv[0], &prd);
621 if (! ret)
622 {
623 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
624 return CMD_WARNING;
625 }
626
627 su = sockunion_str2su (argv[1]);
628 if (su == NULL)
629 {
630 vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
631 return CMD_WARNING;
632 }
633
634 peer = peer_lookup (NULL, su);
635 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
636 {
637 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
638 return CMD_WARNING;
639 }
640
641 return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_neighbor, su, 0);
642 }
643
644 DEFUN (show_ip_bgp_vpnv4_all_neighbor_advertised_routes,
645 show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd,
646 "show ip bgp vpnv4 all neighbors A.B.C.D advertised-routes",
647 SHOW_STR
648 IP_STR
649 BGP_STR
650 "Display VPNv4 NLRI specific information\n"
651 "Display information about all VPNv4 NLRIs\n"
652 "Detailed information on TCP and BGP neighbor connections\n"
653 "Neighbor to display information about\n"
654 "Display the routes advertised to a BGP neighbor\n")
655 {
656 int ret;
657 struct peer *peer;
658 union sockunion su;
659
660 ret = str2sockunion (argv[0], &su);
661 if (ret < 0)
662 {
663 vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
664 return CMD_WARNING;
665 }
666 peer = peer_lookup (NULL, &su);
667 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
668 {
669 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
670 return CMD_WARNING;
671 }
672
673 return show_adj_route_vpn (vty, peer, NULL);
674 }
675
676 DEFUN (show_ip_bgp_vpnv4_rd_neighbor_advertised_routes,
677 show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd,
678 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes",
679 SHOW_STR
680 IP_STR
681 BGP_STR
682 "Display VPNv4 NLRI specific information\n"
683 "Display information for a route distinguisher\n"
684 "VPN Route Distinguisher\n"
685 "Detailed information on TCP and BGP neighbor connections\n"
686 "Neighbor to display information about\n"
687 "Display the routes advertised to a BGP neighbor\n")
688 {
689 int ret;
690 struct peer *peer;
691 struct prefix_rd prd;
692 union sockunion su;
693
694 ret = str2sockunion (argv[1], &su);
695 if (ret < 0)
696 {
697 vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
698 return CMD_WARNING;
699 }
700 peer = peer_lookup (NULL, &su);
701 if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
702 {
703 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
704 return CMD_WARNING;
705 }
706
707 ret = str2prefix_rd (argv[0], &prd);
708 if (! ret)
709 {
710 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
711 return CMD_WARNING;
712 }
713
714 return show_adj_route_vpn (vty, peer, &prd);
715 }
716
717 void
718 bgp_mplsvpn_init ()
719 {
720 install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
721 install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
722
723
724 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_cmd);
725 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_cmd);
726 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
727 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
728 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
729 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
730 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
731 install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
732
733 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_cmd);
734 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_cmd);
735 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
736 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
737 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
738 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
739 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
740 install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
741 }