Coverage Report

Created: 2025-07-14 06:48

/src/frr/bgpd/bgp_evpn_vty.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* Ethernet-VPN Packet and vty Processing File
3
 * Copyright (C) 2017 6WIND
4
 *
5
 * This file is part of FRRouting
6
 */
7
8
#include <zebra.h>
9
#include "command.h"
10
#include "prefix.h"
11
#include "lib/json.h"
12
#include "lib/printfrr.h"
13
#include "lib/vxlan.h"
14
#include "stream.h"
15
16
#include "bgpd/bgpd.h"
17
#include "bgpd/bgp_table.h"
18
#include "bgpd/bgp_attr.h"
19
#include "bgpd/bgp_route.h"
20
#include "bgpd/bgp_mplsvpn.h"
21
#include "bgpd/bgp_vpn.h"
22
#include "bgpd/bgp_evpn_vty.h"
23
#include "bgpd/bgp_evpn.h"
24
#include "bgpd/bgp_evpn_private.h"
25
#include "bgpd/bgp_evpn_mh.h"
26
#include "bgpd/bgp_zebra.h"
27
#include "bgpd/bgp_vty.h"
28
#include "bgpd/bgp_errors.h"
29
#include "bgpd/bgp_ecommunity.h"
30
#include "bgpd/bgp_lcommunity.h"
31
#include "bgpd/bgp_community.h"
32
33
0
#define SHOW_DISPLAY_STANDARD 0
34
0
#define SHOW_DISPLAY_TAGS 1
35
0
#define SHOW_DISPLAY_OVERLAY 2
36
#define VNI_STR_LEN 32
37
38
/*
39
 * Context for VNI hash walk - used by callbacks.
40
 */
41
struct vni_walk_ctx {
42
  struct bgp *bgp;
43
  struct vty *vty;
44
  struct in_addr vtep_ip;
45
  json_object *json;
46
  int detail;
47
  int type;
48
  bool mac_table;
49
};
50
51
int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx,
52
        enum overlay_index_type *oly)
53
0
{
54
0
  *oly = OVERLAY_INDEX_TYPE_NONE;
55
0
  if (argv_find(argv, argc, "gateway-ip", oly_idx))
56
0
    *oly = OVERLAY_INDEX_GATEWAY_IP;
57
0
  return 1;
58
0
}
59
60
static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
61
          json_object *json)
62
0
{
63
0
  const uint8_t *pnt;
64
0
  uint8_t type, sub_type;
65
0
  struct ecommunity_as eas;
66
0
  struct ecommunity_ip eip;
67
0
  struct listnode *node, *nnode;
68
0
  struct bgp *tmp_bgp_vrf = NULL;
69
0
  json_object *json_rt = NULL;
70
0
  json_object *json_vrfs = NULL;
71
0
  char rt_buf[RT_ADDRSTRLEN];
72
73
0
  if (json) {
74
0
    json_rt = json_object_new_object();
75
0
    json_vrfs = json_object_new_array();
76
0
  }
77
78
0
  pnt = (uint8_t *)&irt->rt.val;
79
0
  type = *pnt++;
80
0
  sub_type = *pnt++;
81
0
  if (sub_type != ECOMMUNITY_ROUTE_TARGET)
82
0
    return;
83
84
0
  memset(&eas, 0, sizeof(eas));
85
0
  switch (type) {
86
0
  case ECOMMUNITY_ENCODE_AS:
87
0
    eas.as = (*pnt++ << 8);
88
0
    eas.as |= (*pnt++);
89
0
    ptr_get_be32(pnt, &eas.val);
90
91
0
    snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
92
93
0
    if (json)
94
0
      json_object_string_add(json_rt, "rt", rt_buf);
95
0
    else
96
0
      vty_out(vty, "Route-target: %s", rt_buf);
97
98
0
    break;
99
100
0
  case ECOMMUNITY_ENCODE_IP:
101
0
    memcpy(&eip.ip, pnt, 4);
102
0
    pnt += 4;
103
0
    eip.val = (*pnt++ << 8);
104
0
    eip.val |= (*pnt++);
105
106
0
    snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
107
108
0
    if (json)
109
0
      json_object_string_add(json_rt, "rt", rt_buf);
110
0
    else
111
0
      vty_out(vty, "Route-target: %s", rt_buf);
112
113
0
    break;
114
115
0
  case ECOMMUNITY_ENCODE_AS4:
116
0
    pnt = ptr_get_be32(pnt, &eas.val);
117
0
    eas.val = (*pnt++ << 8);
118
0
    eas.val |= (*pnt++);
119
120
0
    snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
121
122
0
    if (json)
123
0
      json_object_string_add(json_rt, "rt", rt_buf);
124
0
    else
125
0
      vty_out(vty, "Route-target: %s", rt_buf);
126
127
0
    break;
128
129
0
  default:
130
0
    return;
131
0
  }
132
133
0
  if (!json) {
134
0
    vty_out(vty,
135
0
      "\nList of VRFs importing routes with this route-target:\n");
136
0
  }
137
138
0
  for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
139
0
    if (json)
140
0
      json_object_array_add(
141
0
        json_vrfs,
142
0
        json_object_new_string(
143
0
          vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
144
0
    else
145
0
      vty_out(vty, "  %s\n",
146
0
        vrf_id_to_name(tmp_bgp_vrf->vrf_id));
147
0
  }
148
149
0
  if (json) {
150
0
    json_object_object_add(json_rt, "vrfs", json_vrfs);
151
0
    json_object_object_add(json, rt_buf, json_rt);
152
0
  }
153
0
}
154
155
static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
156
0
{
157
0
  json_object *json = NULL;
158
0
  struct vty *vty = NULL;
159
0
  struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
160
161
0
  vty = (struct vty *)args[0];
162
0
  json = (struct json_object *)args[1];
163
164
0
  display_vrf_import_rt(vty, irt, json);
165
0
}
166
167
static void display_import_rt(struct vty *vty, struct irt_node *irt,
168
            json_object *json)
169
0
{
170
0
  const uint8_t *pnt;
171
0
  uint8_t type, sub_type;
172
0
  struct ecommunity_as eas;
173
0
  struct ecommunity_ip eip;
174
0
  struct listnode *node, *nnode;
175
0
  struct bgpevpn *tmp_vpn;
176
0
  json_object *json_rt = NULL;
177
0
  json_object *json_vnis = NULL;
178
0
  char rt_buf[RT_ADDRSTRLEN];
179
180
0
  if (json) {
181
0
    json_rt = json_object_new_object();
182
0
    json_vnis = json_object_new_array();
183
0
  }
184
185
  /* TODO: This needs to go into a function */
186
187
0
  pnt = (uint8_t *)&irt->rt.val;
188
0
  type = *pnt++;
189
0
  sub_type = *pnt++;
190
0
  if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191
0
    return;
192
193
0
  memset(&eas, 0, sizeof(eas));
194
0
  switch (type) {
195
0
  case ECOMMUNITY_ENCODE_AS:
196
0
    eas.as = (*pnt++ << 8);
197
0
    eas.as |= (*pnt++);
198
0
    ptr_get_be32(pnt, &eas.val);
199
200
0
    snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
201
202
0
    if (json)
203
0
      json_object_string_add(json_rt, "rt", rt_buf);
204
0
    else
205
0
      vty_out(vty, "Route-target: %s", rt_buf);
206
207
0
    break;
208
209
0
  case ECOMMUNITY_ENCODE_IP:
210
0
    memcpy(&eip.ip, pnt, 4);
211
0
    pnt += 4;
212
0
    eip.val = (*pnt++ << 8);
213
0
    eip.val |= (*pnt++);
214
215
0
    snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
216
217
0
    if (json)
218
0
      json_object_string_add(json_rt, "rt", rt_buf);
219
0
    else
220
0
      vty_out(vty, "Route-target: %s", rt_buf);
221
222
0
    break;
223
224
0
  case ECOMMUNITY_ENCODE_AS4:
225
0
    pnt = ptr_get_be32(pnt, &eas.val);
226
0
    eas.val = (*pnt++ << 8);
227
0
    eas.val |= (*pnt++);
228
229
0
    snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
230
231
0
    if (json)
232
0
      json_object_string_add(json_rt, "rt", rt_buf);
233
0
    else
234
0
      vty_out(vty, "Route-target: %s", rt_buf);
235
236
0
    break;
237
238
0
  default:
239
0
    return;
240
0
  }
241
242
0
  if (!json) {
243
0
    vty_out(vty,
244
0
      "\nList of VNIs importing routes with this route-target:\n");
245
0
  }
246
247
0
  for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
248
0
    if (json)
249
0
      json_object_array_add(
250
0
        json_vnis, json_object_new_int(tmp_vpn->vni));
251
0
    else
252
0
      vty_out(vty, "  %u\n", tmp_vpn->vni);
253
0
  }
254
255
0
  if (json) {
256
0
    json_object_object_add(json_rt, "vnis", json_vnis);
257
0
    json_object_object_add(json, rt_buf, json_rt);
258
0
  }
259
0
}
260
261
static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
262
0
{
263
0
  json_object *json = NULL;
264
0
  struct vty *vty = NULL;
265
0
  struct irt_node *irt = (struct irt_node *)bucket->data;
266
267
0
  vty = args[0];
268
0
  json = args[1];
269
270
0
  display_import_rt(vty, irt, json);
271
272
0
  return;
273
0
}
274
275
static void bgp_evpn_show_route_rd_header(struct vty *vty,
276
            struct bgp_dest *rd_dest,
277
            json_object *json, char *rd_str,
278
            int len)
279
0
{
280
0
  uint16_t type;
281
0
  struct rd_as rd_as;
282
0
  struct rd_ip rd_ip;
283
0
  const uint8_t *pnt;
284
0
  const struct prefix *p = bgp_dest_get_prefix(rd_dest);
285
286
0
  pnt = p->u.val;
287
288
  /* Decode RD type. */
289
0
  type = decode_rd_type(pnt);
290
291
0
  if (!json)
292
0
    vty_out(vty, "Route Distinguisher: ");
293
294
0
  switch (type) {
295
0
  case RD_TYPE_AS:
296
0
    decode_rd_as(pnt + 2, &rd_as);
297
0
    snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
298
0
    if (json)
299
0
      json_object_string_add(json, "rd", rd_str);
300
0
    else
301
0
      vty_out(vty, "%s\n", rd_str);
302
0
    break;
303
304
0
  case RD_TYPE_AS4:
305
0
    decode_rd_as4(pnt + 2, &rd_as);
306
0
    snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
307
0
    if (json)
308
0
      json_object_string_add(json, "rd", rd_str);
309
0
    else
310
0
      vty_out(vty, "%s\n", rd_str);
311
0
    break;
312
313
0
  case RD_TYPE_IP:
314
0
    decode_rd_ip(pnt + 2, &rd_ip);
315
0
    snprintfrr(rd_str, len, "%pI4:%d", &rd_ip.ip, rd_ip.val);
316
0
    if (json)
317
0
      json_object_string_add(json, "rd", rd_str);
318
0
    else
319
0
      vty_out(vty, "%s\n", rd_str);
320
0
    break;
321
322
0
  default:
323
0
    if (json) {
324
0
      snprintf(rd_str, len, "Unknown");
325
0
      json_object_string_add(json, "rd", rd_str);
326
0
    } else {
327
0
      snprintf(rd_str, len, "Unknown RD type");
328
0
      vty_out(vty, "%s\n", rd_str);
329
0
    }
330
0
    break;
331
0
  }
332
0
}
333
334
static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
335
               uint64_t tbl_ver, json_object *json)
336
0
{
337
0
  char ri_header[] =
338
0
    "   Network          Next Hop            Metric LocPrf Weight Path\n";
339
340
0
  if (json)
341
0
    return;
342
343
0
  vty_out(vty,
344
0
    "BGP table version is %" PRIu64 ", local router ID is %pI4\n",
345
0
    tbl_ver, &bgp->router_id);
346
0
  vty_out(vty,
347
0
    "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
348
0
  vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
349
0
  vty_out(vty,
350
0
    "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
351
0
  vty_out(vty,
352
0
    "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
353
0
  vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
354
0
  vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
355
0
  vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
356
0
  vty_out(vty, "%s", ri_header);
357
0
}
358
359
static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
360
        json_object *json)
361
0
{
362
0
  char *ecom_str;
363
0
  struct listnode *node, *nnode;
364
0
  struct vrf_route_target *l3rt;
365
0
  json_object *json_import_rtl = NULL;
366
0
  json_object *json_export_rtl = NULL;
367
0
  char buf2[ETHER_ADDR_STRLEN];
368
369
0
  json_import_rtl = json_export_rtl = 0;
370
371
0
  if (json) {
372
0
    json_import_rtl = json_object_new_array();
373
0
    json_export_rtl = json_object_new_array();
374
0
    json_object_int_add(json, "vni", bgp_vrf->l3vni);
375
0
    json_object_string_add(json, "type", "L3");
376
0
    json_object_string_add(json, "inKernel", "True");
377
0
    json_object_string_addf(json, "rd",
378
0
          BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
379
0
          &bgp_vrf->vrf_prd);
380
0
    json_object_string_addf(json, "originatorIp", "%pI4",
381
0
          &bgp_vrf->originator_ip);
382
0
    json_object_string_add(json, "advertiseGatewayMacip", "n/a");
383
0
    json_object_string_add(json, "advertiseSviMacIp", "n/a");
384
0
    json_object_string_add(json, "advertisePip",
385
0
               bgp_vrf->evpn_info->advertise_pip ?
386
0
               "Enabled" : "Disabled");
387
0
    json_object_string_addf(json, "sysIP", "%pI4",
388
0
          &bgp_vrf->evpn_info->pip_ip);
389
0
    json_object_string_add(json, "sysMac",
390
0
        prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
391
0
                 buf2, sizeof(buf2)));
392
0
    json_object_string_add(json, "rmac",
393
0
        prefix_mac2str(&bgp_vrf->rmac,
394
0
                 buf2, sizeof(buf2)));
395
0
  } else {
396
0
    vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
397
0
    vty_out(vty, " (known to the kernel)");
398
0
    vty_out(vty, "\n");
399
400
0
    vty_out(vty, "  Type: %s\n", "L3");
401
0
    vty_out(vty, "  Tenant VRF: %s\n",
402
0
      vrf_id_to_name(bgp_vrf->vrf_id));
403
0
    vty_out(vty, "  RD: ");
404
0
    vty_out(vty, BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
405
0
      &bgp_vrf->vrf_prd);
406
0
    vty_out(vty, "\n");
407
0
    vty_out(vty, "  Originator IP: %pI4\n",
408
0
      &bgp_vrf->originator_ip);
409
0
    vty_out(vty, "  Advertise-gw-macip : %s\n", "n/a");
410
0
    vty_out(vty, "  Advertise-svi-macip : %s\n", "n/a");
411
0
    vty_out(vty, "  Advertise-pip: %s\n",
412
0
      bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
413
0
    vty_out(vty, "  System-IP: %pI4\n",
414
0
      &bgp_vrf->evpn_info->pip_ip);
415
0
    vty_out(vty, "  System-MAC: %s\n",
416
0
        prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
417
0
                 buf2, sizeof(buf2)));
418
0
    vty_out(vty, "  Router-MAC: %s\n",
419
0
        prefix_mac2str(&bgp_vrf->rmac,
420
0
                 buf2, sizeof(buf2)));
421
0
  }
422
423
0
  if (!json)
424
0
    vty_out(vty, "  Import Route Target:\n");
425
426
0
  for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt)) {
427
0
    ecom_str = ecommunity_ecom2str(l3rt->ecom,
428
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
429
430
0
    if (json)
431
0
      json_object_array_add(json_import_rtl,
432
0
                json_object_new_string(ecom_str));
433
0
    else
434
0
      vty_out(vty, "    %s\n", ecom_str);
435
436
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
437
0
  }
438
439
0
  if (json)
440
0
    json_object_object_add(json, "importRts", json_import_rtl);
441
0
  else
442
0
    vty_out(vty, "  Export Route Target:\n");
443
444
0
  for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, l3rt)) {
445
0
    ecom_str = ecommunity_ecom2str(l3rt->ecom,
446
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
447
448
0
    if (json)
449
0
      json_object_array_add(json_export_rtl,
450
0
                json_object_new_string(ecom_str));
451
0
    else
452
0
      vty_out(vty, "    %s\n", ecom_str);
453
454
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
455
0
  }
456
457
0
  if (json)
458
0
    json_object_object_add(json, "exportRts", json_export_rtl);
459
0
}
460
461
static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
462
0
{
463
0
  char *ecom_str;
464
0
  struct listnode *node, *nnode;
465
0
  struct ecommunity *ecom;
466
0
  json_object *json_import_rtl = NULL;
467
0
  json_object *json_export_rtl = NULL;
468
0
  struct bgp *bgp_evpn;
469
0
  enum asnotation_mode asnotation;
470
471
0
  bgp_evpn = bgp_get_evpn();
472
0
  asnotation = bgp_get_asnotation(bgp_evpn);
473
474
0
  if (json) {
475
0
    json_import_rtl = json_object_new_array();
476
0
    json_export_rtl = json_object_new_array();
477
0
    json_object_int_add(json, "vni", vpn->vni);
478
0
    json_object_string_add(json, "type", "L2");
479
0
    json_object_string_add(json, "inKernel",
480
0
               is_vni_live(vpn) ? "True" : "False");
481
0
    json_object_string_addf(
482
0
      json, "rd", BGP_RD_AS_FORMAT(asnotation), &vpn->prd);
483
0
    json_object_string_addf(json, "originatorIp", "%pI4",
484
0
          &vpn->originator_ip);
485
0
    json_object_string_addf(json, "mcastGroup", "%pI4",
486
0
          &vpn->mcast_grp);
487
    /* per vni knob is enabled -- Enabled
488
     * Global knob is enabled  -- Active
489
     * default  -- Disabled
490
     */
491
0
    if (!vpn->advertise_gw_macip &&
492
0
        bgp_evpn && bgp_evpn->advertise_gw_macip)
493
0
      json_object_string_add(json, "advertiseGatewayMacip",
494
0
                 "Active");
495
0
    else if (vpn->advertise_gw_macip)
496
0
      json_object_string_add(json, "advertiseGatewayMacip",
497
0
                 "Enabled");
498
0
    else
499
0
      json_object_string_add(json, "advertiseGatewayMacip",
500
0
                 "Disabled");
501
0
    if (!vpn->advertise_svi_macip && bgp_evpn &&
502
0
        bgp_evpn->evpn_info->advertise_svi_macip)
503
0
      json_object_string_add(json, "advertiseSviMacIp",
504
0
                 "Active");
505
0
    else if (vpn->advertise_svi_macip)
506
0
      json_object_string_add(json, "advertiseSviMacIp",
507
0
                 "Enabled");
508
0
    else
509
0
      json_object_string_add(json, "advertiseSviMacIp",
510
0
                 "Disabled");
511
0
    json_object_string_add(
512
0
      json, "sviInterface",
513
0
      ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
514
0
  } else {
515
0
    vty_out(vty, "VNI: %u", vpn->vni);
516
0
    if (is_vni_live(vpn))
517
0
      vty_out(vty, " (known to the kernel)");
518
0
    vty_out(vty, "\n");
519
520
0
    vty_out(vty, "  Type: %s\n", "L2");
521
0
    vty_out(vty, "  Tenant-Vrf: %s\n",
522
0
      vrf_id_to_name(vpn->tenant_vrf_id));
523
0
    vty_out(vty, "  RD: ");
524
0
    vty_out(vty, BGP_RD_AS_FORMAT(asnotation), &vpn->prd);
525
0
    vty_out(vty, "\n");
526
0
    vty_out(vty, "  Originator IP: %pI4\n", &vpn->originator_ip);
527
0
    vty_out(vty, "  Mcast group: %pI4\n", &vpn->mcast_grp);
528
0
    if (!vpn->advertise_gw_macip &&
529
0
        bgp_evpn && bgp_evpn->advertise_gw_macip)
530
0
      vty_out(vty, "  Advertise-gw-macip : %s\n",
531
0
        "Active");
532
0
    else if (vpn->advertise_gw_macip)
533
0
      vty_out(vty, "  Advertise-gw-macip : %s\n",
534
0
        "Enabled");
535
0
    else
536
0
      vty_out(vty, "  Advertise-gw-macip : %s\n",
537
0
        "Disabled");
538
0
    if (!vpn->advertise_svi_macip && bgp_evpn &&
539
0
        bgp_evpn->evpn_info->advertise_svi_macip)
540
0
      vty_out(vty, "  Advertise-svi-macip : %s\n",
541
0
        "Active");
542
0
    else if (vpn->advertise_svi_macip)
543
0
      vty_out(vty, "  Advertise-svi-macip : %s\n",
544
0
        "Enabled");
545
0
    else
546
0
      vty_out(vty, "  Advertise-svi-macip : %s\n",
547
0
        "Disabled");
548
0
    vty_out(vty, "  SVI interface : %s\n",
549
0
      ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
550
0
  }
551
552
0
  if (!json)
553
0
    vty_out(vty, "  Import Route Target:\n");
554
555
0
  for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
556
0
    ecom_str = ecommunity_ecom2str(ecom,
557
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
558
559
0
    if (json)
560
0
      json_object_array_add(json_import_rtl,
561
0
                json_object_new_string(ecom_str));
562
0
    else
563
0
      vty_out(vty, "    %s\n", ecom_str);
564
565
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
566
0
  }
567
568
0
  if (json)
569
0
    json_object_object_add(json, "importRts", json_import_rtl);
570
0
  else
571
0
    vty_out(vty, "  Export Route Target:\n");
572
573
0
  for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
574
0
    ecom_str = ecommunity_ecom2str(ecom,
575
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
576
577
0
    if (json)
578
0
      json_object_array_add(json_export_rtl,
579
0
                json_object_new_string(ecom_str));
580
0
    else
581
0
      vty_out(vty, "    %s\n", ecom_str);
582
583
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
584
0
  }
585
586
0
  if (json)
587
0
    json_object_object_add(json, "exportRts", json_export_rtl);
588
0
}
589
590
static void show_esi_routes(struct bgp *bgp,
591
          struct bgp_evpn_es *es,
592
          struct vty *vty,
593
          json_object *json)
594
0
{
595
0
  int header = 1;
596
0
  struct bgp_dest *dest;
597
0
  struct bgp_path_info *pi;
598
0
  uint32_t prefix_cnt, path_cnt;
599
0
  uint64_t tbl_ver;
600
601
0
  prefix_cnt = path_cnt = 0;
602
603
0
  tbl_ver = es->route_table->version;
604
0
  for (dest = bgp_table_top(es->route_table); dest;
605
0
       dest = bgp_route_next(dest)) {
606
0
    int add_prefix_to_json = 0;
607
0
    json_object *json_paths = NULL;
608
0
    json_object *json_prefix = NULL;
609
0
    const struct prefix *p = bgp_dest_get_prefix(dest);
610
611
0
    if (json)
612
0
      json_prefix = json_object_new_object();
613
614
0
    pi = bgp_dest_get_bgp_path_info(dest);
615
0
    if (pi) {
616
      /* Overall header/legend displayed once. */
617
0
      if (header) {
618
0
        bgp_evpn_show_route_header(vty, bgp,
619
0
                 tbl_ver, json);
620
0
        header = 0;
621
0
      }
622
623
0
      prefix_cnt++;
624
0
    }
625
626
0
    if (json)
627
0
      json_paths = json_object_new_array();
628
629
    /* For EVPN, the prefix is displayed for each path (to fit in
630
     * with code that already exists).
631
     */
632
0
    for (; pi; pi = pi->next) {
633
0
      json_object *json_path = NULL;
634
635
0
      if (json)
636
0
        json_path = json_object_new_array();
637
638
0
      route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path,
639
0
              false);
640
641
0
      if (json)
642
0
        json_object_array_add(json_paths, json_path);
643
644
0
      path_cnt++;
645
0
      add_prefix_to_json = 1;
646
0
    }
647
648
0
    if (json) {
649
0
      if (add_prefix_to_json) {
650
0
        json_object_string_addf(json_prefix, "prefix",
651
0
              "%pFX", p);
652
0
        json_object_int_add(json_prefix, "prefixLen",
653
0
                p->prefixlen);
654
0
        json_object_object_add(json_prefix, "paths",
655
0
                   json_paths);
656
0
        json_object_object_addf(json, json_prefix,
657
0
              "%pFX", p);
658
0
      } else {
659
0
        json_object_free(json_paths);
660
0
        json_object_free(json_prefix);
661
0
        json_paths = NULL;
662
0
        json_prefix = NULL;
663
0
      }
664
0
    }
665
0
  }
666
667
0
  if (json) {
668
0
    json_object_int_add(json, "numPrefix", prefix_cnt);
669
0
    json_object_int_add(json, "numPaths", path_cnt);
670
0
  } else {
671
0
    if (prefix_cnt == 0)
672
0
      vty_out(vty, "No EVPN prefixes exist for this ESI\n");
673
0
    else
674
0
      vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
675
0
        prefix_cnt, path_cnt);
676
0
  }
677
0
}
678
679
/* Display all MAC-IP VNI routes linked to an ES */
680
static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,
681
             json_object *json, int detail,
682
             bool global_table)
683
0
{
684
0
  struct bgp_node *rn;
685
0
  struct bgp_path_info *pi;
686
0
  int header = detail ? 0 : 1;
687
0
  uint32_t path_cnt;
688
0
  struct listnode *node;
689
0
  struct bgp_evpn_es *es;
690
0
  struct bgp_path_es_info *es_info;
691
0
  struct bgp *bgp = bgp_get_evpn();
692
0
  json_object *json_paths = NULL;
693
694
0
  if (!bgp)
695
0
    return;
696
697
0
  path_cnt = 0;
698
699
0
  if (json)
700
0
    json_paths = json_object_new_array();
701
702
0
  RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
703
0
    struct list *es_list;
704
705
0
    if (esi && memcmp(esi, &es->esi, sizeof(*esi)))
706
0
      continue;
707
708
0
    if (global_table)
709
0
      es_list = es->macip_global_path_list;
710
0
    else
711
0
      es_list = es->macip_evi_path_list;
712
713
0
    for (ALL_LIST_ELEMENTS_RO(es_list, node, es_info)) {
714
0
      json_object *json_path = NULL;
715
716
0
      pi = es_info->pi;
717
0
      rn = pi->net;
718
719
0
      if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
720
0
        continue;
721
722
      /* Overall header/legend displayed once. */
723
0
      if (header) {
724
0
        bgp_evpn_show_route_header(vty, bgp, 0, json);
725
0
        header = 0;
726
0
      }
727
728
0
      path_cnt++;
729
730
0
      if (json)
731
0
        json_path = json_object_new_array();
732
733
0
      if (detail)
734
0
        route_vty_out_detail(
735
0
          vty, bgp, rn, bgp_dest_get_prefix(rn),
736
0
          pi, AFI_L2VPN, SAFI_EVPN,
737
0
          RPKI_NOT_BEING_USED, json_path);
738
0
      else
739
0
        route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
740
0
                json_path, false);
741
742
0
      if (json)
743
0
        json_object_array_add(json_paths, json_path);
744
0
    }
745
0
  }
746
747
0
  if (json) {
748
0
    json_object_object_add(json, "paths", json_paths);
749
0
    json_object_int_add(json, "numPaths", path_cnt);
750
0
  } else {
751
0
    if (path_cnt == 0)
752
0
      vty_out(vty, "There are no MAC-IP ES paths");
753
0
    else
754
0
      vty_out(vty, "\nDisplayed %u paths\n", path_cnt);
755
0
    vty_out(vty, "\n");
756
0
  }
757
0
}
758
759
static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi,
760
                 json_object *json, int detail)
761
0
{
762
0
  bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, false);
763
0
}
764
765
static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi,
766
              json_object *json, int detail)
767
0
{
768
0
  bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true);
769
0
}
770
771
static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn,
772
          struct vty *vty, int type, bool mac_table,
773
          struct in_addr vtep_ip, json_object *json,
774
          int detail)
775
0
{
776
0
  struct bgp_dest *dest;
777
0
  struct bgp_path_info *pi;
778
0
  struct bgp_table *table;
779
0
  int header = detail ? 0 : 1;
780
0
  uint64_t tbl_ver;
781
0
  uint32_t prefix_cnt, path_cnt;
782
783
0
  prefix_cnt = path_cnt = 0;
784
785
0
  if (mac_table)
786
0
    table = vpn->mac_table;
787
0
  else
788
0
    table = vpn->ip_table;
789
790
0
  tbl_ver = table->version;
791
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
792
0
    const struct prefix_evpn *evp =
793
0
      (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
794
0
    int add_prefix_to_json = 0;
795
0
    json_object *json_paths = NULL;
796
0
    json_object *json_prefix = NULL;
797
0
    const struct prefix *p = bgp_dest_get_prefix(dest);
798
799
0
    if (type && evp->prefix.route_type != type)
800
0
      continue;
801
802
0
    if (json)
803
0
      json_prefix = json_object_new_object();
804
805
0
    pi = bgp_dest_get_bgp_path_info(dest);
806
0
    if (pi) {
807
      /* Overall header/legend displayed once. */
808
0
      if (header) {
809
0
        bgp_evpn_show_route_header(vty, bgp,
810
0
                 tbl_ver, json);
811
0
        header = 0;
812
0
      }
813
814
0
      prefix_cnt++;
815
0
    }
816
817
0
    if (json)
818
0
      json_paths = json_object_new_array();
819
820
    /* For EVPN, the prefix is displayed for each path (to fit in
821
     * with code that already exists).
822
     */
823
0
    for (; pi; pi = pi->next) {
824
0
      struct prefix tmp_p;
825
0
      json_object *json_path = NULL;
826
827
0
      if (vtep_ip.s_addr != INADDR_ANY
828
0
          && !IPV4_ADDR_SAME(&(vtep_ip),
829
0
                 &(pi->attr->nexthop)))
830
0
        continue;
831
832
0
      if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
833
        /*
834
         * VNI IP/MAC table prefixes don't have MAC/IP
835
         * respectively so make sure it's set from path
836
         * info here.
837
         */
838
0
        if (is_evpn_prefix_ipaddr_none(evp)) {
839
          /* VNI MAC -> Global */
840
0
          evpn_type2_prefix_global_copy(
841
0
            (struct prefix_evpn *)&tmp_p,
842
0
            evp, NULL /* mac */,
843
0
            evpn_type2_path_info_get_ip(
844
0
              pi));
845
0
        } else {
846
          /* VNI IP -> Global */
847
0
          evpn_type2_prefix_global_copy(
848
0
            (struct prefix_evpn *)&tmp_p,
849
0
            evp,
850
0
            evpn_type2_path_info_get_mac(
851
0
              pi),
852
0
            NULL /* ip */);
853
0
        }
854
0
      } else
855
0
        memcpy(&tmp_p, p, sizeof(tmp_p));
856
857
858
0
      if (json)
859
0
        json_path = json_object_new_array();
860
861
0
      if (detail)
862
0
        route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,
863
0
                 AFI_L2VPN, SAFI_EVPN,
864
0
                 RPKI_NOT_BEING_USED,
865
0
                 json_path);
866
867
0
      else
868
0
        route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,
869
0
                json_path, false);
870
871
0
      if (json)
872
0
        json_object_array_add(json_paths, json_path);
873
874
0
      path_cnt++;
875
0
      add_prefix_to_json = 1;
876
0
    }
877
878
0
    if (json) {
879
0
      if (add_prefix_to_json) {
880
0
        json_object_string_addf(json_prefix, "prefix",
881
0
              "%pFX", p);
882
0
        json_object_int_add(json_prefix, "prefixLen",
883
0
                p->prefixlen);
884
0
        json_object_object_add(json_prefix, "paths",
885
0
                   json_paths);
886
0
        json_object_object_addf(json, json_prefix,
887
0
              "%pFX", p);
888
0
      } else {
889
0
        json_object_free(json_paths);
890
0
        json_object_free(json_prefix);
891
0
        json_paths = NULL;
892
0
        json_prefix = NULL;
893
0
      }
894
0
    }
895
0
  }
896
897
0
  if (json) {
898
0
    json_object_int_add(json, "numPrefix", prefix_cnt);
899
0
    json_object_int_add(json, "numPaths", path_cnt);
900
0
  } else {
901
0
    if (prefix_cnt == 0)
902
0
      vty_out(vty, "No EVPN prefixes %sexist for this VNI",
903
0
        type ? "(of requested type) " : "");
904
0
    else
905
0
      vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
906
0
        prefix_cnt, path_cnt,
907
0
        type ? " (of requested type)" : "");
908
0
    vty_out(vty, "\n");
909
0
  }
910
0
}
911
912
static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
913
0
{
914
0
  struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
915
0
  struct vni_walk_ctx *wctx = arg;
916
0
  struct vty *vty = wctx->vty;
917
0
  json_object *json = wctx->json;
918
0
  json_object *json_vni = NULL;
919
0
  char vni_str[VNI_STR_LEN];
920
921
0
  snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
922
0
  if (json) {
923
0
    json_vni = json_object_new_object();
924
0
    json_object_int_add(json_vni, "vni", vpn->vni);
925
0
  } else {
926
0
    vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
927
0
  }
928
929
0
  show_vni_routes(wctx->bgp, vpn, wctx->vty, wctx->type, wctx->mac_table,
930
0
      wctx->vtep_ip, json_vni, wctx->detail);
931
932
0
  if (json)
933
0
    json_object_object_add(json, vni_str, json_vni);
934
0
}
935
936
static void show_vni_routes_all_hash(struct hash_bucket *bucket, void *arg)
937
0
{
938
0
  struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
939
0
  struct vni_walk_ctx *wctx = arg;
940
0
  struct vty *vty = wctx->vty;
941
0
  json_object *json = wctx->json;
942
0
  json_object *json_vni = NULL;
943
0
  json_object *json_vni_mac = NULL;
944
0
  char vni_str[VNI_STR_LEN];
945
946
0
  snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
947
0
  if (json) {
948
0
    json_vni = json_object_new_object();
949
0
    json_object_int_add(json_vni, "vni", vpn->vni);
950
0
  } else {
951
0
    vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
952
0
  }
953
954
0
  show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, false, wctx->vtep_ip,
955
0
      json_vni, wctx->detail);
956
957
0
  if (json)
958
0
    json_object_object_add(json, vni_str, json_vni);
959
960
0
  if (json)
961
0
    json_vni_mac = json_object_new_object();
962
0
  else
963
0
    vty_out(vty, "\nVNI: %u MAC Table\n\n", vpn->vni);
964
965
0
  show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, true, wctx->vtep_ip,
966
0
      json_vni_mac, wctx->detail);
967
968
0
  if (json)
969
0
    json_object_object_add(json_vni, "macTable", json_vni_mac);
970
0
}
971
972
static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
973
           json_object *json)
974
0
{
975
0
  json_object *json_vni = NULL;
976
0
  json_object *json_import_rtl = NULL;
977
0
  json_object *json_export_rtl = NULL;
978
0
  char buf1[10];
979
0
  char buf2[INET6_ADDRSTRLEN];
980
0
  char rt_buf[25];
981
0
  char *ecom_str;
982
0
  struct listnode *node, *nnode;
983
0
  struct vrf_route_target *l3rt;
984
985
0
  if (!bgp->l3vni)
986
0
    return;
987
988
0
  if (json) {
989
0
    json_vni = json_object_new_object();
990
0
    json_import_rtl = json_object_new_array();
991
0
    json_export_rtl = json_object_new_array();
992
0
  }
993
994
  /* if an l3vni is present in bgp it is live */
995
0
  buf1[0] = '\0';
996
0
  snprintf(buf1, sizeof(buf1), "*");
997
998
0
  if (json) {
999
0
    json_object_int_add(json_vni, "vni", bgp->l3vni);
1000
0
    json_object_string_add(json_vni, "type", "L3");
1001
0
    json_object_string_add(json_vni, "inKernel", "True");
1002
0
    json_object_string_addf(json_vni, "originatorIp", "%pI4",
1003
0
          &bgp->originator_ip);
1004
0
    json_object_string_addf(json_vni, "rd",
1005
0
          BGP_RD_AS_FORMAT(bgp->asnotation),
1006
0
          &bgp->vrf_prd);
1007
0
    json_object_string_add(json_vni, "advertiseGatewayMacip",
1008
0
               "n/a");
1009
0
    json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
1010
0
    json_object_string_add(
1011
0
      json_vni, "advertisePip",
1012
0
      bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
1013
0
    json_object_string_addf(json_vni, "sysIP", "%pI4",
1014
0
          &bgp->evpn_info->pip_ip);
1015
0
    json_object_string_add(json_vni, "sysMAC",
1016
0
               prefix_mac2str(&bgp->evpn_info->pip_rmac,
1017
0
                  buf2, sizeof(buf2)));
1018
0
    json_object_string_add(
1019
0
      json_vni, "rmac",
1020
0
      prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
1021
0
  } else {
1022
0
    vty_out(vty, "%-1s %-10u %-4s ", buf1, bgp->l3vni, "L3");
1023
0
    vty_out(vty, BGP_RD_AS_FORMAT_SPACE(bgp->asnotation),
1024
0
      &bgp->vrf_prd);
1025
0
  }
1026
1027
0
  for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, l3rt)) {
1028
0
    ecom_str = ecommunity_ecom2str(l3rt->ecom,
1029
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1030
1031
0
    if (json) {
1032
0
      json_object_array_add(json_import_rtl,
1033
0
                json_object_new_string(ecom_str));
1034
0
    } else {
1035
0
      if (listcount(bgp->vrf_import_rtl) > 1)
1036
0
        snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1037
0
           ecom_str);
1038
0
      else
1039
0
        snprintf(rt_buf, sizeof(rt_buf), "%s",
1040
0
           ecom_str);
1041
0
      vty_out(vty, " %-25s", rt_buf);
1042
0
    }
1043
1044
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1045
1046
    /* If there are multiple import RTs we break here and show only
1047
     * one */
1048
0
    if (!json)
1049
0
      break;
1050
0
  }
1051
1052
0
  if (json)
1053
0
    json_object_object_add(json_vni, "importRTs", json_import_rtl);
1054
1055
0
  for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, l3rt)) {
1056
0
    ecom_str = ecommunity_ecom2str(l3rt->ecom,
1057
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1058
1059
0
    if (json) {
1060
0
      json_object_array_add(json_export_rtl,
1061
0
                json_object_new_string(ecom_str));
1062
0
    } else {
1063
0
      if (listcount(bgp->vrf_export_rtl) > 1)
1064
0
        snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1065
0
           ecom_str);
1066
0
      else
1067
0
        snprintf(rt_buf, sizeof(rt_buf), "%s",
1068
0
           ecom_str);
1069
0
      vty_out(vty, " %-25s", rt_buf);
1070
0
    }
1071
1072
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1073
1074
    /* If there are multiple export RTs we break here and show only
1075
     * one */
1076
0
    if (!json) {
1077
0
      vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
1078
0
      break;
1079
0
    }
1080
0
  }
1081
1082
0
  if (json) {
1083
0
    char vni_str[VNI_STR_LEN];
1084
1085
0
    json_object_object_add(json_vni, "exportRTs", json_export_rtl);
1086
0
    snprintf(vni_str, sizeof(vni_str), "%u", bgp->l3vni);
1087
0
    json_object_object_add(json, vni_str, json_vni);
1088
0
  } else {
1089
0
    vty_out(vty, "\n");
1090
0
  }
1091
0
}
1092
1093
static void show_vni_entry(struct hash_bucket *bucket, void *args[])
1094
0
{
1095
0
  struct vty *vty;
1096
0
  json_object *json;
1097
0
  json_object *json_vni = NULL;
1098
0
  json_object *json_import_rtl = NULL;
1099
0
  json_object *json_export_rtl = NULL;
1100
0
  struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
1101
0
  char buf1[10];
1102
0
  char rt_buf[25];
1103
0
  char *ecom_str;
1104
0
  struct listnode *node, *nnode;
1105
0
  struct ecommunity *ecom;
1106
0
  struct bgp *bgp_evpn;
1107
0
  enum asnotation_mode asnotation;
1108
1109
0
  vty = args[0];
1110
0
  json = args[1];
1111
1112
0
  bgp_evpn = bgp_get_evpn();
1113
0
  asnotation = bgp_get_asnotation(bgp_evpn);
1114
1115
0
  if (json) {
1116
0
    json_vni = json_object_new_object();
1117
0
    json_import_rtl = json_object_new_array();
1118
0
    json_export_rtl = json_object_new_array();
1119
0
  }
1120
1121
0
  buf1[0] = '\0';
1122
0
  if (is_vni_live(vpn))
1123
0
    snprintf(buf1, sizeof(buf1), "*");
1124
1125
0
  if (json) {
1126
0
    json_object_int_add(json_vni, "vni", vpn->vni);
1127
0
    json_object_string_add(json_vni, "type", "L2");
1128
0
    json_object_string_add(json_vni, "inKernel",
1129
0
               is_vni_live(vpn) ? "True" : "False");
1130
0
    json_object_string_addf(json_vni, "rd",
1131
0
          BGP_RD_AS_FORMAT(asnotation),
1132
0
          &vpn->prd);
1133
0
    json_object_string_addf(json_vni, "originatorIp", "%pI4",
1134
0
          &vpn->originator_ip);
1135
0
    json_object_string_addf(json_vni, "mcastGroup", "%pI4",
1136
0
          &vpn->mcast_grp);
1137
    /* per vni knob is enabled -- Enabled
1138
     * Global knob is enabled  -- Active
1139
     * default  -- Disabled
1140
     */
1141
0
    if (!vpn->advertise_gw_macip && bgp_evpn
1142
0
        && bgp_evpn->advertise_gw_macip)
1143
0
      json_object_string_add(
1144
0
        json_vni, "advertiseGatewayMacip", "Active");
1145
0
    else if (vpn->advertise_gw_macip)
1146
0
      json_object_string_add(
1147
0
        json_vni, "advertiseGatewayMacip", "Enabled");
1148
0
    else
1149
0
      json_object_string_add(
1150
0
        json_vni, "advertiseGatewayMacip", "Disabled");
1151
0
    if (!vpn->advertise_svi_macip && bgp_evpn
1152
0
        && bgp_evpn->evpn_info->advertise_svi_macip)
1153
0
      json_object_string_add(json_vni, "advertiseSviMacIp",
1154
0
                 "Active");
1155
0
    else if (vpn->advertise_svi_macip)
1156
0
      json_object_string_add(json_vni, "advertiseSviMacIp",
1157
0
                 "Enabled");
1158
0
    else
1159
0
      json_object_string_add(json_vni, "advertiseSviMacIp",
1160
0
                 "Disabled");
1161
0
  } else {
1162
0
    vty_out(vty, "%-1s %-10u %-4s ", buf1, vpn->vni, "L2");
1163
0
    vty_out(vty, BGP_RD_AS_FORMAT_SPACE(asnotation), &vpn->prd);
1164
0
  }
1165
1166
0
  for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1167
0
    ecom_str = ecommunity_ecom2str(ecom,
1168
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1169
1170
0
    if (json) {
1171
0
      json_object_array_add(json_import_rtl,
1172
0
                json_object_new_string(ecom_str));
1173
0
    } else {
1174
0
      if (listcount(vpn->import_rtl) > 1)
1175
0
        snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1176
0
           ecom_str);
1177
0
      else
1178
0
        snprintf(rt_buf, sizeof(rt_buf), "%s",
1179
0
           ecom_str);
1180
0
      vty_out(vty, " %-25s", rt_buf);
1181
0
    }
1182
1183
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1184
1185
    /* If there are multiple import RTs we break here and show only
1186
     * one */
1187
0
    if (!json)
1188
0
      break;
1189
0
  }
1190
1191
0
  if (json)
1192
0
    json_object_object_add(json_vni, "importRTs", json_import_rtl);
1193
1194
0
  for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1195
0
    ecom_str = ecommunity_ecom2str(ecom,
1196
0
                 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1197
1198
0
    if (json) {
1199
0
      json_object_array_add(json_export_rtl,
1200
0
                json_object_new_string(ecom_str));
1201
0
    } else {
1202
0
      if (listcount(vpn->export_rtl) > 1)
1203
0
        snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1204
0
           ecom_str);
1205
0
      else
1206
0
        snprintf(rt_buf, sizeof(rt_buf), "%s",
1207
0
           ecom_str);
1208
0
      vty_out(vty, " %-25s", rt_buf);
1209
0
    }
1210
1211
0
    XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1212
1213
    /* If there are multiple export RTs we break here and show only
1214
     * one */
1215
0
    if (!json) {
1216
0
      vty_out(vty, "%-37s",
1217
0
        vrf_id_to_name(vpn->tenant_vrf_id));
1218
0
      break;
1219
0
    }
1220
0
  }
1221
1222
0
  if (json) {
1223
0
    char vni_str[VNI_STR_LEN];
1224
1225
0
    json_object_object_add(json_vni, "exportRTs", json_export_rtl);
1226
0
    snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
1227
0
    json_object_object_add(json, vni_str, json_vni);
1228
0
  } else {
1229
0
    vty_out(vty, "\n");
1230
0
  }
1231
0
}
1232
1233
static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1234
         enum bgp_show_type type, void *output_arg,
1235
         int option, bool use_json)
1236
0
{
1237
0
  afi_t afi = AFI_L2VPN;
1238
0
  struct bgp *bgp;
1239
0
  struct bgp_table *table;
1240
0
  struct bgp_dest *dest;
1241
0
  struct bgp_dest *rm;
1242
0
  struct bgp_path_info *pi;
1243
0
  int rd_header;
1244
0
  int header = 1;
1245
0
  char rd_str[RD_ADDRSTRLEN];
1246
0
  int no_display;
1247
1248
0
  unsigned long output_count = 0;
1249
0
  unsigned long total_count = 0;
1250
0
  json_object *json = NULL;
1251
0
  json_object *json_array = NULL;
1252
0
  json_object *json_prefix_info = NULL;
1253
1254
0
  memset(rd_str, 0, RD_ADDRSTRLEN);
1255
1256
0
  bgp = bgp_get_evpn();
1257
0
  if (bgp == NULL) {
1258
0
    if (!use_json)
1259
0
      vty_out(vty, "No BGP process is configured\n");
1260
0
    else
1261
0
      vty_out(vty, "{}\n");
1262
0
    return CMD_WARNING;
1263
0
  }
1264
1265
0
  if (use_json)
1266
0
    json = json_object_new_object();
1267
1268
0
  for (dest = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); dest;
1269
0
       dest = bgp_route_next(dest)) {
1270
0
    uint64_t tbl_ver;
1271
0
    json_object *json_nroute = NULL;
1272
0
    const struct prefix *p = bgp_dest_get_prefix(dest);
1273
1274
0
    if (prd && memcmp(p->u.val, prd->val, 8) != 0)
1275
0
      continue;
1276
1277
0
    table = bgp_dest_get_bgp_table_info(dest);
1278
0
    if (!table)
1279
0
      continue;
1280
1281
0
    rd_header = 1;
1282
0
    tbl_ver = table->version;
1283
1284
0
    for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
1285
0
      pi = bgp_dest_get_bgp_path_info(rm);
1286
0
      if (pi == NULL)
1287
0
        continue;
1288
1289
0
      no_display = 0;
1290
0
      for (; pi; pi = pi->next) {
1291
0
        struct community *picomm = NULL;
1292
1293
0
        picomm = bgp_attr_get_community(pi->attr);
1294
1295
0
        total_count++;
1296
0
        if (type == bgp_show_type_neighbor) {
1297
0
                struct peer *peer = output_arg;
1298
1299
0
          if (peer_cmp(peer, pi->peer) != 0)
1300
0
            continue;
1301
0
        }
1302
0
        if (type == bgp_show_type_lcommunity_exact) {
1303
0
          struct lcommunity *lcom = output_arg;
1304
1305
0
          if (!bgp_attr_get_lcommunity(
1306
0
                pi->attr) ||
1307
0
              !lcommunity_cmp(
1308
0
                bgp_attr_get_lcommunity(
1309
0
                  pi->attr),
1310
0
                lcom))
1311
0
            continue;
1312
0
        }
1313
0
        if (type == bgp_show_type_lcommunity) {
1314
0
          struct lcommunity *lcom = output_arg;
1315
1316
0
          if (!bgp_attr_get_lcommunity(
1317
0
                pi->attr) ||
1318
0
              !lcommunity_match(
1319
0
                bgp_attr_get_lcommunity(
1320
0
                  pi->attr),
1321
0
                lcom))
1322
0
            continue;
1323
0
        }
1324
0
        if (type == bgp_show_type_community) {
1325
0
          struct community *com = output_arg;
1326
1327
0
          if (!picomm ||
1328
0
              !community_match(picomm, com))
1329
0
            continue;
1330
0
        }
1331
0
        if (type == bgp_show_type_community_exact) {
1332
0
          struct community *com = output_arg;
1333
1334
0
          if (!picomm ||
1335
0
              !community_cmp(picomm, com))
1336
0
            continue;
1337
0
        }
1338
0
        if (header) {
1339
0
          if (use_json) {
1340
0
            json_object_int_add(
1341
0
              json, "bgpTableVersion",
1342
0
              tbl_ver);
1343
0
            json_object_string_addf(
1344
0
              json,
1345
0
              "bgpLocalRouterId",
1346
0
              "%pI4",
1347
0
              &bgp->router_id);
1348
0
            json_object_int_add(
1349
0
              json,
1350
0
              "defaultLocPrf",
1351
0
              bgp->default_local_pref);
1352
0
            asn_asn2json(json, "localAS",
1353
0
                   bgp->as,
1354
0
                   bgp->asnotation);
1355
0
          } else {
1356
0
            if (option == SHOW_DISPLAY_TAGS)
1357
0
              vty_out(vty,
1358
0
                V4_HEADER_TAG);
1359
0
            else if (
1360
0
              option
1361
0
              == SHOW_DISPLAY_OVERLAY)
1362
0
              vty_out(vty,
1363
0
                V4_HEADER_OVERLAY);
1364
0
            else {
1365
0
              bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
1366
0
            }
1367
0
          }
1368
0
          header = 0;
1369
0
        }
1370
0
        if (rd_header) {
1371
0
          if (use_json)
1372
0
            json_nroute =
1373
0
                   json_object_new_object();
1374
0
          bgp_evpn_show_route_rd_header(
1375
0
            vty, dest, json_nroute, rd_str,
1376
0
            RD_ADDRSTRLEN);
1377
0
          rd_header = 0;
1378
0
        }
1379
0
        if (use_json && !json_array)
1380
0
          json_array = json_object_new_array();
1381
1382
0
        if (option == SHOW_DISPLAY_TAGS)
1383
0
          route_vty_out_tag(
1384
0
            vty, bgp_dest_get_prefix(rm),
1385
0
            pi, no_display, SAFI_EVPN,
1386
0
            json_array);
1387
0
        else if (option == SHOW_DISPLAY_OVERLAY)
1388
0
          route_vty_out_overlay(
1389
0
            vty, bgp_dest_get_prefix(rm),
1390
0
            pi, no_display, json_array);
1391
0
        else
1392
0
          route_vty_out(vty,
1393
0
                  bgp_dest_get_prefix(rm),
1394
0
                  pi, no_display, SAFI_EVPN,
1395
0
                  json_array, false);
1396
0
        no_display = 1;
1397
0
      }
1398
1399
0
      if (no_display)
1400
0
        output_count++;
1401
1402
0
      if (use_json && json_array) {
1403
0
        const struct prefix *p =
1404
0
          bgp_dest_get_prefix(rm);
1405
1406
0
        json_prefix_info = json_object_new_object();
1407
1408
0
        json_object_string_addf(json_prefix_info,
1409
0
              "prefix", "%pFX", p);
1410
1411
0
        json_object_int_add(json_prefix_info,
1412
0
                "prefixLen", p->prefixlen);
1413
1414
0
        json_object_object_add(json_prefix_info,
1415
0
          "paths", json_array);
1416
0
        json_object_object_addf(json_nroute,
1417
0
              json_prefix_info,
1418
0
              "%pFX", p);
1419
0
        json_array = NULL;
1420
0
      }
1421
0
    }
1422
1423
0
    if (use_json && json_nroute)
1424
0
      json_object_object_add(json, rd_str, json_nroute);
1425
0
  }
1426
1427
0
  if (use_json) {
1428
0
    json_object_int_add(json, "numPrefix", output_count);
1429
0
    json_object_int_add(json, "totalPrefix", total_count);
1430
0
    vty_json(vty, json);
1431
0
  } else {
1432
0
    if (output_count == 0)
1433
0
      vty_out(vty, "No prefixes displayed, %ld exist\n",
1434
0
        total_count);
1435
0
    else
1436
0
      vty_out(vty,
1437
0
        "\nDisplayed %ld out of %ld total prefixes\n",
1438
0
        output_count, total_count);
1439
0
  }
1440
0
  return CMD_SUCCESS;
1441
0
}
1442
1443
DEFUN(show_ip_bgp_l2vpn_evpn,
1444
      show_ip_bgp_l2vpn_evpn_cmd,
1445
      "show [ip] bgp l2vpn evpn [json]",
1446
      SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
1447
0
{
1448
0
  return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1449
0
             SHOW_DISPLAY_STANDARD,
1450
0
             use_json(argc, argv));
1451
0
}
1452
1453
DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1454
      show_ip_bgp_l2vpn_evpn_rd_cmd,
1455
      "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1456
      SHOW_STR
1457
      IP_STR
1458
      BGP_STR
1459
      L2VPN_HELP_STR
1460
      EVPN_HELP_STR
1461
      "Display information for a route distinguisher\n"
1462
      "VPN Route Distinguisher\n"
1463
      "All VPN Route Distinguishers\n"
1464
      JSON_STR)
1465
0
{
1466
0
  int idx_ext_community = 0;
1467
0
  int ret;
1468
0
  struct prefix_rd prd;
1469
0
  int rd_all = 0;
1470
1471
0
  if (argv_find(argv, argc, "all", &rd_all))
1472
0
    return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1473
0
               NULL, SHOW_DISPLAY_STANDARD,
1474
0
               use_json(argc, argv));
1475
1476
0
  argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1477
0
  ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1478
0
  if (!ret) {
1479
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
1480
0
    return CMD_WARNING;
1481
0
  }
1482
0
  return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1483
0
             SHOW_DISPLAY_STANDARD,
1484
0
             use_json(argc, argv));
1485
0
}
1486
1487
DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1488
      show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1489
      "show [ip] bgp l2vpn evpn all tags",
1490
      SHOW_STR
1491
      IP_STR
1492
      BGP_STR
1493
      L2VPN_HELP_STR
1494
      EVPN_HELP_STR
1495
      "Display information about all EVPN NLRIs\n"
1496
      "Display BGP tags for prefixes\n")
1497
0
{
1498
0
  return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1499
0
             SHOW_DISPLAY_TAGS, 0);
1500
0
}
1501
1502
DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1503
      show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
1504
      "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1505
      SHOW_STR
1506
      IP_STR
1507
      BGP_STR
1508
      L2VPN_HELP_STR
1509
      EVPN_HELP_STR
1510
      "Display information for a route distinguisher\n"
1511
      "VPN Route Distinguisher\n"
1512
      "All VPN Route Distinguishers\n"
1513
      "Display BGP tags for prefixes\n")
1514
0
{
1515
0
  int idx_ext_community = 0;
1516
0
  int ret;
1517
0
  struct prefix_rd prd;
1518
0
  int rd_all = 0;
1519
1520
0
  if (argv_find(argv, argc, "all", &rd_all))
1521
0
    return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1522
0
               NULL, SHOW_DISPLAY_TAGS, 0);
1523
1524
0
  argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1525
0
  ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1526
0
  if (!ret) {
1527
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
1528
0
    return CMD_WARNING;
1529
0
  }
1530
0
  return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1531
0
             SHOW_DISPLAY_TAGS, 0);
1532
0
}
1533
1534
DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1535
      show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1536
      "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1537
      SHOW_STR
1538
      IP_STR
1539
      BGP_STR
1540
      L2VPN_HELP_STR
1541
      EVPN_HELP_STR
1542
      "Detailed information on TCP and BGP neighbor connections\n"
1543
      "IPv4 Neighbor to display information about\n"
1544
      "IPv6 Neighbor to display information about\n"
1545
      "Neighbor on BGP configured interface\n"
1546
      "Display routes learned from neighbor\n" JSON_STR)
1547
0
{
1548
0
  int idx = 0;
1549
0
  struct peer *peer;
1550
0
  char *peerstr = NULL;
1551
0
  bool uj = use_json(argc, argv);
1552
0
  afi_t afi = AFI_L2VPN;
1553
0
  safi_t safi = SAFI_EVPN;
1554
0
  struct bgp *bgp = NULL;
1555
1556
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1557
0
              &bgp, uj);
1558
0
  if (!idx) {
1559
0
          vty_out(vty, "No index\n");
1560
0
    return CMD_WARNING;
1561
0
  }
1562
1563
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1564
0
  argv_find(argv, argc, "neighbors", &idx);
1565
0
  peerstr = argv[++idx]->arg;
1566
1567
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1568
0
  if (!peer) {
1569
0
    if (uj) {
1570
0
      json_object *json_no = NULL;
1571
0
      json_no = json_object_new_object();
1572
0
      json_object_string_add(json_no, "warning",
1573
0
                 "Malformed address");
1574
0
      vty_out(vty, "%s\n",
1575
0
        json_object_to_json_string(json_no));
1576
0
      json_object_free(json_no);
1577
0
    } else
1578
0
      vty_out(vty, "Malformed address: %s\n",
1579
0
        argv[idx]->arg);
1580
0
    return CMD_WARNING;
1581
0
  }
1582
0
  if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1583
0
    if (uj) {
1584
0
      json_object *json_no = NULL;
1585
0
      json_no = json_object_new_object();
1586
0
      json_object_string_add(
1587
0
        json_no, "warning",
1588
0
        "No such neighbor or address family");
1589
0
      vty_out(vty, "%s\n",
1590
0
        json_object_to_json_string(json_no));
1591
0
      json_object_free(json_no);
1592
0
    } else
1593
0
      vty_out(vty, "%% No such neighbor or address family\n");
1594
0
    return CMD_WARNING;
1595
0
  }
1596
1597
0
  return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer,
1598
0
             SHOW_DISPLAY_STANDARD, uj);
1599
0
}
1600
1601
DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1602
      show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1603
      "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1604
      SHOW_STR
1605
      IP_STR
1606
      BGP_STR
1607
      L2VPN_HELP_STR
1608
      EVPN_HELP_STR
1609
      "Display information for a route distinguisher\n"
1610
      "VPN Route Distinguisher\n"
1611
      "All VPN Route Distinguishers\n"
1612
      "Detailed information on TCP and BGP neighbor connections\n"
1613
      "IPv4 Neighbor to display information about\n"
1614
      "IPv6 Neighbor to display information about\n"
1615
      "Neighbor on BGP configured interface\n"
1616
      "Display routes learned from neighbor\n" JSON_STR)
1617
0
{
1618
0
  int idx_ext_community = 0;
1619
0
  int idx = 0;
1620
0
  int ret;
1621
0
  struct peer *peer;
1622
0
  char *peerstr = NULL;
1623
0
  struct prefix_rd prd = {};
1624
0
  bool uj = use_json(argc, argv);
1625
0
  afi_t afi = AFI_L2VPN;
1626
0
  safi_t safi = SAFI_EVPN;
1627
0
  struct bgp *bgp = NULL;
1628
0
  int rd_all = 0;
1629
1630
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1631
0
              &bgp, uj);
1632
0
  if (!idx) {
1633
0
          vty_out(vty, "No index\n");
1634
0
    return CMD_WARNING;
1635
0
  }
1636
1637
0
  if (argv_find(argv, argc, "all", &rd_all)) {
1638
0
    argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1639
0
        &idx_ext_community);
1640
0
    ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1641
0
    if (!ret) {
1642
0
      if (uj) {
1643
0
        json_object *json_no = NULL;
1644
0
        json_no = json_object_new_object();
1645
0
        json_object_string_add(
1646
0
          json_no, "warning",
1647
0
          "Malformed Route Distinguisher");
1648
0
        vty_out(vty, "%s\n",
1649
0
          json_object_to_json_string(json_no));
1650
0
        json_object_free(json_no);
1651
0
      } else
1652
0
        vty_out(vty,
1653
0
          "%% Malformed Route Distinguisher\n");
1654
0
      return CMD_WARNING;
1655
0
    }
1656
0
  }
1657
1658
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1659
0
  argv_find(argv, argc, "neighbors", &idx);
1660
0
  peerstr = argv[++idx]->arg;
1661
1662
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1663
0
  if (!peer) {
1664
0
    if (uj) {
1665
0
      json_object *json_no = NULL;
1666
0
      json_no = json_object_new_object();
1667
0
      json_object_string_add(json_no, "warning",
1668
0
                 "Malformed address");
1669
0
      vty_out(vty, "%s\n",
1670
0
        json_object_to_json_string(json_no));
1671
0
      json_object_free(json_no);
1672
0
    } else
1673
0
      vty_out(vty, "Malformed address: %s\n",
1674
0
        argv[idx]->arg);
1675
0
    return CMD_WARNING;
1676
0
  }
1677
0
  if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1678
0
    if (uj) {
1679
0
      json_object *json_no = NULL;
1680
0
      json_no = json_object_new_object();
1681
0
      json_object_string_add(
1682
0
        json_no, "warning",
1683
0
        "No such neighbor or address family");
1684
0
      vty_out(vty, "%s\n",
1685
0
        json_object_to_json_string(json_no));
1686
0
      json_object_free(json_no);
1687
0
    } else
1688
0
      vty_out(vty, "%% No such neighbor or address family\n");
1689
0
    return CMD_WARNING;
1690
0
  }
1691
1692
1693
0
  if (rd_all)
1694
0
    return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor,
1695
0
               peer, SHOW_DISPLAY_STANDARD, uj);
1696
0
  else
1697
0
    return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor,
1698
0
               peer, SHOW_DISPLAY_STANDARD, uj);
1699
0
}
1700
1701
DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1702
      show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1703
      "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1704
      SHOW_STR
1705
      IP_STR
1706
      BGP_STR
1707
      L2VPN_HELP_STR
1708
      EVPN_HELP_STR
1709
      "Detailed information on TCP and BGP neighbor connections\n"
1710
      "IPv4 Neighbor to display information about\n"
1711
      "IPv6 Neighbor to display information about\n"
1712
      "Neighbor on BGP configured interface\n"
1713
      "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1714
0
{
1715
0
  int idx = 0;
1716
0
  struct peer *peer;
1717
0
  bool uj = use_json(argc, argv);
1718
0
  struct bgp *bgp = NULL;
1719
0
  afi_t afi = AFI_L2VPN;
1720
0
  safi_t safi = SAFI_EVPN;
1721
0
  char *peerstr = NULL;
1722
1723
0
  if (uj)
1724
0
    argc--;
1725
1726
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1727
0
              &bgp, uj);
1728
0
  if (!idx) {
1729
0
          vty_out(vty, "No index\n");
1730
0
    return CMD_WARNING;
1731
0
  }
1732
1733
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1734
0
  argv_find(argv, argc, "neighbors", &idx);
1735
0
  peerstr = argv[++idx]->arg;
1736
1737
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1738
0
  if (!peer) {
1739
0
    if (uj) {
1740
0
      json_object *json_no = NULL;
1741
0
      json_no = json_object_new_object();
1742
0
      json_object_string_add(json_no, "warning",
1743
0
                 "Malformed address");
1744
0
      vty_out(vty, "%s\n",
1745
0
        json_object_to_json_string(json_no));
1746
0
      json_object_free(json_no);
1747
0
    } else
1748
0
      vty_out(vty, "Malformed address: %s\n",
1749
0
        argv[idx]->arg);
1750
0
    return CMD_WARNING;
1751
0
  }
1752
0
  if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1753
0
    if (uj) {
1754
0
      json_object *json_no = NULL;
1755
0
      json_no = json_object_new_object();
1756
0
      json_object_string_add(
1757
0
        json_no, "warning",
1758
0
        "No such neighbor or address family");
1759
0
      vty_out(vty, "%s\n",
1760
0
        json_object_to_json_string(json_no));
1761
0
      json_object_free(json_no);
1762
0
    } else
1763
0
      vty_out(vty, "%% No such neighbor or address family\n");
1764
0
    return CMD_WARNING;
1765
0
  }
1766
1767
0
  return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1768
0
}
1769
1770
DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1771
      show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1772
      "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1773
      SHOW_STR
1774
      IP_STR
1775
      BGP_STR
1776
      L2VPN_HELP_STR
1777
      EVPN_HELP_STR
1778
      "Display information for a route distinguisher\n"
1779
      "VPN Route Distinguisher\n"
1780
      "All VPN Route Distinguishers\n"
1781
      "Detailed information on TCP and BGP neighbor connections\n"
1782
      "IPv4 Neighbor to display information about\n"
1783
      "IPv6 Neighbor to display information about\n"
1784
      "Neighbor on BGP configured interface\n"
1785
      "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1786
0
{
1787
0
  int idx_ext_community = 0;
1788
0
  int idx = 0;
1789
0
  int ret;
1790
0
  struct peer *peer;
1791
0
  struct prefix_rd prd;
1792
0
  struct bgp *bgp = NULL;
1793
0
  bool uj = use_json(argc, argv);
1794
0
  char *peerstr = NULL;
1795
0
  afi_t afi = AFI_L2VPN;
1796
0
  safi_t safi = SAFI_EVPN;
1797
0
  int rd_all = 0;
1798
1799
0
  if (uj)
1800
0
    argc--;
1801
1802
0
  if (uj)
1803
0
    argc--;
1804
1805
0
  bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1806
0
              &bgp, uj);
1807
0
  if (!idx) {
1808
0
          vty_out(vty, "No index\n");
1809
0
    return CMD_WARNING;
1810
0
  }
1811
1812
  /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1813
0
  argv_find(argv, argc, "neighbors", &idx);
1814
0
  peerstr = argv[++idx]->arg;
1815
1816
0
  peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1817
0
  if (!peer) {
1818
0
    if (uj) {
1819
0
      json_object *json_no = NULL;
1820
0
      json_no = json_object_new_object();
1821
0
      json_object_string_add(json_no, "warning",
1822
0
                 "Malformed address");
1823
0
      vty_out(vty, "%s\n",
1824
0
        json_object_to_json_string(json_no));
1825
0
      json_object_free(json_no);
1826
0
    } else
1827
0
      vty_out(vty, "Malformed address: %s\n",
1828
0
        argv[idx]->arg);
1829
0
    return CMD_WARNING;
1830
0
  }
1831
0
  if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1832
0
    if (uj) {
1833
0
      json_object *json_no = NULL;
1834
0
      json_no = json_object_new_object();
1835
0
      json_object_string_add(
1836
0
        json_no, "warning",
1837
0
        "No such neighbor or address family");
1838
0
      vty_out(vty, "%s\n",
1839
0
        json_object_to_json_string(json_no));
1840
0
      json_object_free(json_no);
1841
0
    } else
1842
0
      vty_out(vty, "%% No such neighbor or address family\n");
1843
0
    return CMD_WARNING;
1844
0
  }
1845
1846
0
  if (argv_find(argv, argc, "all", &rd_all))
1847
0
    return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN,
1848
0
            uj);
1849
0
  else {
1850
0
    argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1851
0
        &idx_ext_community);
1852
0
    ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1853
0
    if (!ret) {
1854
0
      if (uj) {
1855
0
        json_object *json_no = NULL;
1856
0
        json_no = json_object_new_object();
1857
0
        json_object_string_add(
1858
0
          json_no, "warning",
1859
0
          "Malformed Route Distinguisher");
1860
0
        vty_out(vty, "%s\n",
1861
0
          json_object_to_json_string(json_no));
1862
0
        json_object_free(json_no);
1863
0
      } else
1864
0
        vty_out(vty,
1865
0
          "%% Malformed Route Distinguisher\n");
1866
0
      return CMD_WARNING;
1867
0
    }
1868
0
  }
1869
1870
0
  return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1871
0
}
1872
1873
DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1874
      show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1875
      "show [ip] bgp l2vpn evpn all overlay [json]",
1876
      SHOW_STR
1877
      IP_STR
1878
      BGP_STR
1879
      L2VPN_HELP_STR
1880
      EVPN_HELP_STR
1881
      "Display information about all EVPN NLRIs\n"
1882
      "Display BGP Overlay Information for prefixes\n"
1883
      JSON_STR)
1884
0
{
1885
0
  return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1886
0
             SHOW_DISPLAY_OVERLAY,
1887
0
             use_json(argc, argv));
1888
0
}
1889
1890
DEFUN(show_ip_bgp_evpn_rd_overlay,
1891
      show_ip_bgp_evpn_rd_overlay_cmd,
1892
      "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1893
      SHOW_STR
1894
      IP_STR
1895
      BGP_STR
1896
      L2VPN_HELP_STR
1897
      EVPN_HELP_STR
1898
      "Display information for a route distinguisher\n"
1899
      "VPN Route Distinguisher\n"
1900
      "All VPN Route Distinguishers\n"
1901
      "Display BGP Overlay Information for prefixes\n")
1902
0
{
1903
0
  int idx_ext_community = 0;
1904
0
  int ret;
1905
0
  struct prefix_rd prd;
1906
0
  int rd_all = 0;
1907
1908
0
  if (argv_find(argv, argc, "all", &rd_all))
1909
0
    return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1910
0
               NULL, SHOW_DISPLAY_OVERLAY,
1911
0
               use_json(argc, argv));
1912
1913
0
  argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1914
0
  ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1915
0
  if (!ret) {
1916
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
1917
0
    return CMD_WARNING;
1918
0
  }
1919
0
  return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1920
0
             SHOW_DISPLAY_OVERLAY,
1921
0
             use_json(argc, argv));
1922
0
}
1923
1924
DEFUN(show_bgp_l2vpn_evpn_com,
1925
      show_bgp_l2vpn_evpn_com_cmd,
1926
      "show bgp l2vpn evpn \
1927
      <community AA:NN|large-community AA:BB:CC> \
1928
      [exact-match] [json]",
1929
      SHOW_STR
1930
      BGP_STR
1931
      L2VPN_HELP_STR
1932
      EVPN_HELP_STR
1933
      "Display routes matching the community\n"
1934
      "Community number where AA and NN are (0-65535)\n"
1935
      "Display routes matching the large-community\n"
1936
      "List of large-community numbers\n"
1937
      "Exact match of the communities\n"
1938
      JSON_STR)
1939
0
{
1940
0
  int idx = 0;
1941
0
  int ret = 0;
1942
0
  const char *clist_number_or_name;
1943
0
  int show_type = bgp_show_type_normal;
1944
0
  struct community *com;
1945
0
  struct lcommunity *lcom;
1946
1947
0
  if (argv_find(argv, argc, "large-community", &idx)) {
1948
0
    clist_number_or_name = argv[++idx]->arg;
1949
0
    show_type = bgp_show_type_lcommunity;
1950
1951
0
    if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1952
0
      show_type = bgp_show_type_lcommunity_exact;
1953
1954
0
    lcom = lcommunity_str2com(clist_number_or_name);
1955
0
    if (!lcom) {
1956
0
      vty_out(vty, "%% Large-community malformed\n");
1957
0
      return CMD_WARNING;
1958
0
    }
1959
1960
0
    ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1961
0
              SHOW_DISPLAY_STANDARD,
1962
0
              use_json(argc, argv));
1963
1964
0
    lcommunity_free(&lcom);
1965
0
  } else if (argv_find(argv, argc, "community", &idx)) {
1966
0
    clist_number_or_name = argv[++idx]->arg;
1967
0
    show_type = bgp_show_type_community;
1968
1969
0
    if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1970
0
      show_type = bgp_show_type_community_exact;
1971
1972
0
    com = community_str2com(clist_number_or_name);
1973
1974
0
    if (!com) {
1975
0
      vty_out(vty, "%% Community malformed: %s\n",
1976
0
        clist_number_or_name);
1977
0
      return CMD_WARNING;
1978
0
    }
1979
1980
0
    ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1981
0
              SHOW_DISPLAY_STANDARD,
1982
0
              use_json(argc, argv));
1983
0
    community_free(&com);
1984
0
  }
1985
1986
0
  return ret;
1987
0
}
1988
1989
/* For testing purpose, static route of EVPN RT-5. */
1990
DEFUN(evpnrt5_network,
1991
      evpnrt5_network_cmd,
1992
      "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map RMAP_NAME]",
1993
      "Specify a network to announce via BGP\n"
1994
      "IP prefix\n"
1995
      "IPv6 prefix\n"
1996
      "Specify Route Distinguisher\n"
1997
      "VPN Route Distinguisher\n"
1998
      "Ethernet Tag\n"
1999
      "Ethernet Tag Value\n"
2000
      "BGP label\n"
2001
      "label value\n"
2002
      "Ethernet Segment Identifier\n"
2003
      "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2004
      "Gateway IP\n"
2005
      "Gateway IP ( A.B.C.D )\n"
2006
      "Gateway IPv6 ( X:X::X:X )\n"
2007
      "Router Mac Ext Comm\n"
2008
      "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
2009
      "Route-map to modify the attributes\n"
2010
      "Name of the route map\n")
2011
0
{
2012
0
  int idx_ipv4_prefixlen = 1;
2013
0
  int idx_route_distinguisher = 3;
2014
0
  int idx_label = 7;
2015
0
  int idx_esi = 9;
2016
0
  int idx_gwip = 11;
2017
0
  int idx_ethtag = 5;
2018
0
  int idx_routermac = 13;
2019
2020
0
  return bgp_static_set_safi(
2021
0
    AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
2022
0
    argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
2023
0
    BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2024
0
    argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
2025
0
    argv[idx_routermac]->arg);
2026
0
}
2027
2028
/* For testing purpose, static route of EVPN RT-5. */
2029
DEFUN(no_evpnrt5_network,
2030
      no_evpnrt5_network_cmd,
2031
      "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
2032
      NO_STR
2033
      "Specify a network to announce via BGP\n"
2034
      "IP prefix\n"
2035
      "IPv6 prefix\n"
2036
      "Specify Route Distinguisher\n"
2037
      "VPN Route Distinguisher\n"
2038
      "Ethernet Tag\n"
2039
      "Ethernet Tag Value\n"
2040
      "BGP label\n"
2041
      "label value\n"
2042
      "Ethernet Segment Identifier\n"
2043
      "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2044
      "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2045
0
{
2046
0
  int idx_ipv4_prefixlen = 2;
2047
0
  int idx_ext_community = 4;
2048
0
  int idx_label = 8;
2049
0
  int idx_ethtag = 6;
2050
0
  int idx_esi = 10;
2051
0
  int idx_gwip = 12;
2052
0
  return bgp_static_unset_safi(
2053
0
    AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
2054
0
    argv[idx_ext_community]->arg, argv[idx_label]->arg,
2055
0
    BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2056
0
    argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
2057
0
}
2058
2059
static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
2060
0
{
2061
0
  evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl, false);
2062
0
}
2063
2064
static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
2065
0
{
2066
0
  evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl, false);
2067
0
}
2068
2069
/*
2070
 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2071
 * check that this is a change.
2072
 */
2073
static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2074
             struct ecommunity *ecomadd)
2075
0
{
2076
  /* If the VNI is "live", we need to uninstall routes using the current
2077
   * import RT(s) first before we update the import RT, and subsequently
2078
   * install routes.
2079
   */
2080
0
  if (is_vni_live(vpn))
2081
0
    bgp_evpn_uninstall_routes(bgp, vpn);
2082
2083
  /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2084
0
  bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
2085
2086
  /* If the auto route-target is in use we must remove it */
2087
0
  evpn_import_rt_delete_auto(bgp, vpn);
2088
2089
  /* Add new RT and rebuild the RT to VNI mapping */
2090
0
  listnode_add_sort(vpn->import_rtl, ecomadd);
2091
2092
0
  SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2093
0
  bgp_evpn_map_vni_to_its_rts(bgp, vpn);
2094
2095
  /* Install routes that match new import RT */
2096
0
  if (is_vni_live(vpn))
2097
0
    bgp_evpn_install_routes(bgp, vpn);
2098
0
}
2099
2100
/*
2101
 * Unconfigure Import RT(s) for a VNI (vty handler).
2102
 */
2103
static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2104
               struct ecommunity *ecomdel)
2105
0
{
2106
0
  struct listnode *node, *nnode, *node_to_del;
2107
0
  struct ecommunity *ecom;
2108
2109
  /* Along the lines of "configure" except we have to reset to the
2110
   * automatic value.
2111
   */
2112
0
  if (is_vni_live(vpn))
2113
0
    bgp_evpn_uninstall_routes(bgp, vpn);
2114
2115
  /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2116
0
  bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
2117
2118
  /* Delete all import RTs */
2119
0
  if (ecomdel == NULL) {
2120
0
    for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
2121
0
      ecommunity_free(&ecom);
2122
0
      list_delete_node(vpn->import_rtl, node);
2123
0
    }
2124
0
  }
2125
2126
  /* Delete a specific import RT */
2127
0
  else {
2128
0
    node_to_del = NULL;
2129
2130
0
    for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
2131
0
      if (ecommunity_match(ecom, ecomdel)) {
2132
0
        ecommunity_free(&ecom);
2133
0
        node_to_del = node;
2134
0
        break;
2135
0
      }
2136
0
    }
2137
2138
0
    if (node_to_del)
2139
0
      list_delete_node(vpn->import_rtl, node_to_del);
2140
0
  }
2141
2142
0
  assert(vpn->import_rtl);
2143
  /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2144
0
  if (list_isempty(vpn->import_rtl)) {
2145
0
    UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2146
0
    bgp_evpn_derive_auto_rt_import(bgp, vpn);
2147
0
  }
2148
  /* Rebuild the RT to VNI mapping */
2149
0
  else
2150
0
    bgp_evpn_map_vni_to_its_rts(bgp, vpn);
2151
2152
  /* Install routes that match new import RT */
2153
0
  if (is_vni_live(vpn))
2154
0
    bgp_evpn_install_routes(bgp, vpn);
2155
0
}
2156
2157
/*
2158
 * Configure the Export RT for a VNI (vty handler). Caller expected to
2159
 * check that this is a change. Note that only a single export RT is
2160
 * allowed for a VNI and any change to configuration is implemented as
2161
 * a "replace" (similar to other configuration).
2162
 */
2163
static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2164
             struct ecommunity *ecomadd)
2165
0
{
2166
  /* If the auto route-target is in use we must remove it */
2167
0
  evpn_export_rt_delete_auto(bgp, vpn);
2168
2169
0
  listnode_add_sort(vpn->export_rtl, ecomadd);
2170
0
  SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2171
2172
0
  if (is_vni_live(vpn))
2173
0
    bgp_evpn_handle_export_rt_change(bgp, vpn);
2174
0
}
2175
2176
/*
2177
 * Unconfigure the Export RT for a VNI (vty handler)
2178
 */
2179
static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2180
               struct ecommunity *ecomdel)
2181
0
{
2182
0
  struct listnode *node, *nnode, *node_to_del;
2183
0
  struct ecommunity *ecom;
2184
2185
  /* Delete all export RTs */
2186
0
  if (ecomdel == NULL) {
2187
    /* Reset to default and process all routes. */
2188
0
    for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2189
0
      ecommunity_free(&ecom);
2190
0
      list_delete_node(vpn->export_rtl, node);
2191
0
    }
2192
0
  }
2193
2194
  /* Delete a specific export RT */
2195
0
  else {
2196
0
    node_to_del = NULL;
2197
2198
0
    for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2199
0
      if (ecommunity_match(ecom, ecomdel)) {
2200
0
        ecommunity_free(&ecom);
2201
0
        node_to_del = node;
2202
0
        break;
2203
0
      }
2204
0
    }
2205
2206
0
    if (node_to_del)
2207
0
      list_delete_node(vpn->export_rtl, node_to_del);
2208
0
  }
2209
2210
0
  assert(vpn->export_rtl);
2211
0
  if (list_isempty(vpn->export_rtl)) {
2212
0
    UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2213
0
    bgp_evpn_derive_auto_rt_export(bgp, vpn);
2214
0
  }
2215
2216
0
  if (is_vni_live(vpn))
2217
0
    bgp_evpn_handle_export_rt_change(bgp, vpn);
2218
0
}
2219
2220
/*
2221
 * Configure RD for VRF
2222
 */
2223
static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd,
2224
          const char *rd_pretty)
2225
0
{
2226
  /* If we have already advertise type-5 routes with a diffrent RD, we
2227
   * have to delete and withdraw them firs
2228
   */
2229
0
  bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2230
2231
  /* update RD */
2232
0
  memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
2233
0
  bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
2234
0
  SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2235
2236
  /* We have a new RD for VRF.
2237
   * Advertise all type-5 routes again with the new RD
2238
   */
2239
0
  bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2240
0
}
2241
2242
/*
2243
 * Unconfigure RD for VRF
2244
 */
2245
static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2246
0
{
2247
  /* If we have already advertise type-5 routes with a diffrent RD, we
2248
   * have to delete and withdraw them firs
2249
   */
2250
0
  bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2251
2252
  /* fall back to default RD */
2253
0
  bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
2254
0
  UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2255
0
  if (bgp_vrf->vrf_prd_pretty)
2256
0
    XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);
2257
  /* We have a new RD for VRF.
2258
   * Advertise all type-5 routes again with the new RD
2259
   */
2260
0
  bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2261
0
}
2262
2263
/*
2264
 * Configure RD for a VNI (vty handler)
2265
 */
2266
static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
2267
            struct prefix_rd *rd, const char *rd_pretty)
2268
0
{
2269
  /* If the VNI is "live", we need to delete and withdraw this VNI's
2270
   * local routes with the prior RD first. Then, after updating RD,
2271
   * need to re-advertise.
2272
   */
2273
0
  if (is_vni_live(vpn))
2274
0
    bgp_evpn_handle_rd_change(bgp, vpn, 1);
2275
2276
  /* update RD */
2277
0
  memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
2278
0
  vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
2279
0
  SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
2280
2281
0
  if (is_vni_live(vpn))
2282
0
    bgp_evpn_handle_rd_change(bgp, vpn, 0);
2283
0
}
2284
2285
/*
2286
 * Unconfigure RD for a VNI (vty handler)
2287
 */
2288
static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
2289
0
{
2290
  /* If the VNI is "live", we need to delete and withdraw this VNI's
2291
   * local routes with the prior RD first. Then, after resetting RD
2292
   * to automatic value, need to re-advertise.
2293
   */
2294
0
  if (is_vni_live(vpn))
2295
0
    bgp_evpn_handle_rd_change(bgp, vpn, 1);
2296
2297
  /* reset RD to default */
2298
0
  bgp_evpn_derive_auto_rd(bgp, vpn);
2299
2300
0
  if (is_vni_live(vpn))
2301
0
    bgp_evpn_handle_rd_change(bgp, vpn, 0);
2302
0
}
2303
2304
/*
2305
 * Create VNI, if not already present (VTY handler). Mark as configured.
2306
 */
2307
static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
2308
0
{
2309
0
  struct bgpevpn *vpn;
2310
0
  struct in_addr mcast_grp = {INADDR_ANY};
2311
2312
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
2313
0
  if (!vpn) {
2314
    /* Check if this L2VNI is already configured as L3VNI */
2315
0
    if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
2316
0
      flog_err(
2317
0
        EC_BGP_VNI,
2318
0
        "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2319
0
        bgp->vrf_id, vni);
2320
0
      return NULL;
2321
0
    }
2322
2323
    /* tenant vrf will be updated when we get local_vni_add from
2324
     * zebra
2325
     */
2326
0
    vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp, 0);
2327
0
  }
2328
2329
  /* Mark as configured. */
2330
0
  SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2331
0
  return vpn;
2332
0
}
2333
2334
/*
2335
 * Delete VNI. If VNI does not exist in the system (i.e., just
2336
 * configuration), all that is needed is to free it. Otherwise,
2337
 * any parameters configured for the VNI need to be reset (with
2338
 * appropriate action) and the VNI marked as unconfigured; the
2339
 * VNI will continue to exist, purely as a "learnt" entity.
2340
 */
2341
static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
2342
0
{
2343
0
  if (!is_vni_live(vpn)) {
2344
0
    bgp_evpn_free(bgp, vpn);
2345
0
    return;
2346
0
  }
2347
2348
  /* We need to take the unconfigure action for each parameter of this VNI
2349
   * that is configured. Some optimization is possible, but not worth the
2350
   * additional code for an operation that should be pretty rare.
2351
   */
2352
0
  UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2353
2354
  /* First, deal with the export side - RD and export RT changes. */
2355
0
  if (is_rd_configured(vpn))
2356
0
    evpn_unconfigure_rd(bgp, vpn);
2357
0
  if (is_export_rt_configured(vpn))
2358
0
    evpn_unconfigure_export_rt(bgp, vpn, NULL);
2359
2360
  /* Next, deal with the import side. */
2361
0
  if (is_import_rt_configured(vpn))
2362
0
    evpn_unconfigure_import_rt(bgp, vpn, NULL);
2363
0
}
2364
2365
/*
2366
 * Display import RT mapping to VRFs (vty handler)
2367
 * bgp_evpn: evpn bgp instance
2368
 */
2369
static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
2370
             json_object *json)
2371
0
{
2372
0
  void *args[2];
2373
2374
0
  args[0] = vty;
2375
0
  args[1] = json;
2376
2377
0
  hash_iterate(bgp_evpn->vrf_import_rt_hash,
2378
0
         (void (*)(struct hash_bucket *,
2379
0
             void *))show_vrf_import_rt_entry,
2380
0
         args);
2381
0
}
2382
2383
/*
2384
 * Display import RT mapping to VNIs (vty handler)
2385
 */
2386
static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2387
         json_object *json)
2388
0
{
2389
0
  void *args[2];
2390
2391
0
  args[0] = vty;
2392
0
  args[1] = json;
2393
2394
0
  hash_iterate(
2395
0
    bgp->import_rt_hash,
2396
0
    (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
2397
0
    args);
2398
0
}
2399
2400
/*
2401
 * Display EVPN routes for all VNIs - vty handler.
2402
 */
2403
static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, int type,
2404
             bool mac_table, struct in_addr vtep_ip,
2405
             json_object *json, int detail)
2406
0
{
2407
0
  uint32_t num_vnis;
2408
0
  struct vni_walk_ctx wctx;
2409
2410
0
  num_vnis = hashcount(bgp->vnihash);
2411
0
  if (!num_vnis)
2412
0
    return;
2413
0
  memset(&wctx, 0, sizeof(wctx));
2414
0
  wctx.bgp = bgp;
2415
0
  wctx.vty = vty;
2416
0
  wctx.type = type;
2417
0
  wctx.mac_table = mac_table;
2418
0
  wctx.vtep_ip = vtep_ip;
2419
0
  wctx.json = json;
2420
0
  wctx.detail = detail;
2421
0
  hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
2422
0
               void *))show_vni_routes_hash,
2423
0
         &wctx);
2424
0
}
2425
2426
/*
2427
 * Display EVPN routes for all VNIs & all types - vty handler.
2428
 */
2429
static void evpn_show_routes_vni_all_type_all(struct vty *vty, struct bgp *bgp,
2430
                struct in_addr vtep_ip,
2431
                json_object *json, int detail)
2432
0
{
2433
0
  uint32_t num_vnis;
2434
0
  struct vni_walk_ctx wctx;
2435
2436
0
  num_vnis = hashcount(bgp->vnihash);
2437
0
  if (!num_vnis)
2438
0
    return;
2439
2440
0
  memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2441
0
  wctx.bgp = bgp;
2442
0
  wctx.vty = vty;
2443
0
  wctx.vtep_ip = vtep_ip;
2444
0
  wctx.json = json;
2445
0
  wctx.detail = detail;
2446
0
  hash_iterate(bgp->vnihash,
2447
0
         (void (*)(struct hash_bucket *,
2448
0
             void *))show_vni_routes_all_hash,
2449
0
         &wctx);
2450
0
}
2451
2452
/*
2453
 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2454
 */
2455
static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
2456
            vni_t vni, struct in_addr orig_ip,
2457
            json_object *json)
2458
0
{
2459
0
  struct bgpevpn *vpn;
2460
0
  struct prefix_evpn p;
2461
0
  struct bgp_dest *dest;
2462
0
  struct bgp_path_info *pi;
2463
0
  uint32_t path_cnt = 0;
2464
0
  afi_t afi;
2465
0
  safi_t safi;
2466
0
  json_object *json_paths = NULL;
2467
2468
0
  afi = AFI_L2VPN;
2469
0
  safi = SAFI_EVPN;
2470
2471
  /* Locate VNI. */
2472
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
2473
0
  if (!vpn) {
2474
0
    vty_out(vty, "VNI not found\n");
2475
0
    return;
2476
0
  }
2477
2478
  /* See if route exists. */
2479
0
  build_evpn_type3_prefix(&p, orig_ip);
2480
0
  dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
2481
0
  if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2482
0
    if (!json)
2483
0
      vty_out(vty, "%% Network not in table\n");
2484
2485
0
    if (dest)
2486
0
      bgp_dest_unlock_node(dest);
2487
2488
0
    return;
2489
0
  }
2490
2491
0
  if (json)
2492
0
    json_paths = json_object_new_array();
2493
2494
  /* Prefix and num paths displayed once per prefix. */
2495
0
  route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
2496
0
            NULL, afi, safi, json, false);
2497
2498
  /* Display each path for this prefix. */
2499
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2500
0
    json_object *json_path = NULL;
2501
2502
0
    if (json)
2503
0
      json_path = json_object_new_array();
2504
2505
0
    route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2506
0
             pi, afi, safi, RPKI_NOT_BEING_USED,
2507
0
             json_path);
2508
2509
0
    if (json)
2510
0
      json_object_array_add(json_paths, json_path);
2511
2512
0
    path_cnt++;
2513
0
  }
2514
2515
0
  if (json) {
2516
0
    if (path_cnt)
2517
0
      json_object_object_add(json, "paths", json_paths);
2518
2519
0
    json_object_int_add(json, "numPaths", path_cnt);
2520
0
  } else {
2521
0
    vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2522
0
      path_cnt);
2523
0
  }
2524
2525
0
  bgp_dest_unlock_node(dest);
2526
0
}
2527
2528
/*
2529
 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2530
 * By definition, only matching type-2 route will be displayed.
2531
 */
2532
static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2533
              vni_t vni, struct ethaddr *mac,
2534
              struct ipaddr *ip, json_object *json)
2535
0
{
2536
0
  struct bgpevpn *vpn;
2537
0
  struct prefix_evpn p;
2538
0
  struct prefix_evpn tmp_p;
2539
0
  struct bgp_dest *dest;
2540
0
  struct bgp_path_info *pi;
2541
0
  uint32_t path_cnt = 0;
2542
0
  afi_t afi;
2543
0
  safi_t safi;
2544
0
  json_object *json_paths = NULL;
2545
0
  struct ethaddr empty_mac = {};
2546
0
  struct ipaddr empty_ip = {};
2547
0
  const struct prefix_evpn *evp;
2548
2549
0
  afi = AFI_L2VPN;
2550
0
  safi = SAFI_EVPN;
2551
2552
  /* Locate VNI. */
2553
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
2554
0
  if (!vpn) {
2555
0
    if (!json)
2556
0
      vty_out(vty, "VNI not found\n");
2557
0
    return;
2558
0
  }
2559
2560
0
  build_evpn_type2_prefix(&p, mac ? mac : &empty_mac,
2561
0
        ip ? ip : &empty_ip);
2562
2563
  /* See if route exists. Look for both non-sticky and sticky. */
2564
0
  dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
2565
0
  if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2566
0
    if (!json)
2567
0
      vty_out(vty, "%% Network not in table\n");
2568
2569
0
    if (dest)
2570
0
      bgp_dest_unlock_node(dest);
2571
2572
0
    return;
2573
0
  }
2574
2575
  /*
2576
   * MAC is per-path, we have to walk the path_info's and look for it
2577
   * first here.
2578
   */
2579
0
  if (ip && mac) {
2580
0
    for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2581
0
      if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
2582
0
           sizeof(*mac)) == 0)
2583
0
        break;
2584
0
    }
2585
2586
0
    if (!pi) {
2587
0
      if (!json)
2588
0
        vty_out(vty, "%% Network not in table\n");
2589
0
      return;
2590
0
    }
2591
0
  }
2592
2593
0
  if (json)
2594
0
    json_paths = json_object_new_array();
2595
2596
  /* Prefix and num paths displayed once per prefix. */
2597
0
  route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
2598
0
            afi, safi, json, false);
2599
2600
0
  evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
2601
2602
  /* Display each path for this prefix. */
2603
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2604
0
    json_object *json_path = NULL;
2605
2606
    /* skip non-matching MACs */
2607
0
    if (ip && mac &&
2608
0
        memcmp(mac, evpn_type2_path_info_get_mac(pi),
2609
0
         sizeof(*mac)) != 0)
2610
0
      continue;
2611
2612
0
    if (json)
2613
0
      json_path = json_object_new_array();
2614
2615
    /*
2616
     * VNI table MAC-IP prefixes don't have MAC so
2617
     * make sure it's set from path info
2618
     * here.
2619
     */
2620
0
    if (is_evpn_prefix_ipaddr_none(evp)) {
2621
      /* VNI MAC -> Global */
2622
0
      evpn_type2_prefix_global_copy(
2623
0
        (struct prefix_evpn *)&tmp_p, evp,
2624
0
        NULL /* mac */,
2625
0
        evpn_type2_path_info_get_ip(pi));
2626
0
    } else {
2627
      /* VNI IP -> Global */
2628
0
      evpn_type2_prefix_global_copy(
2629
0
        (struct prefix_evpn *)&tmp_p, evp,
2630
0
        evpn_type2_path_info_get_mac(pi),
2631
0
        NULL /* ip */);
2632
0
    }
2633
2634
0
    route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p,
2635
0
             pi, afi, safi, RPKI_NOT_BEING_USED,
2636
0
             json_path);
2637
2638
0
    if (json)
2639
0
      json_object_array_add(json_paths, json_path);
2640
2641
0
    path_cnt++;
2642
0
  }
2643
2644
0
  if (json) {
2645
0
    if (path_cnt)
2646
0
      json_object_object_add(json, "paths", json_paths);
2647
2648
0
    json_object_int_add(json, "numPaths", path_cnt);
2649
0
  } else {
2650
0
    vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2651
0
      path_cnt);
2652
0
  }
2653
2654
0
  bgp_dest_unlock_node(dest);
2655
0
}
2656
2657
/* Disaplay EVPN routes for a ESI - VTY handler */
2658
static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2659
         esi_t *esi, json_object *json)
2660
0
{
2661
0
  struct bgp_evpn_es *es = NULL;
2662
2663
  /* locate the ES */
2664
0
  es = bgp_evpn_es_find(esi);
2665
0
  if (!es) {
2666
0
    if (!json)
2667
0
      vty_out(vty, "ESI not found\n");
2668
0
    return;
2669
0
  }
2670
2671
0
  show_esi_routes(bgp, es, vty, json);
2672
0
}
2673
2674
/*
2675
 * Display EVPN routes for a VNI - vty handler.
2676
 * If 'type' is non-zero, only routes matching that type are shown.
2677
 * If the vtep_ip is non zero, only routes behind that vtep are shown
2678
 */
2679
static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2680
         int type, bool mac_table,
2681
         struct in_addr vtep_ip, json_object *json)
2682
0
{
2683
0
  struct bgpevpn *vpn;
2684
2685
  /* Locate VNI. */
2686
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
2687
0
  if (!vpn) {
2688
0
    if (!json)
2689
0
      vty_out(vty, "VNI not found\n");
2690
0
    return;
2691
0
  }
2692
2693
  /* Walk this VNI's route table and display appropriate routes. */
2694
0
  show_vni_routes(bgp, vpn, vty, type, mac_table, vtep_ip, json, 0);
2695
0
}
2696
2697
/*
2698
 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2699
 * IP (vty handler). By definition, only matching type-2 route will be
2700
 * displayed.
2701
 */
2702
static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2703
             struct prefix_rd *prd, struct ethaddr *mac,
2704
             struct ipaddr *ip, json_object *json)
2705
0
{
2706
0
  struct prefix_evpn p;
2707
0
  struct bgp_dest *dest;
2708
0
  struct bgp_path_info *pi;
2709
0
  afi_t afi;
2710
0
  safi_t safi;
2711
0
  uint32_t path_cnt = 0;
2712
0
  json_object *json_paths = NULL;
2713
2714
0
  afi = AFI_L2VPN;
2715
0
  safi = SAFI_EVPN;
2716
2717
  /* See if route exists. Look for both non-sticky and sticky. */
2718
0
  build_evpn_type2_prefix(&p, mac, ip);
2719
0
  dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
2720
0
            (struct prefix *)&p, prd);
2721
0
  if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2722
0
    if (!json)
2723
0
      vty_out(vty, "%% Network not in table\n");
2724
2725
0
    if (dest)
2726
0
      bgp_dest_unlock_node(dest);
2727
2728
0
    return;
2729
0
  }
2730
2731
  /* Prefix and num paths displayed once per prefix. */
2732
0
  route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
2733
0
            prd, afi, safi, json, false);
2734
2735
0
  if (json)
2736
0
    json_paths = json_object_new_array();
2737
2738
  /* Display each path for this prefix. */
2739
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2740
0
    json_object *json_path = NULL;
2741
2742
0
    if (json)
2743
0
      json_path = json_object_new_array();
2744
2745
0
    route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2746
0
             pi, afi, safi, RPKI_NOT_BEING_USED,
2747
0
             json_path);
2748
2749
0
    if (json)
2750
0
      json_object_array_add(json_paths, json_path);
2751
2752
0
    path_cnt++;
2753
0
  }
2754
2755
0
  if (json && path_cnt) {
2756
0
    if (path_cnt)
2757
0
      json_object_object_addf(json, json_paths, "%pFX", &p);
2758
0
    json_object_int_add(json, "numPaths", path_cnt);
2759
0
  } else {
2760
0
    vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2761
0
      path_cnt);
2762
0
  }
2763
2764
0
  bgp_dest_unlock_node(dest);
2765
0
}
2766
2767
/*
2768
 * Display BGP EVPN routing table -- for specific RD (vty handler)
2769
 * If 'type' is non-zero, only routes matching that type are shown.
2770
 */
2771
static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
2772
             struct prefix_rd *prd, int type,
2773
             json_object *json)
2774
0
{
2775
0
  struct bgp_dest *rd_dest;
2776
0
  struct bgp_table *table;
2777
0
  struct bgp_dest *dest;
2778
0
  struct bgp_path_info *pi;
2779
0
  int rd_header = 1;
2780
0
  afi_t afi;
2781
0
  safi_t safi;
2782
0
  uint32_t prefix_cnt, path_cnt;
2783
0
  json_object *json_rd = NULL;
2784
0
  int add_rd_to_json = 0;
2785
2786
0
  afi = AFI_L2VPN;
2787
0
  safi = SAFI_EVPN;
2788
0
  prefix_cnt = path_cnt = 0;
2789
2790
0
  rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2791
0
  if (!rd_dest)
2792
0
    return;
2793
2794
0
  table = bgp_dest_get_bgp_table_info(rd_dest);
2795
0
  if (table == NULL) {
2796
0
    bgp_dest_unlock_node(rd_dest);
2797
0
    return;
2798
0
  }
2799
2800
0
  if (json) {
2801
0
    json_rd = json_object_new_object();
2802
0
    json_object_string_addf(json_rd, "rd",
2803
0
          BGP_RD_AS_FORMAT(bgp->asnotation), prd);
2804
0
  }
2805
2806
0
  bgp_dest_unlock_node(rd_dest);
2807
2808
  /* Display all prefixes with this RD. */
2809
0
  for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
2810
0
    const struct prefix_evpn *evp =
2811
0
      (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
2812
0
    json_object *json_prefix = NULL;
2813
0
    json_object *json_paths = NULL;
2814
0
    int add_prefix_to_json = 0;
2815
2816
0
    if (type && evp->prefix.route_type != type)
2817
0
      continue;
2818
2819
0
    if (json)
2820
0
      json_prefix = json_object_new_object();
2821
2822
0
    pi = bgp_dest_get_bgp_path_info(dest);
2823
0
    if (pi) {
2824
      /* RD header and legend - once overall. */
2825
0
      if (rd_header && !json) {
2826
0
        vty_out(vty,
2827
0
          "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2828
0
        vty_out(vty,
2829
0
          "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2830
0
        vty_out(vty,
2831
0
          "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2832
0
        vty_out(vty,
2833
0
          "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2834
0
        vty_out(vty,
2835
0
          "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2836
0
        rd_header = 0;
2837
0
      }
2838
2839
      /* Prefix and num paths displayed once per prefix. */
2840
0
      route_vty_out_detail_header(
2841
0
        vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
2842
0
        afi, safi, json_prefix, false);
2843
2844
0
      prefix_cnt++;
2845
0
    }
2846
2847
0
    if (json)
2848
0
      json_paths = json_object_new_array();
2849
2850
    /* Display each path for this prefix. */
2851
0
    for (; pi; pi = pi->next) {
2852
0
      json_object *json_path = NULL;
2853
2854
0
      if (json)
2855
0
        json_path = json_object_new_array();
2856
2857
0
      route_vty_out_detail(
2858
0
        vty, bgp, dest, bgp_dest_get_prefix(dest), pi,
2859
0
        afi, safi, RPKI_NOT_BEING_USED, json_path);
2860
2861
0
      if (json)
2862
0
        json_object_array_add(json_paths, json_path);
2863
2864
0
      path_cnt++;
2865
0
      add_prefix_to_json = 1;
2866
0
      add_rd_to_json = 1;
2867
0
    }
2868
2869
0
    if (json) {
2870
0
      if (add_prefix_to_json) {
2871
0
        json_object_object_add(json_prefix, "paths",
2872
0
                   json_paths);
2873
0
        json_object_object_addf(json_rd, json_prefix,
2874
0
              "%pFX", evp);
2875
0
      } else {
2876
0
        json_object_free(json_paths);
2877
0
        json_object_free(json_prefix);
2878
0
        json_paths = NULL;
2879
0
        json_prefix = NULL;
2880
0
      }
2881
0
    }
2882
0
  }
2883
2884
0
  if (json) {
2885
0
    if (add_rd_to_json)
2886
0
      json_object_object_addf(
2887
0
        json, json_rd,
2888
0
        BGP_RD_AS_FORMAT(bgp->asnotation), prd);
2889
0
    else {
2890
0
      json_object_free(json_rd);
2891
0
      json_rd = NULL;
2892
0
    }
2893
2894
0
    json_object_int_add(json, "numPrefix", prefix_cnt);
2895
0
    json_object_int_add(json, "numPaths", path_cnt);
2896
0
  } else {
2897
0
    if (prefix_cnt == 0)
2898
0
      vty_out(vty, "No prefixes exist with this RD%s\n",
2899
0
        type ? " (of requested type)" : "");
2900
0
    else
2901
0
      vty_out(vty,
2902
0
        "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2903
0
        prefix_cnt, path_cnt,
2904
0
        type ? " (of requested type)" : "");
2905
0
  }
2906
0
}
2907
2908
/*
2909
 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2910
 * (vty handler).  Only matching type-2 routes will be displayed.
2911
 */
2912
static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
2913
           struct ethaddr *mac, struct ipaddr *ip,
2914
           json_object *json)
2915
0
{
2916
0
  struct bgp_dest *rd_dest;
2917
0
  struct bgp_table *table;
2918
0
  struct bgp_dest *dest;
2919
0
  struct bgp_path_info *pi;
2920
0
  afi_t afi = AFI_L2VPN;
2921
0
  safi_t safi = SAFI_EVPN;
2922
0
  uint32_t prefix_cnt, path_cnt;
2923
0
  prefix_cnt = path_cnt = 0;
2924
2925
  /* EVPN routing table is a 2-level table with the first level being
2926
   * the RD. We need to look in every RD we know about.
2927
   */
2928
0
  for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
2929
0
       rd_dest = bgp_route_next(rd_dest)) {
2930
0
    json_object *json_paths = NULL;  /* paths array for prefix */
2931
0
    json_object *json_prefix = NULL; /* prefix within an RD */
2932
0
    json_object *json_rd = NULL;     /* holds all prefixes for RD */
2933
0
    char rd_str[RD_ADDRSTRLEN];
2934
0
    int add_rd_to_json = 0;
2935
0
    struct prefix_evpn ep;
2936
0
    const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
2937
2938
0
    table = bgp_dest_get_bgp_table_info(rd_dest);
2939
0
    if (table == NULL)
2940
0
      continue;
2941
2942
0
    prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
2943
0
            sizeof(rd_str), bgp->asnotation);
2944
2945
    /* Construct an RT-2 from the user-supplied mac(ip),
2946
     * then search the l2vpn evpn table for it.
2947
     */
2948
0
    build_evpn_type2_prefix(&ep, mac, ip);
2949
0
    dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
2950
0
              (struct prefix *)&ep,
2951
0
              (struct prefix_rd *)rd_destp);
2952
0
    if (!dest)
2953
0
      continue;
2954
2955
0
    if (json)
2956
0
      json_rd = json_object_new_object();
2957
2958
0
    const struct prefix *p = bgp_dest_get_prefix(dest);
2959
2960
0
    pi = bgp_dest_get_bgp_path_info(dest);
2961
0
    if (pi) {
2962
      /* RD header - per RD. */
2963
0
      bgp_evpn_show_route_rd_header(vty, rd_dest, json_rd,
2964
0
                  rd_str, RD_ADDRSTRLEN);
2965
0
      prefix_cnt++;
2966
0
    }
2967
2968
0
    if (json) {
2969
0
      json_prefix = json_object_new_object();
2970
0
      json_paths = json_object_new_array();
2971
0
      json_object_string_addf(json_prefix, "prefix", "%pFX",
2972
0
            p);
2973
0
      json_object_int_add(json_prefix, "prefixLen",
2974
0
              p->prefixlen);
2975
0
    } else
2976
      /* Prefix and num paths displayed once per prefix. */
2977
0
      route_vty_out_detail_header(
2978
0
        vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
2979
0
        AFI_L2VPN, SAFI_EVPN, json_prefix, false);
2980
2981
    /* For EVPN, the prefix is displayed for each path (to
2982
     * fit in with code that already exists).
2983
     */
2984
0
    for (; pi; pi = pi->next) {
2985
0
      json_object *json_path = NULL;
2986
2987
0
      add_rd_to_json = 1;
2988
0
      path_cnt++;
2989
2990
0
      if (json)
2991
0
        json_path = json_object_new_array();
2992
2993
0
      route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,
2994
0
               SAFI_EVPN, RPKI_NOT_BEING_USED,
2995
0
               json_path);
2996
2997
0
      if (json)
2998
0
        json_object_array_add(json_paths, json_path);
2999
0
      else
3000
0
        vty_out(vty, "\n");
3001
0
    }
3002
3003
0
    if (json) {
3004
0
      json_object_object_add(json_prefix, "paths",
3005
0
                 json_paths);
3006
0
      json_object_object_addf(json_rd, json_prefix, "%pFX",
3007
0
            p);
3008
0
      if (add_rd_to_json)
3009
0
        json_object_object_add(json, rd_str, json_rd);
3010
0
      else {
3011
0
        json_object_free(json_rd);
3012
0
        json_rd = NULL;
3013
0
      }
3014
0
    }
3015
3016
0
    bgp_dest_unlock_node(dest);
3017
0
  }
3018
3019
0
  if (json) {
3020
0
    json_object_int_add(json, "numPrefix", prefix_cnt);
3021
0
    json_object_int_add(json, "numPaths", path_cnt);
3022
0
  } else {
3023
0
    if (prefix_cnt == 0) {
3024
0
      vty_out(vty, "No Matching EVPN prefixes exist\n");
3025
0
    } else {
3026
0
      vty_out(vty, "Displayed %u prefixes (%u paths)\n",
3027
0
        prefix_cnt, path_cnt);
3028
0
    }
3029
0
  }
3030
0
}
3031
3032
/*
3033
 * Display BGP EVPN routing table - all routes (vty handler).
3034
 * If 'type' is non-zero, only routes matching that type are shown.
3035
 */
3036
static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3037
         json_object *json, int detail, bool self_orig)
3038
0
{
3039
0
  struct bgp_dest *rd_dest;
3040
0
  struct bgp_table *table;
3041
0
  struct bgp_dest *dest;
3042
0
  struct bgp_path_info *pi;
3043
0
  int header = detail ? 0 : 1;
3044
0
  int rd_header;
3045
0
  afi_t afi;
3046
0
  safi_t safi;
3047
0
  uint32_t prefix_cnt, path_cnt;
3048
3049
0
  afi = AFI_L2VPN;
3050
0
  safi = SAFI_EVPN;
3051
0
  prefix_cnt = path_cnt = 0;
3052
3053
  /* EVPN routing table is a 2-level table with the first level being
3054
   * the RD.
3055
   */
3056
0
  for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
3057
0
       rd_dest = bgp_route_next(rd_dest)) {
3058
0
    char rd_str[RD_ADDRSTRLEN];
3059
0
    json_object *json_rd = NULL; /* contains routes for an RD */
3060
0
    int add_rd_to_json = 0;
3061
0
    uint64_t tbl_ver;
3062
0
    const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
3063
3064
0
    table = bgp_dest_get_bgp_table_info(rd_dest);
3065
0
    if (table == NULL)
3066
0
      continue;
3067
3068
0
    tbl_ver = table->version;
3069
0
    prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
3070
0
            sizeof(rd_str), bgp->asnotation);
3071
3072
0
    if (json)
3073
0
      json_rd = json_object_new_object();
3074
3075
0
    rd_header = 1;
3076
3077
    /* Display all prefixes for an RD */
3078
0
    for (dest = bgp_table_top(table); dest;
3079
0
         dest = bgp_route_next(dest)) {
3080
0
      json_object *json_prefix =
3081
0
        NULL; /* contains prefix under a RD */
3082
0
      json_object *json_paths =
3083
0
        NULL; /* array of paths under a prefix*/
3084
0
      const struct prefix_evpn *evp =
3085
0
        (const struct prefix_evpn *)bgp_dest_get_prefix(
3086
0
          dest);
3087
0
      int add_prefix_to_json = 0;
3088
0
      const struct prefix *p = bgp_dest_get_prefix(dest);
3089
3090
0
      if (type && evp->prefix.route_type != type)
3091
0
        continue;
3092
3093
0
      pi = bgp_dest_get_bgp_path_info(dest);
3094
0
      if (pi) {
3095
0
        if (self_orig && (pi->peer != bgp->peer_self))
3096
0
          continue;
3097
3098
        /* Overall header/legend displayed once. */
3099
0
        if (header) {
3100
0
          bgp_evpn_show_route_header(vty, bgp,
3101
0
                   tbl_ver,
3102
0
                   json);
3103
0
          if (!json)
3104
0
            vty_out(vty,
3105
0
              "%19s Extended Community\n"
3106
0
              , " ");
3107
0
          header = 0;
3108
0
        }
3109
3110
        /* RD header - per RD. */
3111
0
        if (rd_header) {
3112
0
          bgp_evpn_show_route_rd_header(
3113
0
            vty, rd_dest, json_rd, rd_str,
3114
0
            RD_ADDRSTRLEN);
3115
0
          rd_header = 0;
3116
0
        }
3117
3118
0
        prefix_cnt++;
3119
0
      }
3120
3121
0
      if (json) {
3122
0
        json_prefix = json_object_new_object();
3123
0
        json_paths = json_object_new_array();
3124
0
        json_object_string_addf(json_prefix, "prefix",
3125
0
              "%pFX", p);
3126
0
        json_object_int_add(json_prefix, "prefixLen",
3127
0
                p->prefixlen);
3128
0
      }
3129
3130
      /* Prefix and num paths displayed once per prefix. */
3131
0
      if (detail)
3132
0
        route_vty_out_detail_header(
3133
0
          vty, bgp, dest,
3134
0
          bgp_dest_get_prefix(dest),
3135
0
          (struct prefix_rd *)rd_destp, AFI_L2VPN,
3136
0
          SAFI_EVPN, json_prefix, false);
3137
3138
      /* For EVPN, the prefix is displayed for each path (to
3139
       * fit in
3140
       * with code that already exists).
3141
       */
3142
0
      for (; pi; pi = pi->next) {
3143
0
        json_object *json_path = NULL;
3144
3145
0
        path_cnt++;
3146
0
        add_prefix_to_json = 1;
3147
0
        add_rd_to_json = 1;
3148
3149
0
        if (json)
3150
0
          json_path = json_object_new_array();
3151
3152
0
        if (detail) {
3153
0
          route_vty_out_detail(
3154
0
            vty, bgp, dest,
3155
0
            bgp_dest_get_prefix(dest), pi,
3156
0
            AFI_L2VPN, SAFI_EVPN,
3157
0
            RPKI_NOT_BEING_USED, json_path);
3158
0
        } else
3159
0
          route_vty_out(vty, p, pi, 0, SAFI_EVPN,
3160
0
                  json_path, false);
3161
3162
0
        if (json)
3163
0
          json_object_array_add(json_paths,
3164
0
                    json_path);
3165
0
      }
3166
3167
0
      if (json) {
3168
0
        if (add_prefix_to_json) {
3169
0
          json_object_object_add(json_prefix,
3170
0
                     "paths",
3171
0
                     json_paths);
3172
0
          json_object_object_addf(json_rd,
3173
0
                json_prefix,
3174
0
                "%pFX", p);
3175
0
        } else {
3176
0
          json_object_free(json_prefix);
3177
0
          json_object_free(json_paths);
3178
0
          json_prefix = NULL;
3179
0
          json_paths = NULL;
3180
0
        }
3181
0
      }
3182
0
    }
3183
3184
0
    if (json) {
3185
0
      if (add_rd_to_json)
3186
0
        json_object_object_add(json, rd_str, json_rd);
3187
0
      else {
3188
0
        json_object_free(json_rd);
3189
0
        json_rd = NULL;
3190
0
      }
3191
0
    }
3192
0
  }
3193
3194
0
  if (json) {
3195
0
    json_object_int_add(json, "numPrefix", prefix_cnt);
3196
0
    json_object_int_add(json, "numPaths", path_cnt);
3197
0
  } else {
3198
0
    if (prefix_cnt == 0) {
3199
0
      vty_out(vty, "No EVPN prefixes %sexist\n",
3200
0
        type ? "(of requested type) " : "");
3201
0
    } else {
3202
0
      vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
3203
0
        prefix_cnt, path_cnt,
3204
0
        type ? " (of requested type)" : "");
3205
0
    }
3206
0
  }
3207
0
}
3208
3209
int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3210
           bool use_json, int detail)
3211
0
{
3212
0
  json_object *json = NULL;
3213
3214
0
  if (use_json)
3215
0
    json = json_object_new_object();
3216
3217
0
  evpn_show_all_routes(vty, bgp, type, json, detail, false);
3218
3219
0
  if (use_json)
3220
    /*
3221
     * We are using no_pretty here because under extremely high
3222
     * settings (lots of routes with many different paths) this can
3223
     * save several minutes of output when FRR is run on older cpu's
3224
     * or more underperforming routers out there. So for route
3225
     * scale, we need to use no_pretty json.
3226
     */
3227
0
    vty_json_no_pretty(vty, json);
3228
0
  return CMD_SUCCESS;
3229
0
}
3230
3231
/*
3232
 * Display specified VNI (vty handler)
3233
 */
3234
static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
3235
        json_object *json)
3236
0
{
3237
0
  uint8_t found = 0;
3238
0
  struct bgpevpn *vpn;
3239
3240
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
3241
0
  if (vpn) {
3242
0
    found = 1;
3243
0
    display_vni(vty, vpn, json);
3244
0
  } else {
3245
0
    struct bgp *bgp_temp;
3246
0
    struct listnode *node = NULL;
3247
3248
0
    for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3249
0
      if (bgp_temp->l3vni == vni) {
3250
0
        found = 1;
3251
0
        display_l3vni(vty, bgp_temp, json);
3252
0
      }
3253
0
    }
3254
0
  }
3255
3256
0
  if (!found) {
3257
0
    if (json) {
3258
0
      vty_out(vty, "{}\n");
3259
0
    } else {
3260
0
      vty_out(vty, "VNI not found\n");
3261
0
      return;
3262
0
    }
3263
0
  }
3264
0
}
3265
3266
/*
3267
 * Display a VNI (upon user query).
3268
 */
3269
static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
3270
             json_object *json)
3271
0
{
3272
0
  void *args[2];
3273
0
  struct bgp *bgp_temp = NULL;
3274
0
  struct listnode *node;
3275
3276
3277
0
  if (!json) {
3278
0
    vty_out(vty, "Flags: * - Kernel\n");
3279
0
    vty_out(vty, "  %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3280
0
      "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3281
0
  }
3282
3283
  /* print all L2 VNIS */
3284
0
  args[0] = vty;
3285
0
  args[1] = json;
3286
0
  hash_iterate(bgp->vnihash,
3287
0
         (void (*)(struct hash_bucket *, void *))show_vni_entry,
3288
0
         args);
3289
3290
  /* print all L3 VNIs */
3291
0
  for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
3292
0
    show_l3vni_entry(vty, bgp_temp, json);
3293
0
}
3294
3295
/*
3296
 * evpn - enable advertisement of svi MAC-IP
3297
 */
3298
static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
3299
           uint32_t set)
3300
0
{
3301
0
  if (!vpn) {
3302
0
    if (set && bgp->evpn_info->advertise_svi_macip)
3303
0
      return;
3304
0
    else if (!set && !bgp->evpn_info->advertise_svi_macip)
3305
0
      return;
3306
3307
0
    bgp->evpn_info->advertise_svi_macip = set;
3308
0
    bgp_zebra_advertise_svi_macip(bgp,
3309
0
          bgp->evpn_info->advertise_svi_macip, 0);
3310
0
  } else {
3311
0
    if (set && vpn->advertise_svi_macip)
3312
0
      return;
3313
0
    else if (!set && !vpn->advertise_svi_macip)
3314
0
      return;
3315
3316
0
    vpn->advertise_svi_macip = set;
3317
0
    bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
3318
0
                vpn->vni);
3319
0
  }
3320
0
}
3321
3322
/*
3323
 * evpn - enable advertisement of default g/w
3324
 */
3325
static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
3326
0
{
3327
0
  if (!vpn) {
3328
0
    if (bgp->advertise_gw_macip)
3329
0
      return;
3330
3331
0
    bgp->advertise_gw_macip = 1;
3332
0
    bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3333
0
  } else {
3334
0
    if (vpn->advertise_gw_macip)
3335
0
      return;
3336
3337
0
    vpn->advertise_gw_macip = 1;
3338
0
    bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3339
0
               vpn->vni);
3340
0
  }
3341
0
  return;
3342
0
}
3343
3344
/*
3345
 * evpn - disable advertisement of default g/w
3346
 */
3347
static void evpn_unset_advertise_default_gw(struct bgp *bgp,
3348
              struct bgpevpn *vpn)
3349
0
{
3350
0
  if (!vpn) {
3351
0
    if (!bgp->advertise_gw_macip)
3352
0
      return;
3353
3354
0
    bgp->advertise_gw_macip = 0;
3355
0
    bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3356
0
  } else {
3357
0
    if (!vpn->advertise_gw_macip)
3358
0
      return;
3359
3360
0
    vpn->advertise_gw_macip = 0;
3361
0
    bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3362
0
               vpn->vni);
3363
0
  }
3364
0
  return;
3365
0
}
3366
3367
/*
3368
 * evpn - enable advertisement of default g/w
3369
 */
3370
static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
3371
                 afi_t afi, bool add)
3372
0
{
3373
0
  safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
3374
3375
0
  if (add) {
3376
    /* bail if we are already advertising default route */
3377
0
    if (evpn_default_originate_set(bgp_vrf, afi, safi))
3378
0
      return;
3379
3380
0
    if (afi == AFI_IP)
3381
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3382
0
         BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3383
0
    else if (afi == AFI_IP6)
3384
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3385
0
         BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3386
0
  } else {
3387
    /* bail out if we havent advertised the default route */
3388
0
    if (!evpn_default_originate_set(bgp_vrf, afi, safi))
3389
0
      return;
3390
0
    if (afi == AFI_IP)
3391
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3392
0
           BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3393
0
    else if (afi == AFI_IP6)
3394
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3395
0
           BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3396
0
  }
3397
3398
0
  bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
3399
0
}
3400
3401
/*
3402
 * evpn - enable advertisement of default g/w
3403
 */
3404
static void evpn_set_advertise_subnet(struct bgp *bgp,
3405
              struct bgpevpn *vpn)
3406
0
{
3407
0
  if (vpn->advertise_subnet)
3408
0
    return;
3409
3410
0
  vpn->advertise_subnet = 1;
3411
0
  bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3412
0
}
3413
3414
/*
3415
 * evpn - disable advertisement of default g/w
3416
 */
3417
static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
3418
0
{
3419
0
  if (!vpn->advertise_subnet)
3420
0
    return;
3421
3422
0
  vpn->advertise_subnet = 0;
3423
0
  bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3424
0
}
3425
3426
/*
3427
 * EVPN (VNI advertisement) enabled. Register with zebra.
3428
 */
3429
static void evpn_set_advertise_all_vni(struct bgp *bgp)
3430
0
{
3431
0
  bgp->advertise_all_vni = 1;
3432
0
  bgp_set_evpn(bgp);
3433
0
  bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3434
0
}
3435
3436
/*
3437
 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3438
 * cache, EVPN routes (delete and withdraw from peers).
3439
 */
3440
static void evpn_unset_advertise_all_vni(struct bgp *bgp)
3441
0
{
3442
0
  bgp->advertise_all_vni = 0;
3443
0
  bgp_set_evpn(bgp_get_default());
3444
0
  bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3445
0
  bgp_evpn_cleanup_on_disable(bgp);
3446
0
}
3447
3448
/* Set resolve overlay index flag */
3449
static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
3450
0
{
3451
0
  if (set == bgp->resolve_overlay_index)
3452
0
    return;
3453
3454
0
  if (set) {
3455
0
    bgp->resolve_overlay_index = true;
3456
0
    hash_iterate(bgp->vnihash,
3457
0
           (void (*)(struct hash_bucket *, void *))
3458
0
             bgp_evpn_handle_resolve_overlay_index_set,
3459
0
           NULL);
3460
0
  } else {
3461
0
    hash_iterate(
3462
0
      bgp->vnihash,
3463
0
      (void (*)(struct hash_bucket *, void *))
3464
0
        bgp_evpn_handle_resolve_overlay_index_unset,
3465
0
      NULL);
3466
0
    bgp->resolve_overlay_index = false;
3467
0
  }
3468
0
}
3469
3470
/*
3471
 * EVPN - use RFC8365 to auto-derive RT
3472
 */
3473
static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3474
0
{
3475
0
  bgp->advertise_autort_rfc8365 = 1;
3476
0
  bgp_evpn_handle_autort_change(bgp);
3477
0
}
3478
3479
/*
3480
 * EVPN - don't use RFC8365 to auto-derive RT
3481
 */
3482
static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3483
0
{
3484
0
  bgp->advertise_autort_rfc8365 = 0;
3485
0
  bgp_evpn_handle_autort_change(bgp);
3486
0
}
3487
3488
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
3489
0
{
3490
0
  char *ecom_str;
3491
0
  struct listnode *node, *nnode;
3492
0
  struct ecommunity *ecom;
3493
3494
0
  if (is_vni_configured(vpn)) {
3495
0
    vty_out(vty, "  vni %u\n", vpn->vni);
3496
0
    if (is_rd_configured(vpn))
3497
0
      vty_out(vty, "   rd %s\n", vpn->prd_pretty);
3498
3499
0
    if (is_import_rt_configured(vpn)) {
3500
0
      for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3501
0
                 ecom)) {
3502
0
        ecom_str = ecommunity_ecom2str(
3503
0
          ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3504
0
        vty_out(vty, "   route-target import %s\n",
3505
0
          ecom_str);
3506
0
        XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3507
0
      }
3508
0
    }
3509
3510
0
    if (is_export_rt_configured(vpn)) {
3511
0
      for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3512
0
                 ecom)) {
3513
0
        ecom_str = ecommunity_ecom2str(
3514
0
          ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3515
0
        vty_out(vty, "   route-target export %s\n",
3516
0
          ecom_str);
3517
0
        XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3518
0
      }
3519
0
    }
3520
3521
0
    if (vpn->advertise_gw_macip)
3522
0
      vty_out(vty, "   advertise-default-gw\n");
3523
3524
0
    if (vpn->advertise_svi_macip)
3525
0
      vty_out(vty, "   advertise-svi-ip\n");
3526
3527
0
    if (vpn->advertise_subnet)
3528
0
      vty_out(vty, "   advertise-subnet\n");
3529
3530
0
    vty_out(vty, "  exit-vni\n");
3531
0
  }
3532
0
}
3533
3534
#include "bgpd/bgp_evpn_vty_clippy.c"
3535
3536
DEFPY(bgp_evpn_flood_control,
3537
      bgp_evpn_flood_control_cmd,
3538
      "[no$no] flooding <disable$disable|head-end-replication$her>",
3539
      NO_STR
3540
      "Specify handling for BUM packets\n"
3541
      "Do not flood any BUM packets\n"
3542
      "Flood BUM packets using head-end replication\n")
3543
0
{
3544
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3545
0
  enum vxlan_flood_control flood_ctrl;
3546
3547
0
  if (!bgp)
3548
0
    return CMD_WARNING;
3549
3550
0
  if (disable && !no)
3551
0
    flood_ctrl = VXLAN_FLOOD_DISABLED;
3552
0
  else if (her || no)
3553
0
    flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3554
0
  else
3555
0
    return CMD_WARNING;
3556
3557
0
  if (bgp->vxlan_flood_ctrl == flood_ctrl)
3558
0
    return CMD_SUCCESS;
3559
3560
0
  bgp->vxlan_flood_ctrl = flood_ctrl;
3561
0
  bgp_evpn_flood_control_change(bgp);
3562
3563
0
  return CMD_SUCCESS;
3564
0
}
3565
3566
DEFUN (bgp_evpn_advertise_default_gw_vni,
3567
       bgp_evpn_advertise_default_gw_vni_cmd,
3568
       "advertise-default-gw",
3569
       "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3570
0
{
3571
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3572
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3573
3574
0
  if (!bgp)
3575
0
    return CMD_WARNING;
3576
3577
0
  evpn_set_advertise_default_gw(bgp, vpn);
3578
3579
0
  return CMD_SUCCESS;
3580
0
}
3581
3582
DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3583
       no_bgp_evpn_advertise_default_gw_vni_cmd,
3584
       "no advertise-default-gw",
3585
       NO_STR
3586
       "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3587
0
{
3588
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3589
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3590
3591
0
  if (!bgp)
3592
0
    return CMD_WARNING;
3593
3594
0
  evpn_unset_advertise_default_gw(bgp, vpn);
3595
3596
0
  return CMD_SUCCESS;
3597
0
}
3598
3599
3600
DEFUN (bgp_evpn_advertise_default_gw,
3601
       bgp_evpn_advertise_default_gw_cmd,
3602
       "advertise-default-gw",
3603
       "Advertise All default g/w mac-ip routes in EVPN\n")
3604
0
{
3605
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3606
3607
0
  if (!bgp)
3608
0
    return CMD_WARNING;
3609
3610
0
  if (!EVPN_ENABLED(bgp)) {
3611
0
    vty_out(vty,
3612
0
      "This command is only supported under the EVPN VRF\n");
3613
0
    return CMD_WARNING;
3614
0
  }
3615
3616
0
  evpn_set_advertise_default_gw(bgp, NULL);
3617
3618
0
  return CMD_SUCCESS;
3619
0
}
3620
3621
DEFUN (no_bgp_evpn_advertise_default_gw,
3622
       no_bgp_evpn_advertise_default_gw_cmd,
3623
       "no advertise-default-gw",
3624
       NO_STR
3625
       "Withdraw All default g/w mac-ip routes from EVPN\n")
3626
0
{
3627
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3628
3629
0
  if (!bgp)
3630
0
    return CMD_WARNING;
3631
3632
0
  evpn_unset_advertise_default_gw(bgp, NULL);
3633
3634
0
  return CMD_SUCCESS;
3635
0
}
3636
3637
DEFUN (bgp_evpn_advertise_all_vni,
3638
       bgp_evpn_advertise_all_vni_cmd,
3639
       "advertise-all-vni",
3640
       "Advertise All local VNIs\n")
3641
0
{
3642
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3643
0
  struct bgp *bgp_evpn = NULL;
3644
3645
0
  if (!bgp)
3646
0
    return CMD_WARNING;
3647
3648
0
  bgp_evpn = bgp_get_evpn();
3649
0
  if (bgp_evpn && bgp_evpn != bgp) {
3650
0
    vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3651
0
      bgp_evpn->name_pretty);
3652
0
    return CMD_WARNING_CONFIG_FAILED;
3653
0
  }
3654
3655
0
  evpn_set_advertise_all_vni(bgp);
3656
0
  return CMD_SUCCESS;
3657
0
}
3658
3659
DEFUN (no_bgp_evpn_advertise_all_vni,
3660
       no_bgp_evpn_advertise_all_vni_cmd,
3661
       "no advertise-all-vni",
3662
       NO_STR
3663
       "Advertise All local VNIs\n")
3664
0
{
3665
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3666
3667
0
  if (!bgp)
3668
0
    return CMD_WARNING;
3669
0
  evpn_unset_advertise_all_vni(bgp);
3670
0
  return CMD_SUCCESS;
3671
0
}
3672
3673
DEFUN (bgp_evpn_advertise_autort_rfc8365,
3674
       bgp_evpn_advertise_autort_rfc8365_cmd,
3675
       "autort rfc8365-compatible",
3676
       "Auto-derivation of RT\n"
3677
       "Auto-derivation of RT using RFC8365\n")
3678
0
{
3679
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3680
3681
0
  if (!bgp)
3682
0
    return CMD_WARNING;
3683
0
  evpn_set_advertise_autort_rfc8365(bgp);
3684
0
  return CMD_SUCCESS;
3685
0
}
3686
3687
DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3688
       no_bgp_evpn_advertise_autort_rfc8365_cmd,
3689
       "no autort rfc8365-compatible",
3690
       NO_STR
3691
       "Auto-derivation of RT\n"
3692
       "Auto-derivation of RT using RFC8365\n")
3693
0
{
3694
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3695
3696
0
  if (!bgp)
3697
0
    return CMD_WARNING;
3698
0
  evpn_unset_advertise_autort_rfc8365(bgp);
3699
0
  return CMD_SUCCESS;
3700
0
}
3701
3702
DEFUN (bgp_evpn_default_originate,
3703
       bgp_evpn_default_originate_cmd,
3704
       "default-originate <ipv4 | ipv6>",
3705
       "originate a default route\n"
3706
       "ipv4 address family\n"
3707
       "ipv6 address family\n")
3708
0
{
3709
0
  afi_t afi = 0;
3710
0
  int idx_afi = 0;
3711
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3712
3713
0
  if (!bgp_vrf)
3714
0
    return CMD_WARNING;
3715
0
  argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3716
0
  evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3717
0
  return CMD_SUCCESS;
3718
0
}
3719
3720
DEFUN (no_bgp_evpn_default_originate,
3721
       no_bgp_evpn_default_originate_cmd,
3722
       "no default-originate <ipv4 | ipv6>",
3723
       NO_STR
3724
       "withdraw a default route\n"
3725
       "ipv4 address family\n"
3726
       "ipv6 address family\n")
3727
0
{
3728
0
  afi_t afi = 0;
3729
0
  int idx_afi = 0;
3730
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3731
3732
0
  if (!bgp_vrf)
3733
0
    return CMD_WARNING;
3734
0
  argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3735
0
  evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3736
0
  return CMD_SUCCESS;
3737
0
}
3738
3739
DEFPY (dup_addr_detection,
3740
       dup_addr_detection_cmd,
3741
       "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3742
       "Duplicate address detection\n"
3743
       "Max allowed moves before address detected as duplicate\n"
3744
       "Num of max allowed moves (2-1000) default 5\n"
3745
       "Duplicate address detection time\n"
3746
       "Time in seconds (2-1800) default 180\n")
3747
0
{
3748
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3749
3750
0
  if (!bgp_vrf)
3751
0
    return CMD_WARNING;
3752
3753
0
  if (!EVPN_ENABLED(bgp_vrf)) {
3754
0
    vty_out(vty,
3755
0
      "This command is only supported under the EVPN VRF\n");
3756
0
    return CMD_WARNING;
3757
0
  }
3758
3759
0
  bgp_vrf->evpn_info->dup_addr_detect = true;
3760
3761
0
  if (time_val)
3762
0
    bgp_vrf->evpn_info->dad_time = time_val;
3763
0
  if (max_moves_val)
3764
0
    bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3765
3766
0
  bgp_zebra_dup_addr_detection(bgp_vrf);
3767
3768
0
  return CMD_SUCCESS;
3769
0
}
3770
3771
DEFPY (dup_addr_detection_auto_recovery,
3772
       dup_addr_detection_auto_recovery_cmd,
3773
       "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3774
       "Duplicate address detection\n"
3775
       "Duplicate address detection freeze\n"
3776
       "Duplicate address detection permanent freeze\n"
3777
       "Duplicate address detection freeze time (30-3600)\n")
3778
0
{
3779
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3780
0
  uint32_t freeze_time = freeze_time_val;
3781
3782
0
  if (!bgp_vrf)
3783
0
    return CMD_WARNING;
3784
3785
0
  if (!EVPN_ENABLED(bgp_vrf)) {
3786
0
    vty_out(vty,
3787
0
      "This command is only supported under the EVPN VRF\n");
3788
0
    return CMD_WARNING;
3789
0
  }
3790
3791
0
  bgp_vrf->evpn_info->dup_addr_detect = true;
3792
0
  bgp_vrf->evpn_info->dad_freeze = true;
3793
0
  bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3794
3795
0
  bgp_zebra_dup_addr_detection(bgp_vrf);
3796
3797
0
  return CMD_SUCCESS;
3798
0
}
3799
3800
DEFPY (no_dup_addr_detection,
3801
       no_dup_addr_detection_cmd,
3802
       "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3803
       NO_STR
3804
       "Duplicate address detection\n"
3805
       "Max allowed moves before address detected as duplicate\n"
3806
       "Num of max allowed moves (2-1000) default 5\n"
3807
       "Duplicate address detection time\n"
3808
       "Time in seconds (2-1800) default 180\n"
3809
       "Duplicate address detection freeze\n"
3810
       "Duplicate address detection permanent freeze\n"
3811
       "Duplicate address detection freeze time (30-3600)\n")
3812
0
{
3813
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3814
0
  uint32_t max_moves = (uint32_t)max_moves_val;
3815
0
  uint32_t freeze_time = (uint32_t)freeze_time_val;
3816
3817
0
  if (!bgp_vrf)
3818
0
    return CMD_WARNING;
3819
3820
0
  if (!EVPN_ENABLED(bgp_vrf)) {
3821
0
    vty_out(vty,
3822
0
      "This command is only supported under the EVPN VRF\n");
3823
0
    return CMD_WARNING;
3824
0
  }
3825
3826
0
  if (argc == 2) {
3827
0
    if (!bgp_vrf->evpn_info->dup_addr_detect)
3828
0
      return CMD_SUCCESS;
3829
    /* Reset all parameters to default. */
3830
0
    bgp_vrf->evpn_info->dup_addr_detect = false;
3831
0
    bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3832
0
    bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3833
0
    bgp_vrf->evpn_info->dad_freeze = false;
3834
0
    bgp_vrf->evpn_info->dad_freeze_time = 0;
3835
0
  } else {
3836
0
    if (max_moves) {
3837
0
      if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3838
0
        vty_out(vty,
3839
0
        "%% Value does not match with config\n");
3840
0
        return CMD_SUCCESS;
3841
0
      }
3842
0
      bgp_vrf->evpn_info->dad_max_moves =
3843
0
        EVPN_DAD_DEFAULT_MAX_MOVES;
3844
0
    }
3845
3846
0
    if (time_val) {
3847
0
      if (bgp_vrf->evpn_info->dad_time != time_val) {
3848
0
        vty_out(vty,
3849
0
        "%% Value does not match with config\n");
3850
0
        return CMD_SUCCESS;
3851
0
      }
3852
0
      bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3853
0
    }
3854
3855
0
    if (freeze_time) {
3856
0
      if (bgp_vrf->evpn_info->dad_freeze_time
3857
0
          != freeze_time) {
3858
0
        vty_out(vty,
3859
0
        "%% Value does not match with config\n");
3860
0
        return CMD_SUCCESS;
3861
0
      }
3862
0
      bgp_vrf->evpn_info->dad_freeze_time = 0;
3863
0
      bgp_vrf->evpn_info->dad_freeze = false;
3864
0
    }
3865
3866
0
    if (permanent_val) {
3867
0
      if (bgp_vrf->evpn_info->dad_freeze_time) {
3868
0
        vty_out(vty,
3869
0
        "%% Value does not match with config\n");
3870
0
        return CMD_SUCCESS;
3871
0
      }
3872
0
      bgp_vrf->evpn_info->dad_freeze = false;
3873
0
    }
3874
0
  }
3875
3876
0
  bgp_zebra_dup_addr_detection(bgp_vrf);
3877
3878
0
  return CMD_SUCCESS;
3879
0
}
3880
3881
DEFPY(bgp_evpn_advertise_svi_ip,
3882
      bgp_evpn_advertise_svi_ip_cmd,
3883
      "[no$no] advertise-svi-ip",
3884
      NO_STR
3885
      "Advertise svi mac-ip routes in EVPN\n")
3886
0
{
3887
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3888
3889
0
  if (!bgp)
3890
0
    return CMD_WARNING;
3891
3892
0
  if (no)
3893
0
    evpn_set_advertise_svi_macip(bgp, NULL, 0);
3894
0
  else {
3895
0
    if (!EVPN_ENABLED(bgp)) {
3896
0
      vty_out(vty,
3897
0
        "This command is only supported under EVPN VRF\n");
3898
0
      return CMD_WARNING;
3899
0
    }
3900
0
    evpn_set_advertise_svi_macip(bgp, NULL, 1);
3901
0
  }
3902
3903
0
  return CMD_SUCCESS;
3904
0
}
3905
3906
DEFPY(bgp_evpn_advertise_svi_ip_vni,
3907
      bgp_evpn_advertise_svi_ip_vni_cmd,
3908
      "[no$no] advertise-svi-ip",
3909
      NO_STR
3910
      "Advertise svi mac-ip routes in EVPN for a VNI\n")
3911
0
{
3912
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3913
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3914
3915
0
  if (!bgp)
3916
0
    return CMD_WARNING;
3917
3918
0
  if (no)
3919
0
    evpn_set_advertise_svi_macip(bgp, vpn, 0);
3920
0
  else
3921
0
    evpn_set_advertise_svi_macip(bgp, vpn, 1);
3922
3923
0
  return CMD_SUCCESS;
3924
0
}
3925
3926
DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3927
        bgp_evpn_advertise_vni_subnet_cmd,
3928
        "advertise-subnet",
3929
        "Advertise the subnet corresponding to VNI\n")
3930
0
{
3931
0
  struct bgp *bgp_vrf = NULL;
3932
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3933
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3934
3935
0
  if (!bgp)
3936
0
    return CMD_WARNING;
3937
3938
0
  bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3939
0
  if (!bgp_vrf)
3940
0
    return CMD_WARNING;
3941
3942
0
  evpn_set_advertise_subnet(bgp, vpn);
3943
0
  return CMD_SUCCESS;
3944
0
}
3945
3946
DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3947
        no_bgp_evpn_advertise_vni_subnet_cmd,
3948
        "no advertise-subnet",
3949
        NO_STR
3950
        "Advertise All local VNIs\n")
3951
0
{
3952
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3953
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3954
3955
0
  if (!bgp)
3956
0
    return CMD_WARNING;
3957
3958
0
  evpn_unset_advertise_subnet(bgp, vpn);
3959
0
  return CMD_SUCCESS;
3960
0
}
3961
3962
DEFUN (bgp_evpn_advertise_type5,
3963
       bgp_evpn_advertise_type5_cmd,
3964
       "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
3965
       "Advertise prefix routes\n"
3966
       BGP_AFI_HELP_STR
3967
       BGP_SAFI_HELP_STR
3968
       "advertise gateway IP overlay index\n"
3969
       "route-map for filtering specific routes\n"
3970
       "Name of the route map\n")
3971
0
{
3972
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3973
0
  int idx_afi = 0;
3974
0
  int idx_safi = 0;
3975
0
  int idx_rmap = 0;
3976
0
  afi_t afi = 0;
3977
0
  safi_t safi = 0;
3978
0
  int ret = 0;
3979
0
  int rmap_changed = 0;
3980
0
  enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3981
0
  int idx_oly = 0;
3982
0
  bool adv_flag_changed = false;
3983
3984
0
  argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3985
0
  argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3986
0
  argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3987
3988
0
  ret = argv_find(argv, argc, "route-map", &idx_rmap);
3989
0
  if (ret) {
3990
0
    if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3991
0
      rmap_changed = 1;
3992
0
    else if (strcmp(argv[idx_rmap + 1]->arg,
3993
0
        bgp_vrf->adv_cmd_rmap[afi][safi].name)
3994
0
       != 0)
3995
0
      rmap_changed = 1;
3996
0
  } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3997
0
    rmap_changed = 1;
3998
0
  }
3999
4000
0
  if (!(afi == AFI_IP || afi == AFI_IP6)) {
4001
0
    vty_out(vty,
4002
0
      "%% Only ipv4 or ipv6 address families are supported\n");
4003
0
    return CMD_WARNING;
4004
0
  }
4005
4006
0
  if (safi != SAFI_UNICAST) {
4007
0
    vty_out(vty,
4008
0
      "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4009
0
    return CMD_WARNING;
4010
0
  }
4011
4012
0
  if ((oly != OVERLAY_INDEX_TYPE_NONE)
4013
0
      && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
4014
0
    vty_out(vty, "%% Unknown overlay-index type specified\n");
4015
0
    return CMD_WARNING;
4016
0
  }
4017
4018
0
  if (afi == AFI_IP) {
4019
0
    if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4020
0
         BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
4021
0
        && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4022
0
            BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4023
4024
      /*
4025
       * this is the case for first time ever configuration
4026
       * adv ipv4 unicast is enabled for the first time.
4027
       * So no need to reset any flag
4028
       */
4029
0
      if (oly == OVERLAY_INDEX_TYPE_NONE)
4030
0
        SET_FLAG(
4031
0
          bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4032
0
          BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4033
0
      else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4034
0
        SET_FLAG(
4035
0
          bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4036
0
          BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4037
0
    } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4038
0
         && (!CHECK_FLAG(
4039
0
              bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4040
0
              BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
4041
4042
      /*
4043
       * This is modify case from gateway-ip
4044
       * to no overlay index
4045
       */
4046
0
      adv_flag_changed = true;
4047
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4048
0
           BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4049
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4050
0
         BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4051
0
    } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4052
0
         && (!CHECK_FLAG(
4053
0
              bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4054
0
              BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4055
4056
      /*
4057
       * This is modify case from no overlay index
4058
       * to gateway-ip
4059
       */
4060
0
      adv_flag_changed = true;
4061
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4062
0
           BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4063
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4064
0
         BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4065
0
    } else {
4066
4067
      /*
4068
       * Command is issued with the same option
4069
       * (no overlay index or gateway-ip) which was
4070
       * already configured. So nothing to do.
4071
       * However, route-map may have been modified.
4072
       * check if route-map has been modified.
4073
       * If not, return an error
4074
       */
4075
0
      if (!rmap_changed)
4076
0
        return CMD_WARNING;
4077
0
    }
4078
0
  } else {
4079
0
    if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4080
0
         BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
4081
0
        && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4082
0
            BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4083
4084
      /*
4085
       * this is the case for first time ever configuration
4086
       * adv ipv6 unicast is enabled for the first time.
4087
       * So no need to reset any flag
4088
       */
4089
0
      if (oly == OVERLAY_INDEX_TYPE_NONE)
4090
0
        SET_FLAG(
4091
0
          bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4092
0
          BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4093
0
      else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4094
0
        SET_FLAG(
4095
0
          bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4096
0
          BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4097
0
    } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4098
0
         && (!CHECK_FLAG(
4099
0
              bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4100
0
              BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
4101
4102
      /*
4103
       * This is modify case from gateway-ip
4104
       * to no overlay index
4105
       */
4106
0
      adv_flag_changed = true;
4107
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4108
0
           BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4109
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4110
0
         BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4111
0
    } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4112
0
         && (!CHECK_FLAG(
4113
0
              bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4114
0
              BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4115
4116
      /*
4117
       * This is modify case from no overlay index
4118
       * to gateway-ip
4119
       */
4120
0
      adv_flag_changed = true;
4121
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4122
0
           BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4123
0
      SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4124
0
         BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4125
0
    } else {
4126
4127
      /*
4128
       * Command is issued with the same option
4129
       * (no overlay index or gateway-ip) which was
4130
       * already configured. So nothing to do.
4131
       * However, route-map may have been modified.
4132
       * check if route-map has been modified.
4133
       * If not, return an error
4134
       */
4135
0
      if (!rmap_changed)
4136
0
        return CMD_WARNING;
4137
0
    }
4138
0
  }
4139
4140
0
  if ((rmap_changed) || (adv_flag_changed)) {
4141
4142
    /* If either of these are changed, then FRR needs to
4143
     * withdraw already advertised type5 routes.
4144
     */
4145
0
    bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4146
0
    if (rmap_changed) {
4147
0
      if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4148
0
        XFREE(MTYPE_ROUTE_MAP_NAME,
4149
0
              bgp_vrf->adv_cmd_rmap[afi][safi].name);
4150
0
        route_map_counter_decrement(
4151
0
          bgp_vrf->adv_cmd_rmap[afi][safi].map);
4152
0
        bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4153
0
        bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4154
0
      }
4155
0
    }
4156
0
  }
4157
4158
  /* set the route-map for advertise command */
4159
0
  if (ret && argv[idx_rmap + 1]->arg) {
4160
0
    bgp_vrf->adv_cmd_rmap[afi][safi].name =
4161
0
      XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
4162
0
    bgp_vrf->adv_cmd_rmap[afi][safi].map =
4163
0
      route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
4164
0
    route_map_counter_increment(
4165
0
        bgp_vrf->adv_cmd_rmap[afi][safi].map);
4166
0
  }
4167
4168
  /* advertise type-5 routes */
4169
0
  if (advertise_type5_routes(bgp_vrf, afi))
4170
0
    bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
4171
0
  return CMD_SUCCESS;
4172
0
}
4173
4174
DEFUN (no_bgp_evpn_advertise_type5,
4175
       no_bgp_evpn_advertise_type5_cmd,
4176
       "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
4177
       NO_STR
4178
       "Advertise prefix routes\n"
4179
       BGP_AFI_HELP_STR
4180
       BGP_SAFI_HELP_STR
4181
       "route-map for filtering specific routes\n"
4182
       "Name of the route map\n")
4183
0
{
4184
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4185
0
  int idx_afi = 0;
4186
0
  int idx_safi = 0;
4187
0
  afi_t afi = 0;
4188
0
  safi_t safi = 0;
4189
4190
0
  if (!bgp_vrf)
4191
0
    return CMD_WARNING;
4192
4193
0
  argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4194
0
  argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4195
4196
0
  if (!(afi == AFI_IP || afi == AFI_IP6)) {
4197
0
    vty_out(vty,
4198
0
      "%% Only ipv4 or ipv6 address families are supported\n");
4199
0
    return CMD_WARNING;
4200
0
  }
4201
4202
0
  if (safi != SAFI_UNICAST) {
4203
0
    vty_out(vty,
4204
0
      "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4205
0
    return CMD_WARNING;
4206
0
  }
4207
4208
0
  if (afi == AFI_IP) {
4209
4210
    /* if we are not advertising ipv4 prefix as type-5
4211
     * nothing to do
4212
     */
4213
0
    if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4214
0
        BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4215
0
        (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4216
0
        BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4217
0
      bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4218
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4219
0
           BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4220
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4221
0
           BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4222
0
    }
4223
0
  } else {
4224
4225
    /* if we are not advertising ipv6 prefix as type-5
4226
     * nothing to do
4227
     */
4228
0
    if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4229
0
        BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4230
0
        (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4231
0
        BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
4232
0
      bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4233
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4234
0
           BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4235
0
      UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4236
0
           BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4237
0
    }
4238
0
  }
4239
4240
  /* clear the route-map information for advertise ipv4/ipv6 unicast */
4241
0
  if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4242
0
    XFREE(MTYPE_ROUTE_MAP_NAME,
4243
0
          bgp_vrf->adv_cmd_rmap[afi][safi].name);
4244
0
    bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4245
0
    bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4246
0
  }
4247
4248
0
  return CMD_SUCCESS;
4249
0
}
4250
4251
DEFPY (bgp_evpn_use_es_l3nhg,
4252
       bgp_evpn_use_es_l3nhg_cmd,
4253
       "[no$no] use-es-l3nhg",
4254
       NO_STR
4255
       "use L3 nexthop group for host routes with ES destination\n")
4256
0
{
4257
0
  bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4258
0
  return CMD_SUCCESS;
4259
0
}
4260
4261
DEFPY (bgp_evpn_ead_evi_rx_disable,
4262
       bgp_evpn_ead_evi_rx_disable_cmd,
4263
       "[no$no] disable-ead-evi-rx",
4264
       NO_STR
4265
       "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4266
0
{
4267
0
  bool ead_evi_rx = no? true :false;
4268
4269
0
  if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4270
0
    bgp_mh_info->ead_evi_rx = ead_evi_rx;
4271
0
    bgp_evpn_switch_ead_evi_rx();
4272
0
  }
4273
0
  return CMD_SUCCESS;
4274
0
}
4275
4276
DEFPY (bgp_evpn_ead_evi_tx_disable,
4277
       bgp_evpn_ead_evi_tx_disable_cmd,
4278
       "[no$no] disable-ead-evi-tx",
4279
       NO_STR
4280
       "Don't advertise EAD-EVI for local ESs\n")
4281
0
{
4282
0
  bgp_mh_info->ead_evi_tx = no? true :false;
4283
0
  return CMD_SUCCESS;
4284
0
}
4285
4286
DEFPY (bgp_evpn_enable_resolve_overlay_index,
4287
       bgp_evpn_enable_resolve_overlay_index_cmd,
4288
       "[no$no] enable-resolve-overlay-index",
4289
       NO_STR
4290
       "Enable Recursive Resolution of type-5 route overlay index\n")
4291
0
{
4292
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4293
4294
0
  if (bgp != bgp_get_evpn()) {
4295
0
    vty_out(vty, "This command is only supported under EVPN VRF\n");
4296
0
    return CMD_WARNING;
4297
0
  }
4298
4299
0
  bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4300
0
  return CMD_SUCCESS;
4301
0
}
4302
4303
DEFPY (bgp_evpn_advertise_pip_ip_mac,
4304
       bgp_evpn_advertise_pip_ip_mac_cmd,
4305
       "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4306
       NO_STR
4307
       "evpn system primary IP\n"
4308
       IP_STR
4309
       "ip address\n"
4310
       MAC_STR MAC_STR MAC_STR)
4311
0
{
4312
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4313
0
  struct bgp *bgp_evpn = NULL;
4314
4315
0
  if (!bgp_vrf || EVPN_ENABLED(bgp_vrf)) {
4316
0
    vty_out(vty,
4317
0
      "This command is supported under L3VNI BGP EVPN VRF\n");
4318
0
    return CMD_WARNING_CONFIG_FAILED;
4319
0
  }
4320
0
  bgp_evpn = bgp_get_evpn();
4321
4322
0
  if (!no) {
4323
    /* pip is already enabled */
4324
0
    if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4325
0
      return CMD_SUCCESS;
4326
4327
0
    bgp_vrf->evpn_info->advertise_pip = true;
4328
0
    if (ip.s_addr != INADDR_ANY) {
4329
      /* Already configured with same IP */
4330
0
      if (IPV4_ADDR_SAME(&ip,
4331
0
          &bgp_vrf->evpn_info->pip_ip_static))
4332
0
        return CMD_SUCCESS;
4333
4334
0
      bgp_vrf->evpn_info->pip_ip_static = ip;
4335
0
      bgp_vrf->evpn_info->pip_ip = ip;
4336
0
    } else {
4337
0
      bgp_vrf->evpn_info->pip_ip_static.s_addr
4338
0
        = INADDR_ANY;
4339
      /* default instance router-id assignemt */
4340
0
      if (bgp_evpn)
4341
0
        bgp_vrf->evpn_info->pip_ip =
4342
0
          bgp_evpn->router_id;
4343
0
    }
4344
    /* parse sys mac */
4345
0
    if (!is_zero_mac(&mac->eth_addr)) {
4346
      /* Already configured with same MAC */
4347
0
      if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4348
0
           &mac->eth_addr, ETH_ALEN) == 0)
4349
0
        return CMD_SUCCESS;
4350
4351
0
      memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4352
0
             &mac->eth_addr, ETH_ALEN);
4353
0
      memcpy(&bgp_vrf->evpn_info->pip_rmac,
4354
0
             &bgp_vrf->evpn_info->pip_rmac_static,
4355
0
             ETH_ALEN);
4356
0
    } else {
4357
      /* Copy zebra sys mac */
4358
0
      if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4359
0
        memcpy(&bgp_vrf->evpn_info->pip_rmac,
4360
0
               &bgp_vrf->evpn_info->pip_rmac_zebra,
4361
0
               ETH_ALEN);
4362
0
    }
4363
0
  } else {
4364
0
    if (argc == 2) {
4365
0
      if (!bgp_vrf->evpn_info->advertise_pip)
4366
0
        return CMD_SUCCESS;
4367
      /* Disable PIP feature */
4368
0
      bgp_vrf->evpn_info->advertise_pip = false;
4369
      /* copy anycast mac */
4370
0
      memcpy(&bgp_vrf->evpn_info->pip_rmac,
4371
0
             &bgp_vrf->rmac, ETH_ALEN);
4372
0
    } else {
4373
      /* remove MAC-IP option retain PIP knob. */
4374
0
      if ((ip.s_addr != INADDR_ANY) &&
4375
0
          !IPV4_ADDR_SAME(&ip,
4376
0
          &bgp_vrf->evpn_info->pip_ip_static)) {
4377
0
        vty_out(vty,
4378
0
          "%% BGP EVPN PIP IP does not match\n");
4379
0
        return CMD_WARNING_CONFIG_FAILED;
4380
0
      }
4381
4382
0
      if (!is_zero_mac(&mac->eth_addr) &&
4383
0
          memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4384
0
           &mac->eth_addr, ETH_ALEN) != 0) {
4385
0
        vty_out(vty,
4386
0
          "%% BGP EVPN PIP MAC does not match\n");
4387
0
        return CMD_WARNING_CONFIG_FAILED;
4388
0
      }
4389
      /* pip_rmac can carry vrr_rmac reset only if it matches
4390
       * with static value.
4391
       */
4392
0
      if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4393
0
           &bgp_vrf->evpn_info->pip_rmac_static,
4394
0
           ETH_ALEN) == 0) {
4395
        /* Copy zebra sys mac */
4396
0
        if (!is_zero_mac(
4397
0
          &bgp_vrf->evpn_info->pip_rmac_zebra))
4398
0
          memcpy(&bgp_vrf->evpn_info->pip_rmac,
4399
0
          &bgp_vrf->evpn_info->pip_rmac_zebra,
4400
0
                 ETH_ALEN);
4401
0
        else {
4402
          /* copy anycast mac */
4403
0
          memcpy(&bgp_vrf->evpn_info->pip_rmac,
4404
0
                 &bgp_vrf->rmac, ETH_ALEN);
4405
0
        }
4406
0
      }
4407
0
    }
4408
    /* reset user configured sys MAC */
4409
0
    memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4410
    /* reset user configured sys IP */
4411
0
    bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4412
    /* Assign default PIP IP (bgp instance router-id) */
4413
0
    if (bgp_evpn)
4414
0
      bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4415
0
    else
4416
0
      bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4417
0
  }
4418
4419
0
  if (is_evpn_enabled()) {
4420
0
    struct listnode *node = NULL;
4421
0
    struct bgpevpn *vpn = NULL;
4422
4423
    /*
4424
     * At this point if bgp_evpn is NULL and evpn is enabled
4425
     * something stupid has gone wrong
4426
     */
4427
0
    assert(bgp_evpn);
4428
4429
0
    update_advertise_vrf_routes(bgp_vrf);
4430
4431
    /* Update (svi) type-2 routes */
4432
0
    for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4433
0
      if (!bgp_evpn_is_svi_macip_enabled(vpn))
4434
0
        continue;
4435
0
      update_routes_for_vni(bgp_evpn, vpn);
4436
0
    }
4437
0
  }
4438
4439
0
  return CMD_SUCCESS;
4440
0
}
4441
4442
/*
4443
 * Display VNI information - for all or a specific VNI
4444
 */
4445
DEFUN(show_bgp_l2vpn_evpn_vni,
4446
      show_bgp_l2vpn_evpn_vni_cmd,
4447
      "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
4448
      SHOW_STR
4449
      BGP_STR
4450
      L2VPN_HELP_STR
4451
      EVPN_HELP_STR
4452
      "Show VNI\n"
4453
      "VNI number\n"
4454
      JSON_STR)
4455
0
{
4456
0
  struct bgp *bgp_evpn;
4457
0
  vni_t vni;
4458
0
  int idx = 0;
4459
0
  bool uj = false;
4460
0
  json_object *json = NULL;
4461
0
  uint32_t num_l2vnis = 0;
4462
0
  uint32_t num_l3vnis = 0;
4463
0
  uint32_t num_vnis = 0;
4464
0
  struct listnode *node = NULL;
4465
0
  struct bgp *bgp_temp = NULL;
4466
4467
0
  uj = use_json(argc, argv);
4468
4469
0
  bgp_evpn = bgp_get_evpn();
4470
0
  if (!bgp_evpn)
4471
0
    return CMD_WARNING;
4472
4473
0
  if (!argv_find(argv, argc, "evpn", &idx))
4474
0
    return CMD_WARNING;
4475
4476
0
  if (uj)
4477
0
    json = json_object_new_object();
4478
4479
0
  if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4480
4481
0
    num_l2vnis = hashcount(bgp_evpn->vnihash);
4482
4483
0
    for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4484
0
      if (bgp_temp->l3vni)
4485
0
        num_l3vnis++;
4486
0
    }
4487
0
    num_vnis = num_l2vnis + num_l3vnis;
4488
0
    if (uj) {
4489
0
      json_object_string_add(json, "advertiseGatewayMacip",
4490
0
                 bgp_evpn->advertise_gw_macip
4491
0
                   ? "Enabled"
4492
0
                   : "Disabled");
4493
0
      json_object_string_add(json, "advertiseSviMacIp",
4494
0
          bgp_evpn->evpn_info->advertise_svi_macip
4495
0
          ? "Enabled" : "Disabled");
4496
0
      json_object_string_add(json, "advertiseAllVnis",
4497
0
                 is_evpn_enabled() ? "Enabled"
4498
0
                 : "Disabled");
4499
0
      json_object_string_add(
4500
0
        json, "flooding",
4501
0
        bgp_evpn->vxlan_flood_ctrl ==
4502
0
            VXLAN_FLOOD_HEAD_END_REPL
4503
0
          ? "Head-end replication"
4504
0
          : "Disabled");
4505
0
      json_object_string_add(
4506
0
        json, "vxlanFlooding",
4507
0
        bgp_evpn->vxlan_flood_ctrl ==
4508
0
            VXLAN_FLOOD_HEAD_END_REPL
4509
0
          ? "Enabled"
4510
0
          : "Disabled");
4511
0
      json_object_int_add(json, "numVnis", num_vnis);
4512
0
      json_object_int_add(json, "numL2Vnis", num_l2vnis);
4513
0
      json_object_int_add(json, "numL3Vnis", num_l3vnis);
4514
0
    } else {
4515
0
      vty_out(vty, "Advertise Gateway Macip: %s\n",
4516
0
        bgp_evpn->advertise_gw_macip ? "Enabled"
4517
0
                  : "Disabled");
4518
0
      vty_out(vty, "Advertise SVI Macip: %s\n",
4519
0
        bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
4520
0
              : "Disabled");
4521
0
      vty_out(vty, "Advertise All VNI flag: %s\n",
4522
0
        is_evpn_enabled() ? "Enabled" : "Disabled");
4523
0
      vty_out(vty, "BUM flooding: %s\n",
4524
0
        bgp_evpn->vxlan_flood_ctrl ==
4525
0
            VXLAN_FLOOD_HEAD_END_REPL
4526
0
          ? "Head-end replication"
4527
0
          : "Disabled");
4528
0
      vty_out(vty, "VXLAN flooding: %s\n",
4529
0
        bgp_evpn->vxlan_flood_ctrl ==
4530
0
            VXLAN_FLOOD_HEAD_END_REPL
4531
0
          ? "Enabled"
4532
0
          : "Disabled");
4533
0
      vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4534
0
      vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
4535
0
    }
4536
0
    evpn_show_all_vnis(vty, bgp_evpn, json);
4537
0
  } else {
4538
0
    int vni_idx = 0;
4539
4540
0
    if (!argv_find(argv, argc, "vni", &vni_idx))
4541
0
      return CMD_WARNING;
4542
4543
    /* Display specific VNI */
4544
0
    vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4545
0
    evpn_show_vni(vty, bgp_evpn, vni, json);
4546
0
  }
4547
4548
0
  if (uj)
4549
0
    vty_json(vty, json);
4550
4551
0
  return CMD_SUCCESS;
4552
0
}
4553
4554
DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4555
       show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4556
       "show bgp l2vpn evpn vni remote-ip-hash",
4557
       SHOW_STR
4558
       BGP_STR
4559
       L2VPN_HELP_STR
4560
       EVPN_HELP_STR
4561
       "Show VNI\n"
4562
       "Remote IP hash\n")
4563
0
{
4564
0
  struct bgp *bgp_evpn;
4565
0
  int idx = 0;
4566
4567
0
  bgp_evpn = bgp_get_evpn();
4568
0
  if (!bgp_evpn)
4569
0
    return CMD_WARNING;
4570
4571
0
  if (!argv_find(argv, argc, "evpn", &idx))
4572
0
    return CMD_WARNING;
4573
4574
0
  hash_iterate(bgp_evpn->vnihash,
4575
0
         (void (*)(struct hash_bucket *,
4576
0
             void *))bgp_evpn_show_remote_ip_hash,
4577
0
         vty);
4578
4579
0
  return CMD_SUCCESS;
4580
0
}
4581
4582
DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4583
       show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4584
       "show bgp l2vpn evpn vni-svi-hash",
4585
       SHOW_STR
4586
       BGP_STR
4587
       L2VPN_HELP_STR
4588
       EVPN_HELP_STR
4589
       "Show vni-svi-hash\n")
4590
0
{
4591
0
  struct bgp *bgp_evpn;
4592
0
  int idx = 0;
4593
4594
0
  bgp_evpn = bgp_get_evpn();
4595
0
  if (!bgp_evpn)
4596
0
    return CMD_WARNING;
4597
4598
0
  if (!argv_find(argv, argc, "evpn", &idx))
4599
0
    return CMD_WARNING;
4600
4601
0
  hash_iterate(bgp_evpn->vni_svi_hash,
4602
0
         (void (*)(struct hash_bucket *,
4603
0
             void *))bgp_evpn_show_vni_svi_hash,
4604
0
         vty);
4605
4606
0
  return CMD_SUCCESS;
4607
0
}
4608
4609
DEFPY(show_bgp_l2vpn_evpn_es_evi,
4610
      show_bgp_l2vpn_evpn_es_evi_cmd,
4611
      "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4612
      SHOW_STR
4613
      BGP_STR
4614
      L2VPN_HELP_STR
4615
      EVPN_HELP_STR
4616
      "ES per EVI\n"
4617
      "VxLAN Network Identifier\n"
4618
      "VNI\n"
4619
      JSON_STR
4620
      "Detailed information\n")
4621
0
{
4622
0
  if (vni)
4623
0
    bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4624
0
  else
4625
0
    bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4626
4627
0
  return CMD_SUCCESS;
4628
0
}
4629
4630
DEFPY(show_bgp_l2vpn_evpn_es,
4631
      show_bgp_l2vpn_evpn_es_cmd,
4632
      "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4633
      SHOW_STR
4634
      BGP_STR
4635
      L2VPN_HELP_STR
4636
      EVPN_HELP_STR
4637
      "Ethernet Segment\n"
4638
      "ES ID\n"
4639
      "Detailed information\n"
4640
      JSON_STR)
4641
0
{
4642
0
  esi_t esi;
4643
4644
0
  if (esi_str) {
4645
0
    if (!str_to_esi(esi_str, &esi)) {
4646
0
      vty_out(vty, "%% Malformed ESI\n");
4647
0
      return CMD_WARNING;
4648
0
    }
4649
0
    bgp_evpn_es_show_esi(vty, &esi, uj);
4650
0
  } else {
4651
4652
0
    bgp_evpn_es_show(vty, uj, !!detail);
4653
0
  }
4654
4655
0
  return CMD_SUCCESS;
4656
0
}
4657
4658
DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4659
      "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4660
      SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4661
      "Ethernet Segment\n"
4662
      "ES ID\n" JSON_STR)
4663
0
{
4664
0
  esi_t esi;
4665
4666
0
  if (esi_str) {
4667
0
    if (!str_to_esi(esi_str, &esi)) {
4668
0
      vty_out(vty, "%% Malformed ESI\n");
4669
0
      return CMD_WARNING;
4670
0
    }
4671
0
    bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4672
0
  } else {
4673
4674
0
    bgp_evpn_es_vrf_show(vty, uj, NULL);
4675
0
  }
4676
4677
0
  return CMD_SUCCESS;
4678
0
}
4679
4680
DEFPY(show_bgp_l2vpn_evpn_nh,
4681
      show_bgp_l2vpn_evpn_nh_cmd,
4682
      "show bgp l2vpn evpn next-hops [json$uj]",
4683
      SHOW_STR
4684
      BGP_STR
4685
      L2VPN_HELP_STR
4686
      EVPN_HELP_STR
4687
      "Nexthops\n"
4688
      JSON_STR)
4689
0
{
4690
0
  bgp_evpn_nh_show(vty, uj);
4691
4692
0
  return CMD_SUCCESS;
4693
0
}
4694
4695
/*
4696
 * Display EVPN neighbor summary.
4697
 */
4698
DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
4699
      "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
4700
      SHOW_STR BGP_STR
4701
      "bgp vrf\n"
4702
      "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4703
      "Summary of BGP neighbor status\n"
4704
      "Show only sessions in Established state\n"
4705
      "Show only sessions not in Established state\n"
4706
      "Show only the specified neighbor session\n"
4707
      "Neighbor to display information about\n"
4708
      "Neighbor to display information about\n"
4709
      "Neighbor on BGP configured interface\n"
4710
      "Show only the specified remote AS sessions\n"
4711
      "AS number\n"
4712
      "Internal (iBGP) AS sessions\n"
4713
      "External (eBGP) AS sessions\n"
4714
      "Shorten the information on BGP instances\n"
4715
      "Increase table width for longer output\n" JSON_STR)
4716
0
{
4717
0
  int idx_vrf = 0;
4718
0
  int idx = 0;
4719
0
  char *vrf = NULL;
4720
0
  char *neighbor = NULL;
4721
0
  as_t as = 0; /* 0 means AS filter not set */
4722
0
  int as_type = AS_UNSPECIFIED;
4723
0
  uint16_t show_flags = 0;
4724
4725
0
  if (argv_find(argv, argc, "vrf", &idx_vrf))
4726
0
    vrf = argv[++idx_vrf]->arg;
4727
4728
0
  if (argv_find(argv, argc, "failed", &idx))
4729
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4730
4731
0
  if (argv_find(argv, argc, "established", &idx))
4732
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4733
4734
4735
0
  if (argv_find(argv, argc, "neighbor", &idx))
4736
0
    neighbor = argv[idx + 1]->arg;
4737
4738
0
  if (argv_find(argv, argc, "remote-as", &idx)) {
4739
0
    if (argv[idx + 1]->arg[0] == 'i')
4740
0
      as_type = AS_INTERNAL;
4741
0
    else if (argv[idx + 1]->arg[0] == 'e')
4742
0
      as_type = AS_EXTERNAL;
4743
0
    else
4744
0
      as = (as_t)atoi(argv[idx + 1]->arg);
4745
0
  }
4746
4747
0
  if (argv_find(argv, argc, "terse", &idx))
4748
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4749
4750
0
  if (argv_find(argv, argc, "wide", &idx))
4751
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4752
4753
0
  if (use_json(argc, argv))
4754
0
    SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4755
4756
0
  return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4757
0
            as_type, as, show_flags);
4758
0
}
4759
4760
static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
4761
0
{
4762
0
  if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
4763
0
    *type = BGP_EVPN_MAC_IP_ROUTE;
4764
0
  else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
4765
0
    *type = BGP_EVPN_IMET_ROUTE;
4766
0
  else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
4767
0
    *type = BGP_EVPN_ES_ROUTE;
4768
0
  else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
4769
0
    *type = BGP_EVPN_AD_ROUTE;
4770
0
  else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
4771
0
    *type = BGP_EVPN_IP_PREFIX_ROUTE;
4772
0
  else
4773
0
    return -1;
4774
4775
0
  return 0;
4776
0
}
4777
4778
int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
4779
0
{
4780
0
  int type_idx = 0;
4781
4782
0
  if (argv_find(argv, argc, "type", &type_idx)) {
4783
    /* Specific type is requested */
4784
0
    if (bgp_evpn_cli_parse_type_cmp(type,
4785
0
            argv[type_idx + 1]->arg) != 0)
4786
0
      return -1;
4787
0
  }
4788
4789
0
  return 0;
4790
0
}
4791
4792
/*
4793
 * Display global EVPN routing table.
4794
 */
4795
DEFUN(show_bgp_l2vpn_evpn_route,
4796
      show_bgp_l2vpn_evpn_route_cmd,
4797
      "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] ["BGP_SELF_ORIG_CMD_STR"] [json]",
4798
      SHOW_STR
4799
      BGP_STR
4800
      L2VPN_HELP_STR
4801
      EVPN_HELP_STR
4802
      EVPN_RT_HELP_STR
4803
      "Display Detailed Information\n"
4804
      EVPN_TYPE_HELP_STR
4805
      EVPN_TYPE_ALL_LIST_HELP_STR
4806
      BGP_SELF_ORIG_HELP_STR
4807
      JSON_STR)
4808
0
{
4809
0
  struct bgp *bgp;
4810
0
  int detail = 0;
4811
0
  int type = 0;
4812
0
  bool uj = false;
4813
0
  int arg_idx = 0;
4814
0
  bool self_orig = false;
4815
0
  json_object *json = NULL;
4816
4817
0
  uj = use_json(argc, argv);
4818
4819
0
  bgp = bgp_get_evpn();
4820
0
  if (!bgp)
4821
0
    return CMD_WARNING;
4822
4823
0
  if (uj)
4824
0
    json = json_object_new_object();
4825
4826
0
  if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4827
0
    return CMD_WARNING;
4828
4829
0
  if (argv_find(argv, argc, "detail", &detail))
4830
0
    detail = 1;
4831
4832
0
  if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &arg_idx))
4833
0
    self_orig = true;
4834
4835
0
  evpn_show_all_routes(vty, bgp, type, json, detail, self_orig);
4836
4837
  /*
4838
   * This is an extremely expensive operation at scale
4839
   * and as such we need to save as much time as is
4840
   * possible.
4841
   */
4842
0
  if (uj)
4843
0
    vty_json_no_pretty(vty, json);
4844
4845
0
  return CMD_SUCCESS;
4846
0
}
4847
4848
/*
4849
 * Display global EVPN routing table for specific RD.
4850
 */
4851
DEFUN(show_bgp_l2vpn_evpn_route_rd,
4852
      show_bgp_l2vpn_evpn_route_rd_cmd,
4853
      "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
4854
      SHOW_STR
4855
      BGP_STR
4856
      L2VPN_HELP_STR
4857
      EVPN_HELP_STR
4858
      EVPN_RT_HELP_STR
4859
      EVPN_RT_DIST_HELP_STR
4860
      EVPN_ASN_IP_HELP_STR
4861
      "All VPN Route Distinguishers\n"
4862
      EVPN_TYPE_HELP_STR
4863
      EVPN_TYPE_ALL_LIST_HELP_STR
4864
      JSON_STR)
4865
0
{
4866
0
  struct bgp *bgp;
4867
0
  int ret = 0;
4868
0
  struct prefix_rd prd;
4869
0
  int type = 0;
4870
0
  bool uj = false;
4871
0
  json_object *json = NULL;
4872
0
  int idx_ext_community = 0;
4873
0
  int rd_all = 0;
4874
4875
0
  bgp = bgp_get_evpn();
4876
0
  if (!bgp)
4877
0
    return CMD_WARNING;
4878
4879
  /* check if we need json output */
4880
0
  uj = use_json(argc, argv);
4881
0
  if (uj)
4882
0
    json = json_object_new_object();
4883
4884
0
  if (!argv_find(argv, argc, "all", &rd_all)) {
4885
    /* get the RD */
4886
0
    if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4887
0
            &idx_ext_community)) {
4888
0
      ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4889
0
      if (!ret) {
4890
0
        vty_out(vty,
4891
0
          "%% Malformed Route Distinguisher\n");
4892
0
        return CMD_WARNING;
4893
0
      }
4894
0
    }
4895
0
  }
4896
4897
0
  if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4898
0
    return CMD_WARNING;
4899
4900
0
  if (rd_all)
4901
0
    evpn_show_all_routes(vty, bgp, type, json, 1, false);
4902
0
  else
4903
0
    evpn_show_route_rd(vty, bgp, &prd, type, json);
4904
4905
0
  if (uj)
4906
0
    vty_json(vty, json);
4907
4908
0
  return CMD_SUCCESS;
4909
0
}
4910
4911
/*
4912
 * Display global EVPN routing table for specific RD and MACIP.
4913
 */
4914
DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4915
      show_bgp_l2vpn_evpn_route_rd_macip_cmd,
4916
      "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4917
      SHOW_STR
4918
      BGP_STR
4919
      L2VPN_HELP_STR
4920
      EVPN_HELP_STR
4921
      EVPN_RT_HELP_STR
4922
      EVPN_RT_DIST_HELP_STR
4923
      EVPN_ASN_IP_HELP_STR
4924
      "All VPN Route Distinguishers\n"
4925
      "MAC\n"
4926
      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4927
      "IP\n"
4928
      "IP address (IPv4 or IPv6)\n"
4929
      JSON_STR)
4930
0
{
4931
0
  struct bgp *bgp;
4932
0
  int ret = 0;
4933
0
  struct prefix_rd prd;
4934
0
  struct ethaddr mac;
4935
0
  struct ipaddr ip;
4936
0
  int idx_ext_community = 0;
4937
0
  int mac_idx = 0;
4938
0
  int ip_idx = 0;
4939
0
  bool uj = false;
4940
0
  json_object *json = NULL;
4941
0
  int rd_all = 0;
4942
4943
0
  memset(&mac, 0, sizeof(struct ethaddr));
4944
0
  memset(&ip, 0, sizeof(struct ipaddr));
4945
4946
0
  bgp = bgp_get_evpn();
4947
0
  if (!bgp)
4948
0
    return CMD_WARNING;
4949
4950
  /* check if we need json output */
4951
0
  uj = use_json(argc, argv);
4952
0
  if (uj)
4953
0
    json = json_object_new_object();
4954
4955
  /* get the prd */
4956
0
  if (!argv_find(argv, argc, "all", &rd_all)) {
4957
0
    if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4958
0
            &idx_ext_community)) {
4959
0
      ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4960
0
      if (!ret) {
4961
0
        vty_out(vty,
4962
0
          "%% Malformed Route Distinguisher\n");
4963
0
        return CMD_WARNING;
4964
0
      }
4965
0
    }
4966
0
  }
4967
4968
  /* get the mac */
4969
0
  if (argv_find(argv, argc, "mac", &mac_idx)) {
4970
0
    if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4971
0
      vty_out(vty, "%% Malformed MAC address\n");
4972
0
      return CMD_WARNING;
4973
0
    }
4974
0
  }
4975
4976
  /* get the ip if specified */
4977
0
  if (argv_find(argv, argc, "ip", &ip_idx)) {
4978
0
    if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4979
0
      vty_out(vty, "%% Malformed IP address\n");
4980
0
      return CMD_WARNING;
4981
0
    }
4982
0
  }
4983
4984
0
  if (rd_all)
4985
0
    evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4986
0
  else
4987
0
    evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4988
4989
0
  if (uj)
4990
0
    vty_json(vty, json);
4991
4992
0
  return CMD_SUCCESS;
4993
0
}
4994
4995
/* Display per ESI routing table */
4996
DEFUN(show_bgp_l2vpn_evpn_route_esi,
4997
      show_bgp_l2vpn_evpn_route_esi_cmd,
4998
      "show bgp l2vpn evpn route esi ESI [json]",
4999
      SHOW_STR
5000
      BGP_STR
5001
      L2VPN_HELP_STR
5002
      EVPN_HELP_STR
5003
      EVPN_RT_HELP_STR
5004
      "Ethernet Segment Identifier\n"
5005
      "ESI ID\n"
5006
      JSON_STR)
5007
0
{
5008
0
  bool uj = false;
5009
0
  esi_t esi;
5010
0
  struct bgp *bgp = NULL;
5011
0
  json_object *json = NULL;
5012
5013
0
  memset(&esi, 0, sizeof(esi));
5014
0
  bgp = bgp_get_evpn();
5015
0
  if (!bgp)
5016
0
    return CMD_WARNING;
5017
5018
0
  uj = use_json(argc, argv);
5019
0
  if (uj)
5020
0
    json = json_object_new_object();
5021
5022
  /* get the ESI - ESI-ID is at argv[6] */
5023
0
  if (!str_to_esi(argv[6]->arg, &esi)) {
5024
0
    vty_out(vty, "%% Malformed ESI\n");
5025
0
    return CMD_WARNING;
5026
0
  }
5027
5028
0
  evpn_show_routes_esi(vty, bgp, &esi, json);
5029
5030
0
  if (uj)
5031
0
    vty_json(vty, json);
5032
5033
0
  return CMD_SUCCESS;
5034
0
}
5035
5036
5037
/*
5038
 * Display per-VNI EVPN routing table.
5039
 */
5040
DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
5041
      "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5042
      SHOW_STR
5043
      BGP_STR
5044
      L2VPN_HELP_STR
5045
      EVPN_HELP_STR
5046
      EVPN_RT_HELP_STR
5047
      "VXLAN Network Identifier\n"
5048
      "VNI number\n"
5049
      EVPN_TYPE_HELP_STR
5050
      EVPN_TYPE_1_HELP_STR
5051
      EVPN_TYPE_1_HELP_STR
5052
      EVPN_TYPE_2_HELP_STR
5053
      EVPN_TYPE_2_HELP_STR
5054
      EVPN_TYPE_3_HELP_STR
5055
      EVPN_TYPE_3_HELP_STR
5056
      "Remote VTEP\n"
5057
      "Remote VTEP IP address\n"
5058
      JSON_STR)
5059
0
{
5060
0
  vni_t vni;
5061
0
  struct bgp *bgp;
5062
0
  struct in_addr vtep_ip;
5063
0
  int type = 0;
5064
0
  int idx = 0;
5065
0
  int vtep_idx = 0;
5066
0
  bool uj = false;
5067
0
  json_object *json = NULL;
5068
5069
0
  bgp = bgp_get_evpn();
5070
0
  if (!bgp)
5071
0
    return CMD_WARNING;
5072
5073
  /* check if we need json output */
5074
0
  uj = use_json(argc, argv);
5075
0
  if (uj)
5076
0
    json = json_object_new_object();
5077
5078
0
  if (!argv_find(argv, argc, "evpn", &idx))
5079
0
    return CMD_WARNING;
5080
5081
0
  vtep_ip.s_addr = 0;
5082
5083
0
  vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5084
5085
0
  if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
5086
0
    return CMD_WARNING;
5087
5088
0
  if (argv_find(argv, argc, "vtep", &vtep_idx)) {
5089
0
    if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
5090
0
      vty_out(vty, "%% Malformed VTEP IP address\n");
5091
0
      return CMD_WARNING;
5092
0
    }
5093
0
  }
5094
5095
0
  evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
5096
5097
0
  if (uj)
5098
0
    vty_json(vty, json);
5099
5100
0
  return CMD_SUCCESS;
5101
0
}
5102
5103
/*
5104
 * Display per-VNI EVPN routing table for specific MACIP.
5105
 */
5106
DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
5107
      show_bgp_l2vpn_evpn_route_vni_macip_cmd,
5108
      "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
5109
      SHOW_STR
5110
      BGP_STR
5111
      L2VPN_HELP_STR
5112
      EVPN_HELP_STR
5113
      EVPN_RT_HELP_STR
5114
      "VXLAN Network Identifier\n"
5115
      "VNI number\n"
5116
      "MAC\n"
5117
      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5118
      "IP\n"
5119
      "IP address (IPv4 or IPv6)\n"
5120
      JSON_STR)
5121
0
{
5122
0
  vni_t vni;
5123
0
  struct bgp *bgp;
5124
0
  struct ethaddr mac;
5125
0
  struct ipaddr ip;
5126
0
  int idx = 0;
5127
0
  bool uj = false;
5128
0
  json_object *json = NULL;
5129
5130
0
  bgp = bgp_get_evpn();
5131
0
  if (!bgp)
5132
0
    return CMD_WARNING;
5133
5134
  /* check if we need json output */
5135
0
  uj = use_json(argc, argv);
5136
0
  if (uj)
5137
0
    json = json_object_new_object();
5138
5139
0
  if (!argv_find(argv, argc, "evpn", &idx))
5140
0
    return CMD_WARNING;
5141
5142
  /* get the VNI */
5143
0
  vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5144
5145
  /* get the mac */
5146
0
  if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
5147
0
    vty_out(vty, "%% Malformed MAC address\n");
5148
0
    return CMD_WARNING;
5149
0
  }
5150
5151
  /* get the ip */
5152
0
  memset(&ip, 0, sizeof(ip));
5153
0
  if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
5154
0
      || (uj
5155
0
    && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
5156
0
    if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
5157
0
      vty_out(vty, "%% Malformed IP address\n");
5158
0
      return CMD_WARNING;
5159
0
    }
5160
0
  }
5161
5162
0
  evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
5163
5164
0
  if (uj)
5165
0
    vty_json(vty, json);
5166
5167
0
  return CMD_SUCCESS;
5168
0
}
5169
5170
/*
5171
 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5172
 */
5173
DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
5174
      show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
5175
      "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
5176
      SHOW_STR
5177
      BGP_STR
5178
      L2VPN_HELP_STR
5179
      EVPN_HELP_STR
5180
      EVPN_RT_HELP_STR
5181
      "VXLAN Network Identifier\n"
5182
      "VNI number\n"
5183
      EVPN_TYPE_3_HELP_STR
5184
      "Originating Router IP address\n"
5185
      JSON_STR)
5186
0
{
5187
0
  vni_t vni;
5188
0
  struct bgp *bgp;
5189
0
  int ret;
5190
0
  struct in_addr orig_ip;
5191
0
  int idx = 0;
5192
0
  bool uj = false;
5193
0
  json_object *json = NULL;
5194
5195
0
  bgp = bgp_get_evpn();
5196
0
  if (!bgp)
5197
0
    return CMD_WARNING;
5198
5199
  /* check if we need json output */
5200
0
  uj = use_json(argc, argv);
5201
0
  if (uj)
5202
0
    json = json_object_new_object();
5203
5204
0
  if (!argv_find(argv, argc, "evpn", &idx))
5205
0
    return CMD_WARNING;
5206
5207
  /* get the VNI */
5208
0
  vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5209
5210
  /* get the ip */
5211
0
  ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
5212
0
  if (!ret) {
5213
0
    vty_out(vty, "%% Malformed Originating Router IP address\n");
5214
0
    return CMD_WARNING;
5215
0
  }
5216
5217
0
  evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5218
5219
0
  if (uj)
5220
0
    vty_json(vty, json);
5221
5222
0
  return CMD_SUCCESS;
5223
0
}
5224
5225
/*
5226
 * Display per-VNI EVPN routing table - for all VNIs.
5227
 */
5228
DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5229
      show_bgp_l2vpn_evpn_route_vni_all_cmd,
5230
      "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5231
      SHOW_STR
5232
      BGP_STR
5233
      L2VPN_HELP_STR
5234
      EVPN_HELP_STR
5235
      EVPN_RT_HELP_STR
5236
      "VXLAN Network Identifier\n"
5237
      "All VNIs\n"
5238
      "Print Detailed Output\n"
5239
      "Remote VTEP\n"
5240
      "Remote VTEP IP address\n"
5241
      JSON_STR)
5242
0
{
5243
0
  struct bgp *bgp;
5244
0
  struct in_addr vtep_ip;
5245
0
  int idx = 0;
5246
0
  bool uj = false;
5247
0
  json_object *json = NULL;
5248
  /* Detail Adjust. Adjust indexes according to detail option */
5249
0
  int da = 0;
5250
5251
0
  bgp = bgp_get_evpn();
5252
0
  if (!bgp)
5253
0
    return CMD_WARNING;
5254
5255
  /* check if we need json output */
5256
0
  uj = use_json(argc, argv);
5257
0
  if (uj)
5258
0
    json = json_object_new_object();
5259
5260
0
  if (!argv_find(argv, argc, "evpn", &idx))
5261
0
    return CMD_WARNING;
5262
5263
0
  if (argv_find(argv, argc, "detail", &da))
5264
0
    da = 1;
5265
5266
  /* vtep-ip position depends on detail option */
5267
0
  vtep_ip.s_addr = 0;
5268
0
  if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5269
0
      || (uj
5270
0
    && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5271
0
    if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
5272
0
      vty_out(vty, "%% Malformed VTEP IP address\n");
5273
0
      return CMD_WARNING;
5274
0
    }
5275
0
  }
5276
5277
0
  evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
5278
5279
0
  if (uj) {
5280
0
    vty_json(vty, json);
5281
0
    json_object_free(json);
5282
0
  }
5283
5284
0
  return CMD_SUCCESS;
5285
0
}
5286
5287
/*
5288
 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5289
 */
5290
DEFPY(show_bgp_vni_all,
5291
      show_bgp_vni_all_cmd,
5292
      "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5293
      SHOW_STR
5294
      BGP_STR
5295
      VNI_HELP_STR
5296
      VNI_ALL_HELP_STR
5297
      VTEP_HELP_STR
5298
      VTEP_IP_HELP_STR
5299
      DETAIL_HELP_STR
5300
      JSON_STR)
5301
0
{
5302
0
  struct bgp *bgp;
5303
0
  json_object *json = NULL;
5304
5305
0
  bgp = bgp_get_evpn();
5306
0
  if (!bgp)
5307
0
    return CMD_WARNING;
5308
5309
  /* check if we need json output */
5310
0
  if (uj)
5311
0
    json = json_object_new_object();
5312
5313
0
  evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
5314
5315
0
  if (uj)
5316
0
    vty_json(vty, json);
5317
5318
0
  return CMD_SUCCESS;
5319
0
}
5320
5321
/*
5322
 * Display per-VNI EVPN EAD routing table - for all VNIs.
5323
 */
5324
DEFPY(show_bgp_vni_all_ead,
5325
      show_bgp_vni_all_ead_cmd,
5326
      "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5327
      SHOW_STR
5328
      BGP_STR
5329
      VNI_HELP_STR
5330
      VNI_ALL_HELP_STR
5331
      EVPN_TYPE_HELP_STR
5332
      EVPN_TYPE_1_HELP_STR
5333
      EVPN_TYPE_1_HELP_STR
5334
      VTEP_HELP_STR
5335
      VTEP_IP_HELP_STR
5336
      DETAIL_HELP_STR
5337
      JSON_STR)
5338
0
{
5339
0
  struct bgp *bgp;
5340
0
  json_object *json = NULL;
5341
5342
0
  bgp = bgp_get_evpn();
5343
0
  if (!bgp)
5344
0
    return CMD_WARNING;
5345
5346
  /* check if we need json output */
5347
0
  if (uj)
5348
0
    json = json_object_new_object();
5349
5350
0
  evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
5351
0
         !!detail);
5352
5353
0
  if (uj)
5354
0
    vty_json(vty, json);
5355
5356
0
  return CMD_SUCCESS;
5357
0
}
5358
5359
/*
5360
 * Display per-VNI EVPN MAC routing table - for all VNIs.
5361
 */
5362
DEFPY(show_bgp_vni_all_macip_mac,
5363
      show_bgp_vni_all_macip_mac_cmd,
5364
      "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5365
      SHOW_STR
5366
      BGP_STR
5367
      VNI_HELP_STR
5368
      VNI_ALL_HELP_STR
5369
      EVPN_TYPE_HELP_STR
5370
      EVPN_TYPE_2_HELP_STR
5371
      EVPN_TYPE_2_HELP_STR
5372
      "MAC Table\n"
5373
      VTEP_HELP_STR
5374
      VTEP_IP_HELP_STR
5375
      DETAIL_HELP_STR
5376
      JSON_STR)
5377
0
{
5378
0
  struct bgp *bgp;
5379
0
  json_object *json = NULL;
5380
5381
0
  bgp = bgp_get_evpn();
5382
0
  if (!bgp)
5383
0
    return CMD_WARNING;
5384
5385
  /* check if we need json output */
5386
0
  if (uj)
5387
0
    json = json_object_new_object();
5388
5389
0
  evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5390
0
         json, !!detail);
5391
5392
0
  if (uj)
5393
0
    vty_json(vty, json);
5394
5395
0
  return CMD_SUCCESS;
5396
0
}
5397
5398
/*
5399
 * Display per-VNI EVPN IP routing table - for all VNIs.
5400
 */
5401
DEFPY(show_bgp_vni_all_macip_ip,
5402
      show_bgp_vni_all_macip_ip_cmd,
5403
      "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5404
      SHOW_STR
5405
      BGP_STR
5406
      VNI_HELP_STR
5407
      VNI_ALL_HELP_STR
5408
      EVPN_TYPE_HELP_STR
5409
      EVPN_TYPE_2_HELP_STR
5410
      EVPN_TYPE_2_HELP_STR
5411
      "IP Table\n"
5412
      VTEP_HELP_STR
5413
      VTEP_IP_HELP_STR
5414
      DETAIL_HELP_STR
5415
      JSON_STR)
5416
0
{
5417
0
  struct bgp *bgp;
5418
0
  json_object *json = NULL;
5419
5420
0
  bgp = bgp_get_evpn();
5421
0
  if (!bgp)
5422
0
    return CMD_WARNING;
5423
5424
  /* check if we need json output */
5425
0
  if (uj)
5426
0
    json = json_object_new_object();
5427
5428
0
  evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5429
0
         json, !!detail);
5430
5431
0
  if (uj)
5432
0
    vty_json(vty, json);
5433
5434
0
  return CMD_SUCCESS;
5435
0
}
5436
5437
/*
5438
 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5439
 */
5440
DEFPY(show_bgp_vni_all_imet,
5441
      show_bgp_vni_all_imet_cmd,
5442
      "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5443
      SHOW_STR
5444
      BGP_STR
5445
      VNI_HELP_STR
5446
      VNI_ALL_HELP_STR
5447
      EVPN_TYPE_HELP_STR
5448
      EVPN_TYPE_3_HELP_STR
5449
      EVPN_TYPE_3_HELP_STR
5450
      VTEP_HELP_STR
5451
      VTEP_IP_HELP_STR
5452
      DETAIL_HELP_STR
5453
      JSON_STR)
5454
0
{
5455
0
  struct bgp *bgp;
5456
0
  json_object *json = NULL;
5457
5458
0
  bgp = bgp_get_evpn();
5459
0
  if (!bgp)
5460
0
    return CMD_WARNING;
5461
5462
  /* check if we need json output */
5463
0
  if (uj)
5464
0
    json = json_object_new_object();
5465
5466
0
  evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
5467
0
         json, !!detail);
5468
5469
0
  if (uj)
5470
0
    vty_json(vty, json);
5471
5472
0
  return CMD_SUCCESS;
5473
0
}
5474
5475
/*
5476
 * Display per-VNI EVPN ALL routing tables - for select VNI
5477
 */
5478
DEFPY(show_bgp_vni,
5479
      show_bgp_vni_cmd,
5480
      "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
5481
      SHOW_STR
5482
      BGP_STR
5483
      VNI_HELP_STR
5484
      VNI_NUM_HELP_STR
5485
      VTEP_HELP_STR
5486
      VTEP_IP_HELP_STR
5487
      JSON_STR)
5488
0
{
5489
0
  struct bgp *bgp;
5490
0
  json_object *json = NULL;
5491
0
  json_object *json_mac = NULL;
5492
5493
0
  bgp = bgp_get_evpn();
5494
0
  if (!bgp)
5495
0
    return CMD_WARNING;
5496
5497
  /* check if we need json output */
5498
0
  if (uj) {
5499
0
    json = json_object_new_object();
5500
0
    json_mac = json_object_new_object();
5501
0
  }
5502
5503
0
  evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
5504
5505
0
  if (!uj)
5506
0
    vty_out(vty, "\n\nMAC Table:\n\n");
5507
5508
0
  evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
5509
5510
0
  if (uj) {
5511
0
    json_object_object_add(json, "macTable", json_mac);
5512
0
    vty_json(vty, json);
5513
0
  }
5514
5515
0
  return CMD_SUCCESS;
5516
0
}
5517
5518
/*
5519
 * Display per-VNI EVPN EAD routing table - for select VNI
5520
 */
5521
DEFPY(show_bgp_vni_ead,
5522
      show_bgp_vni_ead_cmd,
5523
      "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5524
      SHOW_STR
5525
      BGP_STR
5526
      VNI_HELP_STR
5527
      VNI_NUM_HELP_STR
5528
      EVPN_TYPE_HELP_STR
5529
      EVPN_TYPE_1_HELP_STR
5530
      EVPN_TYPE_1_HELP_STR
5531
      VTEP_HELP_STR
5532
      VTEP_IP_HELP_STR
5533
      JSON_STR)
5534
0
{
5535
0
  struct bgp *bgp;
5536
0
  json_object *json = NULL;
5537
5538
0
  bgp = bgp_get_evpn();
5539
0
  if (!bgp)
5540
0
    return CMD_WARNING;
5541
5542
  /* check if we need json output */
5543
0
  if (uj)
5544
0
    json = json_object_new_object();
5545
5546
0
  evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
5547
0
           json);
5548
5549
0
  if (uj)
5550
0
    vty_json(vty, json);
5551
5552
0
  return CMD_SUCCESS;
5553
0
}
5554
5555
/*
5556
 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5557
 */
5558
DEFPY(show_bgp_vni_macip_mac,
5559
      show_bgp_vni_macip_mac_cmd,
5560
      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5561
      SHOW_STR
5562
      BGP_STR
5563
      VNI_HELP_STR
5564
      VNI_NUM_HELP_STR
5565
      EVPN_TYPE_HELP_STR
5566
      EVPN_TYPE_2_HELP_STR
5567
      EVPN_TYPE_2_HELP_STR
5568
      "MAC Table\n"
5569
      VTEP_HELP_STR
5570
      VTEP_IP_HELP_STR
5571
      JSON_STR)
5572
0
{
5573
0
  struct bgp *bgp;
5574
0
  json_object *json = NULL;
5575
5576
0
  bgp = bgp_get_evpn();
5577
0
  if (!bgp)
5578
0
    return CMD_WARNING;
5579
5580
  /* check if we need json output */
5581
0
  if (uj)
5582
0
    json = json_object_new_object();
5583
5584
0
  evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5585
0
           json);
5586
5587
0
  if (uj)
5588
0
    vty_json(vty, json);
5589
5590
0
  return CMD_SUCCESS;
5591
0
}
5592
5593
/*
5594
 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5595
 */
5596
DEFPY(show_bgp_vni_macip_ip,
5597
      show_bgp_vni_macip_ip_cmd,
5598
      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5599
      SHOW_STR
5600
      BGP_STR
5601
      VNI_HELP_STR
5602
      VNI_NUM_HELP_STR
5603
      EVPN_TYPE_HELP_STR
5604
      EVPN_TYPE_2_HELP_STR
5605
      EVPN_TYPE_2_HELP_STR
5606
      "IP Table\n"
5607
      VTEP_HELP_STR
5608
      VTEP_IP_HELP_STR
5609
      JSON_STR)
5610
0
{
5611
0
  struct bgp *bgp;
5612
0
  json_object *json = NULL;
5613
5614
0
  bgp = bgp_get_evpn();
5615
0
  if (!bgp)
5616
0
    return CMD_WARNING;
5617
5618
  /* check if we need json output */
5619
0
  if (uj)
5620
0
    json = json_object_new_object();
5621
5622
0
  evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5623
0
           json);
5624
5625
0
  if (uj)
5626
0
    vty_json(vty, json);
5627
5628
0
  return CMD_SUCCESS;
5629
0
}
5630
5631
/*
5632
 * Display per-VNI EVPN Multicast routing table - for select VNI
5633
 */
5634
DEFPY(show_bgp_vni_imet,
5635
      show_bgp_vni_imet_cmd,
5636
      "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5637
      SHOW_STR
5638
      BGP_STR
5639
      VNI_HELP_STR
5640
      VNI_NUM_HELP_STR
5641
      EVPN_TYPE_HELP_STR
5642
      EVPN_TYPE_3_HELP_STR
5643
      EVPN_TYPE_3_HELP_STR
5644
      VTEP_HELP_STR
5645
      VTEP_IP_HELP_STR
5646
      JSON_STR)
5647
0
{
5648
0
  struct bgp *bgp;
5649
0
  json_object *json = NULL;
5650
5651
0
  bgp = bgp_get_evpn();
5652
0
  if (!bgp)
5653
0
    return CMD_WARNING;
5654
5655
  /* check if we need json output */
5656
0
  if (uj)
5657
0
    json = json_object_new_object();
5658
5659
0
  evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
5660
0
           json);
5661
5662
0
  if (uj)
5663
0
    vty_json(vty, json);
5664
5665
0
  return CMD_SUCCESS;
5666
0
}
5667
5668
/*
5669
 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5670
 */
5671
DEFPY(show_bgp_vni_macip_mac_addr,
5672
      show_bgp_vni_macip_mac_addr_cmd,
5673
      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5674
      SHOW_STR
5675
      BGP_STR
5676
      VNI_HELP_STR
5677
      VNI_NUM_HELP_STR
5678
      EVPN_TYPE_HELP_STR
5679
      EVPN_TYPE_2_HELP_STR
5680
      EVPN_TYPE_2_HELP_STR
5681
      "MAC Table\n"
5682
      MAC_STR
5683
      JSON_STR)
5684
0
{
5685
0
  struct bgp *bgp;
5686
0
  json_object *json = NULL;
5687
5688
0
  bgp = bgp_get_evpn();
5689
0
  if (!bgp)
5690
0
    return CMD_WARNING;
5691
5692
  /* check if we need json output */
5693
0
  if (uj)
5694
0
    json = json_object_new_object();
5695
5696
0
  evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
5697
5698
0
  if (uj)
5699
0
    vty_json(vty, json);
5700
5701
0
  return CMD_SUCCESS;
5702
0
}
5703
5704
/*
5705
 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5706
 */
5707
DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
5708
      "show bgp vni " CMD_VNI_RANGE
5709
      "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5710
      SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5711
        EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5712
      "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
5713
0
{
5714
0
  struct bgp *bgp;
5715
0
  json_object *json = NULL;
5716
0
  struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
5717
5718
0
  bgp = bgp_get_evpn();
5719
0
  if (!bgp)
5720
0
    return CMD_WARNING;
5721
5722
  /* check if we need json output */
5723
0
  if (uj)
5724
0
    json = json_object_new_object();
5725
5726
0
  if (sockunion_family(ip) == AF_INET) {
5727
0
    ip_addr.ipa_type = IPADDR_V4;
5728
0
    ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
5729
0
  } else {
5730
0
    ip_addr.ipa_type = IPADDR_V6;
5731
0
    memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
5732
0
           sizeof(struct in6_addr));
5733
0
  }
5734
0
  evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
5735
5736
0
  if (uj)
5737
0
    vty_json(vty, json);
5738
5739
0
  return CMD_SUCCESS;
5740
0
}
5741
5742
DEFPY_HIDDEN(
5743
  show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5744
  show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5745
  "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5746
  SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5747
  "EVPN route information\n"
5748
  "MAC IP routes in the EVI tables linked to the ES\n"
5749
  "ES ID\n"
5750
  "Detailed information\n" JSON_STR)
5751
0
{
5752
0
  esi_t esi;
5753
0
  esi_t *esi_p;
5754
0
  json_object *json = NULL;
5755
5756
0
  if (esi_str) {
5757
0
    if (!str_to_esi(esi_str, &esi)) {
5758
0
      vty_out(vty, "%% Malformed ESI\n");
5759
0
      return CMD_WARNING;
5760
0
    }
5761
0
    esi_p = &esi;
5762
0
  } else {
5763
0
    esi_p = NULL;
5764
0
  }
5765
5766
0
  if (uj)
5767
0
    json = json_object_new_object();
5768
0
  bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
5769
0
  if (uj)
5770
0
    vty_json(vty, json);
5771
5772
0
  return CMD_SUCCESS;
5773
0
}
5774
5775
DEFPY_HIDDEN(
5776
  show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5777
  show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5778
  "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5779
  SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5780
  "EVPN route information\n"
5781
  "MAC IP routes in the global table linked to the ES\n"
5782
  "ES ID\n"
5783
  "Detailed information\n" JSON_STR)
5784
0
{
5785
0
  esi_t esi;
5786
0
  esi_t *esi_p;
5787
0
  json_object *json = NULL;
5788
5789
0
  if (esi_str) {
5790
0
    if (!str_to_esi(esi_str, &esi)) {
5791
0
      vty_out(vty, "%% Malformed ESI\n");
5792
0
      return CMD_WARNING;
5793
0
    }
5794
0
    esi_p = &esi;
5795
0
  } else {
5796
0
    esi_p = NULL;
5797
0
  }
5798
5799
0
  if (uj)
5800
0
    json = json_object_new_object();
5801
0
  bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
5802
0
  if (uj)
5803
0
    vty_json(vty, json);
5804
5805
0
  return CMD_SUCCESS;
5806
0
}
5807
5808
/*
5809
 * Display EVPN import route-target hash table
5810
 */
5811
DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5812
      show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5813
      "show bgp l2vpn evpn vrf-import-rt [json]",
5814
      SHOW_STR
5815
      BGP_STR
5816
      L2VPN_HELP_STR
5817
      EVPN_HELP_STR
5818
      "Show vrf import route target\n"
5819
      JSON_STR)
5820
0
{
5821
0
  bool uj = false;
5822
0
  struct bgp *bgp_evpn = NULL;
5823
0
  json_object *json = NULL;
5824
5825
0
  bgp_evpn = bgp_get_evpn();
5826
0
  if (!bgp_evpn)
5827
0
    return CMD_WARNING;
5828
5829
0
  uj = use_json(argc, argv);
5830
0
  if (uj)
5831
0
    json = json_object_new_object();
5832
5833
0
  evpn_show_vrf_import_rts(vty, bgp_evpn, json);
5834
5835
0
  if (uj)
5836
0
    vty_json(vty, json);
5837
5838
0
  return CMD_SUCCESS;
5839
0
}
5840
5841
/*
5842
 * Display EVPN import route-target hash table
5843
 */
5844
DEFUN(show_bgp_l2vpn_evpn_import_rt,
5845
      show_bgp_l2vpn_evpn_import_rt_cmd,
5846
      "show bgp l2vpn evpn import-rt [json]",
5847
      SHOW_STR
5848
      BGP_STR
5849
      L2VPN_HELP_STR
5850
      EVPN_HELP_STR
5851
      "Show import route target\n"
5852
      JSON_STR)
5853
0
{
5854
0
  struct bgp *bgp;
5855
0
  bool uj = false;
5856
0
  json_object *json = NULL;
5857
5858
0
  bgp = bgp_get_evpn();
5859
0
  if (!bgp)
5860
0
    return CMD_WARNING;
5861
5862
0
  uj = use_json(argc, argv);
5863
0
  if (uj)
5864
0
    json = json_object_new_object();
5865
5866
0
  evpn_show_import_rts(vty, bgp, json);
5867
5868
0
  if (uj)
5869
0
    vty_json(vty, json);
5870
5871
0
  return CMD_SUCCESS;
5872
0
}
5873
5874
DEFPY_HIDDEN(test_es_add,
5875
      test_es_add_cmd,
5876
      "[no$no] test es NAME$esi_str [state NAME$state_str]",
5877
      NO_STR
5878
      "Test\n"
5879
      "Ethernet-segment\n"
5880
      "Ethernet-Segment Identifier\n"
5881
      "ES link state\n"
5882
      "up|down\n"
5883
)
5884
0
{
5885
0
  int ret = 0;
5886
0
  esi_t esi;
5887
0
  struct bgp *bgp;
5888
0
  struct in_addr vtep_ip;
5889
0
  bool oper_up;
5890
5891
0
  bgp = bgp_get_evpn();
5892
0
  if (!bgp) {
5893
0
    vty_out(vty, "%% EVPN BGP instance not yet created\n");
5894
0
    return CMD_WARNING;
5895
0
  }
5896
5897
0
  if (!str_to_esi(esi_str, &esi)) {
5898
0
    vty_out(vty, "%% Malformed ESI\n");
5899
0
    return CMD_WARNING;
5900
0
  }
5901
5902
0
  if (no) {
5903
0
    ret = bgp_evpn_local_es_del(bgp, &esi);
5904
0
    if (ret == -1) {
5905
0
      vty_out(vty, "%% Failed to delete ES\n");
5906
0
      return CMD_WARNING;
5907
0
    }
5908
0
  } else {
5909
0
    if (state_str && !strcmp(state_str, "up"))
5910
0
      oper_up = true;
5911
0
    else
5912
0
      oper_up = false;
5913
0
    vtep_ip = bgp->router_id;
5914
5915
0
    ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
5916
0
              EVPN_MH_DF_PREF_MIN, false);
5917
0
    if (ret == -1) {
5918
0
      vty_out(vty, "%% Failed to add ES\n");
5919
0
      return CMD_WARNING;
5920
0
    }
5921
0
  }
5922
0
  return CMD_SUCCESS;
5923
0
}
5924
5925
DEFPY_HIDDEN(test_es_vni_add,
5926
      test_es_vni_add_cmd,
5927
      "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5928
      NO_STR
5929
      "Test\n"
5930
      "Ethernet-segment\n"
5931
      "Ethernet-Segment Identifier\n"
5932
      "VNI\n"
5933
      "1-16777215\n"
5934
)
5935
0
{
5936
0
  int ret = 0;
5937
0
  esi_t esi;
5938
0
  struct bgp *bgp;
5939
5940
0
  bgp = bgp_get_evpn();
5941
0
  if (!bgp) {
5942
0
    vty_out(vty, "%% EVPN BGP instance not yet created\n");
5943
0
    return CMD_WARNING;
5944
0
  }
5945
5946
0
  if (!str_to_esi(esi_str, &esi)) {
5947
0
    vty_out(vty, "%% Malformed ESI\n");
5948
0
    return CMD_WARNING;
5949
0
  }
5950
5951
0
  if (no) {
5952
0
    ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5953
0
    if (ret == -1) {
5954
0
      vty_out(vty, "%% Failed to deref ES VNI\n");
5955
0
      return CMD_WARNING;
5956
0
    }
5957
0
  } else {
5958
0
    ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5959
0
    if (ret == -1) {
5960
0
      vty_out(vty, "%% Failed to ref ES VNI\n");
5961
0
      return CMD_WARNING;
5962
0
    }
5963
0
  }
5964
0
  return CMD_SUCCESS;
5965
0
}
5966
5967
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
5968
       "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5969
       "Show VNI\n"
5970
       "VNI number\n")
5971
5972
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5973
       "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5974
       "Summary of BGP neighbor status\n" JSON_STR)
5975
5976
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
5977
       "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5978
       SHOW_STR BGP_STR EVPN_HELP_STR
5979
       EVPN_RT_HELP_STR
5980
       "Display Detailed Information\n"
5981
       EVPN_TYPE_HELP_STR
5982
       EVPN_TYPE_2_HELP_STR
5983
       EVPN_TYPE_2_HELP_STR
5984
       EVPN_TYPE_3_HELP_STR
5985
       EVPN_TYPE_3_HELP_STR)
5986
5987
ALIAS_HIDDEN(
5988
  show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
5989
  "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5990
  SHOW_STR BGP_STR EVPN_HELP_STR
5991
  EVPN_RT_HELP_STR
5992
  EVPN_RT_DIST_HELP_STR
5993
  EVPN_ASN_IP_HELP_STR
5994
  EVPN_TYPE_HELP_STR
5995
  EVPN_TYPE_2_HELP_STR
5996
  EVPN_TYPE_2_HELP_STR
5997
  EVPN_TYPE_3_HELP_STR
5998
  EVPN_TYPE_3_HELP_STR)
5999
6000
ALIAS_HIDDEN(
6001
  show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
6002
  "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
6003
  SHOW_STR BGP_STR EVPN_HELP_STR
6004
  EVPN_RT_HELP_STR
6005
  EVPN_RT_DIST_HELP_STR
6006
  EVPN_ASN_IP_HELP_STR
6007
  "MAC\n"
6008
  "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6009
  "IP\n"
6010
  "IP address (IPv4 or IPv6)\n")
6011
6012
ALIAS_HIDDEN(
6013
  show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
6014
  "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
6015
  SHOW_STR BGP_STR EVPN_HELP_STR
6016
  EVPN_RT_HELP_STR
6017
  "VXLAN Network Identifier\n"
6018
  "VNI number\n"
6019
  EVPN_TYPE_HELP_STR
6020
  EVPN_TYPE_2_HELP_STR
6021
  EVPN_TYPE_2_HELP_STR
6022
  EVPN_TYPE_3_HELP_STR
6023
  EVPN_TYPE_3_HELP_STR
6024
  "Remote VTEP\n"
6025
  "Remote VTEP IP address\n")
6026
6027
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
6028
       show_bgp_evpn_route_vni_macip_cmd,
6029
       "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
6030
       SHOW_STR BGP_STR EVPN_HELP_STR
6031
       EVPN_RT_HELP_STR
6032
       "VXLAN Network Identifier\n"
6033
       "VNI number\n"
6034
       "MAC\n"
6035
       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6036
       "IP\n"
6037
       "IP address (IPv4 or IPv6)\n")
6038
6039
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
6040
       show_bgp_evpn_route_vni_multicast_cmd,
6041
       "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
6042
       SHOW_STR BGP_STR EVPN_HELP_STR
6043
       EVPN_RT_HELP_STR
6044
       "VXLAN Network Identifier\n"
6045
       "VNI number\n"
6046
       EVPN_TYPE_3_HELP_STR
6047
       "Originating Router IP address\n")
6048
6049
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
6050
       "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6051
       SHOW_STR BGP_STR EVPN_HELP_STR
6052
       EVPN_RT_HELP_STR
6053
       "VXLAN Network Identifier\n"
6054
       "All VNIs\n"
6055
       "Print Detailed Output\n"
6056
       "Remote VTEP\n"
6057
       "Remote VTEP IP address\n")
6058
6059
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
6060
       "show bgp evpn import-rt",
6061
       SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
6062
6063
DEFUN_NOSH (bgp_evpn_vni,
6064
            bgp_evpn_vni_cmd,
6065
            "vni " CMD_VNI_RANGE,
6066
            "VXLAN Network Identifier\n"
6067
            "VNI number\n")
6068
0
{
6069
0
  vni_t vni;
6070
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6071
0
  struct bgpevpn *vpn;
6072
6073
0
  if (!bgp)
6074
0
    return CMD_WARNING;
6075
6076
0
  vni = strtoul(argv[1]->arg, NULL, 10);
6077
6078
  /* Create VNI, or mark as configured. */
6079
0
  vpn = evpn_create_update_vni(bgp, vni);
6080
0
  if (!vpn) {
6081
0
    vty_out(vty, "%% Failed to create VNI \n");
6082
0
    return CMD_WARNING;
6083
0
  }
6084
6085
0
  VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
6086
0
  return CMD_SUCCESS;
6087
0
}
6088
6089
DEFUN (no_bgp_evpn_vni,
6090
       no_bgp_evpn_vni_cmd,
6091
       "no vni " CMD_VNI_RANGE,
6092
       NO_STR
6093
       "VXLAN Network Identifier\n"
6094
       "VNI number\n")
6095
0
{
6096
0
  vni_t vni;
6097
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6098
0
  struct bgpevpn *vpn;
6099
6100
0
  if (!bgp)
6101
0
    return CMD_WARNING;
6102
6103
0
  vni = strtoul(argv[2]->arg, NULL, 10);
6104
6105
  /* Check if we should disallow. */
6106
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
6107
0
  if (!vpn) {
6108
0
    vty_out(vty, "%% Specified VNI does not exist\n");
6109
0
    return CMD_WARNING;
6110
0
  }
6111
0
  if (!is_vni_configured(vpn)) {
6112
0
    vty_out(vty, "%% Specified VNI is not configured\n");
6113
0
    return CMD_WARNING;
6114
0
  }
6115
6116
0
  evpn_delete_vni(bgp, vpn);
6117
0
  return CMD_SUCCESS;
6118
0
}
6119
6120
DEFUN_NOSH (exit_vni,
6121
            exit_vni_cmd,
6122
            "exit-vni",
6123
            "Exit from VNI mode\n")
6124
0
{
6125
0
  if (vty->node == BGP_EVPN_VNI_NODE)
6126
0
    vty->node = BGP_EVPN_NODE;
6127
0
  return CMD_SUCCESS;
6128
0
}
6129
6130
DEFUN (bgp_evpn_vrf_rd,
6131
       bgp_evpn_vrf_rd_cmd,
6132
       "rd ASN:NN_OR_IP-ADDRESS:NN",
6133
       EVPN_RT_DIST_HELP_STR
6134
       EVPN_ASN_IP_HELP_STR)
6135
0
{
6136
0
  int ret;
6137
0
  struct prefix_rd prd;
6138
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6139
6140
0
  if (!bgp_vrf)
6141
0
    return CMD_WARNING;
6142
6143
0
  ret = str2prefix_rd(argv[1]->arg, &prd);
6144
0
  if (!ret) {
6145
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
6146
0
    return CMD_WARNING;
6147
0
  }
6148
6149
  /* If same as existing value, there is nothing more to do. */
6150
0
  if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
6151
0
    return CMD_SUCCESS;
6152
6153
  /* Configure or update the RD. */
6154
0
  evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);
6155
0
  return CMD_SUCCESS;
6156
0
}
6157
6158
DEFUN (no_bgp_evpn_vrf_rd,
6159
       no_bgp_evpn_vrf_rd_cmd,
6160
       "no rd ASN:NN_OR_IP-ADDRESS:NN",
6161
       NO_STR
6162
       EVPN_RT_DIST_HELP_STR
6163
       EVPN_ASN_IP_HELP_STR)
6164
0
{
6165
0
  int ret;
6166
0
  struct prefix_rd prd;
6167
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6168
6169
0
  if (!bgp_vrf)
6170
0
    return CMD_WARNING;
6171
6172
0
  ret = str2prefix_rd(argv[2]->arg, &prd);
6173
0
  if (!ret) {
6174
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
6175
0
    return CMD_WARNING;
6176
0
  }
6177
6178
  /* Check if we should disallow. */
6179
0
  if (!is_vrf_rd_configured(bgp_vrf)) {
6180
0
    vty_out(vty, "%% RD is not configured for this VRF\n");
6181
0
    return CMD_WARNING;
6182
0
  }
6183
6184
0
  if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
6185
0
    vty_out(vty,
6186
0
      "%% RD specified does not match configuration for this VRF\n");
6187
0
    return CMD_WARNING;
6188
0
  }
6189
6190
0
  evpn_unconfigure_vrf_rd(bgp_vrf);
6191
0
  return CMD_SUCCESS;
6192
0
}
6193
6194
DEFUN (no_bgp_evpn_vrf_rd_without_val,
6195
       no_bgp_evpn_vrf_rd_without_val_cmd,
6196
       "no rd",
6197
       NO_STR
6198
       EVPN_RT_DIST_HELP_STR)
6199
0
{
6200
0
  struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6201
6202
0
  if (!bgp_vrf)
6203
0
    return CMD_WARNING;
6204
6205
  /* Check if we should disallow. */
6206
0
  if (!is_vrf_rd_configured(bgp_vrf)) {
6207
0
    vty_out(vty, "%% RD is not configured for this VRF\n");
6208
0
    return CMD_WARNING;
6209
0
  }
6210
6211
0
  evpn_unconfigure_vrf_rd(bgp_vrf);
6212
0
  return CMD_SUCCESS;
6213
0
}
6214
6215
DEFUN (bgp_evpn_vni_rd,
6216
       bgp_evpn_vni_rd_cmd,
6217
       "rd ASN:NN_OR_IP-ADDRESS:NN",
6218
       EVPN_RT_DIST_HELP_STR
6219
       EVPN_ASN_IP_HELP_STR)
6220
0
{
6221
0
  struct prefix_rd prd;
6222
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6223
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6224
0
  int ret;
6225
6226
0
  if (!bgp)
6227
0
    return CMD_WARNING;
6228
6229
0
  if (!EVPN_ENABLED(bgp)) {
6230
0
    vty_out(vty,
6231
0
      "This command is only supported under EVPN VRF\n");
6232
0
    return CMD_WARNING;
6233
0
  }
6234
6235
0
  ret = str2prefix_rd(argv[1]->arg, &prd);
6236
0
  if (!ret) {
6237
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
6238
0
    return CMD_WARNING;
6239
0
  }
6240
6241
  /* If same as existing value, there is nothing more to do. */
6242
0
  if (bgp_evpn_rd_matches_existing(vpn, &prd))
6243
0
    return CMD_SUCCESS;
6244
6245
  /* Configure or update the RD. */
6246
0
  evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);
6247
0
  return CMD_SUCCESS;
6248
0
}
6249
6250
DEFUN (no_bgp_evpn_vni_rd,
6251
       no_bgp_evpn_vni_rd_cmd,
6252
       "no rd ASN:NN_OR_IP-ADDRESS:NN",
6253
       NO_STR
6254
       EVPN_RT_DIST_HELP_STR
6255
       EVPN_ASN_IP_HELP_STR)
6256
0
{
6257
0
  struct prefix_rd prd;
6258
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6259
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6260
0
  int ret;
6261
6262
0
  if (!bgp)
6263
0
    return CMD_WARNING;
6264
6265
0
  if (!EVPN_ENABLED(bgp)) {
6266
0
    vty_out(vty,
6267
0
      "This command is only supported under EVPN VRF\n");
6268
0
    return CMD_WARNING;
6269
0
  }
6270
6271
0
  ret = str2prefix_rd(argv[2]->arg, &prd);
6272
0
  if (!ret) {
6273
0
    vty_out(vty, "%% Malformed Route Distinguisher\n");
6274
0
    return CMD_WARNING;
6275
0
  }
6276
6277
  /* Check if we should disallow. */
6278
0
  if (!is_rd_configured(vpn)) {
6279
0
    vty_out(vty, "%% RD is not configured for this VNI\n");
6280
0
    return CMD_WARNING;
6281
0
  }
6282
6283
0
  if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
6284
0
    vty_out(vty,
6285
0
      "%% RD specified does not match configuration for this VNI\n");
6286
0
    return CMD_WARNING;
6287
0
  }
6288
6289
0
  evpn_unconfigure_rd(bgp, vpn);
6290
0
  return CMD_SUCCESS;
6291
0
}
6292
6293
DEFUN (no_bgp_evpn_vni_rd_without_val,
6294
       no_bgp_evpn_vni_rd_without_val_cmd,
6295
       "no rd",
6296
       NO_STR
6297
       EVPN_RT_DIST_HELP_STR)
6298
0
{
6299
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6300
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6301
6302
0
  if (!bgp)
6303
0
    return CMD_WARNING;
6304
6305
0
  if (!EVPN_ENABLED(bgp)) {
6306
0
    vty_out(vty,
6307
0
      "This command is only supported under EVPN VRF\n");
6308
0
    return CMD_WARNING;
6309
0
  }
6310
6311
  /* Check if we should disallow. */
6312
0
  if (!is_rd_configured(vpn)) {
6313
0
    vty_out(vty, "%% RD is not configured for this VNI\n");
6314
0
    return CMD_WARNING;
6315
0
  }
6316
6317
0
  evpn_unconfigure_rd(bgp, vpn);
6318
0
  return CMD_SUCCESS;
6319
0
}
6320
6321
/*
6322
 * Loop over all extended-communities in the route-target list rtl and
6323
 * return 1 if we find ecomtarget
6324
 */
6325
static bool bgp_evpn_rt_matches_existing(struct list *rtl,
6326
           struct ecommunity *ecomtarget)
6327
0
{
6328
0
  struct listnode *node;
6329
0
  struct ecommunity *ecom;
6330
6331
0
  for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
6332
0
    if (ecommunity_match(ecom, ecomtarget))
6333
0
      return true;
6334
0
  }
6335
6336
0
  return false;
6337
0
}
6338
6339
/*
6340
 * L3 RT version of above.
6341
 */
6342
static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
6343
               struct ecommunity *ecomtarget)
6344
0
{
6345
0
  struct listnode *node;
6346
0
  struct vrf_route_target *l3rt;
6347
6348
0
  for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
6349
0
    if (ecommunity_match(l3rt->ecom, ecomtarget))
6350
0
      return true;
6351
0
  }
6352
6353
0
  return false;
6354
0
}
6355
6356
/* display L3VNI related info for a VRF instance */
6357
DEFUN (show_bgp_vrf_l3vni_info,
6358
       show_bgp_vrf_l3vni_info_cmd,
6359
       "show bgp vrf VRFNAME vni [json]",
6360
       SHOW_STR
6361
       BGP_STR
6362
       "show bgp vrf\n"
6363
       "VRF Name\n"
6364
       "L3-VNI\n"
6365
       JSON_STR)
6366
0
{
6367
0
  char buf[ETHER_ADDR_STRLEN];
6368
0
  int idx_vrf = 3;
6369
0
  const char *name = NULL;
6370
0
  struct bgp *bgp = NULL;
6371
0
  struct listnode *node = NULL;
6372
0
  struct bgpevpn *vpn = NULL;
6373
0
  struct vrf_route_target *l3rt;
6374
0
  json_object *json = NULL;
6375
0
  json_object *json_vnis = NULL;
6376
0
  json_object *json_export_rts = NULL;
6377
0
  json_object *json_import_rts = NULL;
6378
0
  bool uj = use_json(argc, argv);
6379
6380
0
  if (uj) {
6381
0
    json = json_object_new_object();
6382
0
    json_vnis = json_object_new_array();
6383
0
    json_export_rts = json_object_new_array();
6384
0
    json_import_rts = json_object_new_array();
6385
0
  }
6386
6387
0
  name = argv[idx_vrf]->arg;
6388
0
  bgp = bgp_lookup_by_name(name);
6389
0
  if (strmatch(name, VRF_DEFAULT_NAME))
6390
0
    bgp = bgp_get_default();
6391
6392
0
  if (!bgp) {
6393
0
    if (!uj)
6394
0
      vty_out(vty, "BGP instance for VRF %s not found\n",
6395
0
        name);
6396
0
    else {
6397
0
      json_object_string_add(json, "warning",
6398
0
                 "BGP instance not found");
6399
0
      vty_out(vty, "%s\n", json_object_to_json_string(json));
6400
0
      json_object_free(json);
6401
0
    }
6402
0
    return CMD_WARNING;
6403
0
  }
6404
6405
0
  if (!json) {
6406
0
    vty_out(vty, "BGP VRF: %s\n", name);
6407
0
    vty_out(vty, "  Local-Ip: %pI4\n", &bgp->originator_ip);
6408
0
    vty_out(vty, "  L3-VNI: %u\n", bgp->l3vni);
6409
0
    vty_out(vty, "  Rmac: %s\n",
6410
0
      prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6411
0
    vty_out(vty, "  VNI Filter: %s\n",
6412
0
      CHECK_FLAG(bgp->vrf_flags,
6413
0
           BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6414
0
        ? "prefix-routes-only"
6415
0
        : "none");
6416
0
    vty_out(vty, "  L2-VNI List:\n");
6417
0
    vty_out(vty, "    ");
6418
0
    for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6419
0
      vty_out(vty, "%u  ", vpn->vni);
6420
0
    vty_out(vty, "\n");
6421
0
    vty_out(vty, "  Export-RTs:\n");
6422
0
    vty_out(vty, "    ");
6423
0
    for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6424
0
      vty_out(vty, "%s  ", ecommunity_str(l3rt->ecom));
6425
0
    vty_out(vty, "\n");
6426
0
    vty_out(vty, "  Import-RTs:\n");
6427
0
    vty_out(vty, "    ");
6428
0
    for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6429
0
      vty_out(vty, "%s  ", ecommunity_str(l3rt->ecom));
6430
0
    vty_out(vty, "\n");
6431
0
    vty_out(vty, "  RD: ");
6432
0
    vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd);
6433
0
    vty_out(vty, "\n");
6434
0
  } else {
6435
0
    json_object_string_add(json, "vrf", name);
6436
0
    json_object_string_addf(json, "local-ip", "%pI4",
6437
0
          &bgp->originator_ip);
6438
0
    json_object_int_add(json, "l3vni", bgp->l3vni);
6439
0
    json_object_string_add(
6440
0
      json, "rmac",
6441
0
      prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6442
0
    json_object_string_add(
6443
0
      json, "vniFilter",
6444
0
      CHECK_FLAG(bgp->vrf_flags,
6445
0
           BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6446
0
        ? "prefix-routes-only"
6447
0
        : "none");
6448
    /* list of l2vnis */
6449
0
    for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6450
0
      json_object_array_add(json_vnis,
6451
0
                json_object_new_int(vpn->vni));
6452
0
    json_object_object_add(json, "l2vnis", json_vnis);
6453
6454
    /* export rts */
6455
0
    for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6456
0
      json_object_array_add(
6457
0
        json_export_rts,
6458
0
        json_object_new_string(
6459
0
          ecommunity_str(l3rt->ecom)));
6460
0
    json_object_object_add(json, "export-rts", json_export_rts);
6461
6462
    /* import rts */
6463
0
    for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6464
0
      json_object_array_add(
6465
0
        json_import_rts,
6466
0
        json_object_new_string(
6467
0
          ecommunity_str(l3rt->ecom)));
6468
0
    json_object_object_add(json, "import-rts", json_import_rts);
6469
0
    json_object_string_addf(json, "rd",
6470
0
          BGP_RD_AS_FORMAT(bgp->asnotation),
6471
0
          &bgp->vrf_prd);
6472
0
  }
6473
6474
0
  if (uj)
6475
0
    vty_json(vty, json);
6476
0
  return CMD_SUCCESS;
6477
0
}
6478
6479
static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
6480
      bool is_wildcard)
6481
0
{
6482
  /* Do nothing if we already have this route-target */
6483
0
  if (is_import) {
6484
0
    if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6485
0
                  ecom))
6486
0
      bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
6487
0
                   is_wildcard);
6488
0
    else
6489
0
      return -1;
6490
0
  } else {
6491
0
    if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6492
0
                  ecom))
6493
0
      bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
6494
0
    else
6495
0
      return -1;
6496
0
  }
6497
6498
0
  return 0;
6499
0
}
6500
6501
static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
6502
0
{
6503
  /* Verify we already have this route-target */
6504
0
  if (is_import) {
6505
0
    if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6506
0
                  ecom))
6507
0
      return -1;
6508
6509
0
    bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
6510
0
  } else {
6511
0
    if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6512
0
                  ecom))
6513
0
      return -1;
6514
6515
0
    bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
6516
0
  }
6517
6518
0
  return 0;
6519
0
}
6520
6521
static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
6522
      struct cmd_token **argv, int rt_idx, bool is_add,
6523
      bool is_import)
6524
0
{
6525
0
  int ret = CMD_SUCCESS;
6526
0
  bool is_wildcard = false;
6527
0
  struct ecommunity *ecom = NULL;
6528
6529
0
  for (int i = rt_idx; i < argc; i++) {
6530
0
    is_wildcard = false;
6531
6532
    /*
6533
     * Special handling for wildcard '*' here.
6534
     *
6535
     * Let's just convert it to 0 here so we dont have to modify
6536
     * the ecommunity parser.
6537
     */
6538
0
    if ((argv[i]->arg)[0] == '*') {
6539
0
      (argv[i]->arg)[0] = '0';
6540
0
      is_wildcard = true;
6541
0
    }
6542
6543
0
    ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
6544
0
            0);
6545
6546
    /* Put it back as was */
6547
0
    if (is_wildcard)
6548
0
      (argv[i]->arg)[0] = '*';
6549
6550
0
    if (!ecom) {
6551
0
      vty_out(vty, "%% Malformed Route Target list\n");
6552
0
      ret = CMD_WARNING;
6553
0
      continue;
6554
0
    }
6555
6556
0
    ecommunity_str(ecom);
6557
6558
0
    if (is_add) {
6559
0
      if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
6560
0
        vty_out(vty,
6561
0
          "%% RT specified already configured for this VRF: %s\n",
6562
0
          argv[i]->arg);
6563
0
        ecommunity_free(&ecom);
6564
0
        ret = CMD_WARNING;
6565
0
      }
6566
6567
0
    } else {
6568
0
      if (del_rt(bgp, ecom, is_import) != 0) {
6569
0
        vty_out(vty,
6570
0
          "%% RT specified does not match configuration for this VRF: %s\n",
6571
0
          argv[i]->arg);
6572
0
        ret = CMD_WARNING;
6573
0
      }
6574
6575
0
      ecommunity_free(&ecom);
6576
0
    }
6577
0
  }
6578
6579
0
  return ret;
6580
0
}
6581
6582
/* import/export rt for l3vni-vrf */
6583
DEFUN (bgp_evpn_vrf_rt,
6584
       bgp_evpn_vrf_rt_cmd,
6585
       "route-target <both|import|export> RTLIST...",
6586
       "Route Target\n"
6587
       "import and export\n"
6588
       "import\n"
6589
       "export\n"
6590
       "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6591
0
{
6592
0
  int ret = CMD_SUCCESS;
6593
0
  int tmp_ret = CMD_SUCCESS;
6594
0
  int rt_type;
6595
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6596
6597
0
  if (!bgp)
6598
0
    return CMD_WARNING_CONFIG_FAILED;
6599
6600
0
  if (!strcmp(argv[1]->arg, "import"))
6601
0
    rt_type = RT_TYPE_IMPORT;
6602
0
  else if (!strcmp(argv[1]->arg, "export"))
6603
0
    rt_type = RT_TYPE_EXPORT;
6604
0
  else if (!strcmp(argv[1]->arg, "both"))
6605
0
    rt_type = RT_TYPE_BOTH;
6606
0
  else {
6607
0
    vty_out(vty, "%% Invalid Route Target type\n");
6608
0
    return CMD_WARNING_CONFIG_FAILED;
6609
0
  }
6610
6611
0
  if (strmatch(argv[2]->arg, "auto")) {
6612
0
    vty_out(vty, "%% `auto` cannot be configured via list\n");
6613
0
    return CMD_WARNING_CONFIG_FAILED;
6614
0
  }
6615
6616
0
  if (rt_type != RT_TYPE_IMPORT) {
6617
0
    for (int i = 2; i < argc; i++) {
6618
0
      if ((argv[i]->arg)[0] == '*') {
6619
0
        vty_out(vty,
6620
0
          "%% Wildcard '*' only applicable for import\n");
6621
0
        return CMD_WARNING_CONFIG_FAILED;
6622
0
      }
6623
0
    }
6624
0
  }
6625
6626
  /* Add/update the import route-target */
6627
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6628
0
    tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
6629
6630
0
  if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6631
0
    ret = tmp_ret;
6632
6633
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6634
0
    tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
6635
6636
0
  if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6637
0
    ret = tmp_ret;
6638
6639
0
  return ret;
6640
0
}
6641
6642
DEFPY (bgp_evpn_vrf_rt_auto,
6643
       bgp_evpn_vrf_rt_auto_cmd,
6644
       "route-target <both|import|export>$type auto",
6645
       "Route Target\n"
6646
       "import and export\n"
6647
       "import\n"
6648
       "export\n"
6649
       "Automatically derive route target\n")
6650
0
{
6651
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6652
0
  int rt_type;
6653
6654
0
  if (!bgp)
6655
0
    return CMD_WARNING_CONFIG_FAILED;
6656
6657
0
  if (strmatch(type, "import"))
6658
0
    rt_type = RT_TYPE_IMPORT;
6659
0
  else if (strmatch(type, "export"))
6660
0
    rt_type = RT_TYPE_EXPORT;
6661
0
  else if (strmatch(type, "both"))
6662
0
    rt_type = RT_TYPE_BOTH;
6663
0
  else {
6664
0
    vty_out(vty, "%% Invalid Route Target type\n");
6665
0
    return CMD_WARNING_CONFIG_FAILED;
6666
0
  }
6667
6668
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6669
0
    bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6670
6671
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6672
0
    bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6673
6674
0
  return CMD_SUCCESS;
6675
0
}
6676
6677
DEFUN (no_bgp_evpn_vrf_rt,
6678
       no_bgp_evpn_vrf_rt_cmd,
6679
       "no route-target <both|import|export> RTLIST...",
6680
       NO_STR
6681
       "Route Target\n"
6682
       "import and export\n"
6683
       "import\n"
6684
       "export\n"
6685
       "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6686
0
{
6687
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6688
0
  int ret = CMD_SUCCESS;
6689
0
  int tmp_ret = CMD_SUCCESS;
6690
0
  int rt_type;
6691
6692
0
  if (!bgp)
6693
0
    return CMD_WARNING_CONFIG_FAILED;
6694
6695
0
  if (!strcmp(argv[2]->arg, "import"))
6696
0
    rt_type = RT_TYPE_IMPORT;
6697
0
  else if (!strcmp(argv[2]->arg, "export"))
6698
0
    rt_type = RT_TYPE_EXPORT;
6699
0
  else if (!strcmp(argv[2]->arg, "both"))
6700
0
    rt_type = RT_TYPE_BOTH;
6701
0
  else {
6702
0
    vty_out(vty, "%% Invalid Route Target type\n");
6703
0
    return CMD_WARNING_CONFIG_FAILED;
6704
0
  }
6705
6706
0
  if (!strcmp(argv[3]->arg, "auto")) {
6707
0
    vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6708
0
    return CMD_WARNING_CONFIG_FAILED;
6709
0
  }
6710
6711
0
  if (rt_type == RT_TYPE_IMPORT) {
6712
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6713
0
      vty_out(vty,
6714
0
        "%% Import RT is not configured for this VRF\n");
6715
0
      return CMD_WARNING_CONFIG_FAILED;
6716
0
    }
6717
0
  } else if (rt_type == RT_TYPE_EXPORT) {
6718
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6719
0
      vty_out(vty,
6720
0
        "%% Export RT is not configured for this VRF\n");
6721
0
      return CMD_WARNING_CONFIG_FAILED;
6722
0
    }
6723
0
  } else if (rt_type == RT_TYPE_BOTH) {
6724
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6725
0
        && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6726
0
      vty_out(vty,
6727
0
        "%% Import/Export RT is not configured for this VRF\n");
6728
0
      return CMD_WARNING_CONFIG_FAILED;
6729
0
    }
6730
0
  }
6731
6732
0
  if (rt_type != RT_TYPE_IMPORT) {
6733
0
    for (int i = 3; i < argc; i++) {
6734
0
      if ((argv[i]->arg)[0] == '*') {
6735
0
        vty_out(vty,
6736
0
          "%% Wildcard '*' only applicable for import\n");
6737
0
        return CMD_WARNING_CONFIG_FAILED;
6738
0
      }
6739
0
    }
6740
0
  }
6741
6742
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6743
0
    tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
6744
6745
0
  if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6746
0
    ret = tmp_ret;
6747
6748
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6749
0
    tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
6750
6751
0
  if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6752
0
    ret = tmp_ret;
6753
6754
0
  return ret;
6755
0
}
6756
6757
DEFPY (no_bgp_evpn_vrf_rt_auto,
6758
       no_bgp_evpn_vrf_rt_auto_cmd,
6759
       "no route-target <both|import|export>$type auto",
6760
       NO_STR
6761
       "Route Target\n"
6762
       "import and export\n"
6763
       "import\n"
6764
       "export\n"
6765
       "Automatically derive route target\n")
6766
0
{
6767
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6768
0
  int rt_type;
6769
6770
0
  if (!bgp)
6771
0
    return CMD_WARNING_CONFIG_FAILED;
6772
6773
0
  if (strmatch(type, "import"))
6774
0
    rt_type = RT_TYPE_IMPORT;
6775
0
  else if (strmatch(type, "export"))
6776
0
    rt_type = RT_TYPE_EXPORT;
6777
0
  else if (strmatch(type, "both"))
6778
0
    rt_type = RT_TYPE_BOTH;
6779
0
  else {
6780
0
    vty_out(vty, "%% Invalid Route Target type\n");
6781
0
    return CMD_WARNING_CONFIG_FAILED;
6782
0
  }
6783
6784
0
  if (rt_type == RT_TYPE_IMPORT) {
6785
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
6786
0
      vty_out(vty,
6787
0
        "%% Import AUTO RT is not configured for this VRF\n");
6788
0
      return CMD_WARNING_CONFIG_FAILED;
6789
0
    }
6790
0
  } else if (rt_type == RT_TYPE_EXPORT) {
6791
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6792
0
      vty_out(vty,
6793
0
        "%% Export AUTO RT is not configured for this VRF\n");
6794
0
      return CMD_WARNING_CONFIG_FAILED;
6795
0
    }
6796
0
  } else if (rt_type == RT_TYPE_BOTH) {
6797
0
    if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6798
0
        !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6799
0
      vty_out(vty,
6800
0
        "%% Import/Export AUTO RT is not configured for this VRF\n");
6801
0
      return CMD_WARNING_CONFIG_FAILED;
6802
0
    }
6803
0
  }
6804
6805
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6806
0
    bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6807
6808
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6809
0
    bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6810
6811
0
  return CMD_SUCCESS;
6812
0
}
6813
6814
DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6815
      "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6816
      NO_STR
6817
      "EAD ES fragment config\n"
6818
      "EVIs per-fragment\n"
6819
      "limit\n")
6820
0
{
6821
0
  bgp_mh_info->evi_per_es_frag =
6822
0
    no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6823
6824
0
  return CMD_SUCCESS;
6825
0
}
6826
6827
DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6828
      "ead-es-route-target export RT",
6829
      "EAD ES Route Target\n"
6830
      "export\n"
6831
      "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6832
0
{
6833
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6834
0
  struct ecommunity *ecomadd = NULL;
6835
6836
0
  if (!bgp)
6837
0
    return CMD_WARNING;
6838
6839
0
  if (!EVPN_ENABLED(bgp)) {
6840
0
    vty_out(vty, "This command is only supported under EVPN VRF\n");
6841
0
    return CMD_WARNING;
6842
0
  }
6843
6844
  /* Add/update the export route-target */
6845
0
  ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6846
0
  if (!ecomadd) {
6847
0
    vty_out(vty, "%% Malformed Route Target list\n");
6848
0
    return CMD_WARNING;
6849
0
  }
6850
0
  ecommunity_str(ecomadd);
6851
6852
  /* Do nothing if we already have this export route-target */
6853
0
  if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6854
0
            ecomadd))
6855
0
    bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6856
0
  else
6857
0
    ecommunity_free(&ecomadd);
6858
6859
0
  return CMD_SUCCESS;
6860
0
}
6861
6862
DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6863
      "no ead-es-route-target export RT",
6864
      NO_STR
6865
      "EAD ES Route Target\n"
6866
      "export\n" EVPN_ASN_IP_HELP_STR)
6867
0
{
6868
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6869
0
  struct ecommunity *ecomdel = NULL;
6870
6871
0
  if (!bgp)
6872
0
    return CMD_WARNING;
6873
6874
0
  if (!EVPN_ENABLED(bgp)) {
6875
0
    vty_out(vty, "This command is only supported under EVPN VRF\n");
6876
0
    return CMD_WARNING;
6877
0
  }
6878
6879
0
  ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6880
0
  if (!ecomdel) {
6881
0
    vty_out(vty, "%% Malformed Route Target list\n");
6882
0
    return CMD_WARNING;
6883
0
  }
6884
0
  ecommunity_str(ecomdel);
6885
6886
0
  if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6887
0
            ecomdel)) {
6888
0
    ecommunity_free(&ecomdel);
6889
0
    vty_out(vty,
6890
0
      "%% RT specified does not match EAD-ES RT configuration\n");
6891
0
    return CMD_WARNING;
6892
0
  }
6893
0
  bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6894
6895
0
  ecommunity_free(&ecomdel);
6896
0
  return CMD_SUCCESS;
6897
0
}
6898
6899
DEFUN (bgp_evpn_vni_rt,
6900
       bgp_evpn_vni_rt_cmd,
6901
       "route-target <both|import|export> RT",
6902
       "Route Target\n"
6903
       "import and export\n"
6904
       "import\n"
6905
       "export\n"
6906
       "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6907
0
{
6908
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6909
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6910
0
  int rt_type;
6911
0
  struct ecommunity *ecomadd = NULL;
6912
6913
0
  if (!bgp)
6914
0
    return CMD_WARNING;
6915
6916
0
  if (!EVPN_ENABLED(bgp)) {
6917
0
    vty_out(vty,
6918
0
      "This command is only supported under EVPN VRF\n");
6919
0
    return CMD_WARNING;
6920
0
  }
6921
6922
0
  if (!strcmp(argv[1]->text, "import"))
6923
0
    rt_type = RT_TYPE_IMPORT;
6924
0
  else if (!strcmp(argv[1]->text, "export"))
6925
0
    rt_type = RT_TYPE_EXPORT;
6926
0
  else if (!strcmp(argv[1]->text, "both"))
6927
0
    rt_type = RT_TYPE_BOTH;
6928
0
  else {
6929
0
    vty_out(vty, "%% Invalid Route Target type\n");
6930
0
    return CMD_WARNING;
6931
0
  }
6932
6933
  /* Add/update the import route-target */
6934
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
6935
    /* Note that first of the two RTs is created for "both" type */
6936
0
    ecomadd = ecommunity_str2com(argv[2]->arg,
6937
0
               ECOMMUNITY_ROUTE_TARGET, 0);
6938
0
    if (!ecomadd) {
6939
0
      vty_out(vty, "%% Malformed Route Target list\n");
6940
0
      return CMD_WARNING;
6941
0
    }
6942
0
    ecommunity_str(ecomadd);
6943
6944
    /* Do nothing if we already have this import route-target */
6945
0
    if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6946
0
      evpn_configure_import_rt(bgp, vpn, ecomadd);
6947
0
    else
6948
0
      ecommunity_free(&ecomadd);
6949
0
  }
6950
6951
  /* Add/update the export route-target */
6952
0
  if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
6953
    /* Note that second of the two RTs is created for "both" type */
6954
0
    ecomadd = ecommunity_str2com(argv[2]->arg,
6955
0
               ECOMMUNITY_ROUTE_TARGET, 0);
6956
0
    if (!ecomadd) {
6957
0
      vty_out(vty, "%% Malformed Route Target list\n");
6958
0
      return CMD_WARNING;
6959
0
    }
6960
0
    ecommunity_str(ecomadd);
6961
6962
    /* Do nothing if we already have this export route-target */
6963
0
    if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6964
0
      evpn_configure_export_rt(bgp, vpn, ecomadd);
6965
0
    else
6966
0
      ecommunity_free(&ecomadd);
6967
0
  }
6968
6969
0
  return CMD_SUCCESS;
6970
0
}
6971
6972
DEFUN (no_bgp_evpn_vni_rt,
6973
       no_bgp_evpn_vni_rt_cmd,
6974
       "no route-target <both|import|export> RT",
6975
       NO_STR
6976
       "Route Target\n"
6977
       "import and export\n"
6978
       "import\n"
6979
       "export\n"
6980
       EVPN_ASN_IP_HELP_STR)
6981
0
{
6982
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6983
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6984
0
  int rt_type, found_ecomdel;
6985
0
  struct ecommunity *ecomdel = NULL;
6986
6987
0
  if (!bgp)
6988
0
    return CMD_WARNING;
6989
6990
0
  if (!EVPN_ENABLED(bgp)) {
6991
0
    vty_out(vty,
6992
0
      "This command is only supported under EVPN VRF\n");
6993
0
    return CMD_WARNING;
6994
0
  }
6995
6996
0
  if (!strcmp(argv[2]->text, "import"))
6997
0
    rt_type = RT_TYPE_IMPORT;
6998
0
  else if (!strcmp(argv[2]->text, "export"))
6999
0
    rt_type = RT_TYPE_EXPORT;
7000
0
  else if (!strcmp(argv[2]->text, "both"))
7001
0
    rt_type = RT_TYPE_BOTH;
7002
0
  else {
7003
0
    vty_out(vty, "%% Invalid Route Target type\n");
7004
0
    return CMD_WARNING;
7005
0
  }
7006
7007
  /* The user did "no route-target import", check to see if there are any
7008
   * import route-targets configured. */
7009
0
  if (rt_type == RT_TYPE_IMPORT) {
7010
0
    if (!is_import_rt_configured(vpn)) {
7011
0
      vty_out(vty,
7012
0
        "%% Import RT is not configured for this VNI\n");
7013
0
      return CMD_WARNING;
7014
0
    }
7015
0
  } else if (rt_type == RT_TYPE_EXPORT) {
7016
0
    if (!is_export_rt_configured(vpn)) {
7017
0
      vty_out(vty,
7018
0
        "%% Export RT is not configured for this VNI\n");
7019
0
      return CMD_WARNING;
7020
0
    }
7021
0
  } else if (rt_type == RT_TYPE_BOTH) {
7022
0
    if (!is_import_rt_configured(vpn)
7023
0
        && !is_export_rt_configured(vpn)) {
7024
0
      vty_out(vty,
7025
0
        "%% Import/Export RT is not configured for this VNI\n");
7026
0
      return CMD_WARNING;
7027
0
    }
7028
0
  }
7029
7030
0
  ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
7031
0
  if (!ecomdel) {
7032
0
    vty_out(vty, "%% Malformed Route Target list\n");
7033
0
    return CMD_WARNING;
7034
0
  }
7035
0
  ecommunity_str(ecomdel);
7036
7037
0
  if (rt_type == RT_TYPE_IMPORT) {
7038
0
    if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7039
0
      ecommunity_free(&ecomdel);
7040
0
      vty_out(vty,
7041
0
        "%% RT specified does not match configuration for this VNI\n");
7042
0
      return CMD_WARNING;
7043
0
    }
7044
0
    evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7045
0
  } else if (rt_type == RT_TYPE_EXPORT) {
7046
0
    if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7047
0
      ecommunity_free(&ecomdel);
7048
0
      vty_out(vty,
7049
0
        "%% RT specified does not match configuration for this VNI\n");
7050
0
      return CMD_WARNING;
7051
0
    }
7052
0
    evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7053
0
  } else if (rt_type == RT_TYPE_BOTH) {
7054
0
    found_ecomdel = 0;
7055
7056
0
    if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7057
0
      evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7058
0
      found_ecomdel = 1;
7059
0
    }
7060
7061
0
    if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7062
0
      evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7063
0
      found_ecomdel = 1;
7064
0
    }
7065
7066
0
    if (!found_ecomdel) {
7067
0
      ecommunity_free(&ecomdel);
7068
0
      vty_out(vty,
7069
0
        "%% RT specified does not match configuration for this VNI\n");
7070
0
      return CMD_WARNING;
7071
0
    }
7072
0
  }
7073
7074
0
  ecommunity_free(&ecomdel);
7075
0
  return CMD_SUCCESS;
7076
0
}
7077
7078
DEFUN (no_bgp_evpn_vni_rt_without_val,
7079
       no_bgp_evpn_vni_rt_without_val_cmd,
7080
       "no route-target <import|export>",
7081
       NO_STR
7082
       "Route Target\n"
7083
       "import\n"
7084
       "export\n")
7085
0
{
7086
0
  struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7087
0
  VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
7088
0
  int rt_type;
7089
7090
0
  if (!bgp)
7091
0
    return CMD_WARNING;
7092
7093
0
  if (!EVPN_ENABLED(bgp)) {
7094
0
    vty_out(vty,
7095
0
      "This command is only supported under EVPN VRF\n");
7096
0
    return CMD_WARNING;
7097
0
  }
7098
7099
0
  if (!strcmp(argv[2]->text, "import")) {
7100
0
    rt_type = RT_TYPE_IMPORT;
7101
0
  } else if (!strcmp(argv[2]->text, "export")) {
7102
0
    rt_type = RT_TYPE_EXPORT;
7103
0
  } else {
7104
0
    vty_out(vty, "%% Invalid Route Target type\n");
7105
0
    return CMD_WARNING;
7106
0
  }
7107
7108
  /* Check if we should disallow. */
7109
0
  if (rt_type == RT_TYPE_IMPORT) {
7110
0
    if (!is_import_rt_configured(vpn)) {
7111
0
      vty_out(vty,
7112
0
        "%% Import RT is not configured for this VNI\n");
7113
0
      return CMD_WARNING;
7114
0
    }
7115
0
  } else {
7116
0
    if (!is_export_rt_configured(vpn)) {
7117
0
      vty_out(vty,
7118
0
        "%% Export RT is not configured for this VNI\n");
7119
0
      return CMD_WARNING;
7120
0
    }
7121
0
  }
7122
7123
  /* Unconfigure the RT. */
7124
0
  if (rt_type == RT_TYPE_IMPORT)
7125
0
    evpn_unconfigure_import_rt(bgp, vpn, NULL);
7126
0
  else
7127
0
    evpn_unconfigure_export_rt(bgp, vpn, NULL);
7128
0
  return CMD_SUCCESS;
7129
0
}
7130
7131
static int vni_cmp(const void **a, const void **b)
7132
0
{
7133
0
  const struct bgpevpn *first = *a;
7134
0
  const struct bgpevpn *secnd = *b;
7135
7136
0
  return secnd->vni - first->vni;
7137
0
}
7138
7139
/*
7140
 * Output EVPN configuration information.
7141
 */
7142
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
7143
        safi_t safi)
7144
0
{
7145
0
  if (bgp->advertise_all_vni)
7146
0
    vty_out(vty, "  advertise-all-vni\n");
7147
7148
0
  if (hashcount(bgp->vnihash)) {
7149
0
    struct list *vnilist = hash_to_list(bgp->vnihash);
7150
0
    struct listnode *ln;
7151
0
    struct bgpevpn *data;
7152
7153
0
    list_sort(vnilist, vni_cmp);
7154
0
    for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
7155
0
      write_vni_config(vty, data);
7156
7157
0
    list_delete(&vnilist);
7158
0
  }
7159
7160
0
  if (bgp->advertise_autort_rfc8365)
7161
0
    vty_out(vty, "  autort rfc8365-compatible\n");
7162
7163
0
  if (bgp->advertise_gw_macip)
7164
0
    vty_out(vty, "  advertise-default-gw\n");
7165
7166
0
  if (bgp->evpn_info->advertise_svi_macip)
7167
0
    vty_out(vty, "  advertise-svi-ip\n");
7168
7169
0
  if (bgp->resolve_overlay_index)
7170
0
    vty_out(vty, "  enable-resolve-overlay-index\n");
7171
7172
0
  if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
7173
0
    vty_out(vty, "  ead-es-frag evi-limit %u\n",
7174
0
      bgp_mh_info->evi_per_es_frag);
7175
7176
0
  if (bgp_mh_info->host_routes_use_l3nhg !=
7177
0
      BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
7178
0
    if (bgp_mh_info->host_routes_use_l3nhg)
7179
0
      vty_out(vty, "  use-es-l3nhg\n");
7180
0
    else
7181
0
      vty_out(vty, "  no use-es-l3nhg\n");
7182
0
  }
7183
7184
0
  if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
7185
0
    if (bgp_mh_info->ead_evi_rx)
7186
0
      vty_out(vty, "  no disable-ead-evi-rx\n");
7187
0
    else
7188
0
      vty_out(vty, "  disable-ead-evi-rx\n");
7189
0
  }
7190
7191
0
  if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
7192
0
    if (bgp_mh_info->ead_evi_tx)
7193
0
      vty_out(vty, "  no disable-ead-evi-tx\n");
7194
0
    else
7195
0
      vty_out(vty, "  disable-ead-evi-tx\n");
7196
0
  }
7197
7198
0
  if (!bgp->evpn_info->dup_addr_detect)
7199
0
    vty_out(vty, "  no dup-addr-detection\n");
7200
7201
0
  if (bgp->evpn_info->dad_max_moves !=
7202
0
    EVPN_DAD_DEFAULT_MAX_MOVES ||
7203
0
    bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
7204
0
    vty_out(vty, "  dup-addr-detection max-moves %u time %u\n",
7205
0
      bgp->evpn_info->dad_max_moves,
7206
0
      bgp->evpn_info->dad_time);
7207
7208
0
  if (bgp->evpn_info->dad_freeze) {
7209
0
    if (bgp->evpn_info->dad_freeze_time)
7210
0
      vty_out(vty,
7211
0
        "  dup-addr-detection freeze %u\n",
7212
0
        bgp->evpn_info->dad_freeze_time);
7213
0
    else
7214
0
      vty_out(vty,
7215
0
        "  dup-addr-detection freeze permanent\n");
7216
0
  }
7217
7218
0
  if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
7219
0
    vty_out(vty, "  flooding disable\n");
7220
7221
0
  if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7222
0
           BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
7223
0
    if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7224
0
      vty_out(vty, "  advertise ipv4 unicast route-map %s\n",
7225
0
        bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7226
0
    else
7227
0
      vty_out(vty,
7228
0
        "  advertise ipv4 unicast\n");
7229
0
  } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7230
0
       BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
7231
0
    if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7232
0
      vty_out(vty,
7233
0
        "  advertise ipv4 unicast gateway-ip route-map %s\n",
7234
0
        bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7235
0
    else
7236
0
      vty_out(vty, "  advertise ipv4 unicast gateway-ip\n");
7237
0
  }
7238
7239
  /* EAD ES export route-target */
7240
0
  if (listcount(bgp_mh_info->ead_es_export_rtl)) {
7241
0
    struct ecommunity *ecom;
7242
0
    char *ecom_str;
7243
0
    struct listnode *node;
7244
7245
0
    for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
7246
0
            ecom)) {
7247
7248
0
      ecom_str = ecommunity_ecom2str(
7249
0
        ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7250
0
      vty_out(vty, "  ead-es-route-target export %s\n",
7251
0
        ecom_str);
7252
0
      XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7253
0
    }
7254
0
  }
7255
7256
0
  if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7257
0
           BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
7258
0
    if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7259
0
      vty_out(vty,
7260
0
        "  advertise ipv6 unicast route-map %s\n",
7261
0
        bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7262
0
    else
7263
0
      vty_out(vty,
7264
0
        "  advertise ipv6 unicast\n");
7265
0
  } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7266
0
            BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
7267
0
    if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7268
0
      vty_out(vty,
7269
0
        "  advertise ipv6 unicast gateway-ip route-map %s\n",
7270
0
        bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7271
0
    else
7272
0
      vty_out(vty, "  advertise ipv6 unicast gateway-ip\n");
7273
0
  }
7274
7275
0
  if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7276
0
           BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
7277
0
    vty_out(vty, "  default-originate ipv4\n");
7278
7279
0
  if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7280
0
           BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
7281
0
    vty_out(vty, "  default-originate ipv6\n");
7282
7283
0
  if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
7284
0
    if (!bgp->evpn_info->advertise_pip)
7285
0
      vty_out(vty, "  no advertise-pip\n");
7286
0
    if (bgp->evpn_info->advertise_pip) {
7287
0
      if (bgp->evpn_info->pip_ip_static.s_addr
7288
0
          != INADDR_ANY) {
7289
0
        vty_out(vty, "  advertise-pip ip %pI4",
7290
0
          &bgp->evpn_info->pip_ip_static);
7291
0
        if (!is_zero_mac(&(
7292
0
              bgp->evpn_info->pip_rmac_static))) {
7293
0
          char buf[ETHER_ADDR_STRLEN];
7294
7295
0
          vty_out(vty, " mac %s",
7296
0
            prefix_mac2str(
7297
0
              &bgp->evpn_info
7298
0
                 ->pip_rmac,
7299
0
              buf, sizeof(buf)));
7300
0
        }
7301
0
        vty_out(vty, "\n");
7302
0
      }
7303
0
    }
7304
0
  }
7305
0
  if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
7306
0
    vty_out(vty, "  rd %s\n", bgp->vrf_prd_pretty);
7307
7308
  /* import route-target */
7309
0
  if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
7310
0
    char *ecom_str;
7311
0
    struct listnode *node, *nnode;
7312
0
    struct vrf_route_target *l3rt;
7313
7314
0
    for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
7315
0
               l3rt)) {
7316
7317
0
      if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7318
0
        continue;
7319
7320
0
      ecom_str = ecommunity_ecom2str(
7321
0
        l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7322
7323
0
      if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
7324
0
        char *vni_str = NULL;
7325
7326
0
        vni_str = strchr(ecom_str, ':');
7327
0
        if (!vni_str) {
7328
0
          XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7329
0
          continue;
7330
0
        }
7331
7332
        /* Move pointer to vni */
7333
0
        vni_str += 1;
7334
7335
0
        vty_out(vty, "  route-target import *:%s\n",
7336
0
          vni_str);
7337
7338
0
      } else
7339
0
        vty_out(vty, "  route-target import %s\n",
7340
0
          ecom_str);
7341
7342
0
      XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7343
0
    }
7344
0
  }
7345
7346
  /* import route-target auto */
7347
0
  if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
7348
0
    vty_out(vty, "  route-target import auto\n");
7349
7350
  /* export route-target */
7351
0
  if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
7352
0
    char *ecom_str;
7353
0
    struct listnode *node, *nnode;
7354
0
    struct vrf_route_target *l3rt;
7355
7356
0
    for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
7357
0
               l3rt)) {
7358
7359
0
      if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7360
0
        continue;
7361
7362
0
      ecom_str = ecommunity_ecom2str(
7363
0
        l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7364
0
      vty_out(vty, "  route-target export %s\n", ecom_str);
7365
0
      XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7366
0
    }
7367
0
  }
7368
7369
  /* export route-target auto */
7370
0
  if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
7371
0
    vty_out(vty, "  route-target export auto\n");
7372
0
}
7373
7374
void bgp_ethernetvpn_init(void)
7375
0
{
7376
0
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
7377
0
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
7378
0
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
7379
0
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
7380
0
  install_element(VIEW_NODE,
7381
0
      &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
7382
0
  install_element(VIEW_NODE,
7383
0
      &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
7384
0
  install_element(
7385
0
    VIEW_NODE,
7386
0
    &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
7387
0
  install_element(
7388
0
    VIEW_NODE,
7389
0
    &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
7390
0
  install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
7391
0
  install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
7392
0
  install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
7393
0
  install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
7394
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
7395
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
7396
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
7397
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
7398
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
7399
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
7400
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
7401
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
7402
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
7403
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
7404
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
7405
0
  install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
7406
0
  install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
7407
0
  install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
7408
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
7409
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
7410
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
7411
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
7412
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
7413
0
  install_element(BGP_EVPN_NODE,
7414
0
      &bgp_evpn_enable_resolve_overlay_index_cmd);
7415
7416
  /* test commands */
7417
0
  install_element(BGP_EVPN_NODE, &test_es_add_cmd);
7418
0
  install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
7419
7420
  /* "show bgp l2vpn evpn" commands. */
7421
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
7422
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
7423
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
7424
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
7425
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
7426
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
7427
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
7428
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
7429
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
7430
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
7431
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
7432
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
7433
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
7434
0
  install_element(VIEW_NODE,
7435
0
      &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
7436
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
7437
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
7438
0
  install_element(VIEW_NODE,
7439
0
      &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
7440
0
  install_element(VIEW_NODE,
7441
0
      &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
7442
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
7443
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
7444
7445
  /* "show bgp vni" commands. */
7446
0
  install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
7447
0
  install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
7448
0
  install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
7449
0
  install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
7450
0
  install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
7451
0
  install_element(VIEW_NODE, &show_bgp_vni_cmd);
7452
0
  install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
7453
0
  install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
7454
0
  install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
7455
0
  install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
7456
0
  install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
7457
0
  install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
7458
7459
  /* "show bgp evpn" commands. */
7460
0
  install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
7461
0
  install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
7462
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
7463
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
7464
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
7465
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
7466
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
7467
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
7468
0
  install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
7469
0
  install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
7470
0
  install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7471
0
  install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
7472
7473
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
7474
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
7475
0
  install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
7476
0
  install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
7477
0
  install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
7478
0
  install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
7479
0
  install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
7480
0
  install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
7481
0
  install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
7482
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
7483
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
7484
0
  install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
7485
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
7486
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
7487
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
7488
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
7489
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
7490
0
  install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
7491
0
  install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
7492
0
  install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
7493
0
  install_element(BGP_EVPN_VNI_NODE,
7494
0
      &bgp_evpn_advertise_default_gw_vni_cmd);
7495
0
  install_element(BGP_EVPN_VNI_NODE,
7496
0
      &no_bgp_evpn_advertise_default_gw_vni_cmd);
7497
0
  install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
7498
0
  install_element(BGP_EVPN_VNI_NODE,
7499
0
      &no_bgp_evpn_advertise_vni_subnet_cmd);
7500
0
}