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