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