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 (const 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 (const char *str
, u_char
*tag
)
245 l
= strtoul (str
, &endptr
, 10);
247 if (*endptr
== '\0' || l
== ULONG_MAX
|| l
> UINT32_MAX
)
252 tag
[0] = (u_char
)(t
>> 12);
253 tag
[1] = (u_char
)(t
>> 4);
254 tag
[2] = (u_char
)(t
<< 4);
260 prefix_rd2str (struct prefix_rd
*prd
, char *buf
, size_t size
)
267 if (size
< RD_ADDRSTRLEN
)
272 type
= decode_rd_type (pnt
);
274 if (type
== RD_TYPE_AS
)
276 decode_rd_as (pnt
+ 2, &rd_as
);
277 snprintf (buf
, size
, "%d:%d", rd_as
.as
, rd_as
.val
);
280 else if (type
== RD_TYPE_IP
)
282 decode_rd_ip (pnt
+ 2, &rd_ip
);
283 snprintf (buf
, size
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
290 /* For testing purpose, static route of MPLS-VPN. */
291 DEFUN (vpnv4_network
,
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"
301 return bgp_static_set_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
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",
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"
316 return bgp_static_unset_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
320 show_adj_route_vpn (struct vty
*vty
, struct peer
*peer
, struct prefix_rd
*prd
)
323 struct bgp_table
*table
;
329 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
331 bgp
= bgp_get_default ();
334 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
338 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
;
339 rn
= bgp_route_next (rn
))
341 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
344 if ((table
= rn
->info
) != NULL
)
348 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
349 if ((attr
= rm
->info
) != NULL
)
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",
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
);
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
);
380 vty_out (vty
, "Route Distinguisher: ");
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
);
387 vty_out (vty
, "%s", VTY_NEWLINE
);
390 route_vty_out_tmp (vty
, &rm
->p
, attr
, SAFI_MPLS_VPN
);
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
414 bgp_show_mpls_vpn (struct vty
*vty
, struct prefix_rd
*prd
, enum bgp_show_type type
,
415 void *output_arg
, int tags
)
418 struct bgp_table
*table
;
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";
427 bgp
= bgp_get_default ();
430 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
434 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
; rn
= bgp_route_next (rn
))
436 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
439 if ((table
= rn
->info
) != NULL
)
443 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
444 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
446 if (type
== bgp_show_type_neighbor
)
448 union sockunion
*su
= output_arg
;
450 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
456 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
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",
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
);
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
);
487 vty_out (vty
, "Route Distinguisher: ");
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
);
494 vty_out (vty
, "%s", VTY_NEWLINE
);
498 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
500 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
507 DEFUN (show_ip_bgp_vpnv4_all
,
508 show_ip_bgp_vpnv4_all_cmd
,
509 "show ip bgp vpnv4 all",
513 "Display VPNv4 NLRI specific information\n"
514 "Display information about all VPNv4 NLRIs\n")
516 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 0);
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",
525 "Display VPNv4 NLRI specific information\n"
526 "Display information for a route distinguisher\n"
527 "VPN Route Distinguisher\n")
530 struct prefix_rd prd
;
532 ret
= str2prefix_rd (argv
[0], &prd
);
535 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
538 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 0);
541 DEFUN (show_ip_bgp_vpnv4_all_tags
,
542 show_ip_bgp_vpnv4_all_tags_cmd
,
543 "show ip bgp vpnv4 all tags",
547 "Display VPNv4 NLRI specific information\n"
548 "Display information about all VPNv4 NLRIs\n"
549 "Display BGP tags for prefixes\n")
551 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 1);
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",
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")
566 struct prefix_rd prd
;
568 ret
= str2prefix_rd (argv
[0], &prd
);
571 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
574 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 1);
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",
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")
592 su
= sockunion_str2su (argv
[0]);
595 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
599 peer
= peer_lookup (NULL
, su
);
600 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
602 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
606 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_neighbor
, su
, 0);
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",
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")
625 struct prefix_rd prd
;
627 ret
= str2prefix_rd (argv
[0], &prd
);
630 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
634 su
= sockunion_str2su (argv
[1]);
637 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
641 peer
= peer_lookup (NULL
, su
);
642 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
644 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
648 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_neighbor
, su
, 0);
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",
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")
667 ret
= str2sockunion (argv
[0], &su
);
670 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
673 peer
= peer_lookup (NULL
, &su
);
674 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
676 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
680 return show_adj_route_vpn (vty
, peer
, NULL
);
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",
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")
698 struct prefix_rd prd
;
701 ret
= str2sockunion (argv
[1], &su
);
704 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
707 peer
= peer_lookup (NULL
, &su
);
708 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
710 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
714 ret
= str2prefix_rd (argv
[0], &prd
);
717 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
721 return show_adj_route_vpn (vty
, peer
, &prd
);
727 install_element (BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
728 install_element (BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
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
);
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
);