* [PATCH v2] VLAN, support ingress/egress priority map flushing
@ 2017-03-13 14:36 Thierry Du Tre
2017-03-13 15:28 ` Eric Dumazet
0 siblings, 1 reply; 3+ messages in thread
From: Thierry Du Tre @ 2017-03-13 14:36 UTC (permalink / raw)
To: netdev; +Cc: Ben Greear
When sending packets via a vlan device we can manipulate the priority bits in the vlan header (PCP) via a mapping based on tc class value.
Similarly, when packets are received via a vlan device, the PCP value can be mapped onto a tc class value, which is available for iptables rules and tc queueing disciplines.
One can use the vconfig utility to set both ingress and egress mapping entries (set_ingress_map/set_egress_map) or any other application to call the vlan ioctl handler.
The resulting map can be printed via /proc/net/vlan/<ifname> , i.e. :
# cat /proc/net/vlan/vlan11
vlan11 VID: 11 REORDER_HDR: 1 dev->priv_flags: 1
total frames received 52331849
total bytes received 17451834908
Broadcast/Multicast Rcvd 1525155
total frames transmitted 98569270
total bytes transmitted 144870211289
Device: eth_test
INGRESS priority mappings: 0:0 1:1 2:2 3:3 4:0 5:0 6:0 7:0
EGRESS priority mappings: 0:7
The current API offers only GET and SET operations, and when actually using this functionality a flush is missing to reset all entries.
This patch adds a FLUSH operation for both ingress and egress map which can then be used by vconfig or other applications.
Signed-off-by: Thierry Du Tre <thierry@dtsystems.be>
---
Changes in v2:
- Move new vlan cmd values to end of enum list.
include/uapi/linux/if_vlan.h | 4 +++-
net/8021q/vlan.c | 16 ++++++++++++++++
net/8021q/vlan.h | 2 ++
net/8021q/vlan_dev.c | 23 +++++++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/if_vlan.h b/include/uapi/linux/if_vlan.h
index 7e5e6b3..8daea77 100644
--- a/include/uapi/linux/if_vlan.h
+++ b/include/uapi/linux/if_vlan.h
@@ -27,7 +27,9 @@ enum vlan_ioctl_cmds {
SET_VLAN_NAME_TYPE_CMD,
SET_VLAN_FLAG_CMD,
GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
- GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
+ GET_VLAN_VID_CMD, /* Get the VID of this VLAN (specified by name) */
+ FLUSH_VLAN_INGRESS_PRIORITY_CMD,
+ FLUSH_VLAN_EGRESS_PRIORITY_CMD
};
enum vlan_flags {
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 467069b..8988419 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -539,6 +539,22 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
}
switch (args.cmd) {
+ case FLUSH_VLAN_INGRESS_PRIORITY_CMD:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ break;
+ vlan_dev_flush_ingress_priority(dev);
+ err = 0;
+ break;
+
+ case FLUSH_VLAN_EGRESS_PRIORITY_CMD:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ break;
+ vlan_dev_flush_egress_priority(dev);
+ err = 0;
+ break;
+
case SET_VLAN_INGRESS_PRIORITY_CMD:
err = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index df8bd65..d8d90ca 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -97,6 +97,8 @@ static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
(i) % VLAN_N_VID)))
/* found in vlan_dev.c */
+void vlan_dev_flush_ingress_priority(const struct net_device *dev);
+void vlan_dev_flush_egress_priority(const struct net_device *dev);
void vlan_dev_set_ingress_priority(const struct net_device *dev,
u32 skb_prio, u16 vlan_prio);
int vlan_dev_set_egress_priority(const struct net_device *dev,
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index e97ab82..8fd91c3 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -159,6 +159,29 @@ static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+void vlan_dev_flush_ingress_priority(const struct net_device *dev)
+{
+ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+
+ memset(vlan->ingress_priority_map, 0, sizeof(vlan->ingress_priority_map));
+ vlan->nr_ingress_mappings = 0;
+}
+
+void vlan_dev_flush_egress_priority(const struct net_device *dev)
+{
+ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+ struct vlan_priority_tci_mapping *mp;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
+ while ((mp = vlan->egress_priority_map[i]) != NULL) {
+ vlan->egress_priority_map[i] = mp->next;
+ kfree(mp);
+ }
+ }
+ vlan->nr_egress_mappings = 0;
+}
+
void vlan_dev_set_ingress_priority(const struct net_device *dev,
u32 skb_prio, u16 vlan_prio)
{
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] VLAN, support ingress/egress priority map flushing
2017-03-13 14:36 [PATCH v2] VLAN, support ingress/egress priority map flushing Thierry Du Tre
@ 2017-03-13 15:28 ` Eric Dumazet
2017-03-13 20:33 ` Thierry Du Tre
0 siblings, 1 reply; 3+ messages in thread
From: Eric Dumazet @ 2017-03-13 15:28 UTC (permalink / raw)
To: Thierry Du Tre; +Cc: netdev, Ben Greear
On Mon, 2017-03-13 at 15:36 +0100, Thierry Du Tre wrote:
> +void vlan_dev_flush_egress_priority(const struct net_device *dev)
> +{
> + struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
> + struct vlan_priority_tci_mapping *mp;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
> + while ((mp = vlan->egress_priority_map[i]) != NULL) {
> + vlan->egress_priority_map[i] = mp->next;
> + kfree(mp);
> + }
> + }
> + vlan->nr_egress_mappings = 0;
> +}
Are you doing this on a live device ?
Looks you'll need proper RCU support then.
Otherwise, crashes will happen, say in egress_priority_map()
smp_rmb() wont be enough if items can now be destroyed.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] VLAN, support ingress/egress priority map flushing
2017-03-13 15:28 ` Eric Dumazet
@ 2017-03-13 20:33 ` Thierry Du Tre
0 siblings, 0 replies; 3+ messages in thread
From: Thierry Du Tre @ 2017-03-13 20:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, Ben Greear
On 13-03-17 16:28, Eric Dumazet wrote:
> On Mon, 2017-03-13 at 15:36 +0100, Thierry Du Tre wrote:
>
>> +void vlan_dev_flush_egress_priority(const struct net_device *dev)
>> +{
>> + struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
>> + struct vlan_priority_tci_mapping *mp;
>> + int i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
>> + while ((mp = vlan->egress_priority_map[i]) != NULL) {
>> + vlan->egress_priority_map[i] = mp->next;
>> + kfree(mp);
>> + }
>> + }
>> + vlan->nr_egress_mappings = 0;
>> +}
>
> Are you doing this on a live device ?
>
> Looks you'll need proper RCU support then.
>
> Otherwise, crashes will happen, say in egress_priority_map()
>
> smp_rmb() wont be enough if items can now be destroyed.
Yes, good point about the smp concurrency.
I wrongly assumed there was already some locking mechanism in place to
protect these structures.
Let me take a look at this and I'll come back with a new proposal.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-03-13 20:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-13 14:36 [PATCH v2] VLAN, support ingress/egress priority map flushing Thierry Du Tre
2017-03-13 15:28 ` Eric Dumazet
2017-03-13 20:33 ` Thierry Du Tre
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).