]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
6675513d | 2 | /* |
3 | * Zebra Layer-2 interface handling code | |
4 | * Copyright (C) 2016, 2017 Cumulus Networks, Inc. | |
6675513d | 5 | */ |
6 | ||
7 | #include <zebra.h> | |
8 | ||
9 | #include "if.h" | |
10 | #include "prefix.h" | |
11 | #include "table.h" | |
12 | #include "memory.h" | |
13 | #include "log.h" | |
14 | #include "linklist.h" | |
15 | #include "stream.h" | |
16 | #include "hash.h" | |
17 | #include "jhash.h" | |
18 | ||
19 | #include "zebra/rib.h" | |
20 | #include "zebra/rt.h" | |
21 | #include "zebra/zebra_ns.h" | |
22 | #include "zebra/zserv.h" | |
23 | #include "zebra/debug.h" | |
24 | #include "zebra/interface.h" | |
6675513d | 25 | #include "zebra/zebra_vrf.h" |
26 | #include "zebra/rt_netlink.h" | |
c36e442c | 27 | #include "zebra/interface.h" |
6675513d | 28 | #include "zebra/zebra_l2.h" |
efde4f25 | 29 | #include "zebra/zebra_l2_bridge_if.h" |
13d60d35 | 30 | #include "zebra/zebra_vxlan.h" |
0adeb5fd | 31 | #include "zebra/zebra_vxlan_if.h" |
ce5160c0 | 32 | #include "zebra/zebra_evpn_mh.h" |
6675513d | 33 | |
34 | /* definitions */ | |
35 | ||
36 | /* static function declarations */ | |
37 | ||
38 | /* Private functions */ | |
c7620108 PG |
39 | static void map_slaves_to_bridge(struct interface *br_if, int link, |
40 | bool update_slave, uint8_t chgflags) | |
6675513d | 41 | { |
d62a17ae | 42 | struct vrf *vrf; |
d62a17ae | 43 | struct interface *ifp; |
a6e0edf2 PG |
44 | struct zebra_vrf *zvrf; |
45 | struct zebra_ns *zns; | |
d62a17ae | 46 | |
096f7609 | 47 | zvrf = br_if->vrf->info; |
a6e0edf2 PG |
48 | assert(zvrf); |
49 | zns = zvrf->zns; | |
50 | assert(zns); | |
a2addae8 | 51 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { |
451fda4f | 52 | FOR_ALL_INTERFACES (vrf, ifp) { |
d62a17ae | 53 | struct zebra_if *zif; |
54 | struct zebra_l2info_brslave *br_slave; | |
55 | ||
56 | if (ifp->ifindex == IFINDEX_INTERNAL || !ifp->info) | |
57 | continue; | |
58 | if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) | |
59 | continue; | |
60 | ||
61 | /* NOTE: This assumes 'zebra_l2info_brslave' is the | |
62 | * first field | |
63 | * for any L2 interface. | |
64 | */ | |
65 | zif = (struct zebra_if *)ifp->info; | |
66 | br_slave = &zif->brslave_info; | |
67 | ||
68 | if (link) { | |
c7620108 PG |
69 | if (br_slave->bridge_ifindex == br_if->ifindex |
70 | && br_slave->ns_id == zns->ns_id) { | |
d62a17ae | 71 | br_slave->br_if = br_if; |
c7620108 PG |
72 | if (update_slave) { |
73 | zebra_l2if_update_bridge_slave( | |
74 | ifp, | |
75 | br_slave->bridge_ifindex, | |
76 | br_slave->ns_id, | |
77 | chgflags); | |
78 | } | |
79 | } | |
d62a17ae | 80 | } else { |
81 | if (br_slave->br_if == br_if) | |
82 | br_slave->br_if = NULL; | |
83 | } | |
84 | } | |
85 | } | |
6675513d | 86 | } |
87 | ||
88 | /* Public functions */ | |
9771da71 PG |
89 | void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave, |
90 | struct zebra_ns *zns) | |
6675513d | 91 | { |
d62a17ae | 92 | struct interface *br_if; |
6675513d | 93 | |
d62a17ae | 94 | /* TODO: Handle change of master */ |
9771da71 PG |
95 | assert(zns); |
96 | br_if = if_lookup_by_index_per_ns(zebra_ns_lookup(zns->ns_id), | |
d62a17ae | 97 | br_slave->bridge_ifindex); |
98 | if (br_if) | |
99 | br_slave->br_if = br_if; | |
6675513d | 100 | } |
101 | ||
d62a17ae | 102 | void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) |
6675513d | 103 | { |
d62a17ae | 104 | br_slave->br_if = NULL; |
6675513d | 105 | } |
106 | ||
00a7710c AK |
107 | /* If any of the bond members are in bypass state the bond is placed |
108 | * in bypass state | |
109 | */ | |
110 | static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif) | |
111 | { | |
112 | struct listnode *node; | |
113 | struct zebra_if *bond_mbr; | |
114 | bool old_bypass = !!(bond_zif->flags & ZIF_FLAG_LACP_BYPASS); | |
115 | bool new_bypass = false; | |
116 | ||
117 | if (bond_zif->bond_info.mbr_zifs) { | |
118 | for (ALL_LIST_ELEMENTS_RO(bond_zif->bond_info.mbr_zifs, node, | |
119 | bond_mbr)) { | |
120 | if (bond_mbr->flags & ZIF_FLAG_LACP_BYPASS) { | |
121 | new_bypass = true; | |
122 | break; | |
123 | } | |
124 | } | |
125 | } | |
126 | ||
127 | if (old_bypass == new_bypass) | |
128 | return; | |
129 | ||
130 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
131 | zlog_debug("bond %s lacp bypass changed to %s", | |
132 | bond_zif->ifp->name, new_bypass ? "on" : "off"); | |
133 | ||
134 | if (new_bypass) | |
135 | bond_zif->flags |= ZIF_FLAG_LACP_BYPASS; | |
136 | else | |
137 | bond_zif->flags &= ~ZIF_FLAG_LACP_BYPASS; | |
138 | ||
139 | if (bond_zif->es_info.es) | |
140 | zebra_evpn_es_bypass_update(bond_zif->es_info.es, bond_zif->ifp, | |
141 | new_bypass); | |
142 | } | |
143 | ||
144 | /* Returns true if member was newly linked to bond */ | |
c36e442c | 145 | void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id) |
b9368db9 DD |
146 | { |
147 | struct interface *bond_if; | |
c36e442c AK |
148 | struct zebra_if *bond_zif; |
149 | struct zebra_l2info_bondslave *bond_slave = &zif->bondslave_info; | |
b9368db9 | 150 | |
a2df495f | 151 | bond_if = if_lookup_by_index(bond_slave->bond_ifindex, vrf_id); |
c36e442c AK |
152 | if (bond_if == bond_slave->bond_if) |
153 | return; | |
154 | ||
155 | /* unlink the slave from the old master */ | |
156 | zebra_l2_unmap_slave_from_bond(zif); | |
157 | ||
158 | /* If the bond is present and ready link the bond-member | |
159 | * to it | |
160 | */ | |
161 | if (bond_if && (bond_zif = bond_if->info)) { | |
162 | if (bond_zif->bond_info.mbr_zifs) { | |
163 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
164 | zlog_debug("bond mbr %s linked to %s", | |
165 | zif->ifp->name, bond_if->name); | |
166 | bond_slave->bond_if = bond_if; | |
167 | /* link the slave to the new bond master */ | |
168 | listnode_add(bond_zif->bond_info.mbr_zifs, zif); | |
169 | /* inherit protodown flags from the es-bond */ | |
170 | if (zebra_evpn_is_es_bond(bond_if)) | |
171 | zebra_evpn_mh_update_protodown_bond_mbr( | |
172 | zif, false /*clear*/, __func__); | |
00a7710c | 173 | zebra_l2_bond_lacp_bypass_eval(bond_zif); |
c36e442c AK |
174 | } |
175 | } else { | |
176 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
177 | zlog_debug("bond mbr %s link to bond skipped", | |
178 | zif->ifp->name); | |
179 | } | |
180 | } | |
181 | ||
182 | void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif) | |
183 | { | |
184 | struct zebra_l2info_bondslave *bond_slave = &zif->bondslave_info; | |
185 | struct zebra_if *bond_zif; | |
186 | ||
187 | if (!bond_slave->bond_if) { | |
188 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
189 | zlog_debug("bond mbr %s unlink from bond skipped", | |
190 | zif->ifp->name); | |
191 | return; | |
192 | } | |
193 | ||
194 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
195 | zlog_debug("bond mbr %s un-linked from %s", zif->ifp->name, | |
196 | bond_slave->bond_if->name); | |
197 | ||
198 | /* unlink the slave from the bond master */ | |
199 | bond_zif = bond_slave->bond_if->info; | |
200 | /* clear protodown flags */ | |
201 | if (zebra_evpn_is_es_bond(bond_zif->ifp)) | |
202 | zebra_evpn_mh_update_protodown_bond_mbr(zif, true /*clear*/, | |
203 | __func__); | |
204 | listnode_delete(bond_zif->bond_info.mbr_zifs, zif); | |
205 | bond_slave->bond_if = NULL; | |
00a7710c | 206 | zebra_l2_bond_lacp_bypass_eval(bond_zif); |
b9368db9 DD |
207 | } |
208 | ||
c36e442c | 209 | void zebra_l2if_update_bond(struct interface *ifp, bool add) |
b9368db9 | 210 | { |
c36e442c AK |
211 | struct zebra_if *zif; |
212 | struct zebra_l2info_bond *bond; | |
213 | ||
214 | zif = ifp->info; | |
215 | assert(zif); | |
216 | bond = &zif->bond_info; | |
217 | ||
218 | if (add) { | |
219 | if (!bond->mbr_zifs) { | |
220 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
221 | zlog_debug("bond %s mbr list create", | |
222 | ifp->name); | |
223 | bond->mbr_zifs = list_new(); | |
224 | } | |
225 | } else { | |
226 | struct listnode *node; | |
227 | struct listnode *nnode; | |
228 | struct zebra_if *bond_mbr; | |
229 | ||
230 | if (!bond->mbr_zifs) | |
231 | return; | |
232 | ||
233 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
234 | zlog_debug("bond %s mbr list delete", ifp->name); | |
235 | for (ALL_LIST_ELEMENTS(bond->mbr_zifs, node, nnode, bond_mbr)) | |
236 | zebra_l2_unmap_slave_from_bond(bond_mbr); | |
237 | ||
238 | list_delete(&bond->mbr_zifs); | |
239 | } | |
b9368db9 DD |
240 | } |
241 | ||
6675513d | 242 | /* |
243 | * Handle Bridge interface add or update. Update relevant info, | |
244 | * map slaves (if any) to the bridge. | |
245 | */ | |
d62a17ae | 246 | void zebra_l2_bridge_add_update(struct interface *ifp, |
247 | struct zebra_l2info_bridge *bridge_info, | |
248 | int add) | |
6675513d | 249 | { |
d62a17ae | 250 | struct zebra_if *zif; |
efde4f25 | 251 | struct zebra_l2_bridge_if *br; |
6675513d | 252 | |
d62a17ae | 253 | zif = ifp->info; |
254 | assert(zif); | |
6675513d | 255 | |
efde4f25 SR |
256 | br = BRIDGE_FROM_ZEBRA_IF(zif); |
257 | br->vlan_aware = bridge_info->bridge.vlan_aware; | |
258 | zebra_l2_bridge_if_add(ifp); | |
6675513d | 259 | |
d62a17ae | 260 | /* Link all slaves to this bridge */ |
c7620108 | 261 | map_slaves_to_bridge(ifp, 1, false, ZEBRA_BRIDGE_NO_ACTION); |
6675513d | 262 | } |
263 | ||
264 | /* | |
265 | * Handle Bridge interface delete. | |
266 | */ | |
d62a17ae | 267 | void zebra_l2_bridge_del(struct interface *ifp) |
6675513d | 268 | { |
efde4f25 SR |
269 | zebra_l2_bridge_if_del(ifp); |
270 | ||
d62a17ae | 271 | /* Unlink all slaves to this bridge */ |
c7620108 PG |
272 | map_slaves_to_bridge(ifp, 0, false, ZEBRA_BRIDGE_NO_ACTION); |
273 | } | |
274 | ||
275 | void zebra_l2if_update_bridge(struct interface *ifp, uint8_t chgflags) | |
276 | { | |
277 | if (!chgflags) | |
278 | return; | |
279 | map_slaves_to_bridge(ifp, 1, true, chgflags); | |
6675513d | 280 | } |
281 | ||
282 | /* | |
283 | * Update L2 info for a VLAN interface. Only relevant parameter is the | |
284 | * VLAN Id and this cannot change. | |
285 | */ | |
d62a17ae | 286 | void zebra_l2_vlanif_update(struct interface *ifp, |
287 | struct zebra_l2info_vlan *vlan_info) | |
6675513d | 288 | { |
d62a17ae | 289 | struct zebra_if *zif; |
6675513d | 290 | |
d62a17ae | 291 | zif = ifp->info; |
292 | assert(zif); | |
6675513d | 293 | |
d62a17ae | 294 | /* Copy over the L2 information. */ |
295 | memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info)); | |
6675513d | 296 | } |
297 | ||
077c07cc PG |
298 | /* |
299 | * Update L2 info for a GRE interface. This is called upon interface | |
300 | * addition as well as update. Upon add/update, need to inform | |
301 | * clients about GRE information. | |
302 | */ | |
303 | void zebra_l2_greif_add_update(struct interface *ifp, | |
304 | struct zebra_l2info_gre *gre_info, int add) | |
305 | { | |
306 | struct zebra_if *zif; | |
307 | struct in_addr old_vtep_ip; | |
308 | ||
309 | zif = ifp->info; | |
310 | assert(zif); | |
311 | ||
312 | if (add) { | |
313 | memcpy(&zif->l2info.gre, gre_info, sizeof(*gre_info)); | |
314 | return; | |
315 | } | |
316 | ||
317 | old_vtep_ip = zif->l2info.gre.vtep_ip; | |
318 | if (IPV4_ADDR_SAME(&old_vtep_ip, &gre_info->vtep_ip)) | |
319 | return; | |
320 | ||
321 | zif->l2info.gre.vtep_ip = gre_info->vtep_ip; | |
322 | } | |
323 | ||
6675513d | 324 | /* |
325 | * Update L2 info for a VxLAN interface. This is called upon interface | |
326 | * addition as well as update. Upon add, need to invoke the VNI create | |
327 | * function. Upon update, the params of interest are the local tunnel | |
328 | * IP and VLAN mapping, but the latter is handled separately. | |
329 | */ | |
d62a17ae | 330 | void zebra_l2_vxlanif_add_update(struct interface *ifp, |
331 | struct zebra_l2info_vxlan *vxlan_info, int add) | |
6675513d | 332 | { |
d62a17ae | 333 | struct zebra_if *zif; |
d7fe235c | 334 | uint16_t chgflags = 0; |
00d30205 | 335 | struct zebra_vxlan_if_update_ctx ctx; |
6675513d | 336 | |
d62a17ae | 337 | zif = ifp->info; |
338 | assert(zif); | |
6675513d | 339 | |
d62a17ae | 340 | if (add) { |
341 | memcpy(&zif->l2info.vxl, vxlan_info, sizeof(*vxlan_info)); | |
342 | zebra_vxlan_if_add(ifp); | |
343 | return; | |
344 | } | |
6675513d | 345 | |
00d30205 | 346 | memset(&ctx, 0, sizeof(ctx)); |
347 | ctx.old_vtep_ip = zif->l2info.vxl.vtep_ip; | |
6675513d | 348 | |
00d30205 | 349 | if (!IPV4_ADDR_SAME(&ctx.old_vtep_ip, &vxlan_info->vtep_ip)) { |
d7fe235c AK |
350 | chgflags |= ZEBRA_VXLIF_LOCAL_IP_CHANGE; |
351 | zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; | |
352 | } | |
353 | ||
8d30ff3b | 354 | if (IS_ZEBRA_VXLAN_IF_VNI(zif)) { |
00d30205 | 355 | ctx.old_vni = vxlan_info->vni_info.vni; |
8d30ff3b SR |
356 | if (!IPV4_ADDR_SAME(&zif->l2info.vxl.vni_info.vni.mcast_grp, |
357 | &vxlan_info->vni_info.vni.mcast_grp)) { | |
358 | chgflags |= ZEBRA_VXLIF_MCAST_GRP_CHANGE; | |
359 | zif->l2info.vxl.vni_info.vni.mcast_grp = | |
360 | vxlan_info->vni_info.vni.mcast_grp; | |
361 | } | |
d7fe235c AK |
362 | } |
363 | ||
00d30205 | 364 | if (chgflags) { |
365 | ctx.chgflags = chgflags; | |
366 | zebra_vxlan_if_update(ifp, &ctx); | |
367 | } | |
6675513d | 368 | } |
369 | ||
370 | /* | |
371 | * Handle change to VLAN to VNI mapping. | |
372 | */ | |
d62a17ae | 373 | void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, |
374 | vlanid_t access_vlan) | |
6675513d | 375 | { |
d62a17ae | 376 | struct zebra_if *zif; |
377 | vlanid_t old_access_vlan; | |
8d30ff3b | 378 | struct zebra_vxlan_vni *vni; |
00d30205 | 379 | struct zebra_vxlan_if_update_ctx ctx; |
8d30ff3b | 380 | |
6675513d | 381 | |
d62a17ae | 382 | zif = ifp->info; |
383 | assert(zif); | |
6675513d | 384 | |
8d30ff3b SR |
385 | /* This would be called only in non svd case */ |
386 | assert(IS_ZEBRA_VXLAN_IF_VNI(zif)); | |
387 | ||
388 | old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan; | |
389 | ; | |
d62a17ae | 390 | if (old_access_vlan == access_vlan) |
391 | return; | |
13d60d35 | 392 | |
00d30205 | 393 | memset(&ctx, 0, sizeof(ctx)); |
8d30ff3b | 394 | vni = zebra_vxlan_if_vni_find(zif, 0); |
00d30205 | 395 | ctx.old_vni = *vni; |
396 | ctx.chgflags = ZEBRA_VXLIF_VLAN_CHANGE; | |
8d30ff3b | 397 | vni->access_vlan = access_vlan; |
ce5160c0 | 398 | |
8d30ff3b SR |
399 | zebra_evpn_vl_vxl_deref(old_access_vlan, vni->vni, zif); |
400 | zebra_evpn_vl_vxl_ref(access_vlan, vni->vni, zif); | |
00d30205 | 401 | zebra_vxlan_if_update(ifp, &ctx); |
6675513d | 402 | } |
403 | ||
404 | /* | |
405 | * Handle VxLAN interface delete. | |
406 | */ | |
d62a17ae | 407 | void zebra_l2_vxlanif_del(struct interface *ifp) |
6675513d | 408 | { |
ce5160c0 AK |
409 | struct zebra_if *zif; |
410 | ||
411 | zif = ifp->info; | |
412 | assert(zif); | |
413 | ||
d62a17ae | 414 | zebra_vxlan_if_del(ifp); |
6675513d | 415 | } |
416 | ||
417 | /* | |
418 | * Map or unmap interface from bridge. | |
419 | * NOTE: It is currently assumped that an interface has to be unmapped | |
420 | * from a bridge before it can be mapped to another bridge. | |
421 | */ | |
d62a17ae | 422 | void zebra_l2if_update_bridge_slave(struct interface *ifp, |
c7620108 PG |
423 | ifindex_t bridge_ifindex, ns_id_t ns_id, |
424 | uint8_t chgflags) | |
6675513d | 425 | { |
d62a17ae | 426 | struct zebra_if *zif; |
427 | ifindex_t old_bridge_ifindex; | |
a6e0edf2 | 428 | ns_id_t old_ns_id; |
9771da71 | 429 | struct zebra_vrf *zvrf; |
00d30205 | 430 | struct zebra_vxlan_if_update_ctx ctx; |
431 | ||
432 | memset(&ctx, 0, sizeof(ctx)); | |
6675513d | 433 | |
d62a17ae | 434 | zif = ifp->info; |
435 | assert(zif); | |
6675513d | 436 | |
096f7609 | 437 | zvrf = ifp->vrf->info; |
9771da71 PG |
438 | if (!zvrf) |
439 | return; | |
440 | ||
c7620108 PG |
441 | if (zif->zif_type == ZEBRA_IF_VXLAN |
442 | && chgflags != ZEBRA_BRIDGE_NO_ACTION) { | |
00d30205 | 443 | if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) { |
444 | ctx.chgflags = ZEBRA_VXLIF_MASTER_MAC_CHANGE; | |
445 | zebra_vxlan_if_update(ifp, &ctx); | |
446 | } | |
447 | if (chgflags & ZEBRA_BRIDGE_MASTER_UP) { | |
448 | ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE; | |
449 | zebra_vxlan_if_update(ifp, &ctx); | |
450 | } | |
c7620108 | 451 | } |
d62a17ae | 452 | old_bridge_ifindex = zif->brslave_info.bridge_ifindex; |
a6e0edf2 PG |
453 | old_ns_id = zif->brslave_info.ns_id; |
454 | if (old_bridge_ifindex == bridge_ifindex && | |
455 | old_ns_id == zif->brslave_info.ns_id) | |
d62a17ae | 456 | return; |
6675513d | 457 | |
00d30205 | 458 | ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE; |
459 | ||
460 | ||
a6e0edf2 | 461 | zif->brslave_info.ns_id = ns_id; |
d62a17ae | 462 | zif->brslave_info.bridge_ifindex = bridge_ifindex; |
d62a17ae | 463 | /* Set up or remove link with master */ |
af026ae4 | 464 | if (bridge_ifindex != IFINDEX_INTERNAL) { |
9771da71 | 465 | zebra_l2_map_slave_to_bridge(&zif->brslave_info, zvrf->zns); |
af026ae4 | 466 | /* In the case of VxLAN, invoke the handler for EVPN. */ |
467 | if (zif->zif_type == ZEBRA_IF_VXLAN) | |
00d30205 | 468 | zebra_vxlan_if_update(ifp, &ctx); |
72f2674a AK |
469 | if (zif->es_info.es) |
470 | zebra_evpn_es_local_br_port_update(zif); | |
af026ae4 | 471 | } else if (old_bridge_ifindex != IFINDEX_INTERNAL) { |
57f7feb6 MK |
472 | /* |
473 | * In the case of VxLAN, invoke the handler for EVPN. | |
474 | * Note that this should be done *prior* | |
475 | * to unmapping the interface from the bridge. | |
af026ae4 | 476 | */ |
477 | if (zif->zif_type == ZEBRA_IF_VXLAN) | |
00d30205 | 478 | zebra_vxlan_if_update(ifp, &ctx); |
72f2674a AK |
479 | if (zif->es_info.es) |
480 | zebra_evpn_es_local_br_port_update(zif); | |
b682f6de | 481 | zebra_l2_unmap_slave_from_bridge(&zif->brslave_info); |
af026ae4 | 482 | } |
6675513d | 483 | } |
b9368db9 | 484 | |
00a7710c AK |
485 | void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex, |
486 | bool new_bypass) | |
b9368db9 DD |
487 | { |
488 | struct zebra_if *zif; | |
489 | ifindex_t old_bond_ifindex; | |
00a7710c AK |
490 | bool old_bypass; |
491 | struct zebra_l2info_bondslave *bond_mbr; | |
b9368db9 DD |
492 | |
493 | zif = ifp->info; | |
494 | assert(zif); | |
495 | ||
00a7710c AK |
496 | old_bypass = !!(zif->flags & ZIF_FLAG_LACP_BYPASS); |
497 | if (old_bypass != new_bypass) { | |
498 | if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) | |
499 | zlog_debug("bond-mbr %s lacp bypass changed to %s", | |
500 | zif->ifp->name, new_bypass ? "on" : "off"); | |
501 | ||
502 | if (new_bypass) | |
503 | zif->flags |= ZIF_FLAG_LACP_BYPASS; | |
504 | else | |
505 | zif->flags &= ~ZIF_FLAG_LACP_BYPASS; | |
506 | ||
507 | bond_mbr = &zif->bondslave_info; | |
508 | if (bond_mbr->bond_if) { | |
509 | struct zebra_if *bond_zif = bond_mbr->bond_if->info; | |
510 | ||
511 | zebra_l2_bond_lacp_bypass_eval(bond_zif); | |
512 | } | |
513 | } | |
514 | ||
b9368db9 DD |
515 | old_bond_ifindex = zif->bondslave_info.bond_ifindex; |
516 | if (old_bond_ifindex == bond_ifindex) | |
517 | return; | |
518 | ||
519 | zif->bondslave_info.bond_ifindex = bond_ifindex; | |
520 | ||
521 | /* Set up or remove link with master */ | |
522 | if (bond_ifindex != IFINDEX_INTERNAL) | |
096f7609 | 523 | zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id); |
b9368db9 | 524 | else if (old_bond_ifindex != IFINDEX_INTERNAL) |
c36e442c | 525 | zebra_l2_unmap_slave_from_bond(zif); |
b9368db9 | 526 | } |
ce5160c0 AK |
527 | |
528 | void zebra_vlan_bitmap_compute(struct interface *ifp, | |
529 | uint32_t vid_start, uint16_t vid_end) | |
530 | { | |
531 | uint32_t vid; | |
532 | struct zebra_if *zif; | |
533 | ||
534 | zif = (struct zebra_if *)ifp->info; | |
535 | assert(zif); | |
536 | ||
537 | for (vid = vid_start; vid <= vid_end; ++vid) | |
538 | bf_set_bit(zif->vlan_bitmap, vid); | |
539 | } | |
540 | ||
541 | void zebra_vlan_mbr_re_eval(struct interface *ifp, bitfield_t old_vlan_bitmap) | |
542 | { | |
543 | uint32_t vid; | |
544 | struct zebra_if *zif; | |
545 | ||
546 | zif = (struct zebra_if *)ifp->info; | |
547 | assert(zif); | |
548 | ||
549 | if (!bf_cmp(zif->vlan_bitmap, old_vlan_bitmap)) | |
550 | /* no change */ | |
551 | return; | |
552 | ||
553 | bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) { | |
554 | /* if not already set create new reference */ | |
555 | if (!bf_test_index(old_vlan_bitmap, vid)) | |
556 | zebra_evpn_vl_mbr_ref(vid, zif); | |
557 | ||
558 | /* also clear from the old vlan bitmap */ | |
559 | bf_release_index(old_vlan_bitmap, vid); | |
560 | } | |
561 | ||
562 | /* any bits remaining in the old vlan bitmap are stale references */ | |
563 | bf_for_each_set_bit(old_vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) { | |
564 | zebra_evpn_vl_mbr_deref(vid, zif); | |
565 | } | |
566 | } |