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