br_vlan.c (30b0594a3e6c2bcbe5bd59753d0319d6f9925e40) br_vlan.c (9163a0fc1f0c0980f117cc25f4fa6ba9b0750a36)
1#include <linux/kernel.h>
2#include <linux/netdevice.h>
3#include <linux/rtnetlink.h>
4#include <linux/slab.h>
5#include <net/switchdev.h>
6
7#include "br_private.h"
8#include "br_private_tunnel.h"

--- 176 unchanged lines hidden (view full) ---

185 if (refcount_dec_and_test(&masterv->refcnt)) {
186 rhashtable_remove_fast(&vg->vlan_hash,
187 &masterv->vnode, br_vlan_rht_params);
188 __vlan_del_list(masterv);
189 call_rcu(&masterv->rcu, br_master_vlan_rcu_free);
190 }
191}
192
1#include <linux/kernel.h>
2#include <linux/netdevice.h>
3#include <linux/rtnetlink.h>
4#include <linux/slab.h>
5#include <net/switchdev.h>
6
7#include "br_private.h"
8#include "br_private_tunnel.h"

--- 176 unchanged lines hidden (view full) ---

185 if (refcount_dec_and_test(&masterv->refcnt)) {
186 rhashtable_remove_fast(&vg->vlan_hash,
187 &masterv->vnode, br_vlan_rht_params);
188 __vlan_del_list(masterv);
189 call_rcu(&masterv->rcu, br_master_vlan_rcu_free);
190 }
191}
192
193static void nbp_vlan_rcu_free(struct rcu_head *rcu)
194{
195 struct net_bridge_vlan *v;
196
197 v = container_of(rcu, struct net_bridge_vlan, rcu);
198 WARN_ON(br_vlan_is_master(v));
199 /* if we had per-port stats configured then free them here */
200 if (v->brvlan->stats != v->stats)
201 free_percpu(v->stats);
202 v->stats = NULL;
203 kfree(v);
204}
205
193/* This is the shared VLAN add function which works for both ports and bridge
194 * devices. There are four possible calls to this function in terms of the
195 * vlan entry type:
196 * 1. vlan is being added on a port (no master flags, global entry exists)
197 * 2. vlan is being added on a bridge (both master and brentry flags)
198 * 3. vlan is being added on a port, but a global entry didn't exist which
199 * is being created right now (master flag set, brentry flag unset), the
200 * global entry is used for global per-vlan features, but not for filtering

--- 39 unchanged lines hidden (view full) ---

240 if (err)
241 goto out_filt;
242 }
243
244 masterv = br_vlan_get_master(br, v->vid);
245 if (!masterv)
246 goto out_filt;
247 v->brvlan = masterv;
206/* This is the shared VLAN add function which works for both ports and bridge
207 * devices. There are four possible calls to this function in terms of the
208 * vlan entry type:
209 * 1. vlan is being added on a port (no master flags, global entry exists)
210 * 2. vlan is being added on a bridge (both master and brentry flags)
211 * 3. vlan is being added on a port, but a global entry didn't exist which
212 * is being created right now (master flag set, brentry flag unset), the
213 * global entry is used for global per-vlan features, but not for filtering

--- 39 unchanged lines hidden (view full) ---

253 if (err)
254 goto out_filt;
255 }
256
257 masterv = br_vlan_get_master(br, v->vid);
258 if (!masterv)
259 goto out_filt;
260 v->brvlan = masterv;
248 v->stats = masterv->stats;
261 if (br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)) {
262 v->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats);
263 if (!v->stats) {
264 err = -ENOMEM;
265 goto out_filt;
266 }
267 } else {
268 v->stats = masterv->stats;
269 }
249 } else {
250 err = br_switchdev_port_vlan_add(dev, v->vid, flags);
251 if (err && err != -EOPNOTSUPP)
252 goto out;
253 }
254
255 /* Add the dev mac and count the vlan only if it's usable */
256 if (br_vlan_should_use(v)) {

--- 67 unchanged lines hidden (view full) ---

324 vg->num_vlans--;
325 }
326
327 if (masterv != v) {
328 vlan_tunnel_info_del(vg, v);
329 rhashtable_remove_fast(&vg->vlan_hash, &v->vnode,
330 br_vlan_rht_params);
331 __vlan_del_list(v);
270 } else {
271 err = br_switchdev_port_vlan_add(dev, v->vid, flags);
272 if (err && err != -EOPNOTSUPP)
273 goto out;
274 }
275
276 /* Add the dev mac and count the vlan only if it's usable */
277 if (br_vlan_should_use(v)) {

--- 67 unchanged lines hidden (view full) ---

345 vg->num_vlans--;
346 }
347
348 if (masterv != v) {
349 vlan_tunnel_info_del(vg, v);
350 rhashtable_remove_fast(&vg->vlan_hash, &v->vnode,
351 br_vlan_rht_params);
352 __vlan_del_list(v);
332 kfree_rcu(v, rcu);
353 call_rcu(&v->rcu, nbp_vlan_rcu_free);
333 }
334
335 br_vlan_put_master(masterv);
336out:
337 return err;
338}
339
340static void __vlan_group_free(struct net_bridge_vlan_group *vg)

--- 484 unchanged lines hidden (view full) ---

825 break;
826 default:
827 return -EINVAL;
828 }
829
830 return 0;
831}
832
354 }
355
356 br_vlan_put_master(masterv);
357out:
358 return err;
359}
360
361static void __vlan_group_free(struct net_bridge_vlan_group *vg)

--- 484 unchanged lines hidden (view full) ---

846 break;
847 default:
848 return -EINVAL;
849 }
850
851 return 0;
852}
853
854int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val)
855{
856 struct net_bridge_port *p;
857
858 /* allow to change the option if there are no port vlans configured */
859 list_for_each_entry(p, &br->port_list, list) {
860 struct net_bridge_vlan_group *vg = nbp_vlan_group(p);
861
862 if (vg->num_vlans)
863 return -EBUSY;
864 }
865
866 switch (val) {
867 case 0:
868 case 1:
869 br_opt_toggle(br, BROPT_VLAN_STATS_PER_PORT, !!val);
870 break;
871 default:
872 return -EINVAL;
873 }
874
875 return 0;
876}
877
833static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid)
834{
835 struct net_bridge_vlan *v;
836
837 if (vid != vg->pvid)
838 return false;
839
840 v = br_vlan_lookup(&vg->vlan_hash, vid);

--- 366 unchanged lines hidden ---
878static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid)
879{
880 struct net_bridge_vlan *v;
881
882 if (vid != vg->pvid)
883 return false;
884
885 v = br_vlan_lookup(&vg->vlan_hash, vid);

--- 366 unchanged lines hidden ---