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