--- cls_flow.c 2015-11-02 02:05:25.000000000 +0200 +++ net/sched/cls_flow.c 2015-12-10 17:04:03.075202330 +0200 @@ -30,6 +30,8 @@ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #include +#include +#include #endif struct flow_head { @@ -132,16 +134,43 @@ } #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) -#define CTTUPLE(skb, member) \ +#define CTTUPLE(skb, direction, member) \ ({ \ enum ip_conntrack_info ctinfo; \ - const struct nf_conn *ct = nf_ct_get(skb, &ctinfo); \ - if (ct == NULL) \ - goto fallback; \ - ct->tuplehash[CTINFO2DIR(ctinfo)].tuple.member; \ + struct nf_conntrack_tuple tuple; \ + struct nf_conntrack_zone zone; \ + const struct nf_conntrack_tuple_hash *thash; \ + __be32 result; \ + int proto; \ + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); \ + if (ct == NULL){ \ + switch (tc_skb_protocol(skb)) { \ + case htons(ETH_P_IP): \ + proto = NFPROTO_IPV4; \ + break; \ + case htons(ETH_P_IPV6): \ + proto = NFPROTO_IPV6; \ + break; \ + default: goto fallback; \ + } \ + \ + if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, &tuple)) \ + goto fallback; \ + zone.id = NF_CT_DEFAULT_ZONE_ID; \ + zone.dir = NF_CT_DEFAULT_ZONE_DIR; \ + \ + thash = nf_conntrack_find_get(dev_net(skb->dev), &zone, &tuple);\ + if (!thash) goto fallback; \ + ct = nf_ct_tuplehash_to_ctrack(thash); \ + result = ct->tuplehash[(thash->tuple.dst.dir == IP_CT_DIR_REPLY) ? IP_CT_DIR_ORIGINAL : IP_CT_DIR_REPLY].tuple.src.member; \ + nf_ct_put(ct); \ + } else { \ + result = ct->tuplehash[CTINFO2DIR(ctinfo)].tuple.direction.member; \ + } \ + result; \ }) #else -#define CTTUPLE(skb, member) \ +#define CTTUPLE(skb, direction, member) \ ({ \ goto fallback; \ 0; \ @@ -152,9 +181,9 @@ { switch (tc_skb_protocol(skb)) { case htons(ETH_P_IP): - return ntohl(CTTUPLE(skb, src.u3.ip)); + return ntohl(CTTUPLE(skb, src, u3.ip)); case htons(ETH_P_IPV6): - return ntohl(CTTUPLE(skb, src.u3.ip6[3])); + return ntohl(CTTUPLE(skb, src, u3.ip6[3])); } fallback: return flow_get_src(skb, flow); @@ -162,11 +191,12 @@ static u32 flow_get_nfct_dst(const struct sk_buff *skb, const struct flow_keys *flow) { + switch (tc_skb_protocol(skb)) { case htons(ETH_P_IP): - return ntohl(CTTUPLE(skb, dst.u3.ip)); + return ntohl(CTTUPLE(skb, dst, u3.ip)); case htons(ETH_P_IPV6): - return ntohl(CTTUPLE(skb, dst.u3.ip6[3])); + return ntohl(CTTUPLE(skb, dst, u3.ip6[3])); } fallback: return flow_get_dst(skb, flow); @@ -174,14 +204,14 @@ static u32 flow_get_nfct_proto_src(const struct sk_buff *skb, const struct flow_keys *flow) { - return ntohs(CTTUPLE(skb, src.u.all)); + return ntohs(CTTUPLE(skb, src, u.all)); fallback: return flow_get_proto_src(skb, flow); } static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb, const struct flow_keys *flow) { - return ntohs(CTTUPLE(skb, dst.u.all)); + return ntohs(CTTUPLE(skb, dst, u.all)); fallback: return flow_get_proto_dst(skb, flow); }