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