]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
bgpd: vty commands added for EVPN address family
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
CommitLineData
784d3a42
PG
1/* Ethernet-VPN Packet and vty Processing File
2 Copyright (C) 2017 6WIND
3
4This file is part of Free Range Routing
5
6Free Range Routing is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11Free Range Routing is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Free Range Routing; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22#include "command.h"
23#include "prefix.h"
24#include "lib/json.h"
25
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"
33
784d3a42
PG
34#define SHOW_DISPLAY_STANDARD 0
35#define SHOW_DISPLAY_TAGS 1
36#define SHOW_DISPLAY_OVERLAY 2
37
38static int
39bgp_show_ethernet_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
40 void *output_arg, int option, u_char use_json)
41{
42 afi_t afi = AFI_L2VPN;
43 struct bgp *bgp;
44 struct bgp_table *table;
45 struct bgp_node *rn;
46 struct bgp_node *rm;
47 struct bgp_info *ri;
48 int rd_header;
49 int header = 1;
50 char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
51 char v4_header_tag[] = " Network Next Hop In tag/Out tag%s";
52 char v4_header_overlay[] = " Network Next Hop EthTag Overlay Index RouterMac%s";
53
54 unsigned long output_count = 0;
55 unsigned long total_count = 0;
56 json_object *json = NULL;
57 json_object *json_nroute = NULL;
58 json_object *json_array = NULL;
59 json_object *json_scode = NULL;
60 json_object *json_ocode = NULL;
61
62 bgp = bgp_get_default ();
63 if (bgp == NULL)
64 {
65 if (!use_json)
66 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
67 return CMD_WARNING;
68 }
69
70 if (use_json)
71 {
72 json_scode = json_object_new_object();
73 json_ocode = json_object_new_object();
74 json = json_object_new_object();
75 json_nroute = json_object_new_object();
76
77 json_object_string_add(json_scode, "suppressed", "s");
78 json_object_string_add(json_scode, "damped", "d");
79 json_object_string_add(json_scode, "history", "h");
80 json_object_string_add(json_scode, "valid", "*");
81 json_object_string_add(json_scode, "best", ">");
82 json_object_string_add(json_scode, "internal", "i");
83
84 json_object_string_add(json_ocode, "igp", "i");
85 json_object_string_add(json_ocode, "egp", "e");
86 json_object_string_add(json_ocode, "incomplete", "?");
87 }
88
89 for (rn = bgp_table_top (bgp->rib[afi][SAFI_EVPN]); rn; rn = bgp_route_next (rn))
90 {
91 if (use_json)
92 continue; /* XXX json TODO */
93
94 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
95 continue;
96
97 if ((table = rn->info) != NULL)
98 {
99 rd_header = 1;
100
101 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
102 for (ri = rm->info; ri; ri = ri->next)
103 {
104 total_count++;
105 if (type == bgp_show_type_neighbor)
106 {
107 union sockunion *su = output_arg;
108
109 if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
110 continue;
111 }
112 if (header == 0)
113 {
114 if (use_json)
115 {
116 if (option == SHOW_DISPLAY_TAGS)
117 {
118 json_object_int_add(json, "bgpTableVersion", 0);
119 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
120 json_object_object_add(json, "bgpStatusCodes", json_scode);
121 json_object_object_add(json, "bgpOriginCodes", json_ocode);
122 }
123 }
124 else
125 {
126 if (option == SHOW_DISPLAY_TAGS)
127 vty_out (vty, v4_header_tag, VTY_NEWLINE);
128 else if (option == SHOW_DISPLAY_OVERLAY)
129 vty_out (vty, v4_header_overlay, VTY_NEWLINE);
130 else
131 {
132 vty_out (vty, "BGP table version is 0, local router ID is %s%s",
133 inet_ntoa (bgp->router_id), VTY_NEWLINE);
134 vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
135 VTY_NEWLINE);
136 vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
137 VTY_NEWLINE, VTY_NEWLINE);
138 vty_out (vty, v4_header, VTY_NEWLINE);
139 }
140 }
141 header = 0;
142 }
143 if (rd_header)
144 {
145 u_int16_t type;
146 struct rd_as rd_as;
147 struct rd_ip rd_ip;
148 u_char *pnt;
149
150 pnt = rn->p.u.val;
151
152 /* Decode RD type. */
153 type = decode_rd_type (pnt);
154 /* Decode RD value. */
155 if (type == RD_TYPE_AS)
156 decode_rd_as (pnt + 2, &rd_as);
157 else if (type == RD_TYPE_AS4)
158 decode_rd_as4 (pnt + 2, &rd_as);
159 else if (type == RD_TYPE_IP)
160 decode_rd_ip (pnt + 2, &rd_ip);
161 if (use_json)
162 {
163 char buffer[BUFSIZ];
164 if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
165 sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
166 else if (type == RD_TYPE_IP)
167 sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
168 json_object_string_add(json_nroute, "routeDistinguisher", buffer);
169 }
170 else
171 {
172 vty_out (vty, "Route Distinguisher: ");
173 if (type == RD_TYPE_AS)
174 vty_out (vty, "as2 %u:%d", rd_as.as, rd_as.val);
175 else if (type == RD_TYPE_AS4)
176 vty_out (vty, "as4 %u:%d", rd_as.as, rd_as.val);
177 else if (type == RD_TYPE_IP)
178 vty_out (vty, "ip %s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
179 vty_out (vty, "%s", VTY_NEWLINE);
180 }
181 rd_header = 0;
182 }
183 if (use_json)
184 json_array = json_object_new_array();
185 else
186 json_array = NULL;
187 if (option == SHOW_DISPLAY_TAGS)
188 route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_EVPN, json_array);
189 else if (option == SHOW_DISPLAY_OVERLAY)
190 route_vty_out_overlay (vty, &rm->p, ri, 0, json_array);
191 else
192 route_vty_out (vty, &rm->p, ri, 0, SAFI_EVPN, json_array);
193 output_count++;
194 }
195 /* XXX json */
196 }
197 }
198 if (output_count == 0)
199 vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
200 else
201 vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
202 VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
203 return CMD_SUCCESS;
204}
205
206DEFUN (show_ip_bgp_l2vpn_evpn,
207 show_ip_bgp_l2vpn_evpn_cmd,
208 "show [ip] bgp l2vpn evpn [json]",
209 SHOW_STR
210 IP_STR
211 BGP_STR
212 L2VPN_HELP_STR
213 EVPN_HELP_STR
214 JSON_STR)
215{
216 return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL, 0, use_json (argc, argv));
217}
218
219DEFUN (show_ip_bgp_l2vpn_evpn_rd,
220 show_ip_bgp_l2vpn_evpn_rd_cmd,
221 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
222 SHOW_STR
223 IP_STR
224 BGP_STR
225 L2VPN_HELP_STR
226 EVPN_HELP_STR
227 "Display information for a route distinguisher\n"
228 "VPN Route Distinguisher\n"
229 JSON_STR)
230{
231 int idx_ext_community = 6;
232 int ret;
233 struct prefix_rd prd;
234
235 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
236 if (! ret)
237 {
238 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
239 return CMD_WARNING;
240 }
241 return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_normal, NULL, 0, use_json (argc, argv));
242}
243
244DEFUN (show_ip_bgp_l2vpn_evpn_all_tags,
245 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
246 "show [ip] bgp l2vpn evpn all tags",
247 SHOW_STR
248 IP_STR
249 BGP_STR
250 L2VPN_HELP_STR
251 EVPN_HELP_STR
252 "Display information about all EVPN NLRIs\n"
253 "Display BGP tags for prefixes\n")
254{
255 return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL, 1, 0);
256}
257
258DEFUN (show_ip_bgp_l2vpn_evpn_rd_tags,
259 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
260 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
261 SHOW_STR
262 IP_STR
263 BGP_STR
264 L2VPN_HELP_STR
265 EVPN_HELP_STR
266 "Display information for a route distinguisher\n"
267 "VPN Route Distinguisher\n"
268 "Display BGP tags for prefixes\n")
269{
270 int idx_ext_community = 6;
271 int ret;
272 struct prefix_rd prd;
273
274 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
275 if (! ret)
276 {
277 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
278 return CMD_WARNING;
279 }
280 return bgp_show_ethernet_vpn (vty,&prd, bgp_show_type_normal, NULL, 1, 0);
281}
282
283DEFUN (show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
284 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd,
285 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
286 SHOW_STR
287 IP_STR
288 BGP_STR
289 L2VPN_HELP_STR
290 EVPN_HELP_STR
291 "Display information about all EVPN NLRIs\n"
292 "Detailed information on TCP and BGP neighbor connections\n"
293 "Neighbor to display information about\n"
294 "Display routes learned from neighbor\n"
295 JSON_STR)
296{
297 int idx_ipv4 = 6;
298 union sockunion su;
299 struct peer *peer;
300 int ret;
301 u_char uj = use_json(argc, argv);
302
303 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
304 if (ret < 0)
305 {
306 if (uj)
307 {
308 json_object *json_no = NULL;
309 json_no = json_object_new_object();
310 json_object_string_add(json_no, "warning", "Malformed address");
311 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
312 json_object_free(json_no);
313 }
314 else
315 vty_out (vty, "Malformed address: %s%s", argv[idx_ipv4]->arg, VTY_NEWLINE);
316 return CMD_WARNING;
317 }
318
319 peer = peer_lookup (NULL, &su);
320 if (! peer || ! peer->afc[AFI_L2VPN][SAFI_EVPN])
321 {
322 if (uj)
323 {
324 json_object *json_no = NULL;
325 json_no = json_object_new_object();
326 json_object_string_add(json_no, "warning", "No such neighbor or address family");
327 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
328 json_object_free(json_no);
329 }
330 else
331 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
332 return CMD_WARNING;
333 }
334
335 return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_neighbor, &su, 0, uj);
336}
337
338DEFUN (show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
339 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
340 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
341 SHOW_STR
342 IP_STR
343 BGP_STR
344 L2VPN_HELP_STR
345 EVPN_HELP_STR
346 "Display information for a route distinguisher\n"
347 "VPN Route Distinguisher\n"
348 "Detailed information on TCP and BGP neighbor connections\n"
349 "Neighbor to display information about\n"
350 "Display routes learned from neighbor\n"
351 JSON_STR)
352{
353 int idx_ext_community = 6;
354 int idx_ipv4 = 8;
355 int ret;
356 union sockunion su;
357 struct peer *peer;
358 struct prefix_rd prd;
359 u_char uj = use_json(argc, argv);
360
361 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
362 if (! ret)
363 {
364 if (uj)
365 {
366 json_object *json_no = NULL;
367 json_no = json_object_new_object();
368 json_object_string_add(json_no, "warning", "Malformed Route Distinguisher");
369 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
370 json_object_free(json_no);
371 }
372 else
373 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
374 return CMD_WARNING;
375 }
376
377 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
378 if (ret < 0)
379 {
380 if (uj)
381 {
382 json_object *json_no = NULL;
383 json_no = json_object_new_object();
384 json_object_string_add(json_no, "warning", "Malformed address");
385 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
386 json_object_free(json_no);
387 }
388 else
389 vty_out (vty, "Malformed address: %s%s", argv[idx_ext_community]->arg, VTY_NEWLINE);
390 return CMD_WARNING;
391 }
392
393 peer = peer_lookup (NULL, &su);
394 if (! peer || ! peer->afc[AFI_L2VPN][SAFI_EVPN])
395 {
396 if (uj)
397 {
398 json_object *json_no = NULL;
399 json_no = json_object_new_object();
400 json_object_string_add(json_no, "warning", "No such neighbor or address family");
401 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
402 json_object_free(json_no);
403 }
404 else
405 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
406 return CMD_WARNING;
407 }
408
409 return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_neighbor, &su, 0, uj);
410}
411
412DEFUN (show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
413 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd,
414 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
415 SHOW_STR
416 IP_STR
417 BGP_STR
418 L2VPN_HELP_STR
419 EVPN_HELP_STR
420 "Display information about all EVPN NLRIs\n"
421 "Detailed information on TCP and BGP neighbor connections\n"
422 "Neighbor to display information about\n"
423 "Display the routes advertised to a BGP neighbor\n"
424 JSON_STR)
425{
426 int idx_ipv4 = 7;
427 int ret;
428 struct peer *peer;
429 union sockunion su;
430 u_char uj = use_json(argc, argv);
431
432 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
433 if (ret < 0)
434 {
435 if (uj)
436 {
437 json_object *json_no = NULL;
438 json_no = json_object_new_object();
439 json_object_string_add(json_no, "warning", "Malformed address");
440 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
441 json_object_free(json_no);
442 }
443 else
444 vty_out (vty, "Malformed address: %s%s", argv[idx_ipv4]->arg, VTY_NEWLINE);
445 return CMD_WARNING;
446 }
447 peer = peer_lookup (NULL, &su);
448 if (! peer || ! peer->afc[AFI_L2VPN][SAFI_EVPN])
449 {
450 if (uj)
451 {
452 json_object *json_no = NULL;
453 json_no = json_object_new_object();
454 json_object_string_add(json_no, "warning", "No such neighbor or address family");
455 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
456 json_object_free(json_no);
457 }
458 else
459 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
460 return CMD_WARNING;
461 }
462
463 return show_adj_route_vpn (vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
464}
465
466DEFUN (show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
467 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
468 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
469 SHOW_STR
470 IP_STR
471 BGP_STR
472 L2VPN_HELP_STR
473 EVPN_HELP_STR
474 "Display information for a route distinguisher\n"
475 "VPN Route Distinguisher\n"
476 "Detailed information on TCP and BGP neighbor connections\n"
477 "Neighbor to display information about\n"
478 "Display the routes advertised to a BGP neighbor\n"
479 JSON_STR)
480{
481 int idx_ext_community = 6;
482 int idx_ipv4 = 8;
483 int ret;
484 struct peer *peer;
485 struct prefix_rd prd;
486 union sockunion su;
487 u_char uj = use_json(argc, argv);
488
489 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
490 if (ret < 0)
491 {
492 if (uj)
493 {
494 json_object *json_no = NULL;
495 json_no = json_object_new_object();
496 json_object_string_add(json_no, "warning", "Malformed address");
497 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
498 json_object_free(json_no);
499 }
500 else
501 vty_out (vty, "Malformed address: %s%s", argv[idx_ext_community]->arg, VTY_NEWLINE);
502 return CMD_WARNING;
503 }
504 peer = peer_lookup (NULL, &su);
505 if (! peer || ! peer->afc[AFI_L2VPN][SAFI_EVPN])
506 {
507 if (uj)
508 {
509 json_object *json_no = NULL;
510 json_no = json_object_new_object();
511 json_object_string_add(json_no, "warning", "No such neighbor or address family");
512 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
513 json_object_free(json_no);
514 }
515 else
516 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
517 return CMD_WARNING;
518 }
519
520 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
521 if (! ret)
522 {
523 if (uj)
524 {
525 json_object *json_no = NULL;
526 json_no = json_object_new_object();
527 json_object_string_add(json_no, "warning", "Malformed Route Distinguisher");
528 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
529 json_object_free(json_no);
530 }
531 else
532 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
533 return CMD_WARNING;
534 }
535
536 return show_adj_route_vpn (vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
537}
538
539DEFUN (show_ip_bgp_l2vpn_evpn_all_overlay,
540 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
541 "show [ip] bgp l2vpn evpn all overlay",
542 SHOW_STR
543 IP_STR
544 BGP_STR
545 L2VPN_HELP_STR
546 EVPN_HELP_STR
547 "Display information about all EVPN NLRIs\n"
548 "Display BGP Overlay Information for prefixes\n")
549{
550 return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL,
551 SHOW_DISPLAY_OVERLAY, use_json (argc, argv));
552}
553
554DEFUN (show_ip_bgp_evpn_rd_overlay,
555 show_ip_bgp_evpn_rd_overlay_cmd,
556 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
557 SHOW_STR
558 IP_STR
559 BGP_STR
560 L2VPN_HELP_STR
561 EVPN_HELP_STR
562 "Display information for a route distinguisher\n"
563 "VPN Route Distinguisher\n"
564 "Display BGP Overlay Information for prefixes\n")
565{
566 int idx_ext_community = 6;
567 int ret;
568 struct prefix_rd prd;
569
570 ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd);
571 if (! ret)
572 {
573 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
574 return CMD_WARNING;
575 }
576 return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_normal, NULL,
577 SHOW_DISPLAY_OVERLAY, use_json (argc, argv));
578}
579
580
581void
582bgp_ethernetvpn_init (void)
583{
584 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
585 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
586 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
587 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
588 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
589 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
590 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
591 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
592 install_element (VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
593 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
594}