diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 12:07:22 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-10 22:15:01 -0700 |
commit | b020cb488586f982f40eb257a32e92a4de710d65 (patch) | |
tree | a6476a48f969688256079c53b02d8ab20e1d7719 | |
parent | 734423cf38021966a5d3bd5f5c6aaecaf32fb4ac (diff) |
[VLAN]: Keep track of number of QoS mappings
Keep track of the number of configured ingress/egress QoS mappings to
avoid iteration while calculating the netlink attribute size.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/if_vlan.h | 3 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 27 |
2 files changed, 24 insertions, 6 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index aeddb49193f9..b46d4225f74e 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -112,7 +112,10 @@ struct vlan_dev_info { /** This will be the mapping that correlates skb->priority to * 3 bits of VLAN QOS tags... */ + unsigned int nr_ingress_mappings; u32 ingress_priority_map[8]; + + unsigned int nr_egress_mappings; struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */ unsigned short vlan_id; /* The VLAN Identifier for this interface. */ diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 05a23601f670..4f6ede752a37 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -537,35 +537,50 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, short vlan_prio) { - VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; + struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); + + if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio) + vlan->nr_ingress_mappings--; + else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio) + vlan->nr_ingress_mappings++; + + vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio; } int vlan_dev_set_egress_priority(const struct net_device *dev, u32 skb_prio, short vlan_prio) { + struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); struct vlan_priority_tci_mapping *mp = NULL; struct vlan_priority_tci_mapping *np; + u32 vlan_qos = (vlan_prio << 13) & 0xE000; /* See if a priority mapping exists.. */ - mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; + mp = vlan->egress_priority_map[skb_prio & 0xF]; while (mp) { if (mp->priority == skb_prio) { - mp->vlan_qos = ((vlan_prio << 13) & 0xE000); + if (mp->vlan_qos && !vlan_qos) + vlan->nr_egress_mappings--; + else if (!mp->vlan_qos && vlan_qos) + vlan->nr_egress_mappings++; + mp->vlan_qos = vlan_qos; return 0; } mp = mp->next; } /* Create a new mapping then. */ - mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; + mp = vlan->egress_priority_map[skb_prio & 0xF]; np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); if (!np) return -ENOBUFS; np->next = mp; np->priority = skb_prio; - np->vlan_qos = ((vlan_prio << 13) & 0xE000); - VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np; + np->vlan_qos = vlan_qos; + vlan->egress_priority_map[skb_prio & 0xF] = np; + if (vlan_qos) + vlan->nr_egress_mappings++; return 0; } |