]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
Merge pull request #9345 from mjstapp/fix_lib_zmq_free
[mirror_frr.git] / zebra / zebra_vxlan.c
CommitLineData
13d60d35 1/*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
43e52561 25#include "hash.h"
13d60d35 26#include "if.h"
43e52561 27#include "jhash.h"
13d60d35 28#include "linklist.h"
43e52561
QY
29#include "log.h"
30#include "memory.h"
31#include "prefix.h"
13d60d35 32#include "stream.h"
43e52561 33#include "table.h"
13d60d35 34#include "vlan.h"
35#include "vxlan.h"
68e33151
CS
36#ifdef GNU_LINUX
37#include <linux/neighbour.h>
38#endif
9bee0232 39#include "lib/printfrr.h"
13d60d35 40
89272910 41#include "zebra/zebra_router.h"
43e52561
QY
42#include "zebra/debug.h"
43#include "zebra/interface.h"
13d60d35 44#include "zebra/rib.h"
45#include "zebra/rt.h"
43e52561
QY
46#include "zebra/rt_netlink.h"
47#include "zebra/zebra_errors.h"
48#include "zebra/zebra_l2.h"
13d60d35 49#include "zebra/zebra_ns.h"
13d60d35 50#include "zebra/zebra_vrf.h"
13d60d35 51#include "zebra/zebra_vxlan.h"
b2998086
PR
52#include "zebra/zebra_evpn.h"
53#include "zebra/zebra_evpn_mac.h"
54#include "zebra/zebra_evpn_neigh.h"
43e52561 55#include "zebra/zebra_vxlan_private.h"
ce5160c0 56#include "zebra/zebra_evpn_mh.h"
8b5fdf2e 57#include "zebra/zebra_evpn_vxlan.h"
3801e764 58#include "zebra/zebra_router.h"
13d60d35 59
6134fd82 60DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
b7cfce93 61DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
b2998086 62DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC");
7cbae20a 63DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor");
8a93734c 64DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");
13d60d35 65
3198b2b3 66DEFINE_HOOK(zebra_rmac_update,
05843a27 67 (struct zebra_mac * rmac, struct zebra_l3vni *zl3vni, bool delete,
3198b2b3
DS
68 const char *reason),
69 (rmac, zl3vni, delete, reason));
a780a738 70
13d60d35 71/* static function declarations */
87d76d54
PR
72static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
73 void **args);
72de4110 74static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
c0e519d3 75 json_object *json);
3198b2b3 76static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
316f4ca4 77 json_object *json);
87d76d54 78static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt);
d62a17ae 79
b7cfce93 80/* l3-vni next-hop neigh related APIs */
72de4110
DS
81static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
82 const struct ipaddr *ip);
b7cfce93 83static void *zl3vni_nh_alloc(void *p);
72de4110
DS
84static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
85 const struct ipaddr *vtep_ip,
86 const struct ethaddr *rmac);
87static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
88static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
89static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
90 struct zebra_neigh *n);
b7cfce93
MK
91
92/* l3-vni rmac related APIs */
e3b78da8 93static void zl3vni_print_rmac_hash(struct hash_bucket *, void *);
05843a27 94static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
3198b2b3 95 const struct ethaddr *rmac);
b7cfce93 96static void *zl3vni_rmac_alloc(void *p);
05843a27 97static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
3198b2b3 98 const struct ethaddr *rmac);
05843a27
DS
99static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac);
100static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
101 struct zebra_mac *zrmac);
102static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
3198b2b3 103 struct zebra_mac *zrmac);
b7cfce93
MK
104
105/* l3-vni related APIs*/
b7cfce93 106static void *zl3vni_alloc(void *p);
05843a27
DS
107static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
108static int zl3vni_del(struct zebra_l3vni *zl3vni);
109static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
110static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
b7cfce93 111
87d76d54 112static void zevpn_build_hash_table(void);
d8b87afe 113static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
015d264c
AK
114static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
115static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
116 struct in_addr sip, struct in_addr mcast_grp);
847f168d
DS
117static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
118 struct in_addr sip,
119 struct in_addr mcast_grp);
abfa0a96
AK
120static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
121 struct in_addr mcast_grp);
122static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
123 struct in_addr mcast_grp);
0c16fb72 124static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);
13d60d35 125
b2ee2b71
AK
126bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
127{
128 return zvrf->dup_addr_detect && zebra_evpn_mh_do_dup_addr_detect();
129}
130
13d60d35 131/* Private functions */
5e1b0650 132static int host_rb_entry_compare(const struct host_rb_entry *hle1,
85442b09 133 const struct host_rb_entry *hle2)
5e1b0650
DS
134{
135 if (hle1->p.family < hle2->p.family)
136 return -1;
137
138 if (hle1->p.family > hle2->p.family)
139 return 1;
140
141 if (hle1->p.prefixlen < hle2->p.prefixlen)
142 return -1;
143
144 if (hle1->p.prefixlen > hle2->p.prefixlen)
145 return 1;
146
147 if (hle1->p.family == AF_INET) {
148 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
149 return -1;
150
151 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
152 return 1;
153
154 return 0;
2acc2310
DS
155 } else if (hle1->p.family == AF_INET6) {
156 return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
157 IPV6_MAX_BYTELEN);
7bfa7d02 158 } else if (hle1->p.family == AF_EVPN) {
82732723
AK
159 uint8_t family1;
160 uint8_t family2;
161
162 /* two (v4/v6) dummy prefixes of route_type BGP_EVPN_AD_ROUTE
163 * are used for all nexthops associated with a non-zero ESI
7bfa7d02 164 */
82732723
AK
165 family1 = is_evpn_prefix_ipaddr_v4(
166 (const struct prefix_evpn *)&hle1->p)
167 ? AF_INET
168 : AF_INET6;
169 family2 = is_evpn_prefix_ipaddr_v4(
170 (const struct prefix_evpn *)&hle2->p)
171 ? AF_INET
172 : AF_INET6;
173
174
175 if (family1 < family2)
176 return -1;
177
178 if (family1 > family2)
179 return 1;
180
7bfa7d02 181 return 0;
5e1b0650 182 } else {
15569c58
DA
183 zlog_debug("%s: Unexpected family type: %d", __func__,
184 hle1->p.family);
5e1b0650
DS
185 return 0;
186 }
187}
85442b09 188RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
5e1b0650 189
85442b09 190static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
5e1b0650
DS
191{
192 struct host_rb_entry *hle;
193 uint32_t count = 0;
194
85442b09 195 RB_FOREACH (hle, host_rb_tree_entry, hrbe)
5e1b0650
DS
196 count++;
197
198 return count;
199}
13d60d35 200
cec2e17d 201/*
87d76d54 202 * Print neighbors for all EVPN.
cec2e17d 203 */
87d76d54 204static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
cd233079 205 void **args)
cec2e17d 206{
d62a17ae 207 struct vty *vty;
87d76d54 208 json_object *json = NULL, *json_evpn = NULL;
f6371c34 209 struct zebra_evpn *zevpn;
d7c0a89a 210 uint32_t num_neigh;
d62a17ae 211 struct neigh_walk_ctx wctx;
cd233079 212 char vni_str[VNI_STR_LEN];
1374d4db 213 uint32_t print_dup;
cd233079
CS
214
215 vty = (struct vty *)args[0];
216 json = (json_object *)args[1];
1374d4db 217 print_dup = (uint32_t)(uintptr_t)args[2];
cec2e17d 218
f6371c34 219 zevpn = (struct zebra_evpn *)bucket->data;
9ea660be 220
87d76d54 221 num_neigh = hashcount(zevpn->neigh_table);
1374d4db
CS
222
223 if (print_dup)
87d76d54 224 num_neigh = num_dup_detected_neighs(zevpn);
1374d4db 225
68e33151 226 if (json == NULL) {
cd233079
CS
227 vty_out(vty,
228 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
87d76d54 229 zevpn->vni, num_neigh);
68e33151 230 } else {
87d76d54
PR
231 json_evpn = json_object_new_object();
232 json_object_int_add(json_evpn, "numArpNd", num_neigh);
233 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
cd233079 234 }
1374d4db 235
cd233079
CS
236 if (!num_neigh) {
237 if (json)
87d76d54 238 json_object_object_add(json, vni_str, json_evpn);
d62a17ae 239 return;
cd233079 240 }
cec2e17d 241
d62a17ae 242 /* Since we have IPv6 addresses to deal with which can vary widely in
243 * size, we try to be a bit more elegant in display by first computing
244 * the maximum width.
245 */
246 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 247 wctx.zevpn = zevpn;
d62a17ae 248 wctx.vty = vty;
249 wctx.addr_width = 15;
87d76d54 250 wctx.json = json_evpn;
7cbae20a
PR
251 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
252 &wctx);
cec2e17d 253
b169fd6f 254 if (json == NULL)
7cbae20a 255 zebra_evpn_print_neigh_hdr(vty, &wctx);
b169fd6f 256
1374d4db 257 if (print_dup)
7cbae20a
PR
258 hash_iterate(zevpn->neigh_table,
259 zebra_evpn_print_dad_neigh_hash, &wctx);
1374d4db 260 else
7cbae20a
PR
261 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash,
262 &wctx);
cd233079
CS
263
264 if (json)
87d76d54 265 json_object_object_add(json, vni_str, json_evpn);
cec2e17d 266}
267
e3fac919 268/*
87d76d54 269 * Print neighbors for all EVPNs in detail.
e3fac919 270 */
87d76d54 271static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket,
e3fac919
NS
272 void **args)
273{
274 struct vty *vty;
87d76d54 275 json_object *json = NULL, *json_evpn = NULL;
f6371c34 276 struct zebra_evpn *zevpn;
e3fac919
NS
277 uint32_t num_neigh;
278 struct neigh_walk_ctx wctx;
279 char vni_str[VNI_STR_LEN];
280 uint32_t print_dup;
281
282 vty = (struct vty *)args[0];
283 json = (json_object *)args[1];
284 print_dup = (uint32_t)(uintptr_t)args[2];
285
f6371c34 286 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 287 if (!zevpn) {
e3fac919
NS
288 if (json)
289 vty_out(vty, "{}\n");
290 return;
291 }
87d76d54 292 num_neigh = hashcount(zevpn->neigh_table);
e3fac919 293
87d76d54 294 if (print_dup && num_dup_detected_neighs(zevpn) == 0)
e3fac919
NS
295 return;
296
297 if (json == NULL) {
298 vty_out(vty,
299 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
87d76d54 300 zevpn->vni, num_neigh);
e3fac919 301 } else {
87d76d54
PR
302 json_evpn = json_object_new_object();
303 json_object_int_add(json_evpn, "numArpNd", num_neigh);
304 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
e3fac919
NS
305 }
306 if (!num_neigh) {
307 if (json)
87d76d54 308 json_object_object_add(json, vni_str, json_evpn);
e3fac919
NS
309 return;
310 }
311
312 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 313 wctx.zevpn = zevpn;
e3fac919
NS
314 wctx.vty = vty;
315 wctx.addr_width = 15;
87d76d54 316 wctx.json = json_evpn;
e3fac919
NS
317
318 if (print_dup)
87d76d54 319 hash_iterate(zevpn->neigh_table,
7cbae20a 320 zebra_evpn_print_dad_neigh_hash_detail, &wctx);
e3fac919 321 else
7cbae20a
PR
322 hash_iterate(zevpn->neigh_table,
323 zebra_evpn_print_neigh_hash_detail, &wctx);
e3fac919
NS
324
325 if (json)
87d76d54 326 json_object_object_add(json, vni_str, json_evpn);
e3fac919
NS
327}
328
9aa741ea 329/* print a specific next hop for an l3vni */
72de4110 330static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
c0e519d3 331 json_object *json)
9aa741ea
MK
332{
333 char buf1[ETHER_ADDR_STRLEN];
334 char buf2[INET6_ADDRSTRLEN];
c0e519d3 335 json_object *json_hosts = NULL;
f2a503f0 336 struct host_rb_entry *hle;
9aa741ea 337
c0e519d3
MK
338 if (!json) {
339 vty_out(vty, "Ip: %s\n",
340 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
341 vty_out(vty, " RMAC: %s\n",
996c9314 342 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
f2a503f0
DS
343 vty_out(vty, " Refcount: %d\n",
344 rb_host_count(&n->host_rb));
4cce389e 345 vty_out(vty, " Prefixes:\n");
85442b09 346 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
2dbe669b 347 vty_out(vty, " %pFX\n", &hle->p);
c0e519d3
MK
348 } else {
349 json_hosts = json_object_new_array();
996c9314
LB
350 json_object_string_add(
351 json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
352 json_object_string_add(
353 json, "routerMac",
354 prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
f2a503f0
DS
355 json_object_int_add(json, "refCount",
356 rb_host_count(&n->host_rb));
85442b09 357 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
c0e519d3 358 json_object_array_add(json_hosts,
996c9314 359 json_object_new_string(prefix2str(
f2a503f0 360 &hle->p, buf2, sizeof(buf2))));
4cce389e 361 json_object_object_add(json, "prefixList", json_hosts);
c0e519d3 362 }
9aa741ea
MK
363}
364
365/* Print a specific RMAC entry */
3198b2b3 366static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
316f4ca4 367 json_object *json)
9aa741ea
MK
368{
369 char buf1[ETHER_ADDR_STRLEN];
370 char buf2[PREFIX_STRLEN];
316f4ca4 371 json_object *json_hosts = NULL;
5e1b0650 372 struct host_rb_entry *hle;
9aa741ea 373
316f4ca4
MK
374 if (!json) {
375 vty_out(vty, "MAC: %s\n",
376 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
9bcef951
MS
377 vty_out(vty, " Remote VTEP: %pI4\n",
378 &zrmac->fwd_info.r_vtep_ip);
41db76c2 379 vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb));
4cce389e 380 vty_out(vty, " Prefixes:\n");
85442b09 381 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
2dbe669b 382 vty_out(vty, " %pFX\n", &hle->p);
316f4ca4
MK
383 } else {
384 json_hosts = json_object_new_array();
996c9314
LB
385 json_object_string_add(
386 json, "routerMac",
387 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
4cce389e 388 json_object_string_add(json, "vtepIp",
9bcef951
MS
389 inet_ntop(AF_INET,
390 &zrmac->fwd_info.r_vtep_ip,
391 buf1, sizeof(buf1)));
41db76c2
DS
392 json_object_int_add(json, "refCount",
393 rb_host_count(&zrmac->host_rb));
85442b09 394 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
5e1b0650
DS
395 json_object_array_add(
396 json_hosts,
397 json_object_new_string(prefix2str(
398 &hle->p, buf2, sizeof(buf2))));
4cce389e 399 json_object_object_add(json, "prefixList", json_hosts);
316f4ca4 400 }
9aa741ea
MK
401}
402
cec2e17d 403/*
87d76d54 404 * Print MACs for all EVPNs.
cec2e17d 405 */
87d76d54 406static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt)
cec2e17d 407{
d62a17ae 408 struct vty *vty;
87d76d54 409 json_object *json = NULL, *json_evpn = NULL;
cd233079 410 json_object *json_mac = NULL;
f6371c34 411 struct zebra_evpn *zevpn;
d7c0a89a 412 uint32_t num_macs;
d62a17ae 413 struct mac_walk_ctx *wctx = ctxt;
cd233079 414 char vni_str[VNI_STR_LEN];
cec2e17d 415
c4efd0f4
DA
416 vty = wctx->vty;
417 json = wctx->json;
cec2e17d 418
f6371c34 419 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 420 wctx->zevpn = zevpn;
cec2e17d 421
d62a17ae 422 /*We are iterating over a new VNI, set the count to 0*/
423 wctx->count = 0;
cec2e17d 424
87d76d54 425 num_macs = num_valid_macs(zevpn);
d62a17ae 426 if (!num_macs)
427 return;
cd233079 428
1374d4db 429 if (wctx->print_dup)
87d76d54 430 num_macs = num_dup_detected_macs(zevpn);
1374d4db 431
cd233079 432 if (json) {
87d76d54 433 json_evpn = json_object_new_object();
cd233079 434 json_mac = json_object_new_object();
87d76d54 435 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
d62a17ae 436 }
cec2e17d 437
cd233079
CS
438 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
439 if (json == NULL) {
440 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
87d76d54 441 zevpn->vni, num_macs);
b169fd6f
AK
442 vty_out(vty,
443 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
444 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
445 "Type", "Flags", "Intf/Remote ES/VTEP",
446 "VLAN", "Seq #'s");
cd233079 447 } else
87d76d54 448 json_object_int_add(json_evpn, "numMacs", num_macs);
cd233079 449 }
1374d4db
CS
450
451 if (!num_macs) {
452 if (json) {
87d76d54
PR
453 json_object_int_add(json_evpn, "numMacs", num_macs);
454 json_object_object_add(json, vni_str, json_evpn);
1374d4db
CS
455 }
456 return;
457 }
458
87d76d54
PR
459 /* assign per-evpn to wctx->json object to fill macs
460 * under the evpn. Re-assign primary json object to fill
461 * next evpn information.
cd233079
CS
462 */
463 wctx->json = json_mac;
1374d4db 464 if (wctx->print_dup)
b2998086
PR
465 hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash,
466 wctx);
1374d4db 467 else
b2998086 468 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, wctx);
cd233079
CS
469 wctx->json = json;
470 if (json) {
471 if (wctx->count)
87d76d54
PR
472 json_object_object_add(json_evpn, "macs", json_mac);
473 json_object_object_add(json, vni_str, json_evpn);
cd233079 474 }
cec2e17d 475}
476
cffe7580 477/*
87d76d54 478 * Print MACs in detail for all EVPNs.
cffe7580 479 */
87d76d54 480static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket,
cffe7580
NS
481 void *ctxt)
482{
483 struct vty *vty;
87d76d54 484 json_object *json = NULL, *json_evpn = NULL;
cffe7580 485 json_object *json_mac = NULL;
f6371c34 486 struct zebra_evpn *zevpn;
cffe7580
NS
487 uint32_t num_macs;
488 struct mac_walk_ctx *wctx = ctxt;
489 char vni_str[VNI_STR_LEN];
490
c4efd0f4
DA
491 vty = wctx->vty;
492 json = wctx->json;
cffe7580 493
f6371c34 494 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 495 if (!zevpn) {
cffe7580
NS
496 if (json)
497 vty_out(vty, "{}\n");
498 return;
499 }
87d76d54 500 wctx->zevpn = zevpn;
cffe7580 501
87d76d54 502 /*We are iterating over a new EVPN, set the count to 0*/
cffe7580
NS
503 wctx->count = 0;
504
87d76d54 505 num_macs = num_valid_macs(zevpn);
cffe7580
NS
506 if (!num_macs)
507 return;
508
87d76d54 509 if (wctx->print_dup && (num_dup_detected_macs(zevpn) == 0))
cffe7580
NS
510 return;
511
512 if (json) {
87d76d54 513 json_evpn = json_object_new_object();
cffe7580 514 json_mac = json_object_new_object();
87d76d54 515 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
cffe7580
NS
516 }
517
518 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
519 if (json == NULL) {
520 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
87d76d54 521 zevpn->vni, num_macs);
cffe7580 522 } else
87d76d54 523 json_object_int_add(json_evpn, "numMacs", num_macs);
cffe7580 524 }
87d76d54
PR
525 /* assign per-evpn to wctx->json object to fill macs
526 * under the evpn. Re-assign primary json object to fill
527 * next evpn information.
cffe7580
NS
528 */
529 wctx->json = json_mac;
530 if (wctx->print_dup)
b2998086
PR
531 hash_iterate(zevpn->mac_table,
532 zebra_evpn_print_dad_mac_hash_detail, wctx);
cffe7580 533 else
b2998086
PR
534 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail,
535 wctx);
cffe7580
NS
536 wctx->json = json;
537 if (json) {
538 if (wctx->count)
87d76d54
PR
539 json_object_object_add(json_evpn, "macs", json_mac);
540 json_object_object_add(json, vni_str, json_evpn);
cffe7580
NS
541 }
542}
543
e3b78da8 544static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93
MK
545{
546 struct nh_walk_ctx *wctx = NULL;
547 struct vty *vty = NULL;
87d76d54 548 struct json_object *json_evpn = NULL;
b7cfce93 549 struct json_object *json_nh = NULL;
72de4110 550 struct zebra_neigh *n = NULL;
b7cfce93 551 char buf1[ETHER_ADDR_STRLEN];
2dbad57f 552 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
553
554 wctx = (struct nh_walk_ctx *)ctx;
555 vty = wctx->vty;
87d76d54
PR
556 json_evpn = wctx->json;
557 if (json_evpn)
b7cfce93 558 json_nh = json_object_new_object();
72de4110 559 n = (struct zebra_neigh *)bucket->data;
b7cfce93 560
87d76d54 561 if (!json_evpn) {
4cce389e 562 vty_out(vty, "%-15s %-17s\n",
2dbad57f 563 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
4cce389e 564 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
b7cfce93 565 } else {
4cce389e 566 json_object_string_add(json_nh, "nexthopIp",
32798965 567 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
996c9314
LB
568 json_object_string_add(
569 json_nh, "routerMac",
570 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
87d76d54 571 json_object_object_add(json_evpn,
32798965
MK
572 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
573 json_nh);
b7cfce93
MK
574 }
575}
576
e3b78da8 577static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket,
32798965 578 void **args)
2dbad57f 579{
580 struct vty *vty = NULL;
581 json_object *json = NULL;
87d76d54 582 json_object *json_evpn = NULL;
05843a27 583 struct zebra_l3vni *zl3vni = NULL;
2dbad57f 584 uint32_t num_nh = 0;
32798965 585 struct nh_walk_ctx wctx;
2dbad57f 586 char vni_str[VNI_STR_LEN];
587
32798965
MK
588 vty = (struct vty *)args[0];
589 json = (struct json_object *)args[1];
2dbad57f 590
05843a27 591 zl3vni = (struct zebra_l3vni *)bucket->data;
2dbad57f 592
593 num_nh = hashcount(zl3vni->nh_table);
594 if (!num_nh)
595 return;
596
597 if (json) {
87d76d54
PR
598 json_evpn = json_object_new_object();
599 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
2dbad57f 600 }
601
602 if (json == NULL) {
996c9314 603 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
4cce389e 604 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
2dbad57f 605 } else
87d76d54 606 json_object_int_add(json_evpn, "numNextHops", num_nh);
2dbad57f 607
32798965
MK
608 memset(&wctx, 0, sizeof(struct nh_walk_ctx));
609 wctx.vty = vty;
87d76d54 610 wctx.json = json_evpn;
32798965
MK
611 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
612 if (json)
87d76d54 613 json_object_object_add(json, vni_str, json_evpn);
2dbad57f 614}
615
e3b78da8 616static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket,
c0b4eaa4 617 void **args)
b7cfce93
MK
618{
619 struct vty *vty = NULL;
620 json_object *json = NULL;
87d76d54 621 json_object *json_evpn = NULL;
05843a27 622 struct zebra_l3vni *zl3vni = NULL;
d7c0a89a 623 uint32_t num_rmacs;
c0b4eaa4 624 struct rmac_walk_ctx wctx;
b7cfce93
MK
625 char vni_str[VNI_STR_LEN];
626
c0b4eaa4
MK
627 vty = (struct vty *)args[0];
628 json = (struct json_object *)args[1];
b7cfce93 629
05843a27 630 zl3vni = (struct zebra_l3vni *)bucket->data;
b7cfce93
MK
631
632 num_rmacs = hashcount(zl3vni->rmac_table);
633 if (!num_rmacs)
634 return;
635
636 if (json) {
87d76d54
PR
637 json_evpn = json_object_new_object();
638 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
b7cfce93
MK
639 }
640
641 if (json == NULL) {
996c9314 642 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
4cce389e 643 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
b7cfce93 644 } else
87d76d54 645 json_object_int_add(json_evpn, "numRmacs", num_rmacs);
b7cfce93
MK
646
647 /* assign per-vni to wctx->json object to fill macs
648 * under the vni. Re-assign primary json object to fill
649 * next vni information.
650 */
c0b4eaa4
MK
651 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
652 wctx.vty = vty;
87d76d54 653 wctx.json = json_evpn;
c0b4eaa4
MK
654 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
655 if (json)
87d76d54 656 json_object_object_add(json, vni_str, json_evpn);
b7cfce93
MK
657}
658
e3b78da8 659static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93 660{
3198b2b3 661 struct zebra_mac *zrmac = NULL;
b7cfce93
MK
662 struct rmac_walk_ctx *wctx = NULL;
663 struct vty *vty = NULL;
664 struct json_object *json = NULL;
665 struct json_object *json_rmac = NULL;
9bcef951 666 char buf[PREFIX_STRLEN];
b7cfce93
MK
667
668 wctx = (struct rmac_walk_ctx *)ctx;
669 vty = wctx->vty;
670 json = wctx->json;
671 if (json)
672 json_rmac = json_object_new_object();
3198b2b3 673 zrmac = (struct zebra_mac *)bucket->data;
b7cfce93
MK
674
675 if (!json) {
9bcef951 676 vty_out(vty, "%-17s %-21pI4\n",
b7cfce93 677 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
9bcef951 678 &zrmac->fwd_info.r_vtep_ip);
b7cfce93 679 } else {
996c9314
LB
680 json_object_string_add(
681 json_rmac, "routerMac",
682 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
4cce389e 683 json_object_string_add(json_rmac, "vtepIp",
9bcef951
MS
684 inet_ntop(AF_INET,
685 &zrmac->fwd_info.r_vtep_ip,
686 buf, sizeof(buf)));
996c9314
LB
687 json_object_object_add(
688 json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
689 json_rmac);
b7cfce93
MK
690 }
691}
692
693/* print a specific L3 VNI entry */
05843a27 694static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
b7cfce93 695{
9bcef951 696 char buf[PREFIX_STRLEN];
b7cfce93
MK
697 struct vty *vty = NULL;
698 json_object *json = NULL;
f6371c34 699 struct zebra_evpn *zevpn = NULL;
87d76d54 700 json_object *json_evpn_list = NULL;
b7cfce93
MK
701 struct listnode *node = NULL, *nnode = NULL;
702
703 vty = ctx[0];
704 json = ctx[1];
705
706 if (!json) {
707 vty_out(vty, "VNI: %u\n", zl3vni->vni);
4cce389e 708 vty_out(vty, " Type: %s\n", "L3");
996c9314 709 vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
9bcef951
MS
710 vty_out(vty, " Local Vtep Ip: %pI4\n",
711 &zl3vni->local_vtep_ip);
b7cfce93
MK
712 vty_out(vty, " Vxlan-Intf: %s\n",
713 zl3vni_vxlan_if_name(zl3vni));
996c9314
LB
714 vty_out(vty, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
715 vty_out(vty, " State: %s\n", zl3vni_state2str(zl3vni));
c48d9f5f 716 vty_out(vty, " VNI Filter: %s\n",
996c9314
LB
717 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
718 ? "prefix-routes-only"
719 : "none");
28ad0501
CS
720 vty_out(vty, " System MAC: %s\n",
721 zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 722 vty_out(vty, " Router MAC: %s\n",
b7cfce93 723 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 724 vty_out(vty, " L2 VNIs: ");
87d76d54
PR
725 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn))
726 vty_out(vty, "%u ", zevpn->vni);
b7cfce93
MK
727 vty_out(vty, "\n");
728 } else {
87d76d54 729 json_evpn_list = json_object_new_array();
b7cfce93 730 json_object_int_add(json, "vni", zl3vni->vni);
4cce389e 731 json_object_string_add(json, "type", "L3");
9bcef951
MS
732 json_object_string_add(
733 json, "localVtepIp",
734 inet_ntop(AF_INET, &zl3vni->local_vtep_ip, buf,
735 sizeof(buf)));
4cce389e 736 json_object_string_add(json, "vxlanIntf",
b7cfce93 737 zl3vni_vxlan_if_name(zl3vni));
4cce389e 738 json_object_string_add(json, "sviIntf",
b7cfce93 739 zl3vni_svi_if_name(zl3vni));
996c9314
LB
740 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
741 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
28ad0501
CS
742 json_object_string_add(
743 json, "sysMac",
744 zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
996c9314
LB
745 json_object_string_add(
746 json, "routerMac",
747 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
748 json_object_string_add(
749 json, "vniFilter",
750 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
751 ? "prefix-routes-only"
752 : "none");
87d76d54
PR
753 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) {
754 json_object_array_add(json_evpn_list,
755 json_object_new_int(zevpn->vni));
b7cfce93 756 }
87d76d54 757 json_object_object_add(json, "l2Vnis", json_evpn_list);
b7cfce93
MK
758 }
759}
760
b7cfce93 761/* print a L3 VNI hash entry */
e3b78da8 762static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])
b7cfce93 763{
b7cfce93
MK
764 struct vty *vty = NULL;
765 json_object *json = NULL;
87d76d54 766 json_object *json_evpn = NULL;
05843a27 767 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 768
51d8de8f
MK
769 vty = (struct vty *)ctx[0];
770 json = (json_object *)ctx[1];
b7cfce93 771
05843a27 772 zl3vni = (struct zebra_l3vni *)bucket->data;
b7cfce93
MK
773
774 if (!json) {
996c9314
LB
775 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
776 zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
4cce389e 777 hashcount(zl3vni->rmac_table),
996c9314 778 hashcount(zl3vni->nh_table), "n/a",
4cce389e 779 zl3vni_vrf_name(zl3vni));
b7cfce93 780 } else {
51d8de8f
MK
781 char vni_str[VNI_STR_LEN];
782
87d76d54
PR
783 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
784 json_evpn = json_object_new_object();
785 json_object_int_add(json_evpn, "vni", zl3vni->vni);
786 json_object_string_add(json_evpn, "vxlanIf",
b7cfce93 787 zl3vni_vxlan_if_name(zl3vni));
87d76d54 788 json_object_int_add(json_evpn, "numMacs",
4cce389e 789 hashcount(zl3vni->rmac_table));
87d76d54 790 json_object_int_add(json_evpn, "numArpNd",
4cce389e 791 hashcount(zl3vni->nh_table));
87d76d54
PR
792 json_object_string_add(json_evpn, "numRemoteVteps", "n/a");
793 json_object_string_add(json_evpn, "type", "L3");
794 json_object_string_add(json_evpn, "tenantVrf",
b7cfce93 795 zl3vni_vrf_name(zl3vni));
87d76d54 796 json_object_object_add(json, vni_str, json_evpn);
b7cfce93 797 }
b7cfce93
MK
798}
799
09af6961 800/* print a L3 VNI hash entry in detail*/
e3b78da8 801static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
09af6961
NS
802{
803 struct vty *vty = NULL;
05843a27 804 struct zebra_l3vni *zl3vni = NULL;
06931fdb 805 json_object *json_array = NULL;
09af6961 806 bool use_json = false;
8b5fdf2e 807 struct zebra_evpn_show *zes = data;
09af6961
NS
808
809 vty = zes->vty;
06931fdb
LK
810 json_array = zes->json;
811 use_json = zes->use_json;
09af6961 812
05843a27 813 zl3vni = (struct zebra_l3vni *)bucket->data;
09af6961 814
06931fdb
LK
815 zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni,
816 use_json, json_array);
817
818 if (!use_json)
819 vty_out(vty, "\n");
09af6961
NS
820}
821
2961d060 822static int zvni_map_to_svi_ns(struct ns *ns,
a237058f
PG
823 void *_in_param,
824 void **_p_ifp)
825{
2961d060 826 struct zebra_ns *zns = ns->info;
a237058f
PG
827 struct route_node *rn;
828 struct zebra_from_svi_param *in_param =
829 (struct zebra_from_svi_param *)_in_param;
830 struct zebra_l2info_vlan *vl;
831 struct interface *tmp_if = NULL;
832 struct interface **p_ifp = (struct interface **)_p_ifp;
833 struct zebra_if *zif;
834
835 if (!in_param)
2961d060 836 return NS_WALK_STOP;
a237058f
PG
837
838 /* TODO: Optimize with a hash. */
839 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
840 tmp_if = (struct interface *)rn->info;
841 /* Check oper status of the SVI. */
842 if (!tmp_if || !if_is_operative(tmp_if))
843 continue;
844 zif = tmp_if->info;
845 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
846 || zif->link != in_param->br_if)
847 continue;
848 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
849
850 if (vl->vid == in_param->vid) {
851 if (p_ifp)
852 *p_ifp = tmp_if;
2961d060 853 return NS_WALK_STOP;
a237058f
PG
854 }
855 }
2961d060 856 return NS_WALK_CONTINUE;
a237058f
PG
857}
858
8b5fdf2e
PR
859/* Map to SVI on bridge corresponding to specified VLAN. This can be one
860 * of two cases:
861 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
862 * linked to the bridge
863 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
864 * itself
09af6961 865 */
8b5fdf2e 866struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
13d60d35 867{
7cbae20a 868 struct interface *tmp_if = NULL;
8b5fdf2e
PR
869 struct zebra_if *zif;
870 struct zebra_l2info_bridge *br;
a237058f
PG
871 struct zebra_from_svi_param in_param;
872 struct interface **p_ifp;
8b5fdf2e
PR
873 /* Defensive check, caller expected to invoke only with valid bridge. */
874 if (!br_if)
875 return NULL;
1a98c087 876
8b5fdf2e
PR
877 /* Determine if bridge is VLAN-aware or not */
878 zif = br_if->info;
879 assert(zif);
880 br = &zif->l2info.br;
a237058f 881 in_param.bridge_vlan_aware = br->vlan_aware;
8b5fdf2e 882 /* Check oper status of the SVI. */
a237058f 883 if (!in_param.bridge_vlan_aware)
8b5fdf2e 884 return if_is_operative(br_if) ? br_if : NULL;
d62a17ae 885
a237058f
PG
886 in_param.vid = vid;
887 in_param.br_if = br_if;
888 in_param.zif = NULL;
889 p_ifp = &tmp_if;
bf69e212 890 /* Identify corresponding VLAN interface. */
2961d060
PG
891 ns_walk_func(zvni_map_to_svi_ns, (void *)&in_param,
892 (void **)p_ifp);
a237058f 893 return tmp_if;
8b5fdf2e 894}
2232a77c 895
f6371c34 896static int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
8b5fdf2e
PR
897{
898 zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);
2232a77c 899
8b5fdf2e
PR
900 /* Remove references to the BUM mcast grp */
901 zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp);
2232a77c 902
8b5fdf2e 903 return zebra_evpn_del(zevpn);
2232a77c 904}
07509878 905
2961d060 906static int zevpn_build_hash_table_zns(struct ns *ns,
07509878
PG
907 void *param_in __attribute__((unused)),
908 void **param_out __attribute__((unused)))
2232a77c 909{
2961d060 910 struct zebra_ns *zns = ns->info;
2853fed6 911 struct route_node *rn;
d62a17ae 912 struct interface *ifp;
07509878
PG
913 struct zebra_vrf *zvrf;
914
915 zvrf = zebra_vrf_get_evpn();
916
917 if (!zvrf)
2961d060 918 return NS_WALK_STOP;
2232a77c 919
87d76d54 920 /* Walk VxLAN interfaces and create EVPN hash. */
2853fed6 921 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
b7cfce93 922 vni_t vni;
f6371c34 923 struct zebra_evpn *zevpn = NULL;
05843a27 924 struct zebra_l3vni *zl3vni = NULL;
d62a17ae 925 struct zebra_if *zif;
926 struct zebra_l2info_vxlan *vxl;
2232a77c 927
2853fed6 928 ifp = (struct interface *)rn->info;
929 if (!ifp)
930 continue;
d62a17ae 931 zif = ifp->info;
932 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
933 continue;
2232a77c 934
b7cfce93 935 vxl = &zif->l2info.vxl;
d62a17ae 936 vni = vxl->vni;
07509878
PG
937 /* link of VXLAN interface should be in zebra_evpn_vrf */
938 if (zvrf->zns->ns_id != vxl->link_nsid) {
939 if (IS_ZEBRA_DEBUG_VXLAN)
940 zlog_debug(
941 "Intf %s(%u) VNI %u, link not in same "
942 "namespace than BGP EVPN core instance ",
943 ifp->name, ifp->ifindex, vni);
944 continue;
945 }
643215ce 946 /* L3-VNI and L2-VNI are handled seperately */
947 zl3vni = zl3vni_lookup(vni);
948 if (zl3vni) {
2232a77c 949
b7cfce93 950 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
951 zlog_debug(
952 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
953 ifp->name, ifp->ifindex, vni);
2232a77c 954
b7cfce93 955 /* associate with vxlan_if */
b67a60d2 956 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 957 zl3vni->vxlan_if = ifp;
2232a77c 958
523cafc4 959 /*
960 * we need to associate with SVI.
b7cfce93 961 * we can associate with svi-if only after association
523cafc4 962 * with vxlan-intf is complete
963 */
b7cfce93
MK
964 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
965
06d9cde5
CS
966 /* Associate l3vni to mac-vlan and extract VRR MAC */
967 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
968
969 if (IS_ZEBRA_DEBUG_VXLAN)
970 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
971 vni, zl3vni->svi_if ? zl3vni->svi_if->name
972 : "NIL",
973 zl3vni->mac_vlan_if ?
974 zl3vni->mac_vlan_if->name : "NIL");
975
b7cfce93
MK
976 if (is_l3vni_oper_up(zl3vni))
977 zebra_vxlan_process_l3vni_oper_up(zl3vni);
978
979 } else {
b7cfce93
MK
980 struct interface *vlan_if = NULL;
981
982 if (IS_ZEBRA_DEBUG_VXLAN)
983 zlog_debug(
9bcef951 984 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
b7cfce93 985 ifp->name, ifp->ifindex, vni,
9bcef951 986 &vxl->vtep_ip);
b7cfce93 987
87d76d54 988 /* EVPN hash entry is expected to exist, if the BGP process is killed */
8b5fdf2e 989 zevpn = zebra_evpn_lookup(vni);
87d76d54 990 if (zevpn) {
9df414fe 991 zlog_debug(
87d76d54 992 "EVPN hash already present for IF %s(%u) L2-VNI %u",
b7cfce93 993 ifp->name, ifp->ifindex, vni);
b7cfce93 994
27627f9a
KA
995 /*
996 * Inform BGP if intf is up and mapped to
997 * bridge.
998 */
999 if (if_is_operative(ifp) &&
1000 zif->brslave_info.br_if)
8b5fdf2e 1001 zebra_evpn_send_add_to_client(zevpn);
b7cfce93 1002
27627f9a 1003 /* Send Local MAC-entries to client */
b2998086 1004 zebra_evpn_send_mac_list_to_client(zevpn);
27627f9a
KA
1005
1006 /* Send Loval Neighbor entries to client */
7cbae20a 1007 zebra_evpn_send_neigh_to_client(zevpn);
27627f9a 1008 } else {
8b5fdf2e 1009 zevpn = zebra_evpn_add(vni);
87d76d54 1010 if (!zevpn) {
27627f9a 1011 zlog_debug(
87d76d54 1012 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
27627f9a 1013 ifp->name, ifp->ifindex, vni);
2961d060 1014 return NS_WALK_CONTINUE;
27627f9a 1015 }
b7cfce93 1016
87d76d54 1017 if (zevpn->local_vtep_ip.s_addr !=
27627f9a 1018 vxl->vtep_ip.s_addr ||
87d76d54 1019 zevpn->mcast_grp.s_addr !=
27627f9a
KA
1020 vxl->mcast_grp.s_addr) {
1021 zebra_vxlan_sg_deref(
87d76d54
PR
1022 zevpn->local_vtep_ip,
1023 zevpn->mcast_grp);
27627f9a
KA
1024 zebra_vxlan_sg_ref(vxl->vtep_ip,
1025 vxl->mcast_grp);
87d76d54
PR
1026 zevpn->local_vtep_ip = vxl->vtep_ip;
1027 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
1028 /* on local vtep-ip check if ES
1029 * orig-ip needs to be updated
1030 */
87d76d54 1031 zebra_evpn_es_set_base_evpn(zevpn);
27627f9a 1032 }
87d76d54 1033 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
7cbae20a
PR
1034 vlan_if = zvni_map_to_svi(
1035 vxl->access_vlan,
1036 zif->brslave_info.br_if);
27627f9a 1037 if (vlan_if) {
9daa5d47 1038 zevpn->svi_if = vlan_if;
87d76d54 1039 zevpn->vrf_id = vlan_if->vrf_id;
27627f9a
KA
1040 zl3vni = zl3vni_from_vrf(
1041 vlan_if->vrf_id);
1042 if (zl3vni)
1043 listnode_add_sort(
87d76d54 1044 zl3vni->l2vnis, zevpn);
27627f9a 1045 }
b7cfce93 1046
27627f9a
KA
1047 /*
1048 * Inform BGP if intf is up and mapped to
1049 * bridge.
1050 */
1051 if (if_is_operative(ifp) &&
1052 zif->brslave_info.br_if)
8b5fdf2e 1053 zebra_evpn_send_add_to_client(zevpn);
27627f9a 1054 }
b7cfce93 1055 }
d62a17ae 1056 }
2961d060 1057 return NS_WALK_CONTINUE;
07509878
PG
1058}
1059
1060/*
1061 * Build the VNI hash table by going over the VxLAN interfaces. This
1062 * is called when EVPN (advertise-all-vni) is enabled.
1063 */
1064
1065static void zevpn_build_hash_table(void)
1066{
2961d060
PG
1067 ns_walk_func(zevpn_build_hash_table_zns,
1068 (void *)NULL,
1069 (void **)NULL);
2232a77c 1070}
1071
2232a77c 1072/*
87d76d54 1073 * Cleanup EVPN/VTEP and update kernel
2232a77c 1074 */
8b5fdf2e 1075static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket *bucket, void *arg)
2232a77c 1076{
f6371c34 1077 struct zebra_evpn *zevpn = NULL;
05843a27 1078 struct zebra_l3vni *zl3vni = NULL;
84915b0a 1079 struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
2232a77c 1080
f6371c34 1081 zevpn = (struct zebra_evpn *)bucket->data;
2232a77c 1082
b7cfce93 1083 /* remove from l3-vni list */
84915b0a 1084 if (zvrf->l3vni)
1085 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93 1086 if (zl3vni)
87d76d54 1087 listnode_delete(zl3vni->l2vnis, zevpn);
b7cfce93 1088
8b5fdf2e 1089 zebra_evpn_cleanup_all(bucket, arg);
2232a77c 1090}
1091
655b04d1 1092/* cleanup L3VNI */
e3b78da8 1093static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args)
655b04d1 1094{
05843a27 1095 struct zebra_l3vni *zl3vni = NULL;
655b04d1 1096
05843a27 1097 zl3vni = (struct zebra_l3vni *)bucket->data;
655b04d1
MK
1098
1099 zebra_vxlan_process_l3vni_oper_down(zl3vni);
1100}
1101
85442b09 1102static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
e4a1ec74 1103 const struct prefix *host)
5e1b0650
DS
1104{
1105 struct host_rb_entry lookup;
1106 struct host_rb_entry *hle;
1107
1108 memset(&lookup, 0, sizeof(lookup));
1109 memcpy(&lookup.p, host, sizeof(*host));
1110
85442b09 1111 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
5e1b0650
DS
1112 if (hle)
1113 return;
1114
1115 hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
1116 memcpy(hle, &lookup, sizeof(lookup));
1117
85442b09 1118 RB_INSERT(host_rb_tree_entry, hrbe, hle);
5e1b0650
DS
1119}
1120
85442b09 1121static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
5e1b0650
DS
1122{
1123 struct host_rb_entry lookup;
1124 struct host_rb_entry *hle;
1125
1126 memset(&lookup, 0, sizeof(lookup));
1127 memcpy(&lookup.p, host, sizeof(*host));
1128
85442b09 1129 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
10ac2516 1130 if (hle) {
85442b09 1131 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
10ac2516
DS
1132 XFREE(MTYPE_HOST_PREFIX, hle);
1133 }
5e1b0650
DS
1134
1135 return;
1136}
1137
b7cfce93
MK
1138/*
1139 * Look up MAC hash entry.
1140 */
05843a27 1141static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
3198b2b3 1142 const struct ethaddr *rmac)
b7cfce93 1143{
3198b2b3
DS
1144 struct zebra_mac tmp;
1145 struct zebra_mac *pmac;
b7cfce93
MK
1146
1147 memset(&tmp, 0, sizeof(tmp));
1148 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
1149 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
2232a77c 1150
b7cfce93 1151 return pmac;
2dbad57f 1152}
2232a77c 1153
cec2e17d 1154/*
b7cfce93 1155 * Callback to allocate RMAC hash entry.
cec2e17d 1156 */
2dbad57f 1157static void *zl3vni_rmac_alloc(void *p)
d62a17ae 1158{
3198b2b3
DS
1159 const struct zebra_mac *tmp_rmac = p;
1160 struct zebra_mac *zrmac;
d62a17ae 1161
3198b2b3 1162 zrmac = XCALLOC(MTYPE_L3VNI_MAC, sizeof(struct zebra_mac));
b7cfce93 1163 *zrmac = *tmp_rmac;
d62a17ae 1164
b7cfce93 1165 return ((void *)zrmac);
2dbad57f 1166}
cd233079 1167
b7cfce93
MK
1168/*
1169 * Add RMAC entry to l3-vni
1170 */
05843a27 1171static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
3198b2b3 1172 const struct ethaddr *rmac)
b7cfce93 1173{
3198b2b3
DS
1174 struct zebra_mac tmp_rmac;
1175 struct zebra_mac *zrmac = NULL;
d62a17ae 1176
3198b2b3 1177 memset(&tmp_rmac, 0, sizeof(struct zebra_mac));
b7cfce93
MK
1178 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
1179 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
1180 assert(zrmac);
d62a17ae 1181
85442b09 1182 RB_INIT(host_rb_tree_entry, &zrmac->host_rb);
b7cfce93 1183
2dbad57f 1184 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
1185 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
1186
b7cfce93 1187 return zrmac;
2dbad57f 1188}
cec2e17d 1189
1190/*
b7cfce93 1191 * Delete MAC entry.
cec2e17d 1192 */
05843a27 1193static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac)
cec2e17d 1194{
3198b2b3 1195 struct zebra_mac *tmp_rmac;
5e1b0650 1196 struct host_rb_entry *hle;
cd233079 1197
85442b09
DS
1198 while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
1199 hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb);
5e1b0650 1200
85442b09 1201 RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle);
5e1b0650
DS
1202 XFREE(MTYPE_HOST_PREFIX, hle);
1203 }
cd233079 1204
b7cfce93 1205 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
b2998086 1206 XFREE(MTYPE_L3VNI_MAC, tmp_rmac);
cd233079 1207
b7cfce93 1208 return 0;
2dbad57f 1209}
cec2e17d 1210
1211/*
036d93c0 1212 * Install remote RMAC into the forwarding plane.
cec2e17d 1213 */
05843a27
DS
1214static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
1215 struct zebra_mac *zrmac)
cec2e17d 1216{
478566d6
MS
1217 const struct zebra_if *zif = NULL, *br_zif = NULL;
1218 const struct zebra_l2info_vxlan *vxl = NULL;
1219 const struct interface *br_ifp;
036d93c0 1220 enum zebra_dplane_result res;
478566d6 1221 vlanid_t vid;
cec2e17d 1222
996c9314
LB
1223 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
1224 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
1225 return 0;
1226
1227 zif = zl3vni->vxlan_if->info;
1228 if (!zif)
1229 return -1;
1230
478566d6
MS
1231 br_ifp = zif->brslave_info.br_if;
1232 if (br_ifp == NULL)
1233 return -1;
1234
b7cfce93
MK
1235 vxl = &zif->l2info.vxl;
1236
478566d6
MS
1237 br_zif = (const struct zebra_if *)br_ifp->info;
1238
1239 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1240 vid = vxl->access_vlan;
1241 else
1242 vid = 0;
1243
f188e68e
AK
1244 res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid,
1245 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0,
1246 false /*was_static*/);
036d93c0
MS
1247 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
1248 return 0;
1249 else
1250 return -1;
2dbad57f 1251}
b7cfce93
MK
1252
1253/*
036d93c0 1254 * Uninstall remote RMAC from the forwarding plane.
b7cfce93 1255 */
05843a27
DS
1256static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
1257 struct zebra_mac *zrmac)
b7cfce93 1258{
478566d6
MS
1259 const struct zebra_if *zif = NULL, *br_zif;
1260 const struct zebra_l2info_vxlan *vxl = NULL;
1261 const struct interface *br_ifp;
1262 vlanid_t vid;
036d93c0 1263 enum zebra_dplane_result res;
b7cfce93 1264
996c9314
LB
1265 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
1266 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
1267 return 0;
1268
1269 if (!zl3vni->vxlan_if) {
e0e140a7
MS
1270 if (IS_ZEBRA_DEBUG_VXLAN)
1271 zlog_debug(
ef7b8be4
DL
1272 "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
1273 &zrmac->macaddr, zl3vni->vni, zl3vni);
b7cfce93
MK
1274 return -1;
1275 }
1276
1277 zif = zl3vni->vxlan_if->info;
1278 if (!zif)
1279 return -1;
1280
478566d6
MS
1281 br_ifp = zif->brslave_info.br_if;
1282 if (br_ifp == NULL)
1283 return -1;
1284
b7cfce93
MK
1285 vxl = &zif->l2info.vxl;
1286
478566d6
MS
1287 br_zif = (const struct zebra_if *)br_ifp->info;
1288 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1289 vid = vxl->access_vlan;
1290 else
1291 vid = 0;
1292
f188e68e 1293 res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid,
036d93c0
MS
1294 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
1295 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
1296 return 0;
1297 else
1298 return -1;
2dbad57f 1299}
1300
1301/* handle rmac add */
05843a27 1302static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
e4a1ec74
MS
1303 const struct ethaddr *rmac,
1304 const struct ipaddr *vtep_ip,
1305 const struct prefix *host_prefix)
2dbad57f 1306{
3198b2b3 1307 struct zebra_mac *zrmac = NULL;
2dbad57f 1308
1309 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
1310 if (!zrmac) {
1311
651fa905 1312 /* Create the RMAC entry, or update its vtep, if necessary. */
2dbad57f 1313 zrmac = zl3vni_rmac_add(zl3vni, rmac);
1314 if (!zrmac) {
9df414fe 1315 zlog_debug(
ef7b8be4
DL
1316 "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA, prefix %pFX",
1317 rmac, zl3vni->vni, vtep_ip, host_prefix);
2dbad57f 1318 return -1;
1319 }
1320 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
1321 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
1322
a780a738
AD
1323 /* Send RMAC for FPM processing */
1324 hook_call(zebra_rmac_update, zrmac, zl3vni, false,
1325 "new RMAC added");
1326
651fa905
CS
1327 /* install rmac in kernel */
1328 zl3vni_rmac_install(zl3vni, zrmac);
1329 } else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
1330 &vtep_ip->ipaddr_v4)) {
1331 if (IS_ZEBRA_DEBUG_VXLAN)
1332 zlog_debug(
ef7b8be4
DL
1333 "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA, prefix %pFX",
1334 zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
1335 vtep_ip, rmac, host_prefix);
651fa905
CS
1336
1337 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
1338
2dbad57f 1339 /* install rmac in kernel */
1340 zl3vni_rmac_install(zl3vni, zrmac);
1341 }
6134fd82 1342
41db76c2 1343 rb_find_or_add_host(&zrmac->host_rb, host_prefix);
5e1b0650 1344
2dbad57f 1345 return 0;
1346}
1347
1348
1349/* handle rmac delete */
05843a27 1350static void zl3vni_remote_rmac_del(struct zebra_l3vni *zl3vni,
3198b2b3
DS
1351 struct zebra_mac *zrmac,
1352 struct prefix *host_prefix)
2dbad57f 1353{
41db76c2 1354 rb_delete_host(&zrmac->host_rb, host_prefix);
2dbad57f 1355
85442b09 1356 if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
2dbad57f 1357 /* uninstall from kernel */
1358 zl3vni_rmac_uninstall(zl3vni, zrmac);
1359
a780a738
AD
1360 /* Send RMAC for FPM processing */
1361 hook_call(zebra_rmac_update, zrmac, zl3vni, true,
1362 "RMAC deleted");
1363
2dbad57f 1364 /* del the rmac entry */
1365 zl3vni_rmac_del(zl3vni, zrmac);
1366 }
2dbad57f 1367}
b7cfce93
MK
1368
1369/*
1370 * Look up nh hash entry on a l3-vni.
1371 */
72de4110
DS
1372static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
1373 const struct ipaddr *ip)
b7cfce93 1374{
72de4110
DS
1375 struct zebra_neigh tmp;
1376 struct zebra_neigh *n;
b7cfce93
MK
1377
1378 memset(&tmp, 0, sizeof(tmp));
1379 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
1380 n = hash_lookup(zl3vni->nh_table, &tmp);
1381
1382 return n;
2dbad57f 1383}
b7cfce93
MK
1384
1385
1386/*
1387 * Callback to allocate NH hash entry on L3-VNI.
1388 */
2dbad57f 1389static void *zl3vni_nh_alloc(void *p)
b7cfce93 1390{
72de4110
DS
1391 const struct zebra_neigh *tmp_n = p;
1392 struct zebra_neigh *n;
b7cfce93 1393
72de4110 1394 n = XCALLOC(MTYPE_L3NEIGH, sizeof(struct zebra_neigh));
b7cfce93
MK
1395 *n = *tmp_n;
1396
1397 return ((void *)n);
2dbad57f 1398}
b7cfce93
MK
1399
1400/*
1401 * Add neighbor entry.
1402 */
72de4110
DS
1403static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
1404 const struct ipaddr *ip,
1405 const struct ethaddr *mac)
b7cfce93 1406{
72de4110
DS
1407 struct zebra_neigh tmp_n;
1408 struct zebra_neigh *n = NULL;
b7cfce93 1409
72de4110 1410 memset(&tmp_n, 0, sizeof(struct zebra_neigh));
b7cfce93
MK
1411 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
1412 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
1413 assert(n);
1414
85442b09 1415 RB_INIT(host_rb_tree_entry, &n->host_rb);
6134fd82 1416
b7cfce93 1417 memcpy(&n->emac, mac, ETH_ALEN);
2dbad57f 1418 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
1419 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
b7cfce93
MK
1420
1421 return n;
2dbad57f 1422}
b7cfce93
MK
1423
1424/*
1425 * Delete neighbor entry.
1426 */
72de4110 1427static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
b7cfce93 1428{
72de4110 1429 struct zebra_neigh *tmp_n;
f2a503f0 1430 struct host_rb_entry *hle;
b7cfce93 1431
85442b09
DS
1432 while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
1433 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
f2a503f0 1434
85442b09 1435 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
f2a503f0
DS
1436 XFREE(MTYPE_HOST_PREFIX, hle);
1437 }
55aabf6f 1438
b7cfce93 1439 tmp_n = hash_release(zl3vni->nh_table, n);
7cbae20a 1440 XFREE(MTYPE_L3NEIGH, tmp_n);
b7cfce93
MK
1441
1442 return 0;
2dbad57f 1443}
b7cfce93
MK
1444
1445/*
1446 * Install remote nh as neigh into the kernel.
1447 */
72de4110 1448static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
b7cfce93 1449{
68e33151
CS
1450 uint8_t flags;
1451 int ret = 0;
1452
b7cfce93
MK
1453 if (!is_l3vni_oper_up(zl3vni))
1454 return -1;
1455
996c9314
LB
1456 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
1457 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93 1458 return 0;
931fa60c
MS
1459
1460 flags = DPLANE_NTF_EXT_LEARNED;
68e33151 1461 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
931fa60c
MS
1462 flags |= DPLANE_NTF_ROUTER;
1463
f188e68e
AK
1464 dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags,
1465 false /*was_static*/);
931fa60c 1466
68e33151 1467 return ret;
2dbad57f 1468}
b7cfce93
MK
1469
1470/*
1471 * Uninstall remote nh from the kernel.
1472 */
72de4110
DS
1473static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
1474 struct zebra_neigh *n)
b7cfce93 1475{
996c9314
LB
1476 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
1477 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93
MK
1478 return 0;
1479
fa409e1e 1480 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
1481 return 0;
1482
f188e68e 1483 dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip);
931fa60c
MS
1484
1485 return 0;
2dbad57f 1486}
1487
1488/* add remote vtep as a neigh entry */
05843a27 1489static int zl3vni_remote_nh_add(struct zebra_l3vni *zl3vni,
e4a1ec74
MS
1490 const struct ipaddr *vtep_ip,
1491 const struct ethaddr *rmac,
1492 const struct prefix *host_prefix)
2dbad57f 1493{
72de4110 1494 struct zebra_neigh *nh = NULL;
2dbad57f 1495
651fa905 1496 /* Create the next hop entry, or update its mac, if necessary. */
2dbad57f 1497 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
1498 if (!nh) {
1499 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
1500 if (!nh) {
9df414fe 1501 zlog_debug(
ef7b8be4
DL
1502 "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
1503 vtep_ip, rmac, zl3vni->vni, host_prefix);
2dbad57f 1504 return -1;
1505 }
1506
1507 /* install the nh neigh in kernel */
1508 zl3vni_nh_install(zl3vni, nh);
651fa905
CS
1509 } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) {
1510 if (IS_ZEBRA_DEBUG_VXLAN)
2dbe669b 1511 zlog_debug(
ef7b8be4
DL
1512 "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
1513 zl3vni->vni, &nh->emac, rmac, vtep_ip,
2dbe669b 1514 host_prefix);
651fa905
CS
1515
1516 memcpy(&nh->emac, rmac, ETH_ALEN);
1517 /* install (update) the nh neigh in kernel */
1518 zl3vni_nh_install(zl3vni, nh);
2dbad57f 1519 }
6134fd82 1520
f2a503f0 1521 rb_find_or_add_host(&nh->host_rb, host_prefix);
6134fd82 1522
2dbad57f 1523 return 0;
1524}
1525
1526/* handle nh neigh delete */
72de4110
DS
1527static void zl3vni_remote_nh_del(struct zebra_l3vni *zl3vni,
1528 struct zebra_neigh *nh,
22e63104 1529 struct prefix *host_prefix)
2dbad57f 1530{
f2a503f0 1531 rb_delete_host(&nh->host_rb, host_prefix);
2dbad57f 1532
85442b09 1533 if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
2dbad57f 1534 /* uninstall from kernel */
1535 zl3vni_nh_uninstall(zl3vni, nh);
1536
1537 /* delete the nh entry */
1538 zl3vni_nh_del(zl3vni, nh);
1539 }
2dbad57f 1540}
b7cfce93 1541
3bcbba10 1542/* handle neigh update from kernel - the only thing of interest is to
1543 * readd stale entries.
1544 */
05843a27
DS
1545static int zl3vni_local_nh_add_update(struct zebra_l3vni *zl3vni,
1546 struct ipaddr *ip, uint16_t state)
3bcbba10 1547{
c05a738b 1548#ifdef GNU_LINUX
72de4110 1549 struct zebra_neigh *n = NULL;
3bcbba10 1550
1551 n = zl3vni_nh_lookup(zl3vni, ip);
1552 if (!n)
1553 return 0;
1554
1555 /* all next hop neigh are remote and installed by frr.
1556 * If the kernel has aged this entry, re-install.
1557 */
1558 if (state & NUD_STALE)
1559 zl3vni_nh_install(zl3vni, n);
c05a738b 1560#endif
3bcbba10 1561 return 0;
1562}
1563
8c9b80b9 1564/* handle neigh delete from kernel */
05843a27 1565static int zl3vni_local_nh_del(struct zebra_l3vni *zl3vni, struct ipaddr *ip)
8c9b80b9 1566{
72de4110 1567 struct zebra_neigh *n = NULL;
8c9b80b9
MK
1568
1569 n = zl3vni_nh_lookup(zl3vni, ip);
1570 if (!n)
1571 return 0;
1572
1573 /* all next hop neigh are remote and installed by frr.
1574 * If we get an age out notification for these neigh entries, we have to
523cafc4 1575 * install it back
1576 */
8c9b80b9
MK
1577 zl3vni_nh_install(zl3vni, n);
1578
1579 return 0;
1580}
1581
b7cfce93
MK
1582/*
1583 * Hash function for L3 VNI.
1584 */
d8b87afe 1585static unsigned int l3vni_hash_keymake(const void *p)
b7cfce93 1586{
05843a27 1587 const struct zebra_l3vni *zl3vni = p;
b7cfce93
MK
1588
1589 return jhash_1word(zl3vni->vni, 0);
1590}
1591
1592/*
1593 * Compare 2 L3 VNI hash entries.
1594 */
74df8d6d 1595static bool l3vni_hash_cmp(const void *p1, const void *p2)
b7cfce93 1596{
05843a27
DS
1597 const struct zebra_l3vni *zl3vni1 = p1;
1598 const struct zebra_l3vni *zl3vni2 = p2;
b7cfce93
MK
1599
1600 return (zl3vni1->vni == zl3vni2->vni);
1601}
1602
1603/*
1604 * Callback to allocate L3 VNI hash entry.
1605 */
1606static void *zl3vni_alloc(void *p)
1607{
05843a27
DS
1608 struct zebra_l3vni *zl3vni = NULL;
1609 const struct zebra_l3vni *tmp_l3vni = p;
b7cfce93 1610
05843a27 1611 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(struct zebra_l3vni));
b7cfce93
MK
1612 zl3vni->vni = tmp_l3vni->vni;
1613 return ((void *)zl3vni);
1614}
1615
1616/*
1617 * Look up L3 VNI hash entry.
1618 */
05843a27 1619struct zebra_l3vni *zl3vni_lookup(vni_t vni)
b7cfce93 1620{
05843a27
DS
1621 struct zebra_l3vni tmp_l3vni;
1622 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1623
05843a27 1624 memset(&tmp_l3vni, 0, sizeof(struct zebra_l3vni));
b7cfce93 1625 tmp_l3vni.vni = vni;
89272910 1626 zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni);
b7cfce93
MK
1627
1628 return zl3vni;
1629}
1630
1631/*
1632 * Add L3 VNI hash entry.
1633 */
05843a27 1634static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
b7cfce93 1635{
05843a27
DS
1636 struct zebra_l3vni tmp_zl3vni;
1637 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1638
05843a27 1639 memset(&tmp_zl3vni, 0, sizeof(struct zebra_l3vni));
b7cfce93
MK
1640 tmp_zl3vni.vni = vni;
1641
89272910 1642 zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc);
b7cfce93
MK
1643 assert(zl3vni);
1644
1645 zl3vni->vrf_id = vrf_id;
1646 zl3vni->svi_if = NULL;
1647 zl3vni->vxlan_if = NULL;
1648 zl3vni->l2vnis = list_new();
8b5fdf2e 1649 zl3vni->l2vnis->cmp = zebra_evpn_list_cmp;
b7cfce93
MK
1650
1651 /* Create hash table for remote RMAC */
b2998086 1652 zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
b7cfce93
MK
1653
1654 /* Create hash table for neighbors */
7cbae20a 1655 zl3vni->nh_table = zebra_neigh_db_create("Zebra L3-VNI next-hop table");
b7cfce93
MK
1656
1657 return zl3vni;
1658}
1659
1660/*
1661 * Delete L3 VNI hash entry.
1662 */
05843a27 1663static int zl3vni_del(struct zebra_l3vni *zl3vni)
b7cfce93 1664{
05843a27 1665 struct zebra_l3vni *tmp_zl3vni;
b7cfce93 1666
b7cfce93 1667 /* free the list of l2vnis */
6a154c88 1668 list_delete(&zl3vni->l2vnis);
b7cfce93
MK
1669 zl3vni->l2vnis = NULL;
1670
1671 /* Free the rmac table */
1672 hash_free(zl3vni->rmac_table);
1673 zl3vni->rmac_table = NULL;
1674
1675 /* Free the nh table */
1676 hash_free(zl3vni->nh_table);
1677 zl3vni->nh_table = NULL;
1678
1679 /* Free the VNI hash entry and allocated memory. */
89272910 1680 tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
0a22ddfb 1681 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
b7cfce93
MK
1682
1683 return 0;
1684}
1685
2961d060
PG
1686static int zl3vni_map_to_vxlan_if_ns(struct ns *ns,
1687 void *_zl3vni,
1688 void **_pifp)
b7cfce93 1689{
2961d060 1690 struct zebra_ns *zns = ns->info;
05843a27 1691 struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)_zl3vni;
b7cfce93
MK
1692 struct route_node *rn = NULL;
1693 struct interface *ifp = NULL;
07509878
PG
1694 struct zebra_vrf *zvrf;
1695
1696 zvrf = zebra_vrf_get_evpn();
1697
1698 if (!zvrf)
2961d060 1699 return NS_WALK_STOP;
b7cfce93
MK
1700
1701 /* loop through all vxlan-interface */
b7cfce93
MK
1702 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1703
1704 struct zebra_if *zif = NULL;
1705 struct zebra_l2info_vxlan *vxl = NULL;
1706
1707 ifp = (struct interface *)rn->info;
1708 if (!ifp)
1709 continue;
1710
1711 zif = ifp->info;
1712 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1713 continue;
1714
1715 vxl = &zif->l2info.vxl;
07509878
PG
1716 if (vxl->vni != zl3vni->vni)
1717 continue;
1718
1719 /* link of VXLAN interface should be in zebra_evpn_vrf */
1720 if (zvrf->zns->ns_id != vxl->link_nsid) {
1721 if (IS_ZEBRA_DEBUG_VXLAN)
1722 zlog_debug(
1723 "Intf %s(%u) VNI %u, link not in same "
1724 "namespace than BGP EVPN core instance ",
1725 ifp->name, ifp->ifindex, vxl->vni);
1726 continue;
b67a60d2 1727 }
07509878
PG
1728
1729
1730 zl3vni->local_vtep_ip = vxl->vtep_ip;
1731 if (_pifp)
1732 *_pifp = (void *)ifp;
2961d060 1733 return NS_WALK_STOP;
b7cfce93
MK
1734 }
1735
2961d060 1736 return NS_WALK_CONTINUE;
07509878
PG
1737}
1738
05843a27 1739struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni)
07509878
PG
1740{
1741 struct interface **p_ifp;
1742 struct interface *ifp = NULL;
1743
1744 p_ifp = &ifp;
1745
2961d060
PG
1746 ns_walk_func(zl3vni_map_to_vxlan_if_ns,
1747 (void *)zl3vni, (void **)p_ifp);
07509878 1748 return ifp;
b7cfce93
MK
1749}
1750
05843a27 1751struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni)
b7cfce93 1752{
996c9314 1753 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
b7cfce93
MK
1754 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
1755
2aeb403d 1756 if (!zl3vni)
1757 return NULL;
1758
b7cfce93
MK
1759 if (!zl3vni->vxlan_if)
1760 return NULL;
1761
1762 zif = zl3vni->vxlan_if->info;
1763 if (!zif)
1764 return NULL;
1765
1766 vxl = &zif->l2info.vxl;
1767
7cbae20a 1768 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
b7cfce93
MK
1769}
1770
05843a27 1771struct interface *zl3vni_map_to_mac_vlan_if(struct zebra_l3vni *zl3vni)
06d9cde5
CS
1772{
1773 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
1774
1775 if (!zl3vni)
1776 return NULL;
1777
1778 if (!zl3vni->vxlan_if)
1779 return NULL;
1780
1781 zif = zl3vni->vxlan_if->info;
1782 if (!zif)
1783 return NULL;
1784
8b5fdf2e
PR
1785 return zebra_evpn_map_to_macvlan(zif->brslave_info.br_if,
1786 zl3vni->svi_if);
06d9cde5
CS
1787}
1788
1789
05843a27 1790struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id)
b7cfce93
MK
1791{
1792 struct zebra_vrf *zvrf = NULL;
1793
1794 zvrf = zebra_vrf_lookup_by_id(vrf_id);
1795 if (!zvrf)
1796 return NULL;
1797
1798 return zl3vni_lookup(zvrf->l3vni);
1799}
1800
24907262
PG
1801static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
1802{
1803 int found = 0;
1804 struct zebra_ns *zns = ns->info;
1805 struct zebra_l3vni **p_zl3vni = (struct zebra_l3vni **)_p_zl3vni;
1806 struct zebra_from_svi_param *in_param =
1807 (struct zebra_from_svi_param *)_in_param;
1808 struct route_node *rn = NULL;
1809 struct interface *tmp_if = NULL;
1810 struct zebra_if *zif = NULL;
1811 struct zebra_l2info_vxlan *vxl = NULL;
1812
1813 if (!in_param)
1814 return NS_WALK_STOP;
1815
1816 /* loop through all vxlan-interface */
1817 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1818 tmp_if = (struct interface *)rn->info;
1819 if (!tmp_if)
1820 continue;
1821 zif = tmp_if->info;
1822 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1823 continue;
1824 if (!if_is_operative(tmp_if))
1825 continue;
1826 vxl = &zif->l2info.vxl;
1827
1828 if (zif->brslave_info.br_if != in_param->br_if)
1829 continue;
1830
1831 if (!in_param->bridge_vlan_aware
1832 || vxl->access_vlan == in_param->vid) {
1833 found = 1;
1834 break;
1835 }
1836 }
1837
1838 if (!found)
1839 return NS_WALK_CONTINUE;
1840
1841 if (p_zl3vni)
1842 *p_zl3vni = zl3vni_lookup(vxl->vni);
1843 return NS_WALK_STOP;
1844}
1845
b7cfce93
MK
1846/*
1847 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1848 * neighbor notifications, to see if they are of interest.
1849 */
05843a27
DS
1850static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
1851 struct interface *br_if)
b7cfce93 1852{
05843a27 1853 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1854 struct zebra_if *zif = NULL;
b7cfce93 1855 struct zebra_l2info_bridge *br = NULL;
24907262
PG
1856 struct zebra_from_svi_param in_param = {};
1857 struct zebra_l3vni **p_zl3vni;
b7cfce93
MK
1858
1859 if (!br_if)
1860 return NULL;
1861
1862 /* Make sure the linked interface is a bridge. */
1863 if (!IS_ZEBRA_IF_BRIDGE(br_if))
1864 return NULL;
24907262 1865 in_param.br_if = br_if;
b7cfce93
MK
1866
1867 /* Determine if bridge is VLAN-aware or not */
1868 zif = br_if->info;
1869 assert(zif);
1870 br = &zif->l2info.br;
24907262
PG
1871 in_param.bridge_vlan_aware = br->vlan_aware;
1872 if (in_param.bridge_vlan_aware) {
b7cfce93
MK
1873 struct zebra_l2info_vlan *vl;
1874
1875 if (!IS_ZEBRA_IF_VLAN(ifp))
1876 return NULL;
1877
1878 zif = ifp->info;
1879 assert(zif);
1880 vl = &zif->l2info.vl;
24907262 1881 in_param.vid = vl->vid;
b7cfce93
MK
1882 }
1883
1884 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1885 /* TODO: Optimize with a hash. */
b7cfce93 1886
24907262 1887 p_zl3vni = &zl3vni;
b7cfce93 1888
24907262 1889 ns_walk_func(zl3vni_from_svi_ns, (void *)&in_param, (void **)p_zl3vni);
b7cfce93
MK
1890 return zl3vni;
1891}
1892
1b09e77e
AD
1893vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if)
1894{
1895 vni_t vni = 0;
f6371c34 1896 struct zebra_evpn *zevpn = NULL;
05843a27 1897 struct zebra_l3vni *zl3vni = NULL;
1b09e77e
AD
1898
1899 /* Check if an L3VNI belongs to this SVI interface.
1900 * If not, check if an L2VNI belongs to this SVI interface.
1901 */
1902 zl3vni = zl3vni_from_svi(ifp, br_if);
1903 if (zl3vni)
1904 vni = zl3vni->vni;
1905 else {
1906 zevpn = zebra_evpn_from_svi(ifp, br_if);
1907 if (zevpn)
1908 vni = zevpn->vni;
1909 }
1910
1911 return vni;
1912}
1913
05843a27 1914static inline void zl3vni_get_vrr_rmac(struct zebra_l3vni *zl3vni,
06d9cde5
CS
1915 struct ethaddr *rmac)
1916{
1917 if (!zl3vni)
1918 return;
1919
1920 if (!is_l3vni_oper_up(zl3vni))
1921 return;
1922
1923 if (zl3vni->mac_vlan_if && if_is_operative(zl3vni->mac_vlan_if))
1924 memcpy(rmac->octet, zl3vni->mac_vlan_if->hw_addr, ETH_ALEN);
1925}
1926
b7cfce93
MK
1927/*
1928 * Inform BGP about l3-vni.
1929 */
05843a27 1930static int zl3vni_send_add_to_client(struct zebra_l3vni *zl3vni)
b7cfce93
MK
1931{
1932 struct stream *s = NULL;
1933 struct zserv *client = NULL;
06d9cde5
CS
1934 struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
1935 struct zebra_vrf *zvrf;
06d9cde5 1936 bool is_anycast_mac = true;
b7cfce93 1937
21ccc0cf 1938 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
1939 /* BGP may not be running. */
1940 if (!client)
1941 return 0;
1942
06d9cde5
CS
1943 zvrf = zebra_vrf_lookup_by_id(zl3vni->vrf_id);
1944 assert(zvrf);
1945
1946 /* get the svi and vrr rmac values */
1947 memset(&svi_rmac, 0, sizeof(struct ethaddr));
1948 zl3vni_get_svi_rmac(zl3vni, &svi_rmac);
1949 zl3vni_get_vrr_rmac(zl3vni, &vrr_rmac);
1950
1951 /* In absence of vrr mac use svi mac as anycast MAC value */
1952 if (is_zero_mac(&vrr_rmac)) {
1953 memcpy(&vrr_rmac, &svi_rmac, ETH_ALEN);
1954 is_anycast_mac = false;
1955 }
b7cfce93 1956
1002497a 1957 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 1958
06d9cde5
CS
1959 /* The message is used for both vni add and/or update like
1960 * vrr mac is added for l3vni SVI.
1961 */
996c9314 1962 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
b7cfce93 1963 stream_putl(s, zl3vni->vni);
06d9cde5 1964 stream_put(s, &svi_rmac, sizeof(struct ethaddr));
b67a60d2 1965 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
c48d9f5f 1966 stream_put(s, &zl3vni->filter, sizeof(int));
0483af6e 1967 stream_putl(s, zl3vni->svi_if->ifindex);
06d9cde5
CS
1968 stream_put(s, &vrr_rmac, sizeof(struct ethaddr));
1969 stream_putl(s, is_anycast_mac);
b7cfce93
MK
1970
1971 /* Write packet size. */
1972 stream_putw_at(s, 0, stream_get_endp(s));
1973
1974 if (IS_ZEBRA_DEBUG_VXLAN)
c48d9f5f 1975 zlog_debug(
ef7b8be4 1976 "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
996c9314 1977 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
ef7b8be4 1978 &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
996c9314
LB
1979 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
1980 ? "prefix-routes-only"
1981 : "none",
1982 zebra_route_string(client->proto));
b7cfce93
MK
1983
1984 client->l3vniadd_cnt++;
21ccc0cf 1985 return zserv_send_message(client, s);
b7cfce93
MK
1986}
1987
1988/*
1989 * Inform BGP about local l3-VNI deletion.
1990 */
05843a27 1991static int zl3vni_send_del_to_client(struct zebra_l3vni *zl3vni)
b7cfce93
MK
1992{
1993 struct stream *s = NULL;
1994 struct zserv *client = NULL;
1995
21ccc0cf 1996 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
1997 /* BGP may not be running. */
1998 if (!client)
1999 return 0;
2000
1002497a 2001 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 2002
996c9314 2003 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
2004 stream_putl(s, zl3vni->vni);
2005
2006 /* Write packet size. */
2007 stream_putw_at(s, 0, stream_get_endp(s));
2008
2009 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 2010 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
b7cfce93
MK
2011 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
2012 zebra_route_string(client->proto));
2013
2014 client->l3vnidel_cnt++;
21ccc0cf 2015 return zserv_send_message(client, s);
b7cfce93
MK
2016}
2017
05843a27 2018static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni)
b7cfce93 2019{
2aeb403d 2020 if (!zl3vni)
2021 return;
2022
b7cfce93
MK
2023 /* send l3vni add to BGP */
2024 zl3vni_send_add_to_client(zl3vni);
2025}
2026
05843a27 2027static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni)
b7cfce93 2028{
2aeb403d 2029 if (!zl3vni)
2030 return;
2031
b7cfce93
MK
2032 /* send l3-vni del to BGP*/
2033 zl3vni_send_del_to_client(zl3vni);
2034}
2035
7cbae20a 2036static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
b169fd6f 2037{
f6371c34 2038 struct zebra_evpn *zevpn = (struct zebra_evpn *)bucket->data;
05843a27 2039 struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)ctxt;
b169fd6f 2040
7cbae20a
PR
2041 if (zevpn->vrf_id == zl3vni_vrf_id(zl3vni))
2042 listnode_add_sort(zl3vni->l2vnis, zevpn);
b169fd6f
AK
2043}
2044
7cbae20a 2045/*
3b0a590b
AD
2046 * Handle transition of vni from l2 to l3 and vice versa.
2047 * This function handles only the L2VNI add/delete part of
2048 * the above transition.
2049 * L3VNI add/delete is handled by the calling functions.
7cbae20a
PR
2050 */
2051static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
2052 int add)
b169fd6f 2053{
f6371c34 2054 struct zebra_evpn *zevpn = NULL;
b169fd6f 2055
7cbae20a
PR
2056 /* There is a possibility that VNI notification was already received
2057 * from kernel and we programmed it as L2-VNI
2058 * In such a case we need to delete this L2-VNI first, so
2059 * that it can be reprogrammed as L3-VNI in the system. It is also
2060 * possible that the vrf-vni mapping is removed from FRR while the vxlan
2061 * interface is still present in kernel. In this case to keep it
2062 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
2063 */
2064 if (add) {
2065 /* Locate hash entry */
8b5fdf2e 2066 zevpn = zebra_evpn_lookup(vni);
7cbae20a
PR
2067 if (!zevpn)
2068 return 0;
b169fd6f 2069
7cbae20a
PR
2070 if (IS_ZEBRA_DEBUG_VXLAN)
2071 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
b169fd6f 2072
7cbae20a 2073 /* Delete EVPN from BGP. */
8b5fdf2e 2074 zebra_evpn_send_del_to_client(zevpn);
b169fd6f 2075
7cbae20a
PR
2076 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
2077 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
b169fd6f 2078
7cbae20a 2079 /* Free up all remote VTEPs, if any. */
8b5fdf2e 2080 zebra_evpn_vtep_del_all(zevpn, 0);
b169fd6f 2081
7cbae20a 2082 /* Delete the hash entry. */
8b5fdf2e 2083 if (zebra_evpn_vxlan_del(zevpn)) {
7cbae20a
PR
2084 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
2085 "Failed to del EVPN hash %p, VNI %u", zevpn,
2086 zevpn->vni);
2087 return -1;
b169fd6f 2088 }
7cbae20a 2089 } else {
3b0a590b
AD
2090 struct zebra_ns *zns;
2091 struct route_node *rn;
2092 struct interface *ifp;
2093 struct zebra_if *zif;
2094 struct zebra_l2info_vxlan *vxl;
2095 struct interface *vlan_if;
2096 bool found = false;
2097
2098 if (IS_ZEBRA_DEBUG_VXLAN)
2099 zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
2100 vni);
2101
2102 /* Find VxLAN interface for this VNI. */
2103 zns = zebra_ns_lookup(NS_DEFAULT);
2104 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2105 ifp = (struct interface *)rn->info;
2106 if (!ifp)
2107 continue;
2108 zif = ifp->info;
2109 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2110 continue;
2111
2112 vxl = &zif->l2info.vxl;
2113 if (vxl->vni == vni) {
2114 found = true;
2115 break;
2116 }
2117 }
2118
2119 if (!found) {
2120 if (IS_ZEBRA_DEBUG_VXLAN)
2121 zlog_err(
2122 "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
2123 vni);
2124 return -1;
2125 }
2126
2127 /* Create VNI hash entry for L2VNI */
2128 zevpn = zebra_evpn_lookup(vni);
2129 if (zevpn)
2130 return 0;
2131
2132 zevpn = zebra_evpn_add(vni);
2133 if (!zevpn) {
2134 flog_err(EC_ZEBRA_VNI_ADD_FAILED,
2135 "Adding L2-VNI - Failed to add VNI hash, VNI %u",
2136 vni);
2137
2138 return -1;
2139 }
2140
2141 /* Find bridge interface for the VNI */
2142 vlan_if = zvni_map_to_svi(vxl->access_vlan,
2143 zif->brslave_info.br_if);
2144 if (vlan_if)
2145 zevpn->vrf_id = vlan_if->vrf_id;
2146
2147 zevpn->vxlan_if = ifp;
2148 zevpn->local_vtep_ip = vxl->vtep_ip;
2149
2150 /* Inform BGP if the VNI is up and mapped to a bridge. */
2151 if (if_is_operative(ifp) && zif->brslave_info.br_if) {
2152 zebra_evpn_send_add_to_client(zevpn);
2153 zebra_evpn_read_mac_neigh(zevpn, ifp);
2154 }
b169fd6f
AK
2155 }
2156
7cbae20a 2157 return 0;
b169fd6f
AK
2158}
2159
7cbae20a
PR
2160/* delete and uninstall rmac hash entry */
2161static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
b169fd6f 2162{
3198b2b3 2163 struct zebra_mac *zrmac = NULL;
05843a27 2164 struct zebra_l3vni *zl3vni = NULL;
b169fd6f 2165
3198b2b3 2166 zrmac = (struct zebra_mac *)bucket->data;
05843a27 2167 zl3vni = (struct zebra_l3vni *)ctx;
7cbae20a 2168 zl3vni_rmac_uninstall(zl3vni, zrmac);
b169fd6f 2169
7cbae20a
PR
2170 /* Send RMAC for FPM processing */
2171 hook_call(zebra_rmac_update, zrmac, zl3vni, true, "RMAC deleted");
b169fd6f 2172
7cbae20a 2173 zl3vni_rmac_del(zl3vni, zrmac);
b169fd6f
AK
2174}
2175
7cbae20a
PR
2176/* delete and uninstall nh hash entry */
2177static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
b169fd6f 2178{
72de4110 2179 struct zebra_neigh *n = NULL;
05843a27 2180 struct zebra_l3vni *zl3vni = NULL;
b169fd6f 2181
72de4110 2182 n = (struct zebra_neigh *)bucket->data;
05843a27 2183 zl3vni = (struct zebra_l3vni *)ctx;
7cbae20a
PR
2184 zl3vni_nh_uninstall(zl3vni, n);
2185 zl3vni_nh_del(zl3vni, n);
2186}
b169fd6f 2187
7cbae20a 2188/* re-add remote rmac if needed */
05843a27 2189static int zebra_vxlan_readd_remote_rmac(struct zebra_l3vni *zl3vni,
7cbae20a
PR
2190 struct ethaddr *rmac)
2191{
3198b2b3 2192 struct zebra_mac *zrmac = NULL;
7cbae20a
PR
2193
2194 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
2195 if (!zrmac)
2196 return 0;
2197
2198 if (IS_ZEBRA_DEBUG_VXLAN)
ef7b8be4
DL
2199 zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
2200 rmac, zl3vni->vni);
7cbae20a
PR
2201
2202 zl3vni_rmac_install(zl3vni, zrmac);
2203 return 0;
b169fd6f
AK
2204}
2205
b7cfce93
MK
2206/* Public functions */
2207
c48d9f5f
MK
2208int is_l3vni_for_prefix_routes_only(vni_t vni)
2209{
05843a27 2210 struct zebra_l3vni *zl3vni = NULL;
c48d9f5f
MK
2211
2212 zl3vni = zl3vni_lookup(vni);
2213 if (!zl3vni)
2214 return 0;
2215
2216 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
2217}
2218
2dbad57f 2219/* handle evpn route in vrf table */
e4a1ec74
MS
2220void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
2221 const struct ipaddr *vtep_ip,
2222 const struct prefix *host_prefix)
2dbad57f 2223{
05843a27 2224 struct zebra_l3vni *zl3vni = NULL;
f50dc5e6 2225 struct ipaddr ipv4_vtep;
2dbad57f 2226
2227 zl3vni = zl3vni_from_vrf(vrf_id);
2228 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
2229 return;
2230
3518f352 2231 /*
f50dc5e6
MK
2232 * add the next hop neighbor -
2233 * neigh to be installed is the ipv6 nexthop neigh
2234 */
3518f352 2235 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
2dbad57f 2236
f50dc5e6
MK
2237 /*
2238 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
2239 * address. Rmac is programmed against the ipv4 vtep because we only
2240 * support ipv4 tunnels in the h/w right now
2241 */
2242 memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
2243 ipv4_vtep.ipa_type = IPADDR_V4;
2244 if (vtep_ip->ipa_type == IPADDR_V6)
2245 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
2246 &(ipv4_vtep.ipaddr_v4));
2247 else
2248 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
2249 sizeof(struct in_addr));
2250
3518f352
DS
2251 /*
2252 * add the rmac - remote rmac to be installed is against the ipv4
f50dc5e6
MK
2253 * nexthop address
2254 */
3518f352 2255 zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
2dbad57f 2256}
2257
2258/* handle evpn vrf route delete */
22e63104 2259void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
996c9314
LB
2260 struct ipaddr *vtep_ip,
2261 struct prefix *host_prefix)
2dbad57f 2262{
05843a27 2263 struct zebra_l3vni *zl3vni = NULL;
72de4110 2264 struct zebra_neigh *nh = NULL;
3198b2b3 2265 struct zebra_mac *zrmac = NULL;
2dbad57f 2266
2267 zl3vni = zl3vni_from_vrf(vrf_id);
5e06422c 2268 if (!zl3vni)
2dbad57f 2269 return;
2270
22e63104 2271 /* find the next hop entry and rmac entry */
2272 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
2273 if (!nh)
2274 return;
2275 zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
2276
2dbad57f 2277 /* delete the next hop entry */
22e63104 2278 zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
2dbad57f 2279
2280 /* delete the rmac entry */
22e63104 2281 if (zrmac)
2282 zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
2283
2dbad57f 2284}
2285
996c9314 2286void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
9f049418 2287 struct ethaddr *rmac, bool use_json)
9aa741ea 2288{
05843a27 2289 struct zebra_l3vni *zl3vni = NULL;
3198b2b3 2290 struct zebra_mac *zrmac = NULL;
316f4ca4 2291 json_object *json = NULL;
9aa741ea 2292
316f4ca4
MK
2293 if (!is_evpn_enabled()) {
2294 if (use_json)
2295 vty_out(vty, "{}\n");
9aa741ea 2296 return;
316f4ca4
MK
2297 }
2298
2299 if (use_json)
2300 json = json_object_new_object();
9aa741ea
MK
2301
2302 zl3vni = zl3vni_lookup(l3vni);
2303 if (!zl3vni) {
316f4ca4
MK
2304 if (use_json)
2305 vty_out(vty, "{}\n");
2306 else
0437e105 2307 vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
9aa741ea
MK
2308 return;
2309 }
2310
2311 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
2312 if (!zrmac) {
316f4ca4
MK
2313 if (use_json)
2314 vty_out(vty, "{}\n");
2315 else
2316 vty_out(vty,
0437e105 2317 "%% Requested RMAC doesn't exist in L3-VNI %u",
316f4ca4 2318 l3vni);
9aa741ea
MK
2319 return;
2320 }
2321
316f4ca4
MK
2322 zl3vni_print_rmac(zrmac, vty, json);
2323
2324 if (use_json) {
2325 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2326 json, JSON_C_TO_STRING_PRETTY));
2327 json_object_free(json);
2328 }
9aa741ea 2329}
2dbad57f 2330
9f049418 2331void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93 2332{
05843a27 2333 struct zebra_l3vni *zl3vni;
d7c0a89a 2334 uint32_t num_rmacs;
b7cfce93
MK
2335 struct rmac_walk_ctx wctx;
2336 json_object *json = NULL;
b7cfce93
MK
2337
2338 if (!is_evpn_enabled())
2339 return;
2340
2341 zl3vni = zl3vni_lookup(l3vni);
2342 if (!zl3vni) {
2343 if (use_json)
2344 vty_out(vty, "{}\n");
2345 else
2346 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
2347 return;
2348 }
2349 num_rmacs = hashcount(zl3vni->rmac_table);
2350 if (!num_rmacs)
2351 return;
2352
75223c9e 2353 if (use_json)
b7cfce93 2354 json = json_object_new_object();
b7cfce93
MK
2355
2356 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
2357 wctx.vty = vty;
75223c9e 2358 wctx.json = json;
b7cfce93 2359 if (!use_json) {
996c9314 2360 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
b7cfce93 2361 num_rmacs);
4cce389e 2362 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
b7cfce93
MK
2363 } else
2364 json_object_int_add(json, "numRmacs", num_rmacs);
2365
2366 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
2367
2368 if (use_json) {
b7cfce93
MK
2369 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2370 json, JSON_C_TO_STRING_PRETTY));
2371 json_object_free(json);
2372 }
2373}
2374
9f049418 2375void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 2376{
b7cfce93 2377 json_object *json = NULL;
c0b4eaa4 2378 void *args[2];
b7cfce93
MK
2379
2380 if (!is_evpn_enabled()) {
2381 if (use_json)
2382 vty_out(vty, "{}\n");
2383 return;
2384 }
2385
b7cfce93
MK
2386 if (use_json)
2387 json = json_object_new_object();
2388
c0b4eaa4
MK
2389 args[0] = vty;
2390 args[1] = json;
89272910 2391 hash_iterate(zrouter.l3vni_table,
e3b78da8 2392 (void (*)(struct hash_bucket *,
c0b4eaa4
MK
2393 void *))zl3vni_print_rmac_hash_all_vni,
2394 args);
b7cfce93
MK
2395
2396 if (use_json) {
2397 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2398 json, JSON_C_TO_STRING_PRETTY));
2399 json_object_free(json);
2400 }
2401}
2402
996c9314 2403void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
9f049418 2404 struct ipaddr *ip, bool use_json)
9aa741ea 2405{
05843a27 2406 struct zebra_l3vni *zl3vni = NULL;
72de4110 2407 struct zebra_neigh *n = NULL;
c0e519d3 2408 json_object *json = NULL;
9aa741ea 2409
c0e519d3
MK
2410 if (!is_evpn_enabled()) {
2411 if (use_json)
2412 vty_out(vty, "{}\n");
9aa741ea 2413 return;
c0e519d3
MK
2414 }
2415
2416 if (use_json)
2417 json = json_object_new_object();
9aa741ea
MK
2418
2419 zl3vni = zl3vni_lookup(l3vni);
2420 if (!zl3vni) {
c0e519d3
MK
2421 if (use_json)
2422 vty_out(vty, "{}\n");
2423 else
2424 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
9aa741ea
MK
2425 return;
2426 }
2427
2428 n = zl3vni_nh_lookup(zl3vni, ip);
2429 if (!n) {
c0e519d3
MK
2430 if (use_json)
2431 vty_out(vty, "{}\n");
2432 else
2433 vty_out(vty,
2434 "%% Requested next-hop not present for L3-VNI %u",
2435 l3vni);
9aa741ea
MK
2436 return;
2437 }
2438
c0e519d3
MK
2439 zl3vni_print_nh(n, vty, json);
2440
2441 if (use_json) {
2442 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2443 json, JSON_C_TO_STRING_PRETTY));
2444 json_object_free(json);
2445 }
9aa741ea
MK
2446}
2447
9f049418 2448void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93 2449{
d7c0a89a 2450 uint32_t num_nh;
2dbad57f 2451 struct nh_walk_ctx wctx;
b7cfce93 2452 json_object *json = NULL;
05843a27 2453 struct zebra_l3vni *zl3vni = NULL;
b7cfce93
MK
2454
2455 if (!is_evpn_enabled())
2456 return;
2457
2458 zl3vni = zl3vni_lookup(l3vni);
2459 if (!zl3vni) {
2460 if (use_json)
2461 vty_out(vty, "{}\n");
2462 else
2463 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
2464 return;
2465 }
2466
2467 num_nh = hashcount(zl3vni->nh_table);
2468 if (!num_nh)
2469 return;
2470
9187f600 2471 if (use_json)
b7cfce93 2472 json = json_object_new_object();
b7cfce93 2473
2dbad57f 2474 wctx.vty = vty;
9187f600 2475 wctx.json = json;
b7cfce93 2476 if (!use_json) {
996c9314 2477 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
b7cfce93 2478 num_nh);
4cce389e 2479 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
b7cfce93 2480 } else
4cce389e 2481 json_object_int_add(json, "numNextHops", num_nh);
b7cfce93
MK
2482
2483 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
2484
2485 if (use_json) {
b7cfce93
MK
2486 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2487 json, JSON_C_TO_STRING_PRETTY));
2488 json_object_free(json);
2489 }
2490}
2491
9f049418 2492void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 2493{
2dbad57f 2494 json_object *json = NULL;
32798965 2495 void *args[2];
2dbad57f 2496
2497 if (!is_evpn_enabled()) {
2498 if (use_json)
2499 vty_out(vty, "{}\n");
2500 return;
2501 }
2502
2dbad57f 2503 if (use_json)
2504 json = json_object_new_object();
2505
32798965
MK
2506 args[0] = vty;
2507 args[1] = json;
89272910 2508 hash_iterate(zrouter.l3vni_table,
e3b78da8 2509 (void (*)(struct hash_bucket *,
32798965
MK
2510 void *))zl3vni_print_nh_hash_all_vni,
2511 args);
2dbad57f 2512
2513 if (use_json) {
2514 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2515 json, JSON_C_TO_STRING_PRETTY));
2516 json_object_free(json);
2517 }
b7cfce93
MK
2518}
2519
2520/*
2521 * Display L3 VNI information (VTY command handler).
2522 */
9f049418 2523void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
b7cfce93
MK
2524{
2525 void *args[2];
2526 json_object *json = NULL;
05843a27 2527 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 2528
b2ee5a13
MK
2529 if (!is_evpn_enabled()) {
2530 if (use_json)
2531 vty_out(vty, "{}\n");
b7cfce93 2532 return;
b2ee5a13 2533 }
b7cfce93
MK
2534
2535 zl3vni = zl3vni_lookup(vni);
2536 if (!zl3vni) {
2537 if (use_json)
2538 vty_out(vty, "{}\n");
2539 else
2540 vty_out(vty, "%% VNI %u does not exist\n", vni);
2541 return;
2542 }
2543
2544 if (use_json)
2545 json = json_object_new_object();
2546
b2ee5a13
MK
2547 args[0] = vty;
2548 args[1] = json;
b7cfce93
MK
2549 zl3vni_print(zl3vni, (void *)args);
2550
2551 if (use_json) {
2552 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2553 json, JSON_C_TO_STRING_PRETTY));
2554 json_object_free(json);
2555 }
2556}
2557
4cce389e
MK
2558void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
2559 json_object *json_vrfs)
b7cfce93 2560{
4cce389e 2561 char buf[ETHER_ADDR_STRLEN];
05843a27 2562 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 2563
4cce389e
MK
2564 zl3vni = zl3vni_lookup(zvrf->l3vni);
2565 if (!zl3vni)
b7cfce93 2566 return;
b7cfce93 2567
4cce389e
MK
2568 if (!json_vrfs) {
2569 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
996c9314 2570 zvrf_name(zvrf), zl3vni->vni,
4cce389e 2571 zl3vni_vxlan_if_name(zl3vni),
996c9314 2572 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
4cce389e 2573 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
b7cfce93 2574 } else {
4cce389e 2575 json_object *json_vrf = NULL;
9df2b997 2576
4cce389e 2577 json_vrf = json_object_new_object();
996c9314 2578 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
4cce389e
MK
2579 json_object_int_add(json_vrf, "vni", zl3vni->vni);
2580 json_object_string_add(json_vrf, "vxlanIntf",
2581 zl3vni_vxlan_if_name(zl3vni));
2582 json_object_string_add(json_vrf, "sviIntf",
2583 zl3vni_svi_if_name(zl3vni));
2584 json_object_string_add(json_vrf, "state",
2585 zl3vni_state2str(zl3vni));
996c9314
LB
2586 json_object_string_add(
2587 json_vrf, "routerMac",
2588 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 2589 json_object_array_add(json_vrfs, json_vrf);
b7cfce93
MK
2590 }
2591}
2592
2593/*
2594 * Display Neighbors for a VNI (VTY command handler).
2595 */
2596void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 2597 vni_t vni, bool use_json)
b7cfce93 2598{
f6371c34 2599 struct zebra_evpn *zevpn;
d7c0a89a 2600 uint32_t num_neigh;
b7cfce93
MK
2601 struct neigh_walk_ctx wctx;
2602 json_object *json = NULL;
2603
2604 if (!is_evpn_enabled())
2605 return;
8b5fdf2e 2606 zevpn = zebra_evpn_lookup(vni);
87d76d54 2607 if (!zevpn) {
b7cfce93
MK
2608 if (use_json)
2609 vty_out(vty, "{}\n");
2610 else
2611 vty_out(vty, "%% VNI %u does not exist\n", vni);
2612 return;
2613 }
87d76d54 2614 num_neigh = hashcount(zevpn->neigh_table);
b7cfce93
MK
2615 if (!num_neigh)
2616 return;
2617
2618 if (use_json)
2619 json = json_object_new_object();
2620
2621 /* Since we have IPv6 addresses to deal with which can vary widely in
2622 * size, we try to be a bit more elegant in display by first computing
2623 * the maximum width.
2624 */
2625 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 2626 wctx.zevpn = zevpn;
b7cfce93
MK
2627 wctx.vty = vty;
2628 wctx.addr_width = 15;
2629 wctx.json = json;
7cbae20a
PR
2630 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2631 &wctx);
b7cfce93
MK
2632
2633 if (!use_json) {
2634 vty_out(vty,
2635 "Number of ARPs (local and remote) known for this VNI: %u\n",
2636 num_neigh);
7cbae20a 2637 zebra_evpn_print_neigh_hdr(vty, &wctx);
b7cfce93
MK
2638 } else
2639 json_object_int_add(json, "numArpNd", num_neigh);
2640
7cbae20a 2641 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
b7cfce93
MK
2642 if (use_json) {
2643 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2644 json, JSON_C_TO_STRING_PRETTY));
2645 json_object_free(json);
2646 }
2647}
2648
2649/*
2650 * Display neighbors across all VNIs (VTY command handler).
2651 */
2652void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 2653 bool print_dup, bool use_json)
b7cfce93
MK
2654{
2655 json_object *json = NULL;
1374d4db 2656 void *args[3];
b7cfce93
MK
2657
2658 if (!is_evpn_enabled())
2659 return;
2660
2661 if (use_json)
2662 json = json_object_new_object();
2663
2664 args[0] = vty;
2665 args[1] = json;
1374d4db
CS
2666 args[2] = (void *)(ptrdiff_t)print_dup;
2667
87d76d54 2668 hash_iterate(zvrf->evpn_table,
e3b78da8 2669 (void (*)(struct hash_bucket *,
87d76d54 2670 void *))zevpn_print_neigh_hash_all_evpn,
b7cfce93
MK
2671 args);
2672 if (use_json) {
2673 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2674 json, JSON_C_TO_STRING_PRETTY));
2675 json_object_free(json);
2676 }
2677}
2678
e3fac919
NS
2679/*
2680 * Display neighbors across all VNIs in detail(VTY command handler).
2681 */
2682void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
2683 struct zebra_vrf *zvrf,
2684 bool print_dup, bool use_json)
2685{
2686 json_object *json = NULL;
2687 void *args[3];
2688
2689 if (!is_evpn_enabled())
2690 return;
2691
2692 if (use_json)
2693 json = json_object_new_object();
2694
2695 args[0] = vty;
2696 args[1] = json;
2697 args[2] = (void *)(ptrdiff_t)print_dup;
2698
87d76d54 2699 hash_iterate(zvrf->evpn_table,
e3b78da8 2700 (void (*)(struct hash_bucket *,
87d76d54 2701 void *))zevpn_print_neigh_hash_all_evpn_detail,
e3fac919
NS
2702 args);
2703 if (use_json) {
2704 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2705 json, JSON_C_TO_STRING_PRETTY));
2706 json_object_free(json);
2707 }
2708}
2709
b7cfce93
MK
2710/*
2711 * Display specific neighbor for a VNI, if present (VTY command handler).
2712 */
2713void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
2714 struct zebra_vrf *zvrf, vni_t vni,
9f049418 2715 struct ipaddr *ip, bool use_json)
b7cfce93 2716{
f6371c34 2717 struct zebra_evpn *zevpn;
72de4110 2718 struct zebra_neigh *n;
b7cfce93
MK
2719 json_object *json = NULL;
2720
2721 if (!is_evpn_enabled())
2722 return;
8b5fdf2e 2723 zevpn = zebra_evpn_lookup(vni);
87d76d54 2724 if (!zevpn) {
b7cfce93 2725 if (use_json)
cd233079
CS
2726 vty_out(vty, "{}\n");
2727 else
2728 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2729 return;
2730 }
7cbae20a 2731 n = zebra_evpn_neigh_lookup(zevpn, ip);
d62a17ae 2732 if (!n) {
cd233079
CS
2733 if (!use_json)
2734 vty_out(vty,
2735 "%% Requested neighbor does not exist in VNI %u\n",
2736 vni);
d62a17ae 2737 return;
2738 }
cd233079
CS
2739 if (use_json)
2740 json = json_object_new_object();
2741
7cbae20a 2742 zebra_evpn_print_neigh(n, vty, json);
cec2e17d 2743
cd233079
CS
2744 if (use_json) {
2745 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2746 json, JSON_C_TO_STRING_PRETTY));
2747 json_object_free(json);
2748 }
cec2e17d 2749}
2750
2751/*
2752 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2753 * By definition, these are remote neighbors.
2754 */
d62a17ae 2755void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2756 vni_t vni, struct in_addr vtep_ip,
9f049418 2757 bool use_json)
cec2e17d 2758{
f6371c34 2759 struct zebra_evpn *zevpn;
d7c0a89a 2760 uint32_t num_neigh;
d62a17ae 2761 struct neigh_walk_ctx wctx;
cd233079 2762 json_object *json = NULL;
cec2e17d 2763
2853fed6 2764 if (!is_evpn_enabled())
d62a17ae 2765 return;
8b5fdf2e 2766 zevpn = zebra_evpn_lookup(vni);
87d76d54 2767 if (!zevpn) {
cd233079
CS
2768 if (use_json)
2769 vty_out(vty, "{}\n");
2770 else
2771 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2772 return;
2773 }
87d76d54 2774 num_neigh = hashcount(zevpn->neigh_table);
d62a17ae 2775 if (!num_neigh)
2776 return;
cec2e17d 2777
1cc5b093
PR
2778 if (use_json)
2779 json = json_object_new_object();
2780
d62a17ae 2781 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 2782 wctx.zevpn = zevpn;
d62a17ae 2783 wctx.vty = vty;
68e33151 2784 wctx.addr_width = 15;
d62a17ae 2785 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
2786 wctx.r_vtep_ip = vtep_ip;
cd233079 2787 wctx.json = json;
7cbae20a
PR
2788 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2789 &wctx);
2790 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
cd233079
CS
2791
2792 if (use_json) {
2793 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2794 json, JSON_C_TO_STRING_PRETTY));
2795 json_object_free(json);
2796 }
cec2e17d 2797}
2798
1374d4db
CS
2799/*
2800 * Display Duplicate detected Neighbors for a VNI
2801 * (VTY command handler).
2802 */
2803void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
2804 struct zebra_vrf *zvrf,
2805 vni_t vni,
2806 bool use_json)
2807{
f6371c34 2808 struct zebra_evpn *zevpn;
1374d4db
CS
2809 uint32_t num_neigh;
2810 struct neigh_walk_ctx wctx;
2811 json_object *json = NULL;
2812
2813 if (!is_evpn_enabled())
2814 return;
2815
8b5fdf2e 2816 zevpn = zebra_evpn_lookup(vni);
87d76d54 2817 if (!zevpn) {
1374d4db
CS
2818 vty_out(vty, "%% VNI %u does not exist\n", vni);
2819 return;
2820 }
2821
87d76d54 2822 num_neigh = hashcount(zevpn->neigh_table);
1374d4db
CS
2823 if (!num_neigh)
2824 return;
2825
87d76d54 2826 num_neigh = num_dup_detected_neighs(zevpn);
1374d4db
CS
2827 if (!num_neigh)
2828 return;
2829
2830 if (use_json)
2831 json = json_object_new_object();
2832
2833 /* Since we have IPv6 addresses to deal with which can vary widely in
2834 * size, we try to be a bit more elegant in display by first computing
2835 * the maximum width.
2836 */
2837 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 2838 wctx.zevpn = zevpn;
1374d4db
CS
2839 wctx.vty = vty;
2840 wctx.addr_width = 15;
2841 wctx.json = json;
7cbae20a
PR
2842 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2843 &wctx);
1374d4db
CS
2844
2845 if (!use_json) {
2846 vty_out(vty,
2847 "Number of ARPs (local and remote) known for this VNI: %u\n",
2848 num_neigh);
ce5160c0 2849 vty_out(vty, "%*s %-6s %-8s %-17s %-30s\n",
1374d4db 2850 -wctx.addr_width, "IP", "Type",
ce5160c0 2851 "State", "MAC", "Remote ES/VTEP");
1374d4db
CS
2852 } else
2853 json_object_int_add(json, "numArpNd", num_neigh);
2854
7cbae20a
PR
2855 hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash,
2856 &wctx);
1374d4db
CS
2857
2858 if (use_json) {
2859 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2860 json, JSON_C_TO_STRING_PRETTY));
2861 json_object_free(json);
2862 }
2863}
2864
cec2e17d 2865/*
2866 * Display MACs for a VNI (VTY command handler).
2867 */
d62a17ae 2868void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 2869 vni_t vni, bool use_json)
cec2e17d 2870{
f6371c34 2871 struct zebra_evpn *zevpn;
d7c0a89a 2872 uint32_t num_macs;
d62a17ae 2873 struct mac_walk_ctx wctx;
cd233079
CS
2874 json_object *json = NULL;
2875 json_object *json_mac = NULL;
cec2e17d 2876
2853fed6 2877 if (!is_evpn_enabled())
d62a17ae 2878 return;
8b5fdf2e 2879 zevpn = zebra_evpn_lookup(vni);
87d76d54 2880 if (!zevpn) {
cd233079
CS
2881 if (use_json)
2882 vty_out(vty, "{}\n");
2883 else
2884 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2885 return;
2886 }
87d76d54 2887 num_macs = num_valid_macs(zevpn);
d62a17ae 2888 if (!num_macs)
2889 return;
cec2e17d 2890
cd233079
CS
2891 if (use_json) {
2892 json = json_object_new_object();
2893 json_mac = json_object_new_object();
2894 }
2895
d62a17ae 2896 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 2897 wctx.zevpn = zevpn;
d62a17ae 2898 wctx.vty = vty;
cd233079 2899 wctx.json = json_mac;
cec2e17d 2900
cd233079
CS
2901 if (!use_json) {
2902 vty_out(vty,
2903 "Number of MACs (local and remote) known for this VNI: %u\n",
2904 num_macs);
00a7710c
AK
2905 vty_out(vty,
2906 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
2907 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", "Type",
2908 "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
cd233079
CS
2909 } else
2910 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 2911
b2998086 2912 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
cd233079
CS
2913
2914 if (use_json) {
2915 json_object_object_add(json, "macs", json_mac);
2916 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2917 json, JSON_C_TO_STRING_PRETTY));
2918 json_object_free(json);
2919 }
cec2e17d 2920}
2921
2922/*
2923 * Display MACs for all VNIs (VTY command handler).
2924 */
cd233079 2925void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 2926 bool print_dup, bool use_json)
cec2e17d 2927{
d62a17ae 2928 struct mac_walk_ctx wctx;
cd233079 2929 json_object *json = NULL;
cec2e17d 2930
2853fed6 2931 if (!is_evpn_enabled()) {
cd233079
CS
2932 if (use_json)
2933 vty_out(vty, "{}\n");
d62a17ae 2934 return;
cd233079
CS
2935 }
2936 if (use_json)
2937 json = json_object_new_object();
2938
d62a17ae 2939 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2940 wctx.vty = vty;
cd233079 2941 wctx.json = json;
1374d4db 2942 wctx.print_dup = print_dup;
87d76d54 2943 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
cd233079
CS
2944
2945 if (use_json) {
2946 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2947 json, JSON_C_TO_STRING_PRETTY));
2948 json_object_free(json);
2949 }
cec2e17d 2950}
2951
cffe7580
NS
2952/*
2953 * Display MACs in detail for all VNIs (VTY command handler).
2954 */
2955void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
2956 struct zebra_vrf *zvrf,
2957 bool print_dup, bool use_json)
2958{
2959 struct mac_walk_ctx wctx;
2960 json_object *json = NULL;
2961
2962 if (!is_evpn_enabled()) {
2963 if (use_json)
2964 vty_out(vty, "{}\n");
2965 return;
2966 }
2967 if (use_json)
2968 json = json_object_new_object();
2969
2970 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2971 wctx.vty = vty;
2972 wctx.json = json;
2973 wctx.print_dup = print_dup;
87d76d54 2974 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail,
cffe7580
NS
2975 &wctx);
2976
2977 if (use_json) {
2978 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2979 json, JSON_C_TO_STRING_PRETTY));
2980 json_object_free(json);
2981 }
2982}
2983
cec2e17d 2984/*
2985 * Display MACs for all VNIs (VTY command handler).
2986 */
d62a17ae 2987void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
2988 struct zebra_vrf *zvrf,
9f049418 2989 struct in_addr vtep_ip, bool use_json)
cec2e17d 2990{
d62a17ae 2991 struct mac_walk_ctx wctx;
cd233079 2992 json_object *json = NULL;
cec2e17d 2993
2853fed6 2994 if (!is_evpn_enabled())
d62a17ae 2995 return;
cd233079
CS
2996
2997 if (use_json)
2998 json = json_object_new_object();
2999
d62a17ae 3000 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
3001 wctx.vty = vty;
3002 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
3003 wctx.r_vtep_ip = vtep_ip;
cd233079 3004 wctx.json = json;
87d76d54 3005 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
cd233079
CS
3006
3007 if (use_json) {
3008 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3009 json, JSON_C_TO_STRING_PRETTY));
3010 json_object_free(json);
3011 }
cec2e17d 3012}
3013
3014/*
3015 * Display specific MAC for a VNI, if present (VTY command handler).
3016 */
d62a17ae 3017void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
24cdbd0d
DS
3018 vni_t vni, struct ethaddr *macaddr,
3019 bool use_json)
cec2e17d 3020{
f6371c34 3021 struct zebra_evpn *zevpn;
3198b2b3 3022 struct zebra_mac *mac;
24cdbd0d 3023 json_object *json = NULL;
cec2e17d 3024
2853fed6 3025 if (!is_evpn_enabled())
d62a17ae 3026 return;
24cdbd0d 3027
8b5fdf2e 3028 zevpn = zebra_evpn_lookup(vni);
87d76d54 3029 if (!zevpn) {
24cdbd0d
DS
3030 if (use_json)
3031 vty_out(vty, "{}\n");
3032 else
3033 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 3034 return;
3035 }
b2998086 3036 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 3037 if (!mac) {
24cdbd0d
DS
3038 if (use_json)
3039 vty_out(vty, "{}\n");
3040 else
3041 vty_out(vty,
3042 "%% Requested MAC does not exist in VNI %u\n",
3043 vni);
d62a17ae 3044 return;
3045 }
cec2e17d 3046
24cdbd0d
DS
3047 if (use_json)
3048 json = json_object_new_object();
3049
b2998086 3050 zebra_evpn_print_mac(mac, vty, json);
cffe7580
NS
3051 if (use_json) {
3052 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3053 json, JSON_C_TO_STRING_PRETTY));
3054 json_object_free(json);
3055 }
cec2e17d 3056}
3057
1374d4db
CS
3058/* Print Duplicate MACs per VNI */
3059void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
3060 struct zebra_vrf *zvrf,
3061 vni_t vni, bool use_json)
3062{
f6371c34 3063 struct zebra_evpn *zevpn;
1374d4db
CS
3064 struct mac_walk_ctx wctx;
3065 uint32_t num_macs;
3066 json_object *json = NULL;
3067 json_object *json_mac = NULL;
3068
3069 if (!is_evpn_enabled())
3070 return;
3071
8b5fdf2e 3072 zevpn = zebra_evpn_lookup(vni);
87d76d54 3073 if (!zevpn) {
1374d4db
CS
3074 vty_out(vty, "%% VNI %u does not exist\n", vni);
3075 return;
3076 }
3077
87d76d54 3078 num_macs = num_valid_macs(zevpn);
1374d4db
CS
3079 if (!num_macs)
3080 return;
3081
87d76d54 3082 num_macs = num_dup_detected_macs(zevpn);
1374d4db
CS
3083 if (!num_macs)
3084 return;
3085
3086 if (use_json) {
3087 json = json_object_new_object();
3088 json_mac = json_object_new_object();
3089 }
3090
3091 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 3092 wctx.zevpn = zevpn;
1374d4db
CS
3093 wctx.vty = vty;
3094 wctx.json = json_mac;
3095
3096 if (!use_json) {
3097 vty_out(vty,
3098 "Number of MACs (local and remote) known for this VNI: %u\n",
3099 num_macs);
b169fd6f
AK
3100 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
3101 "Flags", "Intf/Remote ES/VTEP", "VLAN");
1374d4db
CS
3102 } else
3103 json_object_int_add(json, "numMacs", num_macs);
3104
b2998086 3105 hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, &wctx);
1374d4db
CS
3106
3107 if (use_json) {
3108 json_object_object_add(json, "macs", json_mac);
3109 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3110 json, JSON_C_TO_STRING_PRETTY));
3111 json_object_free(json);
3112 }
3113
3114}
3115
e20755b2 3116int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni,
9bee0232
CS
3117 struct ethaddr *macaddr, char *errmsg,
3118 size_t errmsg_len)
09de9258 3119{
f6371c34 3120 struct zebra_evpn *zevpn;
3198b2b3 3121 struct zebra_mac *mac;
09de9258 3122 struct listnode *node = NULL;
72de4110 3123 struct zebra_neigh *nbr = NULL;
09de9258
CS
3124
3125 if (!is_evpn_enabled())
e20755b2 3126 return 0;
1883de66 3127
8b5fdf2e 3128 zevpn = zebra_evpn_lookup(vni);
87d76d54 3129 if (!zevpn) {
9bee0232 3130 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist", vni);
e20755b2 3131 return -1;
09de9258
CS
3132 }
3133
b2998086 3134 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
09de9258 3135 if (!mac) {
9bee0232
CS
3136 snprintf(errmsg, errmsg_len,
3137 "Requested MAC does not exist in VNI %u\n", vni);
e20755b2 3138 return -1;
09de9258
CS
3139 }
3140
3141 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
9bee0232
CS
3142 snprintfrr(errmsg, errmsg_len,
3143 "Requested MAC is not duplicate detected\n");
e20755b2 3144 return -1;
09de9258
CS
3145 }
3146
3147 /* Remove all IPs as duplicate associcated with this MAC */
3148 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
3149 /* For local neigh mark inactive so MACIP update is generated
3150 * to BGP. This is a scenario where MAC update received
3151 * and detected as duplicate which marked neigh as duplicate.
3152 * Later local neigh update did not get a chance to relay
3153 * to BGP. Similarly remote macip update, neigh needs to be
3154 * installed locally.
3155 */
d4199657
CS
3156 if (zvrf->dad_freeze &&
3157 CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
09de9258
CS
3158 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
3159 ZEBRA_NEIGH_SET_INACTIVE(nbr);
3160 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
b2998086
PR
3161 zebra_evpn_rem_neigh_install(
3162 zevpn, nbr, false /*was_static*/);
09de9258
CS
3163 }
3164
3165 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3166 nbr->dad_count = 0;
3167 nbr->detect_start_time.tv_sec = 0;
3168 nbr->dad_dup_detect_time = 0;
3169 }
3170
3171 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
3172 mac->dad_count = 0;
3173 mac->detect_start_time.tv_sec = 0;
3174 mac->detect_start_time.tv_usec = 0;
3175 mac->dad_dup_detect_time = 0;
3176 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
3177
d4199657
CS
3178 /* warn-only action return */
3179 if (!zvrf->dad_freeze)
e20755b2 3180 return 0;
d4199657 3181
09de9258
CS
3182 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3183 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3184 /* Inform to BGP */
b2998086
PR
3185 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
3186 mac->flags, mac->loc_seq,
3187 mac->es))
e20755b2 3188 return 0;
09de9258
CS
3189
3190 /* Process all neighbors associated with this MAC. */
b2998086
PR
3191 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
3192 0 /*es_change*/);
09de9258
CS
3193
3194 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b2998086 3195 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
09de9258
CS
3196
3197 /* Install the entry. */
b2998086 3198 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
09de9258
CS
3199 }
3200
e20755b2 3201 return 0;
09de9258
CS
3202}
3203
e20755b2 3204int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni,
9bee0232
CS
3205 struct ipaddr *ip, char *errmsg,
3206 size_t errmsg_len)
09de9258 3207{
f6371c34 3208 struct zebra_evpn *zevpn;
72de4110 3209 struct zebra_neigh *nbr;
3198b2b3 3210 struct zebra_mac *mac;
09de9258
CS
3211 char buf[INET6_ADDRSTRLEN];
3212 char buf2[ETHER_ADDR_STRLEN];
3213
3214 if (!is_evpn_enabled())
e20755b2 3215 return 0;
09de9258 3216
8b5fdf2e 3217 zevpn = zebra_evpn_lookup(vni);
87d76d54 3218 if (!zevpn) {
9bee0232 3219 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist\n", vni);
e20755b2 3220 return -1;
09de9258
CS
3221 }
3222
7cbae20a 3223 nbr = zebra_evpn_neigh_lookup(zevpn, ip);
09de9258 3224 if (!nbr) {
9bee0232
CS
3225 snprintfrr(errmsg, errmsg_len,
3226 "Requested host IP does not exist in VNI %u\n", vni);
e20755b2 3227 return -1;
09de9258
CS
3228 }
3229
3230 ipaddr2str(&nbr->ip, buf, sizeof(buf));
3231
3232 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
9bee0232
CS
3233 snprintfrr(errmsg, errmsg_len,
3234 "Requested host IP %s is not duplicate detected\n",
3235 buf);
e20755b2 3236 return -1;
09de9258
CS
3237 }
3238
b2998086 3239 mac = zebra_evpn_mac_lookup(zevpn, &nbr->emac);
09de9258
CS
3240
3241 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
9bee0232
CS
3242 snprintfrr(
3243 errmsg, errmsg_len,
e20755b2 3244 "Requested IP's associated MAC %s is still in duplicate state\n",
09de9258 3245 prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
e20755b2 3246 return -1;
09de9258
CS
3247 }
3248
3249 if (IS_ZEBRA_DEBUG_VXLAN)
3250 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
15569c58 3251 __func__, buf, nbr->flags, nbr->loc_seq);
09de9258
CS
3252
3253 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3254 nbr->dad_count = 0;
3255 nbr->detect_start_time.tv_sec = 0;
3256 nbr->detect_start_time.tv_usec = 0;
3257 nbr->dad_dup_detect_time = 0;
3258 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
3259
3260 if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
7cbae20a
PR
3261 zebra_evpn_neigh_send_add_to_client(zevpn->vni, ip, &nbr->emac,
3262 nbr->mac, nbr->flags,
3263 nbr->loc_seq);
09de9258 3264 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
b2998086 3265 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
09de9258
CS
3266 }
3267
e20755b2 3268 return 0;
09de9258
CS
3269}
3270
87d76d54 3271static void zevpn_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt)
09de9258
CS
3272{
3273 struct mac_walk_ctx *wctx = ctxt;
3198b2b3 3274 struct zebra_mac *mac;
f6371c34 3275 struct zebra_evpn *zevpn;
09de9258 3276 struct listnode *node = NULL;
72de4110 3277 struct zebra_neigh *nbr = NULL;
09de9258 3278
3198b2b3 3279 mac = (struct zebra_mac *)bucket->data;
09de9258
CS
3280 if (!mac)
3281 return;
3282
87d76d54 3283 zevpn = wctx->zevpn;
09de9258
CS
3284
3285 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
3286 return;
3287
3288 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
3289 mac->dad_count = 0;
3290 mac->detect_start_time.tv_sec = 0;
3291 mac->detect_start_time.tv_usec = 0;
3292 mac->dad_dup_detect_time = 0;
3293 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
3294
3295 /* Remove all IPs as duplicate associcated with this MAC */
3296 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
3297 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
3298 && nbr->dad_count)
3299 ZEBRA_NEIGH_SET_INACTIVE(nbr);
3300
3301 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3302 nbr->dad_count = 0;
3303 nbr->detect_start_time.tv_sec = 0;
3304 nbr->dad_dup_detect_time = 0;
3305 }
3306
3307 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3308 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3309 /* Inform to BGP */
b2998086
PR
3310 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
3311 mac->flags, mac->loc_seq,
3312 mac->es))
09de9258
CS
3313 return;
3314
3315 /* Process all neighbors associated with this MAC. */
b2998086
PR
3316 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
3317 0 /*es_change*/);
09de9258
CS
3318
3319 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b2998086 3320 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
09de9258
CS
3321
3322 /* Install the entry. */
b2998086 3323 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
09de9258
CS
3324 }
3325}
3326
87d76d54 3327static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket,
09de9258
CS
3328 void **args)
3329{
f6371c34 3330 struct zebra_evpn *zevpn;
09de9258
CS
3331 struct zebra_vrf *zvrf;
3332 struct mac_walk_ctx m_wctx;
3333 struct neigh_walk_ctx n_wctx;
3334
f6371c34 3335 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 3336 if (!zevpn)
09de9258
CS
3337 return;
3338
e20755b2 3339 zvrf = (struct zebra_vrf *)args[0];
09de9258 3340
87d76d54 3341 if (hashcount(zevpn->neigh_table)) {
09de9258 3342 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 3343 n_wctx.zevpn = zevpn;
09de9258 3344 n_wctx.zvrf = zvrf;
7cbae20a
PR
3345 hash_iterate(zevpn->neigh_table,
3346 zebra_evpn_clear_dup_neigh_hash, &n_wctx);
09de9258
CS
3347 }
3348
87d76d54 3349 if (num_valid_macs(zevpn)) {
09de9258 3350 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 3351 m_wctx.zevpn = zevpn;
09de9258 3352 m_wctx.zvrf = zvrf;
87d76d54 3353 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
09de9258
CS
3354 }
3355
3356}
3357
e20755b2 3358int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf *zvrf)
09de9258 3359{
e20755b2 3360 void *args[1];
09de9258
CS
3361
3362 if (!is_evpn_enabled())
e20755b2 3363 return 0;
09de9258 3364
e20755b2 3365 args[0] = zvrf;
09de9258 3366
87d76d54 3367 hash_iterate(zvrf->evpn_table,
e3b78da8 3368 (void (*)(struct hash_bucket *, void *))
87d76d54 3369 zevpn_clear_dup_detect_hash_vni_all, args);
09de9258 3370
e20755b2 3371 return 0;
09de9258
CS
3372}
3373
e20755b2 3374int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni)
09de9258 3375{
f6371c34 3376 struct zebra_evpn *zevpn;
09de9258
CS
3377 struct mac_walk_ctx m_wctx;
3378 struct neigh_walk_ctx n_wctx;
3379
3380 if (!is_evpn_enabled())
e20755b2 3381 return 0;
09de9258 3382
8b5fdf2e 3383 zevpn = zebra_evpn_lookup(vni);
87d76d54 3384 if (!zevpn) {
1d5453d6 3385 zlog_warn("VNI %u does not exist", vni);
87d76d54 3386 return CMD_WARNING;
09de9258
CS
3387 }
3388
87d76d54 3389 if (hashcount(zevpn->neigh_table)) {
09de9258 3390 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 3391 n_wctx.zevpn = zevpn;
09de9258 3392 n_wctx.zvrf = zvrf;
7cbae20a
PR
3393 hash_iterate(zevpn->neigh_table,
3394 zebra_evpn_clear_dup_neigh_hash, &n_wctx);
09de9258
CS
3395 }
3396
87d76d54 3397 if (num_valid_macs(zevpn)) {
09de9258 3398 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 3399 m_wctx.zevpn = zevpn;
09de9258 3400 m_wctx.zvrf = zvrf;
87d76d54 3401 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
09de9258
CS
3402 }
3403
e20755b2 3404 return 0;
09de9258
CS
3405}
3406
cec2e17d 3407/*
3408 * Display MACs for a VNI from specific VTEP (VTY command handler).
3409 */
d62a17ae 3410void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 3411 vni_t vni, struct in_addr vtep_ip,
9f049418 3412 bool use_json)
cec2e17d 3413{
f6371c34 3414 struct zebra_evpn *zevpn;
d7c0a89a 3415 uint32_t num_macs;
d62a17ae 3416 struct mac_walk_ctx wctx;
cd233079
CS
3417 json_object *json = NULL;
3418 json_object *json_mac = NULL;
cec2e17d 3419
2853fed6 3420 if (!is_evpn_enabled())
d62a17ae 3421 return;
8b5fdf2e 3422 zevpn = zebra_evpn_lookup(vni);
87d76d54 3423 if (!zevpn) {
cd233079
CS
3424 if (use_json)
3425 vty_out(vty, "{}\n");
3426 else
3427 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 3428 return;
3429 }
87d76d54 3430 num_macs = num_valid_macs(zevpn);
d62a17ae 3431 if (!num_macs)
3432 return;
cd233079
CS
3433
3434 if (use_json) {
3435 json = json_object_new_object();
3436 json_mac = json_object_new_object();
3437 }
3438
d62a17ae 3439 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 3440 wctx.zevpn = zevpn;
d62a17ae 3441 wctx.vty = vty;
3442 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
3443 wctx.r_vtep_ip = vtep_ip;
cd233079 3444 wctx.json = json_mac;
b2998086 3445 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
cd233079
CS
3446
3447 if (use_json) {
3448 json_object_int_add(json, "numMacs", wctx.count);
3449 if (wctx.count)
3450 json_object_object_add(json, "macs", json_mac);
3451 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3452 json, JSON_C_TO_STRING_PRETTY));
3453 json_object_free(json);
3454 }
cec2e17d 3455}
3456
3457
3458/*
3459 * Display VNI information (VTY command handler).
06931fdb
LK
3460 *
3461 * use_json flag indicates that output should be in JSON format.
3462 * json_array is non NULL when JSON output needs to be aggregated (by the
3463 * caller) and then printed, otherwise, JSON evpn vni info is printed
3464 * right away.
cec2e17d 3465 */
cd233079 3466void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
06931fdb 3467 bool use_json, json_object *json_array)
cec2e17d 3468{
cd233079
CS
3469 json_object *json = NULL;
3470 void *args[2];
05843a27 3471 struct zebra_l3vni *zl3vni = NULL;
f6371c34 3472 struct zebra_evpn *zevpn = NULL;
cec2e17d 3473
2853fed6 3474 if (!is_evpn_enabled())
d62a17ae 3475 return;
4cce389e 3476
cd233079
CS
3477 if (use_json)
3478 json = json_object_new_object();
06931fdb 3479
cd233079
CS
3480 args[0] = vty;
3481 args[1] = json;
4cce389e 3482
1f2129ec 3483 zl3vni = zl3vni_lookup(vni);
3484 if (zl3vni) {
4cce389e
MK
3485 zl3vni_print(zl3vni, (void *)args);
3486 } else {
8b5fdf2e 3487 zevpn = zebra_evpn_lookup(vni);
87d76d54 3488 if (zevpn)
8b5fdf2e 3489 zebra_evpn_print(zevpn, (void *)args);
06931fdb
LK
3490 else if (!json)
3491 vty_out(vty, "%% VNI %u does not exist\n", vni);
4cce389e
MK
3492 }
3493
cd233079 3494 if (use_json) {
06931fdb
LK
3495 /*
3496 * Each "json" object contains info about 1 VNI.
3497 * When "json_array" is non-null, we aggreggate the json output
3498 * into json_array and print it as a JSON array.
3499 */
3500 if (json_array)
3501 json_object_array_add(json_array, json);
3502 else {
3503 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3504 json, JSON_C_TO_STRING_PRETTY));
3505 json_object_free(json);
3506 }
cd233079 3507 }
cec2e17d 3508}
3509
4cce389e 3510/* Display all global details for EVPN */
088f1098 3511void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
cec2e17d 3512{
4cce389e
MK
3513 int num_l2vnis = 0;
3514 int num_l3vnis = 0;
d4454626 3515 int num_vnis = 0;
cd233079 3516 json_object *json = NULL;
4cce389e 3517 struct zebra_vrf *zvrf = NULL;
cec2e17d 3518
2853fed6 3519 if (!is_evpn_enabled())
d62a17ae 3520 return;
4cce389e 3521
530db8dc 3522 zvrf = zebra_vrf_get_evpn();
4cce389e
MK
3523 if (!zvrf)
3524 return;
3525
89272910 3526 num_l3vnis = hashcount(zrouter.l3vni_table);
87d76d54 3527 num_l2vnis = hashcount(zvrf->evpn_table);
d4454626 3528 num_vnis = num_l2vnis + num_l3vnis;
4cce389e
MK
3529
3530 if (uj) {
cd233079 3531 json = json_object_new_object();
ddd16ed5
MK
3532 json_object_string_add(json, "advertiseGatewayMacip",
3533 zvrf->advertise_gw_macip ? "Yes" : "No");
d4454626 3534 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
3535 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3536 json_object_int_add(json, "numL3Vnis", num_l3vnis);
b2ee2b71 3537 if (zebra_evpn_do_dup_addr_detect(zvrf))
61d46eda
CS
3538 json_object_boolean_true_add(json,
3539 "isDuplicateAddrDetection");
3540 else
3541 json_object_boolean_false_add(json,
3542 "isDuplicateAddrDetection");
3543 json_object_int_add(json, "maxMoves", zvrf->dad_max_moves);
3544 json_object_int_add(json, "detectionTime", zvrf->dad_time);
3545 json_object_int_add(json, "detectionFreezeTime",
3546 zvrf->dad_freeze_time);
c36e442c 3547 zebra_evpn_mh_json(json);
cd233079 3548 } else {
4cce389e
MK
3549 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
3550 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
ddd16ed5
MK
3551 vty_out(vty, "Advertise gateway mac-ip: %s\n",
3552 zvrf->advertise_gw_macip ? "Yes" : "No");
278e26de
CS
3553 vty_out(vty, "Advertise svi mac-ip: %s\n",
3554 zvrf->advertise_svi_macip ? "Yes" : "No");
243b74ed
AK
3555 vty_out(vty, "Advertise svi mac: %s\n",
3556 zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
61d46eda 3557 vty_out(vty, "Duplicate address detection: %s\n",
b2ee2b71
AK
3558 zebra_evpn_do_dup_addr_detect(zvrf) ? "Enable"
3559 : "Disable");
61d46eda
CS
3560 vty_out(vty, " Detection max-moves %u, time %d\n",
3561 zvrf->dad_max_moves, zvrf->dad_time);
3562 if (zvrf->dad_freeze) {
3563 if (zvrf->dad_freeze_time)
3564 vty_out(vty, " Detection freeze %u\n",
3565 zvrf->dad_freeze_time);
3566 else
3567 vty_out(vty, " Detection freeze %s\n",
3568 "permanent");
3569 }
c36e442c 3570 zebra_evpn_mh_print(vty);
cd233079 3571 }
4cce389e
MK
3572
3573 if (uj) {
3574 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3575 json, JSON_C_TO_STRING_PRETTY));
3576 json_object_free(json);
3577 }
3578}
3579
3580/*
3581 * Display VNI hash table (VTY command handler).
3582 */
3583void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 3584 bool use_json)
4cce389e
MK
3585{
3586 json_object *json = NULL;
4cce389e
MK
3587 void *args[2];
3588
3589 if (!is_evpn_enabled())
3590 return;
3591
4cce389e
MK
3592 if (use_json)
3593 json = json_object_new_object();
3594 else
996c9314
LB
3595 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
3596 "Type", "VxLAN IF", "# MACs", "# ARPs",
3597 "# Remote VTEPs", "Tenant VRF");
4cce389e 3598
cd233079
CS
3599 args[0] = vty;
3600 args[1] = json;
3601
4cce389e 3602 /* Display all L2-VNIs */
8b5fdf2e
PR
3603 hash_iterate(
3604 zvrf->evpn_table,
3605 (void (*)(struct hash_bucket *, void *))zebra_evpn_print_hash,
3606 args);
cd233079 3607
4cce389e 3608 /* Display all L3-VNIs */
89272910 3609 hash_iterate(zrouter.l3vni_table,
e3b78da8 3610 (void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
4cce389e
MK
3611 args);
3612
cd233079
CS
3613 if (use_json) {
3614 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3615 json, JSON_C_TO_STRING_PRETTY));
3616 json_object_free(json);
3617 }
cec2e17d 3618}
3619
3950b52c
CS
3620void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
3621{
3622 struct stream *s;
3623 int time = 0;
3624 uint32_t max_moves = 0;
3625 uint32_t freeze_time = 0;
3626 bool dup_addr_detect = false;
3627 bool freeze = false;
b2ee2b71 3628 bool old_addr_detect;
3950b52c
CS
3629
3630 s = msg;
3631 STREAM_GETL(s, dup_addr_detect);
3632 STREAM_GETL(s, time);
3633 STREAM_GETL(s, max_moves);
3634 STREAM_GETL(s, freeze);
3635 STREAM_GETL(s, freeze_time);
3636
b2ee2b71
AK
3637 old_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
3638 zvrf->dup_addr_detect = dup_addr_detect;
3639 dup_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
3640
09de9258
CS
3641 /* DAD previous state was enabled, and new state is disable,
3642 * clear all duplicate detected addresses.
3643 */
b2ee2b71 3644 if (old_addr_detect && !dup_addr_detect)
e20755b2 3645 zebra_vxlan_clear_dup_detect_vni_all(zvrf);
09de9258 3646
3950b52c
CS
3647 zvrf->dad_time = time;
3648 zvrf->dad_max_moves = max_moves;
3649 zvrf->dad_freeze = freeze;
3650 zvrf->dad_freeze_time = freeze_time;
3651
3652 if (IS_ZEBRA_DEBUG_VXLAN)
3653 zlog_debug(
6005fe55
CS
3654 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
3655 vrf_id_to_name(zvrf->vrf->vrf_id),
b2ee2b71
AK
3656 dup_addr_detect ? "enable" : "disable",
3657 zvrf->dad_max_moves, zvrf->dad_time,
3950b52c
CS
3658 zvrf->dad_freeze ? "enable" : "disable",
3659 zvrf->dad_freeze_time);
3660
3661stream_failure:
3662 return;
3663}
3664
09af6961
NS
3665/*
3666 * Display VNI hash table in detail(VTY command handler).
3667 */
3668void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
3669 bool use_json)
3670{
06931fdb 3671 json_object *json_array = NULL;
09af6961 3672 struct zebra_ns *zns = NULL;
8b5fdf2e 3673 struct zebra_evpn_show zes;
09af6961
NS
3674
3675 if (!is_evpn_enabled())
3676 return;
3677
3678 zns = zebra_ns_lookup(NS_DEFAULT);
3679 if (!zns)
3680 return;
3681
09af6961 3682 if (use_json)
06931fdb 3683 json_array = json_object_new_array();
09af6961
NS
3684
3685 zes.vty = vty;
06931fdb 3686 zes.json = json_array;
09af6961 3687 zes.zvrf = zvrf;
06931fdb 3688 zes.use_json = use_json;
09af6961
NS
3689
3690 /* Display all L2-VNIs */
8b5fdf2e
PR
3691 hash_iterate(zvrf->evpn_table,
3692 (void (*)(struct hash_bucket *,
3693 void *))zebra_evpn_print_hash_detail,
3694 &zes);
09af6961
NS
3695
3696 /* Display all L3-VNIs */
3697 hash_iterate(zrouter.l3vni_table,
e3b78da8 3698 (void (*)(struct hash_bucket *,
09af6961
NS
3699 void *))zl3vni_print_hash_detail,
3700 &zes);
3701
3702 if (use_json) {
2bcb1a7f
QY
3703 vty_out(vty, "%s\n",
3704 json_object_to_json_string_ext(
06931fdb
LK
3705 json_array, JSON_C_TO_STRING_PRETTY));
3706 json_object_free(json_array);
09af6961
NS
3707 }
3708}
3709
2232a77c 3710/*
ee69da27
MK
3711 * Handle neighbor delete notification from the kernel (on a VLAN device
3712 * / L3 interface). This may result in either the neighbor getting deleted
3713 * from our database or being re-added to the kernel (if it is a valid
2232a77c 3714 * remote neighbor).
3715 */
ee69da27
MK
3716int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
3717 struct interface *link_if,
3718 struct ipaddr *ip)
d62a17ae 3719{
f6371c34 3720 struct zebra_evpn *zevpn = NULL;
05843a27 3721 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 3722
8c9b80b9 3723 /* check if this is a remote neigh entry corresponding to remote
523cafc4 3724 * next-hop
3725 */
8c9b80b9
MK
3726 zl3vni = zl3vni_from_svi(ifp, link_if);
3727 if (zl3vni)
3728 return zl3vni_local_nh_del(zl3vni, ip);
d62a17ae 3729
3730 /* We are only interested in neighbors on an SVI that resides on top
3731 * of a VxLAN bridge.
3732 */
8b5fdf2e 3733 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 3734 if (!zevpn) {
6041b686 3735 if (IS_ZEBRA_DEBUG_VXLAN)
15569c58 3736 zlog_debug(
ef7b8be4
DL
3737 "%s: Del neighbor %pIA EVPN is not present for interface %s",
3738 __func__, ip, ifp->name);
d62a17ae 3739 return 0;
6041b686 3740 }
8c9b80b9 3741
87d76d54 3742 if (!zevpn->vxlan_if) {
9df414fe 3743 zlog_debug(
d62a17ae 3744 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
87d76d54 3745 zevpn->vni, zevpn);
d62a17ae 3746 return -1;
3747 }
3748
3749 if (IS_ZEBRA_DEBUG_VXLAN)
ef7b8be4
DL
3750 zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
3751 ip, ifp->name, ifp->ifindex, zevpn->vni);
d62a17ae 3752
33064a62 3753 return zebra_evpn_neigh_del_ip(zevpn, ip);
2232a77c 3754}
3755
3756/*
ee69da27
MK
3757 * Handle neighbor add or update notification from the kernel (on a VLAN
3758 * device / L3 interface). This is typically for a local neighbor but can
3759 * also be for a remote neighbor (e.g., ageout notification). It could
3760 * also be a "move" scenario.
2232a77c 3761 */
ee69da27
MK
3762int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
3763 struct interface *link_if,
3764 struct ipaddr *ip,
3765 struct ethaddr *macaddr,
3766 uint16_t state,
a37f4598 3767 bool is_ext,
b169fd6f
AK
3768 bool is_router,
3769 bool local_inactive, bool dp_static)
d62a17ae 3770{
f6371c34 3771 struct zebra_evpn *zevpn = NULL;
05843a27 3772 struct zebra_l3vni *zl3vni = NULL;
3bcbba10 3773
3774 /* check if this is a remote neigh entry corresponding to remote
3775 * next-hop
3776 */
3777 zl3vni = zl3vni_from_svi(ifp, link_if);
3778 if (zl3vni)
3779 return zl3vni_local_nh_add_update(zl3vni, ip, state);
b7cfce93 3780
d62a17ae 3781 /* We are only interested in neighbors on an SVI that resides on top
3782 * of a VxLAN bridge.
3783 */
8b5fdf2e 3784 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 3785 if (!zevpn)
d62a17ae 3786 return 0;
3787
b169fd6f 3788 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
d62a17ae 3789 zlog_debug(
ef7b8be4
DL
3790 "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
3791 ip, macaddr, ifp->name,
a37f4598 3792 ifp->ifindex, state, is_ext ? "ext-learned " : "",
3793 is_router ? "router " : "",
b169fd6f 3794 local_inactive ? "local_inactive " : "",
7c0e4dc6 3795 dp_static ? "peer_sync " : "", zevpn->vni);
d62a17ae 3796
ee69da27 3797 /* Is this about a local neighbor or a remote one? */
a37f4598 3798 if (!is_ext)
7cbae20a
PR
3799 return zebra_evpn_local_neigh_update(zevpn, ifp, ip, macaddr,
3800 is_router, local_inactive,
3801 dp_static);
b7cfce93 3802
7cbae20a 3803 return zebra_evpn_remote_neigh_update(zevpn, ifp, ip, macaddr, state);
2232a77c 3804}
3805
0bd371c6
DS
3806static int32_t
3807zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni,
3808 struct ethaddr *macaddr, uint16_t *ipa_len,
3809 struct ipaddr *ip, struct in_addr *vtep_ip,
ce5160c0 3810 uint8_t *flags, uint32_t *seq, esi_t *esi)
0bd371c6
DS
3811{
3812 uint16_t l = 0;
3813
3814 /*
3815 * Obtain each remote MACIP and process.
3816 * Message contains VNI, followed by MAC followed by IP (if any)
3817 * followed by remote VTEP IP.
3818 */
3819 memset(ip, 0, sizeof(*ip));
3820 STREAM_GETL(s, *vni);
3821 STREAM_GET(macaddr->octet, s, ETH_ALEN);
0ffd0fb5 3822 STREAM_GETW(s, *ipa_len);
0bd371c6
DS
3823
3824 if (*ipa_len) {
3825 if (*ipa_len == IPV4_MAX_BYTELEN)
3826 ip->ipa_type = IPADDR_V4;
3827 else if (*ipa_len == IPV6_MAX_BYTELEN)
3828 ip->ipa_type = IPADDR_V6;
3829 else {
3830 if (IS_ZEBRA_DEBUG_VXLAN)
3831 zlog_debug(
3832 "ipa_len *must* be %d or %d bytes in length not %d",
3833 IPV4_MAX_BYTELEN, IPV6_MAX_BYTELEN,
3834 *ipa_len);
3835 goto stream_failure;
3836 }
3837
3838 STREAM_GET(&ip->ip.addr, s, *ipa_len);
3839 }
3840 l += 4 + ETH_ALEN + 4 + *ipa_len;
3841 STREAM_GET(&vtep_ip->s_addr, s, IPV4_MAX_BYTELEN);
3842 l += IPV4_MAX_BYTELEN;
3843
3844 if (add) {
3845 STREAM_GETC(s, *flags);
3846 STREAM_GETL(s, *seq);
3847 l += 5;
ce5160c0
AK
3848 STREAM_GET(esi, s, sizeof(esi_t));
3849 l += sizeof(esi_t);
0bd371c6
DS
3850 }
3851
3852 return l;
3853
3854stream_failure:
3855 return -1;
3856}
b682f6de 3857
2232a77c 3858/*
3859 * Handle message from client to delete a remote MACIP for a VNI.
3860 */
89f4e507 3861void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
d62a17ae 3862{
3863 struct stream *s;
3864 vni_t vni;
3865 struct ethaddr macaddr;
3866 struct ipaddr ip;
3867 struct in_addr vtep_ip;
9df2b997 3868 uint16_t l = 0, ipa_len;
d62a17ae 3869 char buf1[INET6_ADDRSTRLEN];
3870
1002497a 3871 s = msg;
d62a17ae 3872
89f4e507 3873 while (l < hdr->length) {
0bd371c6
DS
3874 int res_length = zebra_vxlan_remote_macip_helper(
3875 false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL,
ce5160c0 3876 NULL, NULL);
4824d144 3877
0bd371c6
DS
3878 if (res_length == -1)
3879 goto stream_failure;
d62a17ae 3880
0bd371c6 3881 l += res_length;
d62a17ae 3882 if (IS_ZEBRA_DEBUG_VXLAN)
3883 zlog_debug(
ef7b8be4
DL
3884 "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
3885 vni, &macaddr,
f07e1c99 3886 ipa_len ? " IP " : "",
3887 ipa_len ?
3888 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
9bcef951 3889 &vtep_ip, zebra_route_string(client->proto));
d62a17ae 3890
7f7e49d1
MS
3891 /* Enqueue to workqueue for processing */
3892 zebra_rib_queue_evpn_rem_macip_del(vni, &macaddr, &ip, vtep_ip);
d62a17ae 3893 }
3894
ec93aa12 3895stream_failure:
8068a649 3896 return;
2232a77c 3897}
3898
3899/*
3900 * Handle message from client to add a remote MACIP for a VNI. This
3901 * could be just the add of a MAC address or the add of a neighbor
3902 * (IP+MAC).
3903 */
89f4e507 3904void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
d62a17ae 3905{
3906 struct stream *s;
3907 vni_t vni;
3908 struct ethaddr macaddr;
3909 struct ipaddr ip;
3910 struct in_addr vtep_ip;
9df2b997 3911 uint16_t l = 0, ipa_len;
f07e1c99 3912 uint8_t flags = 0;
3913 uint32_t seq;
d62a17ae 3914 char buf1[INET6_ADDRSTRLEN];
ce5160c0
AK
3915 esi_t esi;
3916 char esi_buf[ESI_STR_LEN];
d62a17ae 3917
ec93aa12 3918 if (!EVPN_ENABLED(zvrf)) {
9df414fe 3919 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
8068a649 3920 return;
ec93aa12 3921 }
d62a17ae 3922
1002497a 3923 s = msg;
d62a17ae 3924
89f4e507 3925 while (l < hdr->length) {
7f7e49d1 3926
0bd371c6
DS
3927 int res_length = zebra_vxlan_remote_macip_helper(
3928 true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip,
ce5160c0 3929 &flags, &seq, &esi);
d62a17ae 3930
0bd371c6
DS
3931 if (res_length == -1)
3932 goto stream_failure;
d62a17ae 3933
0bd371c6 3934 l += res_length;
ce5160c0
AK
3935 if (IS_ZEBRA_DEBUG_VXLAN) {
3936 if (memcmp(&esi, zero_esi, sizeof(esi_t)))
3937 esi_to_str(&esi, esi_buf, sizeof(esi_buf));
3938 else
9e0c2fd1 3939 strlcpy(esi_buf, "-", ESI_STR_LEN);
d62a17ae 3940 zlog_debug(
ef7b8be4 3941 "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
b169fd6f
AK
3942 (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ?
3943 "sync-" : "",
ef7b8be4 3944 vni, &macaddr,
f07e1c99 3945 ipa_len ? " IP " : "",
3946 ipa_len ?
3947 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
9bcef951 3948 flags, seq, &vtep_ip, esi_buf,
d62a17ae 3949 zebra_route_string(client->proto));
ce5160c0 3950 }
d62a17ae 3951
7f7e49d1
MS
3952 /* Enqueue to workqueue for processing */
3953 zebra_rib_queue_evpn_rem_macip_add(vni, &macaddr, &ip, flags,
3954 seq, vtep_ip, &esi);
d62a17ae 3955 }
3956
ec93aa12 3957stream_failure:
8068a649 3958 return;
13d60d35 3959}
3960
4b3f26f4 3961/*
3962 * Handle remote vtep delete by kernel; re-add the vtep if we have it
3963 */
3964int zebra_vxlan_check_readd_vtep(struct interface *ifp,
3965 struct in_addr vtep_ip)
3966{
3967 struct zebra_if *zif;
3968 struct zebra_vrf *zvrf = NULL;
3969 struct zebra_l2info_vxlan *vxl;
3970 vni_t vni;
f6371c34 3971 struct zebra_evpn *zevpn = NULL;
c172c032 3972 struct zebra_vtep *zvtep = NULL;
4b3f26f4 3973
3974 zif = ifp->info;
3975 assert(zif);
3976 vxl = &zif->l2info.vxl;
3977 vni = vxl->vni;
3978
3979 /* If EVPN is not enabled, nothing to do. */
3980 if (!is_evpn_enabled())
3981 return 0;
3982
3983 /* Locate VRF corresponding to interface. */
3984 zvrf = vrf_info_lookup(ifp->vrf_id);
3985 if (!zvrf)
3986 return -1;
3987
3988 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 3989 zevpn = zebra_evpn_lookup(vni);
87d76d54 3990 if (!zevpn)
4b3f26f4 3991 return 0;
3992
3993 /* If the remote vtep entry doesn't exists nothing to do */
8b5fdf2e 3994 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4b3f26f4 3995 if (!zvtep)
3996 return 0;
3997
3998 if (IS_ZEBRA_DEBUG_VXLAN)
3999 zlog_debug(
9bcef951
MS
4000 "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
4001 &vtep_ip, ifp->name, ifp->ifindex, vni);
4b3f26f4 4002
8b5fdf2e 4003 zebra_evpn_vtep_install(zevpn, zvtep);
4b3f26f4 4004 return 0;
4005}
4006
13d60d35 4007/*
2232a77c 4008 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
4009 * us, this must involve a multihoming scenario. Treat this as implicit delete
4010 * of any prior local MAC.
13d60d35 4011 */
15400f95
AK
4012static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
4013 struct interface *br_if,
4014 struct ethaddr *macaddr,
4015 vlanid_t vid)
13d60d35 4016{
d62a17ae 4017 struct zebra_if *zif;
d62a17ae 4018 struct zebra_l2info_vxlan *vxl;
4019 vni_t vni;
f6371c34 4020 struct zebra_evpn *zevpn;
3198b2b3 4021 struct zebra_mac *mac;
13d60d35 4022
d62a17ae 4023 zif = ifp->info;
4024 assert(zif);
4025 vxl = &zif->l2info.vxl;
4026 vni = vxl->vni;
13d60d35 4027
2853fed6 4028 /* Check if EVPN is enabled. */
4029 if (!is_evpn_enabled())
d62a17ae 4030 return 0;
13d60d35 4031
d62a17ae 4032 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4033 zevpn = zebra_evpn_lookup(vni);
87d76d54 4034 if (!zevpn)
d62a17ae 4035 return 0;
13d60d35 4036
d62a17ae 4037 /* If entry doesn't exist, nothing to do. */
b2998086 4038 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 4039 if (!mac)
4040 return 0;
13d60d35 4041
d62a17ae 4042 /* Is it a local entry? */
4043 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
4044 return 0;
13d60d35 4045
d62a17ae 4046 if (IS_ZEBRA_DEBUG_VXLAN)
4047 zlog_debug(
ef7b8be4
DL
4048 "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
4049 macaddr, ifp->name, ifp->ifindex, vni, mac->flags);
13d60d35 4050
d62a17ae 4051 /* Remove MAC from BGP. */
b2998086
PR
4052 zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
4053 false /* force */);
13d60d35 4054
b6938a74
MK
4055 /*
4056 * If there are no neigh associated with the mac delete the mac
4057 * else mark it as AUTO for forward reference
4058 */
4059 if (!listcount(mac->neigh_list)) {
b2998086 4060 zebra_evpn_mac_del(zevpn, mac);
b6938a74 4061 } else {
8b07f173 4062 zebra_evpn_mac_clear_fwd_info(mac);
b169fd6f 4063 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
5756dd1d 4064 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
b6938a74
MK
4065 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
4066 }
13d60d35 4067
d62a17ae 4068 return 0;
13d60d35 4069}
4070
15400f95
AK
4071/* MAC notification from the dataplane with a network dest port -
4072 * 1. This can be a local MAC on a down ES (if fast-failover is not possible
4073 * 2. Or it can be a remote MAC
4074 */
4075int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
4076 struct interface *br_if,
4077 struct ethaddr *macaddr, vlanid_t vid,
4078 uint32_t nhg_id, bool sticky, bool dp_static)
4079{
4080 struct zebra_evpn_es *es;
4081 struct interface *acc_ifp;
4082
4083 /* if remote mac delete the local entry */
4084 if (!nhg_id || !zebra_evpn_nhg_is_local_es(nhg_id, &es)
4085 || !zebra_evpn_es_local_mac_via_network_port(es)) {
4086 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4087 zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr,
4088 vid);
4089 return zebra_vxlan_check_del_local_mac(ifp, br_if, macaddr,
4090 vid);
4091 }
4092
4093 /* If local MAC on a down local ES translate the network-mac-add
4094 * to a local-inactive-mac-add
4095 */
4096 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4097 zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr, vid);
4098 acc_ifp = es->zif->ifp;
4099 return zebra_vxlan_local_mac_add_update(
4100 acc_ifp, br_if, macaddr, vid, sticky,
4101 false /* local_inactive */, dp_static);
4102}
4103
13d60d35 4104/*
15400f95
AK
4105 * Handle network MAC delete by kernel -
4106 * 1. readd the remote MAC if we have it
4107 * 2. local MAC with does ES may also need to be re-installed
13d60d35 4108 */
15400f95
AK
4109int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
4110 struct interface *br_if,
4111 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 4112{
a9a76262
MK
4113 struct zebra_if *zif = NULL;
4114 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 4115 vni_t vni;
f6371c34 4116 struct zebra_evpn *zevpn = NULL;
05843a27 4117 struct zebra_l3vni *zl3vni = NULL;
3198b2b3 4118 struct zebra_mac *mac = NULL;
2232a77c 4119
d62a17ae 4120 zif = ifp->info;
4121 assert(zif);
4122 vxl = &zif->l2info.vxl;
4123 vni = vxl->vni;
2232a77c 4124
2853fed6 4125 /* Check if EVPN is enabled. */
4126 if (!is_evpn_enabled())
d62a17ae 4127 return 0;
2232a77c 4128
a9a76262
MK
4129 /* check if this is a remote RMAC and readd simillar to remote macs */
4130 zl3vni = zl3vni_lookup(vni);
4131 if (zl3vni)
4132 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
4133
d62a17ae 4134 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4135 zevpn = zebra_evpn_lookup(vni);
87d76d54 4136 if (!zevpn)
d62a17ae 4137 return 0;
13d60d35 4138
d62a17ae 4139 /* If entry doesn't exist, nothing to do. */
b2998086 4140 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 4141 if (!mac)
4142 return 0;
2232a77c 4143
15400f95
AK
4144 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
4145 /* If remote entry simply re-install */
4146 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4147 zlog_debug(
4148 "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
4149 macaddr, ifp->name, ifp->ifindex, vni);
4150 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
4151 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && mac->es
4152 && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
4153 /* If local entry via nw-port call local-del which will
4154 * re-install entry in the dataplane is needed
4155 */
4156 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4157 zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr,
4158 vni);
00a7710c
AK
4159
4160 zebra_evpn_del_local_mac(zevpn, mac, false);
15400f95 4161 }
13d60d35 4162
d62a17ae 4163 return 0;
13d60d35 4164}
4165
4166/*
2232a77c 4167 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 4168 */
d62a17ae 4169int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
4170 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 4171{
f6371c34 4172 struct zebra_evpn *zevpn;
3198b2b3 4173 struct zebra_mac *mac;
13d60d35 4174
d62a17ae 4175 /* We are interested in MACs only on ports or (port, VLAN) that
4176 * map to a VNI.
4177 */
8b5fdf2e 4178 zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
87d76d54 4179 if (!zevpn)
d62a17ae 4180 return 0;
87d76d54 4181 if (!zevpn->vxlan_if) {
9df414fe
QY
4182 zlog_debug(
4183 "VNI %u hash %p doesn't have intf upon local MAC DEL",
87d76d54 4184 zevpn->vni, zevpn);
d62a17ae 4185 return -1;
4186 }
13d60d35 4187
15400f95
AK
4188 /* If entry doesn't exist, nothing to do. */
4189 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
4190 if (!mac)
4191 return 0;
4192
4193 /* Is it a local entry? */
4194 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
4195 return 0;
4196
00a7710c 4197 return zebra_evpn_del_local_mac(zevpn, mac, false);
13d60d35 4198}
4199
4200/*
2232a77c 4201 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 4202 */
d62a17ae 4203int zebra_vxlan_local_mac_add_update(struct interface *ifp,
4204 struct interface *br_if,
4205 struct ethaddr *macaddr, vlanid_t vid,
b169fd6f
AK
4206 bool sticky, bool local_inactive,
4207 bool dp_static)
d62a17ae 4208{
f6371c34 4209 struct zebra_evpn *zevpn;
e22a946a 4210 struct zebra_vrf *zvrf;
d62a17ae 4211
2bdd4461 4212 assert(ifp);
b7895aad 4213
d62a17ae 4214 /* We are interested in MACs only on ports or (port, VLAN) that
87d76d54 4215 * map to an EVPN.
d62a17ae 4216 */
8b5fdf2e 4217 zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
87d76d54 4218 if (!zevpn) {
d62a17ae 4219 if (IS_ZEBRA_DEBUG_VXLAN)
4220 zlog_debug(
ef7b8be4
DL
4221 " Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
4222 sticky ? "sticky " : "", macaddr,
d62a17ae 4223 ifp->name, ifp->ifindex, vid);
4224 return 0;
4225 }
4226
87d76d54 4227 if (!zevpn->vxlan_if) {
28bd0652
DS
4228 if (IS_ZEBRA_DEBUG_VXLAN)
4229 zlog_debug(
d6951e5e 4230 " VNI %u hash %p doesn't have intf upon local MAC ADD",
87d76d54 4231 zevpn->vni, zevpn);
d62a17ae 4232 return -1;
4233 }
4234
d6bf8f13 4235 zvrf = zebra_vrf_get_evpn();
28bd0652
DS
4236 if (!zvrf) {
4237 if (IS_ZEBRA_DEBUG_VXLAN)
d6bf8f13 4238 zlog_debug(" No Evpn Global Vrf found");
e22a946a 4239 return -1;
28bd0652 4240 }
e22a946a 4241
d9d3455e
PR
4242 return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid,
4243 sticky, local_inactive,
00a7710c 4244 dp_static, NULL);
2232a77c 4245}
13d60d35 4246
4247/*
87d76d54 4248 * Handle message from client to delete a remote VTEP for an EVPN.
13d60d35 4249 */
7e5b0b2b 4250void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS)
d62a17ae 4251{
4252 struct stream *s;
d7c0a89a 4253 unsigned short l = 0;
d62a17ae 4254 vni_t vni;
4255 struct in_addr vtep_ip;
d62a17ae 4256
ec93aa12 4257 if (!is_evpn_enabled()) {
9df414fe 4258 zlog_debug(
7e5b0b2b 4259 "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
15569c58 4260 __func__);
8068a649 4261 return;
ec93aa12
DS
4262 }
4263
986512a3 4264 if (!EVPN_ENABLED(zvrf)) {
7e5b0b2b
MS
4265 zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
4266 zvrf_id(zvrf));
8068a649 4267 return;
2853fed6 4268 }
4269
1002497a 4270 s = msg;
d62a17ae 4271
89f4e507 4272 while (l < hdr->length) {
694bd4ce 4273 int flood_control __attribute__((unused));
8a64de72 4274
d62a17ae 4275 /* Obtain each remote VTEP and process. */
ec93aa12 4276 STREAM_GETL(s, vni);
d62a17ae 4277 l += 4;
ec93aa12 4278 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4279 l += IPV4_MAX_BYTELEN;
4280
8a64de72
DS
4281 /* Flood control is intentionally ignored right now */
4282 STREAM_GETL(s, flood_control);
4283 l += 4;
4284
d62a17ae 4285 if (IS_ZEBRA_DEBUG_VXLAN)
7e5b0b2b 4286 zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
9bcef951 4287 &vtep_ip, vni,
d62a17ae 4288 zebra_route_string(client->proto));
4289
7e5b0b2b
MS
4290 /* Enqueue for processing */
4291 zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf), vni, vtep_ip);
4292 }
4293
4294stream_failure:
4295 return;
4296}
4297
4298/*
4299 * Handle message from client to delete a remote VTEP for an EVPN.
4300 */
4301void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
4302 struct in_addr vtep_ip)
4303{
f6371c34 4304 struct zebra_evpn *zevpn;
c172c032 4305 struct zebra_vtep *zvtep;
7e5b0b2b
MS
4306 struct interface *ifp;
4307 struct zebra_if *zif;
4308 struct zebra_vrf *zvrf;
4309
4310 if (!is_evpn_enabled()) {
4311 zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
4312 __func__);
4313 return;
4314 }
4315
4316 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4317 if (!zvrf)
4318 return;
d62a17ae 4319
7e5b0b2b
MS
4320 if (!EVPN_ENABLED(zvrf)) {
4321 zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
4322 zvrf_id(zvrf));
4323 return;
4324 }
4325
4326 /* Locate VNI hash entry - expected to exist. */
4327 zevpn = zebra_evpn_lookup(vni);
4328 if (!zevpn) {
4329 if (IS_ZEBRA_DEBUG_VXLAN)
9df414fe 4330 zlog_debug(
7e5b0b2b
MS
4331 "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
4332 vni);
4333 return;
4334 }
b5ebdc9b 4335
7e5b0b2b
MS
4336 ifp = zevpn->vxlan_if;
4337 if (!ifp) {
4338 zlog_debug(
4339 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
4340 zevpn->vni, zevpn);
4341 return;
4342 }
4343 zif = ifp->info;
b5ebdc9b 4344
7e5b0b2b
MS
4345 /* If down or not mapped to a bridge, we're done. */
4346 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4347 return;
4348
4349 /* If the remote VTEP does not exist, there's nothing more to
4350 * do.
4351 * Otherwise, uninstall any remote MACs pointing to this VTEP
4352 * and then, the VTEP entry itself and remove it.
4353 */
4354 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4355 if (!zvtep)
4356 return;
4357
4358 zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
4359 zebra_evpn_vtep_del(zevpn, zvtep);
4360}
4361
4362/*
4363 * Handle message from client to add a remote VTEP for an EVPN.
4364 */
4365void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
4366 struct in_addr vtep_ip, int flood_control)
4367{
f6371c34 4368 struct zebra_evpn *zevpn;
7e5b0b2b
MS
4369 struct interface *ifp;
4370 struct zebra_if *zif;
c172c032 4371 struct zebra_vtep *zvtep;
7e5b0b2b 4372 struct zebra_vrf *zvrf;
d62a17ae 4373
7e5b0b2b
MS
4374 if (!is_evpn_enabled()) {
4375 zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
4376 __func__);
4377 return;
d62a17ae 4378 }
4379
7e5b0b2b
MS
4380 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4381 if (!zvrf)
4382 return;
4383
4384 if (!EVPN_ENABLED(zvrf)) {
4385 zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
4386 zvrf_id(zvrf));
4387 return;
4388 }
4389
4390 /* Locate VNI hash entry - expected to exist. */
4391 zevpn = zebra_evpn_lookup(vni);
4392 if (!zevpn) {
4393 flog_err(
4394 EC_ZEBRA_VTEP_ADD_FAILED,
4395 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
4396 vni);
4397 return;
4398 }
4399
4400 ifp = zevpn->vxlan_if;
4401 if (!ifp) {
4402 flog_err(
4403 EC_ZEBRA_VTEP_ADD_FAILED,
4404 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
4405 zevpn->vni, zevpn);
4406 return;
4407 }
4408
4409 zif = ifp->info;
4410
4411 /* If down or not mapped to a bridge, we're done. */
4412 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4413 return;
4414
4415 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4416 if (zvtep) {
4417 /* If the remote VTEP already exists check if
4418 * the flood mode has changed
4419 */
4420 if (zvtep->flood_control != flood_control) {
4421 if (zvtep->flood_control == VXLAN_FLOOD_DISABLED)
4422 /* old mode was head-end-replication but
4423 * is no longer; get rid of the HER fdb
4424 * entry installed before
4425 */
4426 zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
4427 zvtep->flood_control = flood_control;
4428 zebra_evpn_vtep_install(zevpn, zvtep);
4429 }
4430 } else {
4431 zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, flood_control);
4432 if (zvtep)
4433 zebra_evpn_vtep_install(zevpn, zvtep);
4434 else
4435 flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
4436 "Failed to add remote VTEP, VNI %u zevpn %p",
4437 vni, zevpn);
4438 }
13d60d35 4439}
4440
4441/*
87d76d54 4442 * Handle message from client to add a remote VTEP for an EVPN.
13d60d35 4443 */
7e5b0b2b 4444void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS)
d62a17ae 4445{
4446 struct stream *s;
d7c0a89a 4447 unsigned short l = 0;
d62a17ae 4448 vni_t vni;
4449 struct in_addr vtep_ip;
9718c54e 4450 int flood_control;
d62a17ae 4451
ec93aa12 4452 if (!is_evpn_enabled()) {
9df414fe 4453 zlog_debug(
7e5b0b2b 4454 "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
15569c58 4455 __func__);
8068a649 4456 return;
ec93aa12
DS
4457 }
4458
986512a3 4459 if (!EVPN_ENABLED(zvrf)) {
7e5b0b2b
MS
4460 zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
4461 zvrf_id(zvrf));
8068a649 4462 return;
2853fed6 4463 }
d62a17ae 4464
1002497a 4465 s = msg;
d62a17ae 4466
89f4e507 4467 while (l < hdr->length) {
d62a17ae 4468 /* Obtain each remote VTEP and process. */
ec93aa12 4469 STREAM_GETL(s, vni);
d62a17ae 4470 l += 4;
ec93aa12 4471 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
9718c54e 4472 STREAM_GETL(s, flood_control);
8a64de72 4473 l += IPV4_MAX_BYTELEN + 4;
d62a17ae 4474
4475 if (IS_ZEBRA_DEBUG_VXLAN)
7e5b0b2b
MS
4476 zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
4477 &vtep_ip, vni, flood_control,
4478 zebra_route_string(client->proto));
d62a17ae 4479
7e5b0b2b
MS
4480 /* Enqueue for processing */
4481 zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf), vni, vtep_ip,
4482 flood_control);
d62a17ae 4483 }
4484
ec93aa12 4485stream_failure:
8068a649 4486 return;
13d60d35 4487}
4488
1a98c087
MK
4489/*
4490 * Add/Del gateway macip to evpn
4491 * g/w can be:
4492 * 1. SVI interface on a vlan aware bridge
4493 * 2. SVI interface on a vlan unaware bridge
4494 * 3. vrr interface (MACVLAN) associated to a SVI
4495 * We advertise macip routes for an interface if it is associated to VxLan vlan
4496 */
7e5b0b2b 4497int zebra_vxlan_add_del_gw_macip(struct interface *ifp, const struct prefix *p,
1a98c087
MK
4498 int add)
4499{
4500 struct ipaddr ip;
4501 struct ethaddr macaddr;
f6371c34 4502 struct zebra_evpn *zevpn = NULL;
1a98c087
MK
4503
4504 memset(&ip, 0, sizeof(struct ipaddr));
4505 memset(&macaddr, 0, sizeof(struct ethaddr));
4506
2853fed6 4507 /* Check if EVPN is enabled. */
4508 if (!is_evpn_enabled())
297a21b6
MK
4509 return 0;
4510
1a98c087
MK
4511 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
4512 struct interface *svi_if =
4513 NULL; /* SVI corresponding to the MACVLAN */
4514 struct zebra_if *ifp_zif =
4515 NULL; /* Zebra daemon specific info for MACVLAN */
4516 struct zebra_if *svi_if_zif =
4517 NULL; /* Zebra daemon specific info for SVI*/
4518
4519 ifp_zif = ifp->info;
4520 if (!ifp_zif)
4521 return -1;
4522
71349e03
MK
4523 /*
4524 * for a MACVLAN interface the link represents the svi_if
4525 */
4526 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4527 ifp_zif->link_ifindex);
1a98c087 4528 if (!svi_if) {
9df414fe
QY
4529 zlog_debug("MACVLAN %s(%u) without link information",
4530 ifp->name, ifp->ifindex);
1a98c087
MK
4531 return -1;
4532 }
4533
4534 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
4535 /*
4536 * If it is a vlan aware bridge then the link gives the
4537 * bridge information
4538 */
4539 struct interface *svi_if_link = NULL;
4540
1a98c087 4541 svi_if_zif = svi_if->info;
71349e03
MK
4542 if (svi_if_zif) {
4543 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
4544 zebra_ns_lookup(NS_DEFAULT),
4545 svi_if_zif->link_ifindex);
8b5fdf2e
PR
4546 zevpn = zebra_evpn_from_svi(svi_if,
4547 svi_if_link);
71349e03 4548 }
1a98c087 4549 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
4550 /*
4551 * If it is a vlan unaware bridge then svi is the bridge
4552 * itself
4553 */
8b5fdf2e 4554 zevpn = zebra_evpn_from_svi(svi_if, svi_if);
1a98c087
MK
4555 }
4556 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
4557 struct zebra_if *svi_if_zif =
71349e03
MK
4558 NULL; /* Zebra daemon specific info for SVI */
4559 struct interface *svi_if_link =
4560 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
4561
4562 svi_if_zif = ifp->info;
e3bb770c
IS
4563 if (svi_if_zif) {
4564 svi_if_link = if_lookup_by_index_per_ns(
cef91a18
QY
4565 zebra_ns_lookup(NS_DEFAULT),
4566 svi_if_zif->link_ifindex);
e3bb770c 4567 if (svi_if_link)
8b5fdf2e 4568 zevpn = zebra_evpn_from_svi(ifp, svi_if_link);
e3bb770c 4569 }
1a98c087 4570 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
8b5fdf2e 4571 zevpn = zebra_evpn_from_svi(ifp, ifp);
1a98c087
MK
4572 }
4573
87d76d54 4574 if (!zevpn)
1a98c087
MK
4575 return 0;
4576
87d76d54 4577 if (!zevpn->vxlan_if) {
9df414fe 4578 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
87d76d54 4579 zevpn->vni, zevpn);
1a98c087
MK
4580 return -1;
4581 }
4582
c0c7707d
AK
4583 /* VRR IP is advertised only if gw-macip-adv-enabled */
4584 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
4585 if (!advertise_gw_macip_enabled(zevpn))
4586 return 0;
4587 } else {
4588 /* SVI IP is advertised if gw or svi macip-adv-enabled */
4589 if (!advertise_svi_macip_enabled(zevpn)
4590 && !advertise_gw_macip_enabled(zevpn))
4591 return 0;
4592 }
1a98c087 4593
1a98c087
MK
4594 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
4595
4596 if (p->family == AF_INET) {
4597 ip.ipa_type = IPADDR_V4;
4598 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
4599 sizeof(struct in_addr));
4600 } else if (p->family == AF_INET6) {
4601 ip.ipa_type = IPADDR_V6;
4602 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
4603 sizeof(struct in6_addr));
4604 }
4605
4606
4607 if (add)
8b5fdf2e 4608 zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip);
1a98c087 4609 else
8b5fdf2e 4610 zebra_evpn_gw_macip_del(ifp, zevpn, &ip);
1a98c087
MK
4611
4612 return 0;
4613}
4614
2232a77c 4615/*
b7cfce93
MK
4616 * Handle SVI interface going down.
4617 * SVI can be associated to either L3-VNI or L2-VNI.
4618 * For L2-VNI: At this point, this is a NOP since
4619 * the kernel deletes the neighbor entries on this SVI (if any).
87d76d54 4620 * We only need to update the vrf corresponding to zevpn.
b7cfce93
MK
4621 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
4622 * from bgp
2232a77c 4623 */
d62a17ae 4624int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 4625{
05843a27 4626 struct zebra_l3vni *zl3vni = NULL;
b7cfce93
MK
4627
4628 zl3vni = zl3vni_from_svi(ifp, link_if);
4629 if (zl3vni) {
4630
4631 /* process l3-vni down */
4632 zebra_vxlan_process_l3vni_oper_down(zl3vni);
4633
4634 /* remove association with svi-if */
4635 zl3vni->svi_if = NULL;
4636 } else {
f6371c34 4637 struct zebra_evpn *zevpn = NULL;
b7cfce93 4638
243b74ed
AK
4639 /* Unlink the SVI from the access VLAN */
4640 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, false);
4641
87d76d54 4642 /* since we dont have svi corresponding to zevpn, we associate it
b7cfce93
MK
4643 * to default vrf. Note: the corresponding neigh entries on the
4644 * SVI would have already been deleted */
8b5fdf2e 4645 zevpn = zebra_evpn_from_svi(ifp, link_if);
243b74ed 4646
87d76d54 4647 if (zevpn) {
9daa5d47 4648 zevpn->svi_if = NULL;
87d76d54 4649 zevpn->vrf_id = VRF_DEFAULT;
b7cfce93
MK
4650
4651 /* update the tenant vrf in BGP */
196d7a86
CS
4652 if (if_is_operative(zevpn->vxlan_if))
4653 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
4654 }
4655 }
d62a17ae 4656 return 0;
2232a77c 4657}
4658
4659/*
b7cfce93
MK
4660 * Handle SVI interface coming up.
4661 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
4662 * vxlan intf).
4663 * For L2-VNI: we need to install any remote neighbors entried (used for
4664 * apr-suppression)
4665 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 4666 */
d62a17ae 4667int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 4668{
f6371c34 4669 struct zebra_evpn *zevpn = NULL;
05843a27 4670 struct zebra_l3vni *zl3vni = NULL;
2232a77c 4671
b7cfce93
MK
4672 zl3vni = zl3vni_from_svi(ifp, link_if);
4673 if (zl3vni) {
2232a77c 4674
b7cfce93
MK
4675 /* associate with svi */
4676 zl3vni->svi_if = ifp;
2232a77c 4677
b7cfce93
MK
4678 /* process oper-up */
4679 if (is_l3vni_oper_up(zl3vni))
4680 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4681 } else {
4682
4683 /* process SVI up for l2-vni */
4684 struct neigh_walk_ctx n_wctx;
4685
8b5fdf2e 4686 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 4687 if (!zevpn)
b7cfce93
MK
4688 return 0;
4689
87d76d54 4690 if (!zevpn->vxlan_if) {
9df414fe 4691 zlog_debug(
43e52561 4692 "VNI %u hash %p doesn't have intf upon SVI up",
87d76d54 4693 zevpn->vni, zevpn);
b7cfce93
MK
4694 return -1;
4695 }
4696
4697 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4698 zlog_debug(
4699 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
87d76d54 4700 ifp->name, ifp->ifindex, zevpn->vni,
a36898e7 4701 vrf_id_to_name(ifp->vrf_id));
2232a77c 4702
b7cfce93 4703 /* update the vrf information for l2-vni and inform bgp */
9daa5d47 4704 zevpn->svi_if = ifp;
87d76d54 4705 zevpn->vrf_id = ifp->vrf_id;
196d7a86
CS
4706
4707 if (if_is_operative(zevpn->vxlan_if))
4708 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
4709
4710 /* Install any remote neighbors for this VNI. */
4711 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 4712 n_wctx.zevpn = zevpn;
7cbae20a 4713 hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash,
b7cfce93 4714 &n_wctx);
243b74ed
AK
4715
4716 /* Link the SVI from the access VLAN */
4717 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, true);
b7cfce93 4718 }
2232a77c 4719
d62a17ae 4720 return 0;
2232a77c 4721}
4722
0056f687
CS
4723/*
4724 * Handle MAC-VLAN interface going down.
4725 * L3VNI: When MAC-VLAN interface goes down,
4726 * find its associated SVI and update type2/type-5 routes
4727 * with SVI as RMAC
4728 */
4729void zebra_vxlan_macvlan_down(struct interface *ifp)
4730{
05843a27 4731 struct zebra_l3vni *zl3vni = NULL;
0056f687
CS
4732 struct zebra_if *zif, *link_zif;
4733 struct interface *link_ifp, *link_if;
4734
4735 zif = ifp->info;
4736 assert(zif);
4737 link_ifp = zif->link;
59260d4a 4738 if (!link_ifp) {
65e76a9b
CS
4739 if (IS_ZEBRA_DEBUG_VXLAN) {
4740 struct interface *ifp;
4741
4742 ifp = if_lookup_by_index_all_vrf(zif->link_ifindex);
c1c292e7
CS
4743 zlog_debug("macvlan parent link is not found. Parent index %d ifp %s",
4744 zif->link_ifindex, ifp ? ifp->name : " ");
65e76a9b 4745 }
59260d4a
CS
4746 return;
4747 }
0056f687
CS
4748 link_zif = link_ifp->info;
4749 assert(link_zif);
4750
4751 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4752 link_zif->link_ifindex);
4753
4754 zl3vni = zl3vni_from_svi(link_ifp, link_if);
4755 if (zl3vni) {
4756 zl3vni->mac_vlan_if = NULL;
4757 if (is_l3vni_oper_up(zl3vni))
4758 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4759 }
4760}
4761
4762/*
4763 * Handle MAC-VLAN interface going up.
4764 * L3VNI: When MAC-VLAN interface comes up,
4765 * find its associated SVI and update type-2 routes
4766 * with MAC-VLAN's MAC as RMAC and for type-5 routes
4767 * use SVI's MAC as RMAC.
4768 */
4769void zebra_vxlan_macvlan_up(struct interface *ifp)
4770{
05843a27 4771 struct zebra_l3vni *zl3vni = NULL;
0056f687
CS
4772 struct zebra_if *zif, *link_zif;
4773 struct interface *link_ifp, *link_if;
4774
4775 zif = ifp->info;
4776 assert(zif);
4777 link_ifp = zif->link;
4778 link_zif = link_ifp->info;
4779 assert(link_zif);
4780
4781 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4782 link_zif->link_ifindex);
4783 zl3vni = zl3vni_from_svi(link_ifp, link_if);
4784 if (zl3vni) {
4785 /* associate with macvlan (VRR) interface */
4786 zl3vni->mac_vlan_if = ifp;
4787
4788 /* process oper-up */
4789 if (is_l3vni_oper_up(zl3vni))
4790 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4791 }
4792}
4793
13d60d35 4794/*
b7cfce93 4795 * Handle VxLAN interface down
13d60d35 4796 */
d62a17ae 4797int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 4798{
d62a17ae 4799 vni_t vni;
b7cfce93
MK
4800 struct zebra_if *zif = NULL;
4801 struct zebra_l2info_vxlan *vxl = NULL;
05843a27 4802 struct zebra_l3vni *zl3vni = NULL;
f6371c34 4803 struct zebra_evpn *zevpn;
13d60d35 4804
2853fed6 4805 /* Check if EVPN is enabled. */
4806 if (!is_evpn_enabled())
d62a17ae 4807 return 0;
13d60d35 4808
d62a17ae 4809 zif = ifp->info;
4810 assert(zif);
4811 vxl = &zif->l2info.vxl;
4812 vni = vxl->vni;
13d60d35 4813
643215ce 4814 zl3vni = zl3vni_lookup(vni);
4815 if (zl3vni) {
b7cfce93 4816 /* process-if-down for l3-vni */
b7cfce93 4817 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4818 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
4819 ifp->ifindex, vni);
b7cfce93 4820
b7cfce93 4821 zebra_vxlan_process_l3vni_oper_down(zl3vni);
b7cfce93
MK
4822 } else {
4823 /* process if-down for l2-vni */
b7cfce93 4824 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4825 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
4826 ifp->ifindex, vni);
13d60d35 4827
b7cfce93 4828 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4829 zevpn = zebra_evpn_lookup(vni);
87d76d54 4830 if (!zevpn) {
9df414fe 4831 zlog_debug(
b7cfce93
MK
4832 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
4833 ifp->name, ifp->ifindex, vni);
4834 return -1;
4835 }
13d60d35 4836
87d76d54 4837 assert(zevpn->vxlan_if == ifp);
13d60d35 4838
c7e83a4e
CS
4839 /* remove from l3-vni list */
4840 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
4841 if (zl3vni)
4842 listnode_delete(zl3vni->l2vnis, zevpn);
4843
b7cfce93 4844 /* Delete this VNI from BGP. */
8b5fdf2e 4845 zebra_evpn_send_del_to_client(zevpn);
2232a77c 4846
b7cfce93 4847 /* Free up all neighbors and MACs, if any. */
7cbae20a 4848 zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
b2998086 4849 zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
13d60d35 4850
b7cfce93 4851 /* Free up all remote VTEPs, if any. */
8b5fdf2e 4852 zebra_evpn_vtep_del_all(zevpn, 1);
b7cfce93 4853 }
d62a17ae 4854 return 0;
13d60d35 4855}
4856
4857/*
4858 * Handle VxLAN interface up - update BGP if required.
4859 */
d62a17ae 4860int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 4861{
d62a17ae 4862 vni_t vni;
b7cfce93
MK
4863 struct zebra_if *zif = NULL;
4864 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 4865 struct zebra_evpn *zevpn = NULL;
05843a27 4866 struct zebra_l3vni *zl3vni = NULL;
13d60d35 4867
2853fed6 4868 /* Check if EVPN is enabled. */
4869 if (!is_evpn_enabled())
d62a17ae 4870 return 0;
13d60d35 4871
d62a17ae 4872 zif = ifp->info;
4873 assert(zif);
4874 vxl = &zif->l2info.vxl;
4875 vni = vxl->vni;
13d60d35 4876
643215ce 4877 zl3vni = zl3vni_lookup(vni);
4878 if (zl3vni) {
b7cfce93 4879 /* we need to associate with SVI, if any, we can associate with
523cafc4 4880 * svi-if only after association with vxlan-intf is complete
4881 */
b7cfce93 4882 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
06d9cde5
CS
4883 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
4884
4885 if (IS_ZEBRA_DEBUG_VXLAN)
4886 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
4887 , ifp->name, ifp->ifindex, vni,
4888 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
4889 zl3vni->mac_vlan_if ?
4890 zl3vni->mac_vlan_if->name : "NIL");
b7cfce93
MK
4891
4892 if (is_l3vni_oper_up(zl3vni))
4893 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4894 } else {
4895 /* Handle L2-VNI add */
b7cfce93
MK
4896 struct interface *vlan_if = NULL;
4897
4898 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4899 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
4900 ifp->ifindex, vni);
b7cfce93
MK
4901
4902 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4903 zevpn = zebra_evpn_lookup(vni);
87d76d54 4904 if (!zevpn) {
9df414fe 4905 zlog_debug(
87d76d54 4906 "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
b7cfce93
MK
4907 ifp->name, ifp->ifindex, vni);
4908 return -1;
4909 }
4910
87d76d54 4911 assert(zevpn->vxlan_if == ifp);
7cbae20a 4912 vlan_if = zvni_map_to_svi(vxl->access_vlan,
b7cfce93
MK
4913 zif->brslave_info.br_if);
4914 if (vlan_if) {
9daa5d47 4915 zevpn->svi_if = vlan_if;
87d76d54 4916 zevpn->vrf_id = vlan_if->vrf_id;
a36898e7 4917 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
b7cfce93 4918 if (zl3vni)
c7e83a4e 4919 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
b7cfce93
MK
4920 }
4921
4922 /* If part of a bridge, inform BGP about this VNI. */
4923 /* Also, read and populate local MACs and neighbors. */
4924 if (zif->brslave_info.br_if) {
8b5fdf2e
PR
4925 zebra_evpn_send_add_to_client(zevpn);
4926 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93 4927 }
d62a17ae 4928 }
13d60d35 4929
d62a17ae 4930 return 0;
13d60d35 4931}
4932
4933/*
4934 * Handle VxLAN interface delete. Locate and remove entry in hash table
4935 * and update BGP, if required.
4936 */
d62a17ae 4937int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 4938{
d62a17ae 4939 vni_t vni;
b7cfce93
MK
4940 struct zebra_if *zif = NULL;
4941 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 4942 struct zebra_evpn *zevpn = NULL;
05843a27 4943 struct zebra_l3vni *zl3vni = NULL;
13d60d35 4944
2853fed6 4945 /* Check if EVPN is enabled. */
4946 if (!is_evpn_enabled())
d62a17ae 4947 return 0;
13d60d35 4948
d62a17ae 4949 zif = ifp->info;
4950 assert(zif);
4951 vxl = &zif->l2info.vxl;
4952 vni = vxl->vni;
13d60d35 4953
643215ce 4954 zl3vni = zl3vni_lookup(vni);
4955 if (zl3vni) {
b7cfce93
MK
4956
4957 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4958 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
4959 ifp->ifindex);
13d60d35 4960
b7cfce93
MK
4961 /* process oper-down for l3-vni */
4962 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 4963
b7cfce93 4964 /* remove the association with vxlan_if */
b67a60d2 4965 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
b7cfce93
MK
4966 zl3vni->vxlan_if = NULL;
4967 } else {
13d60d35 4968
b7cfce93 4969 /* process if-del for l2-vni*/
b7cfce93 4970 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4971 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
4972 ifp->ifindex);
b7cfce93
MK
4973
4974 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4975 zevpn = zebra_evpn_lookup(vni);
87d76d54 4976 if (!zevpn) {
9df414fe 4977 zlog_debug(
b7cfce93
MK
4978 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
4979 ifp->name, ifp->ifindex, vni);
4980 return 0;
4981 }
4982
4983 /* remove from l3-vni list */
87d76d54 4984 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
b7cfce93 4985 if (zl3vni)
87d76d54 4986 listnode_delete(zl3vni->l2vnis, zevpn);
b7cfce93 4987 /* Delete VNI from BGP. */
8b5fdf2e 4988 zebra_evpn_send_del_to_client(zevpn);
b7cfce93
MK
4989
4990 /* Free up all neighbors and MAC, if any. */
7cbae20a 4991 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
b2998086 4992 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
b7cfce93
MK
4993
4994 /* Free up all remote VTEPs, if any. */
8b5fdf2e 4995 zebra_evpn_vtep_del_all(zevpn, 0);
b7cfce93
MK
4996
4997 /* Delete the hash entry. */
8b5fdf2e 4998 if (zebra_evpn_vxlan_del(zevpn)) {
e914ccbe 4999 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
87d76d54
PR
5000 "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
5001 zevpn, ifp->name, ifp->ifindex, zevpn->vni);
b7cfce93
MK
5002 return -1;
5003 }
d62a17ae 5004 }
d62a17ae 5005 return 0;
13d60d35 5006}
5007
5008/*
5009 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
5010 */
d7c0a89a 5011int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
d62a17ae 5012{
d62a17ae 5013 vni_t vni;
b7cfce93
MK
5014 struct zebra_if *zif = NULL;
5015 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 5016 struct zebra_evpn *zevpn = NULL;
05843a27 5017 struct zebra_l3vni *zl3vni = NULL;
9daa5d47 5018 struct interface *vlan_if = NULL;
d62a17ae 5019
2853fed6 5020 /* Check if EVPN is enabled. */
5021 if (!is_evpn_enabled())
d62a17ae 5022 return 0;
5023
5024 zif = ifp->info;
5025 assert(zif);
5026 vxl = &zif->l2info.vxl;
5027 vni = vxl->vni;
5028
643215ce 5029 zl3vni = zl3vni_lookup(vni);
5030 if (zl3vni) {
af026ae4 5031
b7cfce93
MK
5032 if (IS_ZEBRA_DEBUG_VXLAN)
5033 zlog_debug(
9bcef951 5034 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
996c9314 5035 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5036 &vxl->vtep_ip,
b7cfce93
MK
5037 zif->brslave_info.bridge_ifindex, chgflags);
5038
5039 /* Removed from bridge? Cleanup and return */
5040 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
5041 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
5042 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5043 return 0;
5044 }
5045
c7620108
PG
5046 if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
5047 && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
5048 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5049 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5050 return 0;
5051 }
5052
b7cfce93 5053 /* access-vlan change - process oper down, associate with new
523cafc4 5054 * svi_if and then process oper up again
5055 */
b7cfce93
MK
5056 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5057 if (if_is_operative(ifp)) {
5058 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5059 zl3vni->svi_if = NULL;
5060 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
06d9cde5
CS
5061 zl3vni->mac_vlan_if =
5062 zl3vni_map_to_mac_vlan_if(zl3vni);
bca63dc8 5063 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
5064 if (is_l3vni_oper_up(zl3vni))
5065 zebra_vxlan_process_l3vni_oper_up(
996c9314 5066 zl3vni);
b7cfce93
MK
5067 }
5068 }
d62a17ae 5069
12eeac84
MK
5070 /*
5071 * local-ip change - process oper down, associate with new
5072 * local-ip and then process oper up again
5073 */
5074 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
5075 if (if_is_operative(ifp)) {
5076 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5077 zl3vni->local_vtep_ip = vxl->vtep_ip;
5078 if (is_l3vni_oper_up(zl3vni))
5079 zebra_vxlan_process_l3vni_oper_up(
996c9314 5080 zl3vni);
12eeac84
MK
5081 }
5082 }
5083
bca63dc8
MK
5084 /* Update local tunnel IP. */
5085 zl3vni->local_vtep_ip = vxl->vtep_ip;
5086
12eeac84
MK
5087 /* if we have a valid new master, process l3-vni oper up */
5088 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
5089 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
b7cfce93
MK
5090 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5091 }
5092 } else {
d62a17ae 5093
b7cfce93 5094 /* Update VNI hash. */
8b5fdf2e 5095 zevpn = zebra_evpn_lookup(vni);
87d76d54 5096 if (!zevpn) {
9df414fe 5097 zlog_debug(
87d76d54 5098 "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
b7cfce93
MK
5099 ifp->name, ifp->ifindex, vni);
5100 return -1;
5101 }
d62a17ae 5102
b7cfce93
MK
5103 if (IS_ZEBRA_DEBUG_VXLAN)
5104 zlog_debug(
9bcef951 5105 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
996c9314 5106 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5107 &vxl->vtep_ip,
b7cfce93
MK
5108 zif->brslave_info.bridge_ifindex, chgflags);
5109
5110 /* Removed from bridge? Cleanup and return */
5111 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
5112 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
5113 /* Delete from client, remove all remote VTEPs */
5114 /* Also, free up all MACs and neighbors. */
9daa5d47 5115 zevpn->svi_if = NULL;
8b5fdf2e 5116 zebra_evpn_send_del_to_client(zevpn);
7cbae20a 5117 zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
b2998086 5118 zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
8b5fdf2e 5119 zebra_evpn_vtep_del_all(zevpn, 1);
b7cfce93
MK
5120 return 0;
5121 }
d62a17ae 5122
b7cfce93
MK
5123 /* Handle other changes. */
5124 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5125 /* Remove all existing local neigh and MACs for this VNI
5126 * (including from BGP)
5127 */
7cbae20a 5128 zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
b2998086 5129 zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
b7cfce93 5130 }
d62a17ae 5131
87d76d54
PR
5132 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
5133 zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
5134 zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
5135 zevpn->mcast_grp);
abfa0a96 5136 zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
87d76d54
PR
5137 zevpn->local_vtep_ip = vxl->vtep_ip;
5138 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
5139 /* on local vtep-ip check if ES orig-ip
5140 * needs to be updated
5141 */
87d76d54 5142 zebra_evpn_es_set_base_evpn(zevpn);
abfa0a96 5143 }
87d76d54 5144 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
9daa5d47
AD
5145 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5146 zif->brslave_info.br_if);
5147 if (vlan_if)
5148 zevpn->svi_if = vlan_if;
5149
b7cfce93
MK
5150 /* Take further actions needed.
5151 * Note that if we are here, there is a change of interest.
5152 */
5153 /* If down or not mapped to a bridge, we're done. */
5154 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5155 return 0;
d62a17ae 5156
b7cfce93
MK
5157 /* Inform BGP, if there is a change of interest. */
5158 if (chgflags
39c46ff1
AK
5159 & (ZEBRA_VXLIF_MASTER_CHANGE |
5160 ZEBRA_VXLIF_LOCAL_IP_CHANGE |
5161 ZEBRA_VXLIF_MCAST_GRP_CHANGE))
8b5fdf2e 5162 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
5163
5164 /* If there is a valid new master or a VLAN mapping change,
5165 * read and populate local MACs and neighbors.
5166 * Also, reinstall any remote MACs and neighbors
5167 * for this VNI (based on new VLAN).
5168 */
5169 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8b5fdf2e 5170 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93
MK
5171 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5172 struct mac_walk_ctx m_wctx;
5173 struct neigh_walk_ctx n_wctx;
5174
8b5fdf2e 5175 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93
MK
5176
5177 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
87d76d54 5178 m_wctx.zevpn = zevpn;
8b5fdf2e
PR
5179 hash_iterate(zevpn->mac_table,
5180 zebra_evpn_install_mac_hash, &m_wctx);
b7cfce93
MK
5181
5182 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
87d76d54 5183 n_wctx.zevpn = zevpn;
7cbae20a
PR
5184 hash_iterate(zevpn->neigh_table,
5185 zebra_evpn_install_neigh_hash, &n_wctx);
b7cfce93 5186 }
d62a17ae 5187 }
5188
5189 return 0;
13d60d35 5190}
5191
5192/*
5193 * Handle VxLAN interface add.
5194 */
d62a17ae 5195int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 5196{
d62a17ae 5197 vni_t vni;
b7cfce93
MK
5198 struct zebra_if *zif = NULL;
5199 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 5200 struct zebra_evpn *zevpn = NULL;
05843a27 5201 struct zebra_l3vni *zl3vni = NULL;
13d60d35 5202
2853fed6 5203 /* Check if EVPN is enabled. */
5204 if (!is_evpn_enabled())
d62a17ae 5205 return 0;
13d60d35 5206
d62a17ae 5207 zif = ifp->info;
5208 assert(zif);
5209 vxl = &zif->l2info.vxl;
5210 vni = vxl->vni;
13d60d35 5211
643215ce 5212 zl3vni = zl3vni_lookup(vni);
5213 if (zl3vni) {
13d60d35 5214
b7cfce93 5215 /* process if-add for l3-vni*/
b7cfce93
MK
5216 if (IS_ZEBRA_DEBUG_VXLAN)
5217 zlog_debug(
9bcef951 5218 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
996c9314 5219 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5220 &vxl->vtep_ip,
b7cfce93
MK
5221 zif->brslave_info.bridge_ifindex);
5222
b7cfce93 5223 /* associate with vxlan_if */
b67a60d2 5224 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
5225 zl3vni->vxlan_if = ifp;
5226
5227 /* Associate with SVI, if any. We can associate with svi-if only
5228 * after association with vxlan_if is complete */
5229 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5230
06d9cde5
CS
5231 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
5232
b7cfce93
MK
5233 if (is_l3vni_oper_up(zl3vni))
5234 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5235 } else {
5236
5237 /* process if-add for l2-vni */
b7cfce93
MK
5238 struct interface *vlan_if = NULL;
5239
87d76d54 5240 /* Create or update EVPN hash. */
8b5fdf2e 5241 zevpn = zebra_evpn_lookup(vni);
87d76d54 5242 if (!zevpn) {
8b5fdf2e 5243 zevpn = zebra_evpn_add(vni);
87d76d54 5244 if (!zevpn) {
af4c2728 5245 flog_err(
e914ccbe 5246 EC_ZEBRA_VNI_ADD_FAILED,
87d76d54 5247 "Failed to add EVPN hash, IF %s(%u) VNI %u",
b7cfce93
MK
5248 ifp->name, ifp->ifindex, vni);
5249 return -1;
5250 }
5251 }
5252
87d76d54
PR
5253 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
5254 zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
5255 zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
5256 zevpn->mcast_grp);
abfa0a96 5257 zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
87d76d54
PR
5258 zevpn->local_vtep_ip = vxl->vtep_ip;
5259 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
5260 /* on local vtep-ip check if ES orig-ip
5261 * needs to be updated
5262 */
87d76d54 5263 zebra_evpn_es_set_base_evpn(zevpn);
abfa0a96 5264 }
87d76d54 5265 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
7cbae20a 5266 vlan_if = zvni_map_to_svi(vxl->access_vlan,
b7cfce93
MK
5267 zif->brslave_info.br_if);
5268 if (vlan_if) {
9daa5d47 5269 zevpn->svi_if = vlan_if;
87d76d54 5270 zevpn->vrf_id = vlan_if->vrf_id;
a36898e7 5271 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
b7cfce93 5272 if (zl3vni)
c7e83a4e 5273 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
b7cfce93
MK
5274 }
5275
f6371c34 5276 if (IS_ZEBRA_DEBUG_VXLAN)
b7cfce93 5277 zlog_debug(
f6371c34 5278 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
b7cfce93 5279 vni,
a36898e7 5280 vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
08ab35fe 5281 : VRF_DEFAULT_NAME,
996c9314 5282 ifp->name, ifp->ifindex, vxl->access_vlan,
f6371c34 5283 &vxl->vtep_ip, &vxl->mcast_grp,
b7cfce93
MK
5284 zif->brslave_info.bridge_ifindex);
5285
5286 /* If down or not mapped to a bridge, we're done. */
5287 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5288 return 0;
5289
5290 /* Inform BGP */
8b5fdf2e 5291 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
5292
5293 /* Read and populate local MACs and neighbors */
8b5fdf2e 5294 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93
MK
5295 }
5296
5297 return 0;
5298}
5299
996c9314
LB
5300int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
5301 char *err, int err_str_sz, int filter,
5302 int add)
b7cfce93 5303{
05843a27 5304 struct zebra_l3vni *zl3vni = NULL;
5e53dce3 5305 struct zebra_vrf *zvrf_evpn = NULL;
b7cfce93 5306
5e53dce3
T
5307 zvrf_evpn = zebra_vrf_get_evpn();
5308 if (!zvrf_evpn)
b7cfce93
MK
5309 return -1;
5310
5311 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 5312 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
b7cfce93
MK
5313 add ? "ADD" : "DEL");
5314
5315 if (add) {
5316
3b0a590b 5317 /* Remove L2VNI if present */
b7cfce93
MK
5318 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
5319
5320 /* check if the vni is already present under zvrf */
5321 if (zvrf->l3vni) {
3f02fbab 5322 snprintf(err, err_str_sz,
b7cfce93
MK
5323 "VNI is already configured under the vrf");
5324 return -1;
5325 }
5326
5327 /* check if this VNI is already present in the system */
5328 zl3vni = zl3vni_lookup(vni);
5329 if (zl3vni) {
3f02fbab 5330 snprintf(err, err_str_sz,
b7cfce93
MK
5331 "VNI is already configured as L3-VNI");
5332 return -1;
5333 }
5334
5335 /* add the L3-VNI to the global table */
5336 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
5337 if (!zl3vni) {
996c9314 5338 snprintf(err, err_str_sz, "Could not add L3-VNI");
b7cfce93
MK
5339 return -1;
5340 }
5341
5342 /* associate the vrf with vni */
5343 zvrf->l3vni = vni;
5344
c48d9f5f
MK
5345 /* set the filter in l3vni to denote if we are using l3vni only
5346 * for prefix routes
5347 */
5348 if (filter)
5349 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
5350
b7cfce93 5351 /* associate with vxlan-intf;
523cafc4 5352 * we need to associate with the vxlan-intf first
5353 */
b7cfce93
MK
5354 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
5355
5356 /* associate with corresponding SVI interface, we can associate
5357 * with svi-if only after vxlan interface association is
523cafc4 5358 * complete
5359 */
b7cfce93
MK
5360 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5361
06d9cde5
CS
5362 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
5363
5364 if (IS_ZEBRA_DEBUG_VXLAN)
15569c58
DA
5365 zlog_debug(
5366 "%s: l3vni %u svi_if %s mac_vlan_if %s",
5367 __func__, vni,
5368 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
5369 zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
5370 : "NIL");
06d9cde5 5371
b7cfce93 5372 /* formulate l2vni list */
87d76d54 5373 hash_iterate(zvrf_evpn->evpn_table, zevpn_add_to_l3vni_list,
996c9314 5374 zl3vni);
b7cfce93
MK
5375
5376 if (is_l3vni_oper_up(zl3vni))
5377 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5378
5379 } else {
5380 zl3vni = zl3vni_lookup(vni);
5381 if (!zl3vni) {
3f02fbab 5382 snprintf(err, err_str_sz, "VNI doesn't exist");
d62a17ae 5383 return -1;
5384 }
b7cfce93 5385
7a6ca8a6
KA
5386 if (zvrf->l3vni != vni) {
5387 snprintf(err, err_str_sz,
5388 "VNI %d doesn't exist in VRF: %s",
5389 vni, zvrf->vrf->name);
5390 return -1;
5391 }
5392
cf299714
MK
5393 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
5394 snprintf(err, ERR_STR_SZ,
5395 "prefix-routes-only is not set for the vni");
5396 return -1;
5397 }
5398
b7cfce93
MK
5399 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5400
5e06422c 5401 /* delete and uninstall all rmacs */
996c9314 5402 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
5e06422c
MK
5403 zl3vni);
5404
5405 /* delete and uninstall all next-hops */
996c9314 5406 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
5e06422c
MK
5407 zl3vni);
5408
b7cfce93
MK
5409 zvrf->l3vni = 0;
5410 zl3vni_del(zl3vni);
5411
3b0a590b 5412 /* Add L2VNI for this VNI */
b7cfce93 5413 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 5414 }
b7cfce93
MK
5415 return 0;
5416}
13d60d35 5417
84915b0a 5418int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
5419{
05843a27 5420 struct zebra_l3vni *zl3vni = NULL;
84915b0a 5421
5422 if (zvrf->l3vni)
5423 zl3vni = zl3vni_lookup(zvrf->l3vni);
5424 if (!zl3vni)
5425 return 0;
5426
5427 zl3vni->vrf_id = zvrf_id(zvrf);
5428 if (is_l3vni_oper_up(zl3vni))
5429 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5430 return 0;
5431}
5432
5433int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
b7cfce93 5434{
05843a27 5435 struct zebra_l3vni *zl3vni = NULL;
13d60d35 5436
84915b0a 5437 if (zvrf->l3vni)
5438 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93 5439 if (!zl3vni)
d62a17ae 5440 return 0;
13d60d35 5441
b7cfce93 5442 zebra_vxlan_process_l3vni_oper_down(zl3vni);
92475ca4
CS
5443
5444 /* delete and uninstall all rmacs */
5445 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, zl3vni);
5446 /* delete and uninstall all next-hops */
5447 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, zl3vni);
5448
5449 zl3vni->vrf_id = VRF_UNKNOWN;
5450
84915b0a 5451 return 0;
5452}
5453
5454int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
5455{
05843a27 5456 struct zebra_l3vni *zl3vni = NULL;
84915b0a 5457 vni_t vni;
5458
5459 if (zvrf->l3vni)
5460 zl3vni = zl3vni_lookup(zvrf->l3vni);
5461 if (!zl3vni)
5462 return 0;
5463
5464 vni = zl3vni->vni;
b7cfce93 5465 zl3vni_del(zl3vni);
84915b0a 5466 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
2232a77c 5467
d62a17ae 5468 return 0;
13d60d35 5469}
5470
fbac9605
DS
5471/*
5472 * Handle message from client to specify the flooding mechanism for
5473 * BUM packets. The default is to do head-end (ingress) replication
5474 * and the other supported option is to disable it. This applies to
5475 * all BUM traffic and disabling it applies to both the transmit and
5476 * receive direction.
5477 */
5478void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
5479{
5480 struct stream *s;
5481 enum vxlan_flood_control flood_ctrl;
5482
986512a3 5483 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8 5484 zlog_err("EVPN flood control for non-EVPN VRF %u",
fbac9605
DS
5485 zvrf_id(zvrf));
5486 return;
5487 }
5488
5489 s = msg;
5490 STREAM_GETC(s, flood_ctrl);
5491
5492 if (IS_ZEBRA_DEBUG_VXLAN)
5493 zlog_debug("EVPN flood control %u, currently %u",
5494 flood_ctrl, zvrf->vxlan_flood_ctrl);
5495
5496 if (zvrf->vxlan_flood_ctrl == flood_ctrl)
5497 return;
5498
5499 zvrf->vxlan_flood_ctrl = flood_ctrl;
5500
5501 /* Install or uninstall flood entries corresponding to
5502 * remote VTEPs.
5503 */
8b5fdf2e 5504 hash_iterate(zvrf->evpn_table, zebra_evpn_handle_flooding_remote_vteps,
fbac9605
DS
5505 zvrf);
5506
5507stream_failure:
5508 return;
5509}
5510
278e26de
CS
5511/*
5512 * Handle message from client to enable/disable advertisement of svi macip
5513 * routes
5514 */
5515void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
5516{
5517 struct stream *s;
5518 int advertise;
5519 vni_t vni = 0;
f6371c34 5520 struct zebra_evpn *zevpn = NULL;
278e26de
CS
5521 struct interface *ifp = NULL;
5522
986512a3 5523 if (!EVPN_ENABLED(zvrf)) {
27627f9a 5524 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
a0b0b5c8 5525 zvrf_id(zvrf));
278e26de
CS
5526 return;
5527 }
5528
5529 s = msg;
5530 STREAM_GETC(s, advertise);
5531 STREAM_GETL(s, vni);
5532
5533 if (!vni) {
5534 if (IS_ZEBRA_DEBUG_VXLAN)
27627f9a 5535 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
278e26de 5536 advertise ? "enabled" : "disabled",
838cef6d 5537 advertise_svi_macip_enabled(NULL)
278e26de
CS
5538 ? "enabled"
5539 : "disabled");
5540
5541 if (zvrf->advertise_svi_macip == advertise)
5542 return;
5543
5544
5545 if (advertise) {
5546 zvrf->advertise_svi_macip = advertise;
87d76d54 5547 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5548 zebra_evpn_gw_macip_add_for_evpn_hash,
5549 NULL);
278e26de 5550 } else {
87d76d54 5551 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5552 zebra_evpn_svi_macip_del_for_evpn_hash,
5553 NULL);
278e26de
CS
5554 zvrf->advertise_svi_macip = advertise;
5555 }
5556
5557 } else {
5558 struct zebra_if *zif = NULL;
5559 struct zebra_l2info_vxlan zl2_info;
5560 struct interface *vlan_if = NULL;
5561
8b5fdf2e 5562 zevpn = zebra_evpn_lookup(vni);
87d76d54 5563 if (!zevpn)
278e26de
CS
5564 return;
5565
5566 if (IS_ZEBRA_DEBUG_VXLAN)
5567 zlog_debug(
5568 "EVPN SVI macip Adv %s on VNI %d , currently %s",
5569 advertise ? "enabled" : "disabled", vni,
87d76d54 5570 advertise_svi_macip_enabled(zevpn)
278e26de
CS
5571 ? "enabled"
5572 : "disabled");
5573
87d76d54 5574 if (zevpn->advertise_svi_macip == advertise)
278e26de
CS
5575 return;
5576
3dacbb9d
CS
5577 /* Store flag even though SVI is not present.
5578 * Once SVI comes up triggers self MAC-IP route add.
5579 */
87d76d54 5580 zevpn->advertise_svi_macip = advertise;
3dacbb9d 5581
87d76d54 5582 ifp = zevpn->vxlan_if;
278e26de
CS
5583 if (!ifp)
5584 return;
5585
5586 zif = ifp->info;
5587
5588 /* If down or not mapped to a bridge, we're done. */
5589 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5590 return;
5591
5592 zl2_info = zif->l2info.vxl;
7cbae20a 5593 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
278e26de
CS
5594 zif->brslave_info.br_if);
5595 if (!vlan_if)
5596 return;
5597
5598 if (advertise) {
278e26de 5599 /* Add primary SVI MAC-IP */
8b5fdf2e 5600 zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
278e26de 5601 } else {
3dacbb9d 5602 /* Del primary SVI MAC-IP */
8b5fdf2e 5603 zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
278e26de
CS
5604 }
5605 }
5606
5607stream_failure:
5608 return;
5609}
5610
31310b25
MK
5611/*
5612 * Handle message from client to enable/disable advertisement of g/w macip
5613 * routes
5614 */
89f4e507 5615void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
31310b25
MK
5616{
5617 struct stream *s;
5618 int advertise;
5619 vni_t vni = 0;
f6371c34 5620 struct zebra_evpn *zevpn = NULL;
31310b25
MK
5621 struct interface *ifp = NULL;
5622 struct zebra_if *zif = NULL;
5623 struct zebra_l2info_vxlan zl2_info;
5624 struct interface *vlan_if = NULL;
5625
986512a3 5626 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8
T
5627 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5628 zvrf_id(zvrf));
8068a649 5629 return;
31310b25
MK
5630 }
5631
1002497a 5632 s = msg;
2017b3ea 5633 STREAM_GETC(s, advertise);
7fb29f49 5634 STREAM_GET(&vni, s, 3);
31310b25 5635
8b5fdf2e 5636 zevpn = zebra_evpn_lookup(vni);
87d76d54 5637 if (!zevpn)
8068a649 5638 return;
31310b25 5639
87d76d54 5640 if (zevpn->advertise_subnet == advertise)
8068a649 5641 return;
31310b25
MK
5642
5643 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5644 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
5645 advertise ? "enabled" : "disabled", vni,
87d76d54 5646 zevpn->advertise_subnet ? "enabled" : "disabled");
31310b25
MK
5647
5648
87d76d54 5649 zevpn->advertise_subnet = advertise;
31310b25 5650
87d76d54 5651 ifp = zevpn->vxlan_if;
31310b25 5652 if (!ifp)
8068a649 5653 return;
31310b25
MK
5654
5655 zif = ifp->info;
5656
5657 /* If down or not mapped to a bridge, we're done. */
5658 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 5659 return;
31310b25
MK
5660
5661 zl2_info = zif->l2info.vxl;
5662
996c9314 5663 vlan_if =
7cbae20a 5664 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
31310b25 5665 if (!vlan_if)
8068a649 5666 return;
31310b25 5667
87d76d54 5668 if (zevpn->advertise_subnet)
8b5fdf2e 5669 zebra_evpn_advertise_subnet(zevpn, vlan_if, 1);
31310b25 5670 else
8b5fdf2e 5671 zebra_evpn_advertise_subnet(zevpn, vlan_if, 0);
2017b3ea
DS
5672
5673stream_failure:
5674 return;
31310b25
MK
5675}
5676
1a98c087
MK
5677/*
5678 * Handle message from client to enable/disable advertisement of g/w macip
5679 * routes
5680 */
89f4e507 5681void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
1a98c087
MK
5682{
5683 struct stream *s;
5684 int advertise;
5685 vni_t vni = 0;
f6371c34 5686 struct zebra_evpn *zevpn = NULL;
b5ebdc9b 5687 struct interface *ifp = NULL;
1a98c087 5688
986512a3 5689 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8 5690 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9df414fe 5691 zvrf_id(zvrf));
8068a649 5692 return;
2853fed6 5693 }
5694
1002497a 5695 s = msg;
ec93aa12 5696 STREAM_GETC(s, advertise);
cc6d5476 5697 STREAM_GETL(s, vni);
1a98c087
MK
5698
5699 if (!vni) {
5700 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5701 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 5702 advertise ? "enabled" : "disabled",
2853fed6 5703 advertise_gw_macip_enabled(NULL)
1a98c087
MK
5704 ? "enabled"
5705 : "disabled");
5706
5707 if (zvrf->advertise_gw_macip == advertise)
8068a649 5708 return;
1a98c087
MK
5709
5710 zvrf->advertise_gw_macip = advertise;
5711
87d76d54
PR
5712 if (advertise_gw_macip_enabled(zevpn))
5713 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5714 zebra_evpn_gw_macip_add_for_evpn_hash,
5715 NULL);
1a98c087 5716 else
87d76d54 5717 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5718 zebra_evpn_gw_macip_del_for_evpn_hash,
5719 NULL);
1a98c087
MK
5720
5721 } else {
5722 struct zebra_if *zif = NULL;
5723 struct zebra_l2info_vxlan zl2_info;
5724 struct interface *vlan_if = NULL;
5725 struct interface *vrr_if = NULL;
5726
8b5fdf2e 5727 zevpn = zebra_evpn_lookup(vni);
87d76d54 5728 if (!zevpn)
124ead27 5729 return;
01a6143b 5730
1a98c087
MK
5731 if (IS_ZEBRA_DEBUG_VXLAN)
5732 zlog_debug(
2853fed6 5733 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 5734 advertise ? "enabled" : "disabled", vni,
87d76d54 5735 advertise_gw_macip_enabled(zevpn) ? "enabled"
996c9314 5736 : "disabled");
1a98c087 5737
87d76d54 5738 if (zevpn->advertise_gw_macip == advertise)
8068a649 5739 return;
1a98c087 5740
87d76d54 5741 zevpn->advertise_gw_macip = advertise;
1a98c087 5742
87d76d54 5743 ifp = zevpn->vxlan_if;
b5ebdc9b 5744 if (!ifp)
8068a649 5745 return;
b5ebdc9b 5746
5747 zif = ifp->info;
5748
5749 /* If down or not mapped to a bridge, we're done. */
b682f6de 5750 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 5751 return;
b5ebdc9b 5752
1a98c087
MK
5753 zl2_info = zif->l2info.vxl;
5754
7cbae20a 5755 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
5756 zif->brslave_info.br_if);
5757 if (!vlan_if)
8068a649 5758 return;
1a98c087 5759
87d76d54 5760 if (advertise_gw_macip_enabled(zevpn)) {
1a98c087 5761 /* Add primary SVI MAC-IP */
8b5fdf2e 5762 zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
1a98c087
MK
5763
5764 /* Add VRR MAC-IP - if any*/
5765 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
5766 if (vrr_if)
8b5fdf2e 5767 zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
1a98c087
MK
5768 } else {
5769 /* Del primary MAC-IP */
8b5fdf2e 5770 zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
1a98c087
MK
5771
5772 /* Del VRR MAC-IP - if any*/
5773 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
5774 if (vrr_if)
8b5fdf2e 5775 zebra_evpn_del_macip_for_intf(vrr_if, zevpn);
1a98c087
MK
5776 }
5777 }
5778
ec93aa12 5779stream_failure:
8068a649 5780 return;
1a98c087
MK
5781}
5782
2961d060
PG
5783static int macfdb_read_ns(struct ns *ns,
5784 void *_in_param __attribute__((unused)),
5785 void **out_param __attribute__((unused)))
6265fbe5 5786{
2961d060
PG
5787 struct zebra_ns *zns = ns->info;
5788
6265fbe5 5789 macfdb_read(zns);
2961d060 5790 return NS_WALK_CONTINUE;
6265fbe5
PG
5791}
5792
2961d060
PG
5793static int neigh_read_ns(struct ns *ns,
5794 void *_in_param __attribute__((unused)),
5795 void **out_param __attribute__((unused)))
6265fbe5 5796{
2961d060
PG
5797 struct zebra_ns *zns = ns->info;
5798
6265fbe5 5799 neigh_read(zns);
2961d060 5800 return NS_WALK_CONTINUE;
6265fbe5 5801}
1a98c087 5802
13d60d35 5803/*
5804 * Handle message from client to learn (or stop learning) about VNIs and MACs.
5805 * When enabled, the VNI hash table will be built and MAC FDB table read;
5806 * when disabled, the entries should be deleted and remote VTEPs and MACs
5807 * uninstalled from the kernel.
fbac9605
DS
5808 * This also informs the setting for BUM handling at the time this change
5809 * occurs; it is relevant only when specifying "learn".
13d60d35 5810 */
89f4e507 5811void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
13d60d35 5812{
655b04d1
MK
5813 struct stream *s = NULL;
5814 int advertise = 0;
fbac9605 5815 enum vxlan_flood_control flood_ctrl;
13d60d35 5816
77b998fb
T
5817 /* Mismatch between EVPN VRF and current VRF (should be prevented by
5818 * bgpd's cli) */
f920dd6d 5819 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf))
8068a649 5820 return;
2853fed6 5821
1002497a 5822 s = msg;
ec93aa12 5823 STREAM_GETC(s, advertise);
fbac9605 5824 STREAM_GETC(s, flood_ctrl);
13d60d35 5825
d62a17ae 5826 if (IS_ZEBRA_DEBUG_VXLAN)
150971b5
T
5827 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
5828 zvrf_name(zvrf), zvrf_id(zvrf),
d62a17ae 5829 advertise ? "enabled" : "disabled",
fbac9605
DS
5830 is_evpn_enabled() ? "enabled" : "disabled",
5831 flood_ctrl);
13d60d35 5832
d62a17ae 5833 if (zvrf->advertise_all_vni == advertise)
8068a649 5834 return;
13d60d35 5835
d62a17ae 5836 zvrf->advertise_all_vni = advertise;
f920dd6d 5837 if (EVPN_ENABLED(zvrf)) {
0fb2ad05 5838 zrouter.evpn_vrf = zvrf;
150971b5 5839
fbac9605
DS
5840 /* Note BUM handling */
5841 zvrf->vxlan_flood_ctrl = flood_ctrl;
5842
ce5160c0
AK
5843 /* Replay all ESs */
5844 zebra_evpn_es_send_all_to_client(true /* add */);
5845
87d76d54
PR
5846 /* Build EVPN hash table and inform BGP. */
5847 zevpn_build_hash_table();
2232a77c 5848
1a98c087 5849 /* Add all SVI (L3 GW) MACs to BGP*/
8b5fdf2e
PR
5850 hash_iterate(zvrf->evpn_table,
5851 zebra_evpn_gw_macip_add_for_evpn_hash, NULL);
1a98c087 5852
d62a17ae 5853 /* Read the MAC FDB */
2961d060 5854 ns_walk_func(macfdb_read_ns, NULL, NULL);
2232a77c 5855
d62a17ae 5856 /* Read neighbors */
2961d060 5857 ns_walk_func(neigh_read_ns, NULL, NULL);
d62a17ae 5858 } else {
87d76d54 5859 /* Cleanup VTEPs for all EVPNs - uninstall from
d62a17ae 5860 * kernel and free entries.
5861 */
8b5fdf2e
PR
5862 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all,
5863 zvrf);
655b04d1 5864
ce5160c0
AK
5865 /* Delete all ESs in BGP */
5866 zebra_evpn_es_send_all_to_client(false /* add */);
5867
655b04d1 5868 /* cleanup all l3vnis */
89272910 5869 hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
150971b5 5870
0fb2ad05
T
5871 /* Mark as "no EVPN VRF" */
5872 zrouter.evpn_vrf = NULL;
d62a17ae 5873 }
13d60d35 5874
ec93aa12 5875stream_failure:
8068a649 5876 return;
13d60d35 5877}
5878
5879/*
87d76d54 5880 * Allocate EVPN hash table for this VRF and do other initialization.
13d60d35 5881 * NOTE: Currently supported only for default VRF.
5882 */
d62a17ae 5883void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 5884{
4a73887e
DS
5885 char buffer[80];
5886
d62a17ae 5887 if (!zvrf)
5888 return;
4a73887e
DS
5889
5890 snprintf(buffer, sizeof(buffer), "Zebra VRF EVPN Table: %s",
5891 zvrf->vrf->name);
5892 zvrf->evpn_table = hash_create_size(8, zebra_evpn_hash_keymake,
5893 zebra_evpn_hash_cmp, buffer);
5894
5895 snprintf(buffer, sizeof(buffer), "Zebra VxLAN SG Table: %s",
5896 zvrf->vrf->name);
5897 zvrf->vxlan_sg_table = hash_create_size(8, zebra_vxlan_sg_hash_key_make,
e2071325 5898 zebra_vxlan_sg_hash_eq, buffer);
13d60d35 5899}
5900
87d76d54 5901/* Cleanup EVPN info, but don't free the table. */
84915b0a 5902void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
5903{
ce5160c0
AK
5904 struct zebra_vrf *evpn_zvrf = zebra_vrf_get_evpn();
5905
84915b0a 5906 if (!zvrf)
5907 return;
8b5fdf2e 5908 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
0c16fb72 5909 zebra_vxlan_cleanup_sg_table(zvrf);
ce5160c0
AK
5910
5911 if (zvrf == evpn_zvrf)
5912 zebra_evpn_es_cleanup();
84915b0a 5913}
5914
87d76d54 5915/* Close all EVPN handling */
d62a17ae 5916void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 5917{
2853fed6 5918 if (!zvrf)
5919 return;
8b5fdf2e 5920 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
87d76d54 5921 hash_free(zvrf->evpn_table);
0c16fb72
AK
5922 if (zvrf->vxlan_sg_table) {
5923 zebra_vxlan_cleanup_sg_table(zvrf);
5924 hash_free(zvrf->vxlan_sg_table);
5925 zvrf->vxlan_sg_table = NULL;
5926 }
13d60d35 5927}
b7cfce93
MK
5928
5929/* init the l3vni table */
6548050a 5930void zebra_vxlan_init(void)
b7cfce93 5931{
89272910
DS
5932 zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
5933 "Zebra VRF L3 VNI table");
0fb2ad05 5934 zrouter.evpn_vrf = NULL;
ce5160c0 5935 zebra_evpn_mh_init();
b7cfce93
MK
5936}
5937
5938/* free l3vni table */
6548050a 5939void zebra_vxlan_disable(void)
b7cfce93 5940{
89272910 5941 hash_free(zrouter.l3vni_table);
ce5160c0 5942 zebra_evpn_mh_terminate();
b7cfce93 5943}
d3135ba3 5944
5945/* get the l3vni svi ifindex */
5946ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
5947{
05843a27 5948 struct zebra_l3vni *zl3vni = NULL;
d3135ba3 5949
5950 zl3vni = zl3vni_from_vrf(vrf_id);
5951 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
5952 return 0;
5953
5954 return zl3vni->svi_if->ifindex;
5955}
c80a972c 5956
015d264c 5957/************************** vxlan SG cache management ************************/
4ab3321f 5958/* Inform PIM about the mcast group */
ecbbc3a7
AK
5959static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
5960 struct prefix_sg *sg,
5961 char *sg_str, uint16_t cmd)
4ab3321f
AK
5962{
5963 struct zserv *client = NULL;
5964 struct stream *s = NULL;
5965
5966 client = zserv_find_client(ZEBRA_ROUTE_PIM, 0);
5967 if (!client)
5968 return 0;
5969
ecbbc3a7
AK
5970 if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG))
5971 return 0;
5972
4ab3321f
AK
5973 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
5974
5975 zclient_create_header(s, cmd, VRF_DEFAULT);
5976 stream_putl(s, IPV4_MAX_BYTELEN);
5977 stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
5978 stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);
5979
5980 /* Write packet size. */
5981 stream_putw_at(s, 0, stream_get_endp(s));
5982
5983 if (IS_ZEBRA_DEBUG_VXLAN)
5984 zlog_debug(
5985 "Send %s %s to %s",
5986 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", sg_str,
5987 zebra_route_string(client->proto));
5988
5989 if (cmd == ZEBRA_VXLAN_SG_ADD)
5990 client->vxlan_sg_add_cnt++;
5991 else
5992 client->vxlan_sg_del_cnt++;
5993
5994 return zserv_send_message(client, s);
5995}
5996
d8b87afe 5997static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
015d264c 5998{
847f168d 5999 const struct zebra_vxlan_sg *vxlan_sg = p;
015d264c
AK
6000
6001 return (jhash_2words(vxlan_sg->sg.src.s_addr,
6002 vxlan_sg->sg.grp.s_addr, 0));
6003}
6004
6005static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
6006{
847f168d
DS
6007 const struct zebra_vxlan_sg *sg1 = p1;
6008 const struct zebra_vxlan_sg *sg2 = p2;
015d264c
AK
6009
6010 return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
6011 && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
6012}
6013
847f168d
DS
6014static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
6015 struct prefix_sg *sg)
015d264c 6016{
847f168d 6017 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
6018
6019 vxlan_sg = XCALLOC(MTYPE_ZVXLAN_SG, sizeof(*vxlan_sg));
6020
6021 vxlan_sg->zvrf = zvrf;
6022 vxlan_sg->sg = *sg;
6023 prefix_sg2str(sg, vxlan_sg->sg_str);
6024
6025 vxlan_sg = hash_get(zvrf->vxlan_sg_table, vxlan_sg, hash_alloc_intern);
6026
6027 if (IS_ZEBRA_DEBUG_VXLAN)
6028 zlog_debug("vxlan SG %s created", vxlan_sg->sg_str);
6029
6030 return vxlan_sg;
6031}
6032
847f168d
DS
6033static struct zebra_vxlan_sg *zebra_vxlan_sg_find(struct zebra_vrf *zvrf,
6034 struct prefix_sg *sg)
015d264c 6035{
847f168d 6036 struct zebra_vxlan_sg lookup;
015d264c
AK
6037
6038 lookup.sg = *sg;
6039 return hash_lookup(zvrf->vxlan_sg_table, &lookup);
6040}
6041
847f168d
DS
6042static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
6043 struct prefix_sg *sg)
015d264c 6044{
847f168d
DS
6045 struct zebra_vxlan_sg *vxlan_sg;
6046 struct zebra_vxlan_sg *parent = NULL;
015d264c
AK
6047 struct in_addr sip;
6048
6049 vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
6050 if (vxlan_sg)
6051 return vxlan_sg;
6052
6053 /* create a *G entry for every BUM group implicitly -
6054 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
6055 * 2. the XG entry is used by pimd to setup the
6056 * vxlan-termination-mroute
6057 */
975a328e 6058 if (sg->src.s_addr != INADDR_ANY) {
015d264c
AK
6059 memset(&sip, 0, sizeof(sip));
6060 parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
6061 if (!parent)
6062 return NULL;
6063 }
6064
6065 vxlan_sg = zebra_vxlan_sg_new(zvrf, sg);
6066 if (!vxlan_sg) {
6067 if (parent)
6068 zebra_vxlan_sg_do_deref(zvrf, sip, sg->grp);
6069 return vxlan_sg;
6070 }
6071
ecbbc3a7
AK
6072 zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str,
6073 ZEBRA_VXLAN_SG_ADD);
4ab3321f 6074
015d264c
AK
6075 return vxlan_sg;
6076}
6077
847f168d 6078static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
015d264c
AK
6079{
6080 struct in_addr sip;
6081 struct zebra_vrf *zvrf;
6082
6083 zvrf = vrf_info_lookup(VRF_DEFAULT);
6084 if (!zvrf)
6085 return;
6086
6087 /* On SG entry deletion remove the reference to its parent XG
6088 * entry
6089 */
975a328e 6090 if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
015d264c
AK
6091 memset(&sip, 0, sizeof(sip));
6092 zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
6093 }
6094
ecbbc3a7
AK
6095 zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
6096 vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
4ab3321f 6097
015d264c
AK
6098 hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
6099
6100 if (IS_ZEBRA_DEBUG_VXLAN)
6101 zlog_debug("VXLAN SG %s deleted", vxlan_sg->sg_str);
6102
6103 XFREE(MTYPE_ZVXLAN_SG, vxlan_sg);
6104}
6105
6106static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
6107 struct in_addr sip, struct in_addr mcast_grp)
6108{
847f168d 6109 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
6110 struct prefix_sg sg;
6111
6112 sg.family = AF_INET;
6113 sg.prefixlen = IPV4_MAX_BYTELEN;
6114 sg.src = sip;
6115 sg.grp = mcast_grp;
6116 vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
6117 if (!vxlan_sg)
6118 return;
6119
6120 if (vxlan_sg->ref_cnt)
6121 --vxlan_sg->ref_cnt;
6122
6123 if (!vxlan_sg->ref_cnt)
6124 zebra_vxlan_sg_del(vxlan_sg);
6125}
6126
847f168d
DS
6127static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
6128 struct in_addr sip,
6129 struct in_addr mcast_grp)
015d264c 6130{
847f168d 6131 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
6132 struct prefix_sg sg;
6133
6134 sg.family = AF_INET;
6135 sg.prefixlen = IPV4_MAX_BYTELEN;
6136 sg.src = sip;
6137 sg.grp = mcast_grp;
6138 vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
6139 if (vxlan_sg)
6140 ++vxlan_sg->ref_cnt;
6141
6142 return vxlan_sg;
6143}
abfa0a96
AK
6144
6145static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
6146 struct in_addr mcast_grp)
6147{
6148 struct zebra_vrf *zvrf;
6149
975a328e
DA
6150 if (local_vtep_ip.s_addr == INADDR_ANY
6151 || mcast_grp.s_addr == INADDR_ANY)
abfa0a96
AK
6152 return;
6153
6154 zvrf = vrf_info_lookup(VRF_DEFAULT);
6155 if (!zvrf)
6156 return;
6157
6158 zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
6159}
6160
6161static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
6162 struct in_addr mcast_grp)
6163{
6164 struct zebra_vrf *zvrf;
6165
975a328e
DA
6166 if (local_vtep_ip.s_addr == INADDR_ANY
6167 || mcast_grp.s_addr == INADDR_ANY)
abfa0a96
AK
6168 return;
6169
6170 zvrf = vrf_info_lookup(VRF_DEFAULT);
6171 if (!zvrf)
6172 return;
6173 zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
6174}
6175
1ac88792 6176static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
0c16fb72 6177{
847f168d 6178 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
0c16fb72
AK
6179
6180 /* increment the ref count against (*,G) to prevent them from being
6181 * deleted
6182 */
6183 if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
6184 ++vxlan_sg->ref_cnt;
6185}
6186
1ac88792 6187static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
0c16fb72 6188{
847f168d 6189 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
0c16fb72
AK
6190
6191 /* decrement the dummy ref count against (*,G) to delete them */
6192 if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
6193 if (vxlan_sg->ref_cnt)
6194 --vxlan_sg->ref_cnt;
6195 if (!vxlan_sg->ref_cnt)
6196 zebra_vxlan_sg_del(vxlan_sg);
6197 }
6198}
6199
1ac88792 6200static void zebra_vxlan_sg_cleanup(struct hash_bucket *bucket, void *arg)
abfa0a96 6201{
847f168d 6202 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
abfa0a96
AK
6203
6204 zebra_vxlan_sg_del(vxlan_sg);
6205}
27627f9a 6206
0c16fb72
AK
6207static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf)
6208{
6209 /* increment the ref count against (*,G) to prevent them from being
6210 * deleted
6211 */
6212 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_pre_cleanup, NULL);
6213
6214 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL);
6215
6216 /* decrement the dummy ref count against the XG entries */
6217 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_post_cleanup, NULL);
6218}
6219
1ac88792 6220static void zebra_vxlan_sg_replay_send(struct hash_bucket *bucket, void *arg)
ecbbc3a7 6221{
847f168d 6222 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
ecbbc3a7
AK
6223
6224 zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg,
6225 vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD);
6226}
6227
6228/* Handle message from client to replay vxlan SG entries */
6229void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS)
6230{
6231 if (IS_ZEBRA_DEBUG_VXLAN)
6232 zlog_debug("VxLAN SG updates to PIM, start");
6233
6234 SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
6235
6236 if (!EVPN_ENABLED(zvrf)) {
8f86bb06
DS
6237 if (IS_ZEBRA_DEBUG_VXLAN)
6238 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
6239 zvrf->vrf->vrf_id);
ecbbc3a7
AK
6240 return;
6241 }
6242
6243 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL);
6244}
6245
27627f9a
KA
6246
6247/* Cleanup EVPN configuration of a specific VRF */
6248static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
6249{
05843a27 6250 struct zebra_l3vni *zl3vni = NULL;
b6587fc2 6251
27627f9a
KA
6252 zvrf->advertise_all_vni = 0;
6253 zvrf->advertise_gw_macip = 0;
6254 zvrf->advertise_svi_macip = 0;
6255 zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
6256
8b5fdf2e 6257 hash_iterate(zvrf->evpn_table, zebra_evpn_cfg_cleanup, NULL);
b6587fc2
CS
6258
6259 if (zvrf->l3vni)
6260 zl3vni = zl3vni_lookup(zvrf->l3vni);
6261 if (zl3vni) {
6262 /* delete and uninstall all rmacs */
6263 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
6264 zl3vni);
6265 /* delete and uninstall all next-hops */
6266 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
6267 zl3vni);
6268 }
27627f9a
KA
6269}
6270
6271/* Cleanup BGP EVPN configuration upon client disconnect */
ecbbc3a7 6272static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client)
27627f9a
KA
6273{
6274 struct vrf *vrf;
6275 struct zebra_vrf *zvrf;
6276
27627f9a
KA
6277 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
6278 zvrf = vrf->info;
6279 if (zvrf)
6280 zebra_evpn_vrf_cfg_cleanup(zvrf);
6281 }
6282
6283 return 0;
6284}
6285
ecbbc3a7
AK
6286static int zebra_evpn_pim_cfg_clean_up(struct zserv *client)
6287{
6288 struct zebra_vrf *zvrf = zebra_vrf_get_evpn();
6289
5e665031 6290 if (zvrf && CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) {
ecbbc3a7
AK
6291 if (IS_ZEBRA_DEBUG_VXLAN)
6292 zlog_debug("VxLAN SG updates to PIM, stop");
6293 UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
6294 }
6295
6296 return 0;
6297}
6298
6299static int zebra_evpn_cfg_clean_up(struct zserv *client)
6300{
6301 if (client->proto == ZEBRA_ROUTE_BGP)
6302 return zebra_evpn_bgp_cfg_clean_up(client);
6303
6304 if (client->proto == ZEBRA_ROUTE_PIM)
6305 return zebra_evpn_pim_cfg_clean_up(client);
6306
6307 return 0;
6308}
6309
036d93c0
MS
6310/*
6311 * Handle results for vxlan dataplane operations.
6312 */
6313extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
6314{
6315 /* TODO -- anything other than freeing the context? */
6316 dplane_ctx_fini(&ctx);
6317}
6318
27627f9a
KA
6319/* Cleanup BGP EVPN configuration upon client disconnect */
6320extern void zebra_evpn_init(void)
6321{
6322 hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
6323}