[PATCH v5 net-next] net:sched: add action inheritdsfield to skbedit

2018-06-26 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v5:
*Update the drop counter for TC_ACT_SHOT

v4:
*Not allow setting flags other than the expected ones.

*Allow dumping the pure flags.

v3:
*Use optional flags, so that it won't break old versions of tc.

*Allow users to set both SKBEDIT_F_PRIORITY and SKBEDIT_F_INHERITDSFIELD flags.

v2:
*Fix the style issue

*Move the code from skbmod to skbedit

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
Acked-by: Jamal Hadi Salim 
Reviewed-by: Marcelo Ricardo Leitner 
Acked-by: Davide Caratti 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a4e6c..6de6071ebed6 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
#define SKBEDIT_F_MARK  0x4
#define SKBEDIT_F_PTYPE 0x8
#define SKBEDIT_F_MASK  0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20

struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
};
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d71900..dfaf5d8028dd 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
#include 
#include 
#include 
+#include 
+#include 
+#include 

#include 
#include 
@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,

if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +75,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,

spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   d->tcf_qstats.drops++;
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
}

static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -62,6 +89,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX 
+ 1] = {
[TCA_SKBEDIT_MARK]  = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK]  = { .len = sizeof(u32) },
+   [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
};

static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -114,6 +142,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
}

+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   u64 *pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
+
+   if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
+   flags |= SKBEDIT_F_INHERITDSFIELD;
+   }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);

exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -178,6 +213,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
.action  = d->tcf_action,
};
struct tcf_t t;
+   u64 pure_flags = 0;

if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), ))
goto nla_put_failure;
@@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
if ((d->flags & SKBEDIT_F_MASK) &&
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
goto nla_put_failure;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD)
+   pure_flags |= SKBEDIT_F_INHERITDSFIELD;
+   if (pure_flags != 0 &&
+   nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), _flags))
+   goto nla_put_failure;

tcf_tm_dump(, >tcf_tm);
if (nla_put_64bit(skb, 

[PATCH v5 net-next] net:sched: add action inheritdsfield to skbedit

2018-06-21 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v5:
*Update the drop counter for TC_ACT_SHOT

v4:
*Not allow setting flags other than the expected ones.

*Allow dumping the pure flags.

v3:
*Use optional flags, so that it won't break old versions of tc.

*Allow users to set both SKBEDIT_F_PRIORITY and SKBEDIT_F_INHERITDSFIELD flags.

v2:
*Fix the style issue

*Move the code from skbmod to skbedit

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
Acked-by: Jamal Hadi Salim 
Reviewed-by: Marcelo Ricardo Leitner 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a4e6c..6de6071ebed6 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d71900..dfaf5d8028dd 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +75,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   d->tcf_qstats.drops++;
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
 }
 
 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -62,6 +89,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX 
+ 1] = {
[TCA_SKBEDIT_MARK]  = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK]  = { .len = sizeof(u32) },
+   [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -114,6 +142,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
}
 
+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   u64 *pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
+
+   if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
+   flags |= SKBEDIT_F_INHERITDSFIELD;
+   }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -178,6 +213,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
.action  = d->tcf_action,
};
struct tcf_t t;
+   u64 pure_flags = 0;
 
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), ))
goto nla_put_failure;
@@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
if ((d->flags & SKBEDIT_F_MASK) &&
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
goto nla_put_failure;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD)
+   pure_flags |= SKBEDIT_F_INHERITDSFIELD;
+   if (pure_flags != 0 &&
+   nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), _flags))
+   goto nla_put_failure;
 
tcf_tm_dump(, >tcf_tm);
if (nla_put_64bit(skb, 

Re: [PATCH v4 net-next] net:sched: add action inheritdsfield to skbedit

2018-06-21 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v5:
*Update the drop counter for TC_ACT_SHOT.

v4:
*Not allow setting flags other than the expected ones.

*Allow dumping the pure flags.

v3:
*Use optional flags, so that it won't break old versions of tc.

*Allow users to set both SKBEDIT_F_PRIORITY and SKBEDIT_F_INHERITDSFIELD flags.

v2:
*Fix the style issue

*Move the code from skbmod to skbedit

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
Acked-by: Jamal Hadi Salim 
Reviewed-by: Marcelo Ricardo Leitner 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a4e6c..6de6071ebed6 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d71900..dfaf5d8028dd 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +75,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   d->tcf_qstats.drops++;
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
 }
 
 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -62,6 +89,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX 
+ 1] = {
[TCA_SKBEDIT_MARK]  = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK]  = { .len = sizeof(u32) },
+   [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -114,6 +142,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
}
 
+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   u64 *pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
+
+   if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
+   flags |= SKBEDIT_F_INHERITDSFIELD;
+   }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -178,6 +213,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
.action  = d->tcf_action,
};
struct tcf_t t;
+   u64 pure_flags = 0;
 
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), ))
goto nla_put_failure;
@@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
if ((d->flags & SKBEDIT_F_MASK) &&
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
goto nla_put_failure;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD)
+   pure_flags |= SKBEDIT_F_INHERITDSFIELD;
+   if (pure_flags != 0 &&
+   nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), _flags))
+   goto nla_put_failure;
 
tcf_tm_dump(, >tcf_tm);
if (nla_put_64bit(skb, 

[PATCH v4 net-next] net:sched: add action inheritdsfield to skbedit

2018-06-12 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v4:
*Not allow setting flags other than the expected ones.

*Allow dumping the pure flags.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a4e6c..6de6071ebed6 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d71900..9adbcfa3f5fe 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +75,10 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
 }
 
 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -62,6 +88,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX 
+ 1] = {
[TCA_SKBEDIT_MARK]  = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK]  = { .len = sizeof(u32) },
+   [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -73,6 +100,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
struct tc_skbedit *parm;
struct tcf_skbedit *d;
u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL;
+   u64 *pure_flags = NULL;
u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false;
int ret = 0, err;
@@ -114,6 +142,12 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
}
 
+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
+   if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
+   flags |= SKBEDIT_F_INHERITDSFIELD;
+   }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -178,6 +212,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
.action  = d->tcf_action,
};
struct tcf_t t;
+   u64 pure_flags = 0;
 
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), ))
goto nla_put_failure;
@@ -196,6 +231,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct 
tc_action *a,
if ((d->flags & SKBEDIT_F_MASK) &&
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
goto nla_put_failure;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD)
+   pure_flags |= SKBEDIT_F_INHERITDSFIELD;
+   if (pure_flags != 0 &&
+   nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), _flags))
+   goto nla_put_failure;
 
tcf_tm_dump(, >tcf_tm);
if (nla_put_64bit(skb, 

Re: [PATCH v2 iproute2] net:sched: add action inheritdsfield to skbedit

2018-06-09 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v2:
*Use optional flags, so that it won't break old versions of tc.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a..6de6071e 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/tc/m_skbedit.c b/tc/m_skbedit.c
index db5c64ca..b7f27f09 100644
--- a/tc/m_skbedit.c
+++ b/tc/m_skbedit.c
@@ -30,16 +30,18 @@
 
 static void explain(void)
 {
-   fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n"
+   fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
"QM = queue_mapping QUEUE_MAPPING\n"
"PM = priority PRIORITY\n"
"MM = mark MARK\n"
"PT = ptype PACKETYPE\n"
+   "IF = inheritdsfield\n"
"PACKETYPE = is one of:\n"
"  host, otherhost, broadcast, multicast\n"
"QUEUE_MAPPING = device transmit queue to use\n"
"PRIORITY = classID to assign to priority field\n"
-   "MARK = firewall mark to set\n");
+   "MARK = firewall mark to set\n"
+   "note: inheritdsfield maps DS field to skb->priority\n");
 }
 
 static void
@@ -60,6 +62,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
unsigned int tmp;
__u16 queue_mapping, ptype;
__u32 flags = 0, priority, mark;
+   __u64 pure_flags = 0;
struct tc_skbedit sel = { 0 };
 
if (matches(*argv, "skbedit") != 0)
@@ -111,6 +114,9 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
}
flags |= SKBEDIT_F_PTYPE;
ok++;
+   } else if (matches(*argv, "inheritdsfield") == 0) {
+   pure_flags |= SKBEDIT_F_INHERITDSFIELD;
+   ok++;
} else if (matches(*argv, "help") == 0) {
usage();
} else {
@@ -156,6 +162,9 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
if (flags & SKBEDIT_F_PTYPE)
addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
  , sizeof(ptype));
+   if (pure_flags != 0)
+   addattr_l(n, MAX_MSG, TCA_SKBEDIT_FLAGS,
+ _flags, sizeof(pure_flags));
addattr_nest_end(n, tail);
 
*argc_p = argc;
@@ -171,6 +180,7 @@ static int print_skbedit(struct action_util *au, FILE *f, 
struct rtattr *arg)
__u32 *priority;
__u32 *mark;
__u16 *queue_mapping, *ptype;
+   __u64 *flags;
struct tc_skbedit *p = NULL;
 
if (arg == NULL)
@@ -211,6 +221,11 @@ static int print_skbedit(struct action_util *au, FILE *f, 
struct rtattr *arg)
else
fprintf(f, " ptype %d", *ptype);
}
+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   flags = RTA_DATA(tb[TCA_SKBEDIT_FLAGS]);
+   if (*flags & SKBEDIT_F_INHERITDSFIELD)
+   fprintf(f, "inherit DS field ");
+   }
 
print_action_control(f, " ", p->action, "");
 



[PATCH v3 net-next] net:sched: add action inheritdsfield to skbedit

2018-06-09 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

v3:
*Use optional flags, so that it won't break old versions of tc.

*Allow users to set both SKBEDIT_F_PRIORITY and SKBEDIT_F_INHERITDSFIELD flags.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---
diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27a4e6c..6de6071ebed6 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,6 +30,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK,
+   TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d71900..ef479cd37e7b 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +75,10 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
 }
 
 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -62,6 +88,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX 
+ 1] = {
[TCA_SKBEDIT_MARK]  = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK]  = { .len = sizeof(u32) },
+   [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -73,6 +100,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
struct tc_skbedit *parm;
struct tcf_skbedit *d;
u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL;
+   u64 *pure_flags = NULL;
u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false;
int ret = 0, err;
@@ -114,6 +142,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
}
 
+   if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
+   pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
+   flags |= *pure_flags;
+   }
+
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);

[PATCH iproute2] net:sched: add action inheritdsfield to skbedit

2018-05-27 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---

diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27..432ad2f 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,9 +30,11 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
+   __u64 flags;
 };
 
 enum {
diff --git a/tc/m_skbedit.c b/tc/m_skbedit.c
index db5c64c..7553a40 100644
--- a/tc/m_skbedit.c
+++ b/tc/m_skbedit.c
@@ -30,16 +30,18 @@
 
 static void explain(void)
 {
-   fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n"
+   fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
"QM = queue_mapping QUEUE_MAPPING\n"
"PM = priority PRIORITY\n"
"MM = mark MARK\n"
"PT = ptype PACKETYPE\n"
+   "IF = inheritdsfield\n"
"PACKETYPE = is one of:\n"
"  host, otherhost, broadcast, multicast\n"
"QUEUE_MAPPING = device transmit queue to use\n"
"PRIORITY = classID to assign to priority field\n"
-   "MARK = firewall mark to set\n");
+   "MARK = firewall mark to set\n"
+   "note: inheritdsfield maps DS field to skb->priority\n");
 }
 
 static void
@@ -59,7 +61,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
struct rtattr *tail;
unsigned int tmp;
__u16 queue_mapping, ptype;
-   __u32 flags = 0, priority, mark;
+   __u32 priority, mark;
struct tc_skbedit sel = { 0 };
 
if (matches(*argv, "skbedit") != 0)
@@ -69,7 +71,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
 
while (argc > 0) {
if (matches(*argv, "queue_mapping") == 0) {
-   flags |= SKBEDIT_F_QUEUE_MAPPING;
+   sel.flags |= SKBEDIT_F_QUEUE_MAPPING;
NEXT_ARG();
if (get_unsigned(, *argv, 10) || tmp > 65535) {
fprintf(stderr, "Illegal queue_mapping\n");
@@ -78,7 +80,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
queue_mapping = tmp;
ok++;
} else if (matches(*argv, "priority") == 0) {
-   flags |= SKBEDIT_F_PRIORITY;
+   sel.flags |= SKBEDIT_F_PRIORITY;
NEXT_ARG();
if (get_tc_classid(, *argv)) {
fprintf(stderr, "Illegal priority\n");
@@ -86,7 +88,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
}
ok++;
} else if (matches(*argv, "mark") == 0) {
-   flags |= SKBEDIT_F_MARK;
+   sel.flags |= SKBEDIT_F_MARK;
NEXT_ARG();
if (get_u32(, *argv, 0)) {
fprintf(stderr, "Illegal mark\n");
@@ -109,7 +111,10 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
*argv);
return -1;
}
-   flags |= SKBEDIT_F_PTYPE;
+   sel.flags |= SKBEDIT_F_PTYPE;
+   ok++;
+   } else if (matches(*argv, "inheritdsfield") == 0) {
+   sel.flags |= SKBEDIT_F_INHERITDSFIELD;
ok++;
} else if (matches(*argv, "help") == 0) {
usage();
@@ -144,16 +149,16 @@ parse_skbedit(struct action_util *a, int *argc_p, char 
***argv_p, int tca_id,
 
tail = addattr_nest(n, MAX_MSG, tca_id);
addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, , sizeof(sel));
-   if (flags & SKBEDIT_F_QUEUE_MAPPING)
+   if (sel.flags & SKBEDIT_F_QUEUE_MAPPING)
addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
  _mapping, sizeof(queue_mapping));
-   if (flags & SKBEDIT_F_PRIORITY)
+   if (sel.flags & SKBEDIT_F_PRIORITY)
addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
  , sizeof(priority));
-   if (flags & SKBEDIT_F_MARK)
+   if (sel.flags & 

[PATCH v2 net-next] net:sched: add action inheritdsfield to skbedit

2018-05-27 Thread Fu, Qiaobin
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---

diff --git a/include/uapi/linux/tc_act/tc_skbedit.h 
b/include/uapi/linux/tc_act/tc_skbedit.h
index fbcfe27..432ad2f 100644
--- a/include/uapi/linux/tc_act/tc_skbedit.h
+++ b/include/uapi/linux/tc_act/tc_skbedit.h
@@ -30,9 +30,11 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD   0x20
 
 struct tc_skbedit {
tc_gen;
+   __u64 flags;
 };
 
 enum {
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6138d1d7..c3e9d03 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -23,6 +23,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -39,8 +42,32 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
tcf_lastuse_update(>tcf_tm);
bstats_update(>tcf_bstats, skb);
 
-   if (d->flags & SKBEDIT_F_PRIORITY)
-   skb->priority = d->priority;
+   if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   goto err;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+
+   default:
+   goto default_priority;
+   }
+   } else {
+default_priority:
+   if (d->flags & SKBEDIT_F_PRIORITY)
+   skb->priority = d->priority;
+   }
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, d->queue_mapping);
@@ -53,6 +80,10 @@ static int tcf_skbedit(struct sk_buff *skb, const struct 
tc_action *a,
 
spin_unlock(>tcf_lock);
return d->tcf_action;
+
+err:
+   spin_unlock(>tcf_lock);
+   return TC_ACT_SHOT;
 }
 
 static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
@@ -115,6 +146,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr 
*nla,
}
 
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
+   if (parm->flags & SKBEDIT_F_INHERITDSFIELD)
+   flags |= SKBEDIT_F_INHERITDSFIELD;
 
exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)

Re: [PATCH net-next] net:sched: add action inheritdsfield to skbmod

2018-05-24 Thread Fu, Qiaobin
Hi Marcelo,

Thanks for pointing out these style issues. Below is the updated version:

---
The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->priority. This enables
later classification of packets based on the DS field.

Original idea by Jamal Hadi Salim <j...@mojatatu.com>

Signed-off-by: Qiaobin Fu <qiaob...@bu.edu>
Reviewed-by: Michel Machado <mic...@digirati.com.br>
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---

diff --git a/include/uapi/linux/tc_act/tc_skbmod.h 
b/include/uapi/linux/tc_act/tc_skbmod.h
index 38c072f..0718b48 100644
--- a/include/uapi/linux/tc_act/tc_skbmod.h
+++ b/include/uapi/linux/tc_act/tc_skbmod.h
@@ -19,6 +19,7 @@
 #define SKBMOD_F_SMAC  0x2
 #define SKBMOD_F_ETYPE 0x4
 #define SKBMOD_F_SWAPMAC 0x8
+#define SKBMOD_F_INHERITDSFIELD 0x10
 
 struct tc_skbmod {
tc_gen;
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index ad050d7..e2082f6 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -16,6 +16,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -72,6 +75,26 @@ static int tcf_skbmod_run(struct sk_buff *skb, const struct 
tc_action *a,
ether_addr_copy(eth_hdr(skb)->h_source, (u8 *)tmpaddr);
}
 
+   if (flags & SKBMOD_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   return TC_ACT_SHOT;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   return TC_ACT_SHOT;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
+
return action;
 }
 
@@ -127,6 +150,9 @@ static int tcf_skbmod_init(struct net *net, struct nlattr 
*nla,
if (parm->flags & SKBMOD_F_SWAPMAC)
lflags = SKBMOD_F_SWAPMAC;
 
+   if (parm->flags & SKBMOD_F_INHERITDSFIELD)
+   lflags |= SKBMOD_F_INHERITDSFIELD;
+
exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;

> On May 23, 2018, at 2:06 PM, Marcelo Ricardo Leitner 
> <marcelo.leit...@gmail.com> wrote:
> 
> Hi,
> 
> Some style fixes:
> 
> On Thu, May 17, 2018 at 07:33:08PM +, Fu, Qiaobin wrote:
>> net/sched: add action inheritdsfield to skbmod
> 
> This extra line above should not be here.
> 
>> 
>> The new action inheritdsfield copies the field DS of
>> IPv4 and IPv6 packets into skb->prioriry. This enables
>  typo -^
> 
>> later classification of packets based on the DS field.
>> 
>> Original idea by Jamal Hadi Salim <j...@mojatatu.com>
>> 
>> Signed-off-by: Qiaobin Fu <qiaob...@bu.edu>
>> Reviewed-by: Michel Machado <mic...@digirati.com.br>
>> ---
>> 
>> Note that the motivation for this patch is found in the following discussion:
>> https://www.spinics.net/lists/netdev/msg501061.html
>> ---
>> 
>> diff --git a/include/uapi/linux/tc_act/tc_skbmod.h 
>> b/include/uapi/linux/tc_act/tc_skbmod.h
>> index 38c072f..0718b48 100644
>> --- a/include/uapi/linux/tc_act/tc_skbmod.h
>> +++ b/include/uapi/linux/tc_act/tc_skbmod.h
>> @@ -19,6 +19,7 @@
>> #define SKBMOD_F_SMAC0x2
>> #define SKBMOD_F_ETYPE   0x4
>> #define SKBMOD_F_SWAPMAC 0x8
>> +#define SKBMOD_F_INHERITDSFIELD 0x10
>> 
>> struct tc_skbmod {
>>  tc_gen;
>> diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
>> index ad050d7..21d5bec 100644
>> --- a/net/sched/act_skbmod.c
>> +++ b/net/sched/act_skbmod.c
>> @@ -16,6 +16,9 @@
>> #include 
>> #include 
>> #include 
>> +#include 
>> +#include 
>> +#include 
>> 
>> #include 
>> #include 
>> @@ -72,6 +75,25 @@ static int tcf_skbmod_run(struct sk_buff *skb, const 
>> struct tc_action *a,
>>  ether_addr_copy(eth_hdr(skb)->h_source, (u8 *)tmpaddr);
>>  }
>> 
>> +if (flags & SKBMOD_F_INHERITDSFIELD) {
>> +int wlen = skb_network_offset(skb);
> 
> You need a blank line here, between var declaration and the rest.
> 

[PATCH net-next] net:sched: add action inheritdsfield to skbmod

2018-05-17 Thread Fu, Qiaobin
net/sched: add action inheritdsfield to skbmod

The new action inheritdsfield copies the field DS of
IPv4 and IPv6 packets into skb->prioriry. This enables
later classification of packets based on the DS field.

Original idea by Jamal Hadi Salim 

Signed-off-by: Qiaobin Fu 
Reviewed-by: Michel Machado 
---

Note that the motivation for this patch is found in the following discussion:
https://www.spinics.net/lists/netdev/msg501061.html
---

diff --git a/include/uapi/linux/tc_act/tc_skbmod.h 
b/include/uapi/linux/tc_act/tc_skbmod.h
index 38c072f..0718b48 100644
--- a/include/uapi/linux/tc_act/tc_skbmod.h
+++ b/include/uapi/linux/tc_act/tc_skbmod.h
@@ -19,6 +19,7 @@
 #define SKBMOD_F_SMAC  0x2
 #define SKBMOD_F_ETYPE 0x4
 #define SKBMOD_F_SWAPMAC 0x8
+#define SKBMOD_F_INHERITDSFIELD 0x10
 
 struct tc_skbmod {
tc_gen;
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index ad050d7..21d5bec 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -16,6 +16,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -72,6 +75,25 @@ static int tcf_skbmod_run(struct sk_buff *skb, const struct 
tc_action *a,
ether_addr_copy(eth_hdr(skb)->h_source, (u8 *)tmpaddr);
}
 
+   if (flags & SKBMOD_F_INHERITDSFIELD) {
+   int wlen = skb_network_offset(skb);
+   switch (tc_skb_protocol(skb)) {
+   case htons(ETH_P_IP):
+   wlen += sizeof(struct iphdr);
+   if (!pskb_may_pull(skb, wlen))
+   return TC_ACT_SHOT;
+   skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+   break;
+
+   case htons(ETH_P_IPV6):
+   wlen += sizeof(struct ipv6hdr);
+   if (!pskb_may_pull(skb, wlen))
+   return TC_ACT_SHOT;
+   skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+   break;
+   }
+   }
+
return action;
 }
 
@@ -127,6 +149,9 @@ static int tcf_skbmod_init(struct net *net, struct nlattr 
*nla,
if (parm->flags & SKBMOD_F_SWAPMAC)
lflags = SKBMOD_F_SWAPMAC;
 
+   if (parm->flags & SKBMOD_F_INHERITDSFIELD)
+   lflags |= SKBMOD_F_INHERITDSFIELD;
+
exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;