[][MAC80211][hnat][Add DSCP offload support]
[Description]
Add DSCP offload support.
If without this patch, PPE driver cannot supports DSCP offload.
[Release-log]
N/A
Change-Id: Id8ab0cc86eb40b060eccd4488fa2926b40dd95e9
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7203713
diff --git a/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/9999-8-flow-offload-add-mtkhnat-dscp.patch b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/9999-8-flow-offload-add-mtkhnat-dscp.patch
new file mode 100644
index 0000000..fe278a7
--- /dev/null
+++ b/autobuild_mac80211_release/target/linux/mediatek/patches-5.4/9999-8-flow-offload-add-mtkhnat-dscp.patch
@@ -0,0 +1,169 @@
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+index c2416b1..bc13a9b 100755
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -435,6 +435,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+
+ return 0;
+ }
++
++int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
++{
++ u32 *ib2 = mtk_foe_entry_ib2(entry);
++
++ *ib2 &= ~MTK_FOE_IB2_DSCP;
++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
++
++ return 0;
++}
++
+ static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry)
+ {
+ return !(entry->ib1 & MTK_FOE_IB1_STATIC) &&
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
+index e7ecbf7..df10040 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
+@@ -430,6 +430,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+ int bss, int wcid);
+ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
++int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
+ int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+ void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index 23d2048..9bc0857 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -246,6 +246,7 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ int wed_index = -1;
+ u16 addr_type = 0;
+ u8 l4proto = 0;
++ u8 dscp = 0;
+ int err = 0;
+ int i;
+
+@@ -282,6 +283,15 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ return -EOPNOTSUPP;
+ }
+
++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
++ struct flow_match_ip match;
++
++ flow_rule_match_ip(rule, &match);
++ dscp = match.key->tos;
++ } else {
++ return -EOPNOTSUPP;
++ }
++
+ switch (addr_type) {
+ case 0:
+ offload_type = MTK_PPE_PKT_TYPE_BRIDGE;
+@@ -441,6 +451,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ if (data.pppoe.num == 1)
+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
+
++ mtk_foe_entry_set_dscp(&foe, dscp);
++
+ err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
+ &wed_index);
+ if (err)
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index 55359dd..1a23c03 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -36,6 +36,7 @@ struct nf_flow_key {
+ };
+ struct flow_dissector_key_tcp tcp;
+ struct flow_dissector_key_ports tp;
++ struct flow_dissector_key_ip ip;
+ } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
+
+ struct nf_flow_match {
+@@ -145,6 +146,7 @@ struct flow_offload_tuple {
+ u8 h_dest[ETH_ALEN];
+ } out;
+ };
++ u8 tos;
+ };
+
+ struct flow_offload_tuple_rhash {
+diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
+index 61cc518..c1a5f64 100644
+--- a/net/netfilter/nf_flow_table_offload.c
++++ b/net/netfilter/nf_flow_table_offload.c
+@@ -104,6 +104,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
++ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IP, ip);
+
+ if (other_dst && other_dst->lwtstate) {
+ tun_info = lwt_tun_info(other_dst->lwtstate);
+@@ -183,10 +184,14 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
+ key->tp.dst = tuple->dst_port;
+ mask->tp.dst = 0xffff;
+
++ key->ip.tos = tuple->tos;
++ mask->ip.tos = 0xff;
++
+ match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_META) |
+ BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+ BIT(FLOW_DISSECTOR_KEY_BASIC) |
+- BIT(FLOW_DISSECTOR_KEY_PORTS);
++ BIT(FLOW_DISSECTOR_KEY_PORTS) |
++ BIT(FLOW_DISSECTOR_KEY_IP);
+ return 0;
+ }
+
+diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
+index 2d5c3cc..b231dd7 100644
+--- a/net/netfilter/xt_FLOWOFFLOAD.c
++++ b/net/netfilter/xt_FLOWOFFLOAD.c
+@@ -49,6 +49,35 @@ static DEFINE_SPINLOCK(hooks_lock);
+
+ struct xt_flowoffload_table flowtable[2];
+
++static int
++xt_flowoffload_dscp_init(struct sk_buff *skb, struct flow_offload *flow,
++ enum ip_conntrack_dir dir)
++{
++ const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
++ struct iphdr *iph;
++ struct ipv6hdr *ip6h;
++ u32 offset = 0;
++ u8 tos = 0;
++
++ switch (flow_tuple->l3proto) {
++ case NFPROTO_IPV4:
++ iph = (struct iphdr *)(skb_network_header(skb) + offset);
++ tos = iph->tos;
++ break;
++ case NFPROTO_IPV6:
++ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
++ tos = ipv6_get_dsfield(ip6h);
++ break;
++ default:
++ return -1;
++ };
++
++ flow->tuplehash[dir].tuple.tos = tos;
++ flow->tuplehash[!dir].tuple.tos = tos;
++
++ return 0;
++}
++
+ static unsigned int
+ xt_flowoffload_net_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+@@ -599,6 +628,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+ if (flow_offload_route_init(flow, &route) < 0)
+ goto err_flow_add;
+
++ if (xt_flowoffload_dscp_init(skb, flow, dir) < 0)
++ goto err_flow_add;
++
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;