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