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