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
)
145 hash_clean_and_free(&vlan_table
, zebra_l2_bridge_vlan_free
);
148 static struct hash
*zebra_l2_bridge_vlan_table_create(void)
150 return hash_create(zebra_l2_bridge_vlan_hash_keymake
,
151 zebra_l2_bridge_vlan_hash_cmp
,
152 "Zebra L2 Bridge Vlan Table");
155 static void zebra_l2_bridge_if_vlan_table_destroy(struct zebra_if
*zif
)
157 struct zebra_l2_bridge_if
*br
;
159 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
160 zebra_l2_bridge_if_vlan_iterate(zif
, zebra_l2_bridge_if_vlan_clean
,
162 zebra_l2_bridge_vlan_table_destroy(br
->vlan_table
);
163 br
->vlan_table
= NULL
;
166 static int zebra_l2_bridge_if_vlan_table_create(struct zebra_if
*zif
)
168 struct zebra_l2_bridge_if
*br
;
170 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
171 if (!br
->vlan_table
) {
172 br
->vlan_table
= zebra_l2_bridge_vlan_table_create();
180 static int zebra_l2_bridge_if_vlan_del(struct interface
*ifp
, vlanid_t vid
)
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
;
187 zif
= (struct zebra_if
*)ifp
->info
;
188 memset(&bvl
, 0, sizeof(bvl
));
191 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
192 bvlan
= hash_release(br
->vlan_table
, &bvl
);
195 zebra_l2_bridge_vlan_free(bvlan
);
200 static int zebra_l2_bridge_if_vlan_update(struct interface
*ifp
,
201 struct zebra_l2_bridge_vlan
*bvl
,
204 struct zebra_if
*zif
;
205 struct zebra_l2_bridge_vlan
*bvlan
;
207 zif
= (struct zebra_if
*)ifp
->info
;
208 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bvl
->vid
);
212 if (chgflags
& ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
)
213 bvlan
->access_bd
= bvl
->access_bd
;
215 if (!bvlan
->access_bd
)
216 return zebra_l2_bridge_if_vlan_del(ifp
, bvl
->vid
);
221 static int zebra_l2_bridge_if_vlan_add(struct interface
*ifp
,
222 struct zebra_l2_bridge_vlan
*bvlan
)
224 struct zebra_if
*zif
;
225 struct zebra_l2_bridge_if
*br
;
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
);
234 struct zebra_l2_bridge_vlan
*
235 zebra_l2_bridge_if_vlan_find(const struct zebra_if
*zif
, vlanid_t vid
)
237 const struct zebra_l2_bridge_if
*br
;
238 struct zebra_l2_bridge_vlan
*bvl
;
239 struct zebra_l2_bridge_vlan bvlan
;
241 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
242 memset(&bvlan
, 0, sizeof(bvlan
));
244 bvl
= (struct zebra_l2_bridge_vlan
*)hash_lookup(br
->vlan_table
,
247 /* TODO: For debugging. Remove later */
249 assert(bvl
->vid
== vid
);
254 vni_t
zebra_l2_bridge_if_vni_find(const struct zebra_if
*zif
, vlanid_t vid
)
257 struct zebra_l2_bridge_vlan
*bvlan
;
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
;
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
*,
272 struct zebra_l2_bridge_if
*br
;
273 struct zebra_l2_bridge_if_ctx ctx
;
275 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
276 memset(&ctx
, 0, sizeof(ctx
));
280 hash_iterate(br
->vlan_table
, zebra_l2_bridge_if_vlan_iterate_callback
,
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
*,
290 struct zebra_l2_bridge_if
*br
;
291 struct zebra_l2_bridge_if_ctx ctx
;
293 br
= BRIDGE_FROM_ZEBRA_IF(zif
);
294 memset(&ctx
, 0, sizeof(ctx
));
298 hash_walk(br
->vlan_table
, zebra_l2_bridge_if_vlan_walk_callback
, &ctx
);
301 int zebra_l2_bridge_if_vlan_access_bd_deref(struct zebra_evpn_access_bd
*bd
)
304 struct zebra_if
*zif
;
305 struct zebra_l2_bridge_vlan bvl
;
306 struct zebra_l2_bridge_vlan
*bvlan
;
308 zif
= bd
->bridge_zif
;
312 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bd
->vid
);
316 memset(&bvl
, 0, sizeof(bvl
));
318 bvl
.access_bd
= NULL
;
319 chgflags
= ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
;
320 return zebra_l2_bridge_if_vlan_update(zif
->ifp
, &bvl
, chgflags
);
323 int zebra_l2_bridge_if_vlan_access_bd_ref(struct zebra_evpn_access_bd
*bd
)
326 struct zebra_if
*zif
;
327 struct zebra_l2_bridge_vlan bvl
;
328 struct zebra_l2_bridge_vlan
*bvlan
;
330 zif
= bd
->bridge_zif
;
337 memset(&bvl
, 0, sizeof(bvl
));
341 bvlan
= zebra_l2_bridge_if_vlan_find(zif
, bd
->vid
);
343 return zebra_l2_bridge_if_vlan_add(zif
->ifp
, &bvl
);
345 chgflags
= ZEBRA_BRIDGEIF_ACCESS_BD_CHANGE
;
346 return zebra_l2_bridge_if_vlan_update(zif
->ifp
, &bvl
, chgflags
);
349 int zebra_l2_bridge_if_cleanup(struct interface
*ifp
)
351 struct zebra_if
*zif
;
353 if (!IS_ZEBRA_IF_BRIDGE(ifp
))
356 if (IS_ZEBRA_DEBUG_VXLAN
)
357 zlog_debug("bridge %s cleanup", ifp
->name
);
359 zif
= (struct zebra_if
*)ifp
->info
;
360 zebra_l2_bridge_if_vlan_table_destroy(zif
);
364 int zebra_l2_bridge_if_del(struct interface
*ifp
)
366 if (IS_ZEBRA_DEBUG_VXLAN
)
367 zlog_debug("bridge %s delete", ifp
->name
);
369 return zebra_l2_bridge_if_cleanup(ifp
);
372 int zebra_l2_bridge_if_add(struct interface
*ifp
)
374 struct zebra_if
*zif
;
375 struct zebra_l2_bridge_if
*br
;
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
);