Re: Problem with cls_flow nfct-* keys

Linux Advanced Routing and Traffic Control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Finally I have working patch, but I need somebody to look at it, and help to send it to developers. Can someone?


30.11.2015, 13:40, "Гаврилов Игорь" <iggorok@xxxxxxxxx>:
> Hi everyone! I've discovered some issues with cls_flow nfct-* keys. I have a router with NAT and clients behind it. All incoming traffic from WAN interface is redirecting to ifb0 device. With HTB qdisc.
> I Am install SFQ qdisc 99:0 with flow classifyer and nfct-dst key on HTB deafault leaf class (1:99) :
>
>     tc qdisc add dev eth0 ingress
>     tc filter add dev eth0 parent ffff: protocol all pref 100 u32 match u32 0 0 action mirred egress redirect dev ifb0
>
>     tc qdisc add dev ifb0 root handle 1: htb default 99 r2q 10
>     tc class add dev ifb0 parent 1: classid 1:1 htb rate 10Mbit
>
>     tc class add dev ifb0 parent 1:1 classid 1:99 htb rate 2mbit ceil 10Mbit burst 150k prio 7
>     tc qdisc add dev ifb0 parent 1:99 handle 99: sfq limit 10240
>     tc filter add dev ifb0 parent 99: protocol all handle 1 flow map key nfct-dst and 0xff divisor 1024
>
> I am trying to achieve equal bandwidth sharing between internal IPs, so that single IP could not get all free bandwidth with Torrent. But it doesn't work. After investigation I've discovered, that all incoming traffic,
> that hit default HTB class (1:99), goes to SFQ class 99:1f, which equals to WAN IP of my router *.*.*.30, so I see that nfct-dst key behaves like a simple dst. Is there any chance to fix it?
> --
> To unsubscribe from this list: send the line "unsubscribe lartc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--- cls_flow.c	2015-11-02 02:05:25.000000000 +0200
+++ net/sched/cls_flow.c	2015-12-07 12:32:56.767127200 +0200
@@ -30,6 +30,8 @@
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_zones.h>
 #endif
 
 struct flow_head {
@@ -132,16 +134,42 @@
 }
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-#define CTTUPLE(skb, member)						\
+#define CTTUPLE(skb, direction, member)						\
 ({									\
 	enum ip_conntrack_info ctinfo;					\
+	struct nf_conntrack_tuple tuple;				\
+	struct nf_conntrack_zone zone;					\
+	const struct nf_conntrack_tuple_hash *thash;			\
+	__be32 result;							\
+	int proto;							\
 	const struct nf_conn *ct = nf_ct_get(skb, &ctinfo);		\
-	if (ct == NULL)							\
-		goto fallback;						\
-	ct->tuplehash[CTINFO2DIR(ctinfo)].tuple.member;			\
+	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;	\
+	} 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 +180,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 +190,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 +203,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);
 }

[Index of Archives]     [LARTC Home Page]     [Netfilter]     [Netfilter Development]     [Network Development]     [Bugtraq]     [GCC Help]     [Yosemite News]     [Linux Kernel]     [Fedora Users]
  Powered by Linux