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