diff options
author | Jiri Pirko <jpirko@redhat.com> | 2011-12-07 23:11:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-08 19:52:42 -0500 |
commit | 5b9ea6e022e9ba0fe39cb349ac40361f78d5da5b (patch) | |
tree | 11f0de492ee799fd4174f79ac6aae4c3533beb25 /net/8021q/vlan.h | |
parent | 87002b03baabd2b8f6281ab6411ed88d24958de1 (diff) |
vlan: introduce vid list with reference counting
This allows to keep track of vids needed to be in rx vlan filters of
devices even if they are used in bond/team etc.
vlan_info as well as vlan_group previously was, is allocated when first
vid is added and dealocated whan last vid is deleted.
vlan_group definition is moved to private header.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q/vlan.h')
-rw-r--r-- | net/8021q/vlan.h | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index d3c4ea4a3836..28d8dc20cb6d 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/if_vlan.h> | 4 | #include <linux/if_vlan.h> |
5 | #include <linux/u64_stats_sync.h> | 5 | #include <linux/u64_stats_sync.h> |
6 | #include <linux/list.h> | ||
6 | 7 | ||
7 | 8 | ||
8 | /** | 9 | /** |
@@ -74,6 +75,29 @@ static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) | |||
74 | return netdev_priv(dev); | 75 | return netdev_priv(dev); |
75 | } | 76 | } |
76 | 77 | ||
78 | /* if this changes, algorithm will have to be reworked because this | ||
79 | * depends on completely exhausting the VLAN identifier space. Thus | ||
80 | * it gives constant time look-up, but in many cases it wastes memory. | ||
81 | */ | ||
82 | #define VLAN_GROUP_ARRAY_SPLIT_PARTS 8 | ||
83 | #define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS) | ||
84 | |||
85 | struct vlan_group { | ||
86 | unsigned int nr_vlan_devs; | ||
87 | struct hlist_node hlist; /* linked list */ | ||
88 | struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; | ||
89 | }; | ||
90 | |||
91 | struct vlan_info { | ||
92 | struct net_device *real_dev; /* The ethernet(like) device | ||
93 | * the vlan is attached to. | ||
94 | */ | ||
95 | struct vlan_group grp; | ||
96 | struct list_head vid_list; | ||
97 | unsigned int nr_vids; | ||
98 | struct rcu_head rcu; | ||
99 | }; | ||
100 | |||
77 | static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, | 101 | static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, |
78 | u16 vlan_id) | 102 | u16 vlan_id) |
79 | { | 103 | { |
@@ -97,10 +121,10 @@ static inline void vlan_group_set_device(struct vlan_group *vg, | |||
97 | static inline struct net_device *vlan_find_dev(struct net_device *real_dev, | 121 | static inline struct net_device *vlan_find_dev(struct net_device *real_dev, |
98 | u16 vlan_id) | 122 | u16 vlan_id) |
99 | { | 123 | { |
100 | struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp); | 124 | struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); |
101 | 125 | ||
102 | if (grp) | 126 | if (vlan_info) |
103 | return vlan_group_get_device(grp, vlan_id); | 127 | return vlan_group_get_device(&vlan_info->grp, vlan_id); |
104 | 128 | ||
105 | return NULL; | 129 | return NULL; |
106 | } | 130 | } |