3 * This file created by LabN Consulting, L.L.C.
6 * This file is based on bgp_mplsvpn.c which is Copyright (C) 2000
7 * Kunihiro Ishiguro <kunihiro@zebra.org>
13 This file is part of GNU Zebra.
15 GNU Zebra is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by the
17 Free Software Foundation; either version 2, or (at your option) any
20 GNU Zebra is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with GNU Zebra; see the file COPYING. If not, write to the Free
27 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
39 #include "bgpd/bgpd.h"
40 #include "bgpd/bgp_table.h"
41 #include "bgpd/bgp_route.h"
42 #include "bgpd/bgp_attr.h"
43 #include "bgpd/bgp_ecommunity.h"
44 #include "bgpd/bgp_lcommunity.h"
45 #include "bgpd/bgp_mplsvpn.h"
46 #include "bgpd/bgp_vty.h"
47 #include "bgpd/bgp_encap.h"
50 #include "bgpd/rfapi/rfapi_backend.h"
54 ecom2prd(struct ecommunity
*ecom
, struct prefix_rd
*prd
)
58 memset(prd
, 0, sizeof(struct prefix_rd
));
59 prd
->family
= AF_UNSPEC
;
65 for (i
= 0; i
< (ecom
->size
* ECOMMUNITY_SIZE
); i
+= ECOMMUNITY_SIZE
) {
79 prd
->val
[1] = ep
[0] & 0x03;
80 memcpy(prd
->val
+ 2, ep
+ 2, 6);
91 struct bgp_nlri
*packet
)
95 afi_t afi
= packet
->afi
;
101 struct prefix_rd prd
;
102 struct ecommunity
*pEcom
= NULL
;
103 u_int16_t rdtype
= 0xffff;
106 /* Check peer status. */
107 if (peer
->status
!= Established
)
111 if (attr
&& attr
->extra
&& attr
->extra
->ecommunity
)
112 pEcom
= attr
->extra
->ecommunity
;
114 ecom2prd(pEcom
, &prd
);
115 memset(&rd_as
, 0, sizeof(rd_as
));
116 memset(&rd_ip
, 0, sizeof(rd_ip
));
120 rdtype
= (prd
.val
[0] << 8) | prd
.val
[1];
122 /* Decode RD value. */
123 if (rdtype
== RD_TYPE_AS
)
124 decode_rd_as (prd
.val
+ 2, &rd_as
);
125 else if (rdtype
== RD_TYPE_IP
)
126 decode_rd_ip (prd
.val
+ 2, &rd_ip
);
127 else if (rdtype
== RD_TYPE_AS4
)
128 decode_rd_as4 (prd
.val
+ 2, &rd_as
);
131 zlog_err ("Invalid RD type %d", rdtype
);
137 * NB: this code was based on the MPLS VPN code, which supported RDs.
138 * For the moment we are retaining the underlying RIB structure that
139 * keeps a per-RD radix tree, but since the RDs are not carried over
140 * the wire, we set the RD internally to 0.
142 prd
.family
= AF_UNSPEC
;
144 memset(prd
.val
, 0, sizeof(prd
.val
));
147 lim
= pnt
+ packet
->length
;
149 for (; pnt
< lim
; pnt
+= psize
)
151 /* Clear prefix structure. */
152 memset (&p
, 0, sizeof (struct prefix
));
154 /* Fetch prefix length. */
156 p
.family
= afi2family(afi
);
158 /* bad afi, shouldn't happen */
159 zlog_warn("%s: bad afi %d, dropping incoming route", __func__
, afi
);
162 psize
= PSIZE (prefixlen
);
164 p
.prefixlen
= prefixlen
;
165 memcpy (&p
.u
.prefix
, pnt
, psize
);
167 if (pnt
+ psize
> lim
)
171 if (rdtype
== RD_TYPE_AS
)
172 zlog_info ("rd-as %u:%u prefix %s/%d", rd_as
.as
, rd_as
.val
,
173 inet_ntop (p
.family
, &p
.u
.prefix
, buf
, BUFSIZ
),
175 else if (rdtype
== RD_TYPE_IP
)
176 zlog_info ("rd-ip %s:%u prefix %s/%d", inet_ntoa (rd_ip
.ip
),
178 inet_ntop (p
.family
, &p
.u
.prefix
, buf
, BUFSIZ
),
180 else if (rdtype
== RD_TYPE_AS4
)
181 zlog_info ("rd-as4 %u:%u prefix %s/%d", rd_as
.as
, rd_as
.val
,
182 inet_ntop (p
.family
, &p
.u
.prefix
, buf
, BUFSIZ
),
185 zlog_info ("rd unknown, default to 0:0 prefix %s/%d",
186 inet_ntop (p
.family
, &p
.u
.prefix
, buf
, BUFSIZ
),
190 bgp_update (peer
, &p
, 0, attr
, afi
, SAFI_ENCAP
,
191 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, NULL
, 0, NULL
);
193 bgp_withdraw (peer
, &p
, 0, attr
, afi
, SAFI_ENCAP
,
194 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, &prd
, NULL
, NULL
);
198 /* Packet length consistency check. */
206 /* TBD: these routes should probably all be host routes */
208 /* For testing purpose, static route of ENCAP. */
209 DEFUN (encap_network
,
211 "network A.B.C.D/M rd ASN:nn_or_IP-address:nn",
212 "Specify a network to announce via BGP\n"
214 "Specify Route Distinguisher\n"
215 "ENCAP Route Distinguisher\n")
219 return bgp_static_set_safi (AFI_IP
, SAFI_ENCAP
, vty
, argv
[idx_ipv4
]->arg
, argv
[idx_rd
]->arg
, NULL
,
220 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
223 /* For testing purpose, static route of ENCAP. */
224 DEFUN (no_encap_network
,
225 no_encap_network_cmd
,
226 "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn",
228 "Specify a network to announce via BGP\n"
230 "Specify Route Distinguisher\n"
231 "ENCAP Route Distinguisher\n"
237 return bgp_static_unset_safi (AFI_IP
, SAFI_ENCAP
, vty
, argv
[idx_ipv4
]->arg
, argv
[idx_rd
]->arg
, NULL
,
238 0, NULL
, NULL
, NULL
);
242 show_adj_route_encap (struct vty
*vty
, struct peer
*peer
, struct prefix_rd
*prd
)
245 struct bgp_table
*table
;
251 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
253 bgp
= bgp_get_default ();
256 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
260 for (rn
= bgp_table_top (bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); rn
;
261 rn
= bgp_route_next (rn
))
263 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
266 if ((table
= rn
->info
) != NULL
)
270 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
271 if ((attr
= rm
->info
) != NULL
)
275 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
276 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
277 vty_out (vty
, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
279 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
280 VTY_NEWLINE
, VTY_NEWLINE
);
281 vty_out (vty
, v4_header
, VTY_NEWLINE
);
294 vty_out (vty
, "Route Distinguisher: ");
296 /* Decode RD type. */
297 type
= decode_rd_type (pnt
);
302 decode_rd_as (pnt
+ 2, &rd_as
);
303 vty_out (vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
307 decode_rd_ip (pnt
+ 2, &rd_ip
);
308 vty_out (vty
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
312 vty_out (vty
, "unknown RD type");
316 vty_out (vty
, "%s", VTY_NEWLINE
);
319 route_vty_out_tmp (vty
, &rm
->p
, attr
, SAFI_ENCAP
, 0, NULL
);
330 struct prefix_rd
*prd
,
331 enum bgp_show_type type
,
336 struct bgp_table
*table
;
342 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
343 char v4_header_tag
[] = " Network Next Hop In tag/Out tag%s";
345 unsigned long output_count
= 0;
346 unsigned long total_count
= 0;
348 bgp
= bgp_get_default ();
351 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
355 if ((afi
!= AFI_IP
) && (afi
!= AFI_IP6
)) {
356 vty_out (vty
, "Afi %d not supported%s", afi
, VTY_NEWLINE
);
360 for (rn
= bgp_table_top (bgp
->rib
[afi
][SAFI_ENCAP
]); rn
; rn
= bgp_route_next (rn
))
362 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
365 if ((table
= rn
->info
) != NULL
)
369 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
370 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
373 if (type
== bgp_show_type_neighbor
)
375 union sockunion
*su
= output_arg
;
377 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
383 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
386 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
387 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
388 vty_out (vty
, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
390 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
391 VTY_NEWLINE
, VTY_NEWLINE
);
392 vty_out (vty
, v4_header
, VTY_NEWLINE
);
406 /* Decode RD type. */
407 type
= decode_rd_type (pnt
);
409 vty_out (vty
, "Route Distinguisher: ");
414 decode_rd_as (pnt
+ 2, &rd_as
);
415 vty_out (vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
419 decode_rd_ip (pnt
+ 2, &rd_ip
);
420 vty_out (vty
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
424 vty_out (vty
, "Unknown RD type");
428 vty_out (vty
, "%s", VTY_NEWLINE
);
432 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_ENCAP
, NULL
);
434 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_ENCAP
, NULL
);
440 if (output_count
== 0)
442 vty_out (vty
, "No prefixes displayed, %ld exist%s", total_count
, VTY_NEWLINE
);
445 vty_out (vty
, "%sDisplayed %ld routes and %ld total paths%s",
446 VTY_NEWLINE
, output_count
, total_count
, VTY_NEWLINE
);
451 DEFUN (show_bgp_ipv4_encap_rd
,
452 show_bgp_ipv4_encap_rd_cmd
,
453 "show [ip] bgp ipv4 encap rd ASN:nn_or_IP-address:nn",
458 "Display ENCAP NLRI specific information\n"
459 "Display information for a route distinguisher\n"
460 "ENCAP Route Distinguisher\n")
464 struct prefix_rd prd
;
466 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
469 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
472 return bgp_show_encap (vty
, AFI_IP
, &prd
, bgp_show_type_normal
, NULL
, 0);
475 DEFUN (show_bgp_ipv6_encap_rd
,
476 show_bgp_ipv6_encap_rd_cmd
,
477 "show [ip] bgp ipv6 encap rd ASN:nn_or_IP-address:nn",
482 "Display ENCAP NLRI specific information\n"
483 "Display information for a route distinguisher\n"
484 "ENCAP Route Distinguisher\n"
485 "Display BGP tags for prefixes\n")
489 struct prefix_rd prd
;
491 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
494 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
497 return bgp_show_encap (vty
, AFI_IP6
, &prd
, bgp_show_type_normal
, NULL
, 0);
500 DEFUN (show_bgp_ipv4_encap_tags
,
501 show_bgp_ipv4_encap_tags_cmd
,
502 "show [ip] bgp ipv4 encap tags",
507 "Display ENCAP NLRI specific information\n"
508 "Display BGP tags for prefixes\n")
510 return bgp_show_encap (vty
, AFI_IP
, NULL
, bgp_show_type_normal
, NULL
, 1);
513 DEFUN (show_bgp_ipv6_encap_tags
,
514 show_bgp_ipv6_encap_tags_cmd
,
515 "show [ip] bgp ipv6 encap tags",
520 "Display ENCAP NLRI specific information\n"
521 "Display BGP tags for prefixes\n")
523 return bgp_show_encap (vty
, AFI_IP6
, NULL
, bgp_show_type_normal
, NULL
, 1);
526 DEFUN (show_bgp_ipv4_encap_rd_tags
,
527 show_bgp_ipv4_encap_rd_tags_cmd
,
528 "show [ip] bgp ipv4 encap rd ASN:nn_or_IP-address:nn tags",
533 "Display ENCAP NLRI specific information\n"
534 "Display information for a route distinguisher\n"
535 "ENCAP Route Distinguisher\n"
536 "Display BGP tags for prefixes\n")
540 struct prefix_rd prd
;
542 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
545 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
548 return bgp_show_encap (vty
, AFI_IP
, &prd
, bgp_show_type_normal
, NULL
, 1);
551 DEFUN (show_bgp_ipv6_encap_rd_tags
,
552 show_bgp_ipv6_encap_rd_tags_cmd
,
553 "show [ip] bgp ipv6 encap rd ASN:nn_or_IP-address:nn tags",
558 "Display ENCAP NLRI specific information\n"
559 "Display information for a route distinguisher\n"
560 "ENCAP Route Distinguisher\n"
561 "Display BGP tags for prefixes\n")
565 struct prefix_rd prd
;
567 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
570 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
573 return bgp_show_encap (vty
, AFI_IP6
, &prd
, bgp_show_type_normal
, NULL
, 1);
576 DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes
,
577 show_bgp_ipv4_encap_rd_neighbor_routes_cmd
,
578 "show [ip] bgp ipv4 encap rd ASN:nn_or_IP-address:nn neighbors <A.B.C.D|X:X::X:X> routes",
583 "Display ENCAP NLRI specific information\n"
584 "Display information for a route distinguisher\n"
585 "ENCAP Route Distinguisher\n"
586 "Detailed information on TCP and BGP neighbor connections\n"
587 "Neighbor to display information about\n"
588 "Neighbor to display information about\n"
589 "Display routes learned from neighbor\n")
596 struct prefix_rd prd
;
598 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
601 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
605 if (str2sockunion(argv
[idx_peer
]->arg
, &su
))
607 vty_out (vty
, "Malformed address: %s%s", argv
[idx_peer
]->arg
, VTY_NEWLINE
);
611 peer
= peer_lookup (NULL
, &su
);
612 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_ENCAP
])
614 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
618 return bgp_show_encap (vty
, AFI_IP
, &prd
, bgp_show_type_neighbor
, &su
, 0);
621 DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes
,
622 show_bgp_ipv6_encap_rd_neighbor_routes_cmd
,
623 "show [ip] bgp ipv6 encap rd ASN:nn_or_IP-address:nn neighbors <A.B.C.D|X:X::X:X> routes",
628 "Display ENCAP NLRI specific information\n"
629 "Display information for a route distinguisher\n"
630 "ENCAP Route Distinguisher\n"
631 "Detailed information on TCP and BGP neighbor connections\n"
632 "Neighbor to display information about\n"
633 "Neighbor to display information about\n"
634 "Display routes learned from neighbor\n")
641 struct prefix_rd prd
;
643 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
646 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
650 if (str2sockunion(argv
[idx_peer
]->arg
, &su
))
652 vty_out (vty
, "Malformed address: %s%s", argv
[idx_peer
]->arg
, VTY_NEWLINE
);
656 peer
= peer_lookup (NULL
, &su
);
657 if (! peer
|| ! peer
->afc
[AFI_IP6
][SAFI_ENCAP
])
659 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
663 return bgp_show_encap (vty
, AFI_IP6
, &prd
, bgp_show_type_neighbor
, &su
, 0);
666 DEFUN (show_bgp_ipv4_encap_rd_neighbor_advertised_routes
,
667 show_bgp_ipv4_encap_rd_neighbor_advertised_routes_cmd
,
668 "show [ip] bgp ipv4 encap rd ASN:nn_or_IP-address:nn neighbors <A.B.C.D|X:X::X:X> advertised-routes",
673 "Display ENCAP NLRI specific information\n"
674 "Display information for a route distinguisher\n"
675 "ENCAP Route Distinguisher\n"
676 "Detailed information on TCP and BGP neighbor connections\n"
677 "Neighbor to display information about\n"
678 "Neighbor to display information about\n"
679 "Display the routes advertised to a BGP neighbor\n")
685 struct prefix_rd prd
;
688 ret
= str2sockunion (argv
[idx_peer
]->arg
, &su
);
691 vty_out (vty
, "%% Malformed address: %s%s", argv
[idx_peer
]->arg
, VTY_NEWLINE
);
694 peer
= peer_lookup (NULL
, &su
);
695 if (! peer
|| ! peer
->afc
[AFI_IP
][SAFI_ENCAP
])
697 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
701 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
704 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
708 return show_adj_route_encap (vty
, peer
, &prd
);
711 DEFUN (show_bgp_ipv6_encap_rd_neighbor_advertised_routes
,
712 show_bgp_ipv6_encap_rd_neighbor_advertised_routes_cmd
,
713 "show [ip] bgp ipv6 encap rd ASN:nn_or_IP-address:nn neighbors <A.B.C.D|X:X::X:X> advertised-routes",
718 "Display ENCAP NLRI specific information\n"
719 "Display information for a route distinguisher\n"
720 "ENCAP Route Distinguisher\n"
721 "Detailed information on TCP and BGP neighbor connections\n"
722 "Neighbor to display information about\n"
723 "Neighbor to display information about\n"
724 "Display the routes advertised to a BGP neighbor\n")
730 struct prefix_rd prd
;
733 ret
= str2sockunion (argv
[idx_peer
]->arg
, &su
);
736 vty_out (vty
, "%% Malformed address: %s%s", argv
[idx_peer
]->arg
, VTY_NEWLINE
);
739 peer
= peer_lookup (NULL
, &su
);
740 if (! peer
|| ! peer
->afc
[AFI_IP6
][SAFI_ENCAP
])
742 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
746 ret
= str2prefix_rd (argv
[idx_rd
]->arg
, &prd
);
749 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
753 return show_adj_route_encap (vty
, peer
, &prd
);
757 bgp_encap_init (void)
759 install_element (BGP_ENCAP_NODE
, &encap_network_cmd
);
760 install_element (BGP_ENCAP_NODE
, &no_encap_network_cmd
);
762 install_element (VIEW_NODE
, &show_bgp_ipv4_encap_rd_cmd
);
763 install_element (VIEW_NODE
, &show_bgp_ipv4_encap_tags_cmd
);
764 install_element (VIEW_NODE
, &show_bgp_ipv4_encap_rd_tags_cmd
);
765 install_element (VIEW_NODE
, &show_bgp_ipv4_encap_rd_neighbor_routes_cmd
);
766 install_element (VIEW_NODE
, &show_bgp_ipv4_encap_rd_neighbor_advertised_routes_cmd
);
768 install_element (VIEW_NODE
, &show_bgp_ipv6_encap_rd_cmd
);
769 install_element (VIEW_NODE
, &show_bgp_ipv6_encap_tags_cmd
);
770 install_element (VIEW_NODE
, &show_bgp_ipv6_encap_rd_tags_cmd
);
771 install_element (VIEW_NODE
, &show_bgp_ipv6_encap_rd_neighbor_routes_cmd
);
772 install_element (VIEW_NODE
, &show_bgp_ipv6_encap_rd_neighbor_advertised_routes_cmd
);