]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_l2_bridge_if.c
bgpd: Refactor subgroup_announce_table() to reuse an existing helpers
[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 hash_clean_and_free(&vlan_table, zebra_l2_bridge_vlan_free);
146 }
147
148 static 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
155 static 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
166 static 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)
174 return -ENOMEM;
175 }
176
177 return 0;
178 }
179
180 static 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
200 static 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);
209 if (!bvlan)
210 return 0;
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
221 static 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
234 struct zebra_l2_bridge_vlan *
235 zebra_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
254 vni_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
266 void 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
284 void 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
301 int 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
323 int 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);
342 if (!bvlan)
343 return zebra_l2_bridge_if_vlan_add(zif->ifp, &bvl);
344
345 chgflags = ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE;
346 return zebra_l2_bridge_if_vlan_update(zif->ifp, &bvl, chgflags);
347 }
348
349 int 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
364 int 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
372 int 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 }