]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_mh.c
bgpd: Handle ES VTEP add/del to a host route
[mirror_frr.git] / bgpd / bgp_evpn_mh.c
1 /* EVPN Multihoming procedures
2 *
3 * Copyright (C) 2019 Cumulus Networks, Inc.
4 * Anuradha Karuppiah
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
32 #include "lib/printfrr.h"
33
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"
50 #include "bgpd/bgp_label.h"
51 #include "bgpd/bgp_nht.h"
52
53 static void bgp_evpn_local_es_down(struct bgp *bgp,
54 struct bgp_evpn_es *es);
55 static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
56 struct bgp_evpn_es *es);
57 static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
58 struct bgp_evpn_es *es,
59 struct in_addr vtep_ip,
60 bool esr, uint8_t df_alg,
61 uint16_t df_pref);
62 static void bgp_evpn_es_vtep_del(struct bgp *bgp,
63 struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr);
64 static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es);
65 static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);
66 static void bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi);
67 static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es);
68 static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es);
69 static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi);
70 static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller);
71 static void bgp_evpn_es_path_all_update(struct bgp_evpn_es_vtep *es_vtep,
72 bool active);
73
74 esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
75
76 /******************************************************************************
77 * per-ES (Ethernet Segment) routing table
78 *
79 * Following routes are added to the ES's routing table -
80 * 1. Local and remote ESR (Type-4)
81 * 2. Local EAD-per-ES (Type-1).
82 *
83 * Key for these routes is {ESI, VTEP-IP} so the path selection is practically
84 * a no-op i.e. all paths lead to same VTEP-IP (i.e. result in the same VTEP
85 * being added to same ES).
86 *
87 * Note the following routes go into the VNI routing table (instead of the
88 * ES routing table) -
89 * 1. Remote EAD-per-ES
90 * 2. Local and remote EAD-per-EVI
91 */
92
93 /* Calculate the best path for a multi-homing (Type-1 or Type-4) route
94 * installed in the ES's routing table.
95 */
96 static int bgp_evpn_es_route_select_install(struct bgp *bgp,
97 struct bgp_evpn_es *es,
98 struct bgp_dest *dest)
99 {
100 int ret = 0;
101 afi_t afi = AFI_L2VPN;
102 safi_t safi = SAFI_EVPN;
103 struct bgp_path_info *old_select; /* old best */
104 struct bgp_path_info *new_select; /* new best */
105 struct bgp_path_info_pair old_and_new;
106
107 /* Compute the best path. */
108 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
109 afi, safi);
110 old_select = old_and_new.old;
111 new_select = old_and_new.new;
112
113 /*
114 * If the best path hasn't changed - see if something needs to be
115 * updated
116 */
117 if (old_select && old_select == new_select
118 && old_select->type == ZEBRA_ROUTE_BGP
119 && old_select->sub_type == BGP_ROUTE_IMPORTED
120 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
121 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
122 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
123 if (bgp_zebra_has_route_changed(old_select)) {
124 bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop,
125 true /*esr*/,
126 old_select->attr->df_alg,
127 old_select->attr->df_pref);
128 }
129 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
130 bgp_zebra_clear_route_change_flags(dest);
131 return ret;
132 }
133
134 /* If the user did a "clear" this flag will be set */
135 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
136
137 /* bestpath has changed; update relevant fields and install or uninstall
138 * into the zebra RIB.
139 */
140 if (old_select || new_select)
141 bgp_bump_version(dest);
142
143 if (old_select)
144 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
145 if (new_select) {
146 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
147 bgp_path_info_unset_flag(dest, new_select,
148 BGP_PATH_ATTR_CHANGED);
149 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
150 }
151
152 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
153 && new_select->sub_type == BGP_ROUTE_IMPORTED) {
154 bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop,
155 true /*esr */, new_select->attr->df_alg,
156 new_select->attr->df_pref);
157 } else {
158 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
159 && old_select->sub_type == BGP_ROUTE_IMPORTED)
160 bgp_evpn_es_vtep_del(
161 bgp, es, old_select->attr->nexthop,
162 true /*esr*/);
163 }
164
165 /* Clear any route change flags. */
166 bgp_zebra_clear_route_change_flags(dest);
167
168 /* Reap old select bgp_path_info, if it has been removed */
169 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
170 bgp_path_info_reap(dest, old_select);
171
172 return ret;
173 }
174
175 /* Install Type-1/Type-4 route entry in the per-ES routing table */
176 static int bgp_evpn_es_route_install(struct bgp *bgp,
177 struct bgp_evpn_es *es, struct prefix_evpn *p,
178 struct bgp_path_info *parent_pi)
179 {
180 int ret = 0;
181 struct bgp_dest *dest = NULL;
182 struct bgp_path_info *pi = NULL;
183 struct attr *attr_new = NULL;
184
185 /* Create (or fetch) route within the VNI.
186 * NOTE: There is no RD here.
187 */
188 dest = bgp_node_get(es->route_table, (struct prefix *)p);
189
190 /* Check if route entry is already present. */
191 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
192 if (pi->extra
193 && (struct bgp_path_info *)pi->extra->parent ==
194 parent_pi)
195 break;
196
197 if (!pi) {
198 /* Add (or update) attribute to hash. */
199 attr_new = bgp_attr_intern(parent_pi->attr);
200
201 /* Create new route with its attribute. */
202 pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0,
203 parent_pi->peer, attr_new, dest);
204 SET_FLAG(pi->flags, BGP_PATH_VALID);
205 bgp_path_info_extra_get(pi);
206 pi->extra->parent = bgp_path_info_lock(parent_pi);
207 bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
208 bgp_path_info_add(dest, pi);
209 } else {
210 if (attrhash_cmp(pi->attr, parent_pi->attr)
211 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
212 bgp_dest_unlock_node(dest);
213 return 0;
214 }
215 /* The attribute has changed. */
216 /* Add (or update) attribute to hash. */
217 attr_new = bgp_attr_intern(parent_pi->attr);
218
219 /* Restore route, if needed. */
220 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
221 bgp_path_info_restore(dest, pi);
222
223 /* Mark if nexthop has changed. */
224 if (!IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop))
225 SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
226
227 /* Unintern existing, set to new. */
228 bgp_attr_unintern(&pi->attr);
229 pi->attr = attr_new;
230 pi->uptime = bgp_clock();
231 }
232
233 /* Perform route selection and update zebra, if required. */
234 ret = bgp_evpn_es_route_select_install(bgp, es, dest);
235
236 bgp_dest_unlock_node(dest);
237
238 return ret;
239 }
240
241 /* Uninstall Type-1/Type-4 route entry from the ES routing table */
242 static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
243 struct prefix_evpn *p, struct bgp_path_info *parent_pi)
244 {
245 int ret;
246 struct bgp_dest *dest;
247 struct bgp_path_info *pi;
248
249 if (!es->route_table)
250 return 0;
251
252 /* Locate route within the ESI.
253 * NOTE: There is no RD here.
254 */
255 dest = bgp_node_lookup(es->route_table, (struct prefix *)p);
256 if (!dest)
257 return 0;
258
259 /* Find matching route entry. */
260 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
261 if (pi->extra
262 && (struct bgp_path_info *)pi->extra->parent ==
263 parent_pi)
264 break;
265
266 if (!pi)
267 return 0;
268
269 /* Mark entry for deletion */
270 bgp_path_info_delete(dest, pi);
271
272 /* Perform route selection and update zebra, if required. */
273 ret = bgp_evpn_es_route_select_install(bgp, es, dest);
274
275 /* Unlock route node. */
276 bgp_dest_unlock_node(dest);
277
278 return ret;
279 }
280
281 /* Install or unistall a Tyoe-4 route in the per-ES routing table */
282 int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
283 afi_t afi, safi_t safi, struct prefix_evpn *evp,
284 struct bgp_path_info *pi, int install)
285 {
286 int ret = 0;
287
288 if (install)
289 ret = bgp_evpn_es_route_install(bgp, es, evp, pi);
290 else
291 ret = bgp_evpn_es_route_uninstall(bgp, es, evp, pi);
292
293 if (ret) {
294 flog_err(
295 EC_BGP_EVPN_FAIL,
296 "%u: Failed to %s EVPN %s route in ESI %s",
297 bgp->vrf_id,
298 install ? "install" : "uninstall",
299 "ES", es->esi_str);
300 return ret;
301 }
302 return 0;
303 }
304
305 /* Delete (and withdraw) local routes for specified ES from global and ES table.
306 * Also remove all remote routes from the per ES table. Invoked when ES
307 * is deleted.
308 */
309 static void bgp_evpn_es_route_del_all(struct bgp *bgp, struct bgp_evpn_es *es)
310 {
311 struct bgp_dest *dest;
312 struct bgp_path_info *pi, *nextpi;
313
314 /* de-activate the ES */
315 bgp_evpn_local_es_down(bgp, es);
316 bgp_evpn_local_type1_evi_route_del(bgp, es);
317
318 /* Walk this ES's routing table and delete all routes. */
319 for (dest = bgp_table_top(es->route_table); dest;
320 dest = bgp_route_next(dest)) {
321 for (pi = bgp_dest_get_bgp_path_info(dest);
322 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
323 bgp_path_info_delete(dest, pi);
324 bgp_path_info_reap(dest, pi);
325 }
326 }
327 }
328
329 /*****************************************************************************
330 * Base APIs for creating MH routes (Type-1 or Type-4) on local ethernet
331 * segment updates.
332 */
333
334 /* create or update local EVPN type1/type4 route entry.
335 *
336 * This could be in -
337 * the ES table if ESR/EAD-ES (or)
338 * the VNI table if EAD-EVI (or)
339 * the global table if ESR/EAD-ES/EAD-EVI
340 *
341 * Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
342 * ESR).
343 */
344 static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
345 struct bgpevpn *vpn, afi_t afi, safi_t safi,
346 struct bgp_dest *dest, struct attr *attr,
347 int add, struct bgp_path_info **ri,
348 int *route_changed)
349 {
350 struct bgp_path_info *tmp_pi = NULL;
351 struct bgp_path_info *local_pi = NULL; /* local route entry if any */
352 struct bgp_path_info *remote_pi = NULL; /* remote route entry if any */
353 struct attr *attr_new = NULL;
354 struct prefix_evpn *evp;
355
356 *ri = NULL;
357 evp = (struct prefix_evpn *)bgp_dest_get_prefix(dest);
358 *route_changed = 1;
359
360 /* locate the local and remote entries if any */
361 for (tmp_pi = bgp_dest_get_bgp_path_info(dest); tmp_pi;
362 tmp_pi = tmp_pi->next) {
363 if (tmp_pi->peer == bgp->peer_self
364 && tmp_pi->type == ZEBRA_ROUTE_BGP
365 && tmp_pi->sub_type == BGP_ROUTE_STATIC)
366 local_pi = tmp_pi;
367 if (tmp_pi->type == ZEBRA_ROUTE_BGP
368 && tmp_pi->sub_type == BGP_ROUTE_IMPORTED
369 && CHECK_FLAG(tmp_pi->flags, BGP_PATH_VALID))
370 remote_pi = tmp_pi;
371 }
372
373 /* we don't expect to see a remote_ri at this point as
374 * an ES route has {esi, vtep_ip} as the key in the ES-rt-table
375 * in the VNI-rt-table.
376 */
377 if (remote_pi) {
378 flog_err(
379 EC_BGP_ES_INVALID,
380 "%u ERROR: local es route for ESI: %s Vtep %pI4 also learnt from remote",
381 bgp->vrf_id, es->esi_str, &es->originator_ip);
382 return -1;
383 }
384
385 if (!local_pi && !add)
386 return 0;
387
388 /* create or update the entry */
389 if (!local_pi) {
390
391 /* Add or update attribute to hash */
392 attr_new = bgp_attr_intern(attr);
393
394 /* Create new route with its attribute. */
395 tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
396 bgp->peer_self, attr_new, dest);
397 SET_FLAG(tmp_pi->flags, BGP_PATH_VALID);
398
399 if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
400 bgp_path_info_extra_get(tmp_pi);
401 tmp_pi->extra->num_labels = 1;
402 if (vpn)
403 vni2label(vpn->vni, &tmp_pi->extra->label[0]);
404 else
405 tmp_pi->extra->label[0] = 0;
406 }
407
408 /* add the newly created path to the route-node */
409 bgp_path_info_add(dest, tmp_pi);
410 } else {
411 tmp_pi = local_pi;
412 if (attrhash_cmp(tmp_pi->attr, attr)
413 && !CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
414 *route_changed = 0;
415 else {
416 /* The attribute has changed.
417 * Add (or update) attribute to hash.
418 */
419 attr_new = bgp_attr_intern(attr);
420 bgp_path_info_set_flag(dest, tmp_pi,
421 BGP_PATH_ATTR_CHANGED);
422
423 /* Restore route, if needed. */
424 if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED))
425 bgp_path_info_restore(dest, tmp_pi);
426
427 /* Unintern existing, set to new. */
428 bgp_attr_unintern(&tmp_pi->attr);
429 tmp_pi->attr = attr_new;
430 tmp_pi->uptime = bgp_clock();
431 }
432 }
433
434 if (*route_changed) {
435 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
436 zlog_debug(
437 "local ES %s vni %u route-type %s nexthop %pI4 updated",
438 es->esi_str, vpn ? vpn->vni : 0,
439 evp->prefix.route_type == BGP_EVPN_ES_ROUTE
440 ? "esr"
441 : (vpn ? "ead-evi" : "ead-es"),
442 &attr->mp_nexthop_global_in);
443 }
444
445 /* Return back the route entry. */
446 *ri = tmp_pi;
447 return 0;
448 }
449
450 /* Delete local EVPN ESR (type-4) and EAD (type-1) route
451 *
452 * Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
453 * ESR).
454 */
455 static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
456 struct bgpevpn *vpn, struct prefix_evpn *p)
457 {
458 afi_t afi = AFI_L2VPN;
459 safi_t safi = SAFI_EVPN;
460 struct bgp_path_info *pi;
461 struct bgp_dest *dest = NULL; /* dest in esi table */
462 struct bgp_dest *global_dest = NULL; /* dest in global table */
463 struct bgp_table *rt_table;
464 struct prefix_rd *prd;
465
466 if (vpn) {
467 rt_table = vpn->route_table;
468 prd = &vpn->prd;
469 } else {
470 rt_table = es->route_table;
471 prd = &es->prd;
472 }
473
474 /* First, locate the route node within the ESI or VNI.
475 * If it doesn't exist, ther is nothing to do.
476 * Note: there is no RD here.
477 */
478 dest = bgp_node_lookup(rt_table, (struct prefix *)p);
479 if (!dest)
480 return 0;
481
482 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
483 zlog_debug(
484 "local ES %s vni %u route-type %s nexthop %pI4 delete",
485 es->esi_str, vpn ? vpn->vni : 0,
486 p->prefix.route_type == BGP_EVPN_ES_ROUTE
487 ? "esr"
488 : (vpn ? "ead-evi" : "ead-es"),
489 &es->originator_ip);
490
491 /* Next, locate route node in the global EVPN routing table.
492 * Note that this table is a 2-level tree (RD-level + Prefix-level)
493 */
494 global_dest =
495 bgp_global_evpn_node_lookup(bgp->rib[afi][safi], afi, safi,
496 (const struct prefix_evpn *)p, prd);
497 if (global_dest) {
498
499 /* Delete route entry in the global EVPN table. */
500 delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
501
502 /* Schedule for processing - withdraws to peers happen from
503 * this table.
504 */
505 if (pi)
506 bgp_process(bgp, global_dest, afi, safi);
507 bgp_dest_unlock_node(global_dest);
508 }
509
510 /*
511 * Delete route entry in the ESI or VNI routing table.
512 * This can just be removed.
513 */
514 delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
515 if (pi)
516 bgp_path_info_reap(dest, pi);
517 bgp_dest_unlock_node(dest);
518 return 0;
519 }
520
521 /*****************************************************************************
522 * Ethernet Segment (Type-4) Routes
523 * ESRs are used for DF election. Currently service-carving described in
524 * RFC 7432 is NOT supported. Instead preference based DF election is
525 * used by default.
526 * Reference: draft-ietf-bess-evpn-pref-df
527 */
528 /* Build extended community for EVPN ES (type-4) route */
529 static void bgp_evpn_type4_route_extcomm_build(struct bgp_evpn_es *es,
530 struct attr *attr)
531 {
532 struct ecommunity ecom_encap;
533 struct ecommunity ecom_es_rt;
534 struct ecommunity ecom_df;
535 struct ecommunity_val eval;
536 struct ecommunity_val eval_es_rt;
537 struct ecommunity_val eval_df;
538 bgp_encap_types tnl_type;
539 struct ethaddr mac;
540
541 /* Encap */
542 tnl_type = BGP_ENCAP_TYPE_VXLAN;
543 memset(&ecom_encap, 0, sizeof(ecom_encap));
544 encode_encap_extcomm(tnl_type, &eval);
545 ecom_encap.size = 1;
546 ecom_encap.unit_size = ECOMMUNITY_SIZE;
547 ecom_encap.val = (uint8_t *)eval.val;
548 attr->ecommunity = ecommunity_dup(&ecom_encap);
549
550 /* ES import RT */
551 memset(&mac, 0, sizeof(struct ethaddr));
552 memset(&ecom_es_rt, 0, sizeof(ecom_es_rt));
553 es_get_system_mac(&es->esi, &mac);
554 encode_es_rt_extcomm(&eval_es_rt, &mac);
555 ecom_es_rt.size = 1;
556 ecom_es_rt.unit_size = ECOMMUNITY_SIZE;
557 ecom_es_rt.val = (uint8_t *)eval_es_rt.val;
558 attr->ecommunity =
559 ecommunity_merge(attr->ecommunity, &ecom_es_rt);
560
561 /* DF election extended community */
562 memset(&ecom_df, 0, sizeof(ecom_df));
563 encode_df_elect_extcomm(&eval_df, es->df_pref);
564 ecom_df.size = 1;
565 ecom_df.val = (uint8_t *)eval_df.val;
566 attr->ecommunity = ecommunity_merge(attr->ecommunity, &ecom_df);
567
568 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
569 }
570
571 /* Create or update local type-4 route */
572 static int bgp_evpn_type4_route_update(struct bgp *bgp,
573 struct bgp_evpn_es *es, struct prefix_evpn *p)
574 {
575 int ret = 0;
576 int route_changed = 0;
577 afi_t afi = AFI_L2VPN;
578 safi_t safi = SAFI_EVPN;
579 struct attr attr;
580 struct attr *attr_new = NULL;
581 struct bgp_dest *dest = NULL;
582 struct bgp_path_info *pi = NULL;
583
584 memset(&attr, 0, sizeof(struct attr));
585
586 /* Build path-attribute for this route. */
587 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
588 attr.nexthop = es->originator_ip;
589 attr.mp_nexthop_global_in = es->originator_ip;
590 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
591
592 /* Set up extended community. */
593 bgp_evpn_type4_route_extcomm_build(es, &attr);
594
595 /* First, create (or fetch) route node within the ESI. */
596 /* NOTE: There is no RD here. */
597 dest = bgp_node_get(es->route_table, (struct prefix *)p);
598
599 /* Create or update route entry. */
600 ret = bgp_evpn_mh_route_update(bgp, es, NULL, afi, safi, dest, &attr, 1,
601 &pi, &route_changed);
602 if (ret != 0)
603 flog_err(
604 EC_BGP_ES_INVALID,
605 "%u ERROR: Failed to updated ES route ESI: %s VTEP %pI4",
606 bgp->vrf_id, es->esi_str, &es->originator_ip);
607
608 assert(pi);
609 attr_new = pi->attr;
610
611 /* Perform route selection;
612 * this is just to set the flags correctly
613 * as local route in the ES always wins.
614 */
615 bgp_evpn_es_route_select_install(bgp, es, dest);
616 bgp_dest_unlock_node(dest);
617
618 /* If this is a new route or some attribute has changed, export the
619 * route to the global table. The route will be advertised to peers
620 * from there. Note that this table is a 2-level tree (RD-level +
621 * Prefix-level) similar to L3VPN routes.
622 */
623 if (route_changed) {
624 struct bgp_path_info *global_pi;
625
626 dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
627 p, &es->prd);
628 bgp_evpn_mh_route_update(bgp, es, NULL, afi, safi, dest,
629 attr_new, 1, &global_pi,
630 &route_changed);
631
632 /* Schedule for processing and unlock node. */
633 bgp_process(bgp, dest, afi, safi);
634 bgp_dest_unlock_node(dest);
635 }
636
637 /* Unintern temporary. */
638 aspath_unintern(&attr.aspath);
639 return 0;
640 }
641
642 /* Delete local type-4 route */
643 static int bgp_evpn_type4_route_delete(struct bgp *bgp,
644 struct bgp_evpn_es *es, struct prefix_evpn *p)
645 {
646 return bgp_evpn_mh_route_delete(bgp, es, NULL /* l2vni */, p);
647 }
648
649 /* Process remote/received EVPN type-4 route (advertise or withdraw) */
650 int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
651 struct attr *attr, uint8_t *pfx, int psize,
652 uint32_t addpath_id)
653 {
654 int ret;
655 esi_t esi;
656 uint8_t ipaddr_len;
657 struct in_addr vtep_ip;
658 struct prefix_rd prd;
659 struct prefix_evpn p;
660
661 /* Type-4 route should be either 23 or 35 bytes
662 * RD (8), ESI (10), ip-len (1), ip (4 or 16)
663 */
664 if (psize != BGP_EVPN_TYPE4_V4_PSIZE &&
665 psize != BGP_EVPN_TYPE4_V6_PSIZE) {
666 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
667 "%u:%s - Rx EVPN Type-4 NLRI with invalid length %d",
668 peer->bgp->vrf_id, peer->host, psize);
669 return -1;
670 }
671
672 /* Make prefix_rd */
673 prd.family = AF_UNSPEC;
674 prd.prefixlen = 64;
675 memcpy(&prd.val, pfx, RD_BYTES);
676 pfx += RD_BYTES;
677
678 /* get the ESI */
679 memcpy(&esi, pfx, ESI_BYTES);
680 pfx += ESI_BYTES;
681
682
683 /* Get the IP. */
684 ipaddr_len = *pfx++;
685 if (ipaddr_len == IPV4_MAX_BITLEN) {
686 memcpy(&vtep_ip, pfx, IPV4_MAX_BYTELEN);
687 } else {
688 flog_err(
689 EC_BGP_EVPN_ROUTE_INVALID,
690 "%u:%s - Rx EVPN Type-4 NLRI with unsupported IP address length %d",
691 peer->bgp->vrf_id, peer->host, ipaddr_len);
692 return -1;
693 }
694
695 build_evpn_type4_prefix(&p, &esi, vtep_ip);
696 /* Process the route. */
697 if (attr) {
698 ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
699 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
700 &prd, NULL, 0, 0, NULL);
701 } else {
702 ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
703 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
704 &prd, NULL, 0, NULL);
705 }
706 return ret;
707 }
708
709 /* Check if a prefix belongs to the local ES */
710 static bool bgp_evpn_type4_prefix_match(struct prefix_evpn *p,
711 struct bgp_evpn_es *es)
712 {
713 return (p->prefix.route_type == BGP_EVPN_ES_ROUTE) &&
714 !memcmp(&p->prefix.es_addr.esi, &es->esi, sizeof(esi_t));
715 }
716
717 /* Import remote ESRs on local ethernet segment add */
718 static int bgp_evpn_type4_remote_routes_import(struct bgp *bgp,
719 struct bgp_evpn_es *es, bool install)
720 {
721 int ret;
722 afi_t afi;
723 safi_t safi;
724 struct bgp_dest *rd_dest, *dest;
725 struct bgp_table *table;
726 struct bgp_path_info *pi;
727
728 afi = AFI_L2VPN;
729 safi = SAFI_EVPN;
730
731 /* Walk entire global routing table and evaluate routes which could be
732 * imported into this Ethernet Segment.
733 */
734 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
735 rd_dest = bgp_route_next(rd_dest)) {
736 table = bgp_dest_get_bgp_table_info(rd_dest);
737 if (!table)
738 continue;
739
740 for (dest = bgp_table_top(table); dest;
741 dest = bgp_route_next(dest)) {
742 struct prefix_evpn *evp =
743 (struct prefix_evpn *)bgp_dest_get_prefix(dest);
744
745 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
746 pi = pi->next) {
747 /*
748 * Consider "valid" remote routes applicable for
749 * this ES.
750 */
751 if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID)
752 && pi->type == ZEBRA_ROUTE_BGP
753 && pi->sub_type == BGP_ROUTE_NORMAL))
754 continue;
755
756 if (!bgp_evpn_type4_prefix_match(evp, es))
757 continue;
758
759 if (install)
760 ret = bgp_evpn_es_route_install(
761 bgp, es, evp, pi);
762 else
763 ret = bgp_evpn_es_route_uninstall(
764 bgp, es, evp, pi);
765
766 if (ret) {
767 flog_err(
768 EC_BGP_EVPN_FAIL,
769 "Failed to %s EVPN %pFX route in ESI %s",
770 install ? "install"
771 : "uninstall",
772 evp, es->esi_str);
773
774 bgp_dest_unlock_node(rd_dest);
775 bgp_dest_unlock_node(dest);
776 return ret;
777 }
778 }
779 }
780 }
781 return 0;
782 }
783
784 /*****************************************************************************
785 * Ethernet Auto Discovery (EAD/Type-1) route handling
786 * There are two types of EAD routes -
787 * 1. EAD-per-ES - Key: {ESI, ET=0xffffffff}
788 * 2. EAD-per-EVI - Key: {ESI, ET=0}
789 */
790
791 /* Extended communities associated with EAD-per-ES */
792 static void bgp_evpn_type1_es_route_extcomm_build(struct bgp_evpn_es *es,
793 struct attr *attr)
794 {
795 struct ecommunity ecom_encap;
796 struct ecommunity ecom_esi_label;
797 struct ecommunity_val eval;
798 struct ecommunity_val eval_esi_label;
799 bgp_encap_types tnl_type;
800 struct listnode *evi_node, *rt_node;
801 struct ecommunity *ecom;
802 struct bgp_evpn_es_evi *es_evi;
803
804 /* Encap */
805 tnl_type = BGP_ENCAP_TYPE_VXLAN;
806 memset(&ecom_encap, 0, sizeof(ecom_encap));
807 encode_encap_extcomm(tnl_type, &eval);
808 ecom_encap.size = 1;
809 ecom_encap.unit_size = ECOMMUNITY_SIZE;
810 ecom_encap.val = (uint8_t *)eval.val;
811 attr->ecommunity = ecommunity_dup(&ecom_encap);
812
813 /* ESI label */
814 encode_esi_label_extcomm(&eval_esi_label,
815 false /*single_active*/);
816 ecom_esi_label.size = 1;
817 ecom_esi_label.unit_size = ECOMMUNITY_SIZE;
818 ecom_esi_label.val = (uint8_t *)eval_esi_label.val;
819 attr->ecommunity =
820 ecommunity_merge(attr->ecommunity, &ecom_esi_label);
821
822 /* Add export RTs for all L2-VNIs associated with this ES */
823 /* XXX - suppress EAD-ES advertisment if there are no EVIs associated
824 * with it.
825 */
826 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list,
827 evi_node, es_evi)) {
828 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
829 continue;
830 for (ALL_LIST_ELEMENTS_RO(es_evi->vpn->export_rtl,
831 rt_node, ecom))
832 attr->ecommunity = ecommunity_merge(attr->ecommunity,
833 ecom);
834 }
835
836 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
837 }
838
839 /* Extended communities associated with EAD-per-EVI */
840 static void bgp_evpn_type1_evi_route_extcomm_build(struct bgp_evpn_es *es,
841 struct bgpevpn *vpn, struct attr *attr)
842 {
843 struct ecommunity ecom_encap;
844 struct ecommunity_val eval;
845 bgp_encap_types tnl_type;
846 struct listnode *rt_node;
847 struct ecommunity *ecom;
848
849 /* Encap */
850 tnl_type = BGP_ENCAP_TYPE_VXLAN;
851 memset(&ecom_encap, 0, sizeof(ecom_encap));
852 encode_encap_extcomm(tnl_type, &eval);
853 ecom_encap.size = 1;
854 ecom_encap.unit_size = ECOMMUNITY_SIZE;
855 ecom_encap.val = (uint8_t *)eval.val;
856 attr->ecommunity = ecommunity_dup(&ecom_encap);
857
858 /* Add export RTs for the L2-VNI */
859 for (ALL_LIST_ELEMENTS_RO(vpn->export_rtl, rt_node, ecom))
860 attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom);
861
862 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
863 }
864
865 /* Update EVPN EAD (type-1) route -
866 * vpn - valid for EAD-EVI routes and NULL for EAD-ES routes
867 */
868 static int bgp_evpn_type1_route_update(struct bgp *bgp,
869 struct bgp_evpn_es *es, struct bgpevpn *vpn,
870 struct prefix_evpn *p)
871 {
872 int ret = 0;
873 afi_t afi = AFI_L2VPN;
874 safi_t safi = SAFI_EVPN;
875 struct attr attr;
876 struct attr *attr_new = NULL;
877 struct bgp_dest *dest = NULL;
878 struct bgp_path_info *pi = NULL;
879 int route_changed = 0;
880 struct prefix_rd *global_rd;
881
882 memset(&attr, 0, sizeof(struct attr));
883
884 /* Build path-attribute for this route. */
885 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
886 attr.nexthop = es->originator_ip;
887 attr.mp_nexthop_global_in = es->originator_ip;
888 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
889
890 if (vpn) {
891 /* EAD-EVI route update */
892 /* MPLS label */
893 vni2label(vpn->vni, &(attr.label));
894
895 /* Set up extended community */
896 bgp_evpn_type1_evi_route_extcomm_build(es, vpn, &attr);
897
898 /* First, create (or fetch) route node within the VNI. */
899 dest = bgp_node_get(vpn->route_table, (struct prefix *)p);
900
901 /* Create or update route entry. */
902 ret = bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
903 &attr, 1, &pi, &route_changed);
904 if (ret != 0)
905 flog_err(
906 EC_BGP_ES_INVALID,
907 "%u Failed to update EAD-EVI route ESI: %s VNI %u VTEP %pI4",
908 bgp->vrf_id, es->esi_str, vpn->vni,
909 &es->originator_ip);
910 global_rd = &vpn->prd;
911 } else {
912 /* EAD-ES route update */
913 /* MPLS label is 0 for EAD-ES route */
914
915 /* Set up extended community */
916 bgp_evpn_type1_es_route_extcomm_build(es, &attr);
917
918 /* First, create (or fetch) route node within the ES. */
919 /* NOTE: There is no RD here. */
920 /* XXX: fragment ID must be included as a part of the prefix. */
921 dest = bgp_node_get(es->route_table, (struct prefix *)p);
922
923 /* Create or update route entry. */
924 ret = bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
925 &attr, 1, &pi, &route_changed);
926 if (ret != 0) {
927 flog_err(
928 EC_BGP_ES_INVALID,
929 "%u ERROR: Failed to updated EAD-EVI route ESI: %s VTEP %pI4",
930 bgp->vrf_id, es->esi_str, &es->originator_ip);
931 }
932 global_rd = &es->prd;
933 }
934
935
936 assert(pi);
937 attr_new = pi->attr;
938
939 /* Perform route selection;
940 * this is just to set the flags correctly as local route in
941 * the ES always wins.
942 */
943 evpn_route_select_install(bgp, vpn, dest);
944 bgp_dest_unlock_node(dest);
945
946 /* If this is a new route or some attribute has changed, export the
947 * route to the global table. The route will be advertised to peers
948 * from there. Note that this table is a 2-level tree (RD-level +
949 * Prefix-level) similar to L3VPN routes.
950 */
951 if (route_changed) {
952 struct bgp_path_info *global_pi;
953
954 dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
955 p, global_rd);
956 bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
957 attr_new, 1, &global_pi,
958 &route_changed);
959
960 /* Schedule for processing and unlock node. */
961 bgp_process(bgp, dest, afi, safi);
962 bgp_dest_unlock_node(dest);
963 }
964
965 /* Unintern temporary. */
966 aspath_unintern(&attr.aspath);
967 return 0;
968 }
969
970 /* Delete local Type-1 route */
971 static int bgp_evpn_type1_es_route_delete(struct bgp *bgp,
972 struct bgp_evpn_es *es, struct prefix_evpn *p)
973 {
974 return bgp_evpn_mh_route_delete(bgp, es, NULL /* l2vni */, p);
975 }
976
977 static int bgp_evpn_type1_evi_route_delete(struct bgp *bgp,
978 struct bgp_evpn_es *es, struct bgpevpn *vpn,
979 struct prefix_evpn *p)
980 {
981 return bgp_evpn_mh_route_delete(bgp, es, vpn, p);
982 }
983
984 /* Generate EAD-EVI for all VNIs */
985 static void bgp_evpn_local_type1_evi_route_add(struct bgp *bgp,
986 struct bgp_evpn_es *es)
987 {
988 struct listnode *evi_node;
989 struct prefix_evpn p;
990 struct bgp_evpn_es_evi *es_evi;
991
992 if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI))
993 /* EAD-EVI route add for this ES is already done */
994 return;
995
996 SET_FLAG(es->flags, BGP_EVPNES_ADV_EVI);
997 build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
998 &es->esi, es->originator_ip);
999
1000 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, evi_node, es_evi)) {
1001 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
1002 continue;
1003 if (bgp_evpn_type1_route_update(bgp, es, es_evi->vpn, &p))
1004 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
1005 "%u: Type4 route creation failure for ESI %s",
1006 bgp->vrf_id, es->esi_str);
1007 }
1008 }
1009
1010 /*
1011 * Withdraw EAD-EVI for all VNIs
1012 */
1013 static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
1014 struct bgp_evpn_es *es)
1015 {
1016 struct listnode *evi_node;
1017 struct prefix_evpn p;
1018 struct bgp_evpn_es_evi *es_evi;
1019
1020 /* Delete and withdraw locally learnt EAD-EVI route */
1021 if (!CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI))
1022 /* EAD-EVI route has not been advertised for this ES */
1023 return;
1024
1025 UNSET_FLAG(es->flags, BGP_EVPNES_ADV_EVI);
1026 build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
1027 &es->esi, es->originator_ip);
1028 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, evi_node, es_evi)) {
1029 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
1030 continue;
1031 if (bgp_evpn_mh_route_delete(bgp, es, es_evi->vpn, &p))
1032 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
1033 "%u: Type4 route creation failure for ESI %s",
1034 bgp->vrf_id, es->esi_str);
1035 }
1036 }
1037
1038 /*
1039 * Process received EVPN type-1 route (advertise or withdraw).
1040 */
1041 int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
1042 struct attr *attr, uint8_t *pfx, int psize,
1043 uint32_t addpath_id)
1044 {
1045 int ret;
1046 struct prefix_rd prd;
1047 esi_t esi;
1048 uint32_t eth_tag;
1049 mpls_label_t label;
1050 struct in_addr vtep_ip;
1051 struct prefix_evpn p;
1052
1053 if (psize != BGP_EVPN_TYPE1_PSIZE) {
1054 flog_err(EC_BGP_EVPN_ROUTE_INVALID,
1055 "%u:%s - Rx EVPN Type-1 NLRI with invalid length %d",
1056 peer->bgp->vrf_id, peer->host, psize);
1057 return -1;
1058 }
1059
1060 /* Make prefix_rd */
1061 prd.family = AF_UNSPEC;
1062 prd.prefixlen = 64;
1063 memcpy(&prd.val, pfx, RD_BYTES);
1064 pfx += RD_BYTES;
1065
1066 /* get the ESI */
1067 memcpy(&esi, pfx, ESI_BYTES);
1068 pfx += ESI_BYTES;
1069
1070 /* Copy Ethernet Tag */
1071 memcpy(&eth_tag, pfx, EVPN_ETH_TAG_BYTES);
1072 eth_tag = ntohl(eth_tag);
1073 pfx += EVPN_ETH_TAG_BYTES;
1074
1075 memcpy(&label, pfx, BGP_LABEL_BYTES);
1076
1077 /* EAD route prefix doesn't include the nexthop in the global
1078 * table
1079 */
1080 vtep_ip.s_addr = 0;
1081 build_evpn_type1_prefix(&p, eth_tag, &esi, vtep_ip);
1082 /* Process the route. */
1083 if (attr) {
1084 ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
1085 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
1086 &prd, NULL, 0, 0, NULL);
1087 } else {
1088 ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
1089 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
1090 &prd, NULL, 0, NULL);
1091 }
1092 return ret;
1093 }
1094
1095 /*****************************************************************************/
1096 /* Ethernet Segment Management
1097 * 1. Ethernet Segment is a collection of links attached to the same
1098 * server (MHD) or switch (MHN)
1099 * 2. An Ethernet Segment can span multiple PEs and is identified by the
1100 * 10-byte ES-ID.
1101 * 3. Local ESs are configured in zebra and sent to BGP
1102 * 4. Remote ESs are created by BGP when one or more ES-EVIs reference it i.e.
1103 * created on first reference and release on last de-reference
1104 * 5. An ES can be both local and remote. Infact most local ESs are expected
1105 * to have an ES peer.
1106 */
1107
1108 /* A list of remote VTEPs is maintained for each ES. This list includes -
1109 * 1. VTEPs for which we have imported the ESR i.e. ES-peers
1110 * 2. VTEPs that have an "active" ES-EVI VTEP i.e. EAD-per-ES and EAD-per-EVI
1111 * have been imported into one or more VNIs
1112 */
1113 static int bgp_evpn_es_vtep_cmp(void *p1, void *p2)
1114 {
1115 const struct bgp_evpn_es_vtep *es_vtep1 = p1;
1116 const struct bgp_evpn_es_vtep *es_vtep2 = p2;
1117
1118 return es_vtep1->vtep_ip.s_addr - es_vtep2->vtep_ip.s_addr;
1119 }
1120
1121 static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_new(struct bgp_evpn_es *es,
1122 struct in_addr vtep_ip)
1123 {
1124 struct bgp_evpn_es_vtep *es_vtep;
1125
1126 es_vtep = XCALLOC(MTYPE_BGP_EVPN_ES_VTEP, sizeof(*es_vtep));
1127
1128 es_vtep->es = es;
1129 es_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
1130 listnode_init(&es_vtep->es_listnode, es_vtep);
1131 listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode);
1132
1133 return es_vtep;
1134 }
1135
1136 static void bgp_evpn_es_vtep_free(struct bgp_evpn_es_vtep *es_vtep)
1137 {
1138 struct bgp_evpn_es *es = es_vtep->es;
1139
1140 if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR) ||
1141 es_vtep->evi_cnt)
1142 /* as long as there is some reference we can't free it */
1143 return;
1144
1145 list_delete_node(es->es_vtep_list, &es_vtep->es_listnode);
1146 XFREE(MTYPE_BGP_EVPN_ES_VTEP, es_vtep);
1147 }
1148
1149 /* check if VTEP is already part of the list */
1150 static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es,
1151 struct in_addr vtep_ip)
1152 {
1153 struct listnode *node = NULL;
1154 struct bgp_evpn_es_vtep *es_vtep;
1155
1156 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1157 if (es_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
1158 return es_vtep;
1159 }
1160 return NULL;
1161 }
1162
1163 /* Send the remote ES to zebra for NHG programming */
1164 static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
1165 struct bgp_evpn_es_vtep *es_vtep, bool add)
1166 {
1167 struct bgp_evpn_es *es = es_vtep->es;
1168 struct stream *s;
1169 uint32_t flags = 0;
1170
1171 /* Check socket. */
1172 if (!zclient || zclient->sock < 0)
1173 return 0;
1174
1175 /* Don't try to register if Zebra doesn't know of this instance. */
1176 if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
1177 if (BGP_DEBUG(zebra, ZEBRA))
1178 zlog_debug("No zebra instance, not installing remote es %s",
1179 es->esi_str);
1180 return 0;
1181 }
1182
1183 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1184 flags |= ZAPI_ES_VTEP_FLAG_ESR_RXED;
1185
1186 s = zclient->obuf;
1187 stream_reset(s);
1188
1189 zclient_create_header(s,
1190 add ? ZEBRA_REMOTE_ES_VTEP_ADD : ZEBRA_REMOTE_ES_VTEP_DEL,
1191 bgp->vrf_id);
1192 stream_put(s, &es->esi, sizeof(esi_t));
1193 stream_put_ipv4(s, es_vtep->vtep_ip.s_addr);
1194 if (add) {
1195 stream_putl(s, flags);
1196 stream_putc(s, es_vtep->df_alg);
1197 stream_putw(s, es_vtep->df_pref);
1198 }
1199
1200 stream_putw_at(s, 0, stream_get_endp(s));
1201
1202 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1203 zlog_debug("Tx %s Remote ESI %s VTEP %pI4", add ? "ADD" : "DEL",
1204 es->esi_str, &es_vtep->vtep_ip);
1205
1206 return zclient_send_message(zclient);
1207 }
1208
1209 static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
1210 struct bgp_evpn_es_vtep *es_vtep,
1211 bool param_change)
1212 {
1213 bool old_active;
1214 bool new_active;
1215
1216 old_active = !!CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1217 /* currently we need an active EVI reference to use the VTEP as
1218 * a nexthop. this may change...
1219 */
1220 if (es_vtep->evi_cnt)
1221 SET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1222 else
1223 UNSET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1224
1225 new_active = !!CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
1226
1227 if ((old_active != new_active) || (new_active && param_change)) {
1228
1229 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1230 zlog_debug("es %s vtep %pI4 %s df %u/%u",
1231 es_vtep->es->esi_str, &es_vtep->vtep_ip,
1232 new_active ? "active" : "inactive",
1233 es_vtep->df_alg, es_vtep->df_pref);
1234
1235 /* send remote ES to zebra */
1236 bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
1237
1238 /* If VTEP becomes active update the NHG first and then
1239 * the exploded routes. If VTEP becomes inactive update
1240 * routes first. This ordering is done to avoid deleting
1241 * the NHG while there are dependent routes against
1242 * it.
1243 */
1244 if (new_active) {
1245 bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es);
1246 bgp_evpn_es_path_all_update(es_vtep, true /*active*/);
1247 } else {
1248 bgp_evpn_es_path_all_update(es_vtep, false /*active*/);
1249 bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es);
1250 }
1251
1252 /* queue up the es for background consistency checks */
1253 bgp_evpn_es_cons_checks_pend_add(es_vtep->es);
1254 }
1255 }
1256
1257 static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
1258 struct bgp_evpn_es *es,
1259 struct in_addr vtep_ip,
1260 bool esr, uint8_t df_alg,
1261 uint16_t df_pref)
1262 {
1263 struct bgp_evpn_es_vtep *es_vtep;
1264 bool param_change = false;
1265
1266 es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
1267
1268 if (!es_vtep)
1269 es_vtep = bgp_evpn_es_vtep_new(es, vtep_ip);
1270
1271 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1272 zlog_debug("es %s vtep %pI4 add %s df %u/%u",
1273 es_vtep->es->esi_str, &es_vtep->vtep_ip,
1274 esr ? "esr" : "ead", df_alg, df_pref);
1275
1276 if (esr) {
1277 SET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR);
1278 if ((es_vtep->df_pref != df_pref)
1279 || (es_vtep->df_alg != df_alg)) {
1280 param_change = true;
1281 es_vtep->df_pref = df_pref;
1282 es_vtep->df_alg = df_alg;
1283 }
1284 } else {
1285 ++es_vtep->evi_cnt;
1286 }
1287
1288 bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
1289
1290 return es_vtep;
1291 }
1292
1293 static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
1294 struct bgp_evpn_es_vtep *es_vtep, bool esr)
1295 {
1296 bool param_change = false;
1297
1298 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1299 zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str,
1300 &es_vtep->vtep_ip, esr ? "esr" : "ead");
1301 if (esr) {
1302 UNSET_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ESR);
1303 if (es_vtep->df_pref || es_vtep->df_alg) {
1304 param_change = true;
1305 es_vtep->df_pref = 0;
1306 es_vtep->df_alg = 0;
1307 }
1308 } else {
1309 if (es_vtep->evi_cnt)
1310 --es_vtep->evi_cnt;
1311 }
1312
1313 bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
1314 bgp_evpn_es_vtep_free(es_vtep);
1315 }
1316
1317 static void bgp_evpn_es_vtep_del(struct bgp *bgp,
1318 struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr)
1319 {
1320 struct bgp_evpn_es_vtep *es_vtep;
1321
1322 es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
1323 if (es_vtep)
1324 bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
1325 }
1326
1327 bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh)
1328 {
1329 struct bgp_evpn_es *es;
1330 struct bgp_evpn_es_vtep *es_vtep;
1331 struct listnode *node = NULL;
1332 bool rc = false;
1333
1334 if (!memcmp(esi, zero_esi, sizeof(*esi)) || !nh.s_addr)
1335 return true;
1336
1337 es = bgp_evpn_es_find(esi);
1338 if (!es)
1339 return false;
1340
1341 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1342 if (es_vtep->vtep_ip.s_addr == nh.s_addr) {
1343 if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
1344 rc = true;
1345 break;
1346 }
1347 }
1348 return rc;
1349 }
1350
1351 /********************** ES MAC-IP paths *************************************
1352 * MAC-IP routes in the VNI routing table are linked to the destination
1353 * ES for efficient updates on ES changes (such as VTEP add/del).
1354 ****************************************************************************/
1355 void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info)
1356 {
1357 bgp_evpn_path_es_unlink(es_info);
1358 XFREE(MTYPE_BGP_EVPN_PATH_ES_INFO, es_info);
1359 }
1360
1361 static struct bgp_path_es_info *
1362 bgp_evpn_path_es_info_new(struct bgp_path_info *pi, vni_t vni)
1363 {
1364 struct bgp_path_info_extra *e;
1365
1366 e = bgp_path_info_extra_get(pi);
1367
1368 /* If es_info doesn't exist allocate it */
1369 if (!e->es_info) {
1370 e->es_info = XCALLOC(MTYPE_BGP_EVPN_PATH_ES_INFO,
1371 sizeof(struct bgp_path_es_info));
1372 e->es_info->pi = pi;
1373 e->es_info->vni = vni;
1374 }
1375
1376 return e->es_info;
1377 }
1378
1379 void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info)
1380 {
1381 struct bgp_evpn_es *es = es_info->es;
1382 struct bgp_path_info *pi;
1383 char prefix_buf[PREFIX_STRLEN];
1384
1385 if (!es)
1386 return;
1387
1388 pi = es_info->pi;
1389 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1390 zlog_debug(
1391 "path %s unlinked from es %s",
1392 prefix2str(&pi->net->p, prefix_buf, sizeof(prefix_buf)),
1393 es->esi_str);
1394
1395 list_delete_node(es->macip_path_list, &es_info->es_listnode);
1396 es_info->es = NULL;
1397
1398 /* if there are no other references against the ES it
1399 * needs to be freed
1400 */
1401 bgp_evpn_es_free(es, __func__);
1402
1403 /* Note we don't free the path es_info on unlink; it will be freed up
1404 * along with the path.
1405 */
1406 }
1407
1408 void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi)
1409 {
1410 struct bgp_path_es_info *es_info;
1411 struct bgp_evpn_es *es;
1412 struct bgp *bgp_evpn = bgp_get_evpn();
1413 char prefix_buf[PREFIX_STRLEN];
1414
1415 es_info = pi->extra ? pi->extra->es_info : NULL;
1416 /* if the esi is zero just unlink the path from the old es */
1417 if (!esi || !memcmp(esi, zero_esi, sizeof(*esi))) {
1418 if (es_info)
1419 bgp_evpn_path_es_unlink(es_info);
1420 return;
1421 }
1422
1423 if (!bgp_evpn)
1424 return;
1425
1426 /* setup es_info against the path if it doesn't aleady exist */
1427 if (!es_info)
1428 es_info = bgp_evpn_path_es_info_new(pi, vni);
1429
1430 /* find-create ES */
1431 es = bgp_evpn_es_find(esi);
1432 if (!es)
1433 bgp_evpn_es_new(bgp_evpn, esi);
1434
1435 /* dup check */
1436 if (es_info->es == es)
1437 return;
1438
1439 /* unlink old ES if any */
1440 bgp_evpn_path_es_unlink(es_info);
1441
1442 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1443 zlog_debug(
1444 "path %s linked to es %s",
1445 prefix2str(&pi->net->p, prefix_buf, sizeof(prefix_buf)),
1446 es->esi_str);
1447
1448 /* link mac-ip path to the new destination ES */
1449 es_info->es = es;
1450 listnode_init(&es_info->es_listnode, es_info);
1451 listnode_add_sort(es->macip_path_list, &es_info->es_listnode);
1452 }
1453
1454 static void bgp_evpn_es_path_all_update(struct bgp_evpn_es_vtep *es_vtep,
1455 bool active)
1456 {
1457 struct listnode *node;
1458 struct bgp_path_es_info *es_info;
1459 struct bgp_path_info *pi;
1460 struct bgp_path_info *parent_pi;
1461 struct bgp_evpn_es *es = es_vtep->es;
1462 char prefix_buf[PREFIX_STRLEN];
1463
1464 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1465 zlog_debug("update all paths linked to es %s", es->esi_str);
1466
1467 for (ALL_LIST_ELEMENTS_RO(es->macip_path_list, node, es_info)) {
1468 pi = es_info->pi;
1469 if (pi->sub_type != BGP_ROUTE_IMPORTED)
1470 continue;
1471
1472 parent_pi = pi->extra ? pi->extra->parent : NULL;
1473 if (!parent_pi || !parent_pi->attr)
1474 continue;
1475
1476 if (es_vtep->vtep_ip.s_addr != parent_pi->attr->nexthop.s_addr)
1477 continue;
1478
1479 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
1480 zlog_debug("update path %s linked to es %s",
1481 prefix2str(&parent_pi->net->p, prefix_buf,
1482 sizeof(prefix_buf)),
1483 es->esi_str);
1484 bgp_evpn_import_route_in_vrfs(parent_pi, active ? 1 : 0);
1485 }
1486 }
1487
1488 /* compare ES-IDs for the global ES RB tree */
1489 static int bgp_es_rb_cmp(const struct bgp_evpn_es *es1,
1490 const struct bgp_evpn_es *es2)
1491 {
1492 return memcmp(&es1->esi, &es2->esi, ESI_BYTES);
1493 }
1494 RB_GENERATE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp);
1495
1496 struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi)
1497 {
1498 struct bgp_evpn_es tmp;
1499
1500 memcpy(&tmp.esi, esi, sizeof(esi_t));
1501 return RB_FIND(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, &tmp);
1502 }
1503
1504 static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)
1505 {
1506 struct bgp_evpn_es *es;
1507
1508 if (!bgp)
1509 return NULL;
1510
1511 es = XCALLOC(MTYPE_BGP_EVPN_ES, sizeof(struct bgp_evpn_es));
1512
1513 /* set the ESI */
1514 memcpy(&es->esi, esi, sizeof(esi_t));
1515
1516 /* Initialise the VTEP list */
1517 es->es_vtep_list = list_new();
1518 listset_app_node_mem(es->es_vtep_list);
1519 es->es_vtep_list->cmp = bgp_evpn_es_vtep_cmp;
1520
1521 esi_to_str(&es->esi, es->esi_str, sizeof(es->esi_str));
1522
1523 /* Initialize the ES routing table */
1524 es->route_table = bgp_table_init(bgp, AFI_L2VPN, SAFI_EVPN);
1525
1526 /* Add to rb_tree */
1527 if (RB_INSERT(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, es)) {
1528 XFREE(MTYPE_BGP_EVPN_ES, es);
1529 return NULL;
1530 }
1531
1532 /* Initialise the ES-EVI list */
1533 es->es_evi_list = list_new();
1534 listset_app_node_mem(es->es_evi_list);
1535
1536 /* Initialise the ES-VRF list used for L3NHG management */
1537 es->es_vrf_list = list_new();
1538 listset_app_node_mem(es->es_vrf_list);
1539
1540 /* Initialise the route list used for efficient event handling */
1541 es->macip_path_list = list_new();
1542 listset_app_node_mem(es->macip_path_list);
1543
1544 QOBJ_REG(es, bgp_evpn_es);
1545
1546 return es;
1547 }
1548
1549 /* Free a given ES -
1550 * This just frees appropriate memory, caller should have taken other
1551 * needed actions.
1552 */
1553 static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
1554 {
1555 if ((es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE))
1556 || listcount(es->macip_path_list))
1557 return;
1558
1559 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1560 zlog_debug("%s: es %s free", caller, es->esi_str);
1561
1562 /* cleanup resources maintained against the ES */
1563 list_delete(&es->es_evi_list);
1564 list_delete(&es->es_vrf_list);
1565 list_delete(&es->es_vtep_list);
1566 list_delete(&es->macip_path_list);
1567 bgp_table_unlock(es->route_table);
1568
1569 /* remove the entry from various databases */
1570 RB_REMOVE(bgp_es_rb_head, &bgp_mh_info->es_rb_tree, es);
1571 bgp_evpn_es_cons_checks_pend_del(es);
1572
1573 QOBJ_UNREG(es);
1574 XFREE(MTYPE_BGP_EVPN_ES, es);
1575 }
1576
1577 /* init local info associated with the ES */
1578 static void bgp_evpn_es_local_info_set(struct bgp *bgp, struct bgp_evpn_es *es)
1579 {
1580 char buf[BGP_EVPN_PREFIX_RD_LEN];
1581
1582 if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
1583 return;
1584
1585 SET_FLAG(es->flags, BGP_EVPNES_LOCAL);
1586 listnode_init(&es->es_listnode, es);
1587 listnode_add(bgp_mh_info->local_es_list, &es->es_listnode);
1588
1589 /* auto derive RD for this es */
1590 bf_assign_index(bm->rd_idspace, es->rd_id);
1591 es->prd.family = AF_UNSPEC;
1592 es->prd.prefixlen = 64;
1593 snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, es->rd_id);
1594 (void)str2prefix_rd(buf, &es->prd);
1595 }
1596
1597 /* clear any local info associated with the ES */
1598 static void bgp_evpn_es_local_info_clear(struct bgp_evpn_es *es)
1599 {
1600 if (!CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
1601 return;
1602
1603 UNSET_FLAG(es->flags, BGP_EVPNES_LOCAL);
1604
1605 /* remove from the ES local list */
1606 list_delete_node(bgp_mh_info->local_es_list, &es->es_listnode);
1607
1608 bf_release_index(bm->rd_idspace, es->rd_id);
1609
1610 bgp_evpn_es_free(es, __func__);
1611 }
1612
1613 /* eval remote info associated with the ES */
1614 static void bgp_evpn_es_remote_info_re_eval(struct bgp_evpn_es *es)
1615 {
1616 if (es->remote_es_evi_cnt) {
1617 SET_FLAG(es->flags, BGP_EVPNES_REMOTE);
1618 } else {
1619 if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE)) {
1620 UNSET_FLAG(es->flags, BGP_EVPNES_REMOTE);
1621 bgp_evpn_es_free(es, __func__);
1622 }
1623 }
1624 }
1625
1626 /* Process ES link oper-down by withdrawing ES-EAD and ESR */
1627 static void bgp_evpn_local_es_down(struct bgp *bgp,
1628 struct bgp_evpn_es *es)
1629 {
1630 struct prefix_evpn p;
1631 int ret;
1632
1633 if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
1634 return;
1635
1636 UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
1637
1638 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1639 zlog_debug("local es %s down", es->esi_str);
1640
1641 /* withdraw ESR */
1642 /* Delete and withdraw locally learnt ES route */
1643 build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
1644 ret = bgp_evpn_type4_route_delete(bgp, es, &p);
1645 if (ret) {
1646 flog_err(EC_BGP_EVPN_ROUTE_DELETE,
1647 "%u failed to delete type-4 route for ESI %s",
1648 bgp->vrf_id, es->esi_str);
1649 }
1650
1651 /* withdraw EAD-EVI */
1652 if (!bgp_mh_info->ead_evi_adv_for_down_links)
1653 bgp_evpn_local_type1_evi_route_del(bgp, es);
1654
1655 /* withdraw EAD-ES */
1656 build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
1657 &es->esi, es->originator_ip);
1658 ret = bgp_evpn_type1_es_route_delete(bgp, es, &p);
1659 if (ret) {
1660 flog_err(EC_BGP_EVPN_ROUTE_DELETE,
1661 "%u failed to delete type-1 route for ESI %s",
1662 bgp->vrf_id, es->esi_str);
1663 }
1664 }
1665
1666 /* Process ES link oper-up by generating ES-EAD and ESR */
1667 static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
1668 bool regen_esr)
1669 {
1670 struct prefix_evpn p;
1671 bool regen_ead = false;
1672
1673 if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
1674 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1675 zlog_debug("local es %s up", es->esi_str);
1676
1677 SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
1678 regen_esr = true;
1679 regen_ead = true;
1680 }
1681
1682 if (regen_esr) {
1683 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1684 zlog_debug("local es %s generate ESR", es->esi_str);
1685 /* generate ESR */
1686 build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
1687 if (bgp_evpn_type4_route_update(bgp, es, &p))
1688 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
1689 "%u: Type4 route creation failure for ESI %s",
1690 bgp->vrf_id, es->esi_str);
1691 }
1692
1693 if (regen_ead) {
1694 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1695 zlog_debug("local es %s generate EAD", es->esi_str);
1696 /* generate EAD-EVI */
1697 bgp_evpn_local_type1_evi_route_add(bgp, es);
1698
1699 /* generate EAD-ES */
1700 build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG, &es->esi,
1701 es->originator_ip);
1702 bgp_evpn_type1_route_update(bgp, es, NULL, &p);
1703 }
1704 }
1705
1706 static void bgp_evpn_local_es_do_del(struct bgp *bgp, struct bgp_evpn_es *es)
1707 {
1708 struct bgp_evpn_es_evi *es_evi;
1709 struct listnode *evi_node, *evi_next_node;
1710
1711 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1712 zlog_debug("del local es %s", es->esi_str);
1713
1714 /* Delete all local EVPN ES routes from ESI table
1715 * and schedule for processing (to withdraw from peers))
1716 */
1717 bgp_evpn_es_route_del_all(bgp, es);
1718
1719 /* release all local ES EVIs associated with the ES */
1720 for (ALL_LIST_ELEMENTS(es->es_evi_list, evi_node,
1721 evi_next_node, es_evi)) {
1722 bgp_evpn_local_es_evi_do_del(es_evi);
1723 }
1724
1725 /* Clear local info associated with the ES and free it up if there is
1726 * no remote reference
1727 */
1728 bgp_evpn_es_local_info_clear(es);
1729 }
1730
1731 bool bgp_evpn_is_esi_local(esi_t *esi)
1732 {
1733 struct bgp_evpn_es *es = NULL;
1734
1735 /* Lookup ESI hash - should exist. */
1736 es = bgp_evpn_es_find(esi);
1737 return es ? !!(es->flags & BGP_EVPNES_LOCAL) : false;
1738 }
1739
1740 int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi)
1741 {
1742 struct bgp_evpn_es *es = NULL;
1743
1744 /* Lookup ESI hash - should exist. */
1745 es = bgp_evpn_es_find(esi);
1746 if (!es) {
1747 flog_warn(EC_BGP_EVPN_ESI,
1748 "%u: ES %s missing at local ES DEL",
1749 bgp->vrf_id, es->esi_str);
1750 return -1;
1751 }
1752
1753 bgp_evpn_local_es_do_del(bgp, es);
1754 return 0;
1755 }
1756
1757 /* Handle device to ES id association. Results in the creation of a local
1758 * ES.
1759 */
1760 int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
1761 struct in_addr originator_ip, bool oper_up,
1762 uint16_t df_pref)
1763 {
1764 char buf[ESI_STR_LEN];
1765 struct bgp_evpn_es *es;
1766 bool new_es = true;
1767 bool regen_esr = false;
1768
1769 /* create the new es */
1770 es = bgp_evpn_es_find(esi);
1771 if (es) {
1772 if (CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL))
1773 new_es = false;
1774 } else {
1775 es = bgp_evpn_es_new(bgp, esi);
1776 if (!es) {
1777 flog_err(EC_BGP_ES_CREATE,
1778 "%u: Failed to allocate ES entry for ESI %s - at Local ES Add",
1779 bgp->vrf_id, esi_to_str(esi, buf, sizeof(buf)));
1780 return -1;
1781 }
1782 }
1783
1784 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1785 zlog_debug("add local es %s orig-ip %pI4 df_pref %u", es->esi_str,
1786 &originator_ip, df_pref);
1787
1788 es->originator_ip = originator_ip;
1789 if (df_pref != es->df_pref) {
1790 es->df_pref = df_pref;
1791 regen_esr = true;
1792 }
1793 bgp_evpn_es_local_info_set(bgp, es);
1794
1795 /* import all remote Type-4 routes in the ES table */
1796 if (new_es)
1797 bgp_evpn_type4_remote_routes_import(bgp, es,
1798 true /* install */);
1799
1800 /* create and advertise EAD-EVI routes for the ES -
1801 * XXX - till an ES-EVI reference is created there is really nothing to
1802 * advertise
1803 */
1804 if (bgp_mh_info->ead_evi_adv_for_down_links)
1805 bgp_evpn_local_type1_evi_route_add(bgp, es);
1806
1807 /* If the ES link is operationally up generate EAD-ES. EAD-EVI
1808 * can be generated even if the link is inactive.
1809 */
1810 if (oper_up)
1811 bgp_evpn_local_es_up(bgp, es, regen_esr);
1812 else
1813 bgp_evpn_local_es_down(bgp, es);
1814
1815 return 0;
1816 }
1817
1818 static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
1819 uint8_t vtep_str_size)
1820 {
1821 char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
1822 struct listnode *node;
1823 struct bgp_evpn_es_vtep *es_vtep;
1824 bool first = true;
1825 char ip_buf[INET6_ADDRSTRLEN];
1826
1827 vtep_str[0] = '\0';
1828 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1829 vtep_flag_str[0] = '\0';
1830
1831 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1832 strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
1833 if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
1834 strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
1835
1836 if (!strlen(vtep_flag_str))
1837 strlcat(vtep_flag_str, "-", sizeof(vtep_flag_str));
1838 if (first)
1839 first = false;
1840 else
1841 strlcat(vtep_str, ",", vtep_str_size);
1842 strlcat(vtep_str,
1843 inet_ntop(AF_INET, &es_vtep->vtep_ip, ip_buf,
1844 sizeof(ip_buf)),
1845 vtep_str_size);
1846 strlcat(vtep_str, "(", vtep_str_size);
1847 strlcat(vtep_str, vtep_flag_str, vtep_str_size);
1848 strlcat(vtep_str, ")", vtep_str_size);
1849 }
1850
1851 return vtep_str;
1852 }
1853
1854 static void bgp_evpn_es_json_vtep_fill(json_object *json_vteps,
1855 struct bgp_evpn_es_vtep *es_vtep)
1856 {
1857 json_object *json_vtep_entry;
1858 json_object *json_flags;
1859 char ip_buf[INET6_ADDRSTRLEN];
1860
1861 json_vtep_entry = json_object_new_object();
1862
1863 json_object_string_add(
1864 json_vtep_entry, "vtep_ip",
1865 inet_ntop(AF_INET, &es_vtep->vtep_ip, ip_buf, sizeof(ip_buf)));
1866 if (es_vtep->flags & (BGP_EVPNES_VTEP_ESR |
1867 BGP_EVPNES_VTEP_ACTIVE)) {
1868 json_flags = json_object_new_array();
1869 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1870 json_array_string_add(json_flags, "esr");
1871 if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
1872 json_array_string_add(json_flags, "active");
1873 json_object_object_add(json_vtep_entry, "flags", json_flags);
1874 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR) {
1875 json_object_int_add(json_vtep_entry, "dfPreference",
1876 es_vtep->df_pref);
1877 json_object_int_add(json_vtep_entry, "dfAlgorithm",
1878 es_vtep->df_pref);
1879 }
1880 }
1881
1882 json_object_array_add(json_vteps,
1883 json_vtep_entry);
1884 }
1885
1886 static void bgp_evpn_es_vteps_show_detail(struct vty *vty,
1887 struct bgp_evpn_es *es)
1888 {
1889 char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
1890 struct listnode *node;
1891 struct bgp_evpn_es_vtep *es_vtep;
1892 char alg_buf[EVPN_DF_ALG_STR_LEN];
1893
1894 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1895 vtep_flag_str[0] = '\0';
1896 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1897 strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
1898 if (es_vtep->flags & BGP_EVPNES_VTEP_ACTIVE)
1899 strlcat(vtep_flag_str, "A", sizeof(vtep_flag_str));
1900
1901 if (!strlen(vtep_flag_str))
1902 strlcat(vtep_flag_str, "-", sizeof(vtep_flag_str));
1903
1904 vty_out(vty, " %pI4 flags: %s", &es_vtep->vtep_ip,
1905 vtep_flag_str);
1906
1907 if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
1908 vty_out(vty, " df_alg: %s df_pref: %u\n",
1909 evpn_es_df_alg2str(es_vtep->df_alg, alg_buf,
1910 sizeof(alg_buf)),
1911 es_vtep->df_pref);
1912 else
1913 vty_out(vty, "\n");
1914 }
1915 }
1916
1917 static void bgp_evpn_es_show_entry(struct vty *vty,
1918 struct bgp_evpn_es *es, json_object *json)
1919 {
1920 char buf1[RD_ADDRSTRLEN];
1921 struct listnode *node;
1922 struct bgp_evpn_es_vtep *es_vtep;
1923
1924 if (json) {
1925 json_object *json_vteps;
1926 json_object *json_types;
1927
1928 json_object_string_add(json, "esi", es->esi_str);
1929 json_object_string_add(json, "rd",
1930 prefix_rd2str(&es->prd, buf1,
1931 sizeof(buf1)));
1932
1933 if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) {
1934 json_types = json_object_new_array();
1935 if (es->flags & BGP_EVPNES_LOCAL)
1936 json_array_string_add(json_types, "local");
1937 if (es->flags & BGP_EVPNES_REMOTE)
1938 json_array_string_add(json_types, "remote");
1939 json_object_object_add(json, "type", json_types);
1940 }
1941
1942 if (listcount(es->es_vtep_list)) {
1943 json_vteps = json_object_new_array();
1944 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list,
1945 node, es_vtep)) {
1946 bgp_evpn_es_json_vtep_fill(json_vteps, es_vtep);
1947 }
1948 json_object_object_add(json, "vteps", json_vteps);
1949 }
1950 json_object_int_add(json, "vniCount",
1951 listcount(es->es_evi_list));
1952 } else {
1953 char type_str[4];
1954 char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
1955
1956 type_str[0] = '\0';
1957 if (es->flags & BGP_EVPNES_LOCAL)
1958 strlcat(type_str, "L", sizeof(type_str));
1959 if (es->flags & BGP_EVPNES_REMOTE)
1960 strlcat(type_str, "R", sizeof(type_str));
1961 if (es->inconsistencies)
1962 strlcat(type_str, "I", sizeof(type_str));
1963
1964 bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str));
1965
1966 if (es->flags & BGP_EVPNES_LOCAL)
1967 prefix_rd2str(&es->prd, buf1, sizeof(buf1));
1968 else
1969 strlcpy(buf1, "-", sizeof(buf1));
1970
1971 vty_out(vty, "%-30s %-5s %-21s %-8d %s\n",
1972 es->esi_str, type_str, buf1,
1973 listcount(es->es_evi_list), vtep_str);
1974 }
1975 }
1976
1977 static void bgp_evpn_es_show_entry_detail(struct vty *vty,
1978 struct bgp_evpn_es *es, json_object *json)
1979 {
1980 char ip_buf[INET6_ADDRSTRLEN];
1981
1982 if (json) {
1983 json_object *json_flags;
1984 json_object *json_incons;
1985 json_object *json_vteps;
1986 struct listnode *node;
1987 struct bgp_evpn_es_vtep *es_vtep;
1988
1989 /* Add the "brief" info first */
1990 bgp_evpn_es_show_entry(vty, es, json);
1991 if (es->flags & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI)) {
1992 json_flags = json_object_new_array();
1993 if (es->flags & BGP_EVPNES_OPER_UP)
1994 json_array_string_add(json_flags, "up");
1995 if (es->flags & BGP_EVPNES_ADV_EVI)
1996 json_array_string_add(json_flags,
1997 "advertiseEVI");
1998 json_object_object_add(json, "flags", json_flags);
1999 }
2000 json_object_string_add(json, "originator_ip",
2001 inet_ntop(AF_INET, &es->originator_ip,
2002 ip_buf, sizeof(ip_buf)));
2003 json_object_int_add(json, "remoteVniCount",
2004 es->remote_es_evi_cnt);
2005 json_object_int_add(json, "inconsistentVniVtepCount",
2006 es->incons_evi_vtep_cnt);
2007 if (listcount(es->es_vtep_list)) {
2008 json_vteps = json_object_new_array();
2009 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node,
2010 es_vtep)) {
2011 bgp_evpn_es_json_vtep_fill(json_vteps, es_vtep);
2012 }
2013 json_object_object_add(json, "vteps", json_vteps);
2014 }
2015 if (es->inconsistencies) {
2016 json_incons = json_object_new_array();
2017 if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
2018 json_array_string_add(json_incons,
2019 "vni-vtep-mismatch");
2020 json_object_object_add(json, "inconsistencies",
2021 json_incons);
2022 }
2023 } else {
2024 char incons_str[BGP_EVPNES_INCONS_STR_SZ];
2025 char type_str[4];
2026 char buf1[RD_ADDRSTRLEN];
2027
2028 type_str[0] = '\0';
2029 if (es->flags & BGP_EVPNES_LOCAL)
2030 strlcat(type_str, "L", sizeof(type_str));
2031 if (es->flags & BGP_EVPNES_REMOTE)
2032 strlcat(type_str, "R", sizeof(type_str));
2033
2034 if (es->flags & BGP_EVPNES_LOCAL)
2035 prefix_rd2str(&es->prd, buf1, sizeof(buf1));
2036 else
2037 strlcpy(buf1, "-", sizeof(buf1));
2038
2039 vty_out(vty, "ESI: %s\n", es->esi_str);
2040 vty_out(vty, " Type: %s\n", type_str);
2041 vty_out(vty, " RD: %s\n", buf1);
2042 vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);
2043 if (es->flags & BGP_EVPNES_LOCAL)
2044 vty_out(vty, " Local ES DF preference: %u\n",
2045 es->df_pref);
2046 vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
2047 vty_out(vty, " Remote VNI Count: %d\n",
2048 es->remote_es_evi_cnt);
2049 vty_out(vty, " Inconsistent VNI VTEP Count: %d\n",
2050 es->incons_evi_vtep_cnt);
2051 if (es->inconsistencies) {
2052 incons_str[0] = '\0';
2053 if (es->inconsistencies & BGP_EVPNES_INCONS_VTEP_LIST)
2054 strlcat(incons_str, "vni-vtep-mismatch",
2055 sizeof(incons_str));
2056 } else {
2057 strlcpy(incons_str, "-", sizeof(incons_str));
2058 }
2059 vty_out(vty, " Inconsistencies: %s\n",
2060 incons_str);
2061 if (listcount(es->es_vtep_list)) {
2062 vty_out(vty, " VTEPs:\n");
2063 bgp_evpn_es_vteps_show_detail(vty, es);
2064 }
2065 vty_out(vty, "\n");
2066 }
2067 }
2068
2069 /* Display all ESs */
2070 void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail)
2071 {
2072 struct bgp_evpn_es *es;
2073 json_object *json_array = NULL;
2074 json_object *json = NULL;
2075
2076 if (uj) {
2077 /* create an array of ESs */
2078 json_array = json_object_new_array();
2079 } else {
2080 if (!detail) {
2081 vty_out(vty,
2082 "ES Flags: L local, R remote, I inconsistent\n");
2083 vty_out(vty,
2084 "VTEP Flags: E ESR/Type-4, A active nexthop\n");
2085 vty_out(vty,
2086 "%-30s %-5s %-21s %-8s %s\n",
2087 "ESI", "Flags", "RD", "#VNIs", "VTEPs");
2088 }
2089 }
2090
2091 RB_FOREACH(es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
2092 if (uj)
2093 /* create a separate json object for each ES */
2094 json = json_object_new_object();
2095 if (detail)
2096 bgp_evpn_es_show_entry_detail(vty, es, json);
2097 else
2098 bgp_evpn_es_show_entry(vty, es, json);
2099 /* add ES to the json array */
2100 if (uj)
2101 json_object_array_add(json_array, json);
2102 }
2103
2104 /* print the array of json-ESs */
2105 if (uj) {
2106 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2107 json_array, JSON_C_TO_STRING_PRETTY));
2108 json_object_free(json_array);
2109 }
2110 }
2111
2112 /* Display specific ES */
2113 void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj)
2114 {
2115 struct bgp_evpn_es *es;
2116 json_object *json = NULL;
2117
2118 if (uj)
2119 json = json_object_new_object();
2120
2121 es = bgp_evpn_es_find(esi);
2122 if (es) {
2123 bgp_evpn_es_show_entry_detail(vty, es, json);
2124 } else {
2125 if (!uj)
2126 vty_out(vty, "ESI not found\n");
2127 }
2128
2129 if (uj) {
2130 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2131 json, JSON_C_TO_STRING_PRETTY));
2132 json_object_free(json);
2133 }
2134 }
2135
2136 /*****************************************************************************/
2137 /* Ethernet Segment to VRF association -
2138 * 1. Each ES-EVI entry is associated with a tenant VRF. This associaton
2139 * triggers the creation of an ES-VRF entry.
2140 * 2. The ES-VRF entry is maintained for the purpose of L3-NHG creation
2141 * 3. Type-2/MAC-IP routes are imported into a tenant VRF and programmed as
2142 * a /32 or host route entry in the dataplane. If the destination of
2143 * the host route is a remote-ES the route is programmed with the
2144 * corresponding (keyed in by {vrf,ES-id}) L3-NHG.
2145 * 4. The reason for this indirection (route->L3-NHG, L3-NHG->list-of-VTEPs)
2146 * is to avoid route updates to the dplane when a remote-ES link flaps i.e.
2147 * instead of updating all the dependent routes the NHG's contents are updated.
2148 * This reduces the amount of datplane updates (nhg updates vs. route updates)
2149 * allowing for a faster failover.
2150 *
2151 * XXX - can the L3 SVI index change without change in vpn->bgp_vrf
2152 * association? If yes we need to handle that by updating all the L3 NHGs
2153 * in that VRF.
2154 */
2155 /******************************** L3 NHG management *************************/
2156 static void bgp_evpn_l3nhg_zebra_add(struct bgp_evpn_es_vrf *es_vrf)
2157 {
2158 uint32_t nh_cnt = 0;
2159 struct listnode *node;
2160 struct bgp_evpn_es_vtep *es_vtep;
2161 struct bgp_evpn_es *es = es_vrf->es;
2162
2163 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2164 zlog_debug("es %s vrf %u nhg 0x%x to zebra", es->esi_str,
2165 es_vrf->bgp_vrf->vrf_id, es_vrf->nhg_id);
2166 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
2167 if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE)) {
2168 ++nh_cnt;
2169 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2170 zlog_debug("nhg 0x%x vtep %pI4 dev 0x%x",
2171 es_vrf->nhg_id, &es_vtep->vtep_ip,
2172 es_vrf->bgp_vrf->l3vni_svi_ifindex);
2173 }
2174 }
2175
2176 /* XXX - program NHG in zebra */
2177 }
2178
2179 static void bgp_evpn_l3nhg_zebra_del(struct bgp_evpn_es_vrf *es_vrf)
2180 {
2181 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2182 zlog_debug("es %s vrf %u nhg 0x%x to zebra",
2183 es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2184 es_vrf->nhg_id);
2185
2186 /* XXX - program NHG in zebra */
2187 }
2188
2189 static void bgp_evpn_l3nhg_deactivate(struct bgp_evpn_es_vrf *es_vrf)
2190 {
2191 if (!(es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE))
2192 return;
2193
2194 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2195 zlog_debug("es %s vrf %u nhg 0x%x de-activate",
2196 es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2197 es_vrf->nhg_id);
2198 bgp_evpn_l3nhg_zebra_del(es_vrf);
2199 es_vrf->flags &= ~BGP_EVPNES_VRF_NHG_ACTIVE;
2200 }
2201
2202 static void bgp_evpn_l3nhg_activate(struct bgp_evpn_es_vrf *es_vrf, bool update)
2203 {
2204 if (!bgp_evpn_es_get_active_vtep_cnt(es_vrf->es)) {
2205 bgp_evpn_l3nhg_deactivate(es_vrf);
2206 return;
2207 }
2208
2209 if (es_vrf->flags & BGP_EVPNES_VRF_NHG_ACTIVE) {
2210 if (!update)
2211 return;
2212 } else {
2213 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2214 zlog_debug("es %s vrf %u nhg 0x%x activate",
2215 es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id,
2216 es_vrf->nhg_id);
2217 es_vrf->flags |= BGP_EVPNES_VRF_NHG_ACTIVE;
2218 }
2219
2220 bgp_evpn_l3nhg_zebra_add(es_vrf);
2221 }
2222
2223 /* when a VTEP is activated or de-activated against an ES associated
2224 * VRFs' NHG needs to be updated
2225 */
2226 static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es)
2227 {
2228 struct bgp_evpn_es_vrf *es_vrf;
2229 struct listnode *es_vrf_node;
2230
2231 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2232 zlog_debug("es %s nhg update on vtep chg", es->esi_str);
2233
2234 for (ALL_LIST_ELEMENTS_RO(es->es_vrf_list, es_vrf_node, es_vrf))
2235 bgp_evpn_l3nhg_activate(es_vrf, true /* update */);
2236 }
2237
2238 /* compare ES-IDs for the ES-VRF RB tree maintained per-VRF */
2239 static int bgp_es_vrf_rb_cmp(const struct bgp_evpn_es_vrf *es_vrf1,
2240 const struct bgp_evpn_es_vrf *es_vrf2)
2241 {
2242 return memcmp(&es_vrf1->es->esi, &es_vrf2->es->esi, ESI_BYTES);
2243 }
2244 RB_GENERATE(bgp_es_vrf_rb_head, bgp_evpn_es_vrf, rb_node, bgp_es_vrf_rb_cmp);
2245
2246 /* Initialize the ES tables maintained per-tenant vrf */
2247 void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf)
2248 {
2249 /* Initialize the ES-VRF RB tree */
2250 RB_INIT(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree);
2251 }
2252
2253 /* find the ES-VRF in the per-VRF RB tree */
2254 static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_find(struct bgp_evpn_es *es,
2255 struct bgp *bgp_vrf)
2256 {
2257 struct bgp_evpn_es_vrf es_vrf;
2258
2259 es_vrf.es = es;
2260
2261 return RB_FIND(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, &es_vrf);
2262 }
2263
2264 /* allocate a new ES-VRF and setup L3NHG for it */
2265 static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_create(struct bgp_evpn_es *es,
2266 struct bgp *bgp_vrf)
2267 {
2268 struct bgp_evpn_es_vrf *es_vrf;
2269
2270 es_vrf = XCALLOC(MTYPE_BGP_EVPN_ES_VRF, sizeof(*es_vrf));
2271
2272 es_vrf->es = es;
2273 es_vrf->bgp_vrf = bgp_vrf;
2274
2275 /* insert into the VRF-ESI rb tree */
2276 if (RB_INSERT(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, es_vrf)) {
2277 XFREE(MTYPE_BGP_EVPN_ES_VRF, es_vrf);
2278 return NULL;
2279 }
2280
2281 /* add to the ES's VRF list */
2282 listnode_init(&es_vrf->es_listnode, es_vrf);
2283 listnode_add(es->es_vrf_list, &es_vrf->es_listnode);
2284
2285 /* setup the L3 NHG id for the ES */
2286 es_vrf->nhg_id = bgp_l3nhg_id_alloc();
2287 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2288 zlog_debug("es %s vrf %u nhg 0x%x create", es->esi_str,
2289 bgp_vrf->vrf_id, es_vrf->nhg_id);
2290 bgp_evpn_l3nhg_activate(es_vrf, false /* update */);
2291
2292 return es_vrf;
2293 }
2294
2295 /* remove the L3-NHG associated with the ES-VRF and free it */
2296 static void bgp_evpn_es_vrf_delete(struct bgp_evpn_es_vrf *es_vrf)
2297 {
2298 struct bgp_evpn_es *es = es_vrf->es;
2299 struct bgp *bgp_vrf = es_vrf->bgp_vrf;
2300
2301 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2302 zlog_debug("es %s vrf %u nhg 0x%x delete", es->esi_str,
2303 bgp_vrf->vrf_id, es_vrf->nhg_id);
2304
2305 /* Remove the NHG resources */
2306 bgp_evpn_l3nhg_deactivate(es_vrf);
2307 if (es_vrf->nhg_id)
2308 bgp_l3nhg_id_free(es_vrf->nhg_id);
2309 es_vrf->nhg_id = 0;
2310
2311 /* remove from the ES's VRF list */
2312 list_delete_node(es->es_vrf_list, &es_vrf->es_listnode);
2313
2314 /* remove from the VRF-ESI rb tree */
2315 RB_REMOVE(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, es_vrf);
2316
2317 XFREE(MTYPE_BGP_EVPN_ES_VRF, es_vrf);
2318 }
2319
2320 /* deref and delete if there are no references */
2321 void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi)
2322 {
2323 struct bgp_evpn_es_vrf *es_vrf = es_evi->es_vrf;
2324
2325 if (!es_vrf)
2326 return;
2327
2328 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2329 zlog_debug("es-evi %s vni %u vrf %u de-ref",
2330 es_evi->es->esi_str, es_evi->vpn->vni,
2331 es_vrf->bgp_vrf->vrf_id);
2332
2333 es_evi->es_vrf = NULL;
2334 if (es_vrf->ref_cnt)
2335 --es_vrf->ref_cnt;
2336
2337 if (!es_vrf->ref_cnt)
2338 bgp_evpn_es_vrf_delete(es_vrf);
2339 }
2340
2341 /* find or create and reference */
2342 void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi, struct bgp *bgp_vrf)
2343 {
2344 struct bgp_evpn_es *es = es_evi->es;
2345 struct bgp_evpn_es_vrf *es_vrf = es_evi->es_vrf;
2346 struct bgp *old_bgp_vrf = NULL;
2347
2348 if (es_vrf)
2349 old_bgp_vrf = es_vrf->bgp_vrf;
2350
2351 if (old_bgp_vrf == bgp_vrf)
2352 return;
2353
2354 /* deref the old ES-VRF */
2355 bgp_evpn_es_vrf_deref(es_evi);
2356
2357 if (!bgp_vrf)
2358 return;
2359
2360 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2361 zlog_debug("es-evi %s vni %u vrf %u ref", es_evi->es->esi_str,
2362 es_evi->vpn->vni, bgp_vrf->vrf_id);
2363
2364 /* find-create the new ES-VRF */
2365 es_vrf = bgp_evpn_es_vrf_find(es, bgp_vrf);
2366 if (!es_vrf)
2367 es_vrf = bgp_evpn_es_vrf_create(es, bgp_vrf);
2368 if (!es_vrf)
2369 return;
2370
2371 es_evi->es_vrf = es_vrf;
2372 ++es_vrf->ref_cnt;
2373 }
2374
2375 /* When the L2-VNI is associated with a L3-VNI/VRF update all the
2376 * associated ES-EVI entries
2377 */
2378 void bgp_evpn_es_evi_vrf_deref(struct bgpevpn *vpn)
2379 {
2380 struct bgp_evpn_es_evi *es_evi;
2381
2382 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2383 zlog_debug("es-vrf de-ref for vni %u", vpn->vni);
2384
2385 RB_FOREACH (es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree)
2386 bgp_evpn_es_vrf_deref(es_evi);
2387 }
2388 void bgp_evpn_es_evi_vrf_ref(struct bgpevpn *vpn)
2389 {
2390 struct bgp_evpn_es_evi *es_evi;
2391
2392 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2393 zlog_debug("es-vrf ref for vni %u", vpn->vni);
2394
2395 RB_FOREACH (es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree)
2396 bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf);
2397 }
2398
2399 /*****************************************************************************/
2400 /* Ethernet Segment to EVI association -
2401 * 1. The ES-EVI entry is maintained as a RB tree per L2-VNI
2402 * (bgpevpn->es_evi_rb_tree).
2403 * 2. Each local ES-EVI entry is rxed from zebra and then used by BGP to
2404 * advertises an EAD-EVI (Type-1 EVPN) route
2405 * 3. The remote ES-EVI is created when a bgp_evpn_es_evi_vtep references
2406 * it.
2407 */
2408
2409 /* A list of remote VTEPs is maintained for each ES-EVI. This list includes -
2410 * 1. VTEPs for which we have imported the EAD-per-ES Type1 route
2411 * 2. VTEPs for which we have imported the EAD-per-EVI Type1 route
2412 * VTEPs for which both routes have been rxed are activated. Activation
2413 * creates a NHG in the parent ES.
2414 */
2415 static int bgp_evpn_es_evi_vtep_cmp(void *p1, void *p2)
2416 {
2417 const struct bgp_evpn_es_evi_vtep *evi_vtep1 = p1;
2418 const struct bgp_evpn_es_evi_vtep *evi_vtep2 = p2;
2419
2420 return evi_vtep1->vtep_ip.s_addr - evi_vtep2->vtep_ip.s_addr;
2421 }
2422
2423 static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_new(
2424 struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip)
2425 {
2426 struct bgp_evpn_es_evi_vtep *evi_vtep;
2427
2428 evi_vtep = XCALLOC(MTYPE_BGP_EVPN_ES_EVI_VTEP, sizeof(*evi_vtep));
2429
2430 evi_vtep->es_evi = es_evi;
2431 evi_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
2432 listnode_init(&evi_vtep->es_evi_listnode, evi_vtep);
2433 listnode_add_sort(es_evi->es_evi_vtep_list, &evi_vtep->es_evi_listnode);
2434
2435 return evi_vtep;
2436 }
2437
2438 static void bgp_evpn_es_evi_vtep_free(struct bgp_evpn_es_evi_vtep *evi_vtep)
2439 {
2440 struct bgp_evpn_es_evi *es_evi = evi_vtep->es_evi;
2441
2442 if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD))
2443 /* as long as there is some reference we can't free it */
2444 return;
2445
2446 list_delete_node(es_evi->es_evi_vtep_list, &evi_vtep->es_evi_listnode);
2447 XFREE(MTYPE_BGP_EVPN_ES_EVI_VTEP, evi_vtep);
2448 }
2449
2450 /* check if VTEP is already part of the list */
2451 static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find(
2452 struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip)
2453 {
2454 struct listnode *node = NULL;
2455 struct bgp_evpn_es_evi_vtep *evi_vtep;
2456
2457 for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
2458 if (evi_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
2459 return evi_vtep;
2460 }
2461 return NULL;
2462 }
2463
2464 /* A VTEP can be added as "active" attach to an ES if EAD-per-ES and
2465 * EAD-per-EVI routes are rxed from it.
2466 */
2467 static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
2468 struct bgp_evpn_es_evi_vtep *evi_vtep)
2469 {
2470 bool old_active;
2471 bool new_active;
2472
2473 old_active = !!CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
2474
2475 /* Both EAD-per-ES and EAD-per-EVI routes must be rxed from a PE
2476 * before it can be activated.
2477 */
2478 if ((evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD) ==
2479 BGP_EVPN_EVI_VTEP_EAD)
2480 SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
2481 else
2482 UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
2483
2484 new_active = !!CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
2485
2486 if (old_active == new_active)
2487 return;
2488
2489 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2490 zlog_debug("es %s evi %u vtep %pI4 %s",
2491 evi_vtep->es_evi->es->esi_str,
2492 evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
2493 new_active ? "active" : "inactive");
2494
2495 /* add VTEP to parent es */
2496 if (new_active) {
2497 struct bgp_evpn_es_vtep *es_vtep;
2498
2499 es_vtep = bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es,
2500 evi_vtep->vtep_ip, false /*esr*/,
2501 0, 0);
2502 evi_vtep->es_vtep = es_vtep;
2503 } else {
2504 if (evi_vtep->es_vtep) {
2505 bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
2506 false /*esr*/);
2507 evi_vtep->es_vtep = NULL;
2508 }
2509 }
2510 /* queue up the parent es for background consistency checks */
2511 bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es);
2512 }
2513
2514 static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
2515 struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
2516 bool ead_es)
2517 {
2518 struct bgp_evpn_es_evi_vtep *evi_vtep;
2519
2520 evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
2521
2522 if (!evi_vtep)
2523 evi_vtep = bgp_evpn_es_evi_vtep_new(es_evi, vtep_ip);
2524
2525 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2526 zlog_debug("add es %s evi %u vtep %pI4 %s",
2527 evi_vtep->es_evi->es->esi_str,
2528 evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
2529 ead_es ? "ead_es" : "ead_evi");
2530
2531 if (ead_es)
2532 SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
2533 else
2534 SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
2535
2536 bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
2537 }
2538
2539 static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
2540 struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
2541 bool ead_es)
2542 {
2543 struct bgp_evpn_es_evi_vtep *evi_vtep;
2544
2545 evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
2546 if (!evi_vtep)
2547 return;
2548
2549 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2550 zlog_debug("del es %s evi %u vtep %pI4 %s",
2551 evi_vtep->es_evi->es->esi_str,
2552 evi_vtep->es_evi->vpn->vni, &evi_vtep->vtep_ip,
2553 ead_es ? "ead_es" : "ead_evi");
2554
2555 if (ead_es)
2556 UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_ES);
2557 else
2558 UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
2559
2560 bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
2561 bgp_evpn_es_evi_vtep_free(evi_vtep);
2562 }
2563
2564 /* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */
2565 static int bgp_es_evi_rb_cmp(const struct bgp_evpn_es_evi *es_evi1,
2566 const struct bgp_evpn_es_evi *es_evi2)
2567 {
2568 return memcmp(&es_evi1->es->esi, &es_evi2->es->esi, ESI_BYTES);
2569 }
2570 RB_GENERATE(bgp_es_evi_rb_head, bgp_evpn_es_evi, rb_node, bgp_es_evi_rb_cmp);
2571
2572 /* find the ES-EVI in the per-L2-VNI RB tree */
2573 static struct bgp_evpn_es_evi *bgp_evpn_es_evi_find(struct bgp_evpn_es *es,
2574 struct bgpevpn *vpn)
2575 {
2576 struct bgp_evpn_es_evi es_evi;
2577
2578 es_evi.es = es;
2579
2580 return RB_FIND(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, &es_evi);
2581 }
2582
2583 /* allocate a new ES-EVI and insert it into the per-L2-VNI and per-ES
2584 * tables.
2585 */
2586 static struct bgp_evpn_es_evi *bgp_evpn_es_evi_new(struct bgp_evpn_es *es,
2587 struct bgpevpn *vpn)
2588 {
2589 struct bgp_evpn_es_evi *es_evi;
2590
2591 es_evi = XCALLOC(MTYPE_BGP_EVPN_ES_EVI, sizeof(*es_evi));
2592
2593 es_evi->es = es;
2594 es_evi->vpn = vpn;
2595
2596 /* Initialise the VTEP list */
2597 es_evi->es_evi_vtep_list = list_new();
2598 listset_app_node_mem(es_evi->es_evi_vtep_list);
2599 es_evi->es_evi_vtep_list->cmp = bgp_evpn_es_evi_vtep_cmp;
2600
2601 /* insert into the VNI-ESI rb tree */
2602 if (RB_INSERT(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, es_evi)) {
2603 XFREE(MTYPE_BGP_EVPN_ES_EVI, es_evi);
2604 return NULL;
2605 }
2606
2607 /* add to the ES's VNI list */
2608 listnode_init(&es_evi->es_listnode, es_evi);
2609 listnode_add(es->es_evi_list, &es_evi->es_listnode);
2610
2611 bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf);
2612
2613 return es_evi;
2614 }
2615
2616 /* remove the ES-EVI from the per-L2-VNI and per-ES tables and free
2617 * up the memory.
2618 */
2619 static void bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi)
2620 {
2621 struct bgp_evpn_es *es = es_evi->es;
2622 struct bgpevpn *vpn = es_evi->vpn;
2623
2624 /* cannot free the element as long as there is a local or remote
2625 * reference
2626 */
2627 if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL | BGP_EVPNES_EVI_REMOTE))
2628 return;
2629
2630 bgp_evpn_es_vrf_deref(es_evi);
2631
2632 /* remove from the ES's VNI list */
2633 list_delete_node(es->es_evi_list, &es_evi->es_listnode);
2634
2635 /* remove from the VNI-ESI rb tree */
2636 RB_REMOVE(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree, es_evi);
2637
2638 /* free the VTEP list */
2639 list_delete(&es_evi->es_evi_vtep_list);
2640
2641 /* remove from the VNI-ESI rb tree */
2642 XFREE(MTYPE_BGP_EVPN_ES_EVI, es_evi);
2643 }
2644
2645 /* init local info associated with the ES-EVI */
2646 static void bgp_evpn_es_evi_local_info_set(struct bgp_evpn_es_evi *es_evi)
2647 {
2648 struct bgpevpn *vpn = es_evi->vpn;
2649
2650 if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
2651 return;
2652
2653 SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL);
2654 listnode_init(&es_evi->l2vni_listnode, es_evi);
2655 listnode_add(vpn->local_es_evi_list, &es_evi->l2vni_listnode);
2656 }
2657
2658 /* clear any local info associated with the ES-EVI */
2659 static void bgp_evpn_es_evi_local_info_clear(struct bgp_evpn_es_evi *es_evi)
2660 {
2661 struct bgpevpn *vpn = es_evi->vpn;
2662
2663 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
2664 return;
2665
2666 UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL);
2667 list_delete_node(vpn->local_es_evi_list, &es_evi->l2vni_listnode);
2668
2669 bgp_evpn_es_evi_free(es_evi);
2670 }
2671
2672 /* eval remote info associated with the ES */
2673 static void bgp_evpn_es_evi_remote_info_re_eval(struct bgp_evpn_es_evi *es_evi)
2674 {
2675 struct bgp_evpn_es *es = es_evi->es;
2676
2677 /* if there are remote VTEPs the ES-EVI is classified as "remote" */
2678 if (listcount(es_evi->es_evi_vtep_list)) {
2679 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE)) {
2680 SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE);
2681 ++es->remote_es_evi_cnt;
2682 /* set remote on the parent es */
2683 bgp_evpn_es_remote_info_re_eval(es);
2684 }
2685 } else {
2686 if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE)) {
2687 UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE);
2688 if (es->remote_es_evi_cnt)
2689 --es->remote_es_evi_cnt;
2690 bgp_evpn_es_evi_free(es_evi);
2691 /* check if "remote" can be cleared from the
2692 * parent es.
2693 */
2694 bgp_evpn_es_remote_info_re_eval(es);
2695 }
2696 }
2697 }
2698
2699 static void bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi)
2700 {
2701 struct prefix_evpn p;
2702 struct bgp_evpn_es *es = es_evi->es;
2703 struct bgp *bgp;
2704
2705 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
2706 return;
2707
2708 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2709 zlog_debug("del local es %s evi %u",
2710 es_evi->es->esi_str,
2711 es_evi->vpn->vni);
2712
2713 bgp = bgp_get_evpn();
2714
2715 if (bgp) {
2716 /* update EAD-ES with new list of VNIs */
2717 if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
2718 build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
2719 &es->esi, es->originator_ip);
2720 if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
2721 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
2722 "%u: EAD-ES route update failure for ESI %s VNI %u",
2723 bgp->vrf_id, es->esi_str,
2724 es_evi->vpn->vni);
2725 }
2726
2727 /* withdraw and delete EAD-EVI */
2728 if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
2729 build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
2730 &es->esi, es->originator_ip);
2731 if (bgp_evpn_type1_evi_route_delete(bgp,
2732 es, es_evi->vpn, &p))
2733 flog_err(EC_BGP_EVPN_ROUTE_DELETE,
2734 "%u: EAD-EVI route deletion failure for ESI %s VNI %u",
2735 bgp->vrf_id, es->esi_str,
2736 es_evi->vpn->vni);
2737 }
2738 }
2739
2740 bgp_evpn_es_evi_local_info_clear(es_evi);
2741
2742 }
2743
2744 int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni)
2745 {
2746 struct bgpevpn *vpn;
2747 struct bgp_evpn_es *es;
2748 struct bgp_evpn_es_evi *es_evi;
2749 char buf[ESI_STR_LEN];
2750
2751 es = bgp_evpn_es_find(esi);
2752 if (!es) {
2753 flog_err(
2754 EC_BGP_ES_CREATE,
2755 "%u: Failed to deref VNI %d from ESI %s; ES not present",
2756 bgp->vrf_id, vni,
2757 esi_to_str(esi, buf, sizeof(buf)));
2758 return -1;
2759 }
2760
2761 vpn = bgp_evpn_lookup_vni(bgp, vni);
2762 if (!vpn) {
2763 flog_err(
2764 EC_BGP_ES_CREATE,
2765 "%u: Failed to deref VNI %d from ESI %s; VNI not present",
2766 bgp->vrf_id, vni, es->esi_str);
2767 return -1;
2768 }
2769
2770 es_evi = bgp_evpn_es_evi_find(es, vpn);
2771 if (!es_evi) {
2772 flog_err(
2773 EC_BGP_ES_CREATE,
2774 "%u: Failed to deref VNI %d from ESI %s; ES-VNI not present",
2775 bgp->vrf_id, vni, es->esi_str);
2776 return -1;
2777 }
2778
2779 bgp_evpn_local_es_evi_do_del(es_evi);
2780 return 0;
2781 }
2782
2783 /* Create ES-EVI and advertise the corresponding EAD routes */
2784 int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
2785 {
2786 struct bgpevpn *vpn;
2787 struct prefix_evpn p;
2788 struct bgp_evpn_es *es;
2789 struct bgp_evpn_es_evi *es_evi;
2790 char buf[ESI_STR_LEN];
2791
2792 es = bgp_evpn_es_find(esi);
2793 if (!es) {
2794 flog_err(
2795 EC_BGP_ES_CREATE,
2796 "%u: Failed to associate VNI %d with ESI %s; ES not present",
2797 bgp->vrf_id, vni,
2798 esi_to_str(esi, buf, sizeof(buf)));
2799 return -1;
2800 }
2801
2802 vpn = bgp_evpn_lookup_vni(bgp, vni);
2803 if (!vpn) {
2804 flog_err(
2805 EC_BGP_ES_CREATE,
2806 "%u: Failed to associate VNI %d with ESI %s; VNI not present",
2807 bgp->vrf_id, vni, es->esi_str);
2808 return -1;
2809 }
2810
2811 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2812 zlog_debug("add local es %s evi %u",
2813 es->esi_str, vni);
2814
2815 es_evi = bgp_evpn_es_evi_find(es, vpn);
2816
2817 if (es_evi) {
2818 if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
2819 /* dup */
2820 return 0;
2821 } else {
2822 es_evi = bgp_evpn_es_evi_new(es, vpn);
2823 if (!es_evi)
2824 return -1;
2825 }
2826
2827 bgp_evpn_es_evi_local_info_set(es_evi);
2828
2829 /* generate an EAD-EVI for this new VNI */
2830 build_evpn_type1_prefix(&p, BGP_EVPN_AD_EVI_ETH_TAG,
2831 &es->esi, es->originator_ip);
2832 if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
2833 if (bgp_evpn_type1_route_update(bgp, es, vpn, &p))
2834 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
2835 "%u: EAD-EVI route creation failure for ESI %s VNI %u",
2836 bgp->vrf_id, es->esi_str, vni);
2837 }
2838
2839 /* update EAD-ES */
2840 build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
2841 &es->esi, es->originator_ip);
2842 if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
2843 if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
2844 flog_err(EC_BGP_EVPN_ROUTE_CREATE,
2845 "%u: EAD-ES route creation failure for ESI %s VNI %u",
2846 bgp->vrf_id, es->esi_str, vni);
2847 }
2848
2849 return 0;
2850 }
2851
2852 /* Add remote ES-EVI entry. This is actually the remote VTEP add and the
2853 * ES-EVI is implicity created on first VTEP's reference.
2854 */
2855 int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
2856 const struct prefix_evpn *p)
2857 {
2858 char buf[ESI_STR_LEN];
2859 struct bgp_evpn_es *es;
2860 struct bgp_evpn_es_evi *es_evi;
2861 bool ead_es;
2862 const esi_t *esi = &p->prefix.ead_addr.esi;
2863
2864 if (!vpn)
2865 /* local EAD-ES need not be sent back to zebra */
2866 return 0;
2867
2868 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2869 zlog_debug("add remote %s es %s evi %u vtep %pI4",
2870 p->prefix.ead_addr.eth_tag ? "ead-es" : "ead-evi",
2871 esi_to_str(esi, buf, sizeof(buf)), vpn->vni,
2872 &p->prefix.ead_addr.ip.ipaddr_v4);
2873
2874 es = bgp_evpn_es_find(esi);
2875 if (!es) {
2876 es = bgp_evpn_es_new(bgp, esi);
2877 if (!es) {
2878 flog_err(EC_BGP_ES_CREATE,
2879 "%u: Failed to allocate ES entry for ESI %s - at remote ES Add",
2880 bgp->vrf_id, esi_to_str(esi, buf, sizeof(buf)));
2881 return -1;
2882 }
2883 }
2884
2885 es_evi = bgp_evpn_es_evi_find(es, vpn);
2886 if (!es_evi) {
2887 es_evi = bgp_evpn_es_evi_new(es, vpn);
2888 if (!es_evi) {
2889 bgp_evpn_es_free(es, __func__);
2890 return -1;
2891 }
2892 }
2893
2894 ead_es = !!p->prefix.ead_addr.eth_tag;
2895 bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
2896 ead_es);
2897
2898 bgp_evpn_es_evi_remote_info_re_eval(es_evi);
2899 return 0;
2900 }
2901
2902 /* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the
2903 * parent es-evi freed up implicitly in last VTEP's deref.
2904 */
2905 int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
2906 const struct prefix_evpn *p)
2907 {
2908 char buf[ESI_STR_LEN];
2909 struct bgp_evpn_es *es;
2910 struct bgp_evpn_es_evi *es_evi;
2911 bool ead_es;
2912
2913 if (!vpn)
2914 /* local EAD-ES need not be sent back to zebra */
2915 return 0;
2916
2917 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
2918 zlog_debug(
2919 "del remote %s es %s evi %u vtep %pI4",
2920 p->prefix.ead_addr.eth_tag ? "ead-es" : "ead-evi",
2921 esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)),
2922 vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
2923
2924 es = bgp_evpn_es_find(&p->prefix.ead_addr.esi);
2925 if (!es)
2926 /* XXX - error logs */
2927 return 0;
2928 es_evi = bgp_evpn_es_evi_find(es, vpn);
2929 if (!es_evi)
2930 /* XXX - error logs */
2931 return 0;
2932
2933 ead_es = !!p->prefix.ead_addr.eth_tag;
2934 bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
2935 ead_es);
2936 bgp_evpn_es_evi_remote_info_re_eval(es_evi);
2937 return 0;
2938 }
2939
2940 /* Initialize the ES tables maintained per-L2_VNI */
2941 void bgp_evpn_vni_es_init(struct bgpevpn *vpn)
2942 {
2943 /* Initialize the ES-EVI RB tree */
2944 RB_INIT(bgp_es_evi_rb_head, &vpn->es_evi_rb_tree);
2945
2946 /* Initialize the local list maintained for quick walks by type */
2947 vpn->local_es_evi_list = list_new();
2948 listset_app_node_mem(vpn->local_es_evi_list);
2949 }
2950
2951 /* Cleanup the ES info maintained per-L2_VNI */
2952 void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn)
2953 {
2954 struct bgp_evpn_es_evi *es_evi;
2955 struct bgp_evpn_es_evi *es_evi_next;
2956
2957 RB_FOREACH_SAFE(es_evi, bgp_es_evi_rb_head,
2958 &vpn->es_evi_rb_tree, es_evi_next) {
2959 bgp_evpn_local_es_evi_do_del(es_evi);
2960 }
2961
2962 list_delete(&vpn->local_es_evi_list);
2963 }
2964
2965 static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
2966 struct bgp_evpn_es_evi *es_evi,
2967 uint8_t vtep_str_size)
2968 {
2969 char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
2970 struct listnode *node;
2971 struct bgp_evpn_es_evi_vtep *evi_vtep;
2972 bool first = true;
2973 char ip_buf[INET6_ADDRSTRLEN];
2974
2975 vtep_str[0] = '\0';
2976 for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
2977 vtep_flag_str[0] = '\0';
2978 if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
2979 strlcat(vtep_flag_str, "E", sizeof(vtep_flag_str));
2980 if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
2981 strlcat(vtep_flag_str, "V", sizeof(vtep_flag_str));
2982
2983 if (!strnlen(vtep_flag_str, sizeof(vtep_flag_str)))
2984 strlcpy(vtep_flag_str, "-", sizeof(vtep_flag_str));
2985 if (first)
2986 first = false;
2987 else
2988 strlcat(vtep_str, ",", vtep_str_size);
2989 strlcat(vtep_str,
2990 inet_ntop(AF_INET, &evi_vtep->vtep_ip, ip_buf,
2991 sizeof(ip_buf)),
2992 vtep_str_size);
2993 strlcat(vtep_str, "(", vtep_str_size);
2994 strlcat(vtep_str, vtep_flag_str, vtep_str_size);
2995 strlcat(vtep_str, ")", vtep_str_size);
2996 }
2997
2998 return vtep_str;
2999 }
3000
3001 static void bgp_evpn_es_evi_json_vtep_fill(json_object *json_vteps,
3002 struct bgp_evpn_es_evi_vtep *evi_vtep)
3003 {
3004 json_object *json_vtep_entry;
3005 json_object *json_flags;
3006 char ip_buf[INET6_ADDRSTRLEN];
3007
3008 json_vtep_entry = json_object_new_object();
3009
3010 json_object_string_add(
3011 json_vtep_entry, "vtep_ip",
3012 inet_ntop(AF_INET, &evi_vtep->vtep_ip, ip_buf, sizeof(ip_buf)));
3013 if (evi_vtep->flags & (BGP_EVPN_EVI_VTEP_EAD_PER_ES |
3014 BGP_EVPN_EVI_VTEP_EAD_PER_EVI)) {
3015 json_flags = json_object_new_array();
3016 if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_ES)
3017 json_array_string_add(json_flags, "ead-per-es");
3018 if (evi_vtep->flags & BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
3019 json_array_string_add(json_flags, "ed-per-evi");
3020 json_object_object_add(json_vtep_entry,
3021 "flags", json_flags);
3022 }
3023
3024 json_object_array_add(json_vteps,
3025 json_vtep_entry);
3026 }
3027
3028 static void bgp_evpn_es_evi_show_entry(struct vty *vty,
3029 struct bgp_evpn_es_evi *es_evi, json_object *json)
3030 {
3031 struct listnode *node;
3032 struct bgp_evpn_es_evi_vtep *evi_vtep;
3033
3034 if (json) {
3035 json_object *json_vteps;
3036 json_object *json_types;
3037
3038 json_object_string_add(json, "esi", es_evi->es->esi_str);
3039 json_object_int_add(json, "vni", es_evi->vpn->vni);
3040
3041 if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL |
3042 BGP_EVPNES_EVI_REMOTE)) {
3043 json_types = json_object_new_array();
3044 if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
3045 json_array_string_add(json_types, "local");
3046 if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
3047 json_array_string_add(json_types, "remote");
3048 json_object_object_add(json, "type", json_types);
3049 }
3050
3051 if (listcount(es_evi->es_evi_vtep_list)) {
3052 json_vteps = json_object_new_array();
3053 for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list,
3054 node, evi_vtep)) {
3055 bgp_evpn_es_evi_json_vtep_fill(json_vteps,
3056 evi_vtep);
3057 }
3058 json_object_object_add(json, "vteps", json_vteps);
3059 }
3060 } else {
3061 char type_str[4];
3062 char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
3063
3064 type_str[0] = '\0';
3065 if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
3066 strlcat(type_str, "L", sizeof(type_str));
3067 if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
3068 strlcat(type_str, "R", sizeof(type_str));
3069 if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST)
3070 strlcat(type_str, "I", sizeof(type_str));
3071
3072 bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
3073
3074 vty_out(vty, "%-8d %-30s %-5s %s\n",
3075 es_evi->vpn->vni, es_evi->es->esi_str,
3076 type_str, vtep_str);
3077 }
3078 }
3079
3080 static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
3081 struct bgp_evpn_es_evi *es_evi, json_object *json)
3082 {
3083 if (json) {
3084 json_object *json_flags;
3085
3086 /* Add the "brief" info first */
3087 bgp_evpn_es_evi_show_entry(vty, es_evi, json);
3088 if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {
3089 json_flags = json_object_new_array();
3090 json_array_string_add(json_flags, "es-vtep-mismatch");
3091 json_object_object_add(json, "flags", json_flags);
3092 }
3093 } else {
3094 char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
3095 char type_str[4];
3096
3097 type_str[0] = '\0';
3098 if (es_evi->flags & BGP_EVPNES_EVI_LOCAL)
3099 strlcat(type_str, "L", sizeof(type_str));
3100 if (es_evi->flags & BGP_EVPNES_EVI_REMOTE)
3101 strlcat(type_str, "R", sizeof(type_str));
3102
3103 bgp_evpn_es_evi_vteps_str(vtep_str, es_evi, sizeof(vtep_str));
3104 if (!strlen(vtep_str))
3105 strlcpy(vtep_str, "-", sizeof(type_str));
3106
3107 vty_out(vty, "VNI: %d ESI: %s\n",
3108 es_evi->vpn->vni, es_evi->es->esi_str);
3109 vty_out(vty, " Type: %s\n", type_str);
3110 vty_out(vty, " Inconsistencies: %s\n",
3111 (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?
3112 "es-vtep-mismatch":"-");
3113 vty_out(vty, " VTEPs: %s\n", vtep_str);
3114 vty_out(vty, "\n");
3115 }
3116 }
3117
3118 static void bgp_evpn_es_evi_show_one_vni(struct bgpevpn *vpn, struct vty *vty,
3119 json_object *json_array, bool detail)
3120 {
3121 struct bgp_evpn_es_evi *es_evi;
3122 json_object *json = NULL;
3123
3124 RB_FOREACH(es_evi, bgp_es_evi_rb_head, &vpn->es_evi_rb_tree) {
3125 if (json_array)
3126 /* create a separate json object for each ES */
3127 json = json_object_new_object();
3128 if (detail)
3129 bgp_evpn_es_evi_show_entry_detail(vty, es_evi, json);
3130 else
3131 bgp_evpn_es_evi_show_entry(vty, es_evi, json);
3132 /* add ES to the json array */
3133 if (json_array)
3134 json_object_array_add(json_array, json);
3135 }
3136 }
3137
3138 struct es_evi_show_ctx {
3139 struct vty *vty;
3140 json_object *json;
3141 int detail;
3142 };
3143
3144 static void bgp_evpn_es_evi_show_one_vni_hash_cb(struct hash_bucket *bucket,
3145 void *ctxt)
3146 {
3147 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
3148 struct es_evi_show_ctx *wctx = (struct es_evi_show_ctx *)ctxt;
3149
3150 bgp_evpn_es_evi_show_one_vni(vpn, wctx->vty, wctx->json, wctx->detail);
3151 }
3152
3153 /* Display all ES EVIs */
3154 void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail)
3155 {
3156 json_object *json_array = NULL;
3157 struct es_evi_show_ctx wctx;
3158 struct bgp *bgp;
3159
3160 if (uj) {
3161 /* create an array of ES-EVIs */
3162 json_array = json_object_new_array();
3163 }
3164
3165 wctx.vty = vty;
3166 wctx.json = json_array;
3167 wctx.detail = detail;
3168
3169 bgp = bgp_get_evpn();
3170
3171 if (!json_array && !detail) {
3172 vty_out(vty, "Flags: L local, R remote, I inconsistent\n");
3173 vty_out(vty, "VTEP-Flags: E EAD-per-ES, V EAD-per-EVI\n");
3174 vty_out(vty, "%-8s %-30s %-5s %s\n",
3175 "VNI", "ESI", "Flags", "VTEPs");
3176 }
3177
3178 if (bgp)
3179 hash_iterate(bgp->vnihash,
3180 (void (*)(struct hash_bucket *,
3181 void *))bgp_evpn_es_evi_show_one_vni_hash_cb,
3182 &wctx);
3183 if (uj) {
3184 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3185 json_array, JSON_C_TO_STRING_PRETTY));
3186 json_object_free(json_array);
3187 }
3188 }
3189
3190 /* Display specific ES EVI */
3191 void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
3192 bool uj, bool detail)
3193 {
3194 struct bgpevpn *vpn = NULL;
3195 json_object *json_array = NULL;
3196 struct bgp *bgp;
3197
3198 if (uj) {
3199 /* create an array of ES-EVIs */
3200 json_array = json_object_new_array();
3201 }
3202
3203 bgp = bgp_get_evpn();
3204 if (bgp)
3205 vpn = bgp_evpn_lookup_vni(bgp, vni);
3206
3207 if (vpn) {
3208 if (!json_array && !detail) {
3209 vty_out(vty, "Flags: L local, R remote, I inconsistent\n");
3210 vty_out(vty, "VTEP-Flags: E EAD-per-ES, V EAD-per-EVI\n");
3211 vty_out(vty, "%-8s %-30s %-5s %s\n",
3212 "VNI", "ESI", "Flags", "VTEPs");
3213 }
3214
3215 bgp_evpn_es_evi_show_one_vni(vpn, vty, json_array, detail);
3216 } else {
3217 if (!uj)
3218 vty_out(vty, "VNI not found\n");
3219 }
3220
3221 if (uj) {
3222 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3223 json_array, JSON_C_TO_STRING_PRETTY));
3224 json_object_free(json_array);
3225 }
3226 }
3227
3228 /*****************************************************************************
3229 * Ethernet Segment Consistency checks
3230 * Consistency checking is done to detect misconfig or mis-cabling. When
3231 * an inconsistency is detected it is simply logged (and displayed via
3232 * show commands) at this point. A more drastic action can be executed (based
3233 * on user config) in the future.
3234 */
3235 /* queue up the es for background consistency checks */
3236 static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es)
3237 {
3238 if (!bgp_mh_info->consistency_checking)
3239 /* consistency checking is not enabled */
3240 return;
3241
3242 if (CHECK_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND))
3243 /* already queued for consistency checking */
3244 return;
3245
3246 SET_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND);
3247 listnode_init(&es->pend_es_listnode, es);
3248 listnode_add_after(bgp_mh_info->pend_es_list,
3249 listtail_unchecked(bgp_mh_info->pend_es_list),
3250 &es->pend_es_listnode);
3251 }
3252
3253 /* pull the ES from the consistency check list */
3254 static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es)
3255 {
3256 if (!CHECK_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND))
3257 return;
3258
3259 UNSET_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND);
3260 list_delete_node(bgp_mh_info->pend_es_list,
3261 &es->pend_es_listnode);
3262 }
3263
3264 /* Number of active VTEPs associated with the ES-per-EVI */
3265 static uint32_t bgp_evpn_es_evi_get_active_vtep_cnt(
3266 struct bgp_evpn_es_evi *es_evi)
3267 {
3268 struct bgp_evpn_es_evi_vtep *evi_vtep;
3269 struct listnode *node;
3270 uint32_t vtep_cnt = 0;
3271
3272 for (ALL_LIST_ELEMENTS_RO(es_evi->es_evi_vtep_list, node, evi_vtep)) {
3273 if (CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE))
3274 ++vtep_cnt;
3275 }
3276
3277 return vtep_cnt;
3278 }
3279
3280 /* Number of active VTEPs associated with the ES */
3281 static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es)
3282 {
3283 struct listnode *node;
3284 uint32_t vtep_cnt = 0;
3285 struct bgp_evpn_es_vtep *es_vtep;
3286
3287 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
3288 if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
3289 ++vtep_cnt;
3290 }
3291
3292 return vtep_cnt;
3293 }
3294
3295 static struct bgp_evpn_es_vtep *bgp_evpn_es_get_next_active_vtep(
3296 struct bgp_evpn_es *es, struct bgp_evpn_es_vtep *es_vtep)
3297 {
3298 struct listnode *node;
3299 struct bgp_evpn_es_vtep *next_es_vtep;
3300
3301 if (es_vtep)
3302 node = listnextnode_unchecked(&es_vtep->es_listnode);
3303 else
3304 node = listhead(es->es_vtep_list);
3305
3306 for (; node; node = listnextnode_unchecked(node)) {
3307 next_es_vtep = listgetdata(node);
3308 if (CHECK_FLAG(next_es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
3309 return next_es_vtep;
3310 }
3311
3312 return NULL;
3313 }
3314
3315 static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_get_next_active_vtep(
3316 struct bgp_evpn_es_evi *es_evi,
3317 struct bgp_evpn_es_evi_vtep *evi_vtep)
3318 {
3319 struct listnode *node;
3320 struct bgp_evpn_es_evi_vtep *next_evi_vtep;
3321
3322 if (evi_vtep)
3323 node = listnextnode_unchecked(&evi_vtep->es_evi_listnode);
3324 else
3325 node = listhead(es_evi->es_evi_vtep_list);
3326
3327 for (; node; node = listnextnode_unchecked(node)) {
3328 next_evi_vtep = listgetdata(node);
3329 if (CHECK_FLAG(next_evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE))
3330 return next_evi_vtep;
3331 }
3332
3333 return NULL;
3334 }
3335
3336 static void bgp_evpn_es_evi_set_inconsistent(struct bgp_evpn_es_evi *es_evi)
3337 {
3338 if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST)) {
3339 if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3340 zlog_debug("inconsistency detected - es %s evi %u vtep list mismatch",
3341 es_evi->es->esi_str,
3342 es_evi->vpn->vni);
3343 SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST);
3344
3345 /* update parent ES with the incosistency setting */
3346 if (!es_evi->es->incons_evi_vtep_cnt &&
3347 BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3348 zlog_debug("inconsistency detected - es %s vtep list mismatch",
3349 es_evi->es->esi_str);
3350 ++es_evi->es->incons_evi_vtep_cnt;
3351 SET_FLAG(es_evi->es->inconsistencies,
3352 BGP_EVPNES_INCONS_VTEP_LIST);
3353 }
3354 }
3355
3356 static uint32_t bgp_evpn_es_run_consistency_checks(struct bgp_evpn_es *es)
3357 {
3358 int proc_cnt = 0;
3359 int es_active_vtep_cnt;
3360 int evi_active_vtep_cnt;
3361 struct bgp_evpn_es_evi *es_evi;
3362 struct listnode *evi_node;
3363 struct bgp_evpn_es_vtep *es_vtep;
3364 struct bgp_evpn_es_evi_vtep *evi_vtep;
3365
3366 /* reset the inconsistencies and re-evaluate */
3367 es->incons_evi_vtep_cnt = 0;
3368 es->inconsistencies = 0;
3369
3370 es_active_vtep_cnt = bgp_evpn_es_get_active_vtep_cnt(es);
3371 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list,
3372 evi_node, es_evi)) {
3373 ++proc_cnt;
3374
3375 /* reset the inconsistencies on the EVI and re-evaluate*/
3376 UNSET_FLAG(es_evi->flags, BGP_EVPNES_EVI_INCONS_VTEP_LIST);
3377
3378 evi_active_vtep_cnt =
3379 bgp_evpn_es_evi_get_active_vtep_cnt(es_evi);
3380 if (es_active_vtep_cnt != evi_active_vtep_cnt) {
3381 bgp_evpn_es_evi_set_inconsistent(es_evi);
3382 continue;
3383 }
3384
3385 if (!es_active_vtep_cnt)
3386 continue;
3387
3388 es_vtep = NULL;
3389 evi_vtep = NULL;
3390 while ((es_vtep = bgp_evpn_es_get_next_active_vtep(
3391 es, es_vtep))) {
3392 evi_vtep = bgp_evpn_es_evi_get_next_active_vtep(es_evi,
3393 evi_vtep);
3394 if (!evi_vtep) {
3395 bgp_evpn_es_evi_set_inconsistent(es_evi);
3396 break;
3397 }
3398 if (es_vtep->vtep_ip.s_addr !=
3399 evi_vtep->vtep_ip.s_addr) {
3400 /* inconsistency detected; set it and move
3401 * to the next evi
3402 */
3403 bgp_evpn_es_evi_set_inconsistent(es_evi);
3404 break;
3405 }
3406 }
3407 }
3408
3409 return proc_cnt;
3410 }
3411
3412 static int bgp_evpn_run_consistency_checks(struct thread *t)
3413 {
3414 int proc_cnt = 0;
3415 int es_cnt = 0;
3416 struct listnode *node;
3417 struct listnode *nextnode;
3418 struct bgp_evpn_es *es;
3419
3420 for (ALL_LIST_ELEMENTS(bgp_mh_info->pend_es_list,
3421 node, nextnode, es)) {
3422 ++es_cnt;
3423 ++proc_cnt;
3424 /* run consistency checks on the ES and remove it from the
3425 * pending list
3426 */
3427 proc_cnt += bgp_evpn_es_run_consistency_checks(es);
3428 bgp_evpn_es_cons_checks_pend_del(es);
3429 if (proc_cnt > 500)
3430 break;
3431 }
3432
3433 /* restart the timer */
3434 thread_add_timer(bm->master, bgp_evpn_run_consistency_checks, NULL,
3435 BGP_EVPN_CONS_CHECK_INTERVAL,
3436 &bgp_mh_info->t_cons_check);
3437
3438 return 0;
3439 }
3440
3441 /*****************************************************************************/
3442 void bgp_evpn_mh_init(void)
3443 {
3444 bm->mh_info = XCALLOC(MTYPE_BGP_EVPN_MH_INFO, sizeof(*bm->mh_info));
3445
3446 /* setup ES tables */
3447 RB_INIT(bgp_es_rb_head, &bgp_mh_info->es_rb_tree);
3448 /* local ES list */
3449 bgp_mh_info->local_es_list = list_new();
3450 listset_app_node_mem(bgp_mh_info->local_es_list);
3451 /* list of ESs with pending processing */
3452 bgp_mh_info->pend_es_list = list_new();
3453 listset_app_node_mem(bgp_mh_info->pend_es_list);
3454
3455 /* config knobs - XXX add cli to control it */
3456 bgp_mh_info->ead_evi_adv_for_down_links = true;
3457 bgp_mh_info->consistency_checking = true;
3458
3459 if (bgp_mh_info->consistency_checking)
3460 thread_add_timer(bm->master, bgp_evpn_run_consistency_checks,
3461 NULL, BGP_EVPN_CONS_CHECK_INTERVAL,
3462 &bgp_mh_info->t_cons_check);
3463
3464 memset(&zero_esi_buf, 0, sizeof(esi_t));
3465 }
3466
3467 void bgp_evpn_mh_finish(void)
3468 {
3469 struct bgp_evpn_es *es;
3470 struct bgp_evpn_es *es_next;
3471
3472 if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
3473 zlog_debug("evpn mh finish");
3474
3475 RB_FOREACH_SAFE (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree,
3476 es_next) {
3477 bgp_evpn_es_local_info_clear(es);
3478 }
3479 thread_cancel(&bgp_mh_info->t_cons_check);
3480 list_delete(&bgp_mh_info->local_es_list);
3481 list_delete(&bgp_mh_info->pend_es_list);
3482
3483 XFREE(MTYPE_BGP_EVPN_MH_INFO, bgp_mh_info);
3484 }