Skip to content

Commit 7dddc74

Browse files
fengsxyPaolo Abeni
authored andcommitted
8021q: delete cleared egress QoS mappings
vlan_dev_set_egress_priority() currently keeps cleared egress priority mappings in the hash as tombstones. Repeated set/clear cycles with distinct skb priorities therefore accumulate mapping nodes until device teardown and leak memory. Delete mappings when vlan_prio is cleared instead of keeping tombstones. Now that the egress mapping lists are RCU protected, the node can be unlinked safely and freed after a grace period. Fixes: 1da177e ("Linux-2.6.12-rc2") Cc: stable@kernel.org Reported-by: Yifan Wu <yifanwucs@gmail.com> Reported-by: Juefei Pu <tomapufckgml@gmail.com> Reported-by: Xin Liu <bird@lzu.edu.cn> Co-developed-by: Yuan Tan <yuantan098@gmail.com> Signed-off-by: Yuan Tan <yuantan098@gmail.com> Signed-off-by: Longxuan Yu <ylong030@ucr.edu> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn> Link: https://patch.msgid.link/ecfa6f6ce2467a42647ff4c5221238ae85b79a59.1776647968.git.yuantan098@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent fc69dec commit 7dddc74

2 files changed

Lines changed: 14 additions & 10 deletions

File tree

net/8021q/vlan_dev.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,26 +172,34 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
172172
u32 skb_prio, u16 vlan_prio)
173173
{
174174
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
175+
struct vlan_priority_tci_mapping __rcu **mpp;
175176
struct vlan_priority_tci_mapping *mp;
176177
struct vlan_priority_tci_mapping *np;
177178
u32 bucket = skb_prio & 0xF;
178179
u32 vlan_qos = (vlan_prio << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK;
179180

180181
/* See if a priority mapping exists.. */
181-
mp = rtnl_dereference(vlan->egress_priority_map[bucket]);
182+
mpp = &vlan->egress_priority_map[bucket];
183+
mp = rtnl_dereference(*mpp);
182184
while (mp) {
183185
if (mp->priority == skb_prio) {
184-
if (mp->vlan_qos && !vlan_qos)
186+
if (!vlan_qos) {
187+
rcu_assign_pointer(*mpp, rtnl_dereference(mp->next));
185188
vlan->nr_egress_mappings--;
186-
else if (!mp->vlan_qos && vlan_qos)
187-
vlan->nr_egress_mappings++;
188-
WRITE_ONCE(mp->vlan_qos, vlan_qos);
189+
kfree_rcu(mp, rcu);
190+
} else {
191+
WRITE_ONCE(mp->vlan_qos, vlan_qos);
192+
}
189193
return 0;
190194
}
191-
mp = rtnl_dereference(mp->next);
195+
mpp = &mp->next;
196+
mp = rtnl_dereference(*mpp);
192197
}
193198

194199
/* Create a new mapping then. */
200+
if (!vlan_qos)
201+
return 0;
202+
195203
np = kmalloc_obj(struct vlan_priority_tci_mapping);
196204
if (!np)
197205
return -ENOBUFS;

net/8021q/vlan_netlink.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
263263
for (pm = rcu_dereference_rtnl(vlan->egress_priority_map[i]); pm;
264264
pm = rcu_dereference_rtnl(pm->next)) {
265265
u16 vlan_qos = READ_ONCE(pm->vlan_qos);
266-
267-
if (!vlan_qos)
268-
continue;
269-
270266
m.from = pm->priority;
271267
m.to = (vlan_qos >> 13) & 0x7;
272268
if (nla_put(skb, IFLA_VLAN_QOS_MAPPING,

0 commit comments

Comments
 (0)