]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_l2_bridge_if.c
Merge pull request #13445 from donaldsharp/lua_scripting_mem_leak
[mirror_frr.git] / zebra / zebra_l2_bridge_if.c
CommitLineData
239b26f9
SR
1/*
2 * Zebra L2 bridge interface handling
3 *
4 * Copyright (C) 2021 Cumulus Networks, Inc.
5 * 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_l2_bridge_if.h"
46#include "zebra/zebra_ns.h"
47#include "zebra/zebra_vrf.h"
48#include "zebra/zebra_vxlan.h"
49#include "zebra/zebra_vxlan_if.h"
50#include "zebra/zebra_evpn.h"
51#include "zebra/zebra_evpn_mac.h"
52#include "zebra/zebra_evpn_neigh.h"
53#include "zebra/zebra_vxlan_private.h"
54#include "zebra/zebra_evpn_mh.h"
55#include "zebra/zebra_evpn_vxlan.h"
56#include "zebra/zebra_router.h"
57
58static unsigned int zebra_l2_bridge_vlan_hash_keymake(const void *p)
59{
60 const struct zebra_l2_bridge_vlan *bvlan;
61
62 bvlan = (const struct zebra_l2_bridge_vlan *)p;
63 return jhash(&bvlan->vid, sizeof(bvlan->vid), 0);
64}
65
66static bool zebra_l2_bridge_vlan_hash_cmp(const void *p1, const void *p2)
67{
68 const struct zebra_l2_bridge_vlan *bv1;
69 const struct zebra_l2_bridge_vlan *bv2;
70
71 bv1 = (const struct zebra_l2_bridge_vlan *)p1;
72 bv2 = (const struct zebra_l2_bridge_vlan *)p2;
73
74 return (bv1->vid == bv2->vid);
75}
76
77static int zebra_l2_bridge_if_vlan_walk_callback(struct hash_bucket *bucket,
78 void *ctxt)
79{
80 int ret;
81 struct zebra_l2_bridge_vlan *bvlan;
82 struct zebra_l2_bridge_if_ctx *ctx;
83
84 bvlan = (struct zebra_l2_bridge_vlan *)bucket->data;
85 ctx = (struct zebra_l2_bridge_if_ctx *)ctxt;
86
87 ret = ctx->func(ctx->zif, bvlan, ctx->arg);
88 return ret;
89}
90
91static void zebra_l2_bridge_if_vlan_iterate_callback(struct hash_bucket *bucket,
92 void *ctxt)
93{
94 struct zebra_l2_bridge_vlan *bvlan;
95 struct zebra_l2_bridge_if_ctx *ctx;
96
97 bvlan = (struct zebra_l2_bridge_vlan *)bucket->data;
98 ctx = (struct zebra_l2_bridge_if_ctx *)ctxt;
99
100 ctx->func(ctx->zif, bvlan, ctx->arg);
101}
102
103static int zebra_l2_bridge_if_vlan_clean(struct zebra_if *zif,
104 struct zebra_l2_bridge_vlan *bvlan,
105 void *ctxt)
106{
107 struct zebra_evpn_access_bd *acc_bd;
108
109 if (IS_ZEBRA_DEBUG_VXLAN)
110 zlog_debug("access vlan %d bridge %s cleanup", bvlan->vid,
111 zif->ifp->name);
112
113 acc_bd = zebra_evpn_acc_vl_find(bvlan->vid, zif->ifp);
114 if (acc_bd)
115 zebra_evpn_access_bd_bridge_cleanup(bvlan->vid, zif->ifp,
116 acc_bd);
117
118 bvlan->access_bd = NULL;
119 return 0;
120}
121
122static void zebra_l2_bridge_vlan_free(void *arg)
123{
124 struct zebra_l2_bridge_vlan *bvl;
125
126 bvl = (struct zebra_l2_bridge_vlan *)arg;
127 XFREE(MTYPE_TMP, bvl);
128}
129
130static void *zebra_l2_bridge_vlan_alloc(void *p)
131{
132 struct zebra_l2_bridge_vlan *bvlan;
133 const struct zebra_l2_bridge_vlan *bvl;
134
135 bvl = (const struct zebra_l2_bridge_vlan *)p;
136 bvlan = XCALLOC(MTYPE_TMP, sizeof(*bvlan));
137 bvlan->vid = bvl->vid;
138 bvlan->access_bd = bvl->access_bd;
139
140 return (void *)bvlan;
141}
142
143static void zebra_l2_bridge_vlan_table_destroy(struct hash *vlan_table)
144{
d8bc11a5 145 hash_clean_and_free(&vlan_table, zebra_l2_bridge_vlan_free);
239b26f9
SR
146}
147
148static struct hash *zebra_l2_bridge_vlan_table_create(void)
149{
150 return hash_create(zebra_l2_bridge_vlan_hash_keymake,
151 zebra_l2_bridge_vlan_hash_cmp,
152 "Zebra L2 Bridge Vlan Table");
153}
154
155static void zebra_l2_bridge_if_vlan_table_destroy(struct zebra_if *zif)
156{
157 struct zebra_l2_bridge_if *br;
158
159 br = BRIDGE_FROM_ZEBRA_IF(zif);
160 zebra_l2_bridge_if_vlan_iterate(zif, zebra_l2_bridge_if_vlan_clean,
161 NULL);
162 zebra_l2_bridge_vlan_table_destroy(br->vlan_table);
163 br->vlan_table = NULL;
164}
165
166static int zebra_l2_bridge_if_vlan_table_create(struct zebra_if *zif)
167{
168 struct zebra_l2_bridge_if *br;
169
170 br = BRIDGE_FROM_ZEBRA_IF(zif);
171 if (!br->vlan_table) {
172 br->vlan_table = zebra_l2_bridge_vlan_table_create();
173 if (!br->vlan_table)
9464e5b8 174 return -ENOMEM;
239b26f9
SR
175 }
176
177 return 0;
178}
179
180static int zebra_l2_bridge_if_vlan_del(struct interface *ifp, vlanid_t vid)
181{
182 struct zebra_if *zif;
183 struct zebra_l2_bridge_if *br;
184 struct zebra_l2_bridge_vlan bvl;
185 struct zebra_l2_bridge_vlan *bvlan;
186
187 zif = (struct zebra_if *)ifp->info;
188 memset(&bvl, 0, sizeof(bvl));
189 bvl.vid = vid;
190
191 br = BRIDGE_FROM_ZEBRA_IF(zif);
192 bvlan = hash_release(br->vlan_table, &bvl);
193
194 if (bvlan)
195 zebra_l2_bridge_vlan_free(bvlan);
196
197 return 0;
198}
199
200static int zebra_l2_bridge_if_vlan_update(struct interface *ifp,
201 struct zebra_l2_bridge_vlan *bvl,
202 int chgflags)
203{
204 struct zebra_if *zif;
205 struct zebra_l2_bridge_vlan *bvlan;
206
207 zif = (struct zebra_if *)ifp->info;
208 bvlan = zebra_l2_bridge_if_vlan_find(zif, bvl->vid);
578c0b13
DS
209 if (!bvlan)
210 return 0;
239b26f9
SR
211
212 if (chgflags & ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE)
213 bvlan->access_bd = bvl->access_bd;
214
215 if (!bvlan->access_bd)
216 return zebra_l2_bridge_if_vlan_del(ifp, bvl->vid);
217
218 return 0;
219}
220
221static int zebra_l2_bridge_if_vlan_add(struct interface *ifp,
222 struct zebra_l2_bridge_vlan *bvlan)
223{
224 struct zebra_if *zif;
225 struct zebra_l2_bridge_if *br;
226
227 zif = (struct zebra_if *)ifp->info;
228 br = BRIDGE_FROM_ZEBRA_IF(zif);
229 hash_get(br->vlan_table, (void *)bvlan, zebra_l2_bridge_vlan_alloc);
230
231 return 0;
232}
233
234struct zebra_l2_bridge_vlan *
235zebra_l2_bridge_if_vlan_find(const struct zebra_if *zif, vlanid_t vid)
236{
237 const struct zebra_l2_bridge_if *br;
238 struct zebra_l2_bridge_vlan *bvl;
239 struct zebra_l2_bridge_vlan bvlan;
240
241 br = BRIDGE_FROM_ZEBRA_IF(zif);
242 memset(&bvlan, 0, sizeof(bvlan));
243 bvlan.vid = vid;
244 bvl = (struct zebra_l2_bridge_vlan *)hash_lookup(br->vlan_table,
245 (void *)&bvlan);
246
247 /* TODO: For debugging. Remove later */
248 if (bvl)
249 assert(bvl->vid == vid);
250
251 return bvl;
252}
253
254vni_t zebra_l2_bridge_if_vni_find(const struct zebra_if *zif, vlanid_t vid)
255{
256 vni_t vni_id = 0;
257 struct zebra_l2_bridge_vlan *bvlan;
258
259 bvlan = zebra_l2_bridge_if_vlan_find(zif, vid);
260 if (bvlan && bvlan->access_bd && bvlan->access_bd->vni)
261 vni_id = bvlan->access_bd->vni;
262
263 return vni_id;
264}
265
266void zebra_l2_bridge_if_vlan_iterate(struct zebra_if *zif,
267 int (*func)(struct zebra_if *zif,
268 struct zebra_l2_bridge_vlan *,
269 void *),
270 void *arg)
271{
272 struct zebra_l2_bridge_if *br;
273 struct zebra_l2_bridge_if_ctx ctx;
274
275 br = BRIDGE_FROM_ZEBRA_IF(zif);
276 memset(&ctx, 0, sizeof(ctx));
277 ctx.zif = zif;
278 ctx.func = func;
279 ctx.arg = arg;
280 hash_iterate(br->vlan_table, zebra_l2_bridge_if_vlan_iterate_callback,
281 &ctx);
282}
283
284void zebra_l2_bridge_if_vlan_walk(struct zebra_if *zif,
285 int (*func)(struct zebra_if *zif,
286 struct zebra_l2_bridge_vlan *,
287 void *),
288 void *arg)
289{
290 struct zebra_l2_bridge_if *br;
291 struct zebra_l2_bridge_if_ctx ctx;
292
293 br = BRIDGE_FROM_ZEBRA_IF(zif);
294 memset(&ctx, 0, sizeof(ctx));
295 ctx.zif = zif;
296 ctx.func = func;
297 ctx.arg = arg;
298 hash_walk(br->vlan_table, zebra_l2_bridge_if_vlan_walk_callback, &ctx);
299}
300
301int zebra_l2_bridge_if_vlan_access_bd_deref(struct zebra_evpn_access_bd *bd)
302{
303 int chgflags = 0;
304 struct zebra_if *zif;
305 struct zebra_l2_bridge_vlan bvl;
306 struct zebra_l2_bridge_vlan *bvlan;
307
308 zif = bd->bridge_zif;
309 if (!zif)
310 return -1;
311
312 bvlan = zebra_l2_bridge_if_vlan_find(zif, bd->vid);
313 if (!bvlan)
314 return 0;
315
316 memset(&bvl, 0, sizeof(bvl));
317 bvl.vid = bd->vid;
318 bvl.access_bd = NULL;
319 chgflags = ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE;
320 return zebra_l2_bridge_if_vlan_update(zif->ifp, &bvl, chgflags);
321}
322
323int zebra_l2_bridge_if_vlan_access_bd_ref(struct zebra_evpn_access_bd *bd)
324{
325 int chgflags = 0;
326 struct zebra_if *zif;
327 struct zebra_l2_bridge_vlan bvl;
328 struct zebra_l2_bridge_vlan *bvlan;
329
330 zif = bd->bridge_zif;
331 if (!zif)
332 return -1;
333
334 if (!bd->vid)
335 return -1;
336
337 memset(&bvl, 0, sizeof(bvl));
338 bvl.vid = bd->vid;
339 bvl.access_bd = bd;
340
341 bvlan = zebra_l2_bridge_if_vlan_find(zif, bd->vid);
9464e5b8 342 if (!bvlan)
239b26f9 343 return zebra_l2_bridge_if_vlan_add(zif->ifp, &bvl);
239b26f9
SR
344
345 chgflags = ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE;
346 return zebra_l2_bridge_if_vlan_update(zif->ifp, &bvl, chgflags);
347}
348
349int zebra_l2_bridge_if_cleanup(struct interface *ifp)
350{
351 struct zebra_if *zif;
352
353 if (!IS_ZEBRA_IF_BRIDGE(ifp))
354 return 0;
355
356 if (IS_ZEBRA_DEBUG_VXLAN)
357 zlog_debug("bridge %s cleanup", ifp->name);
358
359 zif = (struct zebra_if *)ifp->info;
360 zebra_l2_bridge_if_vlan_table_destroy(zif);
361 return 0;
362}
363
364int zebra_l2_bridge_if_del(struct interface *ifp)
365{
366 if (IS_ZEBRA_DEBUG_VXLAN)
367 zlog_debug("bridge %s delete", ifp->name);
368
369 return zebra_l2_bridge_if_cleanup(ifp);
370}
371
372int zebra_l2_bridge_if_add(struct interface *ifp)
373{
374 struct zebra_if *zif;
375 struct zebra_l2_bridge_if *br;
376
377 zif = (struct zebra_if *)ifp->info;
378 br = BRIDGE_FROM_ZEBRA_IF(zif);
379 br->br_zif = (struct zebra_if *)ifp->info;
380 zebra_l2_bridge_if_vlan_table_create(zif);
381 return 0;
382}