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