2 Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 This file is part of GNU Zebra.
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
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.
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
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"
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
);
40 decode_rd_type (u_char
*pnt
)
44 v
= ((u_int16_t
) *pnt
++ << 8);
45 v
|= (u_int16_t
) *pnt
;
50 decode_label (u_char
*pnt
)
54 l
= ((u_int32_t
) *pnt
++ << 12);
55 l
|= (u_int32_t
) *pnt
++ << 4;
56 l
|= (u_int32_t
) ((*pnt
& 0xf0) >> 4);
61 decode_rd_as (u_char
*pnt
, struct rd_as
*rd_as
)
63 rd_as
->as
= (u_int16_t
) *pnt
++ << 8;
64 rd_as
->as
|= (u_int16_t
) *pnt
++;
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
;
73 decode_rd_ip (u_char
*pnt
, struct rd_ip
*rd_ip
)
75 memcpy (&rd_ip
->ip
, pnt
, 4);
78 rd_ip
->val
= ((u_int16_t
) *pnt
++ << 8);
79 rd_ip
->val
|= (u_int16_t
) *pnt
;
82 int bgp_update (struct peer
*, struct prefix
*, struct attr
*,
83 afi_t
, safi_t
, int, int, struct prefix_rd
*, u_char
*);
85 int bgp_withdraw (struct peer
*, struct prefix
*, struct attr
*,
86 int, int, int, int, struct prefix_rd
*, u_char
*);
88 bgp_nlri_parse_vpnv4 (struct peer
*peer
, struct attr
*attr
,
89 struct bgp_nlri
*packet
)
100 struct prefix_rd prd
;
103 /* Check peer status. */
104 if (peer
->status
!= Established
)
108 prd
.family
= AF_UNSPEC
;
112 lim
= pnt
+ packet
->length
;
114 for (; pnt
< lim
; pnt
+= psize
)
116 /* Clear prefix structure. */
117 memset (&p
, 0, sizeof (struct prefix
));
119 /* Fetch prefix length. */
122 psize
= PSIZE (prefixlen
);
126 zlog_err ("prefix length is less than 88: %d", prefixlen
);
130 label
= decode_label (pnt
);
132 /* Copyr label to prefix. */
135 /* Copy routing distinguisher to rd. */
136 memcpy (&prd
.val
, pnt
+ 3, 8);
138 /* Decode RD type. */
139 type
= decode_rd_type (pnt
+ 3);
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
);
148 zlog_err ("Invalid RD type %d", type
);
152 p
.prefixlen
= prefixlen
- 88;
153 memcpy (&p
.u
.prefix
, pnt
+ 11, psize
- 11);
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
);
164 if (pnt
+ psize
> lim
)
168 bgp_update (peer
, &p
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
169 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
);
171 bgp_withdraw (peer
, &p
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
172 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
);
175 /* Packet length consistency check. */
183 str2prefix_rd (u_char
*str
, struct prefix_rd
*prd
)
194 prd
->family
= AF_UNSPEC
;
197 p
= strchr (str
, ':');
201 if (! all_digit (p
+ 1))
204 half
= XMALLOC (MTYPE_TMP
, (p
- str
) + 1);
205 memcpy (half
, str
, (p
- str
));
206 half
[p
- str
] = '\0';
208 p2
= strchr (str
, '.');
212 if (! all_digit (half
))
214 XFREE (MTYPE_TMP
, half
);
217 stream_putw (s
, RD_TYPE_AS
);
218 stream_putw (s
, atoi (half
));
219 stream_putl (s
, atol (p
+ 1));
223 ret
= inet_aton (half
, &addr
);
226 XFREE (MTYPE_TMP
, half
);
229 stream_putw (s
, RD_TYPE_IP
);
230 stream_put_in_addr (s
, &addr
);
231 stream_putw (s
, atol (p
+ 1));
233 memcpy (prd
->val
, s
->data
, 8);
239 str2tag (u_char
*str
, u_char
*tag
)
245 tag
[0] = (u_char
)(l
>> 12);
246 tag
[1] = (u_char
)(l
>> 4);
247 tag
[2] = (u_char
)(l
<< 4);
253 prefix_rd2str (struct prefix_rd
*prd
, char *buf
, size_t size
)
260 if (size
< RD_ADDRSTRLEN
)
265 type
= decode_rd_type (pnt
);
267 if (type
== RD_TYPE_AS
)
269 decode_rd_as (pnt
+ 2, &rd_as
);
270 snprintf (buf
, size
, "%d:%d", rd_as
.as
, rd_as
.val
);
273 else if (type
== RD_TYPE_IP
)
275 decode_rd_ip (pnt
+ 2, &rd_ip
);
276 snprintf (buf
, size
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
283 /* For testing purpose, static route of MPLS-VPN. */
284 DEFUN (vpnv4_network
,
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"
294 return bgp_static_set_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
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",
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"
309 return bgp_static_unset_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
313 show_adj_route_vpn (struct vty
*vty
, struct peer
*peer
, struct prefix_rd
*prd
)
316 struct bgp_table
*table
;
322 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
324 bgp
= bgp_get_default ();
327 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
331 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
;
332 rn
= bgp_route_next (rn
))
334 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
337 if ((table
= rn
->info
) != NULL
)
341 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
342 if ((attr
= rm
->info
) != NULL
)
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",
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
);
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
);
373 vty_out (vty
, "Route Distinguisher: ");
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
);
380 vty_out (vty
, "%s", VTY_NEWLINE
);
383 route_vty_out_tmp (vty
, &rm
->p
, attr
, SAFI_MPLS_VPN
);
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
407 bgp_show_mpls_vpn (struct vty
*vty
, struct prefix_rd
*prd
, enum bgp_show_type type
,
408 void *output_arg
, int tags
)
411 struct bgp_table
*table
;
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";
420 bgp
= bgp_get_default ();
423 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
427 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
; rn
= bgp_route_next (rn
))
429 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
432 if ((table
= rn
->info
) != NULL
)
436 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
437 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
439 if (type
== bgp_show_type_neighbor
)
441 union sockunion
*su
= output_arg
;
443 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
449 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
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",
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
);
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
);
480 vty_out (vty
, "Route Distinguisher: ");
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
);
487 vty_out (vty
, "%s", VTY_NEWLINE
);
491 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
493 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
500 DEFUN (show_ip_bgp_vpnv4_all
,
501 show_ip_bgp_vpnv4_all_cmd
,
502 "show ip bgp vpnv4 all",
506 "Display VPNv4 NLRI specific information\n"
507 "Display information about all VPNv4 NLRIs\n")
509 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 0);
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",
518 "Display VPNv4 NLRI specific information\n"
519 "Display information for a route distinguisher\n"
520 "VPN Route Distinguisher\n")
523 struct prefix_rd prd
;
525 ret
= str2prefix_rd (argv
[0], &prd
);
528 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
531 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 0);
534 DEFUN (show_ip_bgp_vpnv4_all_tags
,
535 show_ip_bgp_vpnv4_all_tags_cmd
,
536 "show ip bgp vpnv4 all tags",
540 "Display VPNv4 NLRI specific information\n"
541 "Display information about all VPNv4 NLRIs\n"
542 "Display BGP tags for prefixes\n")
544 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 1);
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",
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")
559 struct prefix_rd prd
;
561 ret
= str2prefix_rd (argv
[0], &prd
);
564 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
567 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 1);
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",
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")
585 su
= sockunion_str2su (argv
[0]);
588 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
592 peer
= peer_lookup (NULL
, su
);
593 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
595 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
599 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_neighbor
, su
, 0);
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",
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")
618 struct prefix_rd prd
;
620 ret
= str2prefix_rd (argv
[0], &prd
);
623 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
627 su
= sockunion_str2su (argv
[1]);
630 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
634 peer
= peer_lookup (NULL
, su
);
635 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
637 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
641 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_neighbor
, su
, 0);
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",
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")
660 ret
= str2sockunion (argv
[0], &su
);
663 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
666 peer
= peer_lookup (NULL
, &su
);
667 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
669 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
673 return show_adj_route_vpn (vty
, peer
, NULL
);
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",
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")
691 struct prefix_rd prd
;
694 ret
= str2sockunion (argv
[1], &su
);
697 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
700 peer
= peer_lookup (NULL
, &su
);
701 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
703 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
707 ret
= str2prefix_rd (argv
[0], &prd
);
710 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
714 return show_adj_route_vpn (vty
, peer
, &prd
);
720 install_element (BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
721 install_element (BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
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
);
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
);