]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_l2_bridge_if.c
Merge pull request #12796 from donaldsharp/routemap_debugging
[mirror_frr.git] / zebra / zebra_l2_bridge_if.c
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
58 static 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
66 static 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
77 static 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
91 static 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
103 static 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
122 static 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
130 static 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
143 static void zebra_l2_bridge_vlan_table_destroy(struct hash *vlan_table)
144 {
145 if (vlan_table) {
146 hash_clean(vlan_table, zebra_l2_bridge_vlan_free);
147 hash_free(vlan_table);
148 }
149 }
150
151 static struct hash *zebra_l2_bridge_vlan_table_create(void)
152 {
153 return hash_create(zebra_l2_bridge_vlan_hash_keymake,
154 zebra_l2_bridge_vlan_hash_cmp,
155 "Zebra L2 Bridge Vlan Table");
156 }
157
158 static void zebra_l2_bridge_if_vlan_table_destroy(struct zebra_if *zif)
159 {
160 struct zebra_l2_bridge_if *br;
161
162 br = BRIDGE_FROM_ZEBRA_IF(zif);
163 zebra_l2_bridge_if_vlan_iterate(zif, zebra_l2_bridge_if_vlan_clean,
164 NULL);
165 zebra_l2_bridge_vlan_table_destroy(br->vlan_table);
166 br->vlan_table = NULL;
167 }
168
169 static int zebra_l2_bridge_if_vlan_table_create(struct zebra_if *zif)
170 {
171 struct zebra_l2_bridge_if *br;
172
173 br = BRIDGE_FROM_ZEBRA_IF(zif);
174 if (!br->vlan_table) {
175 br->vlan_table = zebra_l2_bridge_vlan_table_create();
176 if (!br->vlan_table)
177 return -ENOMEM;
178 }
179
180 return 0;
181 }
182
183 static int zebra_l2_bridge_if_vlan_del(struct interface *ifp, vlanid_t vid)
184 {
185 struct zebra_if *zif;
186 struct zebra_l2_bridge_if *br;
187 struct zebra_l2_bridge_vlan bvl;
188 struct zebra_l2_bridge_vlan *bvlan;
189
190 zif = (struct zebra_if *)ifp->info;
191 memset(&bvl, 0, sizeof(bvl));
192 bvl.vid = vid;
193
194 br = BRIDGE_FROM_ZEBRA_IF(zif);
195 bvlan = hash_release(br->vlan_table, &bvl);
196
197 if (bvlan)
198 zebra_l2_bridge_vlan_free(bvlan);
199
200 return 0;
201 }
202
203 static int zebra_l2_bridge_if_vlan_update(struct interface *ifp,
204 struct zebra_l2_bridge_vlan *bvl,
205 int chgflags)
206 {
207 struct zebra_if *zif;
208 struct zebra_l2_bridge_vlan *bvlan;
209
210 zif = (struct zebra_if *)ifp->info;
211 bvlan = zebra_l2_bridge_if_vlan_find(zif, bvl->vid);
212
213 if (chgflags & ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE)
214 bvlan->access_bd = bvl->access_bd;
215
216 if (!bvlan->access_bd)
217 return zebra_l2_bridge_if_vlan_del(ifp, bvl->vid);
218
219 return 0;
220 }
221
222 static int zebra_l2_bridge_if_vlan_add(struct interface *ifp,
223 struct zebra_l2_bridge_vlan *bvlan)
224 {
225 struct zebra_if *zif;
226 struct zebra_l2_bridge_if *br;
227
228 zif = (struct zebra_if *)ifp->info;
229 br = BRIDGE_FROM_ZEBRA_IF(zif);
230 hash_get(br->vlan_table, (void *)bvlan, zebra_l2_bridge_vlan_alloc);
231
232 return 0;
233 }
234
235 struct zebra_l2_bridge_vlan *
236 zebra_l2_bridge_if_vlan_find(const struct zebra_if *zif, vlanid_t vid)
237 {
238 const struct zebra_l2_bridge_if *br;
239 struct zebra_l2_bridge_vlan *bvl;
240 struct zebra_l2_bridge_vlan bvlan;
241
242 br = BRIDGE_FROM_ZEBRA_IF(zif);
243 memset(&bvlan, 0, sizeof(bvlan));
244 bvlan.vid = vid;
245 bvl = (struct zebra_l2_bridge_vlan *)hash_lookup(br->vlan_table,
246 (void *)&bvlan);
247
248 /* TODO: For debugging. Remove later */
249 if (bvl)
250 assert(bvl->vid == vid);
251
252 return bvl;
253 }
254
255 vni_t zebra_l2_bridge_if_vni_find(const struct zebra_if *zif, vlanid_t vid)
256 {
257 vni_t vni_id = 0;
258 struct zebra_l2_bridge_vlan *bvlan;
259
260 bvlan = zebra_l2_bridge_if_vlan_find(zif, vid);
261 if (bvlan && bvlan->access_bd && bvlan->access_bd->vni)
262 vni_id = bvlan->access_bd->vni;
263
264 return vni_id;
265 }
266
267 void zebra_l2_bridge_if_vlan_iterate(struct zebra_if *zif,
268 int (*func)(struct zebra_if *zif,
269 struct zebra_l2_bridge_vlan *,
270 void *),
271 void *arg)
272 {
273 struct zebra_l2_bridge_if *br;
274 struct zebra_l2_bridge_if_ctx ctx;
275
276 br = BRIDGE_FROM_ZEBRA_IF(zif);
277 memset(&ctx, 0, sizeof(ctx));
278 ctx.zif = zif;
279 ctx.func = func;
280 ctx.arg = arg;
281 hash_iterate(br->vlan_table, zebra_l2_bridge_if_vlan_iterate_callback,
282 &ctx);
283 }
284
285 void zebra_l2_bridge_if_vlan_walk(struct zebra_if *zif,
286 int (*func)(struct zebra_if *zif,
287 struct zebra_l2_bridge_vlan *,
288 void *),
289 void *arg)
290 {
291 struct zebra_l2_bridge_if *br;
292 struct zebra_l2_bridge_if_ctx ctx;
293
294 br = BRIDGE_FROM_ZEBRA_IF(zif);
295 memset(&ctx, 0, sizeof(ctx));
296 ctx.zif = zif;
297 ctx.func = func;
298 ctx.arg = arg;
299 hash_walk(br->vlan_table, zebra_l2_bridge_if_vlan_walk_callback, &ctx);
300 }
301
302 int zebra_l2_bridge_if_vlan_access_bd_deref(struct zebra_evpn_access_bd *bd)
303 {
304 int chgflags = 0;
305 struct zebra_if *zif;
306 struct zebra_l2_bridge_vlan bvl;
307 struct zebra_l2_bridge_vlan *bvlan;
308
309 zif = bd->bridge_zif;
310 if (!zif)
311 return -1;
312
313 bvlan = zebra_l2_bridge_if_vlan_find(zif, bd->vid);
314 if (!bvlan)
315 return 0;
316
317 memset(&bvl, 0, sizeof(bvl));
318 bvl.vid = bd->vid;
319 bvl.access_bd = NULL;
320 chgflags = ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE;
321 return zebra_l2_bridge_if_vlan_update(zif->ifp, &bvl, chgflags);
322 }
323
324 int zebra_l2_bridge_if_vlan_access_bd_ref(struct zebra_evpn_access_bd *bd)
325 {
326 int chgflags = 0;
327 struct zebra_if *zif;
328 struct zebra_l2_bridge_vlan bvl;
329 struct zebra_l2_bridge_vlan *bvlan;
330
331 zif = bd->bridge_zif;
332 if (!zif)
333 return -1;
334
335 if (!bd->vid)
336 return -1;
337
338 memset(&bvl, 0, sizeof(bvl));
339 bvl.vid = bd->vid;
340 bvl.access_bd = bd;
341
342 bvlan = zebra_l2_bridge_if_vlan_find(zif, bd->vid);
343 if (!bvlan)
344 return zebra_l2_bridge_if_vlan_add(zif->ifp, &bvl);
345
346 chgflags = ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE;
347 return zebra_l2_bridge_if_vlan_update(zif->ifp, &bvl, chgflags);
348 }
349
350 int zebra_l2_bridge_if_cleanup(struct interface *ifp)
351 {
352 struct zebra_if *zif;
353
354 if (!IS_ZEBRA_IF_BRIDGE(ifp))
355 return 0;
356
357 if (IS_ZEBRA_DEBUG_VXLAN)
358 zlog_debug("bridge %s cleanup", ifp->name);
359
360 zif = (struct zebra_if *)ifp->info;
361 zebra_l2_bridge_if_vlan_table_destroy(zif);
362 return 0;
363 }
364
365 int zebra_l2_bridge_if_del(struct interface *ifp)
366 {
367 if (IS_ZEBRA_DEBUG_VXLAN)
368 zlog_debug("bridge %s delete", ifp->name);
369
370 return zebra_l2_bridge_if_cleanup(ifp);
371 }
372
373 int zebra_l2_bridge_if_add(struct interface *ifp)
374 {
375 struct zebra_if *zif;
376 struct zebra_l2_bridge_if *br;
377
378 zif = (struct zebra_if *)ifp->info;
379 br = BRIDGE_FROM_ZEBRA_IF(zif);
380 br->br_zif = (struct zebra_if *)ifp->info;
381 zebra_l2_bridge_if_vlan_table_create(zif);
382 return 0;
383 }