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