2 * Zebra L2 bridge interface handling
4 * Copyright (C) 2021 Cumulus Networks, Inc.
7 * This file is part of FRR.
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
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.
34 #include <linux/neighbour.h>
37 #include "zebra/zebra_router.h"
38 #include "zebra/debug.h"
39 #include "zebra/interface.h"
40 #include "zebra/rib.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"
58 static unsigned int zebra_l2_bridge_vlan_hash_keymake(const void *p
)
60 const struct zebra_l2_bridge_vlan
*bvlan
;
62 bvlan
= (const struct zebra_l2_bridge_vlan
*)p
;
63 return jhash(&bvlan
->vid
, sizeof(bvlan
->vid
), 0);
66 static bool zebra_l2_bridge_vlan_hash_cmp(const void *p1
, const void *p2
)
68 const struct zebra_l2_bridge_vlan
*bv1
;
69 const struct zebra_l2_bridge_vlan
*bv2
;
71 bv1
= (const struct zebra_l2_bridge_vlan
*)p1
;
72 bv2
= (const struct zebra_l2_bridge_vlan
*)p2
;
74 return (bv1
->vid
== bv2
->vid
);
77 static int zebra_l2_bridge_if_vlan_walk_callback(struct hash_bucket
*bucket
,
81 struct zebra_l2_bridge_vlan
*bvlan
;
82 struct zebra_l2_bridge_if_ctx
*ctx
;
84 bvlan
= (struct zebra_l2_bridge_vlan
*)bucket
->data
;
85 ctx
= (struct zebra_l2_bridge_if_ctx
*)ctxt
;
87 ret
= ctx
->func(ctx
->zif
, bvlan
, ctx
->arg
);
91 static void zebra_l2_bridge_if_vlan_iterate_callback(struct hash_bucket
*bucket
,
94 struct zebra_l2_bridge_vlan
*bvlan
;
95 struct zebra_l2_bridge_if_ctx
*ctx
;
97 bvlan
= (struct zebra_l2_bridge_vlan
*)bucket
->data
;
98 ctx
= (struct zebra_l2_bridge_if_ctx
*)ctxt
;
100 ctx
->func(ctx
->zif
, bvlan
, ctx
->arg
);
103 static int zebra_l2_bridge_if_vlan_clean(struct zebra_if
*zif
,
104 struct zebra_l2_bridge_vlan
*bvlan
,
107 struct zebra_evpn_access_bd
*acc_bd
;
109 if (IS_ZEBRA_DEBUG_VXLAN
)
110 zlog_debug("access vlan %d bridge %s cleanup", bvlan
->vid
,
113 acc_bd
= zebra_evpn_acc_vl_find(bvlan
->vid
, zif
->ifp
);
115 zebra_evpn_access_bd_bridge_cleanup(bvlan
->vid
, zif
->ifp
,
118 bvlan
->access_bd
= NULL
;
122 static void zebra_l2_bridge_vlan_free(void *arg
)
124 struct zebra_l2_bridge_vlan
*bvl
;
126 bvl
= (struct zebra_l2_bridge_vlan
*)arg
;
127 XFREE(MTYPE_TMP
, bvl
);
130 static void *zebra_l2_bridge_vlan_alloc(void *p
)
132 struct zebra_l2_bridge_vlan
*bvlan
;
133 const struct zebra_l2_bridge_vlan
*bvl
;
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
;
140 return (void *)bvlan
;
143 static void zebra_l2_bridge_vlan_table_destroy(struct hash
*vlan_table
)
146 hash_clean(vlan_table
, zebra_l2_bridge_vlan_free
);
147 hash_free(vlan_table
);
151 static struct hash
*zebra_l2_bridge_vlan_table_create(void)
153 return hash_create(zebra_l2_bridge_vlan_hash_keymake
,
154 zebra_l2_bridge_vlan_hash_cmp
,
155 "Zebra L2 Bridge Vlan Table");
158 static void zebra_l2_bridge_if_vlan_table_destroy(struct zebra_if
*zif
)
160 struct zebra_l2_bridge_if
*br
;
162 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
163 zebra_l2_bridge_if_vlan_iterate(zif
, zebra_l2_bridge_if_vlan_clean
,
165 zebra_l2_bridge_vlan_table_destroy(br
->vlan_table
);
166 br
->vlan_table
= NULL
;
169 static int zebra_l2_bridge_if_vlan_table_create(struct zebra_if
*zif
)
171 struct zebra_l2_bridge_if
*br
;
173 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
174 if (!br
->vlan_table
) {
175 br
->vlan_table
= zebra_l2_bridge_vlan_table_create();
183 static int zebra_l2_bridge_if_vlan_del(struct interface
*ifp
, vlanid_t vid
)
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
;
190 zif
= (struct zebra_if
*)ifp
->info
;
191 memset(&bvl
, 0, sizeof(bvl
));
194 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
195 bvlan
= hash_release(br
->vlan_table
, &bvl
);
198 zebra_l2_bridge_vlan_free(bvlan
);
203 static int zebra_l2_bridge_if_vlan_update(struct interface
*ifp
,
204 struct zebra_l2_bridge_vlan
*bvl
,
207 struct zebra_if
*zif
;
208 struct zebra_l2_bridge_vlan
*bvlan
;
210 zif
= (struct zebra_if
*)ifp
->info
;
211 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bvl
->vid
);
215 if (chgflags
& ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
)
216 bvlan
->access_bd
= bvl
->access_bd
;
218 if (!bvlan
->access_bd
)
219 return zebra_l2_bridge_if_vlan_del(ifp
, bvl
->vid
);
224 static int zebra_l2_bridge_if_vlan_add(struct interface
*ifp
,
225 struct zebra_l2_bridge_vlan
*bvlan
)
227 struct zebra_if
*zif
;
228 struct zebra_l2_bridge_if
*br
;
230 zif
= (struct zebra_if
*)ifp
->info
;
231 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
232 hash_get(br
->vlan_table
, (void *)bvlan
, zebra_l2_bridge_vlan_alloc
);
237 struct zebra_l2_bridge_vlan
*
238 zebra_l2_bridge_if_vlan_find(const struct zebra_if
*zif
, vlanid_t vid
)
240 const struct zebra_l2_bridge_if
*br
;
241 struct zebra_l2_bridge_vlan
*bvl
;
242 struct zebra_l2_bridge_vlan bvlan
;
244 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
245 memset(&bvlan
, 0, sizeof(bvlan
));
247 bvl
= (struct zebra_l2_bridge_vlan
*)hash_lookup(br
->vlan_table
,
250 /* TODO: For debugging. Remove later */
252 assert(bvl
->vid
== vid
);
257 vni_t
zebra_l2_bridge_if_vni_find(const struct zebra_if
*zif
, vlanid_t vid
)
260 struct zebra_l2_bridge_vlan
*bvlan
;
262 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, vid
);
263 if (bvlan
&& bvlan
->access_bd
&& bvlan
->access_bd
->vni
)
264 vni_id
= bvlan
->access_bd
->vni
;
269 void zebra_l2_bridge_if_vlan_iterate(struct zebra_if
*zif
,
270 int (*func
)(struct zebra_if
*zif
,
271 struct zebra_l2_bridge_vlan
*,
275 struct zebra_l2_bridge_if
*br
;
276 struct zebra_l2_bridge_if_ctx ctx
;
278 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
279 memset(&ctx
, 0, sizeof(ctx
));
283 hash_iterate(br
->vlan_table
, zebra_l2_bridge_if_vlan_iterate_callback
,
287 void zebra_l2_bridge_if_vlan_walk(struct zebra_if
*zif
,
288 int (*func
)(struct zebra_if
*zif
,
289 struct zebra_l2_bridge_vlan
*,
293 struct zebra_l2_bridge_if
*br
;
294 struct zebra_l2_bridge_if_ctx ctx
;
296 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
297 memset(&ctx
, 0, sizeof(ctx
));
301 hash_walk(br
->vlan_table
, zebra_l2_bridge_if_vlan_walk_callback
, &ctx
);
304 int zebra_l2_bridge_if_vlan_access_bd_deref(struct zebra_evpn_access_bd
*bd
)
307 struct zebra_if
*zif
;
308 struct zebra_l2_bridge_vlan bvl
;
309 struct zebra_l2_bridge_vlan
*bvlan
;
311 zif
= bd
->bridge_zif
;
315 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bd
->vid
);
319 memset(&bvl
, 0, sizeof(bvl
));
321 bvl
.access_bd
= NULL
;
322 chgflags
= ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
;
323 return zebra_l2_bridge_if_vlan_update(zif
->ifp
, &bvl
, chgflags
);
326 int zebra_l2_bridge_if_vlan_access_bd_ref(struct zebra_evpn_access_bd
*bd
)
329 struct zebra_if
*zif
;
330 struct zebra_l2_bridge_vlan bvl
;
331 struct zebra_l2_bridge_vlan
*bvlan
;
333 zif
= bd
->bridge_zif
;
340 memset(&bvl
, 0, sizeof(bvl
));
344 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bd
->vid
);
346 return zebra_l2_bridge_if_vlan_add(zif
->ifp
, &bvl
);
348 chgflags
= ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
;
349 return zebra_l2_bridge_if_vlan_update(zif
->ifp
, &bvl
, chgflags
);
352 int zebra_l2_bridge_if_cleanup(struct interface
*ifp
)
354 struct zebra_if
*zif
;
356 if (!IS_ZEBRA_IF_BRIDGE(ifp
))
359 if (IS_ZEBRA_DEBUG_VXLAN
)
360 zlog_debug("bridge %s cleanup", ifp
->name
);
362 zif
= (struct zebra_if
*)ifp
->info
;
363 zebra_l2_bridge_if_vlan_table_destroy(zif
);
367 int zebra_l2_bridge_if_del(struct interface
*ifp
)
369 if (IS_ZEBRA_DEBUG_VXLAN
)
370 zlog_debug("bridge %s delete", ifp
->name
);
372 return zebra_l2_bridge_if_cleanup(ifp
);
375 int zebra_l2_bridge_if_add(struct interface
*ifp
)
377 struct zebra_if
*zif
;
378 struct zebra_l2_bridge_if
*br
;
380 zif
= (struct zebra_if
*)ifp
->info
;
381 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
382 br
->br_zif
= (struct zebra_if
*)ifp
->info
;
383 zebra_l2_bridge_if_vlan_table_create(zif
);