1 /* Ethernet-VPN Packet and vty Processing File
2 Copyright (C) 2017 6WIND
4 This file is part of Free Range Routing
6 Free Range Routing 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 Free Range Routing 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 Free Range Routing; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include "bgpd/bgpd.h"
27 #include "bgpd/bgp_table.h"
28 #include "bgpd/bgp_attr.h"
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_mplsvpn.h"
31 #include "bgpd/bgp_vpn.h"
32 #include "bgpd/bgp_evpn_vty.h"
34 #define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
35 #define EVPN_HELP_STR "Ethernet Virtual Private Network\n"
37 #define SHOW_DISPLAY_STANDARD 0
38 #define SHOW_DISPLAY_TAGS 1
39 #define SHOW_DISPLAY_OVERLAY 2
42 bgp_show_ethernet_vpn (struct vty
*vty
, struct prefix_rd
*prd
, enum bgp_show_type type
,
43 void *output_arg
, int option
, u_char use_json
)
45 afi_t afi
= AFI_L2VPN
;
47 struct bgp_table
*table
;
53 char v4_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
54 char v4_header_tag
[] = " Network Next Hop In tag/Out tag%s";
55 char v4_header_overlay
[] = " Network Next Hop EthTag Overlay Index RouterMac%s";
57 unsigned long output_count
= 0;
58 unsigned long total_count
= 0;
59 json_object
*json
= NULL
;
60 json_object
*json_nroute
= NULL
;
61 json_object
*json_array
= NULL
;
62 json_object
*json_scode
= NULL
;
63 json_object
*json_ocode
= NULL
;
65 bgp
= bgp_get_default ();
69 vty_out (vty
, "No BGP process is configured%s", VTY_NEWLINE
);
75 json_scode
= json_object_new_object();
76 json_ocode
= json_object_new_object();
77 json
= json_object_new_object();
78 json_nroute
= json_object_new_object();
80 json_object_string_add(json_scode
, "suppressed", "s");
81 json_object_string_add(json_scode
, "damped", "d");
82 json_object_string_add(json_scode
, "history", "h");
83 json_object_string_add(json_scode
, "valid", "*");
84 json_object_string_add(json_scode
, "best", ">");
85 json_object_string_add(json_scode
, "internal", "i");
87 json_object_string_add(json_ocode
, "igp", "i");
88 json_object_string_add(json_ocode
, "egp", "e");
89 json_object_string_add(json_ocode
, "incomplete", "?");
92 for (rn
= bgp_table_top (bgp
->rib
[afi
][SAFI_EVPN
]); rn
; rn
= bgp_route_next (rn
))
95 continue; /* XXX json TODO */
97 if (prd
&& memcmp (rn
->p
.u
.val
, prd
->val
, 8) != 0)
100 if ((table
= rn
->info
) != NULL
)
104 for (rm
= bgp_table_top (table
); rm
; rm
= bgp_route_next (rm
))
105 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
108 if (type
== bgp_show_type_neighbor
)
110 union sockunion
*su
= output_arg
;
112 if (ri
->peer
->su_remote
== NULL
|| ! sockunion_same(ri
->peer
->su_remote
, su
))
119 if (option
== SHOW_DISPLAY_TAGS
)
121 json_object_int_add(json
, "bgpTableVersion", 0);
122 json_object_string_add(json
, "bgpLocalRouterId", inet_ntoa (bgp
->router_id
));
123 json_object_object_add(json
, "bgpStatusCodes", json_scode
);
124 json_object_object_add(json
, "bgpOriginCodes", json_ocode
);
129 if (option
== SHOW_DISPLAY_TAGS
)
130 vty_out (vty
, v4_header_tag
, VTY_NEWLINE
);
131 else if (option
== SHOW_DISPLAY_OVERLAY
)
132 vty_out (vty
, v4_header_overlay
, VTY_NEWLINE
);
135 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
136 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
137 vty_out (vty
, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
139 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
140 VTY_NEWLINE
, VTY_NEWLINE
);
141 vty_out (vty
, v4_header
, VTY_NEWLINE
);
155 /* Decode RD type. */
156 type
= decode_rd_type (pnt
);
157 /* Decode RD value. */
158 if (type
== RD_TYPE_AS
)
159 decode_rd_as (pnt
+ 2, &rd_as
);
160 else if (type
== RD_TYPE_AS4
)
161 decode_rd_as4 (pnt
+ 2, &rd_as
);
162 else if (type
== RD_TYPE_IP
)
163 decode_rd_ip (pnt
+ 2, &rd_ip
);
167 if (type
== RD_TYPE_AS
|| type
== RD_TYPE_AS4
)
168 sprintf (buffer
, "%u:%d", rd_as
.as
, rd_as
.val
);
169 else if (type
== RD_TYPE_IP
)
170 sprintf (buffer
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
171 json_object_string_add(json_nroute
, "routeDistinguisher", buffer
);
175 vty_out (vty
, "Route Distinguisher: ");
176 if (type
== RD_TYPE_AS
)
177 vty_out (vty
, "as2 %u:%d", rd_as
.as
, rd_as
.val
);
178 else if (type
== RD_TYPE_AS4
)
179 vty_out (vty
, "as4 %u:%d", rd_as
.as
, rd_as
.val
);
180 else if (type
== RD_TYPE_IP
)
181 vty_out (vty
, "ip %s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
182 vty_out (vty
, "%s", VTY_NEWLINE
);
187 json_array
= json_object_new_array();
190 if (option
== SHOW_DISPLAY_TAGS
)
191 route_vty_out_tag (vty
, &rm
->p
, ri
, 0, SAFI_EVPN
, json_array
);
192 else if (option
== SHOW_DISPLAY_OVERLAY
)
193 route_vty_out_overlay (vty
, &rm
->p
, ri
, 0, json_array
);
195 route_vty_out (vty
, &rm
->p
, ri
, 0, SAFI_EVPN
, json_array
);
201 if (output_count
== 0)
202 vty_out (vty
, "No prefixes displayed, %ld exist%s", total_count
, VTY_NEWLINE
);
204 vty_out (vty
, "%sDisplayed %ld out of %ld total prefixes%s",
205 VTY_NEWLINE
, output_count
, total_count
, VTY_NEWLINE
);
209 DEFUN (show_ip_bgp_l2vpn_evpn
,
210 show_ip_bgp_l2vpn_evpn_cmd
,
211 "show [ip] bgp l2vpn evpn [json]",
219 return bgp_show_ethernet_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 0, use_json (argc
, argv
));
222 DEFUN (show_ip_bgp_l2vpn_evpn_rd
,
223 show_ip_bgp_l2vpn_evpn_rd_cmd
,
224 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
230 "Display information for a route distinguisher\n"
231 "VPN Route Distinguisher\n"
234 int idx_ext_community
= 6;
236 struct prefix_rd prd
;
238 ret
= str2prefix_rd (argv
[idx_ext_community
]->arg
, &prd
);
241 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
244 return bgp_show_ethernet_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
, 0, use_json (argc
, argv
));
247 DEFUN (show_ip_bgp_l2vpn_evpn_all_tags
,
248 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
249 "show [ip] bgp l2vpn evpn all tags",
255 "Display information about all EVPN NLRIs\n"
256 "Display BGP tags for prefixes\n")
258 return bgp_show_ethernet_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
, 1, 0);
261 DEFUN (show_ip_bgp_l2vpn_evpn_rd_tags
,
262 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
263 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
269 "Display information for a route distinguisher\n"
270 "VPN Route Distinguisher\n"
271 "Display BGP tags for prefixes\n")
273 int idx_ext_community
= 6;
275 struct prefix_rd prd
;
277 ret
= str2prefix_rd (argv
[idx_ext_community
]->arg
, &prd
);
280 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
283 return bgp_show_ethernet_vpn (vty
,&prd
, bgp_show_type_normal
, NULL
, 1, 0);
286 DEFUN (show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
287 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
288 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
294 "Display information about all EVPN NLRIs\n"
295 "Detailed information on TCP and BGP neighbor connections\n"
296 "Neighbor to display information about\n"
297 "Display routes learned from neighbor\n"
304 u_char uj
= use_json(argc
, argv
);
306 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
311 json_object
*json_no
= NULL
;
312 json_no
= json_object_new_object();
313 json_object_string_add(json_no
, "warning", "Malformed address");
314 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
315 json_object_free(json_no
);
318 vty_out (vty
, "Malformed address: %s%s", argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
322 peer
= peer_lookup (NULL
, &su
);
323 if (! peer
|| ! peer
->afc
[AFI_L2VPN
][SAFI_EVPN
])
327 json_object
*json_no
= NULL
;
328 json_no
= json_object_new_object();
329 json_object_string_add(json_no
, "warning", "No such neighbor or address family");
330 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
331 json_object_free(json_no
);
334 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
338 return bgp_show_ethernet_vpn (vty
, NULL
, bgp_show_type_neighbor
, &su
, 0, uj
);
341 DEFUN (show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
342 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
343 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
349 "Display information for a route distinguisher\n"
350 "VPN Route Distinguisher\n"
351 "Detailed information on TCP and BGP neighbor connections\n"
352 "Neighbor to display information about\n"
353 "Display routes learned from neighbor\n"
356 int idx_ext_community
= 6;
361 struct prefix_rd prd
;
362 u_char uj
= use_json(argc
, argv
);
364 ret
= str2prefix_rd (argv
[idx_ext_community
]->arg
, &prd
);
369 json_object
*json_no
= NULL
;
370 json_no
= json_object_new_object();
371 json_object_string_add(json_no
, "warning", "Malformed Route Distinguisher");
372 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
373 json_object_free(json_no
);
376 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
380 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
385 json_object
*json_no
= NULL
;
386 json_no
= json_object_new_object();
387 json_object_string_add(json_no
, "warning", "Malformed address");
388 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
389 json_object_free(json_no
);
392 vty_out (vty
, "Malformed address: %s%s", argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
396 peer
= peer_lookup (NULL
, &su
);
397 if (! peer
|| ! peer
->afc
[AFI_L2VPN
][SAFI_EVPN
])
401 json_object
*json_no
= NULL
;
402 json_no
= json_object_new_object();
403 json_object_string_add(json_no
, "warning", "No such neighbor or address family");
404 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
405 json_object_free(json_no
);
408 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
412 return bgp_show_ethernet_vpn (vty
, &prd
, bgp_show_type_neighbor
, &su
, 0, uj
);
415 DEFUN (show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
416 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
417 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
423 "Display information about all EVPN NLRIs\n"
424 "Detailed information on TCP and BGP neighbor connections\n"
425 "Neighbor to display information about\n"
426 "Display the routes advertised to a BGP neighbor\n"
433 u_char uj
= use_json(argc
, argv
);
435 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
440 json_object
*json_no
= NULL
;
441 json_no
= json_object_new_object();
442 json_object_string_add(json_no
, "warning", "Malformed address");
443 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
444 json_object_free(json_no
);
447 vty_out (vty
, "Malformed address: %s%s", argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
450 peer
= peer_lookup (NULL
, &su
);
451 if (! peer
|| ! peer
->afc
[AFI_L2VPN
][SAFI_EVPN
])
455 json_object
*json_no
= NULL
;
456 json_no
= json_object_new_object();
457 json_object_string_add(json_no
, "warning", "No such neighbor or address family");
458 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
459 json_object_free(json_no
);
462 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
466 return show_adj_route_vpn (vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
469 DEFUN (show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
470 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
471 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
477 "Display information for a route distinguisher\n"
478 "VPN Route Distinguisher\n"
479 "Detailed information on TCP and BGP neighbor connections\n"
480 "Neighbor to display information about\n"
481 "Display the routes advertised to a BGP neighbor\n"
484 int idx_ext_community
= 6;
488 struct prefix_rd prd
;
490 u_char uj
= use_json(argc
, argv
);
492 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
497 json_object
*json_no
= NULL
;
498 json_no
= json_object_new_object();
499 json_object_string_add(json_no
, "warning", "Malformed address");
500 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
501 json_object_free(json_no
);
504 vty_out (vty
, "Malformed address: %s%s", argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
507 peer
= peer_lookup (NULL
, &su
);
508 if (! peer
|| ! peer
->afc
[AFI_L2VPN
][SAFI_EVPN
])
512 json_object
*json_no
= NULL
;
513 json_no
= json_object_new_object();
514 json_object_string_add(json_no
, "warning", "No such neighbor or address family");
515 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
516 json_object_free(json_no
);
519 vty_out (vty
, "%% No such neighbor or address family%s", VTY_NEWLINE
);
523 ret
= str2prefix_rd (argv
[idx_ext_community
]->arg
, &prd
);
528 json_object
*json_no
= NULL
;
529 json_no
= json_object_new_object();
530 json_object_string_add(json_no
, "warning", "Malformed Route Distinguisher");
531 vty_out (vty
, "%s%s", json_object_to_json_string(json_no
), VTY_NEWLINE
);
532 json_object_free(json_no
);
535 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
539 return show_adj_route_vpn (vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
542 DEFUN (show_ip_bgp_l2vpn_evpn_all_overlay
,
543 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
544 "show [ip] bgp l2vpn evpn all overlay",
550 "Display information about all EVPN NLRIs\n"
551 "Display BGP Overlay Information for prefixes\n")
553 return bgp_show_ethernet_vpn (vty
, NULL
, bgp_show_type_normal
, NULL
,
554 SHOW_DISPLAY_OVERLAY
, use_json (argc
, argv
));
557 DEFUN (show_ip_bgp_evpn_rd_overlay
,
558 show_ip_bgp_evpn_rd_overlay_cmd
,
559 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
565 "Display information for a route distinguisher\n"
566 "VPN Route Distinguisher\n"
567 "Display BGP Overlay Information for prefixes\n")
569 int idx_ext_community
= 6;
571 struct prefix_rd prd
;
573 ret
= str2prefix_rd (argv
[idx_ext_community
]->arg
, &prd
);
576 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
579 return bgp_show_ethernet_vpn (vty
, &prd
, bgp_show_type_normal
, NULL
,
580 SHOW_DISPLAY_OVERLAY
, use_json (argc
, argv
));
585 bgp_ethernetvpn_init (void)
587 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
588 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
589 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
590 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
591 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
592 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
593 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
594 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
595 install_element (VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
596 install_element (VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);