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"
36 decode_rd_type (u_char
*pnt
)
40 v
= ((u_int16_t
) *pnt
++ << 8);
41 v
|= (u_int16_t
) *pnt
;
46 decode_label (u_char
*pnt
)
50 l
= ((u_int32_t
) *pnt
++ << 12);
51 l
|= (u_int32_t
) *pnt
++ << 4;
52 l
|= (u_int32_t
) ((*pnt
& 0xf0) >> 4);
57 decode_rd_as (u_char
*pnt
, struct rd_as
*rd_as
)
59 rd_as
->as
= (u_int16_t
) *pnt
++ << 8;
60 rd_as
->as
|= (u_int16_t
) *pnt
++;
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
;
69 decode_rd_ip (u_char
*pnt
, struct rd_ip
*rd_ip
)
71 memcpy (&rd_ip
->ip
, pnt
, 4);
74 rd_ip
->val
= ((u_int16_t
) *pnt
++ << 8);
75 rd_ip
->val
|= (u_int16_t
) *pnt
;
79 bgp_nlri_parse_vpnv4 (struct peer
*peer
, struct attr
*attr
,
80 struct bgp_nlri
*packet
)
94 /* Check peer status. */
95 if (peer
->status
!= Established
)
99 prd
.family
= AF_UNSPEC
;
103 lim
= pnt
+ packet
->length
;
105 for (; pnt
< lim
; pnt
+= psize
)
107 /* Clear prefix structure. */
108 memset (&p
, 0, sizeof (struct prefix
));
110 /* Fetch prefix length. */
113 psize
= PSIZE (prefixlen
);
117 zlog_err ("prefix length is less than 88: %d", prefixlen
);
121 label
= decode_label (pnt
);
123 /* Copyr label to prefix. */
126 /* Copy routing distinguisher to rd. */
127 memcpy (&prd
.val
, pnt
+ 3, 8);
129 /* Decode RD type. */
130 type
= decode_rd_type (pnt
+ 3);
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
);
139 zlog_err ("Invalid RD type %d", type
);
143 p
.prefixlen
= prefixlen
- 88;
144 memcpy (&p
.u
.prefix
, pnt
+ 11, psize
- 11);
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
);
155 if (pnt
+ psize
> lim
)
159 bgp_update (peer
, &p
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
160 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
, 0);
162 bgp_withdraw (peer
, &p
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
163 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
);
166 /* Packet length consistency check. */
174 str2prefix_rd (const char *str
, struct prefix_rd
*prd
)
185 prd
->family
= AF_UNSPEC
;
188 p
= strchr (str
, ':');
192 if (! all_digit (p
+ 1))
195 half
= XMALLOC (MTYPE_TMP
, (p
- str
) + 1);
196 memcpy (half
, str
, (p
- str
));
197 half
[p
- str
] = '\0';
199 p2
= strchr (str
, '.');
203 if (! all_digit (half
))
205 XFREE (MTYPE_TMP
, half
);
208 stream_putw (s
, RD_TYPE_AS
);
209 stream_putw (s
, atoi (half
));
210 stream_putl (s
, atol (p
+ 1));
214 ret
= inet_aton (half
, &addr
);
217 XFREE (MTYPE_TMP
, half
);
220 stream_putw (s
, RD_TYPE_IP
);
221 stream_put_in_addr (s
, &addr
);
222 stream_putw (s
, atol (p
+ 1));
224 memcpy (prd
->val
, s
->data
, 8);
230 str2tag (const char *str
, u_char
*tag
)
236 l
= strtoul (str
, &endptr
, 10);
238 if (*endptr
== '\0' || l
== ULONG_MAX
|| l
> UINT32_MAX
)
243 tag
[0] = (u_char
)(t
>> 12);
244 tag
[1] = (u_char
)(t
>> 4);
245 tag
[2] = (u_char
)(t
<< 4);
251 prefix_rd2str (struct prefix_rd
*prd
, char *buf
, size_t size
)
258 if (size
< RD_ADDRSTRLEN
)
263 type
= decode_rd_type (pnt
);
265 if (type
== RD_TYPE_AS
)
267 decode_rd_as (pnt
+ 2, &rd_as
);
268 snprintf (buf
, size
, "%d:%d", rd_as
.as
, rd_as
.val
);
271 else if (type
== RD_TYPE_IP
)
273 decode_rd_ip (pnt
+ 2, &rd_ip
);
274 snprintf (buf
, size
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
281 /* For testing purpose, static route of MPLS-VPN. */
282 DEFUN (vpnv4_network
,
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"
292 return bgp_static_set_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
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",
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"
307 return bgp_static_unset_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
311 show_adj_route_vpn (struct vty
*vty
, struct peer
*peer
, struct prefix_rd
*prd
)
314 struct bgp_table
*table
;
320 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
322 bgp
= bgp_get_default ();
325 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
329 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
;
330 rn
= bgp_route_next (rn
))
332 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
335 if ((table
= rn
->info
) != NULL
)
339 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
340 if ((attr
= rm
->info
) != NULL
)
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",
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
);
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
);
371 vty_out (vty
, "Route Distinguisher: ");
373 if (type
== RD_TYPE_AS
)
374 vty_out (vty
, "%d:%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
);
378 vty_out (vty
, "%s", VTY_NEWLINE
);
381 route_vty_out_tmp (vty
, &rm
->p
, attr
, SAFI_MPLS_VPN
);
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
405 bgp_show_mpls_vpn (struct vty
*vty
, struct prefix_rd
*prd
, enum bgp_show_type type
,
406 void *output_arg
, int tags
)
409 struct bgp_table
*table
;
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";
418 bgp
= bgp_get_default ();
421 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
425 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
; rn
= bgp_route_next (rn
))
427 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
430 if ((table
= rn
->info
) != NULL
)
434 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
435 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
437 if (type
== bgp_show_type_neighbor
)
439 union sockunion
*su
= output_arg
;
441 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
447 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
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",
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
);
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
);
478 vty_out (vty
, "Route Distinguisher: ");
480 if (type
== RD_TYPE_AS
)
481 vty_out (vty
, "%d:%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
);
485 vty_out (vty
, "%s", VTY_NEWLINE
);
489 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
491 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
498 DEFUN (show_ip_bgp_vpnv4_all
,
499 show_ip_bgp_vpnv4_all_cmd
,
500 "show ip bgp vpnv4 all",
504 "Display VPNv4 NLRI specific information\n"
505 "Display information about all VPNv4 NLRIs\n")
507 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 0);
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",
516 "Display VPNv4 NLRI specific information\n"
517 "Display information for a route distinguisher\n"
518 "VPN Route Distinguisher\n")
521 struct prefix_rd prd
;
523 ret
= str2prefix_rd (argv
[0], &prd
);
526 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
529 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 0);
532 DEFUN (show_ip_bgp_vpnv4_all_tags
,
533 show_ip_bgp_vpnv4_all_tags_cmd
,
534 "show ip bgp vpnv4 all tags",
538 "Display VPNv4 NLRI specific information\n"
539 "Display information about all VPNv4 NLRIs\n"
540 "Display BGP tags for prefixes\n")
542 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 1);
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",
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")
557 struct prefix_rd prd
;
559 ret
= str2prefix_rd (argv
[0], &prd
);
562 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
565 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 1);
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",
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")
583 su
= sockunion_str2su (argv
[0]);
586 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
590 peer
= peer_lookup (NULL
, su
);
591 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
593 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
597 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_neighbor
, su
, 0);
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",
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")
616 struct prefix_rd prd
;
618 ret
= str2prefix_rd (argv
[0], &prd
);
621 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
625 su
= sockunion_str2su (argv
[1]);
628 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
632 peer
= peer_lookup (NULL
, su
);
633 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
635 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
639 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_neighbor
, su
, 0);
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",
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")
658 ret
= str2sockunion (argv
[0], &su
);
661 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
664 peer
= peer_lookup (NULL
, &su
);
665 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
667 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
671 return show_adj_route_vpn (vty
, peer
, NULL
);
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",
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")
689 struct prefix_rd prd
;
692 ret
= str2sockunion (argv
[1], &su
);
695 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
698 peer
= peer_lookup (NULL
, &su
);
699 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
701 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
705 ret
= str2prefix_rd (argv
[0], &prd
);
708 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
712 return show_adj_route_vpn (vty
, peer
, &prd
);
716 bgp_mplsvpn_init (void)
718 install_element (BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
719 install_element (BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
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
);
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
);