[PATCH net-next] net:sched: add action inheritdsfield to skbmod
From: Fu, Qiaobin <hidden>
Date: 2018-05-17 19:33:10
Subsystem:
networking [general], tc subsystem, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Jamal Hadi Salim, Jiri Pirko, Linus Torvalds
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 [off-list ref] Signed-off-by: Qiaobin Fu <redacted> Reviewed-by: Michel Machado <redacted> --- 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 <linux/rtnetlink.h> #include <net/netlink.h> #include <net/pkt_sched.h> +#include <net/ip.h> +#include <net/ipv6.h> +#include <net/dsfield.h> #include <linux/tc_act/tc_skbmod.h> #include <net/tc_act/tc_skbmod.h>
@@ -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;