Coverage Report

Created: 2026-01-25 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_evpn_mh.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* EVPN Multihoming procedures
3
 *
4
 * Copyright (C) 2019 Cumulus Networks, Inc.
5
 * Anuradha Karuppiah
6
 *
7
 */
8
9
#include <zebra.h>
10
11
#include "command.h"
12
#include "filter.h"
13
#include "prefix.h"
14
#include "log.h"
15
#include "memory.h"
16
#include "stream.h"
17
#include "hash.h"
18
#include "jhash.h"
19
#include "zclient.h"
20
21
#include "lib/printfrr.h"
22
23
#include "bgpd/bgp_attr_evpn.h"
24
#include "bgpd/bgpd.h"
25
#include "bgpd/bgp_table.h"
26
#include "bgpd/bgp_route.h"
27
#include "bgpd/bgp_attr.h"
28
#include "bgpd/bgp_mplsvpn.h"
29
#include "bgpd/bgp_evpn.h"
30
#include "bgpd/bgp_evpn_private.h"
31
#include "bgpd/bgp_evpn_mh.h"
32
#include "bgpd/bgp_ecommunity.h"
33
#include "bgpd/bgp_encap_types.h"
34
#include "bgpd/bgp_debug.h"
35
#include "bgpd/bgp_errors.h"
36
#include "bgpd/bgp_aspath.h"
37
#include "bgpd/bgp_zebra.h"
38
#include "bgpd/bgp_addpath.h"
39
#include "bgpd/bgp_label.h"
40
#include "bgpd/bgp_nht.h"
41
#include "bgpd/bgp_mpath.h"
42
#include "bgpd/bgp_trace.h"
43
44
static void bgp_evpn_local_es_down(struct bgp *bgp,
45
    struct bgp_evpn_es *es);
46
static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
47
    struct bgp_evpn_es *es);
48
static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
49
                 struct bgp_evpn_es *es,
50
                 struct in_addr vtep_ip,
51
                 bool esr, uint8_t df_alg,
52
                 uint16_t df_pref);
53
static void bgp_evpn_es_vtep_del(struct bgp *bgp,
54
    struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr);
55
static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es);
56
static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);
57
static struct bgp_evpn_es_evi *
58
bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi);
59
static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es);
60
static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es);
61
static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi);
62
static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller);
63
static void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info);
64
static void bgp_evpn_mac_update_on_es_local_chg(struct bgp_evpn_es *es,
65
            bool is_local);
66
67
esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
68
static void bgp_evpn_run_consistency_checks(struct event *t);
69
static void bgp_evpn_path_nh_info_free(struct bgp_path_evpn_nh_info *nh_info);
70
static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info);
71
72
/******************************************************************************
73
 * per-ES (Ethernet Segment) routing table
74
 *
75
 * Following routes are added to the ES's routing table -
76
 * 1. Local and remote ESR (Type-4)
77
 * 2. Local EAD-per-ES (Type-1).
78
 *
79
 * Key for these routes is {ESI, VTEP-IP} so the path selection is practically
80
 * a no-op i.e. all paths lead to same VTEP-IP (i.e. result in the same VTEP
81
 * being added to same ES).
82
 *
83
 * Note the following routes go into the VNI routing table (instead of the
84
 * ES routing table) -
85
 * 1. Remote EAD-per-ES
86
 * 2. Local and remote EAD-per-EVI
87
 */
88
89
/* Calculate the best path for a multi-homing (Type-1 or Type-4) route
90
 * installed in the ES's routing table.
91
 */
92
static int bgp_evpn_es_route_select_install(struct bgp *bgp,
93
              struct bgp_evpn_es *es,
94
              struct bgp_dest *dest)
95
0
{
96
0
  int ret = 0;
97
0
  afi_t afi = AFI_L2VPN;
98
0
  safi_t safi = SAFI_EVPN;
99
0
  struct bgp_path_info *old_select; /* old best */
100
0
  struct bgp_path_info *new_select; /* new best */
101
0
  struct bgp_path_info_pair old_and_new;
102
103
  /* Compute the best path. */
104
0
  bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
105
0
         afi, safi);
106
0
  old_select = old_and_new.old;
107
0
  new_select = old_and_new.new;
108
109
  /*
110
   * If the best path hasn't changed - see if something needs to be
111
   * updated
112
   */
113
0
  if (old_select && old_select == new_select
114
0
      && old_select->type == ZEBRA_ROUTE_BGP
115
0
      && old_select->sub_type == BGP_ROUTE_IMPORTED
116
0
      && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
117
0
      && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
118
0
      && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
119
0
    if (bgp_zebra_has_route_changed(old_select)) {
120
0
      bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop,
121
0
               true /*esr*/,
122
0
               old_select->attr->df_alg,
123
0
               old_select->attr->df_pref);
124
0
    }
125
0
    UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
126
0
    bgp_zebra_clear_route_change_flags(dest);
127
0
    return ret;
128
0
  }
129
130
  /* If the user did a "clear" this flag will be set */
131
0
  UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
132
133
  /* bestpath has changed; update relevant fields and install or uninstall
134
   * into the zebra RIB.
135
   */
136
0
  if (old_select || new_select)
137
0
    bgp_bump_version(dest);
138
139
0
  if (old_select)
140
0
    bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
141
0
  if (new_select) {
142
0
    bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
143
0
    bgp_path_info_unset_flag(dest, new_select,
144
0
           BGP_PATH_ATTR_CHANGED);
145
0
    UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
146
0
  }
147
148
0
  if (new_select && new_select->type == ZEBRA_ROUTE_BGP
149
0
      && new_select->sub_type == BGP_ROUTE_IMPORTED) {
150
0
    bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop,
151
0
             true /*esr */, new_select->attr->df_alg,
152
0
             new_select->attr->df_pref);
153
0
  } else {
154
0
    if (old_select && old_select->type == ZEBRA_ROUTE_BGP
155
0
        && old_select->sub_type == BGP_ROUTE_IMPORTED)
156
0
      bgp_evpn_es_vtep_del(
157
0
          bgp, es, old_select->attr->nexthop,
158
0
          true /*esr*/);
159
0
  }
160
161
  /* Clear any route change flags. */
162
0
  bgp_zebra_clear_route_change_flags(dest);
163
164
  /* Reap old select bgp_path_info, if it has been removed */
165
0
  if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
166
0
    bgp_path_info_reap(dest, old_select);
167
168
0
  return ret;
169
0
}
170
171
/* Install Type-1/Type-4 route entry in the per-ES routing table */
172
static int bgp_evpn_es_route_install(struct bgp *bgp,
173
    struct bgp_evpn_es *es, struct prefix_evpn *p,
174
    struct bgp_path_info *parent_pi)
175
0
{
176
0
  int ret = 0;
177
0
  struct bgp_dest *dest = NULL;
178
0
  struct bgp_path_info *pi = NULL;
179
0
  struct attr *attr_new = NULL;
180
181
  /* Create (or fetch) route within the VNI.
182
   * NOTE: There is no RD here.
183
   */
184
0
  dest = bgp_node_get(es->route_table, (struct prefix *)p);
185
186
  /* Check if route entry is already present. */
187
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
188
0
    if (pi->extra &&
189
0
        (struct bgp_path_info *)pi->extra->parent == parent_pi)
190
0
      break;
191
192
0
  if (!pi) {
193
    /* Add (or update) attribute to hash. */
194
0
    attr_new = bgp_attr_intern(parent_pi->attr);
195
196
    /* Create new route with its attribute. */
197
0
    pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0,
198
0
             parent_pi->peer, attr_new, dest);
199
0
    SET_FLAG(pi->flags, BGP_PATH_VALID);
200
0
    bgp_path_info_extra_get(pi);
201
0
    pi->extra->parent = bgp_path_info_lock(parent_pi);
202
0
    bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
203
0
    bgp_path_info_add(dest, pi);
204
0
  } else {
205
0
    if (attrhash_cmp(pi->attr, parent_pi->attr)
206
0
        && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
207
0
      bgp_dest_unlock_node(dest);
208
0
      return 0;
209
0
    }
210
    /* The attribute has changed. */
211
    /* Add (or update) attribute to hash. */
212
0
    attr_new = bgp_attr_intern(parent_pi->attr);
213
214
    /* Restore route, if needed. */
215
0
    if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
216
0
      bgp_path_info_restore(dest, pi);
217
218
    /* Mark if nexthop has changed. */
219
0
    if (!IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop))
220
0
      SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
221
222
    /* Unintern existing, set to new. */
223
0
    bgp_attr_unintern(&pi->attr);
224
0
    pi->attr = attr_new;
225
0
    pi->uptime = monotime(NULL);
226
0
  }
227
228
  /* Perform route selection and update zebra, if required. */
229
0
  ret = bgp_evpn_es_route_select_install(bgp, es, dest);
230
231
0
  bgp_dest_unlock_node(dest);
232
233
0
  return ret;
234
0
}
235
236
/* Uninstall Type-1/Type-4 route entry from the ES routing table */
237
static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
238
    struct prefix_evpn *p, struct bgp_path_info *parent_pi)
239
0
{
240
0
  int ret;
241
0
  struct bgp_dest *dest;
242
0
  struct bgp_path_info *pi;
243
244
0
  if (!es->route_table)
245
0
    return 0;
246
247
  /* Locate route within the ESI.
248
   * NOTE: There is no RD here.
249
   */
250
0
  dest = bgp_node_lookup(es->route_table, (struct prefix *)p);
251
0
  if (!dest)
252
0
    return 0;
253
254
  /* Find matching route entry. */
255
0
  for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
256
0
    if (pi->extra
257
0
        && (struct bgp_path_info *)pi->extra->parent ==
258
0
        parent_pi)
259
0
      break;
260
261
0
  if (!pi) {
262
0
    bgp_dest_unlock_node(dest);
263
0
    return 0;
264
0
  }
265
266
  /* Mark entry for deletion */
267
0
  bgp_path_info_delete(dest, pi);
268
269
  /* Perform route selection and update zebra, if required. */
270
0
  ret = bgp_evpn_es_route_select_install(bgp, es, dest);
271
272
  /* Unlock route node. */
273
0
  bgp_dest_unlock_node(dest);
274
275
0
  return ret;
276
0
}
277
278
/* Install or unistall a Type-4 route in the per-ES routing table */
279
int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
280
    afi_t afi, safi_t safi, struct prefix_evpn *evp,
281
    struct bgp_path_info *pi, int install)
282
0
{
283
0
  int ret = 0;
284
285
0
  if (install)
286
0
    ret = bgp_evpn_es_route_install(bgp, es, evp, pi);
287
0
  else
288
0
    ret = bgp_evpn_es_route_uninstall(bgp, es, evp, pi);
289
290
0
  if (ret) {
291
0
    flog_err(
292
0
        EC_BGP_EVPN_FAIL,
293
0
        "%u: Failed to %s EVPN %s route in ESI %s",
294
0
        bgp->vrf_id,
295
0
        install ? "install" : "uninstall",
296
0
        "ES", es->esi_str);
297
0
    return ret;
298
0
  }
299
0
  return 0;
300
0
}
301
302
/* Delete (and withdraw) local routes for specified ES from global and ES table.
303
 * Also remove all remote routes from the per ES table. Invoked when ES
304
 * is deleted.
305
 */
306
static void bgp_evpn_es_route_del_all(struct bgp *bgp, struct bgp_evpn_es *es)
307
0
{
308
0
  struct bgp_dest *dest;
309
0
  struct bgp_path_info *pi, *nextpi;
310
311
  /* de-activate the ES */
312
0
  bgp_evpn_local_es_down(bgp, es);
313
0
  bgp_evpn_local_type1_evi_route_del(bgp, es);
314
315
  /* Walk this ES's routing table and delete all routes. */
316
0
  for (dest = bgp_table_top(es->route_table); dest;
317
0
       dest = bgp_route_next(dest)) {
318
0
    for (pi = bgp_dest_get_bgp_path_info(dest);
319
0
         (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
320
0
      bgp_path_info_delete(dest, pi);
321
0
      bgp_path_info_reap(dest, pi);
322
0
    }
323
0
  }
324
0
}
325
326
/*****************************************************************************
327
 * Base APIs for creating MH routes (Type-1 or Type-4) on local ethernet
328
 * segment updates.
329
 */
330
331
/* create or update local EVPN type1/type4 route entry.
332
 *
333
 * This could be in -
334
 *     the ES table if ESR/EAD-ES (or)
335
 *     the VNI table if EAD-EVI (or)
336
 *     the global table if ESR/EAD-ES/EAD-EVI
337
 *
338
 * Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
339
 * ESR).
340
 */
341
int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
342
           struct bgpevpn *vpn, afi_t afi, safi_t safi,
343
           struct bgp_dest *dest, struct attr *attr,
344
           struct bgp_path_info **ri, int *route_changed)
345
0
{
346
0
  struct bgp_path_info *tmp_pi = NULL;
347
0
  struct bgp_path_info *local_pi = NULL;  /* local route entry if any */
348
0
  struct bgp_path_info *remote_pi = NULL; /* remote route entry if any */
349
0
  struct attr *attr_new = NULL;
350
0
  struct prefix_evpn *evp;
351
352
0
  *ri = NULL;
353
0
  evp = (struct prefix_evpn *)bgp_dest_get_prefix(dest);
354
0
  *route_changed = 1;
355
356
  /* locate the local and remote entries if any */
357
0
  for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
358
0
       tmp_pi = tmp_pi->next) {
359
0
    if (tmp_pi->peer == bgp->peer_self
360
0
        && tmp_pi->type == ZEBRA_ROUTE_BGP
361
0
        && tmp_pi->sub_type == BGP_ROUTE_STATIC)
362
0
      local_pi = tmp_pi;
363
0
    if (tmp_pi->type == ZEBRA_ROUTE_BGP
364
0
        && tmp_pi->sub_type == BGP_ROUTE_IMPORTED
365
0
        && CHECK_FLAG(tmp_pi->flags, BGP_PATH_VALID))
366
0
      remote_pi = tmp_pi;
367
0
  }
368
369
  /* we don't expect to see a remote_pi at this point as
370
   * an ES route has {esi, vtep_ip} as the key in the ES-rt-table
371
   * in the VNI-rt-table.
372
   */
373
0
  if (remote_pi) {
374
0
    flog_err(
375
0
      EC_BGP_ES_INVALID,
376
0
      "%u ERROR: local es route for ESI: %s vtep %pI4 also learnt from remote",
377
0
      bgp->vrf_id, es ? es->esi_str : "Null",
378
0
      es ? &es->originator_ip : NULL);
379
0
    return -1;
380
0
  }
381
382
  /* create or update the entry */
383
0
  if (!local_pi) {
384
385
    /* Add or update attribute to hash */
386
0
    attr_new = bgp_attr_intern(attr);
387
388
    /* Create new route with its attribute. */
389
0
    tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
390
0
           bgp->peer_self, attr_new, dest);
391
0
    SET_FLAG(tmp_pi->flags, BGP_PATH_VALID);
392
393
0
    if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
394
0
      bgp_path_info_extra_get(tmp_pi);
395
0
      tmp_pi->extra->num_labels = 1;
396
0
      if (vpn)
397
0
        vni2label(vpn->vni, &tmp_pi->extra->label[0]);
398
0
      else
399
0
        tmp_pi->extra->label[0] = 0;
400
0
    }
401
402
    /* add the newly created path to the route-node */
403
0
    bgp_path_info_add(dest, tmp_pi);
404
0
  } else {
405
0
    tmp_pi = local_pi;
406
0
    if (attrhash_cmp(tmp_pi->attr, attr)
407
0
        && !CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
408
0
      *route_changed = 0;
409
0
    else {
410
      /* The attribute has changed.
411
       * Add (or update) attribute to hash.
412
       */
413
0
      attr_new = bgp_attr_intern(attr);
414
0
      bgp_path_info_set_flag(dest, tmp_pi,
415
0
                 BGP_PATH_ATTR_CHANGED);
416
417
      /* Restore route, if needed. */
418
0
      if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
419
0
        bgp_path_info_restore(dest, tmp_pi);
420
421
      /* Unintern existing, set to new. */
422
0
      bgp_attr_unintern(&tmp_pi->attr);
423
0
      tmp_pi->attr = attr_new;
424
0
      tmp_pi->uptime = monotime(NULL);
425
0
    }
426
0
  }
427
428
0
  if (*route_changed) {
429
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
430
0
      zlog_debug(
431
0
        "local ES %s vni %u route-type %s nexthop %pI4 updated",
432
0
        es ? es->esi_str : "Null", vpn ? vpn->vni : 0,
433
0
        evp->prefix.route_type == BGP_EVPN_ES_ROUTE
434
0
          ? "esr"
435
0
          : (vpn ? "ead-evi" : "ead-es"),
436
0
        &attr->mp_nexthop_global_in);
437
0
  }
438
439
  /* Return back the route entry. */
440
0
  *ri = tmp_pi;
441
0
  return 0;
442
0
}
443
444
/* Delete local EVPN ESR (type-4) and EAD (type-1) route
445
 *
446
 * Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
447
 * ESR).
448
 */
449
static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
450
            struct bgpevpn *vpn,
451
            struct bgp_evpn_es_frag *es_frag,
452
            struct prefix_evpn *p)
453
0
{
454
0
  afi_t afi = AFI_L2VPN;
455
0
  safi_t safi = SAFI_EVPN;
456
0
  struct bgp_path_info *pi;
457
0
  struct bgp_dest *dest = NULL;      /* dest in esi table */
458
0
  struct bgp_dest *global_dest = NULL; /* dest in global table */
459
0
  struct bgp_table *rt_table;
460
0
  struct prefix_rd *prd;
461
462
0
  if (vpn) {
463
0
    rt_table = vpn->ip_table;
464
0
    prd = &vpn->prd;
465
0
  } else {
466
0
    rt_table = es->route_table;
467
0
    prd = &es_frag->prd;
468
0
  }
469
470
  /* First, locate the route node within the ESI or VNI.
471
   * If it doesn't exist, ther is nothing to do.
472
   * Note: there is no RD here.
473
   */
474
0
  dest = bgp_node_lookup(rt_table, (struct prefix *)p);
475
0
  if (!dest)
476
0
    return 0;
477
478
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
479
0
    zlog_debug(
480
0
      "local ES %s vni %u route-type %s nexthop %pI4 delete",
481
0
      es->esi_str, vpn ? vpn->vni : 0,
482
0
      p->prefix.route_type == BGP_EVPN_ES_ROUTE
483
0
        ? "esr"
484
0
        : (vpn ? "ead-evi" : "ead-es"),
485
0
      &es->originator_ip);
486
487
  /* Next, locate route node in the global EVPN routing table.
488
   * Note that this table is a 2-level tree (RD-level + Prefix-level)
489
   */
490
0
  global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], safi, p,
491
0
              prd, NULL);
492
0
  if (global_dest) {
493
494
    /* Delete route entry in the global EVPN table. */
495
0
    delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
496
497
    /* Schedule for processing - withdraws to peers happen from
498
     * this table.
499
     */
500
0
    if (pi)
501
0
      bgp_process(bgp, global_dest, afi, safi);
502
0
    bgp_dest_unlock_node(global_dest);
503
0
  }
504
505
  /*
506
   * Delete route entry in the ESI or VNI routing table.
507
   * This can just be removed.
508
   */
509
0
  delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
510
0
  if (pi)
511
0
    bgp_path_info_reap(dest, pi);
512
0
  bgp_dest_unlock_node(dest);
513
0
  return 0;
514
0
}
515
516
/*
517
 * This function is called when the VNI RD changes.
518
 * Delete all EAD/EVI local routes for this VNI from the global routing table.
519
 * These routes are scheduled for withdraw from peers.
520
 */
521
int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
522
0
{
523
0
  afi_t afi;
524
0
  safi_t safi;
525
0
  struct bgp_dest *rdrn, *rn;
526
0
  struct bgp_table *table;
527
0
  struct bgp_path_info *pi;
528
529
0
  afi = AFI_L2VPN;
530
0
  safi = SAFI_EVPN;
531
532
  /* Find the RD node for the VNI in the global table */
533
0
  rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd);
534
0
  if (rdrn && bgp_dest_has_bgp_path_info_data(rdrn)) {
535
0
    table = bgp_dest_get_bgp_table_info(rdrn);
536
537
    /*
538
     * Iterate over all the routes in this table and delete EAD/EVI
539
     * routes
540
     */
541
0
    for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
542
0
      struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
543
544
0
      if (evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
545
0
        continue;
546
547
0
      delete_evpn_route_entry(bgp, afi, safi, rn, &pi);
548
0
      if (pi)
549
0
        bgp_process(bgp, rn, afi, safi);
550
0
    }
551
0
  }
552
553
  /* Unlock RD node. */
554
0
  if (rdrn)
555
0
    bgp_dest_unlock_node(rdrn);
556
557
0
  return 0;
558
0
}
559
560
/*****************************************************************************
561
 * Ethernet Segment (Type-4) Routes
562
 * ESRs are used for DF election. Currently service-carving described in
563
 * RFC 7432 is NOT supported. Instead preference based DF election is
564
 * used by default.
565
 * Reference: draft-ietf-bess-evpn-pref-df
566
 */
567
/* Build extended community for EVPN ES (type-4) route */
568
static void bgp_evpn_type4_route_extcomm_build(struct bgp_evpn_es *es,
569
    struct attr *attr)
570
0
{
571
0
  struct ecommunity ecom_encap;
572
0
  struct ecommunity ecom_es_rt;
573
0
  struct ecommunity ecom_df;
574
0
  struct ecommunity_val eval;
575
0
  struct ecommunity_val eval_es_rt;
576
0
  struct ecommunity_val eval_df;
577
0
  bgp_encap_types tnl_type;
578
0
  struct ethaddr mac;
579
580
  /* Encap */
581
0
  tnl_type = BGP_ENCAP_TYPE_VXLAN;
582
0
  memset(&ecom_encap, 0, sizeof(ecom_encap));
583
0
  encode_encap_extcomm(tnl_type, &eval);
584
0
  ecom_encap.size = 1;
585
0
  ecom_encap.unit_size = ECOMMUNITY_SIZE;
586
0
  ecom_encap.val = (uint8_t *)eval.val;
587
0
  bgp_attr_set_ecommunity(attr, ecommunity_dup(&ecom_encap));
588
589
  /* ES import RT */
590
0
  memset(&mac, 0, sizeof(mac));
591
0
  memset(&ecom_es_rt, 0, sizeof(ecom_es_rt));
592
0
  es_get_system_mac(&es->esi, &mac);
593
0
  encode_es_rt_extcomm(&eval_es_rt, &mac);
594
0
  ecom_es_rt.size = 1;
595
0
  ecom_es_rt.unit_size = ECOMMUNITY_SIZE;
596
0
  ecom_es_rt.val = (uint8_t *)eval_es_rt.val;
597
0
  bgp_attr_set_ecommunity(
598
0
    attr,
599
0
    ecommunity_merge(bgp_attr_get_ecommunity(attr), &ecom_es_rt));
600
601
  /* DF election extended community */
602
0
  memset(&ecom_df, 0, sizeof(ecom_df));
603
0
  encode_df_elect_extcomm(&eval_df, es->df_pref);
604
0
  ecom_df.size = 1;
605
0
  ecom_df.val = (uint8_t *)eval_df.val;
606
0
  bgp_attr_set_ecommunity(
607
0
    attr,
608
0
    ecommunity_merge(bgp_attr_get_ecommunity(attr), &ecom_df));
609
0
}
610
611
/* Create or update local type-4 route */
612
static int bgp_evpn_type4_route_update(struct bgp *bgp,
613
    struct bgp_evpn_es *es, struct prefix_evpn *p)
614
0
{
615
0
  int ret = 0;
616
0
  int route_changed = 0;
617
0
  afi_t afi = AFI_L2VPN;
618
0
  safi_t safi = SAFI_EVPN;
619
0
  struct attr attr;
620
0
  struct attr *attr_new = NULL;
621
0
  struct bgp_dest *dest = NULL;
622
0
  struct bgp_path_info *pi = NULL;
623
624
0
  memset(&attr, 0, sizeof(attr));
625
626
  /* Build path-attribute for this route. */
627
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
628
0
  attr.nexthop = es->originator_ip;
629
0
  attr.mp_nexthop_global_in = es->originator_ip;
630
0
  attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
631
632
  /* Set up extended community. */
633
0
  bgp_evpn_type4_route_extcomm_build(es, &attr);
634
635
  /* First, create (or fetch) route node within the ESI. */
636
  /* NOTE: There is no RD here. */
637
0
  dest = bgp_node_get(es->route_table, (struct prefix *)p);
638
639
  /* Create or update route entry. */
640
0
  ret = bgp_evpn_mh_route_update(bgp, es, NULL, afi, safi, dest, &attr,
641
0
               &pi, &route_changed);
642
0
  if (ret != 0)
643
0
    flog_err(
644
0
      EC_BGP_ES_INVALID,
645
0
      "%u ERROR: Failed to updated ES route ESI: %s VTEP %pI4",
646
0
      bgp->vrf_id, es->esi_str, &es->originator_ip);
647
648
0
  assert(pi);
649
0
  attr_new = pi->attr;
650
651
  /* Perform route selection;
652
   * this is just to set the flags correctly
653
   * as local route in the ES always wins.
654
   */
655
0
  bgp_evpn_es_route_select_install(bgp, es, dest);
656
0
  bgp_dest_unlock_node(dest);
657
658
  /* If this is a new route or some attribute has changed, export the
659
   * route to the global table. The route will be advertised to peers
660
   * from there. Note that this table is a 2-level tree (RD-level +
661
   * Prefix-level) similar to L3VPN routes.
662
   */
663
0
  if (route_changed) {
664
0
    struct bgp_path_info *global_pi;
665
666
0
    dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
667
0
            p, &es->es_base_frag->prd,
668
0
            NULL);
669
0
    bgp_evpn_mh_route_update(bgp, es, NULL, afi, safi, dest,
670
0
           attr_new, &global_pi, &route_changed);
671
672
    /* Schedule for processing and unlock node. */
673
0
    bgp_process(bgp, dest, afi, safi);
674
0
    bgp_dest_unlock_node(dest);
675
0
  }
676
677
  /* Unintern temporary. */
678
0
  aspath_unintern(&attr.aspath);
679
0
  return 0;
680
0
}
681
682
/* Delete local type-4 route */
683
static int bgp_evpn_type4_route_delete(struct bgp *bgp,
684
    struct bgp_evpn_es *es, struct prefix_evpn *p)
685
0
{
686
0
  if (!es->es_base_frag)
687
0
    return -1;
688
689
0
  return bgp_evpn_mh_route_delete(bgp, es, NULL /* l2vni */,
690
0
          es->es_base_frag, p);
691
0
}
692
693
/* Process remote/received EVPN type-4 route (advertise or withdraw)  */
694
int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
695
    struct attr *attr, uint8_t *pfx, int psize,
696
    uint32_t addpath_id)
697
14
{
698
14
  esi_t esi;
699
14
  uint8_t ipaddr_len;
700
14
  struct in_addr vtep_ip;
701
14
  struct prefix_rd prd;
702
14
  struct prefix_evpn p;
703
704
  /* Type-4 route should be either 23 or 35 bytes
705
   *  RD (8), ESI (10), ip-len (1), ip (4 or 16)
706
   */
707
14
  if (psize != BGP_EVPN_TYPE4_V4_PSIZE &&
708
14
      psize != BGP_EVPN_TYPE4_V6_PSIZE) {
709
13
    flog_err(EC_BGP_EVPN_ROUTE_INVALID,
710
13
        "%u:%s - Rx EVPN Type-4 NLRI with invalid length %d",
711
13
        peer->bgp->vrf_id, peer->host, psize);
712
13
    return -1;
713
13
  }
714
715
  /* Make prefix_rd */
716
1
  prd.family = AF_UNSPEC;
717
1
  prd.prefixlen = 64;
718
1
  memcpy(&prd.val, pfx, RD_BYTES);
719
1
  pfx += RD_BYTES;
720
721
  /* get the ESI */
722
1
  memcpy(&esi, pfx, ESI_BYTES);
723
1
  pfx += ESI_BYTES;
724
725
726
  /* Get the IP. */
727
1
  ipaddr_len = *pfx++;
728
1
  if (ipaddr_len == IPV4_MAX_BITLEN) {
729
1
    memcpy(&vtep_ip, pfx, IPV4_MAX_BYTELEN);
730
1
  } else {
731
0
    flog_err(
732
0
        EC_BGP_EVPN_ROUTE_INVALID,
733
0
        "%u:%s - Rx EVPN Type-4 NLRI with unsupported IP address length %d",
734
0
        peer->bgp->vrf_id, peer->host, ipaddr_len);
735
0
    return -1;
736
0
  }
737
738
1
  build_evpn_type4_prefix(&p, &esi, vtep_ip);
739
  /* Process the route. */
740
1
  if (attr) {
741
1
    bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
742
1
         safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
743
1
         0, 0, NULL);
744
1
  } else {
745
0
    bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
746
0
           ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0,
747
0
           NULL);
748
0
  }
749
1
  return 0;
750
1
}
751
752
/* Check if a prefix belongs to the local ES */
753
static bool bgp_evpn_type4_prefix_match(struct prefix_evpn *p,
754
    struct bgp_evpn_es *es)
755
0
{
756
0
  return (p->prefix.route_type == BGP_EVPN_ES_ROUTE) &&
757
0
    !memcmp(&p->prefix.es_addr.esi, &es->esi, sizeof(esi_t));
758
0
}
759
760
/* Import remote ESRs on local ethernet segment add  */
761
static int bgp_evpn_type4_remote_routes_import(struct bgp *bgp,
762
    struct bgp_evpn_es *es, bool install)
763
0
{
764
0
  int ret;
765
0
  afi_t afi;
766
0
  safi_t safi;
767
0
  struct bgp_dest *rd_dest, *dest;
768
0
  struct bgp_table *table;
769
0
  struct bgp_path_info *pi;
770
771
0
  afi = AFI_L2VPN;
772
0
  safi = SAFI_EVPN;
773
774
  /* Walk entire global routing table and evaluate routes which could be
775
   * imported into this Ethernet Segment.
776
   */
777
0
  for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
778
0
       rd_dest = bgp_route_next(rd_dest)) {
779
0
    table = bgp_dest_get_bgp_table_info(rd_dest);
780
0
    if (!table)
781
0
      continue;
782
783
0
    for (dest = bgp_table_top(table); dest;
784
0
         dest = bgp_route_next(dest)) {
785
0
      struct prefix_evpn *evp =
786
0
        (struct prefix_evpn *)bgp_dest_get_prefix(dest);
787
788
0
      for (pi = bgp_dest_get_bgp_path_info(dest); pi;
789
0
           pi = pi->next) {
790
        /*
791
         * Consider "valid" remote routes applicable for
792
         * this ES.
793
         */
794
0
        if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID)
795
0
          && pi->type == ZEBRA_ROUTE_BGP
796
0
          && pi->sub_type == BGP_ROUTE_NORMAL))
797
0
          continue;
798
799
0
        if (!bgp_evpn_type4_prefix_match(evp, es))
800
0
          continue;
801
802
0
        if (install)
803
0
          ret = bgp_evpn_es_route_install(
804
0
              bgp, es, evp, pi);
805
0
        else
806
0
          ret = bgp_evpn_es_route_uninstall(
807
0
              bgp, es, evp, pi);
808
809
0
        if (ret) {
810
0
          flog_err(
811
0
            EC_BGP_EVPN_FAIL,
812
0
            "Failed to %s EVPN %pFX route in ESI %s",
813
0
            install ? "install"
814
0
              : "uninstall",
815
0
            evp, es->esi_str);
816
817
0
          bgp_dest_unlock_node(rd_dest);
818
0
          bgp_dest_unlock_node(dest);
819
0
          return ret;
820
0
        }
821
0
      }
822
0
    }
823
0
  }
824
0
  return 0;
825
0
}
826
827
/*****************************************************************************
828
 * Ethernet Auto Discovery (EAD/Type-1) route handling
829
 * There are two types of EAD routes -
830
 * 1. EAD-per-ES - Key: {ESI, ET=0xffffffff}
831
 * 2. EAD-per-EVI - Key: {ESI, ET=0}
832
 */
833
834
/* Extended communities associated with EAD-per-ES */
835
static void
836
bgp_evpn_type1_es_route_extcomm_build(struct bgp_evpn_es_frag *es_frag,
837
              struct attr *attr)
838
0
{
839
0
  struct ecommunity ecom_encap;
840
0
  struct ecommunity ecom_esi_label;
841
0
  struct ecommunity_val eval;
842
0
  struct ecommunity_val eval_esi_label;
843
0
  bgp_encap_types tnl_type;
844
0
  struct listnode *evi_node, *rt_node;
845
0
  struct ecommunity *ecom;
846
0
  struct bgp_evpn_es_evi *es_evi;
847
848
  /* Encap */
849
0
  tnl_type = BGP_ENCAP_TYPE_VXLAN;
850
0
  memset(&ecom_encap, 0, sizeof(ecom_encap));
851
0
  encode_encap_extcomm(tnl_type, &eval);
852
0
  ecom_encap.size = 1;
853
0
  ecom_encap.unit_size = ECOMMUNITY_SIZE;
854
0
  ecom_encap.val = (uint8_t *)eval.val;
855
0
  bgp_attr_set_ecommunity(attr, ecommunity_dup(&ecom_encap));
856
857
  /* ESI label */
858
0
  encode_esi_label_extcomm(&eval_esi_label,
859
0
      false /*single_active*/);
860
0
  ecom_esi_label.size = 1;
861
0
  ecom_esi_label.unit_size = ECOMMUNITY_SIZE;
862
0
  ecom_esi_label.val = (uint8_t *)eval_esi_label.val;
863
0
  bgp_attr_set_ecommunity(attr,
864
0
        ecommunity_merge(bgp_attr_get_ecommunity(attr),
865
0
             &ecom_esi_label));
866
867
  /* Add export RTs for all L2-VNIs associated with this ES */
868
  /* XXX - suppress EAD-ES advertisment if there are no EVIs associated
869
   * with it.
870
   */
871
0
  if (listcount(bgp_mh_info->ead_es_export_rtl)) {
872
0
    for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl,
873
0
            rt_node, ecom))
874
0
      bgp_attr_set_ecommunity(
875
0
        attr, ecommunity_merge(attr->ecommunity, ecom));
876
0
  } else {
877
0
    for (ALL_LIST_ELEMENTS_RO(es_frag->es_evi_frag_list, evi_node,
878
0
            es_evi)) {
879
0
      if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
880
0
        continue;
881
0
      for (ALL_LIST_ELEMENTS_RO(es_evi->vpn->export_rtl,
882
0
              rt_node, ecom))
883
0
        bgp_attr_set_ecommunity(
884
0
          attr, ecommunity_merge(attr->ecommunity,
885
0
                     ecom));
886
0
    }
887
0
  }
888
0
}
889
890
/* Extended communities associated with EAD-per-EVI */
891
static void bgp_evpn_type1_evi_route_extcomm_build(struct bgp_evpn_es *es,
892
    struct bgpevpn *vpn, struct attr *attr)
893
0
{
894
0
  struct ecommunity ecom_encap;
895
0
  struct ecommunity_val eval;
896
0
  bgp_encap_types tnl_type;
897
0
  struct listnode *rt_node;
898
0
  struct ecommunity *ecom;
899
900
  /* Encap */
901
0
  tnl_type = BGP_ENCAP_TYPE_VXLAN;
902
0
  memset(&ecom_encap, 0, sizeof(ecom_encap));
903
0
  encode_encap_extcomm(tnl_type, &eval);
904
0
  ecom_encap.size = 1;
905
0
  ecom_encap.unit_size = ECOMMUNITY_SIZE;
906
0
  ecom_encap.val = (uint8_t *)eval.val;
907
0
  bgp_attr_set_ecommunity(attr, ecommunity_dup(&ecom_encap));
908
909
  /* Add export RTs for the L2-VNI */
910
0
  for (ALL_LIST_ELEMENTS_RO(vpn->export_rtl, rt_node, ecom))
911
0
    bgp_attr_set_ecommunity(
912
0
      attr,
913
0
      ecommunity_merge(bgp_attr_get_ecommunity(attr), ecom));
914
0
}
915
916
/* Update EVPN EAD (type-1) route -
917
 * vpn - valid for EAD-EVI routes and NULL for EAD-ES routes
918
 */
919
static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
920
               struct bgpevpn *vpn,
921
               struct bgp_evpn_es_frag *es_frag,
922
               struct prefix_evpn *p)
923
0
{
924
0
  int ret = 0;
925
0
  afi_t afi = AFI_L2VPN;
926
0
  safi_t safi = SAFI_EVPN;
927
0
  struct attr attr;
928
0
  struct attr *attr_new = NULL;
929
0
  struct bgp_dest *dest = NULL;
930
0
  struct bgp_path_info *pi = NULL;
931
0
  int route_changed = 0;
932
0
  struct prefix_rd *global_rd;
933
934
0
  memset(&attr, 0, sizeof(attr));
935
936
  /* Build path-attribute for this route. */
937
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
938
0
  attr.nexthop = es->originator_ip;
939
0
  attr.mp_nexthop_global_in = es->originator_ip;
940
0
  attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
941
942
0
  if (vpn) {
943
    /* EAD-EVI route update */
944
    /* MPLS label */
945
0
    vni2label(vpn->vni, &(attr.label));
946
947
    /* Set up extended community */
948
0
    bgp_evpn_type1_evi_route_extcomm_build(es, vpn, &attr);
949
950
    /* First, create (or fetch) route node within the VNI. */
951
0
    dest = bgp_node_get(vpn->ip_table, (struct prefix *)p);
952
953
    /* Create or update route entry. */
954
0
    ret = bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
955
0
                 &attr, &pi, &route_changed);
956
0
    if (ret != 0)
957
0
      flog_err(
958
0
        EC_BGP_ES_INVALID,
959
0
        "%u Failed to update EAD-EVI route ESI: %s VNI %u VTEP %pI4",
960
0
        bgp->vrf_id, es->esi_str, vpn->vni,
961
0
        &es->originator_ip);
962
0
    global_rd = &vpn->prd;
963
0
  } else {
964
    /* EAD-ES route update */
965
    /* MPLS label is 0 for EAD-ES route */
966
967
    /* Set up extended community */
968
0
    bgp_evpn_type1_es_route_extcomm_build(es_frag, &attr);
969
970
    /* First, create (or fetch) route node within the ES. */
971
    /* NOTE: There is no RD here. */
972
    /* XXX: fragment ID must be included as a part of the prefix. */
973
0
    dest = bgp_node_get(es->route_table, (struct prefix *)p);
974
975
    /* Create or update route entry. */
976
0
    ret = bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
977
0
                 &attr, &pi, &route_changed);
978
0
    if (ret != 0) {
979
0
      flog_err(
980
0
        EC_BGP_ES_INVALID,
981
0
        "%u ERROR: Failed to updated EAD-ES route ESI: %s VTEP %pI4",
982
0
        bgp->vrf_id, es->esi_str, &es->originator_ip);
983
0
    }
984
0
    global_rd = &es_frag->prd;
985
0
  }
986
987
988
0
  assert(pi);
989
0
  attr_new = pi->attr;
990
991
  /* Perform route selection;
992
   * this is just to set the flags correctly as local route in
993
   * the ES always wins.
994
   */
995
0
  evpn_route_select_install(bgp, vpn, dest);
996
0
  bgp_dest_unlock_node(dest);
997
998
  /* If this is a new route or some attribute has changed, export the
999
   * route to the global table. The route will be advertised to peers
1000
   * from there. Note that this table is a 2-level tree (RD-level +
1001
   * Prefix-level) similar to L3VPN routes.
1002
   */
1003
0
  if (route_changed) {
1004
0
    struct bgp_path_info *global_pi;
1005
1006
0
    dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
1007
0
            p, global_rd, NULL);
1008
0
    bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
1009
0
           attr_new, &global_pi, &route_changed);
1010
1011
    /* Schedule for processing and unlock node. */
1012
0
    bgp_process(bgp, dest, afi, safi);
1013
0
    bgp_dest_unlock_node(dest);
1014
0
  }
1015
1016
  /* Unintern temporary. */
1017
0
  aspath_unintern(&attr.aspath);
1018
0
  return 0;
1019
0
}
1020
1021
/*
1022
 * This function is called when the export RT for a VNI changes.
1023
 * Update all type-1 local routes for this VNI from VNI/ES tables and the global
1024
 * table and advertise these routes to peers.
1025
 */
1026
1027
static void bgp_evpn_ead_es_route_update(struct bgp *bgp,
1028
           struct bgp_evpn_es *es)
1029
0
{
1030
0
  struct listnode *node;
1031
0
  struct bgp_evpn_es_frag *es_frag;
1032
0
  struct prefix_evpn p;
1033
1034
0
  build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG, &es->esi,
1035
0
        es->originator_ip);
1036
0
  for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
1037
0
    if (!listcount(es_frag->es_evi_frag_list))
1038
0
      continue;
1039
1040
0
    p.prefix.ead_addr.frag_id = es_frag->rd_id;
1041
0
    if (bgp_evpn_type1_route_update(bgp, es, NULL, es_frag, &p))
1042
0
      flog_err(
1043
0
        EC_BGP_EVPN_ROUTE_CREATE,
1044
0
        "EAD-ES route creation failure for ESI %s frag %u",
1045
0
        es->esi_str, es_frag->rd_id);
1046
0
  }
1047
0
}
1048
1049
static void bgp_evpn_ead_evi_route_update(struct bgp *bgp,
1050
            struct bgp_evpn_es *es,
1051
            struct bgpevpn *vpn,
1052
            struct prefix_evpn *p)
1053
0
{
1054
0
  if (bgp_evpn_type1_route_update(bgp, es, vpn, NULL, p))
1055
0
    flog_err(EC_BGP_EVPN_ROUTE_CREATE,
1056
0
       "EAD-EVI route creation failure for ESI %s VNI %u",
1057
0
       es->esi_str, vpn->vni);
1058
0
}
1059
1060
void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn)
1061
0
{
1062
0
  struct prefix_evpn p;
1063
0
  struct bgp_evpn_es *es;
1064
0
  struct bgp_evpn_es_evi *es_evi;
1065
1066
1067
0
  RB_FOREACH (es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree) {
1068
0
    es = es_evi->es;
1069
1070
0
    if (es_evi->vpn != vpn)
1071
0
      continue;
1072
1073
    /* Update EAD-ES */
1074
0
    if (bgp_evpn_local_es_is_active(es))
1075
0
      bgp_evpn_ead_es_route_update(bgp, es);
1076
1077
    /* Update EAD-EVI */
1078
0
    if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
1079
0
      build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
1080
0
            &es->esi, es->originator_ip);
1081
0
      bgp_evpn_ead_evi_route_update(bgp, es, vpn, &p);
1082
0
    }
1083
0
  }
1084
0
}
1085
1086
/* Delete local Type-1 route */
1087
static void bgp_evpn_ead_es_route_delete(struct bgp *bgp,
1088
           struct bgp_evpn_es *es)
1089
0
{
1090
0
  struct listnode *node;
1091
0
  struct bgp_evpn_es_frag *es_frag;
1092
0
  struct prefix_evpn p;
1093
1094
0
  build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG, &es->esi,
1095
0
        es->originator_ip);
1096
0
  for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
1097
0
    p.prefix.ead_addr.frag_id = es_frag->rd_id;
1098
0
    bgp_evpn_mh_route_delete(bgp, es, NULL, es_frag, &p);
1099
0
  }
1100
0
}
1101
1102
static int bgp_evpn_ead_evi_route_delete(struct bgp *bgp,
1103
           struct bgp_evpn_es *es,
1104
           struct bgpevpn *vpn,
1105
           struct prefix_evpn *p)
1106
0
{
1107
0
  return bgp_evpn_mh_route_delete(bgp, es, vpn, NULL, p);
1108
0
}
1109
1110
/* Generate EAD-EVI for all VNIs */
1111
static void bgp_evpn_local_type1_evi_route_add(struct bgp *bgp,
1112
    struct bgp_evpn_es *es)
1113
0
{
1114
0
  struct listnode *evi_node;
1115
0
  struct prefix_evpn p;
1116
0
  struct bgp_evpn_es_evi *es_evi;
1117
1118
  /* EAD-per-EVI routes have been suppressed */
1119
0
  if (!bgp_mh_info->ead_evi_tx)
1120
0
    return;
1121
1122
0
  if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI))
1123
    /* EAD-EVI route add for this ES is already done */
1124
0
    return;
1125
1126
0
  SET_FLAG(es->flags, BGP_EVPNES_ADV_EVI);
1127
0
  build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
1128
0
      &es->esi, es->originator_ip);
1129
1130
0
  for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, evi_node, es_evi)) {
1131
0
    if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
1132
0
      continue;
1133
0
    bgp_evpn_ead_evi_route_update(bgp, es, es_evi->vpn, &p);
1134
0
  }
1135
0
}
1136
1137
/*
1138
 * Withdraw EAD-EVI for all VNIs
1139
 */
1140
static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
1141
    struct bgp_evpn_es *es)
1142
0
{
1143
0
  struct listnode *evi_node;
1144
0
  struct prefix_evpn p;
1145
0
  struct bgp_evpn_es_evi *es_evi;
1146
1147
  /* Delete and withdraw locally learnt EAD-EVI route */
1148
0
  if (!CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI))
1149
    /* EAD-EVI route has not been advertised for this ES */
1150
0
    return;
1151
1152
0
  UNSET_FLAG(es->flags, BGP_EVPNES_ADV_EVI);
1153
0
  build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
1154
0
      &es->esi, es->originator_ip);
1155
0
  for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, evi_node, es_evi)) {
1156
0
    if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
1157
0
      continue;
1158
0
    if (bgp_evpn_mh_route_delete(bgp, es, es_evi->vpn, NULL, &p))
1159
0
      flog_err(EC_BGP_EVPN_ROUTE_CREATE,
1160
0
          "%u: Type4 route creation failure for ESI %s",
1161
0
          bgp->vrf_id, es->esi_str);
1162
0
  }
1163
0
}
1164
1165
/*
1166
 * Process received EVPN type-1 route (advertise or withdraw).
1167
 */
1168
int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
1169
    struct attr *attr, uint8_t *pfx, int psize,
1170
    uint32_t addpath_id)
1171
17
{
1172
17
  struct prefix_rd prd;
1173
17
  esi_t esi;
1174
17
  uint32_t eth_tag;
1175
17
  mpls_label_t label;
1176
17
  struct in_addr vtep_ip;
1177
17
  struct prefix_evpn p;
1178
1179
17
  if (psize != BGP_EVPN_TYPE1_PSIZE) {
1180
16
    flog_err(EC_BGP_EVPN_ROUTE_INVALID,
1181
16
        "%u:%s - Rx EVPN Type-1 NLRI with invalid length %d",
1182
16
        peer->bgp->vrf_id, peer->host, psize);
1183
16
    return -1;
1184
16
  }
1185
1186
  /* Make prefix_rd */
1187
1
  prd.family = AF_UNSPEC;
1188
1
  prd.prefixlen = 64;
1189
1
  memcpy(&prd.val, pfx, RD_BYTES);
1190
1
  pfx += RD_BYTES;
1191
1192
  /* get the ESI */
1193
1
  memcpy(&esi, pfx, ESI_BYTES);
1194
1
  pfx += ESI_BYTES;
1195
1196
  /* Copy Ethernet Tag */
1197
1
  memcpy(&eth_tag, pfx, EVPN_ETH_TAG_BYTES);
1198
1
  eth_tag = ntohl(eth_tag);
1199
1
  pfx += EVPN_ETH_TAG_BYTES;
1200
1201
1
  memcpy(&label, pfx, BGP_LABEL_BYTES);
1202
1203
  /* EAD route prefix doesn't include the nexthop in the global
1204
   * table
1205
   */
1206
1
  vtep_ip.s_addr = INADDR_ANY;
1207
1
  build_evpn_type1_prefix(&p, eth_tag, &esi, vtep_ip);
1208
  /* Process the route. */
1209
1
  if (attr) {
1210
1
    bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
1211
1
         safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
1212
1
         0, 0, NULL);
1213
1
  } else {
1214
0
    bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi,
1215
0
           ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0,
1216
0
           NULL);
1217
0
  }
1218
1
  return 0;
1219
17
}
1220
1221
void bgp_evpn_mh_config_ead_export_rt(struct bgp *bgp,
1222
              struct ecommunity *ecomcfg, bool del)
1223
0
{
1224
0
  struct listnode *node, *nnode, *node_to_del;
1225
0
  struct ecommunity *ecom;
1226
0
  struct bgp_evpn_es *es;
1227
1228
0
  if (del) {
1229
0
    if (ecomcfg == NULL) {
1230
      /* Reset to default and process all routes. */
1231
0
      for (ALL_LIST_ELEMENTS(bgp_mh_info->ead_es_export_rtl,
1232
0
                 node, nnode, ecom)) {
1233
0
        ecommunity_free(&ecom);
1234
0
        list_delete_node(bgp_mh_info->ead_es_export_rtl,
1235
0
             node);
1236
0
      }
1237
0
    }
1238
1239
    /* Delete a specific export RT */
1240
0
    else {
1241
0
      node_to_del = NULL;
1242
1243
0
      for (ALL_LIST_ELEMENTS(bgp_mh_info->ead_es_export_rtl,
1244
0
                 node, nnode, ecom)) {
1245
0
        if (ecommunity_match(ecom, ecomcfg)) {
1246
0
          ecommunity_free(&ecom);
1247
0
          node_to_del = node;
1248
0
          break;
1249
0
        }
1250
0
      }
1251
1252
0
      assert(node_to_del);
1253
0
      list_delete_node(bgp_mh_info->ead_es_export_rtl,
1254
0
           node_to_del);
1255
0
    }
1256
0
  } else {
1257
0
    listnode_add_sort(bgp_mh_info->ead_es_export_rtl, ecomcfg);
1258
0
  }
1259
1260
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1261
0
    zlog_debug("local ES del/re-add EAD route on export RT change");
1262
  /*
1263
   * walk through all active ESs withdraw the old EAD and
1264
   * generate a new one
1265
   */
1266
0
  RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
1267
0
    if (!bgp_evpn_is_es_local(es) ||
1268
0
        !bgp_evpn_local_es_is_active(es))
1269
0
      continue;
1270
1271
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1272
0
      zlog_debug(
1273
0
        "local ES %s del/re-add EAD route on export RT change",
1274
0
        es->esi_str);
1275
1276
    /*
1277
     * withdraw EAD-ES. XXX - this should technically not be
1278
     * needed; can be removed after testing
1279
     */
1280
0
    bgp_evpn_ead_es_route_delete(bgp, es);
1281
1282
    /* generate EAD-ES */
1283
0
    bgp_evpn_ead_es_route_update(bgp, es);
1284
0
  }
1285
0
}
1286
1287
/*****************************************************************************/
1288
/* Ethernet Segment Management
1289
 * 1. Ethernet Segment is a collection of links attached to the same
1290
 *    server (MHD) or switch (MHN)
1291
 * 2. An Ethernet Segment can span multiple PEs and is identified by the
1292
 *    10-byte ES-ID.
1293
 * 3. Local ESs are configured in zebra and sent to BGP
1294
 * 4. Remote ESs are created by BGP when one or more ES-EVIs reference it i.e.
1295
 *    created on first reference and release on last de-reference
1296
 * 5. An ES can be both local and remote. Infact most local ESs are expected
1297
 *    to have an ES peer.
1298
 */
1299
1300
/* A list of remote VTEPs is maintained for each ES. This list includes -
1301
 * 1. VTEPs for which we have imported the ESR i.e. ES-peers
1302
 * 2. VTEPs that have an "active" ES-EVI VTEP i.e. EAD-per-ES and EAD-per-EVI
1303
 *    have been imported into one or more VNIs
1304
 */
1305
static int bgp_evpn_es_vtep_cmp(void *p1, void *p2)
1306
0
{
1307
0
  const struct bgp_evpn_es_vtep *es_vtep1 = p1;
1308
0
  const struct bgp_evpn_es_vtep *es_vtep2 = p2;
1309
1310
0
  return es_vtep1->vtep_ip.s_addr - es_vtep2->vtep_ip.s_addr;
1311
0
}
1312
1313
static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_new(struct bgp_evpn_es *es,
1314
    struct in_addr vtep_ip)
1315
0
{
1316
0
  struct bgp_evpn_es_vtep *es_vtep;
1317
1318
0
  es_vtep = XCALLOC(MTYPE_BGP_EVPN_ES_VTEP, sizeof(*es_vtep));
1319
1320
0
  es_vtep->es = es;
1321
0
  es_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
1322
0
  inet_ntop(AF_INET, &es_vtep->vtep_ip, es_vtep->vtep_str,
1323
0
      sizeof(es_vtep->vtep_str));
1324
0
  listnode_init(&es_vtep->es_listnode, es_vtep);
1325
0
  listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode);
1326
1327
0
  return es_vtep;
1328
0
}
1329
1330
static void bgp_evpn_es_vtep_free(struct bgp_evpn_es_vtep *es_vtep)
1331
0
{
1332
0
  struct bgp_evpn_es *es = es_vtep->es;
1333
1334
0
  if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR) ||
1335
0
      es_vtep->evi_cnt)
1336
    /* as long as there is some reference we can't free it */
1337
0
    return;
1338
1339
0
  list_delete_node(es->es_vtep_list, &es_vtep->es_listnode);
1340
0
  XFREE(MTYPE_BGP_EVPN_ES_VTEP, es_vtep);
1341
0
}
1342
1343
/* check if VTEP is already part of the list */
1344
static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es,
1345
    struct in_addr vtep_ip)
1346
0
{
1347
0
  struct listnode *node = NULL;
1348
0
  struct bgp_evpn_es_vtep *es_vtep;
1349
1350
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1351
0
    if (es_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
1352
0
      return es_vtep;
1353
0
  }
1354
0
  return NULL;
1355
0
}
1356
1357
/* Send the remote ES to zebra for NHG programming */
1358
static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
1359
    struct bgp_evpn_es_vtep *es_vtep, bool add)
1360
0
{
1361
0
  struct bgp_evpn_es *es = es_vtep->es;
1362
0
  struct stream *s;
1363
0
  uint32_t flags = 0;
1364
1365
  /* Check socket. */
1366
0
  if (!zclient || zclient->sock < 0)
1367
0
    return 0;
1368
1369
  /* Don't try to register if Zebra doesn't know of this instance. */
1370
0
  if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
1371
0
    if (BGP_DEBUG(zebra, ZEBRA))
1372
0
      zlog_debug("No zebra instance, not installing remote es %s",
1373
0
          es->esi_str);
1374
0
    return 0;
1375
0
  }
1376
1377
0
  if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1378
0
    flags |= ZAPI_ES_VTEP_FLAG_ESR_RXED;
1379
1380
0
  s = zclient->obuf;
1381
0
  stream_reset(s);
1382
1383
0
  zclient_create_header(s,
1384
0
    add ? ZEBRA_REMOTE_ES_VTEP_ADD : ZEBRA_REMOTE_ES_VTEP_DEL,
1385
0
    bgp->vrf_id);
1386
0
  stream_put(s, &es->esi, sizeof(esi_t));
1387
0
  stream_put_ipv4(s, es_vtep->vtep_ip.s_addr);
1388
0
  if (add) {
1389
0
    stream_putl(s, flags);
1390
0
    stream_putc(s, es_vtep->df_alg);
1391
0
    stream_putw(s, es_vtep->df_pref);
1392
0
  }
1393
1394
0
  stream_putw_at(s, 0, stream_get_endp(s));
1395
1396
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1397
0
    zlog_debug("Tx %s Remote ESI %s VTEP %pI4", add ? "ADD" : "DEL",
1398
0
         es->esi_str, &es_vtep->vtep_ip);
1399
1400
0
  frrtrace(3, frr_bgp, evpn_mh_vtep_zsend, add, es, es_vtep);
1401
1402
0
  return zclient_send_message(zclient);
1403
0
}
1404
1405
static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
1406
              struct bgp_evpn_es_vtep *es_vtep,
1407
              bool param_change)
1408
0
{
1409
0
  bool old_active;
1410
0
  bool new_active;
1411
1412
0
  old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1413
  /* currently we need an active EVI reference to use the VTEP as
1414
   * a nexthop. this may change...
1415
   */
1416
0
  if (es_vtep->evi_cnt)
1417
0
    SET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1418
0
  else
1419
0
    UNSET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1420
1421
0
  new_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1422
1423
0
  if ((old_active != new_active) || (new_active && param_change)) {
1424
1425
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1426
0
      zlog_debug("es %s vtep %pI4 %s df %u/%u",
1427
0
           es_vtep->es->esi_str, &es_vtep->vtep_ip,
1428
0
           new_active ? "active" : "inactive",
1429
0
           es_vtep->df_alg, es_vtep->df_pref);
1430
1431
    /* send remote ES to zebra */
1432
0
    bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
1433
1434
    /* The NHG is updated first for efficient failover handling.
1435
     * Note the NHG can be de-activated while there are bgp
1436
     * routes referencing it. Zebra is capable of handling that
1437
     * elegantly by holding the NHG till all routes using it are
1438
     * removed.
1439
     */
1440
0
    bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es);
1441
    /* queue up the es for background consistency checks */
1442
0
    bgp_evpn_es_cons_checks_pend_add(es_vtep->es);
1443
0
  }
1444
0
}
1445
1446
static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
1447
                 struct bgp_evpn_es *es,
1448
                 struct in_addr vtep_ip,
1449
                 bool esr, uint8_t df_alg,
1450
                 uint16_t df_pref)
1451
0
{
1452
0
  struct bgp_evpn_es_vtep *es_vtep;
1453
0
  bool param_change = false;
1454
1455
0
  es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
1456
1457
0
  if (!es_vtep)
1458
0
    es_vtep = bgp_evpn_es_vtep_new(es, vtep_ip);
1459
1460
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1461
0
    zlog_debug("es %s vtep %pI4 add %s df %u/%u",
1462
0
         es_vtep->es->esi_str, &es_vtep->vtep_ip,
1463
0
         esr ? "esr" : "ead", df_alg, df_pref);
1464
1465
0
  if (esr) {
1466
0
    SET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR);
1467
0
    if ((es_vtep->df_pref != df_pref)
1468
0
        || (es_vtep->df_alg != df_alg)) {
1469
0
      param_change = true;
1470
0
      es_vtep->df_pref = df_pref;
1471
0
      es_vtep->df_alg = df_alg;
1472
0
    }
1473
0
  } else {
1474
0
    ++es_vtep->evi_cnt;
1475
0
  }
1476
1477
0
  bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
1478
1479
0
  return es_vtep;
1480
0
}
1481
1482
static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
1483
    struct bgp_evpn_es_vtep *es_vtep, bool esr)
1484
0
{
1485
0
  bool param_change = false;
1486
1487
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1488
0
    zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str,
1489
0
         &es_vtep->vtep_ip, esr ? "esr" : "ead");
1490
0
  if (esr) {
1491
0
    UNSET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR);
1492
0
    if (es_vtep->df_pref || es_vtep->df_alg) {
1493
0
      param_change = true;
1494
0
      es_vtep->df_pref = 0;
1495
0
      es_vtep->df_alg = 0;
1496
0
    }
1497
0
  } else {
1498
0
    if (es_vtep->evi_cnt)
1499
0
      --es_vtep->evi_cnt;
1500
0
  }
1501
1502
0
  bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
1503
0
  bgp_evpn_es_vtep_free(es_vtep);
1504
0
}
1505
1506
static void bgp_evpn_es_vtep_del(struct bgp *bgp,
1507
    struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr)
1508
0
{
1509
0
  struct bgp_evpn_es_vtep *es_vtep;
1510
1511
0
  es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
1512
0
  if (es_vtep)
1513
0
    bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
1514
0
}
1515
1516
/********************** ES MAC-IP paths *************************************
1517
 * 1. Local MAC-IP routes in the VNI routing table are linked to the
1518
 * destination ES (macip_evi_path_list) for efficient updates on ES oper
1519
 * state changes.
1520
 * 2. Non-local MAC-IP routes in the global routing table are linked to
1521
 * the detination for efficient updates on -
1522
 * a. VTEP add/del - this results in a L3NHG update.
1523
 * b. ES-VRF add/del - this may result in the host route being migrated to
1524
 *    L3NHG or vice versa (flat multipath list).
1525
 ****************************************************************************/
1526
static void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info)
1527
0
{
1528
0
  bgp_evpn_path_es_unlink(es_info);
1529
0
  XFREE(MTYPE_BGP_EVPN_PATH_ES_INFO, es_info);
1530
0
}
1531
1532
void bgp_evpn_path_mh_info_free(struct bgp_path_mh_info *mh_info)
1533
0
{
1534
0
  if (mh_info->es_info)
1535
0
    bgp_evpn_path_es_info_free(mh_info->es_info);
1536
0
  if (mh_info->nh_info)
1537
0
    bgp_evpn_path_nh_info_free(mh_info->nh_info);
1538
0
  XFREE(MTYPE_BGP_EVPN_PATH_MH_INFO, mh_info);
1539
0
}
1540
1541
static struct bgp_path_es_info *
1542
bgp_evpn_path_es_info_new(struct bgp_path_info *pi, vni_t vni)
1543
0
{
1544
0
  struct bgp_path_info_extra *e;
1545
0
  struct bgp_path_mh_info *mh_info;
1546
0
  struct bgp_path_es_info *es_info;
1547
1548
0
  e = bgp_path_info_extra_get(pi);
1549
1550
  /* If mh_info doesn't exist allocate it */
1551
0
  mh_info = e->mh_info;
1552
0
  if (!mh_info)
1553
0
    e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
1554
0
                 sizeof(struct bgp_path_mh_info));
1555
1556
  /* If es_info doesn't exist allocate it */
1557
0
  es_info = mh_info->es_info;
1558
0
  if (!es_info) {
1559
0
    mh_info->es_info = es_info =
1560
0
      XCALLOC(MTYPE_BGP_EVPN_PATH_ES_INFO,
1561
0
        sizeof(struct bgp_path_es_info));
1562
0
    es_info->vni = vni;
1563
0
    es_info->pi = pi;
1564
0
  }
1565
1566
0
  return es_info;
1567
0
}
1568
1569
static void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info)
1570
0
{
1571
0
  struct bgp_evpn_es *es = es_info->es;
1572
0
  struct bgp_path_info *pi;
1573
1574
0
  if (!es)
1575
0
    return;
1576
1577
0
  pi = es_info->pi;
1578
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1579
0
    zlog_debug("vni %u path %pFX unlinked from es %s", es_info->vni,
1580
0
         &pi->net->p, es->esi_str);
1581
1582
0
  if (es_info->vni)
1583
0
    list_delete_node(es->macip_evi_path_list,
1584
0
         &es_info->es_listnode);
1585
0
  else
1586
0
    list_delete_node(es->macip_global_path_list,
1587
0
         &es_info->es_listnode);
1588
1589
0
  es_info->es = NULL;
1590
1591
  /* if there are no other references against the ES it
1592
   * needs to be freed
1593
   */
1594
0
  bgp_evpn_es_free(es, __func__);
1595
1596
  /* Note we don't free the path es_info on unlink; it will be freed up
1597
   * along with the path.
1598
   */
1599
0
}
1600
1601
void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi)
1602
0
{
1603
0
  struct bgp_path_es_info *es_info;
1604
0
  struct bgp_evpn_es *es;
1605
0
  struct bgp *bgp_evpn;
1606
1607
0
  es_info = (pi->extra && pi->extra->mh_info)
1608
0
        ? pi->extra->mh_info->es_info
1609
0
        : NULL;
1610
  /* if the esi is zero just unlink the path from the old es */
1611
0
  if (!esi || !memcmp(esi, zero_esi, sizeof(*esi))) {
1612
0
    if (es_info)
1613
0
      bgp_evpn_path_es_unlink(es_info);
1614
0
    return;
1615
0
  }
1616
1617
0
  bgp_evpn = bgp_get_evpn();
1618
0
  if (!bgp_evpn)
1619
0
    return;
1620
1621
  /* setup es_info against the path if it doesn't aleady exist */
1622
0
  if (!es_info)
1623
0
    es_info = bgp_evpn_path_es_info_new(pi, vni);
1624
1625
  /* find-create ES */
1626
0
  es = bgp_evpn_es_find(esi);
1627
0
  if (!es)
1628
0
    es = bgp_evpn_es_new(bgp_evpn, esi);
1629
1630
  /* dup check */
1631
0
  if (es_info->es == es)
1632
0
    return;
1633
1634
  /* unlink old ES if any */
1635
0
  bgp_evpn_path_es_unlink(es_info);
1636
1637
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1638
0
    zlog_debug("vni %u path %pFX linked to es %s", vni, &pi->net->p,
1639
0
         es->esi_str);
1640
1641
  /* link mac-ip path to the new destination ES */
1642
0
  es_info->es = es;
1643
0
  listnode_init(&es_info->es_listnode, es_info);
1644
0
  if (es_info->vni)
1645
0
    listnode_add(es->macip_evi_path_list, &es_info->es_listnode);
1646
0
  else
1647
0
    listnode_add(es->macip_global_path_list, &es_info->es_listnode);
1648
0
}
1649
1650
static bool bgp_evpn_is_macip_path(struct bgp_path_info *pi)
1651
0
{
1652
0
  struct prefix_evpn *evp;
1653
1654
  /* Only MAC-IP routes need to be linked (MAC-only routes can be
1655
   * skipped) as these lists are maintained for managing
1656
   * host routes in the tenant VRF
1657
   */
1658
0
  evp = (struct prefix_evpn *)&pi->net->p;
1659
0
  return is_evpn_prefix_ipaddr_v4(evp) || is_evpn_prefix_ipaddr_v6(evp);
1660
0
}
1661
1662
/* When a remote ES is added to a VRF, routes using that as
1663
 * a destination need to be migrated to a L3NHG or viceversa.
1664
 * This is done indirectly by re-attempting an install of the
1665
 * route in the associated VRFs. As a part of the VRF install use
1666
 * of l3 NHG is evaluated and this results in the
1667
 * attr.es_flag ATTR_ES_L3_NHG_USE being set or cleared.
1668
 */
1669
static void
1670
bgp_evpn_es_path_update_on_es_vrf_chg(struct bgp_evpn_es_vrf *es_vrf,
1671
              const char *reason)
1672
0
{
1673
0
  struct listnode *node;
1674
0
  struct bgp_path_es_info *es_info;
1675
0
  struct bgp_path_info *pi;
1676
0
  struct bgp_evpn_es *es = es_vrf->es;
1677
1678
0
  if (!bgp_mh_info->host_routes_use_l3nhg)
1679
0
    return;
1680
1681
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1682
0
    zlog_debug("update paths linked to es %s on es-vrf %s %s",
1683
0
         es->esi_str, es_vrf->bgp_vrf->name_pretty, reason);
1684
1685
0
  for (ALL_LIST_ELEMENTS_RO(es->macip_global_path_list, node, es_info)) {
1686
0
    pi = es_info->pi;
1687
1688
0
    if (!bgp_evpn_is_macip_path(pi))
1689
0
      continue;
1690
1691
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1692
0
      zlog_debug(
1693
0
        "update path %pFX linked to es %s on vrf chg",
1694
0
        &pi->net->p, es->esi_str);
1695
0
    bgp_evpn_route_entry_install_if_vrf_match(es_vrf->bgp_vrf, pi,
1696
0
                1);
1697
0
  }
1698
0
}
1699
1700
static void bgp_evpn_es_frag_free(struct bgp_evpn_es_frag *es_frag)
1701
0
{
1702
0
  struct bgp_evpn_es *es = es_frag->es;
1703
1704
0
  if (es->es_base_frag == es_frag)
1705
0
    es->es_base_frag = NULL;
1706
1707
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1708
0
    zlog_debug("es %s frag %u free", es->esi_str, es_frag->rd_id);
1709
0
  list_delete_node(es->es_frag_list, &es_frag->es_listnode);
1710
1711
  /* EVIs that are advertised using the info in this fragment */
1712
0
  list_delete(&es_frag->es_evi_frag_list);
1713
1714
0
  bf_release_index(bm->rd_idspace, es_frag->rd_id);
1715
1716
1717
0
  XFREE(MTYPE_BGP_EVPN_ES_FRAG, es_frag);
1718
0
}
1719
1720
static void bgp_evpn_es_frag_free_unused(struct bgp_evpn_es_frag *es_frag)
1721
0
{
1722
0
  if ((es_frag->es->es_base_frag == es_frag) ||
1723
0
      listcount(es_frag->es_evi_frag_list))
1724
0
    return;
1725
1726
0
  bgp_evpn_es_frag_free(es_frag);
1727
0
}
1728
1729
static void bgp_evpn_es_frag_free_all(struct bgp_evpn_es *es)
1730
0
{
1731
0
  struct listnode *node;
1732
0
  struct listnode *nnode;
1733
0
  struct bgp_evpn_es_frag *es_frag;
1734
1735
0
  for (ALL_LIST_ELEMENTS(es->es_frag_list, node, nnode, es_frag))
1736
0
    bgp_evpn_es_frag_free(es_frag);
1737
0
}
1738
1739
static struct bgp_evpn_es_frag *bgp_evpn_es_frag_new(struct bgp_evpn_es *es)
1740
0
{
1741
0
  struct bgp_evpn_es_frag *es_frag;
1742
0
  char buf[BGP_EVPN_PREFIX_RD_LEN];
1743
0
  struct bgp *bgp;
1744
1745
0
  es_frag = XCALLOC(MTYPE_BGP_EVPN_ES_FRAG, sizeof(*es_frag));
1746
0
  bf_assign_index(bm->rd_idspace, es_frag->rd_id);
1747
0
  es_frag->prd.family = AF_UNSPEC;
1748
0
  es_frag->prd.prefixlen = 64;
1749
0
  bgp = bgp_get_evpn();
1750
0
  snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id,
1751
0
       es_frag->rd_id);
1752
0
  (void)str2prefix_rd(buf, &es_frag->prd);
1753
1754
  /* EVIs that are advertised using the info in this fragment */
1755
0
  es_frag->es_evi_frag_list = list_new();
1756
0
  listset_app_node_mem(es_frag->es_evi_frag_list);
1757
1758
  /* Link the fragment to the parent ES */
1759
0
  es_frag->es = es;
1760
0
  listnode_init(&es_frag->es_listnode, es_frag);
1761
0
  listnode_add(es->es_frag_list, &es_frag->es_listnode);
1762
1763
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1764
0
    zlog_debug("es %s frag %u new", es->esi_str, es_frag->rd_id);
1765
0
  return es_frag;
1766
0
}
1767
1768
static struct bgp_evpn_es_frag *
1769
bgp_evpn_es_find_frag_with_space(struct bgp_evpn_es *es)
1770
0
{
1771
0
  struct listnode *node;
1772
0
  struct bgp_evpn_es_frag *es_frag;
1773
1774
0
  for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
1775
0
    if (listcount(es_frag->es_evi_frag_list) <
1776
0
        bgp_mh_info->evi_per_es_frag)
1777
0
      return es_frag;
1778
0
  }
1779
1780
  /* No frags where found with space; allocate a new one */
1781
0
  return bgp_evpn_es_frag_new(es);
1782
0
}
1783
1784
/* Link the ES-EVI to one of the ES fragments */
1785
static void bgp_evpn_es_frag_evi_add(struct bgp_evpn_es_evi *es_evi)
1786
0
{
1787
0
  struct bgp_evpn_es_frag *es_frag;
1788
0
  struct bgp_evpn_es *es = es_evi->es;
1789
1790
0
  if (es_evi->es_frag ||
1791
0
      !(CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL)))
1792
0
    return;
1793
1794
0
  es_frag = bgp_evpn_es_find_frag_with_space(es);
1795
1796
0
  es_evi->es_frag = es_frag;
1797
0
  listnode_init(&es_evi->es_frag_listnode, es_evi);
1798
0
  listnode_add(es_frag->es_evi_frag_list, &es_evi->es_frag_listnode);
1799
1800
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1801
0
    zlog_debug("es %s vni %d linked to frag %u", es->esi_str,
1802
0
         es_evi->vpn->vni, es_frag->rd_id);
1803
0
}
1804
1805
/* UnLink the ES-EVI from the ES fragment */
1806
static void bgp_evpn_es_frag_evi_del(struct bgp_evpn_es_evi *es_evi,
1807
             bool send_ead_del_if_empty)
1808
0
{
1809
0
  struct bgp_evpn_es_frag *es_frag = es_evi->es_frag;
1810
0
  struct prefix_evpn p;
1811
0
  struct bgp_evpn_es *es;
1812
0
  struct bgp *bgp;
1813
1814
0
  if (!es_frag)
1815
0
    return;
1816
1817
0
  es = es_frag->es;
1818
0
  es_evi->es_frag = NULL;
1819
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1820
0
    zlog_debug("es %s vni %d unlinked from frag %u", es->esi_str,
1821
0
         es_evi->vpn->vni, es_frag->rd_id);
1822
1823
0
  list_delete_node(es_frag->es_evi_frag_list, &es_evi->es_frag_listnode);
1824
1825
  /*
1826
   * if there are no other EVIs on the fragment deleted the EAD-ES for
1827
   * the fragment
1828
   */
1829
0
  if (send_ead_del_if_empty && !listcount(es_frag->es_evi_frag_list)) {
1830
0
    bgp = bgp_get_evpn();
1831
1832
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1833
0
      zlog_debug("es %s frag %u ead-es route delete",
1834
0
           es->esi_str, es_frag->rd_id);
1835
0
    build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG, &es->esi,
1836
0
          es->originator_ip);
1837
0
    p.prefix.ead_addr.frag_id = es_frag->rd_id;
1838
0
    bgp_evpn_mh_route_delete(bgp, es, NULL, es_frag, &p);
1839
0
  }
1840
1841
  /* We don't attempt to coalesce frags that may not be full. Instead we
1842
   * only free up the frag when it is completely empty.
1843
   */
1844
0
  bgp_evpn_es_frag_free_unused(es_frag);
1845
0
}
1846
1847
/* Link the ES-EVIs to one of the ES fragments */
1848
static void bgp_evpn_es_frag_evi_update_all(struct bgp_evpn_es *es, bool add)
1849
0
{
1850
0
  struct listnode *node;
1851
0
  struct bgp_evpn_es_evi *es_evi;
1852
1853
0
  for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, node, es_evi)) {
1854
0
    if (add)
1855
0
      bgp_evpn_es_frag_evi_add(es_evi);
1856
0
    else
1857
0
      bgp_evpn_es_frag_evi_del(es_evi, false);
1858
0
  }
1859
0
}
1860
1861
/* compare ES-IDs for the global ES RB tree */
1862
static int bgp_es_rb_cmp(const struct bgp_evpn_es *es1,
1863
    const struct bgp_evpn_es *es2)
1864
0
{
1865
0
  return memcmp(&es1->esi, &es2->esi, ESI_BYTES);
1866
0
}
1867
RB_GENERATE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp);
1868
1869
struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi)
1870
12
{
1871
12
  struct bgp_evpn_es tmp;
1872
1873
12
  memcpy(&tmp.esi, esi, sizeof(esi_t));
1874
12
  return RB_FIND(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, &tmp);
1875
12
}
1876
1877
static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)
1878
0
{
1879
0
  struct bgp_evpn_es *es;
1880
1881
0
  es = XCALLOC(MTYPE_BGP_EVPN_ES, sizeof(struct bgp_evpn_es));
1882
1883
  /* set the ESI */
1884
0
  memcpy(&es->esi, esi, sizeof(esi_t));
1885
1886
  /* Initialise the VTEP list */
1887
0
  es->es_vtep_list = list_new();
1888
0
  listset_app_node_mem(es->es_vtep_list);
1889
0
  es->es_vtep_list->cmp = bgp_evpn_es_vtep_cmp;
1890
1891
0
  esi_to_str(&es->esi, es->esi_str, sizeof(es->esi_str));
1892
1893
  /* Initialize the ES routing table */
1894
0
  es->route_table = bgp_table_init(bgp, AFI_L2VPN, SAFI_EVPN);
1895
1896
  /* Add to rb_tree */
1897
0
  RB_INSERT(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, es);
1898
1899
  /* Initialise the ES-EVI list */
1900
0
  es->es_evi_list = list_new();
1901
0
  listset_app_node_mem(es->es_evi_list);
1902
1903
  /* Initialise the ES-VRF list used for L3NHG management */
1904
0
  es->es_vrf_list = list_new();
1905
0
  listset_app_node_mem(es->es_vrf_list);
1906
1907
  /* Initialise the route list used for efficient event handling */
1908
0
  es->macip_evi_path_list = list_new();
1909
0
  listset_app_node_mem(es->macip_evi_path_list);
1910
0
  es->macip_global_path_list = list_new();
1911
0
  listset_app_node_mem(es->macip_global_path_list);
1912
0
  es->es_frag_list = list_new();
1913
0
  listset_app_node_mem(es->es_frag_list);
1914
1915
0
  QOBJ_REG(es, bgp_evpn_es);
1916
1917
0
  return es;
1918
0
}
1919
1920
/* Free a given ES -
1921
 * This just frees appropriate memory, caller should have taken other
1922
 * needed actions.
1923
 */
1924
static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
1925
0
{
1926
0
  if ((es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE))
1927
0
      || listcount(es->macip_evi_path_list)
1928
0
      || listcount(es->macip_global_path_list))
1929
0
    return;
1930
1931
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1932
0
    zlog_debug("%s: es %s free", caller, es->esi_str);
1933
1934
  /* cleanup resources maintained against the ES */
1935
0
  list_delete(&es->es_evi_list);
1936
0
  list_delete(&es->es_vrf_list);
1937
0
  list_delete(&es->es_vtep_list);
1938
0
  list_delete(&es->macip_evi_path_list);
1939
0
  list_delete(&es->macip_global_path_list);
1940
0
  list_delete(&es->es_frag_list);
1941
0
  bgp_table_unlock(es->route_table);
1942
1943
  /* remove the entry from various databases */
1944
0
  RB_REMOVE(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, es);
1945
0
  bgp_evpn_es_cons_checks_pend_del(es);
1946
1947
0
  QOBJ_UNREG(es);
1948
0
  XFREE(MTYPE_BGP_EVPN_ES, es);
1949
0
}
1950
1951
static inline bool bgp_evpn_is_es_local_and_non_bypass(struct bgp_evpn_es *es)
1952
0
{
1953
0
  return (es->flags & BGP_EVPNES_LOCAL)
1954
0
         && !(es->flags & BGP_EVPNES_BYPASS);
1955
0
}
1956
1957
/* init local info associated with the ES */
1958
static void bgp_evpn_es_local_info_set(struct bgp *bgp, struct bgp_evpn_es *es)
1959
0
{
1960
0
  bool old_is_local;
1961
0
  bool is_local;
1962
1963
0
  if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
1964
0
    return;
1965
1966
0
  old_is_local = bgp_evpn_is_es_local_and_non_bypass(es);
1967
0
  SET_FLAG(es->flags, BGP_EVPNES_LOCAL);
1968
1969
0
  listnode_init(&es->es_listnode, es);
1970
0
  listnode_add(bgp_mh_info->local_es_list, &es->es_listnode);
1971
1972
  /* setup the first ES fragment; more fragments may be allocated based
1973
   * on the the number of EVI entries
1974
   */
1975
0
  es->es_base_frag = bgp_evpn_es_frag_new(es);
1976
  /* distribute ES-EVIs to one or more ES fragments */
1977
0
  bgp_evpn_es_frag_evi_update_all(es, true);
1978
1979
0
  is_local = bgp_evpn_is_es_local_and_non_bypass(es);
1980
0
  if (old_is_local != is_local)
1981
0
    bgp_evpn_mac_update_on_es_local_chg(es, is_local);
1982
0
}
1983
1984
/* clear any local info associated with the ES */
1985
static void bgp_evpn_es_local_info_clear(struct bgp_evpn_es *es, bool finish)
1986
0
{
1987
0
  bool old_is_local;
1988
0
  bool is_local;
1989
1990
0
  if (!CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
1991
0
    return;
1992
1993
  /* clear the es frag references and free them up */
1994
0
  bgp_evpn_es_frag_evi_update_all(es, false);
1995
0
  es->es_base_frag = NULL;
1996
0
  bgp_evpn_es_frag_free_all(es);
1997
1998
0
  old_is_local = bgp_evpn_is_es_local_and_non_bypass(es);
1999
0
  UNSET_FLAG(es->flags, BGP_EVPNES_LOCAL);
2000
2001
0
  is_local = bgp_evpn_is_es_local_and_non_bypass(es);
2002
0
  if (!finish && (old_is_local != is_local))
2003
0
    bgp_evpn_mac_update_on_es_local_chg(es, is_local);
2004
2005
  /* remove from the ES local list */
2006
0
  list_delete_node(bgp_mh_info->local_es_list, &es->es_listnode);
2007
2008
0
  bgp_evpn_es_free(es, __func__);
2009
0
}
2010
2011
/* eval remote info associated with the ES */
2012
static void bgp_evpn_es_remote_info_re_eval(struct bgp_evpn_es *es)
2013
0
{
2014
0
  if (es->remote_es_evi_cnt) {
2015
0
    SET_FLAG(es->flags, BGP_EVPNES_REMOTE);
2016
0
  } else {
2017
0
    if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE)) {
2018
0
      UNSET_FLAG(es->flags, BGP_EVPNES_REMOTE);
2019
0
      bgp_evpn_es_free(es, __func__);
2020
0
    }
2021
0
  }
2022
0
}
2023
2024
/* If ES is present and local it needs to be active/oper-up for
2025
 * including L3 EC
2026
 */
2027
bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi)
2028
0
{
2029
0
  struct bgp_evpn_es *es;
2030
2031
0
  if (!esi || !bgp_mh_info->suppress_l3_ecomm_on_inactive_es)
2032
0
    return true;
2033
2034
0
  es = bgp_evpn_es_find(esi);
2035
2036
0
  return (!es || !(es->flags & BGP_EVPNES_LOCAL)
2037
0
    || bgp_evpn_local_es_is_active(es));
2038
0
}
2039
2040
static bool bgp_evpn_is_valid_local_path(struct bgp_path_info *pi)
2041
0
{
2042
0
  return (CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2043
0
    && pi->type == ZEBRA_ROUTE_BGP
2044
0
    && pi->sub_type == BGP_ROUTE_STATIC);
2045
0
}
2046
2047
/* Update all local MAC-IP routes in the VNI routing table associated
2048
 * with the ES. When the ES is down the routes are advertised without
2049
 * the L3 extcomm
2050
 */
2051
static void bgp_evpn_mac_update_on_es_oper_chg(struct bgp_evpn_es *es)
2052
0
{
2053
0
  struct listnode *node;
2054
0
  struct bgp_path_es_info *es_info;
2055
0
  struct bgp_path_info *pi;
2056
0
  struct bgp *bgp;
2057
0
  struct bgpevpn *vpn;
2058
2059
0
  if (!bgp_mh_info->suppress_l3_ecomm_on_inactive_es)
2060
0
    return;
2061
2062
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2063
0
    zlog_debug("update paths linked to es %s on oper chg",
2064
0
         es->esi_str);
2065
2066
0
  bgp = bgp_get_evpn();
2067
0
  for (ALL_LIST_ELEMENTS_RO(es->macip_evi_path_list, node, es_info)) {
2068
0
    pi = es_info->pi;
2069
2070
0
    if (!bgp_evpn_is_valid_local_path(pi))
2071
0
      continue;
2072
2073
0
    if (!bgp_evpn_is_macip_path(pi))
2074
0
      continue;
2075
2076
0
    vpn = bgp_evpn_lookup_vni(bgp, es_info->vni);
2077
0
    if (!vpn)
2078
0
      continue;
2079
2080
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
2081
0
      zlog_debug(
2082
0
        "update path %d %pFX linked to es %s on oper chg",
2083
0
        es_info->vni, &pi->net->p, es->esi_str);
2084
2085
0
    bgp_evpn_update_type2_route_entry(bgp, vpn, pi->net, pi,
2086
0
              __func__);
2087
0
  }
2088
0
}
2089
2090
static bool bgp_evpn_is_valid_bgp_path(struct bgp_path_info *pi)
2091
0
{
2092
0
  return (CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2093
0
    && pi->type == ZEBRA_ROUTE_BGP
2094
0
    && pi->sub_type == BGP_ROUTE_NORMAL);
2095
0
}
2096
2097
/* If an ES is no longer local (or becomes local) we need to re-install
2098
 * paths using that ES as destination. This is needed as the criteria
2099
 * for best path selection has changed.
2100
 */
2101
static void bgp_evpn_mac_update_on_es_local_chg(struct bgp_evpn_es *es,
2102
            bool is_local)
2103
0
{
2104
0
  struct listnode *node;
2105
0
  struct bgp_path_es_info *es_info;
2106
0
  struct bgp_path_info *pi;
2107
0
  bool tmp_local;
2108
0
  struct attr *attr_new;
2109
0
  struct attr attr_tmp;
2110
2111
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2112
0
    zlog_debug("update paths linked to es %s on chg to %s",
2113
0
         es->esi_str, is_local ? "local" : "non-local");
2114
2115
0
  for (ALL_LIST_ELEMENTS_RO(es->macip_global_path_list, node, es_info)) {
2116
0
    pi = es_info->pi;
2117
2118
    /* Consider "valid" remote routes */
2119
0
    if (!bgp_evpn_is_valid_bgp_path(pi))
2120
0
      continue;
2121
2122
0
    if (!pi->attr)
2123
0
      continue;
2124
2125
0
    tmp_local = !!(pi->attr->es_flags & ATTR_ES_IS_LOCAL);
2126
0
    if (tmp_local == is_local)
2127
0
      continue;
2128
2129
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
2130
0
      zlog_debug(
2131
0
        "update path %pFX linked to es %s on chg to %s",
2132
0
        &pi->net->p, es->esi_str,
2133
0
        is_local ? "local" : "non-local");
2134
2135
0
    attr_tmp = *pi->attr;
2136
0
    if (is_local)
2137
0
      attr_tmp.es_flags |= ATTR_ES_IS_LOCAL;
2138
0
    else
2139
0
      attr_tmp.es_flags &= ~ATTR_ES_IS_LOCAL;
2140
0
    attr_new = bgp_attr_intern(&attr_tmp);
2141
0
    bgp_attr_unintern(&pi->attr);
2142
0
    pi->attr = attr_new;
2143
0
    bgp_evpn_import_type2_route(pi, 1);
2144
0
  }
2145
0
}
2146
2147
static void bgp_evpn_local_es_deactivate(struct bgp *bgp,
2148
           struct bgp_evpn_es *es)
2149
0
{
2150
0
  struct prefix_evpn p;
2151
0
  int ret;
2152
2153
  /* withdraw ESR */
2154
  /* Delete and withdraw locally learnt ES route */
2155
0
  build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
2156
0
  ret = bgp_evpn_type4_route_delete(bgp, es, &p);
2157
0
  if (ret) {
2158
0
    flog_err(EC_BGP_EVPN_ROUTE_DELETE,
2159
0
        "%u failed to delete type-4 route for ESI %s",
2160
0
        bgp->vrf_id, es->esi_str);
2161
0
  }
2162
2163
  /* withdraw EAD-EVI */
2164
0
  if (!bgp_mh_info->ead_evi_adv_for_down_links)
2165
0
    bgp_evpn_local_type1_evi_route_del(bgp, es);
2166
2167
  /* withdraw EAD-ES */
2168
0
  bgp_evpn_ead_es_route_delete(bgp, es);
2169
2170
0
  bgp_evpn_mac_update_on_es_oper_chg(es);
2171
0
}
2172
2173
/* Process ES link oper-down by withdrawing ES-EAD and ESR */
2174
static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es)
2175
0
{
2176
0
  bool old_active;
2177
2178
0
  if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
2179
0
    return;
2180
2181
0
  old_active = bgp_evpn_local_es_is_active(es);
2182
0
  UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
2183
2184
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2185
0
    zlog_debug("local es %s down", es->esi_str);
2186
2187
0
  if (old_active)
2188
0
    bgp_evpn_local_es_deactivate(bgp, es);
2189
0
}
2190
2191
static void bgp_evpn_local_es_activate(struct bgp *bgp, struct bgp_evpn_es *es,
2192
               bool regen_ead, bool regen_esr)
2193
0
{
2194
0
  struct prefix_evpn p;
2195
2196
0
  if (regen_esr) {
2197
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2198
0
      zlog_debug("local es %s generate ESR", es->esi_str);
2199
    /* generate ESR */
2200
0
    build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
2201
0
    if (bgp_evpn_type4_route_update(bgp, es, &p))
2202
0
      flog_err(EC_BGP_EVPN_ROUTE_CREATE,
2203
0
         "%u: Type4 route creation failure for ESI %s",
2204
0
         bgp->vrf_id, es->esi_str);
2205
0
  }
2206
2207
0
  if (regen_ead) {
2208
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2209
0
      zlog_debug("local es %s generate EAD", es->esi_str);
2210
    /* generate EAD-EVI */
2211
0
    bgp_evpn_local_type1_evi_route_add(bgp, es);
2212
2213
    /* generate EAD-ES */
2214
0
    bgp_evpn_ead_es_route_update(bgp, es);
2215
0
  }
2216
2217
0
  bgp_evpn_mac_update_on_es_oper_chg(es);
2218
0
}
2219
2220
/* Process ES link oper-up by generating ES-EAD and ESR */
2221
static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
2222
         bool regen_esr)
2223
0
{
2224
0
  bool regen_ead = false;
2225
0
  bool active = false;
2226
2227
0
  if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
2228
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2229
0
      zlog_debug("local es %s up", es->esi_str);
2230
2231
0
    SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
2232
0
    regen_esr = true;
2233
0
    regen_ead = true;
2234
0
  }
2235
2236
0
  active = bgp_evpn_local_es_is_active(es);
2237
0
  if (active && (regen_ead || regen_esr))
2238
0
    bgp_evpn_local_es_activate(bgp, es, regen_ead, regen_esr);
2239
0
}
2240
2241
/* If an ethernet segment is in LACP bypass we cannot advertise
2242
 * reachability to it i.e. EAD-per-ES and ESR is not advertised in
2243
 * bypass state.
2244
 * PS: EAD-per-EVI will continue to be advertised
2245
 */
2246
static void bgp_evpn_local_es_bypass_update(struct bgp *bgp,
2247
              struct bgp_evpn_es *es, bool bypass)
2248
0
{
2249
0
  bool old_bypass = !!(es->flags & BGP_EVPNES_BYPASS);
2250
0
  bool old_active;
2251
0
  bool new_active;
2252
0
  bool old_is_local;
2253
0
  bool is_local;
2254
2255
0
  if (bypass == old_bypass)
2256
0
    return;
2257
2258
0
  old_active = bgp_evpn_local_es_is_active(es);
2259
0
  old_is_local = bgp_evpn_is_es_local_and_non_bypass(es);
2260
0
  if (bypass)
2261
0
    SET_FLAG(es->flags, BGP_EVPNES_BYPASS);
2262
0
  else
2263
0
    UNSET_FLAG(es->flags, BGP_EVPNES_BYPASS);
2264
2265
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2266
0
    zlog_debug("local es %s bypass %s", es->esi_str,
2267
0
         bypass ? "set" : "clear");
2268
2269
0
  new_active = bgp_evpn_local_es_is_active(es);
2270
0
  if (old_active != new_active) {
2271
0
    if (new_active)
2272
0
      bgp_evpn_local_es_activate(bgp, es, true, true);
2273
0
    else
2274
0
      bgp_evpn_local_es_deactivate(bgp, es);
2275
0
  }
2276
2277
0
  is_local = bgp_evpn_is_es_local_and_non_bypass(es);
2278
0
  if (old_is_local != is_local)
2279
0
    bgp_evpn_mac_update_on_es_local_chg(es, is_local);
2280
0
}
2281
2282
static void bgp_evpn_local_es_do_del(struct bgp *bgp, struct bgp_evpn_es *es)
2283
0
{
2284
0
  struct bgp_evpn_es_evi *es_evi;
2285
0
  struct listnode *evi_node, *evi_next_node;
2286
2287
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2288
0
    zlog_debug("del local es %s", es->esi_str);
2289
2290
  /* Delete all local EVPN ES routes from ESI table
2291
   * and schedule for processing (to withdraw from peers))
2292
   */
2293
0
  bgp_evpn_es_route_del_all(bgp, es);
2294
2295
  /* release all local ES EVIs associated with the ES */
2296
0
  for (ALL_LIST_ELEMENTS(es->es_evi_list, evi_node,
2297
0
        evi_next_node, es_evi)) {
2298
0
    bgp_evpn_local_es_evi_do_del(es_evi);
2299
0
  }
2300
2301
  /* Clear local info associated with the ES and free it up if there is
2302
   * no remote reference
2303
   */
2304
0
  bgp_evpn_es_local_info_clear(es, false);
2305
0
}
2306
2307
bool bgp_evpn_is_esi_local_and_non_bypass(esi_t *esi)
2308
12
{
2309
12
  struct bgp_evpn_es *es = NULL;
2310
2311
  /* Lookup ESI hash - should exist. */
2312
12
  es = bgp_evpn_es_find(esi);
2313
2314
12
  return es && bgp_evpn_is_es_local_and_non_bypass(es);
2315
12
}
2316
2317
int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi)
2318
0
{
2319
0
  struct bgp_evpn_es *es = NULL;
2320
2321
  /* Lookup ESI hash - should exist. */
2322
0
  es = bgp_evpn_es_find(esi);
2323
0
  if (!es) {
2324
0
    flog_warn(EC_BGP_EVPN_ESI, "%u: ES missing at local ES DEL",
2325
0
        bgp->vrf_id);
2326
0
    return -1;
2327
0
  }
2328
2329
0
  bgp_evpn_local_es_do_del(bgp, es);
2330
0
  return 0;
2331
0
}
2332
2333
/* Handle device to ES id association. Results in the creation of a local
2334
 * ES.
2335
 */
2336
int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
2337
        struct in_addr originator_ip, bool oper_up,
2338
        uint16_t df_pref, bool bypass)
2339
0
{
2340
0
  struct bgp_evpn_es *es;
2341
0
  bool new_es = true;
2342
0
  bool regen_esr = false;
2343
2344
  /* create the new es */
2345
0
  es = bgp_evpn_es_find(esi);
2346
0
  if (es) {
2347
0
    if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
2348
0
      new_es = false;
2349
0
  } else
2350
0
    es = bgp_evpn_es_new(bgp, esi);
2351
2352
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2353
0
    zlog_debug("add local es %s orig-ip %pI4 df_pref %u %s",
2354
0
         es->esi_str, &originator_ip, df_pref,
2355
0
         bypass ? "bypass" : "");
2356
2357
0
  es->originator_ip = originator_ip;
2358
0
  if (df_pref != es->df_pref) {
2359
0
    es->df_pref = df_pref;
2360
0
    regen_esr = true;
2361
0
  }
2362
0
  bgp_evpn_es_local_info_set(bgp, es);
2363
2364
  /* import all remote Type-4 routes in the ES table */
2365
0
  if (new_es)
2366
0
    bgp_evpn_type4_remote_routes_import(bgp, es,
2367
0
        true /* install */);
2368
2369
  /* create and advertise EAD-EVI routes for the ES -
2370
   * XXX - till an ES-EVI reference is created there is really nothing to
2371
   * advertise
2372
   */
2373
0
  if (bgp_mh_info->ead_evi_adv_for_down_links)
2374
0
    bgp_evpn_local_type1_evi_route_add(bgp, es);
2375
2376
0
  bgp_evpn_local_es_bypass_update(bgp, es, bypass);
2377
2378
  /* If the ES link is operationally up generate EAD-ES. EAD-EVI
2379
   * can be generated even if the link is inactive.
2380
   */
2381
0
  if (oper_up)
2382
0
    bgp_evpn_local_es_up(bgp, es, regen_esr);
2383
0
  else
2384
0
    bgp_evpn_local_es_down(bgp, es);
2385
2386
0
  return 0;
2387
0
}
2388
2389
static void bgp_evpn_es_json_frag_fill(json_object *json_frags,
2390
               struct bgp_evpn_es *es)
2391
0
{
2392
0
  json_object *json_frag;
2393
0
  struct listnode *node;
2394
0
  struct bgp_evpn_es_frag *es_frag;
2395
2396
0
  for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
2397
0
    json_frag = json_object_new_object();
2398
2399
0
    json_object_string_addf(json_frag, "rd", "%pRDP",
2400
0
          &es_frag->prd);
2401
0
    json_object_int_add(json_frag, "eviCount",
2402
0
            listcount(es_frag->es_evi_frag_list));
2403
2404
0
    json_object_array_add(json_frags, json_frag);
2405
0
  }
2406
0
}
2407
2408
static void bgp_evpn_es_frag_show_detail(struct vty *vty,
2409
           struct bgp_evpn_es *es)
2410
0
{
2411
0
  struct listnode *node;
2412
0
  struct bgp_evpn_es_frag *es_frag;
2413
2414
0
  for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
2415
0
    vty_out(vty, "  %pRDP EVIs: %d\n", &es_frag->prd,
2416
0
      listcount(es_frag->es_evi_frag_list));
2417
0
  }
2418
0
}
2419
2420
static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
2421
           uint8_t vtep_str_size)
2422
0
{
2423
0
  char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
2424
0
  struct listnode *node;
2425
0
  struct bgp_evpn_es_vtep *es_vtep;
2426
0
  bool first = true;
2427
0
  char ip_buf[INET_ADDRSTRLEN];
2428
2429
0
  vtep_str[0] = '\0';
2430
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
2431
0
    vtep_flag_str[0] = '\0';
2432
2433
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
2434
0
      strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
2435
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
2436
0
      strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
2437
2438
0
    if (!strlen(vtep_flag_str))
2439
0
      strlcat(vtep_flag_str, "-", sizeof(vtep_flag_str));
2440
0
    if (first)
2441
0
      first = false;
2442
0
    else
2443
0
      strlcat(vtep_str, ",", vtep_str_size);
2444
0
    strlcat(vtep_str,
2445
0
      inet_ntop(AF_INET, &es_vtep->vtep_ip, ip_buf,
2446
0
          sizeof(ip_buf)),
2447
0
      vtep_str_size);
2448
0
    strlcat(vtep_str, "(", vtep_str_size);
2449
0
    strlcat(vtep_str, vtep_flag_str, vtep_str_size);
2450
0
    strlcat(vtep_str, ")", vtep_str_size);
2451
0
  }
2452
2453
0
  return vtep_str;
2454
0
}
2455
2456
static void bgp_evpn_es_json_vtep_fill(json_object *json_vteps,
2457
    struct bgp_evpn_es_vtep *es_vtep)
2458
0
{
2459
0
  json_object *json_vtep_entry;
2460
0
  json_object *json_flags;
2461
0
  char alg_buf[EVPN_DF_ALG_STR_LEN];
2462
2463
0
  json_vtep_entry = json_object_new_object();
2464
2465
0
  json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
2466
0
        &es_vtep->vtep_ip);
2467
0
  if (es_vtep->flags & (BGP_EVPNES_VTEP_ESR |
2468
0
       BGP_EVPNES_VTEP_ACTIVE)) {
2469
0
    json_flags = json_object_new_array();
2470
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
2471
0
      json_array_string_add(json_flags, "esr");
2472
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
2473
0
      json_array_string_add(json_flags, "active");
2474
0
    json_object_object_add(json_vtep_entry, "flags", json_flags);
2475
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ESR) {
2476
0
      json_object_int_add(json_vtep_entry, "dfPreference",
2477
0
              es_vtep->df_pref);
2478
0
      json_object_string_add(
2479
0
        json_vtep_entry, "dfAlgorithm",
2480
0
        evpn_es_df_alg2str(es_vtep->df_alg, alg_buf,
2481
0
               sizeof(alg_buf)));
2482
0
    }
2483
0
  }
2484
2485
0
  json_object_array_add(json_vteps,
2486
0
      json_vtep_entry);
2487
0
}
2488
2489
static void bgp_evpn_es_vteps_show_detail(struct vty *vty,
2490
            struct bgp_evpn_es *es)
2491
0
{
2492
0
  char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
2493
0
  struct listnode *node;
2494
0
  struct bgp_evpn_es_vtep *es_vtep;
2495
0
  char alg_buf[EVPN_DF_ALG_STR_LEN];
2496
2497
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
2498
0
    vtep_flag_str[0] = '\0';
2499
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
2500
0
      strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
2501
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
2502
0
      strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
2503
2504
0
    if (!strlen(vtep_flag_str))
2505
0
      strlcat(vtep_flag_str, "-", sizeof(vtep_flag_str));
2506
2507
0
    vty_out(vty, "  %pI4 flags: %s", &es_vtep->vtep_ip,
2508
0
      vtep_flag_str);
2509
2510
0
    if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
2511
0
      vty_out(vty, " df_alg: %s df_pref: %u\n",
2512
0
        evpn_es_df_alg2str(es_vtep->df_alg, alg_buf,
2513
0
               sizeof(alg_buf)),
2514
0
        es_vtep->df_pref);
2515
0
    else
2516
0
      vty_out(vty, "\n");
2517
0
  }
2518
0
}
2519
2520
static void bgp_evpn_es_show_entry(struct vty *vty,
2521
    struct bgp_evpn_es *es, json_object *json)
2522
0
{
2523
0
  struct listnode *node;
2524
0
  struct bgp_evpn_es_vtep *es_vtep;
2525
2526
0
  if (json) {
2527
0
    json_object *json_vteps;
2528
0
    json_object *json_types;
2529
2530
0
    json_object_string_add(json, "esi", es->esi_str);
2531
0
    if (es->es_base_frag)
2532
0
      json_object_string_addf(json, "rd", "%pRDP",
2533
0
            &es->es_base_frag->prd);
2534
2535
0
    if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) {
2536
0
      json_types = json_object_new_array();
2537
0
      if (es->flags & BGP_EVPNES_LOCAL)
2538
0
        json_array_string_add(json_types, "local");
2539
0
      if (es->flags & BGP_EVPNES_REMOTE)
2540
0
        json_array_string_add(json_types, "remote");
2541
0
      json_object_object_add(json, "type", json_types);
2542
0
    }
2543
2544
0
    if (listcount(es->es_vtep_list)) {
2545
0
      json_vteps = json_object_new_array();
2546
0
      for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list,
2547
0
            node, es_vtep)) {
2548
0
        bgp_evpn_es_json_vtep_fill(json_vteps, es_vtep);
2549
0
      }
2550
0
      json_object_object_add(json, "vteps", json_vteps);
2551
0
    }
2552
0
    json_object_int_add(json, "vniCount",
2553
0
        listcount(es->es_evi_list));
2554
0
  } else {
2555
0
    char type_str[4];
2556
0
    char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
2557
2558
0
    type_str[0] = '\0';
2559
0
    if (es->flags & BGP_EVPNES_BYPASS)
2560
0
      strlcat(type_str, "B", sizeof(type_str));
2561
0
    if (es->flags & BGP_EVPNES_LOCAL)
2562
0
      strlcat(type_str, "L", sizeof(type_str));
2563
0
    if (es->flags & BGP_EVPNES_REMOTE)
2564
0
      strlcat(type_str, "R", sizeof(type_str));
2565
0
    if (es->inconsistencies)
2566
0
      strlcat(type_str, "I", sizeof(type_str));
2567
2568
0
    bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str));
2569
2570
0
    vty_out(vty, "%-30s %-5s %-21pRDP %-8d %s\n", es->esi_str,
2571
0
      type_str,
2572
0
      es->es_base_frag ? &es->es_base_frag->prd : NULL,
2573
0
      listcount(es->es_evi_list), vtep_str);
2574
0
  }
2575
0
}
2576
2577
static void bgp_evpn_es_show_entry_detail(struct vty *vty,
2578
    struct bgp_evpn_es *es, json_object *json)
2579
0
{
2580
0
  if (json) {
2581
0
    json_object *json_flags;
2582
0
    json_object *json_incons;
2583
0
    json_object *json_vteps;
2584
0
    json_object *json_frags;
2585
0
    struct listnode *node;
2586
0
    struct bgp_evpn_es_vtep *es_vtep;
2587
2588
    /* Add the "brief" info first */
2589
0
    bgp_evpn_es_show_entry(vty, es, json);
2590
0
    if (es->flags
2591
0
        & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI
2592
0
           | BGP_EVPNES_BYPASS)) {
2593
0
      json_flags = json_object_new_array();
2594
0
      if (es->flags & BGP_EVPNES_OPER_UP)
2595
0
        json_array_string_add(json_flags, "up");
2596
0
      if (es->flags & BGP_EVPNES_ADV_EVI)
2597
0
        json_array_string_add(json_flags,
2598
0
            "advertiseEVI");
2599
0
      if (es->flags & BGP_EVPNES_BYPASS)
2600
0
        json_array_string_add(json_flags, "bypass");
2601
0
      json_object_object_add(json, "flags", json_flags);
2602
0
    }
2603
0
    json_object_string_addf(json, "originator_ip", "%pI4",
2604
0
          &es->originator_ip);
2605
0
    json_object_int_add(json, "remoteVniCount",
2606
0
        es->remote_es_evi_cnt);
2607
0
    json_object_int_add(json, "vrfCount",
2608
0
            listcount(es->es_vrf_list));
2609
0
    json_object_int_add(json, "macipPathCount",
2610
0
            listcount(es->macip_evi_path_list));
2611
0
    json_object_int_add(json, "macipGlobalPathCount",
2612
0
            listcount(es->macip_global_path_list));
2613
0
    json_object_int_add(json, "inconsistentVniVtepCount",
2614
0
        es->incons_evi_vtep_cnt);
2615
0
    if (es->flags & BGP_EVPNES_LOCAL)
2616
0
      json_object_int_add(json, "localEsDfPreference",
2617
0
              es->df_pref);
2618
0
    if (listcount(es->es_vtep_list)) {
2619
0
      json_vteps = json_object_new_array();
2620
0
      for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node,
2621
0
              es_vtep)) {
2622
0
        bgp_evpn_es_json_vtep_fill(json_vteps, es_vtep);
2623
0
      }
2624
0
      json_object_object_add(json, "vteps", json_vteps);
2625
0
    }
2626
0
    if (listcount(es->es_frag_list)) {
2627
0
      json_frags = json_object_new_array();
2628
0
      bgp_evpn_es_json_frag_fill(json_frags, es);
2629
0
      json_object_object_add(json, "fragments", json_frags);
2630
0
    }
2631
0
    if (es->inconsistencies) {
2632
0
      json_incons = json_object_new_array();
2633
0
      if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
2634
0
        json_array_string_add(json_incons,
2635
0
            "vni-vtep-mismatch");
2636
0
      json_object_object_add(json, "inconsistencies",
2637
0
          json_incons);
2638
0
    }
2639
0
  } else {
2640
0
    char incons_str[BGP_EVPNES_INCONS_STR_SZ];
2641
0
    char type_str[4];
2642
2643
0
    type_str[0] = '\0';
2644
0
    if (es->flags & BGP_EVPNES_LOCAL)
2645
0
      strlcat(type_str, "L", sizeof(type_str));
2646
0
    if (es->flags & BGP_EVPNES_REMOTE)
2647
0
      strlcat(type_str, "R", sizeof(type_str));
2648
2649
0
    vty_out(vty, "ESI: %s\n", es->esi_str);
2650
0
    vty_out(vty, " Type: %s\n", type_str);
2651
0
    vty_out(vty, " RD: %pRDP\n",
2652
0
      es->es_base_frag ? &es->es_base_frag->prd : NULL);
2653
0
    vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);
2654
0
    if (es->flags & BGP_EVPNES_LOCAL)
2655
0
      vty_out(vty, " Local ES DF preference: %u\n",
2656
0
        es->df_pref);
2657
0
    if (es->flags & BGP_EVPNES_BYPASS)
2658
0
      vty_out(vty, " LACP bypass: on\n");
2659
0
    vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
2660
0
    vty_out(vty, " Remote VNI Count: %d\n",
2661
0
        es->remote_es_evi_cnt);
2662
0
    vty_out(vty, " VRF Count: %d\n", listcount(es->es_vrf_list));
2663
0
    vty_out(vty, " MACIP EVI Path Count: %d\n",
2664
0
      listcount(es->macip_evi_path_list));
2665
0
    vty_out(vty, " MACIP Global Path Count: %d\n",
2666
0
      listcount(es->macip_global_path_list));
2667
0
    vty_out(vty, " Inconsistent VNI VTEP Count: %d\n",
2668
0
        es->incons_evi_vtep_cnt);
2669
0
    if (es->inconsistencies) {
2670
0
      incons_str[0] = '\0';
2671
0
      if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
2672
0
        strlcat(incons_str, "vni-vtep-mismatch",
2673
0
          sizeof(incons_str));
2674
0
    } else {
2675
0
      strlcpy(incons_str, "-", sizeof(incons_str));
2676
0
    }
2677
0
    vty_out(vty, " Inconsistencies: %s\n",
2678
0
        incons_str);
2679
0
    if (listcount(es->es_frag_list)) {
2680
0
      vty_out(vty, " Fragments:\n");
2681
0
      bgp_evpn_es_frag_show_detail(vty, es);
2682
0
    }
2683
0
    if (listcount(es->es_vtep_list)) {
2684
0
      vty_out(vty, " VTEPs:\n");
2685
0
      bgp_evpn_es_vteps_show_detail(vty, es);
2686
0
    }
2687
0
    vty_out(vty, "\n");
2688
0
  }
2689
0
}
2690
2691
/* Display all ESs */
2692
void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail)
2693
0
{
2694
0
  struct bgp_evpn_es *es;
2695
0
  json_object *json_array = NULL;
2696
0
  json_object *json = NULL;
2697
2698
0
  if (uj) {
2699
    /* create an array of ESs */
2700
0
    json_array = json_object_new_array();
2701
0
  } else {
2702
0
    if (!detail) {
2703
0
      vty_out(vty,
2704
0
        "ES Flags: B - bypass, L local, R remote, I inconsistent\n");
2705
0
      vty_out(vty,
2706
0
        "VTEP Flags: E ESR/Type-4, A active nexthop\n");
2707
0
      vty_out(vty,
2708
0
        "%-30s %-5s %-21s %-8s %s\n",
2709
0
        "ESI", "Flags", "RD", "#VNIs", "VTEPs");
2710
0
    }
2711
0
  }
2712
2713
0
  RB_FOREACH(es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
2714
0
    if (uj)
2715
      /* create a separate json object for each ES */
2716
0
      json = json_object_new_object();
2717
0
    if (detail)
2718
0
      bgp_evpn_es_show_entry_detail(vty, es, json);
2719
0
    else
2720
0
      bgp_evpn_es_show_entry(vty, es, json);
2721
    /* add ES to the json array */
2722
0
    if (uj)
2723
0
      json_object_array_add(json_array, json);
2724
0
  }
2725
2726
  /* print the array of json-ESs */
2727
0
  if (uj)
2728
0
    vty_json(vty, json_array);
2729
0
}
2730
2731
/* Display specific ES */
2732
void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj)
2733
0
{
2734
0
  struct bgp_evpn_es *es;
2735
0
  json_object *json = NULL;
2736
2737
0
  if (uj)
2738
0
    json = json_object_new_object();
2739
2740
0
  es = bgp_evpn_es_find(esi);
2741
0
  if (es) {
2742
0
    bgp_evpn_es_show_entry_detail(vty, es, json);
2743
0
  } else {
2744
0
    if (!uj)
2745
0
      vty_out(vty, "ESI not found\n");
2746
0
  }
2747
2748
0
  if (uj)
2749
0
    vty_json(vty, json);
2750
0
}
2751
2752
/*****************************************************************************/
2753
/* Ethernet Segment to VRF association -
2754
 * 1. Each ES-EVI entry is associated with a tenant VRF. This associaton
2755
 * triggers the creation of an ES-VRF entry.
2756
 * 2. The ES-VRF entry is maintained for the purpose of L3-NHG creation
2757
 * 3. Type-2/MAC-IP routes are imported into a tenant VRF and programmed as
2758
 * a /32 or host route entry in the dataplane. If the destination of
2759
 * the host route is a remote-ES the route is programmed with the
2760
 * corresponding (keyed in by {vrf,ES-id}) L3-NHG.
2761
 * 4. The reason for this indirection (route->L3-NHG, L3-NHG->list-of-VTEPs)
2762
 * is to avoid route updates to the dplane when a remote-ES link flaps i.e.
2763
 * instead of updating all the dependent routes the NHG's contents are updated.
2764
 * This reduces the amount of datplane updates (nhg updates vs. route updates)
2765
 * allowing for a faster failover.
2766
 *
2767
 * XXX - can the L3 SVI index change without change in vpn->bgp_vrf
2768
 * association? If yes we need to handle that by updating all the L3 NHGs
2769
 * in that VRF.
2770
 */
2771
/******************************** L3 NHG management *************************/
2772
static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
2773
                bool v4_nhg)
2774
0
{
2775
0
  uint32_t nhg_id = v4_nhg ? es_vrf->nhg_id : es_vrf->v6_nhg_id;
2776
0
  struct bgp_evpn_es *es = es_vrf->es;
2777
0
  struct listnode *node;
2778
0
  struct bgp_evpn_es_vtep *es_vtep;
2779
0
  struct nexthop nh;
2780
0
  struct zapi_nexthop *api_nh;
2781
0
  struct zapi_nhg api_nhg = {};
2782
2783
  /* Skip installation of L3-NHG if host routes used */
2784
0
  if (!nhg_id)
2785
0
    return;
2786
2787
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2788
0
    zlog_debug("es %s vrf %u %s nhg %u to zebra", es->esi_str,
2789
0
         es_vrf->bgp_vrf->vrf_id,
2790
0
         v4_nhg ? "v4_nhg" : "v6_nhg", nhg_id);
2791
2792
0
  frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, true, v4_nhg, nhg_id, es_vrf);
2793
2794
  /* only the gateway ip changes for each NH. rest of the params
2795
   * are constant
2796
   */
2797
0
  memset(&nh, 0, sizeof(nh));
2798
0
  nh.vrf_id = es_vrf->bgp_vrf->vrf_id;
2799
0
  nh.flags = NEXTHOP_FLAG_ONLINK;
2800
0
  nh.ifindex = es_vrf->bgp_vrf->l3vni_svi_ifindex;
2801
0
  nh.weight = 1;
2802
0
  nh.type =
2803
0
    v4_nhg ? NEXTHOP_TYPE_IPV4_IFINDEX : NEXTHOP_TYPE_IPV6_IFINDEX;
2804
2805
0
  api_nhg.id = nhg_id;
2806
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
2807
0
    if (!CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
2808
0
      continue;
2809
2810
    /* Don't overrun the zapi buffer. */
2811
0
    if (api_nhg.nexthop_num == MULTIPATH_NUM)
2812
0
      break;
2813
2814
    /* overwrite the gw */
2815
0
    if (v4_nhg)
2816
0
      nh.gate.ipv4 = es_vtep->vtep_ip;
2817
0
    else
2818
0
      ipv4_to_ipv4_mapped_ipv6(&nh.gate.ipv6,
2819
0
             es_vtep->vtep_ip);
2820
2821
    /* convert to zapi format */
2822
0
    api_nh = &api_nhg.nexthops[api_nhg.nexthop_num];
2823
0
    zapi_nexthop_from_nexthop(api_nh, &nh);
2824
2825
0
    ++api_nhg.nexthop_num;
2826
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2827
0
      zlog_debug("nhg %u vtep %pI4 l3-svi %d", api_nhg.id,
2828
0
           &es_vtep->vtep_ip,
2829
0
           es_vrf->bgp_vrf->l3vni_svi_ifindex);
2830
2831
0
    frrtrace(3, frr_bgp, evpn_mh_nh_zsend, nhg_id, es_vtep, es_vrf);
2832
0
  }
2833
2834
0
  if (!api_nhg.nexthop_num)
2835
0
    return;
2836
2837
0
  zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
2838
0
}
2839
2840
static bool bgp_evpn_l3nhg_zebra_ok(struct bgp_evpn_es_vrf *es_vrf)
2841
0
{
2842
0
  if (!bgp_mh_info->host_routes_use_l3nhg)
2843
0
    return false;
2844
2845
  /* Check socket. */
2846
0
  if (!zclient || zclient->sock < 0)
2847
0
    return false;
2848
2849
0
  return true;
2850
0
}
2851
2852
static void bgp_evpn_l3nhg_zebra_add(struct bgp_evpn_es_vrf *es_vrf)
2853
0
{
2854
0
  if (!bgp_evpn_l3nhg_zebra_ok(es_vrf))
2855
0
    return;
2856
2857
0
  bgp_evpn_l3nhg_zebra_add_v4_or_v6(es_vrf, true /*v4_nhg*/);
2858
0
  bgp_evpn_l3nhg_zebra_add_v4_or_v6(es_vrf, false /*v4_nhg*/);
2859
0
}
2860
2861
static void bgp_evpn_l3nhg_zebra_del_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
2862
                bool v4_nhg)
2863
0
{
2864
0
  struct zapi_nhg api_nhg = {};
2865
2866
0
  api_nhg.id = v4_nhg ? es_vrf->nhg_id : es_vrf->v6_nhg_id;
2867
2868
  /* Skip installation of L3-NHG if host routes used */
2869
0
  if (!api_nhg.id)
2870
0
    return;
2871
2872
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2873
0
    zlog_debug("es %s vrf %u %s nhg %u to zebra",
2874
0
         es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2875
0
         v4_nhg ? "v4_nhg" : "v6_nhg", api_nhg.id);
2876
2877
2878
0
  frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, false, v4_nhg, api_nhg.id,
2879
0
     es_vrf);
2880
2881
0
  zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg);
2882
0
}
2883
2884
static void bgp_evpn_l3nhg_zebra_del(struct bgp_evpn_es_vrf *es_vrf)
2885
0
{
2886
0
  if (!bgp_evpn_l3nhg_zebra_ok(es_vrf))
2887
0
    return;
2888
2889
0
  bgp_evpn_l3nhg_zebra_del_v4_or_v6(es_vrf, true /*v4_nhg*/);
2890
0
  bgp_evpn_l3nhg_zebra_del_v4_or_v6(es_vrf, false /*v4_nhg*/);
2891
0
}
2892
2893
static void bgp_evpn_l3nhg_deactivate(struct bgp_evpn_es_vrf *es_vrf)
2894
0
{
2895
0
  if (!(es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE))
2896
0
    return;
2897
2898
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2899
0
    zlog_debug("es %s vrf %u nhg %u de-activate",
2900
0
         es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2901
0
         es_vrf->nhg_id);
2902
0
  bgp_evpn_l3nhg_zebra_del(es_vrf);
2903
0
  es_vrf->flags &= ~BGP_EVPNES_VRF_NHG_ACTIVE;
2904
  /* MAC-IPs can now be installed via the L3NHG */
2905
0
  bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg-deactivate");
2906
0
}
2907
2908
static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update)
2909
0
{
2910
0
  if (!bgp_evpn_es_get_active_vtep_cnt(es_vrf->es)) {
2911
0
    bgp_evpn_l3nhg_deactivate(es_vrf);
2912
0
    return;
2913
0
  }
2914
2915
0
  if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE) {
2916
0
    if (!update)
2917
0
      return;
2918
0
  } else {
2919
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2920
0
      zlog_debug("es %s vrf %u nhg %u activate",
2921
0
           es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2922
0
           es_vrf->nhg_id);
2923
0
    es_vrf->flags |= BGP_EVPNES_VRF_NHG_ACTIVE;
2924
    /* MAC-IPs can now be installed via the L3NHG */
2925
0
    bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "l3nhg_activate");
2926
0
  }
2927
2928
0
  bgp_evpn_l3nhg_zebra_add(es_vrf);
2929
0
}
2930
2931
/* when a VTEP is activated or de-activated against an ES associated
2932
 * VRFs' NHG needs to be updated
2933
 */
2934
static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es)
2935
0
{
2936
0
  struct bgp_evpn_es_vrf *es_vrf;
2937
0
  struct listnode *es_vrf_node;
2938
2939
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2940
0
    zlog_debug("es %s nhg update on vtep chg", es->esi_str);
2941
2942
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vrf_list, es_vrf_node, es_vrf))
2943
0
    bgp_evpn_l3nhg_activate(es_vrf, true /* update */);
2944
0
}
2945
2946
/* compare ES-IDs for the ES-VRF RB tree maintained per-VRF */
2947
static int bgp_es_vrf_rb_cmp(const struct bgp_evpn_es_vrf *es_vrf1,
2948
           const struct bgp_evpn_es_vrf *es_vrf2)
2949
0
{
2950
0
  return memcmp(&es_vrf1->es->esi, &es_vrf2->es->esi, ESI_BYTES);
2951
0
}
2952
RB_GENERATE(bgp_es_vrf_rb_head, bgp_evpn_es_vrf, rb_node, bgp_es_vrf_rb_cmp);
2953
2954
/* Initialize the ES tables maintained per-tenant vrf */
2955
void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf)
2956
1
{
2957
  /* Initialize the ES-VRF RB tree */
2958
1
  RB_INIT(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree);
2959
1
}
2960
2961
/* find the ES-VRF in the per-VRF RB tree */
2962
static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_find(struct bgp_evpn_es *es,
2963
                struct bgp *bgp_vrf)
2964
0
{
2965
0
  struct bgp_evpn_es_vrf es_vrf;
2966
2967
0
  es_vrf.es = es;
2968
2969
0
  return RB_FIND(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, &es_vrf);
2970
0
}
2971
2972
/* allocate a new ES-VRF and setup L3NHG for it */
2973
static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_create(struct bgp_evpn_es *es,
2974
                  struct bgp *bgp_vrf)
2975
0
{
2976
0
  struct bgp_evpn_es_vrf *es_vrf;
2977
2978
0
  es_vrf = XCALLOC(MTYPE_BGP_EVPN_ES_VRF, sizeof(*es_vrf));
2979
2980
0
  es_vrf->es = es;
2981
0
  es_vrf->bgp_vrf = bgp_vrf;
2982
2983
  /* insert into the VRF-ESI rb tree */
2984
0
  RB_INSERT(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, es_vrf);
2985
2986
  /* add to the ES's VRF list */
2987
0
  listnode_init(&es_vrf->es_listnode, es_vrf);
2988
0
  listnode_add(es->es_vrf_list, &es_vrf->es_listnode);
2989
2990
  /* setup the L3 NHG id for the ES */
2991
0
  es_vrf->nhg_id = bgp_l3nhg_id_alloc();
2992
0
  es_vrf->v6_nhg_id = bgp_l3nhg_id_alloc();
2993
2994
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2995
0
    zlog_debug("es %s vrf %u nhg %u v6_nhg %d create", es->esi_str,
2996
0
         bgp_vrf->vrf_id, es_vrf->nhg_id, es_vrf->v6_nhg_id);
2997
0
  bgp_evpn_l3nhg_activate(es_vrf, false /* update */);
2998
2999
  /* update paths in the VRF that may already be associated with
3000
   * this destination ES
3001
   */
3002
0
  bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "es-vrf-create");
3003
3004
0
  return es_vrf;
3005
0
}
3006
3007
/* remove the L3-NHG associated with the ES-VRF and free it */
3008
static void bgp_evpn_es_vrf_delete(struct bgp_evpn_es_vrf *es_vrf)
3009
0
{
3010
0
  struct bgp_evpn_es *es = es_vrf->es;
3011
0
  struct bgp *bgp_vrf = es_vrf->bgp_vrf;
3012
3013
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3014
0
    zlog_debug("es %s vrf %u nhg %u delete", es->esi_str,
3015
0
         bgp_vrf->vrf_id, es_vrf->nhg_id);
3016
3017
  /* Remove the NHG resources */
3018
0
  bgp_evpn_l3nhg_deactivate(es_vrf);
3019
0
  if (es_vrf->nhg_id)
3020
0
    bgp_l3nhg_id_free(es_vrf->nhg_id);
3021
0
  es_vrf->nhg_id = 0;
3022
0
  if (es_vrf->v6_nhg_id)
3023
0
    bgp_l3nhg_id_free(es_vrf->v6_nhg_id);
3024
0
  es_vrf->v6_nhg_id = 0;
3025
3026
  /* remove from the ES's VRF list */
3027
0
  list_delete_node(es->es_vrf_list, &es_vrf->es_listnode);
3028
3029
  /* remove from the VRF-ESI rb tree */
3030
0
  RB_REMOVE(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, es_vrf);
3031
3032
  /* update paths in the VRF that may already be associated with
3033
   * this destination ES
3034
   */
3035
0
  bgp_evpn_es_path_update_on_es_vrf_chg(es_vrf, "es-vrf-delete");
3036
3037
0
  XFREE(MTYPE_BGP_EVPN_ES_VRF, es_vrf);
3038
0
}
3039
3040
/* deref and delete if there are no references */
3041
void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi)
3042
0
{
3043
0
  struct bgp_evpn_es_vrf *es_vrf = es_evi->es_vrf;
3044
3045
0
  if (!es_vrf)
3046
0
    return;
3047
3048
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3049
0
    zlog_debug("es-evi %s vni %u vrf %u de-ref",
3050
0
         es_evi->es->esi_str, es_evi->vpn->vni,
3051
0
         es_vrf->bgp_vrf->vrf_id);
3052
3053
0
  es_evi->es_vrf = NULL;
3054
0
  if (es_vrf->ref_cnt)
3055
0
    --es_vrf->ref_cnt;
3056
3057
0
  if (!es_vrf->ref_cnt)
3058
0
    bgp_evpn_es_vrf_delete(es_vrf);
3059
0
}
3060
3061
/* find or create and reference */
3062
void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi, struct bgp *bgp_vrf)
3063
0
{
3064
0
  struct bgp_evpn_es *es = es_evi->es;
3065
0
  struct bgp_evpn_es_vrf *es_vrf = es_evi->es_vrf;
3066
0
  struct bgp *old_bgp_vrf = NULL;
3067
3068
0
  if (es_vrf)
3069
0
    old_bgp_vrf = es_vrf->bgp_vrf;
3070
3071
0
  if (old_bgp_vrf == bgp_vrf)
3072
0
    return;
3073
3074
  /* deref the old ES-VRF */
3075
0
  bgp_evpn_es_vrf_deref(es_evi);
3076
3077
0
  if (!bgp_vrf)
3078
0
    return;
3079
3080
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3081
0
    zlog_debug("es-evi %s vni %u vrf %u ref", es_evi->es->esi_str,
3082
0
         es_evi->vpn->vni, bgp_vrf->vrf_id);
3083
3084
  /* find-create the new ES-VRF */
3085
0
  es_vrf = bgp_evpn_es_vrf_find(es, bgp_vrf);
3086
0
  if (!es_vrf)
3087
0
    es_vrf = bgp_evpn_es_vrf_create(es, bgp_vrf);
3088
3089
0
  es_evi->es_vrf = es_vrf;
3090
0
  ++es_vrf->ref_cnt;
3091
0
}
3092
3093
/* When the L2-VNI is associated with a L3-VNI/VRF update all the
3094
 * associated ES-EVI entries
3095
 */
3096
void bgp_evpn_es_evi_vrf_deref(struct bgpevpn *vpn)
3097
0
{
3098
0
  struct bgp_evpn_es_evi *es_evi;
3099
3100
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3101
0
    zlog_debug("es-vrf de-ref for vni %u", vpn->vni);
3102
3103
0
  RB_FOREACH (es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree)
3104
0
    bgp_evpn_es_vrf_deref(es_evi);
3105
0
}
3106
void bgp_evpn_es_evi_vrf_ref(struct bgpevpn *vpn)
3107
0
{
3108
0
  struct bgp_evpn_es_evi *es_evi;
3109
3110
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3111
0
    zlog_debug("es-vrf ref for vni %u", vpn->vni);
3112
3113
0
  RB_FOREACH (es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree)
3114
0
    bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf);
3115
0
}
3116
3117
/* 1. If ES-VRF is not present install the host route with the exploded/flat
3118
 * multi-path list.
3119
 * 2. If ES-VRF is present -
3120
 * - if L3NHG has not been activated for the ES-VRF (this could be because
3121
 *   all the PEs attached to the VRF are down) do not install the route
3122
 *   in zebra.
3123
 * - if L3NHG has been activated install the route via that L3NHG
3124
 */
3125
void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, bool *use_l3nhg,
3126
           bool *is_l3nhg_active,
3127
           struct bgp_evpn_es_vrf **es_vrf_p)
3128
0
{
3129
0
  struct bgp_evpn_es *es;
3130
0
  struct bgp_evpn_es_vrf *es_vrf;
3131
3132
0
  if (!bgp_mh_info->host_routes_use_l3nhg)
3133
0
    return;
3134
3135
0
  es = bgp_evpn_es_find(esi);
3136
0
  if (!es)
3137
0
    return;
3138
3139
0
  es_vrf = bgp_evpn_es_vrf_find(es, bgp_vrf);
3140
0
  if (!es_vrf)
3141
0
    return;
3142
3143
0
  *use_l3nhg = true;
3144
0
  if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
3145
0
    *is_l3nhg_active = true;
3146
0
  if (es_vrf_p)
3147
0
    *es_vrf_p = es_vrf;
3148
0
}
3149
3150
/* returns false if legacy-exploded mp needs to be used for route install */
3151
bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi,
3152
            uint32_t *nhg_p)
3153
0
{
3154
0
  esi_t *esi;
3155
0
  struct bgp_evpn_es_vrf *es_vrf = NULL;
3156
0
  struct bgp_path_info *parent_pi;
3157
0
  struct bgp_node *rn;
3158
0
  struct prefix_evpn *evp;
3159
0
  struct bgp_path_info *mpinfo;
3160
0
  bool use_l3nhg = false;
3161
0
  bool is_l3nhg_active = false;
3162
3163
0
  *nhg_p = 0;
3164
3165
  /* we don't support NHG for routes leaked from another VRF yet */
3166
0
  if (pi->extra && pi->extra->bgp_orig)
3167
0
    return false;
3168
3169
0
  parent_pi = get_route_parent_evpn(pi);
3170
0
  if (!parent_pi)
3171
0
    return false;
3172
3173
0
  rn = parent_pi->net;
3174
0
  if (!rn)
3175
0
    return false;
3176
3177
0
  evp = (struct prefix_evpn *)&rn->p;
3178
0
  if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
3179
0
    return false;
3180
3181
  /* non-es path, use legacy-exploded multipath */
3182
0
  esi = bgp_evpn_attr_get_esi(parent_pi->attr);
3183
0
  if (!memcmp(esi, zero_esi, sizeof(*esi)))
3184
0
    return false;
3185
3186
  /* we don't support NHG for d-vni yet */
3187
0
  if (bgp_evpn_mpath_has_dvni(bgp_vrf, pi))
3188
0
    return false;
3189
3190
0
  bgp_evpn_es_vrf_use_nhg(bgp_vrf, esi, &use_l3nhg, &is_l3nhg_active,
3191
0
        &es_vrf);
3192
3193
  /* L3NHG support is disabled, use legacy-exploded multipath */
3194
0
  if (!use_l3nhg)
3195
0
    return false;
3196
3197
  /* if the NHG has not been installed we cannot install the route yet,
3198
   * return a 0-NHG to indicate that
3199
   */
3200
0
  if (!is_l3nhg_active)
3201
0
    return true;
3202
3203
  /* this needs to be set the v6NHG if v6route */
3204
0
  if (is_evpn_prefix_ipaddr_v6(evp))
3205
0
    *nhg_p = es_vrf->v6_nhg_id;
3206
0
  else
3207
0
    *nhg_p = es_vrf->nhg_id;
3208
3209
0
  for (mpinfo = bgp_path_info_mpath_next(pi); mpinfo;
3210
0
       mpinfo = bgp_path_info_mpath_next(mpinfo)) {
3211
    /* if any of the paths have a different ESI we can't use
3212
     * the NHG associated with the ES. fallback to legacy-exploded
3213
     * multipath
3214
     */
3215
0
    if (memcmp(esi, bgp_evpn_attr_get_esi(mpinfo->attr),
3216
0
         sizeof(*esi)))
3217
0
      return false;
3218
0
  }
3219
3220
0
  return true;
3221
0
}
3222
3223
static void bgp_evpn_es_vrf_show_entry(struct vty *vty,
3224
               struct bgp_evpn_es_vrf *es_vrf,
3225
               json_object *json)
3226
0
{
3227
0
  struct bgp_evpn_es *es = es_vrf->es;
3228
0
  struct bgp *bgp_vrf = es_vrf->bgp_vrf;
3229
3230
0
  if (json) {
3231
0
    json_object *json_types;
3232
3233
0
    json_object_string_add(json, "esi", es->esi_str);
3234
0
    json_object_string_add(json, "vrf", bgp_vrf->name_pretty);
3235
3236
0
    if (es_vrf->flags & (BGP_EVPNES_VRF_NHG_ACTIVE)) {
3237
0
      json_types = json_object_new_array();
3238
0
      if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
3239
0
        json_array_string_add(json_types, "active");
3240
0
      json_object_object_add(json, "flags", json_types);
3241
0
    }
3242
3243
0
    json_object_int_add(json, "ipv4NHG", es_vrf->nhg_id);
3244
0
    json_object_int_add(json, "ipv6NHG", es_vrf->v6_nhg_id);
3245
0
    json_object_int_add(json, "refCount", es_vrf->ref_cnt);
3246
0
  } else {
3247
0
    char flags_str[4];
3248
3249
0
    flags_str[0] = '\0';
3250
0
    if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE)
3251
0
      strlcat(flags_str, "A", sizeof(flags_str));
3252
3253
0
    vty_out(vty, "%-30s %-15s %-5s %-8u %-8u %u\n", es->esi_str,
3254
0
      bgp_vrf->name_pretty, flags_str, es_vrf->nhg_id,
3255
0
      es_vrf->v6_nhg_id, es_vrf->ref_cnt);
3256
0
  }
3257
0
}
3258
3259
static void bgp_evpn_es_vrf_show_es(struct vty *vty, json_object *json_array,
3260
            struct bgp_evpn_es *es)
3261
0
{
3262
0
  json_object *json = NULL;
3263
0
  struct listnode *es_vrf_node;
3264
0
  struct bgp_evpn_es_vrf *es_vrf;
3265
3266
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vrf_list, es_vrf_node, es_vrf)) {
3267
    /* create a separate json object for each ES-VRF */
3268
0
    if (json_array)
3269
0
      json = json_object_new_object();
3270
0
    bgp_evpn_es_vrf_show_entry(vty, es_vrf, json);
3271
    /* add ES-VRF to the json array */
3272
0
    if (json_array)
3273
0
      json_object_array_add(json_array, json);
3274
0
  }
3275
0
}
3276
3277
/* Display all ES VRFs */
3278
void bgp_evpn_es_vrf_show(struct vty *vty, bool uj, struct bgp_evpn_es *es)
3279
0
{
3280
0
  json_object *json_array = NULL;
3281
3282
0
  if (uj) {
3283
    /* create an array of ESs */
3284
0
    json_array = json_object_new_array();
3285
0
  } else {
3286
0
    vty_out(vty, "ES-VRF Flags: A Active\n");
3287
0
    vty_out(vty, "%-30s %-15s %-5s %-8s %-8s %s\n", "ESI", "VRF",
3288
0
      "Flags", "IPv4-NHG", "IPv6-NHG", "Ref");
3289
0
  }
3290
3291
0
  if (es) {
3292
0
    bgp_evpn_es_vrf_show_es(vty, json_array, es);
3293
0
  } else {
3294
0
    RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree)
3295
0
      bgp_evpn_es_vrf_show_es(vty, json_array, es);
3296
0
  }
3297
3298
  /* print the array of json-ESs */
3299
0
  if (uj)
3300
0
    vty_json(vty, json_array);
3301
0
}
3302
3303
/* Display specific ES VRF */
3304
void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj)
3305
0
{
3306
0
  struct bgp_evpn_es *es;
3307
3308
0
  es = bgp_evpn_es_find(esi);
3309
0
  if (es) {
3310
0
    bgp_evpn_es_vrf_show(vty, uj, es);
3311
0
  } else {
3312
0
    if (!uj)
3313
0
      vty_out(vty, "ESI not found\n");
3314
0
  }
3315
0
}
3316
3317
/*****************************************************************************/
3318
/* Ethernet Segment to EVI association -
3319
 * 1. The ES-EVI entry is maintained as a RB tree per L2-VNI
3320
 * (bgpevpn->es_evi_rb_tree).
3321
 * 2. Each local ES-EVI entry is rxed from zebra and then used by BGP to
3322
 * advertises an EAD-EVI (Type-1 EVPN) route
3323
 * 3. The remote ES-EVI is created when a bgp_evpn_es_evi_vtep references
3324
 * it.
3325
 */
3326
3327
/* A list of remote VTEPs is maintained for each ES-EVI. This list includes -
3328
 * 1. VTEPs for which we have imported the EAD-per-ES Type1 route
3329
 * 2. VTEPs for which we have imported the EAD-per-EVI Type1 route
3330
 * VTEPs for which both routes have been rxed are activated. Activation
3331
 * creates a NHG in the parent ES.
3332
 */
3333
static int bgp_evpn_es_evi_vtep_cmp(void *p1, void *p2)
3334
0
{
3335
0
  const struct bgp_evpn_es_evi_vtep *evi_vtep1 = p1;
3336
0
  const struct bgp_evpn_es_evi_vtep *evi_vtep2 = p2;
3337
3338
0
  return evi_vtep1->vtep_ip.s_addr - evi_vtep2->vtep_ip.s_addr;
3339
0
}
3340
3341
static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_new(
3342
    struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip)
3343
0
{
3344
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3345
3346
0
  evi_vtep = XCALLOC(MTYPE_BGP_EVPN_ES_EVI_VTEP, sizeof(*evi_vtep));
3347
3348
0
  evi_vtep->es_evi = es_evi;
3349
0
  evi_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
3350
0
  listnode_init(&evi_vtep->es_evi_listnode, evi_vtep);
3351
0
  listnode_add_sort(es_evi->es_evi_vtep_list, &evi_vtep->es_evi_listnode);
3352
3353
0
  return evi_vtep;
3354
0
}
3355
3356
static void bgp_evpn_es_evi_vtep_free(struct bgp_evpn_es_evi_vtep *evi_vtep)
3357
0
{
3358
0
  struct bgp_evpn_es_evi *es_evi = evi_vtep->es_evi;
3359
3360
0
  if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD))
3361
    /* as long as there is some reference we can't free it */
3362
0
    return;
3363
3364
0
  list_delete_node(es_evi->es_evi_vtep_list, &evi_vtep->es_evi_listnode);
3365
0
  XFREE(MTYPE_BGP_EVPN_ES_EVI_VTEP, evi_vtep);
3366
0
}
3367
3368
/* check if VTEP is already part of the list */
3369
static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find(
3370
    struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip)
3371
0
{
3372
0
  struct listnode *node = NULL;
3373
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3374
3375
0
  for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
3376
0
    if (evi_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
3377
0
      return evi_vtep;
3378
0
  }
3379
0
  return NULL;
3380
0
}
3381
3382
/* A VTEP can be added as "active" attach to an ES if EAD-per-ES and
3383
 * EAD-per-EVI routes are rxed from it.
3384
 */
3385
static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
3386
    struct bgp_evpn_es_evi_vtep *evi_vtep)
3387
0
{
3388
0
  bool old_active;
3389
0
  bool new_active;
3390
0
  uint32_t ead_activity_flags;
3391
3392
0
  old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
3393
3394
0
  if (bgp_mh_info->ead_evi_rx)
3395
    /* Both EAD-per-ES and EAD-per-EVI routes must be rxed from a PE
3396
     * before it can be activated.
3397
     */
3398
0
    ead_activity_flags = BGP_EVPN_EVI_VTEP_EAD;
3399
0
  else
3400
    /* EAD-per-ES is sufficent to activate the PE */
3401
0
    ead_activity_flags = BGP_EVPN_EVI_VTEP_EAD_PER_ES;
3402
3403
0
  if ((evi_vtep->flags & ead_activity_flags) == ead_activity_flags)
3404
0
    SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
3405
0
  else
3406
0
    UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
3407
3408
0
  new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
3409
3410
0
  if (old_active == new_active)
3411
0
    return;
3412
3413
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3414
0
    zlog_debug("es %s evi %u vtep %pI4 %s",
3415
0
         evi_vtep->es_evi->es->esi_str,
3416
0
         evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
3417
0
         new_active ? "active" : "inactive");
3418
3419
  /* add VTEP to parent es */
3420
0
  if (new_active)
3421
0
    evi_vtep->es_vtep = bgp_evpn_es_vtep_add(
3422
0
      bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip,
3423
0
      false /*esr*/, 0, 0);
3424
0
  else {
3425
0
    if (evi_vtep->es_vtep) {
3426
0
      bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
3427
0
          false /*esr*/);
3428
0
      evi_vtep->es_vtep = NULL;
3429
0
    }
3430
0
  }
3431
  /* queue up the parent es for background consistency checks */
3432
0
  bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es);
3433
0
}
3434
3435
static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
3436
    struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
3437
    bool ead_es)
3438
0
{
3439
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3440
3441
0
  evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
3442
3443
0
  if (!evi_vtep)
3444
0
    evi_vtep = bgp_evpn_es_evi_vtep_new(es_evi, vtep_ip);
3445
3446
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3447
0
    zlog_debug("add es %s evi %u vtep %pI4 %s",
3448
0
         evi_vtep->es_evi->es->esi_str,
3449
0
         evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
3450
0
         ead_es ? "ead_es" : "ead_evi");
3451
3452
0
  if (ead_es)
3453
0
    SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
3454
0
  else
3455
0
    SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
3456
3457
0
  bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
3458
0
}
3459
3460
static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
3461
    struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
3462
    bool ead_es)
3463
0
{
3464
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3465
3466
0
  evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
3467
0
  if (!evi_vtep)
3468
0
    return;
3469
3470
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3471
0
    zlog_debug("del es %s evi %u vtep %pI4 %s",
3472
0
         evi_vtep->es_evi->es->esi_str,
3473
0
         evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
3474
0
         ead_es ? "ead_es" : "ead_evi");
3475
3476
0
  if (ead_es)
3477
0
    UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
3478
0
  else
3479
0
    UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
3480
3481
0
  bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
3482
0
  bgp_evpn_es_evi_vtep_free(evi_vtep);
3483
0
}
3484
3485
/* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */
3486
static int bgp_es_evi_rb_cmp(const struct bgp_evpn_es_evi *es_evi1,
3487
    const struct bgp_evpn_es_evi *es_evi2)
3488
0
{
3489
0
  return memcmp(&es_evi1->es->esi, &es_evi2->es->esi, ESI_BYTES);
3490
0
}
3491
RB_GENERATE(bgp_es_evi_rb_head, bgp_evpn_es_evi, rb_node, bgp_es_evi_rb_cmp);
3492
3493
/* find the ES-EVI in the per-L2-VNI RB tree */
3494
static struct bgp_evpn_es_evi *bgp_evpn_es_evi_find(struct bgp_evpn_es *es,
3495
    struct bgpevpn *vpn)
3496
0
{
3497
0
  struct bgp_evpn_es_evi es_evi;
3498
3499
0
  es_evi.es = es;
3500
3501
0
  return RB_FIND(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, &es_evi);
3502
0
}
3503
3504
/* allocate a new ES-EVI and insert it into the per-L2-VNI and per-ES
3505
 * tables.
3506
 */
3507
static struct bgp_evpn_es_evi *bgp_evpn_es_evi_new(struct bgp_evpn_es *es,
3508
    struct bgpevpn *vpn)
3509
0
{
3510
0
  struct bgp_evpn_es_evi *es_evi;
3511
3512
0
  es_evi = XCALLOC(MTYPE_BGP_EVPN_ES_EVI, sizeof(*es_evi));
3513
3514
0
  es_evi->es = es;
3515
0
  es_evi->vpn = vpn;
3516
3517
  /* Initialise the VTEP list */
3518
0
  es_evi->es_evi_vtep_list = list_new();
3519
0
  listset_app_node_mem(es_evi->es_evi_vtep_list);
3520
0
  es_evi->es_evi_vtep_list->cmp = bgp_evpn_es_evi_vtep_cmp;
3521
3522
  /* insert into the VNI-ESI rb tree */
3523
0
  RB_INSERT(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, es_evi);
3524
3525
  /* add to the ES's VNI list */
3526
0
  listnode_init(&es_evi->es_listnode, es_evi);
3527
0
  listnode_add(es->es_evi_list, &es_evi->es_listnode);
3528
3529
0
  bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf);
3530
3531
0
  return es_evi;
3532
0
}
3533
3534
/* remove the ES-EVI from the per-L2-VNI and per-ES tables and free
3535
 * up the memory.
3536
 */
3537
static struct bgp_evpn_es_evi *
3538
bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi)
3539
0
{
3540
0
  struct bgp_evpn_es *es = es_evi->es;
3541
0
  struct bgpevpn *vpn = es_evi->vpn;
3542
3543
  /* cannot free the element as long as there is a local or remote
3544
   * reference
3545
   */
3546
0
  if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL | BGP_EVPNES_EVI_REMOTE))
3547
0
    return es_evi;
3548
0
  bgp_evpn_es_frag_evi_del(es_evi, false);
3549
0
  bgp_evpn_es_vrf_deref(es_evi);
3550
3551
  /* remove from the ES's VNI list */
3552
0
  list_delete_node(es->es_evi_list, &es_evi->es_listnode);
3553
3554
  /* remove from the VNI-ESI rb tree */
3555
0
  RB_REMOVE(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, es_evi);
3556
3557
  /* free the VTEP list */
3558
0
  list_delete(&es_evi->es_evi_vtep_list);
3559
3560
  /* remove from the VNI-ESI rb tree */
3561
0
  XFREE(MTYPE_BGP_EVPN_ES_EVI, es_evi);
3562
3563
0
  return NULL;
3564
0
}
3565
3566
/* init local info associated with the ES-EVI */
3567
static void bgp_evpn_es_evi_local_info_set(struct bgp_evpn_es_evi *es_evi)
3568
0
{
3569
0
  struct bgpevpn *vpn = es_evi->vpn;
3570
3571
0
  if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
3572
0
    return;
3573
3574
0
  SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL);
3575
0
  listnode_init(&es_evi->l2vni_listnode, es_evi);
3576
0
  listnode_add(vpn->local_es_evi_list, &es_evi->l2vni_listnode);
3577
0
  bgp_evpn_es_frag_evi_add(es_evi);
3578
0
}
3579
3580
/* clear any local info associated with the ES-EVI */
3581
static struct bgp_evpn_es_evi *
3582
bgp_evpn_es_evi_local_info_clear(struct bgp_evpn_es_evi *es_evi)
3583
0
{
3584
0
  struct bgpevpn *vpn = es_evi->vpn;
3585
3586
0
  UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL);
3587
0
  list_delete_node(vpn->local_es_evi_list, &es_evi->l2vni_listnode);
3588
3589
0
  return bgp_evpn_es_evi_free(es_evi);
3590
0
}
3591
3592
/* eval remote info associated with the ES */
3593
static void bgp_evpn_es_evi_remote_info_re_eval(struct bgp_evpn_es_evi *es_evi)
3594
0
{
3595
0
  struct bgp_evpn_es *es = es_evi->es;
3596
3597
  /* if there are remote VTEPs the ES-EVI is classified as "remote" */
3598
0
  if (listcount(es_evi->es_evi_vtep_list)) {
3599
0
    if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE)) {
3600
0
      SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE);
3601
0
      ++es->remote_es_evi_cnt;
3602
      /* set remote on the parent es */
3603
0
      bgp_evpn_es_remote_info_re_eval(es);
3604
0
    }
3605
0
  } else {
3606
0
    if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE)) {
3607
0
      UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE);
3608
0
      if (es->remote_es_evi_cnt)
3609
0
        --es->remote_es_evi_cnt;
3610
0
      bgp_evpn_es_evi_free(es_evi);
3611
      /* check if "remote" can be cleared from the
3612
       * parent es.
3613
       */
3614
0
      bgp_evpn_es_remote_info_re_eval(es);
3615
0
    }
3616
0
  }
3617
0
}
3618
3619
static struct bgp_evpn_es_evi *
3620
bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi)
3621
0
{
3622
0
  struct prefix_evpn p;
3623
0
  struct bgp_evpn_es *es = es_evi->es;
3624
0
  struct bgp *bgp;
3625
3626
0
  if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
3627
0
    return es_evi;
3628
3629
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3630
0
    zlog_debug("del local es %s evi %u",
3631
0
        es_evi->es->esi_str,
3632
0
        es_evi->vpn->vni);
3633
3634
0
  bgp = bgp_get_evpn();
3635
3636
  /* remove the es_evi from the es_frag before sending the update */
3637
0
  bgp_evpn_es_frag_evi_del(es_evi, true);
3638
0
  if (bgp) {
3639
    /* update EAD-ES with new list of VNIs */
3640
0
    if (bgp_evpn_local_es_is_active(es))
3641
0
      bgp_evpn_ead_es_route_update(bgp, es);
3642
3643
    /* withdraw and delete EAD-EVI */
3644
0
    if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
3645
0
      build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
3646
0
          &es->esi, es->originator_ip);
3647
0
      if (bgp_evpn_ead_evi_route_delete(bgp, es, es_evi->vpn,
3648
0
                &p))
3649
0
        flog_err(EC_BGP_EVPN_ROUTE_DELETE,
3650
0
          "%u: EAD-EVI route deletion failure for ESI %s VNI %u",
3651
0
          bgp->vrf_id, es->esi_str,
3652
0
          es_evi->vpn->vni);
3653
0
    }
3654
0
  }
3655
3656
0
  return bgp_evpn_es_evi_local_info_clear(es_evi);
3657
0
}
3658
3659
int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni)
3660
0
{
3661
0
  struct bgpevpn *vpn;
3662
0
  struct bgp_evpn_es *es;
3663
0
  struct bgp_evpn_es_evi *es_evi;
3664
0
  char buf[ESI_STR_LEN];
3665
3666
0
  es = bgp_evpn_es_find(esi);
3667
0
  if (!es) {
3668
0
    flog_err(
3669
0
        EC_BGP_ES_CREATE,
3670
0
        "%u: Failed to deref VNI %d from ESI %s; ES not present",
3671
0
        bgp->vrf_id, vni,
3672
0
        esi_to_str(esi, buf, sizeof(buf)));
3673
0
    return -1;
3674
0
  }
3675
3676
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
3677
0
  if (!vpn) {
3678
0
    flog_err(
3679
0
        EC_BGP_ES_CREATE,
3680
0
        "%u: Failed to deref VNI %d from ESI %s; VNI not present",
3681
0
        bgp->vrf_id, vni, es->esi_str);
3682
0
    return -1;
3683
0
  }
3684
3685
0
  es_evi = bgp_evpn_es_evi_find(es, vpn);
3686
0
  if (!es_evi) {
3687
0
    flog_err(
3688
0
        EC_BGP_ES_CREATE,
3689
0
        "%u: Failed to deref VNI %d from ESI %s; ES-VNI not present",
3690
0
        bgp->vrf_id, vni, es->esi_str);
3691
0
    return -1;
3692
0
  }
3693
3694
0
  bgp_evpn_local_es_evi_do_del(es_evi);
3695
0
  return 0;
3696
0
}
3697
3698
/* Create ES-EVI and advertise the corresponding EAD routes */
3699
int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
3700
0
{
3701
0
  struct bgpevpn *vpn;
3702
0
  struct prefix_evpn p;
3703
0
  struct bgp_evpn_es *es;
3704
0
  struct bgp_evpn_es_evi *es_evi;
3705
0
  char buf[ESI_STR_LEN];
3706
3707
0
  es = bgp_evpn_es_find(esi);
3708
0
  if (!es) {
3709
0
    flog_err(
3710
0
        EC_BGP_ES_CREATE,
3711
0
        "%u: Failed to associate VNI %d with ESI %s; ES not present",
3712
0
        bgp->vrf_id, vni,
3713
0
        esi_to_str(esi, buf, sizeof(buf)));
3714
0
    return -1;
3715
0
  }
3716
3717
0
  vpn = bgp_evpn_lookup_vni(bgp, vni);
3718
0
  if (!vpn) {
3719
0
    flog_err(
3720
0
        EC_BGP_ES_CREATE,
3721
0
        "%u: Failed to associate VNI %d with ESI %s; VNI not present",
3722
0
        bgp->vrf_id, vni, es->esi_str);
3723
0
    return -1;
3724
0
  }
3725
3726
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3727
0
    zlog_debug("add local es %s evi %u",
3728
0
        es->esi_str, vni);
3729
3730
0
  es_evi = bgp_evpn_es_evi_find(es, vpn);
3731
3732
0
  if (es_evi) {
3733
0
    if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
3734
      /* dup */
3735
0
      return 0;
3736
0
  } else
3737
0
    es_evi = bgp_evpn_es_evi_new(es, vpn);
3738
3739
0
  bgp_evpn_es_evi_local_info_set(es_evi);
3740
3741
  /* generate an EAD-EVI for this new VNI */
3742
0
  if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
3743
0
    build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG, &es->esi,
3744
0
          es->originator_ip);
3745
0
    bgp_evpn_ead_evi_route_update(bgp, es, vpn, &p);
3746
0
  }
3747
3748
  /* update EAD-ES */
3749
0
  if (bgp_evpn_local_es_is_active(es))
3750
0
    bgp_evpn_ead_es_route_update(bgp, es);
3751
3752
0
  return 0;
3753
0
}
3754
3755
/* Add remote ES-EVI entry. This is actually the remote VTEP add and the
3756
 * ES-EVI is implicity created on first VTEP's reference.
3757
 */
3758
int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
3759
    const struct prefix_evpn *p)
3760
0
{
3761
0
  char buf[ESI_STR_LEN];
3762
0
  struct bgp_evpn_es *es;
3763
0
  struct bgp_evpn_es_evi *es_evi;
3764
0
  bool ead_es;
3765
0
  const esi_t *esi = &p->prefix.ead_addr.esi;
3766
3767
0
  if (!vpn)
3768
    /* local EAD-ES need not be sent back to zebra */
3769
0
    return 0;
3770
3771
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3772
0
    zlog_debug("add remote %s es %s evi %u vtep %pI4",
3773
0
         p->prefix.ead_addr.eth_tag ? "ead-es" : "ead-evi",
3774
0
         esi_to_str(esi, buf, sizeof(buf)), vpn->vni,
3775
0
         &p->prefix.ead_addr.ip.ipaddr_v4);
3776
3777
0
  es = bgp_evpn_es_find(esi);
3778
0
  if (!es)
3779
0
    es = bgp_evpn_es_new(bgp, esi);
3780
3781
0
  es_evi = bgp_evpn_es_evi_find(es, vpn);
3782
0
  if (!es_evi)
3783
0
    es_evi = bgp_evpn_es_evi_new(es, vpn);
3784
3785
0
  ead_es = !!p->prefix.ead_addr.eth_tag;
3786
0
  bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
3787
0
      ead_es);
3788
3789
0
  bgp_evpn_es_evi_remote_info_re_eval(es_evi);
3790
0
  return 0;
3791
0
}
3792
3793
/* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the
3794
 * parent es-evi freed up implicitly in last VTEP's deref.
3795
 */
3796
int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
3797
    const struct prefix_evpn *p)
3798
0
{
3799
0
  char buf[ESI_STR_LEN];
3800
0
  struct bgp_evpn_es *es;
3801
0
  struct bgp_evpn_es_evi *es_evi;
3802
0
  bool ead_es;
3803
3804
0
  if (!vpn)
3805
    /* local EAD-ES need not be sent back to zebra */
3806
0
    return 0;
3807
3808
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3809
0
    zlog_debug(
3810
0
      "del remote %s es %s evi %u vtep %pI4",
3811
0
      p->prefix.ead_addr.eth_tag ? "ead-es" : "ead-evi",
3812
0
      esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)),
3813
0
      vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
3814
3815
0
  es = bgp_evpn_es_find(&p->prefix.ead_addr.esi);
3816
0
  if (!es) {
3817
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3818
0
      zlog_debug(
3819
0
        "del remote %s es %s evi %u vtep %pI4, NO es",
3820
0
        p->prefix.ead_addr.eth_tag ? "ead-es"
3821
0
                 : "ead-evi",
3822
0
        esi_to_str(&p->prefix.ead_addr.esi, buf,
3823
0
             sizeof(buf)),
3824
0
        vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
3825
0
    return 0;
3826
0
  }
3827
0
  es_evi = bgp_evpn_es_evi_find(es, vpn);
3828
0
  if (!es_evi) {
3829
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3830
0
      zlog_debug(
3831
0
        "del remote %s es %s evi %u vtep %pI4, NO es-evi",
3832
0
        p->prefix.ead_addr.eth_tag ? "ead-es"
3833
0
                 : "ead-evi",
3834
0
        esi_to_str(&p->prefix.ead_addr.esi, buf,
3835
0
             sizeof(buf)),
3836
0
        vpn->vni,
3837
0
        &p->prefix.ead_addr.ip.ipaddr_v4);
3838
0
    return 0;
3839
0
  }
3840
3841
0
  ead_es = !!p->prefix.ead_addr.eth_tag;
3842
0
  bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
3843
0
      ead_es);
3844
0
  bgp_evpn_es_evi_remote_info_re_eval(es_evi);
3845
0
  return 0;
3846
0
}
3847
3848
/* If a VNI is being deleted we need to force del all remote VTEPs */
3849
static void bgp_evpn_remote_es_evi_flush(struct bgp_evpn_es_evi *es_evi)
3850
0
{
3851
0
  struct listnode *node = NULL;
3852
0
  struct listnode *nnode = NULL;
3853
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3854
0
  struct bgp *bgp;
3855
3856
0
  bgp = bgp_get_evpn();
3857
0
  if (!bgp)
3858
0
    return;
3859
3860
  /* delete all VTEPs */
3861
0
  for (ALL_LIST_ELEMENTS(es_evi->es_evi_vtep_list, node, nnode,
3862
0
             evi_vtep)) {
3863
0
    evi_vtep->flags &= ~(BGP_EVPN_EVI_VTEP_EAD_PER_ES
3864
0
             | BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
3865
0
    bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
3866
0
    bgp_evpn_es_evi_vtep_free(evi_vtep);
3867
0
  }
3868
  /* delete the EVI */
3869
0
  bgp_evpn_es_evi_remote_info_re_eval(es_evi);
3870
0
}
3871
3872
/* Initialize the ES tables maintained per-L2_VNI */
3873
void bgp_evpn_vni_es_init(struct bgpevpn *vpn)
3874
0
{
3875
  /* Initialize the ES-EVI RB tree */
3876
0
  RB_INIT(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree);
3877
3878
  /* Initialize the local list maintained for quick walks by type */
3879
0
  vpn->local_es_evi_list = list_new();
3880
0
  listset_app_node_mem(vpn->local_es_evi_list);
3881
0
}
3882
3883
/* Cleanup the ES info maintained per-L2_VNI */
3884
void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn)
3885
0
{
3886
0
  struct bgp_evpn_es_evi *es_evi;
3887
0
  struct bgp_evpn_es_evi *es_evi_next;
3888
3889
0
  RB_FOREACH_SAFE(es_evi, bgp_es_evi_rb_head,
3890
0
      &vpn->es_evi_rb_tree, es_evi_next) {
3891
0
    es_evi = bgp_evpn_local_es_evi_do_del(es_evi);
3892
0
    if (es_evi)
3893
0
      bgp_evpn_remote_es_evi_flush(es_evi);
3894
0
  }
3895
3896
0
  list_delete(&vpn->local_es_evi_list);
3897
0
}
3898
3899
static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
3900
               struct bgp_evpn_es_evi *es_evi,
3901
               uint8_t vtep_str_size)
3902
0
{
3903
0
  char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
3904
0
  struct listnode *node;
3905
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3906
0
  bool first = true;
3907
0
  char ip_buf[INET_ADDRSTRLEN];
3908
3909
0
  vtep_str[0] = '\0';
3910
0
  for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
3911
0
    vtep_flag_str[0] = '\0';
3912
0
    if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
3913
0
      strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
3914
0
    if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
3915
0
      strlcat(vtep_flag_str, "V", sizeof(vtep_flag_str));
3916
3917
0
    if (!strnlen(vtep_flag_str, sizeof(vtep_flag_str)))
3918
0
      strlcpy(vtep_flag_str, "-", sizeof(vtep_flag_str));
3919
0
    if (first)
3920
0
      first = false;
3921
0
    else
3922
0
      strlcat(vtep_str, ",", vtep_str_size);
3923
0
    strlcat(vtep_str,
3924
0
      inet_ntop(AF_INET, &evi_vtep->vtep_ip, ip_buf,
3925
0
          sizeof(ip_buf)),
3926
0
      vtep_str_size);
3927
0
    strlcat(vtep_str, "(", vtep_str_size);
3928
0
    strlcat(vtep_str, vtep_flag_str, vtep_str_size);
3929
0
    strlcat(vtep_str, ")", vtep_str_size);
3930
0
  }
3931
3932
0
  return vtep_str;
3933
0
}
3934
3935
static void bgp_evpn_es_evi_json_vtep_fill(json_object *json_vteps,
3936
    struct bgp_evpn_es_evi_vtep *evi_vtep)
3937
0
{
3938
0
  json_object *json_vtep_entry;
3939
0
  json_object *json_flags;
3940
3941
0
  json_vtep_entry = json_object_new_object();
3942
3943
0
  json_object_string_addf(json_vtep_entry, "vtep_ip", "%pI4",
3944
0
        &evi_vtep->vtep_ip);
3945
0
  if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
3946
0
       BGP_EVPN_EVI_VTEP_EAD_PER_EVI)) {
3947
0
    json_flags = json_object_new_array();
3948
0
    if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
3949
0
      json_array_string_add(json_flags, "ead-per-es");
3950
0
    if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
3951
0
      json_array_string_add(json_flags, "ead-per-evi");
3952
0
    json_object_object_add(json_vtep_entry,
3953
0
        "flags", json_flags);
3954
0
  }
3955
3956
0
  json_object_array_add(json_vteps,
3957
0
      json_vtep_entry);
3958
0
}
3959
3960
static void bgp_evpn_es_evi_show_entry(struct vty *vty,
3961
    struct bgp_evpn_es_evi *es_evi, json_object *json)
3962
0
{
3963
0
  struct listnode *node;
3964
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
3965
3966
0
  if (json) {
3967
0
    json_object *json_vteps;
3968
0
    json_object *json_types;
3969
3970
0
    json_object_string_add(json, "esi", es_evi->es->esi_str);
3971
0
    if (es_evi->vpn)
3972
0
      json_object_int_add(json, "vni", es_evi->vpn->vni);
3973
3974
0
    if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL |
3975
0
          BGP_EVPNES_EVI_REMOTE)) {
3976
0
      json_types = json_object_new_array();
3977
0
      if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
3978
0
        json_array_string_add(json_types, "local");
3979
0
      if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
3980
0
        json_array_string_add(json_types, "remote");
3981
0
      json_object_object_add(json, "type", json_types);
3982
0
    }
3983
3984
0
    if (listcount(es_evi->es_evi_vtep_list)) {
3985
0
      json_vteps = json_object_new_array();
3986
0
      for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list,
3987
0
            node, evi_vtep)) {
3988
0
        bgp_evpn_es_evi_json_vtep_fill(json_vteps,
3989
0
            evi_vtep);
3990
0
      }
3991
0
      json_object_object_add(json, "vteps", json_vteps);
3992
0
    }
3993
0
  } else {
3994
0
    char type_str[4];
3995
0
    char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
3996
3997
0
    type_str[0] = '\0';
3998
0
    if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
3999
0
      strlcat(type_str, "L", sizeof(type_str));
4000
0
    if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
4001
0
      strlcat(type_str, "R", sizeof(type_str));
4002
0
    if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST)
4003
0
      strlcat(type_str, "I", sizeof(type_str));
4004
4005
0
    bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
4006
4007
0
    vty_out(vty, "%-8d %-30s %-5s %s\n",
4008
0
        es_evi->vpn->vni, es_evi->es->esi_str,
4009
0
        type_str, vtep_str);
4010
0
  }
4011
0
}
4012
4013
static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
4014
    struct bgp_evpn_es_evi *es_evi, json_object *json)
4015
0
{
4016
0
  enum asnotation_mode mode;
4017
4018
0
  mode = bgp_get_asnotation(es_evi->vpn->bgp_vrf);
4019
4020
0
  if (json) {
4021
0
    json_object *json_flags;
4022
4023
    /* Add the "brief" info first */
4024
0
    bgp_evpn_es_evi_show_entry(vty, es_evi, json);
4025
0
    if (es_evi->es_frag)
4026
0
      json_object_string_addf(json, "esFragmentRd",
4027
0
            BGP_RD_AS_FORMAT(mode),
4028
0
            &es_evi->es_frag->prd);
4029
0
    if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {
4030
0
      json_flags = json_object_new_array();
4031
0
      json_array_string_add(json_flags, "es-vtep-mismatch");
4032
0
      json_object_object_add(json, "flags", json_flags);
4033
0
    }
4034
0
  } else {
4035
0
    char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
4036
0
    char type_str[4];
4037
4038
0
    type_str[0] = '\0';
4039
0
    if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
4040
0
      strlcat(type_str, "L", sizeof(type_str));
4041
0
    if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
4042
0
      strlcat(type_str, "R", sizeof(type_str));
4043
4044
0
    bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
4045
0
    if (!strlen(vtep_str))
4046
0
      strlcpy(vtep_str, "-", sizeof(type_str));
4047
4048
0
    vty_out(vty, "VNI: %d ESI: %s\n",
4049
0
        es_evi->vpn->vni, es_evi->es->esi_str);
4050
0
    vty_out(vty, " Type: %s\n", type_str);
4051
0
    if (es_evi->es_frag) {
4052
0
      vty_out(vty, " ES fragment RD: ");
4053
0
      vty_out(vty, BGP_RD_AS_FORMAT(mode),
4054
0
        &es_evi->es_frag->prd);
4055
0
      vty_out(vty, "\n");
4056
0
    }
4057
0
    vty_out(vty, " Inconsistencies: %s\n",
4058
0
      (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?
4059
0
      "es-vtep-mismatch":"-");
4060
0
    vty_out(vty, " VTEPs: %s\n", vtep_str);
4061
0
    vty_out(vty, "\n");
4062
0
  }
4063
0
}
4064
4065
static void bgp_evpn_es_evi_show_one_vni(struct bgpevpn *vpn, struct vty *vty,
4066
    json_object *json_array, bool detail)
4067
0
{
4068
0
  struct bgp_evpn_es_evi *es_evi;
4069
0
  json_object *json = NULL;
4070
4071
0
  RB_FOREACH(es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree) {
4072
0
    if (json_array)
4073
      /* create a separate json object for each ES */
4074
0
      json = json_object_new_object();
4075
0
    if (detail)
4076
0
      bgp_evpn_es_evi_show_entry_detail(vty, es_evi, json);
4077
0
    else
4078
0
      bgp_evpn_es_evi_show_entry(vty, es_evi, json);
4079
    /* add ES to the json array */
4080
0
    if (json_array)
4081
0
      json_object_array_add(json_array, json);
4082
0
  }
4083
0
}
4084
4085
struct es_evi_show_ctx {
4086
  struct vty *vty;
4087
  json_object *json;
4088
  int detail;
4089
};
4090
4091
static void bgp_evpn_es_evi_show_one_vni_hash_cb(struct hash_bucket *bucket,
4092
    void *ctxt)
4093
0
{
4094
0
  struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
4095
0
  struct es_evi_show_ctx *wctx = (struct es_evi_show_ctx *)ctxt;
4096
4097
0
  bgp_evpn_es_evi_show_one_vni(vpn, wctx->vty, wctx->json, wctx->detail);
4098
0
}
4099
4100
/* Display all ES EVIs */
4101
void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail)
4102
0
{
4103
0
  json_object *json_array = NULL;
4104
0
  struct es_evi_show_ctx wctx;
4105
0
  struct bgp *bgp;
4106
4107
0
  if (uj) {
4108
    /* create an array of ES-EVIs */
4109
0
    json_array = json_object_new_array();
4110
0
  }
4111
4112
0
  wctx.vty = vty;
4113
0
  wctx.json = json_array;
4114
0
  wctx.detail = detail;
4115
4116
0
  bgp = bgp_get_evpn();
4117
4118
0
  if (!json_array && !detail) {
4119
0
    vty_out(vty, "Flags: L local, R remote, I inconsistent\n");
4120
0
    vty_out(vty, "VTEP-Flags: E EAD-per-ES, V EAD-per-EVI\n");
4121
0
    vty_out(vty, "%-8s %-30s %-5s %s\n",
4122
0
        "VNI", "ESI", "Flags", "VTEPs");
4123
0
  }
4124
4125
0
  if (bgp)
4126
0
    hash_iterate(bgp->vnihash,
4127
0
        (void (*)(struct hash_bucket *,
4128
0
          void *))bgp_evpn_es_evi_show_one_vni_hash_cb,
4129
0
        &wctx);
4130
0
  if (uj)
4131
0
    vty_json(vty, json_array);
4132
0
}
4133
4134
/* Display specific ES EVI */
4135
void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
4136
    bool uj, bool detail)
4137
0
{
4138
0
  struct bgpevpn *vpn = NULL;
4139
0
  json_object *json_array = NULL;
4140
0
  struct bgp *bgp;
4141
4142
0
  if (uj) {
4143
    /* create an array of ES-EVIs */
4144
0
    json_array = json_object_new_array();
4145
0
  }
4146
4147
0
  bgp = bgp_get_evpn();
4148
0
  if (bgp)
4149
0
    vpn = bgp_evpn_lookup_vni(bgp, vni);
4150
4151
0
  if (vpn) {
4152
0
    if (!json_array && !detail) {
4153
0
      vty_out(vty, "Flags: L local, R remote, I inconsistent\n");
4154
0
      vty_out(vty, "VTEP-Flags: E EAD-per-ES, V EAD-per-EVI\n");
4155
0
      vty_out(vty, "%-8s %-30s %-5s %s\n",
4156
0
          "VNI", "ESI", "Flags", "VTEPs");
4157
0
    }
4158
4159
0
    bgp_evpn_es_evi_show_one_vni(vpn, vty, json_array, detail);
4160
0
  } else {
4161
0
    if (!uj)
4162
0
      vty_out(vty, "VNI not found\n");
4163
0
  }
4164
4165
0
  if (uj)
4166
0
    vty_json(vty, json_array);
4167
0
}
4168
4169
/*****************************************************************************
4170
 * Ethernet Segment Consistency checks
4171
 *     Consistency checking is done to detect misconfig or mis-cabling. When
4172
 * an inconsistency is detected it is simply logged (and displayed via
4173
 * show commands) at this point. A more drastic action can be executed (based
4174
 * on user config) in the future.
4175
 */
4176
static void bgp_evpn_es_cons_checks_timer_start(void)
4177
0
{
4178
0
  if (!bgp_mh_info->consistency_checking || bgp_mh_info->t_cons_check)
4179
0
    return;
4180
4181
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4182
0
    zlog_debug("periodic consistency checking started");
4183
4184
0
  event_add_timer(bm->master, bgp_evpn_run_consistency_checks, NULL,
4185
0
      BGP_EVPN_CONS_CHECK_INTERVAL,
4186
0
      &bgp_mh_info->t_cons_check);
4187
0
}
4188
4189
/* queue up the es for background consistency checks */
4190
static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es)
4191
0
{
4192
0
  if (!bgp_mh_info->consistency_checking)
4193
    /* consistency checking is not enabled */
4194
0
    return;
4195
4196
0
  if (CHECK_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND))
4197
    /* already queued for consistency checking */
4198
0
    return;
4199
4200
  /* start the periodic timer for consistency checks if it is not
4201
   * already running */
4202
0
  bgp_evpn_es_cons_checks_timer_start();
4203
4204
0
  SET_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND);
4205
0
  listnode_init(&es->pend_es_listnode, es);
4206
0
  listnode_add_after(bgp_mh_info->pend_es_list,
4207
0
      listtail_unchecked(bgp_mh_info->pend_es_list),
4208
0
      &es->pend_es_listnode);
4209
0
}
4210
4211
/* pull the ES from the consistency check list */
4212
static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es)
4213
0
{
4214
0
  if (!CHECK_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND))
4215
0
    return;
4216
4217
0
  UNSET_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND);
4218
0
  list_delete_node(bgp_mh_info->pend_es_list,
4219
0
      &es->pend_es_listnode);
4220
0
}
4221
4222
/* Number of active VTEPs associated with the ES-per-EVI */
4223
static uint32_t bgp_evpn_es_evi_get_active_vtep_cnt(
4224
    struct bgp_evpn_es_evi *es_evi)
4225
0
{
4226
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
4227
0
  struct listnode *node;
4228
0
  uint32_t vtep_cnt = 0;
4229
0
4230
0
  for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
4231
0
    if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE))
4232
0
      ++vtep_cnt;
4233
0
  }
4234
0
4235
0
  return vtep_cnt;
4236
0
}
4237
4238
/* Number of active VTEPs associated with the ES */
4239
static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es)
4240
0
{
4241
0
  struct listnode *node;
4242
0
  uint32_t vtep_cnt = 0;
4243
0
  struct bgp_evpn_es_vtep *es_vtep;
4244
4245
0
  for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
4246
0
    if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
4247
0
      ++vtep_cnt;
4248
0
  }
4249
4250
0
  return vtep_cnt;
4251
0
}
4252
4253
static struct bgp_evpn_es_vtep *bgp_evpn_es_get_next_active_vtep(
4254
    struct bgp_evpn_es *es, struct bgp_evpn_es_vtep *es_vtep)
4255
0
{
4256
0
  struct listnode *node;
4257
0
  struct bgp_evpn_es_vtep *next_es_vtep;
4258
0
4259
0
  if (es_vtep)
4260
0
    node = listnextnode_unchecked(&es_vtep->es_listnode);
4261
0
  else
4262
0
    node = listhead(es->es_vtep_list);
4263
0
4264
0
  for (; node; node = listnextnode_unchecked(node)) {
4265
0
    next_es_vtep = listgetdata(node);
4266
0
    if (CHECK_FLAG(next_es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
4267
0
      return next_es_vtep;
4268
0
  }
4269
0
4270
0
  return NULL;
4271
0
}
4272
4273
static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_get_next_active_vtep(
4274
  struct bgp_evpn_es_evi *es_evi,
4275
  struct bgp_evpn_es_evi_vtep *evi_vtep)
4276
0
{
4277
0
  struct listnode *node;
4278
0
  struct bgp_evpn_es_evi_vtep *next_evi_vtep;
4279
0
4280
0
  if (evi_vtep)
4281
0
    node = listnextnode_unchecked(&evi_vtep->es_evi_listnode);
4282
0
  else
4283
0
    node = listhead(es_evi->es_evi_vtep_list);
4284
0
4285
0
  for (; node; node = listnextnode_unchecked(node)) {
4286
0
    next_evi_vtep = listgetdata(node);
4287
0
    if (CHECK_FLAG(next_evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE))
4288
0
      return next_evi_vtep;
4289
0
  }
4290
0
4291
0
  return NULL;
4292
0
}
4293
4294
static void bgp_evpn_es_evi_set_inconsistent(struct bgp_evpn_es_evi *es_evi)
4295
0
{
4296
0
  if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST)) {
4297
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4298
0
      zlog_debug("inconsistency detected - es %s evi %u vtep list mismatch",
4299
0
          es_evi->es->esi_str,
4300
0
          es_evi->vpn->vni);
4301
0
    SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST);
4302
0
4303
0
    /* update parent ES with the incosistency setting */
4304
0
    if (!es_evi->es->incons_evi_vtep_cnt &&
4305
0
        BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4306
0
      zlog_debug("inconsistency detected - es %s vtep list mismatch",
4307
0
          es_evi->es->esi_str);
4308
0
    ++es_evi->es->incons_evi_vtep_cnt;
4309
0
    SET_FLAG(es_evi->es->inconsistencies,
4310
0
        BGP_EVPNES_INCONS_VTEP_LIST);
4311
0
  }
4312
0
}
4313
4314
static uint32_t bgp_evpn_es_run_consistency_checks(struct bgp_evpn_es *es)
4315
0
{
4316
0
  int proc_cnt = 0;
4317
0
  int es_active_vtep_cnt;
4318
0
  int evi_active_vtep_cnt;
4319
0
  struct bgp_evpn_es_evi *es_evi;
4320
0
  struct listnode *evi_node;
4321
0
  struct bgp_evpn_es_vtep *es_vtep;
4322
0
  struct bgp_evpn_es_evi_vtep *evi_vtep;
4323
0
4324
0
  /* reset the inconsistencies and re-evaluate */
4325
0
  es->incons_evi_vtep_cnt = 0;
4326
0
  es->inconsistencies = 0;
4327
0
4328
0
  es_active_vtep_cnt = bgp_evpn_es_get_active_vtep_cnt(es);
4329
0
  for (ALL_LIST_ELEMENTS_RO(es->es_evi_list,
4330
0
        evi_node, es_evi)) {
4331
0
    ++proc_cnt;
4332
0
4333
0
    /* reset the inconsistencies on the EVI and re-evaluate*/
4334
0
    UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST);
4335
0
4336
0
    evi_active_vtep_cnt =
4337
0
      bgp_evpn_es_evi_get_active_vtep_cnt(es_evi);
4338
0
    if (es_active_vtep_cnt != evi_active_vtep_cnt) {
4339
0
      bgp_evpn_es_evi_set_inconsistent(es_evi);
4340
0
      continue;
4341
0
    }
4342
0
4343
0
    if (!es_active_vtep_cnt)
4344
0
      continue;
4345
0
4346
0
    es_vtep = NULL;
4347
0
    evi_vtep = NULL;
4348
0
    while ((es_vtep = bgp_evpn_es_get_next_active_vtep(
4349
0
            es, es_vtep))) {
4350
0
      evi_vtep = bgp_evpn_es_evi_get_next_active_vtep(es_evi,
4351
0
          evi_vtep);
4352
0
      if (!evi_vtep) {
4353
0
        bgp_evpn_es_evi_set_inconsistent(es_evi);
4354
0
        break;
4355
0
      }
4356
0
      if (es_vtep->vtep_ip.s_addr !=
4357
0
          evi_vtep->vtep_ip.s_addr) {
4358
0
        /* inconsistency detected; set it and move
4359
0
         * to the next evi
4360
0
         */
4361
0
        bgp_evpn_es_evi_set_inconsistent(es_evi);
4362
0
        break;
4363
0
      }
4364
0
    }
4365
0
  }
4366
0
4367
0
  return proc_cnt;
4368
0
}
4369
4370
static void bgp_evpn_run_consistency_checks(struct event *t)
4371
0
{
4372
0
  int proc_cnt = 0;
4373
0
  struct listnode *node;
4374
0
  struct listnode *nextnode;
4375
0
  struct bgp_evpn_es *es;
4376
0
4377
0
  for (ALL_LIST_ELEMENTS(bgp_mh_info->pend_es_list,
4378
0
        node, nextnode, es)) {
4379
0
    ++proc_cnt;
4380
0
    /* run consistency checks on the ES and remove it from the
4381
0
     * pending list
4382
0
     */
4383
0
    proc_cnt += bgp_evpn_es_run_consistency_checks(es);
4384
0
    bgp_evpn_es_cons_checks_pend_del(es);
4385
0
    if (proc_cnt > 500)
4386
0
      break;
4387
0
  }
4388
0
4389
0
  /* restart the timer */
4390
0
  event_add_timer(bm->master, bgp_evpn_run_consistency_checks, NULL,
4391
0
      BGP_EVPN_CONS_CHECK_INTERVAL,
4392
0
      &bgp_mh_info->t_cons_check);
4393
0
}
4394
4395
/*****************************************************************************
4396
 * EVPN-Nexthop and RMAC management: nexthops associated with Type-2 routes
4397
 * that have an ES as destination are consolidated by BGP into a per-VRF
4398
 * nh->rmac mapping which is sent to zebra. Zebra installs the nexthop
4399
 * as a remote neigh/fdb entry with a dummy (type-1) prefix referencing it.
4400
 *
4401
 * This handling is needed because Type-2 routes with ES as dest use NHG
4402
 * that is setup using EAD routes (i.e. such NHGs do not include the
4403
 * RMAC info).
4404
 ****************************************************************************/
4405
static void bgp_evpn_nh_zebra_update_send(struct bgp_evpn_nh *nh, bool add)
4406
0
{
4407
0
  struct stream *s;
4408
0
  struct bgp *bgp_vrf = nh->bgp_vrf;
4409
4410
  /* Check socket. */
4411
0
  if (!zclient || zclient->sock < 0)
4412
0
    return;
4413
4414
  /* Don't try to register if Zebra doesn't know of this instance. */
4415
0
  if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp_vrf)) {
4416
0
    if (BGP_DEBUG(zebra, ZEBRA))
4417
0
      zlog_debug("No zebra instance, not %s remote nh %s",
4418
0
           add ? "adding" : "deleting", nh->nh_str);
4419
0
    return;
4420
0
  }
4421
4422
0
  s = zclient->obuf;
4423
0
  stream_reset(s);
4424
4425
0
  zclient_create_header(
4426
0
    s, add ? ZEBRA_EVPN_REMOTE_NH_ADD : ZEBRA_EVPN_REMOTE_NH_DEL,
4427
0
    bgp_vrf->vrf_id);
4428
0
  stream_putl(s, bgp_vrf->vrf_id);
4429
0
  stream_put(s, &nh->ip, sizeof(nh->ip));
4430
0
  if (add)
4431
0
    stream_put(s, &nh->rmac, sizeof(nh->rmac));
4432
4433
0
  stream_putw_at(s, 0, stream_get_endp(s));
4434
4435
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) {
4436
0
    if (add)
4437
0
      zlog_debug("evpn vrf %s nh %s rmac %pEA add to zebra",
4438
0
           nh->bgp_vrf->name_pretty, nh->nh_str,
4439
0
           &nh->rmac);
4440
0
    else if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4441
0
      zlog_debug("evpn vrf %s nh %s del to zebra",
4442
0
           nh->bgp_vrf->name_pretty, nh->nh_str);
4443
0
  }
4444
4445
0
  frrtrace(2, frr_bgp, evpn_mh_nh_rmac_zsend, add, nh);
4446
4447
0
  zclient_send_message(zclient);
4448
0
}
4449
4450
static void bgp_evpn_nh_zebra_update(struct bgp_evpn_nh *nh, bool add)
4451
0
{
4452
0
  if (add && !is_zero_mac(&nh->rmac)) {
4453
0
    nh->flags |= BGP_EVPN_NH_READY_FOR_ZEBRA;
4454
0
    bgp_evpn_nh_zebra_update_send(nh, true);
4455
0
  } else {
4456
0
    if (!(nh->flags & BGP_EVPN_NH_READY_FOR_ZEBRA))
4457
0
      return;
4458
0
    nh->flags &= ~BGP_EVPN_NH_READY_FOR_ZEBRA;
4459
0
    bgp_evpn_nh_zebra_update_send(nh, false);
4460
0
  }
4461
0
}
4462
4463
static void *bgp_evpn_nh_alloc(void *p)
4464
0
{
4465
0
  struct bgp_evpn_nh *tmp_n = p;
4466
0
  struct bgp_evpn_nh *n;
4467
4468
0
  n = XCALLOC(MTYPE_BGP_EVPN_NH, sizeof(struct bgp_evpn_nh));
4469
0
  *n = *tmp_n;
4470
4471
0
  return ((void *)n);
4472
0
}
4473
4474
static struct bgp_evpn_nh *bgp_evpn_nh_find(struct bgp *bgp_vrf,
4475
              struct ipaddr *ip)
4476
0
{
4477
0
  struct bgp_evpn_nh tmp;
4478
0
  struct bgp_evpn_nh *n;
4479
4480
0
  memset(&tmp, 0, sizeof(tmp));
4481
0
  memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
4482
0
  n = hash_lookup(bgp_vrf->evpn_nh_table, &tmp);
4483
4484
0
  return n;
4485
0
}
4486
4487
/* Add nexthop entry - implicitly created on first path reference */
4488
static struct bgp_evpn_nh *bgp_evpn_nh_add(struct bgp *bgp_vrf,
4489
             struct ipaddr *ip,
4490
             struct bgp_path_info *pi)
4491
0
{
4492
0
  struct bgp_evpn_nh tmp_n;
4493
0
  struct bgp_evpn_nh *n = NULL;
4494
4495
0
  memset(&tmp_n, 0, sizeof(tmp_n));
4496
0
  memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
4497
0
  n = hash_get(bgp_vrf->evpn_nh_table, &tmp_n, bgp_evpn_nh_alloc);
4498
0
  ipaddr2str(ip, n->nh_str, sizeof(n->nh_str));
4499
0
  n->bgp_vrf = bgp_vrf;
4500
4501
0
  n->pi_list = list_new();
4502
0
  listset_app_node_mem(n->pi_list);
4503
4504
  /* Setup ref_pi when the nh is created */
4505
0
  if (CHECK_FLAG(pi->flags, BGP_PATH_VALID) && pi->attr) {
4506
0
    n->ref_pi = pi;
4507
0
    memcpy(&n->rmac, &pi->attr->rmac, ETH_ALEN);
4508
0
  }
4509
4510
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4511
0
    zlog_debug("evpn vrf %s nh %s rmac %pEA add",
4512
0
         n->bgp_vrf->name_pretty, n->nh_str, &n->rmac);
4513
0
  bgp_evpn_nh_zebra_update(n, true);
4514
0
  return n;
4515
0
}
4516
4517
/* Delete nexthop entry if there are no paths referencing it */
4518
static void bgp_evpn_nh_del(struct bgp_evpn_nh *n)
4519
0
{
4520
0
  struct bgp_evpn_nh *tmp_n;
4521
0
  struct bgp *bgp_vrf = n->bgp_vrf;
4522
4523
0
  if (listcount(n->pi_list))
4524
0
    return;
4525
4526
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4527
0
    zlog_debug("evpn vrf %s nh %s del to zebra",
4528
0
         bgp_vrf->name_pretty, n->nh_str);
4529
4530
0
  bgp_evpn_nh_zebra_update(n, false);
4531
0
  list_delete(&n->pi_list);
4532
0
  tmp_n = hash_release(bgp_vrf->evpn_nh_table, n);
4533
0
  XFREE(MTYPE_BGP_EVPN_NH, tmp_n);
4534
0
}
4535
4536
static void hash_evpn_nh_free(struct bgp_evpn_nh *ben)
4537
0
{
4538
0
  XFREE(MTYPE_BGP_EVPN_NH, ben);
4539
0
}
4540
4541
static unsigned int bgp_evpn_nh_hash_keymake(const void *p)
4542
0
{
4543
0
  const struct bgp_evpn_nh *n = p;
4544
0
  const struct ipaddr *ip = &n->ip;
4545
4546
0
  if (IS_IPADDR_V4(ip))
4547
0
    return jhash_1word(ip->ipaddr_v4.s_addr, 0);
4548
4549
0
  return jhash2(ip->ipaddr_v6.s6_addr32,
4550
0
          array_size(ip->ipaddr_v6.s6_addr32), 0);
4551
0
}
4552
4553
static bool bgp_evpn_nh_cmp(const void *p1, const void *p2)
4554
0
{
4555
0
  const struct bgp_evpn_nh *n1 = p1;
4556
0
  const struct bgp_evpn_nh *n2 = p2;
4557
4558
0
  if (n1 == NULL && n2 == NULL)
4559
0
    return true;
4560
4561
0
  if (n1 == NULL || n2 == NULL)
4562
0
    return false;
4563
4564
0
  return (ipaddr_cmp(&n1->ip, &n2->ip) == 0);
4565
0
}
4566
4567
void bgp_evpn_nh_init(struct bgp *bgp_vrf)
4568
1
{
4569
1
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4570
0
    zlog_debug("evpn vrf %s nh init", bgp_vrf->name_pretty);
4571
1
  bgp_vrf->evpn_nh_table = hash_create(
4572
1
    bgp_evpn_nh_hash_keymake, bgp_evpn_nh_cmp, "BGP EVPN NH table");
4573
1
}
4574
4575
static void bgp_evpn_nh_flush_entry(struct bgp_evpn_nh *nh)
4576
0
{
4577
0
  struct listnode *node;
4578
0
  struct listnode *nnode;
4579
0
  struct bgp_path_evpn_nh_info *nh_info;
4580
4581
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4582
0
    zlog_debug("evpn vrf %s nh %s flush", nh->bgp_vrf->name_pretty,
4583
0
         nh->nh_str);
4584
4585
  /* force flush paths */
4586
0
  for (ALL_LIST_ELEMENTS(nh->pi_list, node, nnode, nh_info))
4587
0
    bgp_evpn_path_nh_del(nh->bgp_vrf, nh_info->pi);
4588
0
}
4589
4590
static void bgp_evpn_nh_flush_cb(struct hash_bucket *bucket, void *ctxt)
4591
0
{
4592
0
  struct bgp_evpn_nh *nh = (struct bgp_evpn_nh *)bucket->data;
4593
4594
0
  bgp_evpn_nh_flush_entry(nh);
4595
0
}
4596
4597
void bgp_evpn_nh_finish(struct bgp *bgp_vrf)
4598
0
{
4599
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4600
0
    zlog_debug("evpn vrf %s nh finish", bgp_vrf->name_pretty);
4601
0
  hash_iterate(
4602
0
    bgp_vrf->evpn_nh_table,
4603
0
    (void (*)(struct hash_bucket *, void *))bgp_evpn_nh_flush_cb,
4604
0
    NULL);
4605
0
  hash_clean_and_free(&bgp_vrf->evpn_nh_table,
4606
0
          (void (*)(void *))hash_evpn_nh_free);
4607
0
}
4608
4609
static void bgp_evpn_nh_update_ref_pi(struct bgp_evpn_nh *nh)
4610
0
{
4611
0
  struct listnode *node;
4612
0
  struct bgp_path_info *pi;
4613
0
  struct bgp_path_evpn_nh_info *nh_info;
4614
4615
0
  if (nh->ref_pi)
4616
0
    return;
4617
4618
0
  for (ALL_LIST_ELEMENTS_RO(nh->pi_list, node, nh_info)) {
4619
0
    pi = nh_info->pi;
4620
0
    if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || !pi->attr)
4621
0
      continue;
4622
4623
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4624
0
      zlog_debug("evpn vrf %s nh %s ref_pi update",
4625
0
           nh->bgp_vrf->name_pretty, nh->nh_str);
4626
0
    nh->ref_pi = pi;
4627
    /* If we have a new pi copy rmac from it and update
4628
     * zebra if the new rmac is different
4629
     */
4630
0
    if (memcmp(&nh->rmac, &nh->ref_pi->attr->rmac, ETH_ALEN)) {
4631
0
      memcpy(&nh->rmac, &nh->ref_pi->attr->rmac, ETH_ALEN);
4632
0
      bgp_evpn_nh_zebra_update(nh, true);
4633
0
    }
4634
0
    break;
4635
0
  }
4636
0
}
4637
4638
static void bgp_evpn_nh_clear_ref_pi(struct bgp_evpn_nh *nh,
4639
             struct bgp_path_info *pi)
4640
0
{
4641
0
  if (nh->ref_pi != pi)
4642
0
    return;
4643
4644
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
4645
0
    zlog_debug("evpn vrf %s nh %s ref_pi clear",
4646
0
         nh->bgp_vrf->name_pretty, nh->nh_str);
4647
0
  nh->ref_pi = NULL;
4648
  /* try to find another ref_pi */
4649
0
  bgp_evpn_nh_update_ref_pi(nh);
4650
  /* couldn't find one - clear the old rmac and notify zebra */
4651
0
  if (!nh->ref_pi) {
4652
0
    memset(&nh->rmac, 0, ETH_ALEN);
4653
0
    bgp_evpn_nh_zebra_update(nh, true);
4654
0
  }
4655
0
}
4656
4657
static void bgp_evpn_path_nh_info_free(struct bgp_path_evpn_nh_info *nh_info)
4658
0
{
4659
0
  bgp_evpn_path_nh_unlink(nh_info);
4660
0
  XFREE(MTYPE_BGP_EVPN_PATH_NH_INFO, nh_info);
4661
0
}
4662
4663
static struct bgp_path_evpn_nh_info *
4664
bgp_evpn_path_nh_info_new(struct bgp_path_info *pi)
4665
0
{
4666
0
  struct bgp_path_info_extra *e;
4667
0
  struct bgp_path_mh_info *mh_info;
4668
0
  struct bgp_path_evpn_nh_info *nh_info;
4669
4670
0
  e = bgp_path_info_extra_get(pi);
4671
4672
  /* If mh_info doesn't exist allocate it */
4673
0
  mh_info = e->mh_info;
4674
0
  if (!mh_info)
4675
0
    e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
4676
0
                 sizeof(struct bgp_path_mh_info));
4677
4678
  /* If nh_info doesn't exist allocate it */
4679
0
  nh_info = mh_info->nh_info;
4680
0
  if (!nh_info) {
4681
0
    mh_info->nh_info = nh_info =
4682
0
      XCALLOC(MTYPE_BGP_EVPN_PATH_NH_INFO,
4683
0
        sizeof(struct bgp_path_evpn_nh_info));
4684
0
    nh_info->pi = pi;
4685
0
  }
4686
4687
0
  return nh_info;
4688
0
}
4689
4690
static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info)
4691
0
{
4692
0
  struct bgp_evpn_nh *nh = nh_info->nh;
4693
0
  struct bgp_path_info *pi;
4694
0
  char prefix_buf[PREFIX_STRLEN];
4695
4696
0
  if (!nh)
4697
0
    return;
4698
4699
0
  pi = nh_info->pi;
4700
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
4701
0
    zlog_debug("path %s unlinked from nh %s %s",
4702
0
         pi->net ? prefix2str(&pi->net->p, prefix_buf,
4703
0
            sizeof(prefix_buf))
4704
0
           : "",
4705
0
         nh->bgp_vrf->name_pretty, nh->nh_str);
4706
4707
0
  list_delete_node(nh->pi_list, &nh_info->nh_listnode);
4708
4709
0
  nh_info->nh = NULL;
4710
4711
  /* check if the ref_pi need to be updated */
4712
0
  bgp_evpn_nh_clear_ref_pi(nh, pi);
4713
4714
  /* if there are no other references against the nh it
4715
   * needs to be freed
4716
   */
4717
0
  bgp_evpn_nh_del(nh);
4718
4719
  /* Note we don't free the path nh_info on unlink; it will be freed up
4720
   * along with the path.
4721
   */
4722
0
}
4723
4724
static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi)
4725
0
{
4726
0
  struct bgp_path_evpn_nh_info *nh_info;
4727
0
  struct bgp_evpn_nh *nh;
4728
0
  struct ipaddr ip;
4729
4730
  /* EVPN nexthop setup in bgp has been turned off */
4731
0
  if (!bgp_mh_info->bgp_evpn_nh_setup)
4732
0
    return;
4733
4734
0
  if (!bgp_vrf->evpn_nh_table) {
4735
0
    if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
4736
0
      zlog_debug("path %pFX linked to vrf %s failed",
4737
0
           &pi->net->p, bgp_vrf->name_pretty);
4738
0
    return;
4739
0
  }
4740
4741
0
  nh_info = (pi->extra && pi->extra->mh_info)
4742
0
        ? pi->extra->mh_info->nh_info
4743
0
        : NULL;
4744
4745
  /* if NHG is not being used for this path we don't need to manage the
4746
   * nexthops in bgp (they are managed by zebra instead)
4747
   */
4748
0
  if (!(pi->attr->es_flags & ATTR_ES_L3_NHG_USE)) {
4749
0
    if (nh_info)
4750
0
      bgp_evpn_path_nh_unlink(nh_info);
4751
0
    return;
4752
0
  }
4753
4754
  /* setup nh_info against the path if it doesn't aleady exist */
4755
0
  if (!nh_info)
4756
0
    nh_info = bgp_evpn_path_nh_info_new(pi);
4757
4758
  /* find-create nh */
4759
0
  memset(&ip, 0, sizeof(ip));
4760
0
  if (pi->net->p.family == AF_INET6) {
4761
0
    SET_IPADDR_V6(&ip);
4762
0
    memcpy(&ip.ipaddr_v6, &pi->attr->mp_nexthop_global,
4763
0
           sizeof(ip.ipaddr_v6));
4764
0
  } else {
4765
0
    SET_IPADDR_V4(&ip);
4766
0
    memcpy(&ip.ipaddr_v4, &pi->attr->nexthop, sizeof(ip.ipaddr_v4));
4767
0
  }
4768
4769
0
  nh = bgp_evpn_nh_find(bgp_vrf, &ip);
4770
0
  if (!nh)
4771
0
    nh = bgp_evpn_nh_add(bgp_vrf, &ip, pi);
4772
4773
  /* dup check */
4774
0
  if (nh_info->nh == nh) {
4775
    /* Check if any of the paths are now valid */
4776
0
    bgp_evpn_nh_update_ref_pi(nh);
4777
0
    return;
4778
0
  }
4779
4780
  /* unlink old nh if any */
4781
0
  bgp_evpn_path_nh_unlink(nh_info);
4782
4783
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
4784
0
    zlog_debug("path %pFX linked to nh %s %s", &pi->net->p,
4785
0
         nh->bgp_vrf->name_pretty, nh->nh_str);
4786
4787
  /* link mac-ip path to the new nh */
4788
0
  nh_info->nh = nh;
4789
0
  listnode_init(&nh_info->nh_listnode, nh_info);
4790
0
  listnode_add(nh->pi_list, &nh_info->nh_listnode);
4791
  /* If a new valid path got linked to the nh see if can get the rmac
4792
   * from it
4793
   */
4794
0
  bgp_evpn_nh_update_ref_pi(nh);
4795
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) {
4796
0
    if (!nh->ref_pi)
4797
0
      zlog_debug(
4798
0
        "path %pFX linked to nh %s %s with no valid pi",
4799
0
        &pi->net->p, nh->bgp_vrf->name_pretty,
4800
0
        nh->nh_str);
4801
0
  }
4802
0
}
4803
4804
void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi)
4805
0
{
4806
0
  struct bgp_path_evpn_nh_info *nh_info;
4807
4808
0
  nh_info = (pi->extra && pi->extra->mh_info)
4809
0
        ? pi->extra->mh_info->nh_info
4810
0
        : NULL;
4811
4812
0
  if (!nh_info)
4813
0
    return;
4814
4815
0
  bgp_evpn_path_nh_unlink(nh_info);
4816
0
}
4817
4818
void bgp_evpn_path_nh_add(struct bgp *bgp_vrf, struct bgp_path_info *pi)
4819
0
{
4820
0
  bgp_evpn_path_nh_link(bgp_vrf, pi);
4821
0
}
4822
4823
static void bgp_evpn_nh_show_entry(struct bgp_evpn_nh *nh, struct vty *vty,
4824
           json_object *json_array)
4825
0
{
4826
0
  json_object *json = NULL;
4827
0
  char mac_buf[ETHER_ADDR_STRLEN];
4828
0
  char prefix_buf[PREFIX_STRLEN];
4829
4830
0
  if (json_array)
4831
    /* create a separate json object for each ES */
4832
0
    json = json_object_new_object();
4833
4834
0
  prefix_mac2str(&nh->rmac, mac_buf, sizeof(mac_buf));
4835
0
  if (nh->ref_pi && nh->ref_pi->net)
4836
0
    prefix2str(&nh->ref_pi->net->p, prefix_buf, sizeof(prefix_buf));
4837
0
  else
4838
0
    prefix_buf[0] = '\0';
4839
0
  if (json) {
4840
0
    json_object_string_add(json, "vrf", nh->bgp_vrf->name_pretty);
4841
0
    json_object_string_add(json, "ip", nh->nh_str);
4842
0
    json_object_string_add(json, "rmac", mac_buf);
4843
0
    json_object_string_add(json, "basePath", prefix_buf);
4844
0
    json_object_int_add(json, "pathCount", listcount(nh->pi_list));
4845
0
  } else {
4846
0
    vty_out(vty, "%-15s %-15s %-17s %-10d %s\n",
4847
0
      nh->bgp_vrf->name_pretty, nh->nh_str, mac_buf,
4848
0
      listcount(nh->pi_list), prefix_buf);
4849
0
  }
4850
4851
  /* add ES to the json array */
4852
0
  if (json_array)
4853
0
    json_object_array_add(json_array, json);
4854
0
}
4855
4856
struct nh_show_ctx {
4857
  struct vty *vty;
4858
  json_object *json;
4859
};
4860
4861
static void bgp_evpn_nh_show_hash_cb(struct hash_bucket *bucket, void *ctxt)
4862
0
{
4863
0
  struct bgp_evpn_nh *nh = (struct bgp_evpn_nh *)bucket->data;
4864
0
  struct nh_show_ctx *wctx = (struct nh_show_ctx *)ctxt;
4865
4866
0
  bgp_evpn_nh_show_entry(nh, wctx->vty, wctx->json);
4867
0
}
4868
4869
/* Display all evpn nexthops */
4870
void bgp_evpn_nh_show(struct vty *vty, bool uj)
4871
0
{
4872
0
  json_object *json_array = NULL;
4873
0
  struct bgp *bgp_vrf;
4874
0
  struct listnode *node;
4875
0
  struct nh_show_ctx wctx;
4876
4877
0
  if (uj) {
4878
    /* create an array of nexthops */
4879
0
    json_array = json_object_new_array();
4880
0
  } else {
4881
0
    vty_out(vty, "%-15s %-15s %-17s %-10s %s\n", "VRF", "IP",
4882
0
      "RMAC", "#Paths", "Base Path");
4883
0
  }
4884
4885
0
  wctx.vty = vty;
4886
0
  wctx.json = json_array;
4887
4888
  /* walk through all vrfs */
4889
0
  for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
4890
0
    hash_iterate(bgp_vrf->evpn_nh_table,
4891
0
           (void (*)(struct hash_bucket *,
4892
0
               void *))bgp_evpn_nh_show_hash_cb,
4893
0
           &wctx);
4894
0
  }
4895
4896
  /* print the array of json-ESs */
4897
0
  if (uj)
4898
0
    vty_json(vty, json_array);
4899
0
}
4900
4901
/*****************************************************************************/
4902
void bgp_evpn_mh_init(void)
4903
1
{
4904
1
  bm->mh_info = XCALLOC(MTYPE_BGP_EVPN_MH_INFO, sizeof(*bm->mh_info));
4905
4906
  /* setup ES tables */
4907
1
  RB_INIT(bgp_es_rb_head, &bgp_mh_info->es_rb_tree);
4908
  /* local ES list */
4909
1
  bgp_mh_info->local_es_list = list_new();
4910
1
  listset_app_node_mem(bgp_mh_info->local_es_list);
4911
  /* list of ESs with pending processing */
4912
1
  bgp_mh_info->pend_es_list = list_new();
4913
1
  listset_app_node_mem(bgp_mh_info->pend_es_list);
4914
4915
1
  bgp_mh_info->ead_evi_rx = BGP_EVPN_MH_EAD_EVI_RX_DEF;
4916
1
  bgp_mh_info->ead_evi_tx = BGP_EVPN_MH_EAD_EVI_TX_DEF;
4917
1
  bgp_mh_info->ead_es_export_rtl = list_new();
4918
1
  bgp_mh_info->ead_es_export_rtl->cmp =
4919
1
    (int (*)(void *, void *))bgp_evpn_route_target_cmp;
4920
1
  bgp_mh_info->ead_es_export_rtl->del = bgp_evpn_xxport_delete_ecomm;
4921
4922
  /* config knobs - XXX add cli to control it */
4923
1
  bgp_mh_info->ead_evi_adv_for_down_links = true;
4924
1
  bgp_mh_info->consistency_checking = true;
4925
1
  bgp_mh_info->host_routes_use_l3nhg = BGP_EVPN_MH_USE_ES_L3NHG_DEF;
4926
1
  bgp_mh_info->suppress_l3_ecomm_on_inactive_es = true;
4927
1
  bgp_mh_info->bgp_evpn_nh_setup = true;
4928
1
  bgp_mh_info->evi_per_es_frag = BGP_EVPN_MAX_EVI_PER_ES_FRAG;
4929
4930
1
  memset(&zero_esi_buf, 0, sizeof(esi_t));
4931
1
}
4932
4933
void bgp_evpn_mh_finish(void)
4934
0
{
4935
0
  struct bgp_evpn_es *es;
4936
0
  struct bgp_evpn_es *es_next;
4937
4938
0
  if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
4939
0
    zlog_debug("evpn mh finish");
4940
4941
0
  RB_FOREACH_SAFE (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree,
4942
0
       es_next) {
4943
0
    bgp_evpn_es_local_info_clear(es, true);
4944
0
  }
4945
0
  if (bgp_mh_info->t_cons_check)
4946
0
    EVENT_OFF(bgp_mh_info->t_cons_check);
4947
0
  list_delete(&bgp_mh_info->local_es_list);
4948
0
  list_delete(&bgp_mh_info->pend_es_list);
4949
0
  list_delete(&bgp_mh_info->ead_es_export_rtl);
4950
4951
0
  XFREE(MTYPE_BGP_EVPN_MH_INFO, bgp_mh_info);
4952
0
}
4953
4954
/* This function is called when disable-ead-evi-rx knob flaps */
4955
void bgp_evpn_switch_ead_evi_rx(void)
4956
0
{
4957
0
  struct bgp *bgp;
4958
0
  struct bgp_evpn_es *es;
4959
0
  struct bgp_evpn_es_evi *es_evi;
4960
0
  struct listnode *evi_node = NULL;
4961
0
  struct listnode *evi_next = NULL;
4962
0
  struct bgp_evpn_es_evi_vtep *vtep;
4963
0
  struct listnode *vtep_node = NULL;
4964
0
  struct listnode *vtep_next = NULL;
4965
4966
0
  bgp = bgp_get_evpn();
4967
0
  if (!bgp)
4968
0
    return;
4969
4970
  /*
4971
   * Process all the remote es_evi_vteps and reevaluate if the es_evi_vtep
4972
   * is active.
4973
   */
4974
0
  RB_FOREACH(es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
4975
0
    if (!CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE))
4976
0
      continue;
4977
4978
0
    for (ALL_LIST_ELEMENTS(es->es_evi_list, evi_node, evi_next,
4979
0
               es_evi)) {
4980
0
      if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE))
4981
0
        continue;
4982
4983
0
      for (ALL_LIST_ELEMENTS(es_evi->es_evi_vtep_list,
4984
0
                 vtep_node, vtep_next, vtep))
4985
0
        bgp_evpn_es_evi_vtep_re_eval_active(bgp, vtep);
4986
0
    }
4987
0
  }
4988
0
}