Coverage Report

Created: 2025-11-11 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/zebra/zebra_vxlan_if.c
Line
Count
Source
1
/*
2
 * Zebra EVPN for VxLAN interface handling
3
 *
4
 * Copyright (C) 2021 Cumulus Networks, Inc.
5
 * Vivek Venkatraman, Stephen Worley, Sharath Ramamurthy
6
 *
7
 * This file is part of FRR.
8
 *
9
 * FRR is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU General Public License as published by the
11
 * Free Software Foundation; either version 2, or (at your option) any
12
 * later version.
13
 *
14
 * FRR is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * General Public License for more details.
18
 */
19
20
#include <zebra.h>
21
22
#include "hash.h"
23
#include "if.h"
24
#include "jhash.h"
25
#include "linklist.h"
26
#include "log.h"
27
#include "memory.h"
28
#include "prefix.h"
29
#include "stream.h"
30
#include "table.h"
31
#include "vlan.h"
32
#include "vxlan.h"
33
#ifdef GNU_LINUX
34
#include <linux/neighbour.h>
35
#endif
36
37
#include "zebra/zebra_router.h"
38
#include "zebra/debug.h"
39
#include "zebra/interface.h"
40
#include "zebra/rib.h"
41
#include "zebra/rt.h"
42
#include "zebra/rt_netlink.h"
43
#include "zebra/zebra_errors.h"
44
#include "zebra/zebra_l2.h"
45
#include "zebra/zebra_ns.h"
46
#include "zebra/zebra_vrf.h"
47
#include "zebra/zebra_vxlan.h"
48
#include "zebra/zebra_vxlan_if.h"
49
#include "zebra/zebra_evpn.h"
50
#include "zebra/zebra_evpn_mac.h"
51
#include "zebra/zebra_evpn_neigh.h"
52
#include "zebra/zebra_vxlan_private.h"
53
#include "zebra/zebra_evpn_mh.h"
54
#include "zebra/zebra_evpn_vxlan.h"
55
#include "zebra/zebra_router.h"
56
57
static unsigned int zebra_vxlan_vni_hash_keymake(const void *p)
58
0
{
59
0
  const struct zebra_vxlan_vni *vni;
60
61
0
  vni = (const struct zebra_vxlan_vni *)p;
62
0
  return jhash_1word(vni->vni, 0);
63
0
}
64
65
static bool zebra_vxlan_vni_hash_cmp(const void *p1, const void *p2)
66
0
{
67
0
  const struct zebra_vxlan_vni *vni1;
68
0
  const struct zebra_vxlan_vni *vni2;
69
70
0
  vni1 = (const struct zebra_vxlan_vni *)p1;
71
0
  vni2 = (const struct zebra_vxlan_vni *)p2;
72
73
0
  return (vni1->vni == vni2->vni);
74
0
}
75
76
static int zebra_vxlan_if_vni_walk_callback(struct hash_bucket *bucket,
77
              void *ctxt)
78
0
{
79
0
  int ret;
80
0
  struct zebra_vxlan_vni *vni;
81
0
  struct zebra_vxlan_if_ctx *ctx;
82
83
0
  vni = (struct zebra_vxlan_vni *)bucket->data;
84
0
  ctx = (struct zebra_vxlan_if_ctx *)ctxt;
85
86
0
  ret = ctx->func(ctx->zif, vni, ctx->arg);
87
0
  return ret;
88
0
}
89
90
static void zebra_vxlan_if_vni_iterate_callback(struct hash_bucket *bucket,
91
            void *ctxt)
92
0
{
93
0
  struct zebra_vxlan_vni *vni;
94
0
  struct zebra_vxlan_if_ctx *ctx;
95
96
0
  vni = (struct zebra_vxlan_vni *)bucket->data;
97
0
  ctx = (struct zebra_vxlan_if_ctx *)ctxt;
98
99
0
  ctx->func(ctx->zif, vni, ctx->arg);
100
0
}
101
102
static int zebra_vxlan_if_del_vni(struct interface *ifp,
103
          struct zebra_vxlan_vni *vnip)
104
0
{
105
0
  vni_t vni;
106
0
  struct zebra_if *zif;
107
0
  struct zebra_evpn *zevpn;
108
0
  struct zebra_l3vni *zl3vni;
109
0
  struct interface *br_if;
110
111
  /* Check if EVPN is enabled. */
112
0
  if (!is_evpn_enabled())
113
0
    return 0;
114
115
0
  zif = ifp->info;
116
0
  assert(zif);
117
0
  vni = vnip->vni;
118
119
0
  zl3vni = zl3vni_lookup(vni);
120
0
  if (zl3vni) {
121
122
0
    if (IS_ZEBRA_DEBUG_VXLAN)
123
0
      zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
124
0
           ifp->ifindex);
125
126
    /* process oper-down for l3-vni */
127
0
    zebra_vxlan_process_l3vni_oper_down(zl3vni);
128
129
    /* remove the association with vxlan_if */
130
0
    memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
131
0
    zl3vni->vxlan_if = NULL;
132
0
    zl3vni->vid = 0;
133
0
    br_if = zif->brslave_info.br_if;
134
0
    zl3vni_bridge_if_set(zl3vni, br_if, false /* unset */);
135
0
  } else {
136
137
    /* process if-del for l2-vni*/
138
0
    if (IS_ZEBRA_DEBUG_VXLAN)
139
0
      zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
140
0
           ifp->ifindex);
141
142
    /* Locate hash entry; it is expected to exist. */
143
0
    zevpn = zebra_evpn_lookup(vni);
144
0
    if (!zevpn) {
145
0
      zlog_debug(
146
0
        "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
147
0
        ifp->name, ifp->ifindex, vni);
148
0
      return 0;
149
0
    }
150
151
    /* remove from l3-vni list */
152
0
    zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
153
0
    if (zl3vni)
154
0
      listnode_delete(zl3vni->l2vnis, zevpn);
155
    /* Delete VNI from BGP. */
156
0
    zebra_evpn_send_del_to_client(zevpn);
157
158
    /* Free up all neighbors and MAC, if any. */
159
0
    zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
160
0
    zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
161
162
    /* Free up all remote VTEPs, if any. */
163
0
    zebra_evpn_vtep_del_all(zevpn, 1);
164
165
    /* Delete the hash entry. */
166
0
    if (zebra_evpn_vxlan_del(zevpn)) {
167
0
      flog_err(EC_ZEBRA_VNI_DEL_FAILED,
168
0
         "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
169
0
         zevpn, ifp->name, ifp->ifindex, zevpn->vni);
170
0
      return -1;
171
0
    }
172
0
  }
173
0
  return 0;
174
0
}
175
176
static int zebra_vxlan_if_update_vni(struct interface *ifp,
177
             struct zebra_vxlan_vni *vnip,
178
             struct zebra_vxlan_if_update_ctx *ctx)
179
0
{
180
0
  vni_t vni;
181
0
  uint16_t chgflags;
182
0
  vlanid_t access_vlan;
183
0
  struct zebra_if *zif;
184
0
  struct zebra_l2info_vxlan *vxl;
185
0
  struct zebra_evpn *zevpn;
186
0
  struct zebra_l3vni *zl3vni;
187
0
  struct interface *vlan_if;
188
0
  struct interface *br_if;
189
190
  /* Check if EVPN is enabled. */
191
0
  if (!is_evpn_enabled())
192
0
    return 0;
193
194
0
  zif = ifp->info;
195
0
  assert(zif);
196
0
  vxl = &zif->l2info.vxl;
197
0
  vni = vnip->vni;
198
0
  chgflags = ctx->chgflags;
199
200
0
  zl3vni = zl3vni_lookup(vni);
201
0
  if (zl3vni) {
202
203
0
    if (IS_ZEBRA_DEBUG_VXLAN)
204
0
      zlog_debug(
205
0
        "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
206
0
        vni, ifp->name, ifp->ifindex, vnip->access_vlan,
207
0
        &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
208
0
        chgflags);
209
210
    /* Removed from bridge? Cleanup and return */
211
0
    if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) &&
212
0
        (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
213
0
      zebra_vxlan_process_l3vni_oper_down(zl3vni);
214
0
      return 0;
215
0
    }
216
217
0
    if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE) &&
218
0
        if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
219
0
      zebra_vxlan_process_l3vni_oper_down(zl3vni);
220
0
      zebra_vxlan_process_l3vni_oper_up(zl3vni);
221
0
      return 0;
222
0
    }
223
224
    /* access-vlan change - process oper down, associate with new
225
     * svi_if and then process oper up again
226
     */
227
0
    if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
228
0
      if (if_is_operative(ifp)) {
229
0
        zebra_vxlan_process_l3vni_oper_down(zl3vni);
230
0
        zl3vni->svi_if = NULL;
231
0
        zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
232
0
        zl3vni->mac_vlan_if =
233
0
          zl3vni_map_to_mac_vlan_if(zl3vni);
234
0
        zl3vni->local_vtep_ip = vxl->vtep_ip;
235
0
        if (is_l3vni_oper_up(zl3vni))
236
0
          zebra_vxlan_process_l3vni_oper_up(
237
0
            zl3vni);
238
0
      }
239
0
    }
240
241
    /*
242
     * local-ip change - process oper down, associate with new
243
     * local-ip and then process oper up again
244
     */
245
0
    if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
246
0
      if (if_is_operative(ifp)) {
247
0
        zebra_vxlan_process_l3vni_oper_down(zl3vni);
248
0
        zl3vni->local_vtep_ip = vxl->vtep_ip;
249
0
        if (is_l3vni_oper_up(zl3vni))
250
0
          zebra_vxlan_process_l3vni_oper_up(
251
0
            zl3vni);
252
0
      }
253
0
    }
254
255
    /* Update local tunnel IP. */
256
0
    zl3vni->local_vtep_ip = vxl->vtep_ip;
257
258
0
    zl3vni->vid = (zl3vni->vid != vnip->access_vlan)
259
0
              ? vnip->access_vlan
260
0
              : zl3vni->vid;
261
0
    br_if = zif->brslave_info.br_if;
262
0
    zl3vni_bridge_if_set(zl3vni, br_if, true /* set */);
263
264
    /* if we have a valid new master, process l3-vni oper up */
265
0
    if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
266
0
      if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
267
0
        zebra_vxlan_process_l3vni_oper_up(zl3vni);
268
0
    }
269
0
  } else {
270
271
    /* Update VNI hash. */
272
0
    zevpn = zebra_evpn_lookup(vni);
273
0
    if (!zevpn) {
274
0
      zlog_debug(
275
0
        "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
276
0
        ifp->name, ifp->ifindex, vni);
277
0
      return -1;
278
0
    }
279
280
0
    if (IS_ZEBRA_DEBUG_VXLAN)
281
0
      zlog_debug(
282
0
        "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
283
0
        vni, ifp->name, ifp->ifindex, vnip->access_vlan,
284
0
        &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
285
0
        chgflags);
286
287
    /* Removed from bridge? Cleanup and return */
288
0
    if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) &&
289
0
        (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
290
      /* Delete from client, remove all remote VTEPs */
291
      /* Also, free up all MACs and neighbors. */
292
0
      zevpn->svi_if = NULL;
293
0
      zebra_evpn_send_del_to_client(zevpn);
294
0
      zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
295
0
      zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
296
0
      zebra_evpn_vtep_del_all(zevpn, 1);
297
0
      return 0;
298
0
    }
299
300
    /* Handle other changes. */
301
0
    if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
302
      /* Remove all existing local neigh and MACs for this VNI
303
       * (including from BGP)
304
       */
305
0
      access_vlan = vnip->access_vlan;
306
0
      vnip->access_vlan = ctx->old_vni.access_vlan;
307
0
      zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
308
0
      zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
309
0
      zebra_evpn_rem_mac_uninstall_all(zevpn);
310
0
      vnip->access_vlan = access_vlan;
311
0
    }
312
313
0
    if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
314
0
        zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
315
0
      zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
316
0
               zevpn->mcast_grp);
317
0
      zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
318
0
      zevpn->local_vtep_ip = vxl->vtep_ip;
319
0
      zevpn->mcast_grp = vnip->mcast_grp;
320
      /* on local vtep-ip check if ES orig-ip
321
       * needs to be updated
322
       */
323
0
      zebra_evpn_es_set_base_evpn(zevpn);
324
0
    }
325
0
    zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
326
0
    zevpn->vid = (zevpn->vid != vnip->access_vlan)
327
0
             ? vnip->access_vlan
328
0
             : zevpn->vid;
329
0
    br_if = zif->brslave_info.br_if;
330
0
    zevpn_bridge_if_set(zevpn, br_if, true /* set */);
331
332
0
    vlan_if = zvni_map_to_svi(vnip->access_vlan, br_if);
333
0
    if (vlan_if)
334
0
      zevpn->svi_if = vlan_if;
335
336
    /* Take further actions needed.
337
     * Note that if we are here, there is a change of interest.
338
     */
339
    /* If down or not mapped to a bridge, we're done. */
340
0
    if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
341
0
      return 0;
342
343
    /* Inform BGP, if there is a change of interest. */
344
0
    if (chgflags &
345
0
        (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE |
346
0
         ZEBRA_VXLIF_MCAST_GRP_CHANGE | ZEBRA_VXLIF_VLAN_CHANGE))
347
0
      zebra_evpn_send_add_to_client(zevpn);
348
349
    /* If there is a valid new master or a VLAN mapping change,
350
     * read and populate local MACs and neighbors.
351
     * Also, reinstall any remote MACs and neighbors
352
     * for this VNI (based on new VLAN).
353
     */
354
0
    if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
355
0
      zebra_evpn_read_mac_neigh(zevpn, ifp);
356
0
    else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
357
0
      struct neigh_walk_ctx n_wctx;
358
359
0
      zebra_evpn_read_mac_neigh(zevpn, ifp);
360
361
0
      zebra_evpn_rem_mac_install_all(zevpn);
362
363
0
      memset(&n_wctx, 0, sizeof(n_wctx));
364
0
      n_wctx.zevpn = zevpn;
365
0
      hash_iterate(zevpn->neigh_table,
366
0
             zebra_evpn_install_neigh_hash, &n_wctx);
367
0
    }
368
0
  }
369
370
0
  return 0;
371
0
}
372
373
static int zebra_vxlan_if_add_vni(struct interface *ifp,
374
          struct zebra_vxlan_vni *vnip)
375
0
{
376
0
  vni_t vni;
377
0
  struct zebra_if *zif;
378
0
  struct zebra_l2info_vxlan *vxl;
379
0
  struct zebra_evpn *zevpn;
380
0
  struct zebra_l3vni *zl3vni;
381
0
  struct interface *br_if;
382
383
  /* Check if EVPN is enabled. */
384
0
  if (!is_evpn_enabled())
385
0
    return 0;
386
387
0
  zif = ifp->info;
388
0
  assert(zif);
389
0
  vxl = &zif->l2info.vxl;
390
0
  vni = vnip->vni;
391
392
0
  zl3vni = zl3vni_lookup(vni);
393
0
  if (zl3vni) {
394
395
    /* process if-add for l3-vni*/
396
0
    if (IS_ZEBRA_DEBUG_VXLAN)
397
0
      zlog_debug(
398
0
        "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
399
0
        vni, ifp->name, ifp->ifindex, vnip->access_vlan,
400
0
        &vxl->vtep_ip,
401
0
        zif->brslave_info.bridge_ifindex);
402
403
    /* associate with vxlan_if */
404
0
    zl3vni->local_vtep_ip = vxl->vtep_ip;
405
0
    zl3vni->vxlan_if = ifp;
406
407
    /*
408
     * Associate with SVI, if any. We can associate with svi-if only
409
     * after association with vxlan_if is complete
410
     */
411
0
    zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
412
413
0
    zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
414
415
0
    zl3vni->vid = vnip->access_vlan;
416
0
    br_if = zif->brslave_info.br_if;
417
0
    zl3vni_bridge_if_set(zl3vni, br_if, true /* set */);
418
419
0
    if (is_l3vni_oper_up(zl3vni))
420
0
      zebra_vxlan_process_l3vni_oper_up(zl3vni);
421
0
  } else {
422
423
    /* process if-add for l2-vni */
424
0
    struct interface *vlan_if = NULL;
425
426
    /* Create or update EVPN hash. */
427
0
    zevpn = zebra_evpn_lookup(vni);
428
0
    if (!zevpn)
429
0
      zevpn = zebra_evpn_add(vni);
430
431
0
    if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
432
0
        zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
433
0
      zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
434
0
               zevpn->mcast_grp);
435
0
      zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
436
0
      zevpn->local_vtep_ip = vxl->vtep_ip;
437
0
      zevpn->mcast_grp = vnip->mcast_grp;
438
      /* on local vtep-ip check if ES orig-ip
439
       * needs to be updated
440
       */
441
0
      zebra_evpn_es_set_base_evpn(zevpn);
442
0
    }
443
0
    zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
444
0
    br_if = zif->brslave_info.br_if;
445
0
    zevpn_bridge_if_set(zevpn, br_if, true /* set */);
446
0
    vlan_if = zvni_map_to_svi(vnip->access_vlan, br_if);
447
0
    if (vlan_if) {
448
0
      zevpn->vid = vnip->access_vlan;
449
0
      zevpn->svi_if = vlan_if;
450
0
      zevpn->vrf_id = vlan_if->vrf->vrf_id;
451
0
      zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
452
0
      if (zl3vni)
453
0
        listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
454
0
    }
455
456
0
    if (IS_ZEBRA_DEBUG_VXLAN)
457
0
      zlog_debug(
458
0
        "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
459
0
        vni,
460
0
        vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
461
0
        ifp->name, ifp->ifindex, vnip->access_vlan,
462
0
        &vxl->vtep_ip, &vnip->mcast_grp,
463
0
        zif->brslave_info.bridge_ifindex);
464
465
    /* If down or not mapped to a bridge, we're done. */
466
0
    if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
467
0
      return 0;
468
469
    /* Inform BGP */
470
0
    zebra_evpn_send_add_to_client(zevpn);
471
472
    /* Read and populate local MACs and neighbors */
473
0
    zebra_evpn_read_mac_neigh(zevpn, ifp);
474
0
  }
475
476
0
  return 0;
477
0
}
478
479
static void zebra_vxlan_if_vni_entry_del(struct zebra_if *zif,
480
           struct zebra_vxlan_vni *vni)
481
0
{
482
0
  if (vni) {
483
0
    zebra_evpn_vl_vxl_deref(vni->access_vlan, vni->vni, zif);
484
0
    zebra_vxlan_if_del_vni(zif->ifp, vni);
485
0
  }
486
0
}
487
488
static int zebra_vxlan_if_vni_entry_add(struct zebra_if *zif,
489
          struct zebra_vxlan_vni *vni)
490
0
{
491
0
  zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
492
0
  return zebra_vxlan_if_add_vni(zif->ifp, vni);
493
0
}
494
495
static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
496
           struct zebra_vxlan_vni *vni,
497
           void *ctxt)
498
0
{
499
0
  struct zebra_vxlan_vni vni_tmp;
500
0
  struct zebra_vxlan_if_update_ctx *ctx;
501
0
  struct zebra_vxlan_vni *old_vni = NULL;
502
503
0
  ctx = (struct zebra_vxlan_if_update_ctx *)ctxt;
504
0
  memcpy(&vni_tmp, vni, sizeof(*vni));
505
506
0
  if ((hashcount(ctx->old_vni_table) == 0) ||
507
0
      !(old_vni = hash_release(ctx->old_vni_table, &vni_tmp))) {
508
0
    if (IS_ZEBRA_DEBUG_VXLAN)
509
0
      zlog_debug("vxlan %s adding vni(%d, %d)",
510
0
           zif->ifp->name, vni->vni, vni->access_vlan);
511
512
0
    zebra_vxlan_if_vni_entry_add(zif, &vni_tmp);
513
0
    return 0;
514
0
  }
515
516
0
  ctx->old_vni = *old_vni;
517
0
  ctx->chgflags = ZEBRA_VXLIF_VLAN_CHANGE;
518
519
  /* copy mcast group from old_vni as thats not being changed here */
520
0
  vni->mcast_grp = old_vni->mcast_grp;
521
522
0
  if (old_vni->access_vlan != vni->access_vlan) {
523
0
    if (IS_ZEBRA_DEBUG_VXLAN)
524
0
      zlog_debug(
525
0
        "vxlan %s updating vni(%d, %d) -> vni(%d, %d)",
526
0
        zif->ifp->name, old_vni->vni,
527
0
        old_vni->access_vlan, vni->vni,
528
0
        vni->access_vlan);
529
530
0
    zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni,
531
0
          zif);
532
0
    zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
533
0
    zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
534
0
    zebra_vxlan_vni_free(old_vni);
535
0
  }
536
537
0
  return 0;
538
0
}
539
540
static int zebra_vxlan_if_vni_entry_update_callback(struct zebra_if *zif,
541
                struct zebra_vxlan_vni *vni,
542
                void *ctxt)
543
0
{
544
0
  struct zebra_vxlan_if_update_ctx *ctx;
545
546
0
  ctx = (struct zebra_vxlan_if_update_ctx *)ctxt;
547
0
  return zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
548
0
}
549
550
static int zebra_vxlan_if_vni_entry_del_callback(struct zebra_if *zif,
551
             struct zebra_vxlan_vni *vni,
552
             void *ctxt)
553
0
{
554
0
  zebra_vxlan_if_vni_entry_del(zif, vni);
555
0
  return 0;
556
0
}
557
558
static int zebra_vxlan_if_vni_entry_down_callback(struct zebra_if *zif,
559
              struct zebra_vxlan_vni *vni,
560
              void *ctxt)
561
0
{
562
0
  return zebra_vxlan_if_vni_down(zif->ifp, vni);
563
0
}
564
565
static int zebra_vxlan_if_vni_entry_up_callback(struct zebra_if *zif,
566
            struct zebra_vxlan_vni *vni,
567
            void *ctxt)
568
0
{
569
0
  return zebra_vxlan_if_vni_up(zif->ifp, vni);
570
0
}
571
572
static void zebra_vxlan_if_vni_clean(struct hash_bucket *bucket, void *arg)
573
0
{
574
0
  struct zebra_if *zif;
575
0
  struct zebra_vxlan_vni *vni;
576
577
0
  zif = (struct zebra_if *)arg;
578
0
  vni = (struct zebra_vxlan_vni *)bucket->data;
579
0
  zebra_vxlan_if_vni_entry_del(zif, vni);
580
0
}
581
582
void zebra_vxlan_vni_free(void *arg)
583
0
{
584
0
  struct zebra_vxlan_vni *vni;
585
586
0
  vni = (struct zebra_vxlan_vni *)arg;
587
588
0
  XFREE(MTYPE_TMP, vni);
589
0
}
590
591
void *zebra_vxlan_vni_alloc(void *p)
592
0
{
593
0
  struct zebra_vxlan_vni *vni;
594
0
  const struct zebra_vxlan_vni *vnip;
595
596
0
  vnip = (const struct zebra_vxlan_vni *)p;
597
0
  vni = XCALLOC(MTYPE_TMP, sizeof(*vni));
598
0
  vni->vni = vnip->vni;
599
0
  vni->access_vlan = vnip->access_vlan;
600
0
  vni->mcast_grp = vnip->mcast_grp;
601
602
0
  return (void *)vni;
603
0
}
604
605
struct hash *zebra_vxlan_vni_table_create(void)
606
0
{
607
0
  return hash_create(zebra_vxlan_vni_hash_keymake,
608
0
         zebra_vxlan_vni_hash_cmp, "Zebra Vxlan VNI Table");
609
0
}
610
611
void zebra_vxlan_vni_table_destroy(struct hash *vni_table)
612
0
{
613
0
  hash_clean_and_free(&vni_table, zebra_vxlan_vni_free);
614
0
}
615
616
int zebra_vxlan_if_vni_table_destroy(struct zebra_if *zif)
617
0
{
618
0
  struct zebra_vxlan_vni_info *vni_info;
619
620
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
621
0
  if (vni_info->vni_table) {
622
0
    zebra_vxlan_if_vni_iterate(
623
0
      zif, zebra_vxlan_if_vni_entry_del_callback, NULL);
624
0
    zebra_vxlan_vni_table_destroy(vni_info->vni_table);
625
0
    vni_info->vni_table = NULL;
626
0
  }
627
0
  return 0;
628
0
}
629
630
int zebra_vxlan_if_vni_table_create(struct zebra_if *zif)
631
0
{
632
0
  struct zebra_vxlan_vni_info *vni_info;
633
634
0
  if (!IS_ZEBRA_VXLAN_IF_SVD(zif))
635
0
    return 0;
636
637
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
638
0
  vni_info->vni_table = zebra_vxlan_vni_table_create();
639
0
  if (!vni_info->vni_table)
640
0
    return -ENOMEM;
641
642
0
  return 0;
643
0
}
644
645
struct zebra_vxlan_vni *zebra_vxlan_if_vni_find(const struct zebra_if *zif,
646
            vni_t vni)
647
0
{
648
0
  struct zebra_vxlan_vni *vnip = NULL;
649
0
  const struct zebra_vxlan_vni_info *vni_info;
650
0
  struct zebra_vxlan_vni vni_tmp;
651
652
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
653
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
654
0
    vnip = (struct zebra_vxlan_vni *)&vni_info->vni;
655
0
    assert(vnip);
656
0
    if (vni && (vnip->vni != vni))
657
0
      vnip = NULL;
658
659
0
    return vnip;
660
0
  }
661
662
  /* For SVD, the VNI value is a required parameter. */
663
0
  assert(vni);
664
665
0
  memset(&vni_tmp, 0, sizeof(vni_tmp));
666
0
  vni_tmp.vni = vni;
667
0
  vnip = (struct zebra_vxlan_vni *)hash_lookup(vni_info->vni_table,
668
0
                 (void *)&vni_tmp);
669
670
  /* TODO: For debugging. Remove later */
671
0
  if (vnip)
672
0
    assert(vnip->vni == vni);
673
674
0
  return vnip;
675
0
}
676
677
static int zif_vlanid_vni_walker(struct zebra_if *zif,
678
         struct zebra_vxlan_vni *vnip, void *arg)
679
0
{
680
0
  struct zebra_vxlan_if_vlan_ctx *ctx;
681
682
0
  ctx = (struct zebra_vxlan_if_vlan_ctx *)arg;
683
684
0
  if (vnip->access_vlan == ctx->vid) {
685
0
    ctx->vni = vnip;
686
0
    return HASHWALK_ABORT;
687
0
  }
688
689
0
  return HASHWALK_CONTINUE;
690
0
}
691
692
struct zebra_vxlan_vni *zebra_vxlan_if_vlanid_vni_find(struct zebra_if *zif,
693
                   vlanid_t vid)
694
0
{
695
0
  struct zebra_vxlan_if_vlan_ctx ctx = {};
696
697
0
  if (!IS_ZEBRA_VXLAN_IF_SVD(zif))
698
0
    return NULL;
699
700
0
  ctx.vid = vid;
701
702
0
  zebra_vxlan_if_vni_walk(zif, zif_vlanid_vni_walker, &ctx);
703
704
0
  return ctx.vni;
705
0
}
706
707
void zebra_vxlan_if_vni_iterate(struct zebra_if *zif,
708
        int (*func)(struct zebra_if *zif,
709
              struct zebra_vxlan_vni *, void *),
710
        void *arg)
711
0
{
712
0
  struct zebra_vxlan_vni_info *vni_info;
713
0
  struct zebra_vxlan_vni *vni = NULL;
714
0
  struct zebra_vxlan_if_ctx ctx;
715
716
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
717
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
718
0
    vni = zebra_vxlan_if_vni_find(zif, 0);
719
0
    func(zif, vni, arg);
720
0
    return;
721
0
  }
722
723
0
  memset(&ctx, 0, sizeof(ctx));
724
0
  ctx.zif = zif;
725
0
  ctx.func = func;
726
0
  ctx.arg = arg;
727
0
  hash_iterate(vni_info->vni_table, zebra_vxlan_if_vni_iterate_callback,
728
0
         &ctx);
729
0
}
730
731
void zebra_vxlan_if_vni_walk(struct zebra_if *zif,
732
           int (*func)(struct zebra_if *zif,
733
           struct zebra_vxlan_vni *, void *),
734
           void *arg)
735
0
{
736
0
  struct zebra_vxlan_vni_info *vni_info;
737
0
  struct zebra_vxlan_vni *vni = NULL;
738
0
  struct zebra_vxlan_if_ctx ctx;
739
740
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
741
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
742
0
    vni = zebra_vxlan_if_vni_find(zif, 0);
743
0
    func(zif, vni, arg);
744
0
    return;
745
0
  }
746
747
0
  memset(&ctx, 0, sizeof(ctx));
748
0
  ctx.zif = zif;
749
0
  ctx.func = func;
750
0
  ctx.arg = arg;
751
0
  hash_walk(vni_info->vni_table, zebra_vxlan_if_vni_walk_callback, &ctx);
752
0
}
753
754
vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif,
755
            struct interface *br_if)
756
0
{
757
0
  struct zebra_vxlan_vni *vni = NULL;
758
759
  /* Expected to be called only for vlan-unware bridges. In this case,
760
   * we only support a per-VNI VXLAN interface model.
761
   */
762
0
  if (!IS_ZEBRA_VXLAN_IF_VNI(zif))
763
0
    return 0;
764
765
0
  vni = zebra_vxlan_if_vni_find(zif, 0);
766
0
  assert(vni);
767
768
0
  return vni->vni;
769
0
}
770
771
int zebra_vxlan_if_vni_table_add_update(struct interface *ifp,
772
          struct hash *vni_table)
773
0
{
774
0
  struct zebra_if *zif;
775
0
  struct zebra_vxlan_vni_info *vni_info;
776
0
  struct zebra_vxlan_if_update_ctx ctx;
777
778
0
  zif = (struct zebra_if *)ifp->info;
779
780
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
781
782
0
  memset(&ctx, 0, sizeof(ctx));
783
0
  ctx.old_vni_table = vni_info->vni_table;
784
0
  vni_info->vni_table = vni_table;
785
786
0
  zebra_vxlan_if_vni_iterate(zif, zebra_vxlan_if_add_update_vni, &ctx);
787
788
  /* release kernel deleted vnis */
789
0
  if (ctx.old_vni_table) {
790
0
    if (hashcount(ctx.old_vni_table)) {
791
      /* UGLY HACK: Put back the old table so that delete of
792
       * MACs goes through and then flip back.
793
       */
794
0
      vni_info->vni_table = ctx.old_vni_table;
795
0
      hash_iterate(ctx.old_vni_table,
796
0
             zebra_vxlan_if_vni_clean, zif);
797
0
      vni_info->vni_table = vni_table;
798
0
    }
799
0
    zebra_vxlan_vni_table_destroy(ctx.old_vni_table);
800
0
    ctx.old_vni_table = NULL;
801
0
  }
802
803
0
  return 0;
804
0
}
805
806
int zebra_vxlan_if_vni_mcast_group_add_update(struct interface *ifp,
807
                vni_t vni_id,
808
                struct in_addr *mcast_group)
809
0
{
810
0
  struct zebra_if *zif;
811
0
  struct zebra_vxlan_vni *vni;
812
0
  struct zebra_vxlan_if_update_ctx ctx;
813
814
0
  zif = (struct zebra_if *)ifp->info;
815
816
0
  if (!IS_ZEBRA_VXLAN_IF_SVD(zif))
817
0
    return 0;
818
819
0
  vni = zebra_vxlan_if_vni_find(zif, vni_id);
820
0
  if (!vni)
821
0
    return 0;
822
823
0
  memset(&ctx, 0, sizeof(ctx));
824
0
  ctx.old_vni.mcast_grp = vni->mcast_grp;
825
0
  ctx.chgflags = ZEBRA_VXLIF_MCAST_GRP_CHANGE;
826
827
0
  vni->mcast_grp = *mcast_group;
828
829
0
  return zebra_vxlan_if_update_vni(ifp, vni, &ctx);
830
0
}
831
832
int zebra_vxlan_if_vni_mcast_group_del(struct interface *ifp, vni_t vni_id,
833
               struct in_addr *mcast_group)
834
0
{
835
0
  struct zebra_if *zif = NULL;
836
0
  struct zebra_vxlan_vni *vni;
837
0
  struct zebra_vxlan_if_update_ctx ctx;
838
839
0
  zif = (struct zebra_if *)ifp->info;
840
841
0
  if (!IS_ZEBRA_VXLAN_IF_SVD(zif))
842
0
    return 0;
843
844
0
  vni = zebra_vxlan_if_vni_find(zif, vni_id);
845
0
  if (!vni)
846
0
    return 0;
847
848
0
  if (memcmp(mcast_group, &vni->mcast_grp, sizeof(*mcast_group)))
849
0
    return 0;
850
851
0
  memset(&ctx, 0, sizeof(ctx));
852
0
  ctx.old_vni.mcast_grp = vni->mcast_grp;
853
0
  ctx.chgflags = ZEBRA_VXLIF_MCAST_GRP_CHANGE;
854
855
0
  memset(&vni->mcast_grp, 0, sizeof(vni->mcast_grp));
856
857
0
  return zebra_vxlan_if_update_vni(ifp, vni, &ctx);
858
0
}
859
860
int zebra_vxlan_if_vni_down(struct interface *ifp, struct zebra_vxlan_vni *vnip)
861
0
{
862
0
  vni_t vni;
863
0
  struct zebra_if *zif;
864
0
  struct zebra_l3vni *zl3vni;
865
0
  struct zebra_evpn *zevpn;
866
867
  /* Check if EVPN is enabled. */
868
0
  if (!is_evpn_enabled())
869
0
    return 0;
870
871
0
  zif = ifp->info;
872
0
  assert(zif);
873
0
  vni = vnip->vni;
874
875
0
  zl3vni = zl3vni_lookup(vni);
876
0
  if (zl3vni) {
877
    /* process-if-down for l3-vni */
878
0
    if (IS_ZEBRA_DEBUG_VXLAN)
879
0
      zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
880
0
           ifp->ifindex, vni);
881
882
0
    zebra_vxlan_process_l3vni_oper_down(zl3vni);
883
0
  } else {
884
    /* process if-down for l2-vni */
885
0
    if (IS_ZEBRA_DEBUG_VXLAN)
886
0
      zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
887
0
           ifp->ifindex, vni);
888
889
    /* Locate hash entry; it is expected to exist. */
890
0
    zevpn = zebra_evpn_lookup(vni);
891
0
    if (!zevpn) {
892
0
      zlog_debug(
893
0
        "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
894
0
        ifp->name, ifp->ifindex, vni);
895
0
      return -1;
896
0
    }
897
898
0
    assert(zevpn->vxlan_if == ifp);
899
900
    /* remove from l3-vni list */
901
0
    zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
902
0
    if (zl3vni)
903
0
      listnode_delete(zl3vni->l2vnis, zevpn);
904
905
0
    zebra_evpn_vl_vxl_deref(vnip->access_vlan, vnip->vni, zif);
906
907
    /* Delete this VNI from BGP. */
908
0
    zebra_evpn_send_del_to_client(zevpn);
909
910
    /* Free up all neighbors and MACs, if any. */
911
0
    zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
912
0
    zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
913
914
    /* Free up all remote VTEPs, if any. */
915
0
    zebra_evpn_vtep_del_all(zevpn, 1);
916
0
  }
917
0
  return 0;
918
0
}
919
920
/*
921
 * Handle VxLAN interface down
922
 */
923
int zebra_vxlan_if_down(struct interface *ifp)
924
0
{
925
0
  struct zebra_if *zif;
926
0
  struct zebra_vxlan_vni_info *vni_info;
927
928
  /* Check if EVPN is enabled. */
929
0
  if (!is_evpn_enabled())
930
0
    return 0;
931
932
0
  zif = ifp->info;
933
0
  assert(zif);
934
935
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
936
0
    vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
937
0
    return zebra_vxlan_if_vni_down(ifp, &vni_info->vni);
938
0
  }
939
940
0
  zebra_vxlan_if_vni_iterate(zif, zebra_vxlan_if_vni_entry_down_callback,
941
0
           NULL);
942
943
0
  return 0;
944
0
}
945
946
int zebra_vxlan_if_vni_up(struct interface *ifp, struct zebra_vxlan_vni *vnip)
947
0
{
948
0
  vni_t vni;
949
0
  struct zebra_if *zif;
950
0
  struct zebra_evpn *zevpn;
951
0
  struct zebra_l3vni *zl3vni;
952
953
  /* Check if EVPN is enabled. */
954
0
  if (!is_evpn_enabled())
955
0
    return 0;
956
957
0
  zif = ifp->info;
958
0
  assert(zif);
959
0
  vni = vnip->vni;
960
961
0
  zl3vni = zl3vni_lookup(vni);
962
0
  if (zl3vni) {
963
    /* we need to associate with SVI, if any, we can associate with
964
     * svi-if only after association with vxlan-intf is complete
965
     */
966
0
    zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
967
0
    zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
968
969
0
    if (IS_ZEBRA_DEBUG_VXLAN)
970
0
      zlog_debug(
971
0
        "Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s",
972
0
        ifp->name, ifp->ifindex, vni,
973
0
        zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
974
0
        zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
975
0
                : "NIL");
976
977
0
    if (is_l3vni_oper_up(zl3vni))
978
0
      zebra_vxlan_process_l3vni_oper_up(zl3vni);
979
0
  } else {
980
    /* Handle L2-VNI add */
981
0
    struct interface *vlan_if = NULL;
982
983
0
    if (IS_ZEBRA_DEBUG_VXLAN)
984
0
      zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
985
0
           ifp->ifindex, vni);
986
987
    /* Locate hash entry; it is expected to exist. */
988
0
    zevpn = zebra_evpn_lookup(vni);
989
0
    if (!zevpn) {
990
0
      zlog_debug(
991
0
        "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
992
0
        ifp->name, ifp->ifindex, vni);
993
0
      return -1;
994
0
    }
995
996
0
    assert(zevpn->vxlan_if == ifp);
997
0
    zebra_evpn_vl_vxl_ref(vnip->access_vlan, vnip->vni, zif);
998
0
    vlan_if = zvni_map_to_svi(vnip->access_vlan,
999
0
            zif->brslave_info.br_if);
1000
0
    if (vlan_if) {
1001
0
      zevpn->svi_if = vlan_if;
1002
0
      zevpn->vrf_id = vlan_if->vrf->vrf_id;
1003
0
      zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
1004
0
      if (zl3vni)
1005
0
        listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
1006
0
    }
1007
1008
    /* If part of a bridge, inform BGP about this VNI. */
1009
    /* Also, read and populate local MACs and neighbors. */
1010
0
    if (zif->brslave_info.br_if) {
1011
0
      zebra_evpn_send_add_to_client(zevpn);
1012
0
      zebra_evpn_read_mac_neigh(zevpn, ifp);
1013
0
    }
1014
0
  }
1015
1016
0
  return 0;
1017
0
}
1018
1019
/*
1020
 * Handle VxLAN interface up - update BGP if required.
1021
 */
1022
int zebra_vxlan_if_up(struct interface *ifp)
1023
0
{
1024
0
  struct zebra_if *zif;
1025
0
  struct zebra_vxlan_vni_info *vni_info;
1026
1027
  /* Check if EVPN is enabled. */
1028
0
  if (!is_evpn_enabled())
1029
0
    return 0;
1030
1031
0
  zif = ifp->info;
1032
0
  assert(zif);
1033
1034
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
1035
0
    vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1036
0
    return zebra_vxlan_if_vni_up(ifp, &vni_info->vni);
1037
0
  }
1038
1039
0
  zebra_vxlan_if_vni_iterate(zif, zebra_vxlan_if_vni_entry_up_callback,
1040
0
           NULL);
1041
1042
0
  return 0;
1043
0
}
1044
1045
int zebra_vxlan_if_vni_del(struct interface *ifp, vni_t vni)
1046
0
{
1047
0
  struct zebra_if *zif;
1048
0
  struct zebra_vxlan_vni *vnip;
1049
0
  struct zebra_vxlan_vni vni_tmp;
1050
0
  struct zebra_vxlan_vni_info *vni_info;
1051
1052
0
  zif = ifp->info;
1053
0
  assert(zif);
1054
1055
  /* This should be called in SVD context only */
1056
0
  assert(IS_ZEBRA_VXLAN_IF_SVD(zif));
1057
1058
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1059
0
  memset(&vni_tmp, 0, sizeof(vni_tmp));
1060
0
  vni_tmp.vni = vni;
1061
1062
0
  vnip = hash_release(vni_info->vni_table, &vni_tmp);
1063
0
  if (vnip) {
1064
0
    zebra_vxlan_if_vni_entry_del(zif, vnip);
1065
0
    zebra_vxlan_vni_free(vnip);
1066
0
  }
1067
0
  return 0;
1068
0
}
1069
1070
/*
1071
 * Handle VxLAN interface delete. Locate and remove entry in hash table
1072
 * and update BGP, if required.
1073
 */
1074
int zebra_vxlan_if_del(struct interface *ifp)
1075
0
{
1076
0
  struct zebra_if *zif;
1077
0
  struct zebra_vxlan_vni_info *vni_info;
1078
1079
0
  zif = ifp->info;
1080
0
  assert(zif);
1081
1082
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
1083
0
    vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1084
0
    zebra_evpn_vl_vxl_deref(vni_info->vni.access_vlan,
1085
0
          vni_info->vni.vni, zif);
1086
0
    return zebra_vxlan_if_del_vni(ifp, &vni_info->vni);
1087
0
  }
1088
1089
0
  zebra_vxlan_if_vni_table_destroy(zif);
1090
1091
0
  return 0;
1092
0
}
1093
1094
/*
1095
 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
1096
 */
1097
int zebra_vxlan_if_update(struct interface *ifp,
1098
        struct zebra_vxlan_if_update_ctx *ctx)
1099
0
{
1100
0
  struct zebra_if *zif;
1101
0
  struct zebra_vxlan_vni_info *vni_info;
1102
1103
0
  zif = ifp->info;
1104
0
  assert(zif);
1105
1106
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
1107
0
    vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1108
0
    return zebra_vxlan_if_update_vni(ifp, &vni_info->vni, ctx);
1109
0
  }
1110
1111
0
  zebra_vxlan_if_vni_iterate(
1112
0
    zif, zebra_vxlan_if_vni_entry_update_callback, ctx);
1113
1114
0
  return 0;
1115
0
}
1116
1117
int zebra_vxlan_if_vni_add(struct interface *ifp, struct zebra_vxlan_vni *vni)
1118
0
{
1119
0
  struct zebra_if *zif;
1120
0
  struct zebra_vxlan_vni_info *vni_info;
1121
1122
0
  zif = ifp->info;
1123
0
  assert(zif);
1124
1125
  /* This should be called in SVD context only */
1126
0
  assert(IS_ZEBRA_VXLAN_IF_SVD(zif));
1127
1128
  /* First insert into the table */
1129
0
  vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1130
0
  hash_get(vni_info->vni_table, (void *)vni, zebra_vxlan_vni_alloc);
1131
1132
0
  return zebra_vxlan_if_vni_entry_add(zif, vni);
1133
0
}
1134
1135
/*
1136
 * Handle VxLAN interface add.
1137
 */
1138
int zebra_vxlan_if_add(struct interface *ifp)
1139
0
{
1140
0
  int ret;
1141
0
  struct zebra_if *zif;
1142
0
  struct zebra_vxlan_vni_info *vni_info;
1143
1144
0
  zif = ifp->info;
1145
0
  assert(zif);
1146
1147
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
1148
0
    vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
1149
0
    zebra_evpn_vl_vxl_ref(vni_info->vni.access_vlan,
1150
0
              vni_info->vni.vni, zif);
1151
0
    return zebra_vxlan_if_add_vni(ifp, &vni_info->vni);
1152
0
  }
1153
1154
0
  ret = zebra_vxlan_if_vni_table_create(zif);
1155
0
  if (ret < 0)
1156
0
    return ret;
1157
1158
0
  return 0;
1159
0
}