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