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
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_table.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_attr.h"
34 #include "bgpd/bgp_mplsvpn.h"
37 decode_rd_type (u_char
*pnt
)
41 v
= ((u_int16_t
) *pnt
++ << 8);
42 v
|= (u_int16_t
) *pnt
;
47 decode_label (u_char
*pnt
)
51 l
= ((u_int32_t
) *pnt
++ << 12);
52 l
|= (u_int32_t
) *pnt
++ << 4;
53 l
|= (u_int32_t
) ((*pnt
& 0xf0) >> 4);
58 decode_rd_as (u_char
*pnt
, struct rd_as
*rd_as
)
60 rd_as
->as
= (u_int16_t
) *pnt
++ << 8;
61 rd_as
->as
|= (u_int16_t
) *pnt
++;
63 rd_as
->val
= ((u_int32_t
) *pnt
++ << 24);
64 rd_as
->val
|= ((u_int32_t
) *pnt
++ << 16);
65 rd_as
->val
|= ((u_int32_t
) *pnt
++ << 8);
66 rd_as
->val
|= (u_int32_t
) *pnt
;
70 decode_rd_ip (u_char
*pnt
, struct rd_ip
*rd_ip
)
72 memcpy (&rd_ip
->ip
, pnt
, 4);
75 rd_ip
->val
= ((u_int16_t
) *pnt
++ << 8);
76 rd_ip
->val
|= (u_int16_t
) *pnt
;
80 bgp_nlri_parse_vpnv4 (struct peer
*peer
, struct attr
*attr
,
81 struct bgp_nlri
*packet
)
96 u_char addpath_encoded
;
99 /* Check peer status. */
100 if (peer
->status
!= Established
)
104 prd
.family
= AF_UNSPEC
;
108 lim
= pnt
+ packet
->length
;
113 addpath_encoded
= (CHECK_FLAG (peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
) &&
114 CHECK_FLAG (peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_TX_RCV
));
116 for (; pnt
< lim
; pnt
+= psize
)
118 /* Clear prefix structure. */
119 memset (&p
, 0, sizeof (struct prefix
));
123 addpath_id
= ntohl(*((uint32_t*) pnt
));
124 pnt
+= BGP_ADDPATH_ID_LEN
;
127 /* Fetch prefix length. */
130 psize
= PSIZE (prefixlen
);
134 zlog_err ("prefix length is less than 88: %d", prefixlen
);
138 label
= decode_label (pnt
);
140 /* Copyr label to prefix. */
143 /* Copy routing distinguisher to rd. */
144 memcpy (&prd
.val
, pnt
+ 3, 8);
146 /* Decode RD type. */
147 type
= decode_rd_type (pnt
+ 3);
149 /* Decode RD value. */
150 if (type
== RD_TYPE_AS
)
151 decode_rd_as (pnt
+ 5, &rd_as
);
152 else if (type
== RD_TYPE_IP
)
153 decode_rd_ip (pnt
+ 5, &rd_ip
);
156 zlog_err ("Invalid RD type %d", type
);
160 p
.prefixlen
= prefixlen
- 88;
161 memcpy (&p
.u
.prefix
, pnt
+ 11, psize
- 11);
164 if (type
== RD_TYPE_AS
)
165 zlog_info ("prefix %ld:%ld:%ld:%s/%d", label
, rd_as
.as
, rd_as
.val
,
166 inet_ntoa (p
.u
.prefix4
), p
.prefixlen
);
167 else if (type
== RD_TYPE_IP
)
168 zlog_info ("prefix %ld:%s:%ld:%s/%d", label
, inet_ntoa (rd_ip
.ip
),
169 rd_ip
.val
, inet_ntoa (p
.u
.prefix4
), p
.prefixlen
);
172 if (pnt
+ psize
> lim
)
176 bgp_update (peer
, &p
, addpath_id
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
177 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
, 0);
179 bgp_withdraw (peer
, &p
, addpath_id
, attr
, AFI_IP
, SAFI_MPLS_VPN
,
180 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, tagpnt
);
183 /* Packet length consistency check. */
191 str2prefix_rd (const char *str
, struct prefix_rd
*prd
)
202 prd
->family
= AF_UNSPEC
;
205 p
= strchr (str
, ':');
209 if (! all_digit (p
+ 1))
212 half
= XMALLOC (MTYPE_TMP
, (p
- str
) + 1);
213 memcpy (half
, str
, (p
- str
));
214 half
[p
- str
] = '\0';
216 p2
= strchr (str
, '.');
220 if (! all_digit (half
))
222 XFREE (MTYPE_TMP
, half
);
225 stream_putw (s
, RD_TYPE_AS
);
226 stream_putw (s
, atoi (half
));
227 stream_putl (s
, atol (p
+ 1));
231 ret
= inet_aton (half
, &addr
);
234 XFREE (MTYPE_TMP
, half
);
237 stream_putw (s
, RD_TYPE_IP
);
238 stream_put_in_addr (s
, &addr
);
239 stream_putw (s
, atol (p
+ 1));
241 memcpy (prd
->val
, s
->data
, 8);
247 str2tag (const char *str
, u_char
*tag
)
257 l
= strtoul (str
, &endptr
, 10);
259 if (*endptr
!= '\0' || errno
|| l
> UINT32_MAX
)
264 tag
[0] = (u_char
)(t
>> 12);
265 tag
[1] = (u_char
)(t
>> 4);
266 tag
[2] = (u_char
)(t
<< 4);
272 prefix_rd2str (struct prefix_rd
*prd
, char *buf
, size_t size
)
279 if (size
< RD_ADDRSTRLEN
)
284 type
= decode_rd_type (pnt
);
286 if (type
== RD_TYPE_AS
)
288 decode_rd_as (pnt
+ 2, &rd_as
);
289 snprintf (buf
, size
, "%u:%d", rd_as
.as
, rd_as
.val
);
292 else if (type
== RD_TYPE_IP
)
294 decode_rd_ip (pnt
+ 2, &rd_ip
);
295 snprintf (buf
, size
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
302 /* For testing purpose, static route of MPLS-VPN. */
303 DEFUN (vpnv4_network
,
305 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
306 "Specify a network to announce via BGP\n"
307 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
308 "Specify Route Distinguisher\n"
309 "VPN Route Distinguisher\n"
313 return bgp_static_set_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
316 /* For testing purpose, static route of MPLS-VPN. */
317 DEFUN (no_vpnv4_network
,
318 no_vpnv4_network_cmd
,
319 "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
321 "Specify a network to announce via BGP\n"
322 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
323 "Specify Route Distinguisher\n"
324 "VPN Route Distinguisher\n"
328 return bgp_static_unset_vpnv4 (vty
, argv
[0], argv
[1], argv
[2]);
332 show_adj_route_vpn (struct vty
*vty
, struct peer
*peer
, struct prefix_rd
*prd
)
335 struct bgp_table
*table
;
341 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
343 bgp
= bgp_get_default ();
346 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
350 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
;
351 rn
= bgp_route_next (rn
))
353 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
356 if ((table
= rn
->info
) != NULL
)
360 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
361 if ((attr
= rm
->info
) != NULL
)
365 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
366 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
367 vty_out (vty
, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
369 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
370 VTY_NEWLINE
, VTY_NEWLINE
);
371 vty_out (vty
, v4_header
, VTY_NEWLINE
);
384 /* Decode RD type. */
385 type
= decode_rd_type (pnt
);
386 /* Decode RD value. */
387 if (type
== RD_TYPE_AS
)
388 decode_rd_as (pnt
+ 2, &rd_as
);
389 else if (type
== RD_TYPE_IP
)
390 decode_rd_ip (pnt
+ 2, &rd_ip
);
392 vty_out (vty
, "Route Distinguisher: ");
394 if (type
== RD_TYPE_AS
)
395 vty_out (vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
396 else if (type
== RD_TYPE_IP
)
397 vty_out (vty
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
399 vty_out (vty
, "%s", VTY_NEWLINE
);
402 route_vty_out_tmp (vty
, &rm
->p
, attr
, SAFI_MPLS_VPN
, NULL
);
411 bgp_show_type_normal
,
412 bgp_show_type_regexp
,
413 bgp_show_type_prefix_list
,
414 bgp_show_type_filter_list
,
415 bgp_show_type_neighbor
,
416 bgp_show_type_cidr_only
,
417 bgp_show_type_prefix_longer
,
418 bgp_show_type_community_all
,
419 bgp_show_type_community
,
420 bgp_show_type_community_exact
,
421 bgp_show_type_community_list
,
422 bgp_show_type_community_list_exact
426 bgp_show_mpls_vpn (struct vty
*vty
, struct prefix_rd
*prd
, enum bgp_show_type type
,
427 void *output_arg
, int tags
)
430 struct bgp_table
*table
;
436 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
437 char v4_header_tag
[] = " Network Next Hop In tag/Out tag%s";
439 bgp
= bgp_get_default ();
442 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
446 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rn
; rn
= bgp_route_next (rn
))
448 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
451 if ((table
= rn
->info
) != NULL
)
455 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
456 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
458 if (type
== bgp_show_type_neighbor
)
460 union sockunion
*su
= output_arg
;
462 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
468 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
471 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
472 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
473 vty_out (vty
, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
475 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
476 VTY_NEWLINE
, VTY_NEWLINE
);
477 vty_out (vty
, v4_header
, VTY_NEWLINE
);
491 /* Decode RD type. */
492 type
= decode_rd_type (pnt
);
493 /* Decode RD value. */
494 if (type
== RD_TYPE_AS
)
495 decode_rd_as (pnt
+ 2, &rd_as
);
496 else if (type
== RD_TYPE_IP
)
497 decode_rd_ip (pnt
+ 2, &rd_ip
);
499 vty_out (vty
, "Route Distinguisher: ");
501 if (type
== RD_TYPE_AS
)
502 vty_out (vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
503 else if (type
== RD_TYPE_IP
)
504 vty_out (vty
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
506 vty_out (vty
, "%s", VTY_NEWLINE
);
510 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
);
512 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_MPLS_VPN
, NULL
);
519 DEFUN (show_ip_bgp_vpnv4_all
,
520 show_ip_bgp_vpnv4_all_cmd
,
521 "show ip bgp vpnv4 all",
525 "Display VPNv4 NLRI specific information\n"
526 "Display information about all VPNv4 NLRIs\n")
528 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 0);
531 DEFUN (show_ip_bgp_vpnv4_rd
,
532 show_ip_bgp_vpnv4_rd_cmd
,
533 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn",
537 "Display VPNv4 NLRI specific information\n"
538 "Display information for a route distinguisher\n"
539 "VPN Route Distinguisher\n")
542 struct prefix_rd prd
;
544 ret
= str2prefix_rd (argv
[0], &prd
);
547 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
550 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 0);
553 DEFUN (show_ip_bgp_vpnv4_all_tags
,
554 show_ip_bgp_vpnv4_all_tags_cmd
,
555 "show ip bgp vpnv4 all tags",
559 "Display VPNv4 NLRI specific information\n"
560 "Display information about all VPNv4 NLRIs\n"
561 "Display BGP tags for prefixes\n")
563 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 1);
566 DEFUN (show_ip_bgp_vpnv4_rd_tags
,
567 show_ip_bgp_vpnv4_rd_tags_cmd
,
568 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn tags",
572 "Display VPNv4 NLRI specific information\n"
573 "Display information for a route distinguisher\n"
574 "VPN Route Distinguisher\n"
575 "Display BGP tags for prefixes\n")
578 struct prefix_rd prd
;
580 ret
= str2prefix_rd (argv
[0], &prd
);
583 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
586 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 1);
589 DEFUN (show_ip_bgp_vpnv4_all_neighbor_routes
,
590 show_ip_bgp_vpnv4_all_neighbor_routes_cmd
,
591 "show ip bgp vpnv4 all neighbors A.B.C.D routes",
595 "Display VPNv4 NLRI specific information\n"
596 "Display information about all VPNv4 NLRIs\n"
597 "Detailed information on TCP and BGP neighbor connections\n"
598 "Neighbor to display information about\n"
599 "Display routes learned from neighbor\n")
605 ret
= str2sockunion (argv
[0], &su
);
608 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
612 peer
= peer_lookup (NULL
, &su
);
613 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
615 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
619 return bgp_show_mpls_vpn (vty
, NULL
, bgp_show_type_neighbor
, &su
, 0);
622 DEFUN (show_ip_bgp_vpnv4_rd_neighbor_routes
,
623 show_ip_bgp_vpnv4_rd_neighbor_routes_cmd
,
624 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes",
628 "Display VPNv4 NLRI specific information\n"
629 "Display information for a route distinguisher\n"
630 "VPN Route Distinguisher\n"
631 "Detailed information on TCP and BGP neighbor connections\n"
632 "Neighbor to display information about\n"
633 "Display routes learned from neighbor\n")
638 struct prefix_rd prd
;
640 ret
= str2prefix_rd (argv
[0], &prd
);
643 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
647 ret
= str2sockunion (argv
[1], &su
);
650 vty_out (vty
, "Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
654 peer
= peer_lookup (NULL
, &su
);
655 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
657 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
661 return bgp_show_mpls_vpn (vty
, &prd
, bgp_show_type_neighbor
, &su
, 0);
664 DEFUN (show_ip_bgp_vpnv4_all_neighbor_advertised_routes
,
665 show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd
,
666 "show ip bgp vpnv4 all neighbors A.B.C.D advertised-routes",
670 "Display VPNv4 NLRI specific information\n"
671 "Display information about all VPNv4 NLRIs\n"
672 "Detailed information on TCP and BGP neighbor connections\n"
673 "Neighbor to display information about\n"
674 "Display the routes advertised to a BGP neighbor\n")
680 ret
= str2sockunion (argv
[0], &su
);
683 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
686 peer
= peer_lookup (NULL
, &su
);
687 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
689 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
693 return show_adj_route_vpn (vty
, peer
, NULL
);
696 DEFUN (show_ip_bgp_vpnv4_rd_neighbor_advertised_routes
,
697 show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd
,
698 "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes",
702 "Display VPNv4 NLRI specific information\n"
703 "Display information for a route distinguisher\n"
704 "VPN Route Distinguisher\n"
705 "Detailed information on TCP and BGP neighbor connections\n"
706 "Neighbor to display information about\n"
707 "Display the routes advertised to a BGP neighbor\n")
711 struct prefix_rd prd
;
714 ret
= str2sockunion (argv
[1], &su
);
717 vty_out (vty
, "%% Malformed address: %s%s", argv
[0], VTY_NEWLINE
);
720 peer
= peer_lookup (NULL
, &su
);
721 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_MPLS_VPN
])
723 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
727 ret
= str2prefix_rd (argv
[0], &prd
);
730 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
734 return show_adj_route_vpn (vty
, peer
, &prd
);
738 bgp_mplsvpn_init (void)
740 install_element (BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
741 install_element (BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
744 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_all_cmd
);
745 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_rd_cmd
);
746 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_all_tags_cmd
);
747 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_rd_tags_cmd
);
748 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd
);
749 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd
);
750 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd
);
751 install_element (VIEW_NODE
, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd
);
753 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_all_cmd
);
754 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_rd_cmd
);
755 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_all_tags_cmd
);
756 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_rd_tags_cmd
);
757 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd
);
758 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd
);
759 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd
);
760 install_element (ENABLE_NODE
, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd
);