Netdev List
 help / color / mirror / Atom feed
* Re: BQL + Basic Latency under load results - 100Mbit, GSO/TSO off, pfifo_fast vs SFQ vs QFQ
From: Eric Dumazet @ 2012-01-02  5:07 UTC (permalink / raw)
  To: Dave Taht
  Cc: jg, Stephen Hemminger, Juliusz Chroboczek, Kathleen Nichols,
	netdev
In-Reply-To: <1325480125.2526.13.camel@edumazet-laptop>

Le lundi 02 janvier 2012 à 05:55 +0100, Eric Dumazet a écrit :

> I tested this patch with a 50 concurrent netperf workload, and indeed
> this fixes the problem for me.
> 
> # ping 192.168.20.108
> PING 192.168.20.108 (192.168.20.108) 56(84) bytes of data.
> 64 bytes from 192.168.20.108: icmp_req=1 ttl=64 time=0.021 ms
> 64 bytes from 192.168.20.108: icmp_req=2 ttl=64 time=0.011 ms
> 64 bytes from 192.168.20.108: icmp_req=3 ttl=64 time=0.011 ms
> 64 bytes from 192.168.20.108: icmp_req=4 ttl=64 time=0.010 ms
> 64 bytes from 192.168.20.108: icmp_req=5 ttl=64 time=0.010 ms
> 64 bytes from 192.168.20.108: icmp_req=6 ttl=64 time=0.010 ms
> 

Oops, pinging a real machine, not myself I get more realistic numbers :)

# ping -c 20 192.168.20.112
PING 192.168.20.112 (192.168.20.112) 56(84) bytes of data.
64 bytes from 192.168.20.112: icmp_req=1 ttl=64 time=0.488 ms
64 bytes from 192.168.20.112: icmp_req=2 ttl=64 time=0.214 ms
64 bytes from 192.168.20.112: icmp_req=3 ttl=64 time=0.696 ms
64 bytes from 192.168.20.112: icmp_req=4 ttl=64 time=0.135 ms
64 bytes from 192.168.20.112: icmp_req=5 ttl=64 time=0.110 ms
64 bytes from 192.168.20.112: icmp_req=6 ttl=64 time=0.401 ms
64 bytes from 192.168.20.112: icmp_req=7 ttl=64 time=0.378 ms
64 bytes from 192.168.20.112: icmp_req=8 ttl=64 time=0.384 ms
64 bytes from 192.168.20.112: icmp_req=9 ttl=64 time=1.03 ms
64 bytes from 192.168.20.112: icmp_req=10 ttl=64 time=0.439 ms
64 bytes from 192.168.20.112: icmp_req=11 ttl=64 time=0.126 ms
64 bytes from 192.168.20.112: icmp_req=12 ttl=64 time=0.093 ms
64 bytes from 192.168.20.112: icmp_req=13 ttl=64 time=0.834 ms
64 bytes from 192.168.20.112: icmp_req=14 ttl=64 time=0.696 ms
64 bytes from 192.168.20.112: icmp_req=15 ttl=64 time=0.776 ms
64 bytes from 192.168.20.112: icmp_req=16 ttl=64 time=0.215 ms
64 bytes from 192.168.20.112: icmp_req=17 ttl=64 time=0.262 ms
64 bytes from 192.168.20.112: icmp_req=18 ttl=64 time=0.554 ms
64 bytes from 192.168.20.112: icmp_req=19 ttl=64 time=0.373 ms
64 bytes from 192.168.20.112: icmp_req=20 ttl=64 time=0.666 ms

--- 192.168.20.112 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19000ms
rtt min/avg/max/mdev = 0.093/0.443/1.035/0.264 ms

^ permalink raw reply

* Re: BQL + Basic Latency under load results - 100Mbit, GSO/TSO off, pfifo_fast vs SFQ vs QFQ
From: Eric Dumazet @ 2012-01-02  5:27 UTC (permalink / raw)
  To: Dave Taht
  Cc: jg, Stephen Hemminger, Juliusz Chroboczek, Kathleen Nichols,
	netdev
In-Reply-To: <1325480861.2526.15.camel@edumazet-laptop>

Le lundi 02 janvier 2012 à 06:07 +0100, Eric Dumazet a écrit :
> Le lundi 02 janvier 2012 à 05:55 +0100, Eric Dumazet a écrit :
> 
> > I tested this patch with a 50 concurrent netperf workload, and indeed
> > this fixes the problem for me.
> > 
> > # ping 192.168.20.108
> > PING 192.168.20.108 (192.168.20.108) 56(84) bytes of data.
> > 64 bytes from 192.168.20.108: icmp_req=1 ttl=64 time=0.021 ms
> > 64 bytes from 192.168.20.108: icmp_req=2 ttl=64 time=0.011 ms
> > 64 bytes from 192.168.20.108: icmp_req=3 ttl=64 time=0.011 ms
> > 64 bytes from 192.168.20.108: icmp_req=4 ttl=64 time=0.010 ms
> > 64 bytes from 192.168.20.108: icmp_req=5 ttl=64 time=0.010 ms
> > 64 bytes from 192.168.20.108: icmp_req=6 ttl=64 time=0.010 ms
> > 
> 
> Oops, pinging a real machine, not myself I get more realistic numbers :)
> 
> # ping -c 20 192.168.20.112
> PING 192.168.20.112 (192.168.20.112) 56(84) bytes of data.
> 64 bytes from 192.168.20.112: icmp_req=1 ttl=64 time=0.488 ms
> 64 bytes from 192.168.20.112: icmp_req=2 ttl=64 time=0.214 ms
> 64 bytes from 192.168.20.112: icmp_req=3 ttl=64 time=0.696 ms
> 64 bytes from 192.168.20.112: icmp_req=4 ttl=64 time=0.135 ms
> 64 bytes from 192.168.20.112: icmp_req=5 ttl=64 time=0.110 ms
> 64 bytes from 192.168.20.112: icmp_req=6 ttl=64 time=0.401 ms
> 64 bytes from 192.168.20.112: icmp_req=7 ttl=64 time=0.378 ms
> 64 bytes from 192.168.20.112: icmp_req=8 ttl=64 time=0.384 ms
> 64 bytes from 192.168.20.112: icmp_req=9 ttl=64 time=1.03 ms
> 64 bytes from 192.168.20.112: icmp_req=10 ttl=64 time=0.439 ms
> 64 bytes from 192.168.20.112: icmp_req=11 ttl=64 time=0.126 ms
> 64 bytes from 192.168.20.112: icmp_req=12 ttl=64 time=0.093 ms
> 64 bytes from 192.168.20.112: icmp_req=13 ttl=64 time=0.834 ms
> 64 bytes from 192.168.20.112: icmp_req=14 ttl=64 time=0.696 ms
> 64 bytes from 192.168.20.112: icmp_req=15 ttl=64 time=0.776 ms
> 64 bytes from 192.168.20.112: icmp_req=16 ttl=64 time=0.215 ms
> 64 bytes from 192.168.20.112: icmp_req=17 ttl=64 time=0.262 ms
> 64 bytes from 192.168.20.112: icmp_req=18 ttl=64 time=0.554 ms
> 64 bytes from 192.168.20.112: icmp_req=19 ttl=64 time=0.373 ms
> 64 bytes from 192.168.20.112: icmp_req=20 ttl=64 time=0.666 ms
> 
> --- 192.168.20.112 ping statistics ---
> 20 packets transmitted, 20 received, 0% packet loss, time 19000ms
> rtt min/avg/max/mdev = 0.093/0.443/1.035/0.264 ms
> 

And after disabling TSO (as you did in your tests) I get this :
(Note my link is Gigabit, so I had to install a HTB shaper to 100Mbit to
mimic your workload)

# ping -c 20 192.168.20.112
PING 192.168.20.112 (192.168.20.112) 56(84) bytes of data.
64 bytes from 192.168.20.112: icmp_req=1 ttl=64 time=0.113 ms
64 bytes from 192.168.20.112: icmp_req=2 ttl=64 time=0.153 ms
64 bytes from 192.168.20.112: icmp_req=3 ttl=64 time=0.092 ms
64 bytes from 192.168.20.112: icmp_req=4 ttl=64 time=0.095 ms
64 bytes from 192.168.20.112: icmp_req=5 ttl=64 time=0.176 ms
64 bytes from 192.168.20.112: icmp_req=6 ttl=64 time=0.159 ms
64 bytes from 192.168.20.112: icmp_req=7 ttl=64 time=0.169 ms
64 bytes from 192.168.20.112: icmp_req=8 ttl=64 time=0.122 ms
64 bytes from 192.168.20.112: icmp_req=9 ttl=64 time=0.148 ms
64 bytes from 192.168.20.112: icmp_req=10 ttl=64 time=0.123 ms
64 bytes from 192.168.20.112: icmp_req=11 ttl=64 time=0.186 ms
64 bytes from 192.168.20.112: icmp_req=12 ttl=64 time=0.210 ms
64 bytes from 192.168.20.112: icmp_req=13 ttl=64 time=0.142 ms
64 bytes from 192.168.20.112: icmp_req=14 ttl=64 time=0.134 ms
64 bytes from 192.168.20.112: icmp_req=15 ttl=64 time=0.092 ms
64 bytes from 192.168.20.112: icmp_req=16 ttl=64 time=0.187 ms
64 bytes from 192.168.20.112: icmp_req=17 ttl=64 time=0.123 ms
64 bytes from 192.168.20.112: icmp_req=18 ttl=64 time=0.159 ms
64 bytes from 192.168.20.112: icmp_req=19 ttl=64 time=0.142 ms
64 bytes from 192.168.20.112: icmp_req=20 ttl=64 time=0.207 ms

--- 192.168.20.112 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 18999ms
rtt min/avg/max/mdev = 0.092/0.146/0.210/0.037 ms

# tc -s -d cl show dev eth3
class htb 1:1 root leaf 10: prio 0 quantum 80000 rate 100000Kbit ceil 100000Kbit 
burst 40000b/256 mpu 0b overhead 0b cburst 40000b/256 mpu 0b overhead 0b level 0 
 Sent 4569893772 bytes 3107171 pkt (dropped 43457, overlimits 0 requeues 0) 
 rate 75836Kbit 6315pps backlog 0b 127p requeues 0 
 lended: 1204316 borrowed: 0 giants: 0
 tokens: -1892 ctokens: -1892

class sfq 10:1b parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:25 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:34 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:48 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:4b parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot -448 

class sfq 10:4c parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:68 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:96 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:a9 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:c8 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:ca parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:112 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:11a parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:149 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:150 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:16b parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:171 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:185 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:19f parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:1ac parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:1bb parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:1bf parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:1dc parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:1e7 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:1f1 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:201 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:20f parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:216 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:21d parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:22a parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:22e parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:263 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:2d4 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:306 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:307 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:344 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:346 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:34f parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:359 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:36f parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:385 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:3a0 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:3a4 parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 1514b 1p requeues 0 
 allot 0 

class sfq 10:3ac parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 3028b 2p requeues 0 
 allot 1520 

class sfq 10:3ee parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

class sfq 10:3fe parent 10: 
 (dropped 0, overlimits 0 requeues 0) 
 backlog 4542b 3p requeues 0 
 allot 1520 

^ permalink raw reply

* Re: [PATCH net-next] xfrm: Call IP receive handler directly for inbound tunnel-mode packets
From: Herbert Xu @ 2012-01-02  7:28 UTC (permalink / raw)
  To: David Ward; +Cc: netdev
In-Reply-To: <1325475154-15997-1-git-send-email-david.ward@ll.mit.edu>

On Sun, Jan 01, 2012 at 10:32:34PM -0500, David Ward wrote:
> For IPsec tunnel mode (or BEET mode), after inbound packets are xfrm'ed,
> call the IPv4/IPv6 receive handler directly instead of calling netif_rx.
> In addition to avoiding unneeded re-processing of the MAC layer, packets
> will not be received a second time on network taps. (Note that outbound
> packets are only received on network taps post-xfrm, but inbound packets
> were being received both pre- and post-xfrm. So now network taps will
> receive packets in either direction only once, in the form that they go
> "over the wire".)
> 
> Signed-off-by: David Ward <david.ward@ll.mit.edu>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>

You can't do this as this may cause stack overruns if we nest
too deeply.

Changing the existing tap processing behaviour will also break
existing setups.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* RE: [PATCH net-next V2 00/21] net/mlx4: SRIOV support
From: Yevgeny Petrilin @ 2012-01-02  7:55 UTC (permalink / raw)
  To: Yinghai Lu, Roland Dreier
  Cc: Or Gerlitz, David Miller,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Liran Liss,
	jackm-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org
In-Reply-To: <CAE9FiQX1q+qFHrGJdX5aZ9ix0bZ-vH3xEWPqFcRab87a9y2vrQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

> >
> >> hotplug removal is broken...
> >
> > Is this a new regression with these patches?
> >
> 
> yes.
> 
> after reverting those patches, removal work well without problem.
> 
> Thanks
> 
> Yinghai

Thanks,
We just found the same failure internally.
Will send a fix shortly.

Yevgeny
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next] xfrm: Call IP receive handler directly for inbound tunnel-mode packets
From: Eric Dumazet @ 2012-01-02  8:18 UTC (permalink / raw)
  To: Herbert Xu; +Cc: David Ward, netdev
In-Reply-To: <20120102072828.GA5380@gondor.apana.org.au>

Le lundi 02 janvier 2012 à 18:28 +1100, Herbert Xu a écrit :

> You can't do this as this may cause stack overruns if we nest
> too deeply.
> 

I was considering adding a generic helper, for tunneling,
taking into account the depth for current packet.

[ calling netif_receive_skb() instead of netif_rx(), to solve the OOO
problem occurring on SMP when interrupts are spreaded on several cpus ]


We could use the delta between skb->data and skb->head as an estimation
of this depth, in order not adding a new skb field ?

#define DEPTH_THRESHOLD (NET_SKB_PAD + 64)

static inline void netif_reinject(struct sk_buff *skb)
{
if (skb->data - skb->head < DEPTH_THRESHOLD)
	netif_receive_skb(skb);
else
	netif_rx(skb);
}

^ permalink raw reply

* Re: [PATCH 1/4] block: xsysace: Don't use NO_IRQ
From: Grant Likely @ 2012-01-02  8:21 UTC (permalink / raw)
  To: Michal Simek
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ryan Mallon
In-Reply-To: <1324477932-19262-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

On Wed, Dec 21, 2011 at 03:32:09PM +0100, Michal Simek wrote:
> Drivers shouldn't use NO_IRQ. Microblaze and PPC
> define NO_IRQ as 0 and this reference will be removed
> in near future.
> 
> Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
> CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> CC: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

> ---
>  drivers/block/xsysace.c |   10 +++++-----
>  1 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
> index fb1975d..1a17e33 100644
> --- a/drivers/block/xsysace.c
> +++ b/drivers/block/xsysace.c
> @@ -456,7 +456,7 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace)
>  {
>  	dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
>  
> -	if (ace->irq == NO_IRQ)
> +	if (!ace->irq)
>  		/* No IRQ assigned, so need to poll */
>  		tasklet_schedule(&ace->fsm_tasklet);
>  	ace->fsm_continue_flag = 0;
> @@ -1034,12 +1034,12 @@ static int __devinit ace_setup(struct ace_device *ace)
>  		ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
>  
>  	/* Now we can hook up the irq handler */
> -	if (ace->irq != NO_IRQ) {
> +	if (ace->irq) {
>  		rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
>  		if (rc) {
>  			/* Failure - fall back to polled mode */
>  			dev_err(ace->dev, "request_irq failed\n");
> -			ace->irq = NO_IRQ;
> +			ace->irq = 0;
>  		}
>  	}
>  
> @@ -1086,7 +1086,7 @@ static void __devexit ace_teardown(struct ace_device *ace)
>  
>  	tasklet_kill(&ace->fsm_tasklet);
>  
> -	if (ace->irq != NO_IRQ)
> +	if (ace->irq)
>  		free_irq(ace->irq, ace);
>  
>  	iounmap(ace->baseaddr);
> @@ -1156,7 +1156,7 @@ static int __devinit ace_probe(struct platform_device *dev)
>  	resource_size_t physaddr = 0;
>  	int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
>  	u32 id = dev->id;
> -	int irq = NO_IRQ;
> +	int irq = 0;
>  	int i;
>  
>  	dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
> -- 
> 1.7.5.4
> 

^ permalink raw reply

* Re: [PATCH 2/4] net: ethernet: xilinx: Don't use NO_IRQ in xilinx
From: Grant Likely @ 2012-01-02  8:21 UTC (permalink / raw)
  To: Michal Simek
  Cc: Stephen Rothwell, Ryan Mallon, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, David S. Miller
In-Reply-To: <1324477932-19262-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

On Wed, Dec 21, 2011 at 03:32:10PM +0100, Michal Simek wrote:
> Fix ll_temac and emaclite drivers. Only Microblaze and Xilinx PPC
> use then and both use NO_IRQ as 0. It will be removed in near future.
> 
> Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
> CC: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> (commit_signer:7/10=70%)
> CC: Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org> (commit_signer:1/10=10%)
> CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---

Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

>  drivers/net/ethernet/xilinx/ll_temac_main.c   |    2 +-
>  drivers/net/ethernet/xilinx/xilinx_emaclite.c |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
> index 2681b53..87775d7 100644
> --- a/drivers/net/ethernet/xilinx/ll_temac_main.c
> +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
> @@ -1077,7 +1077,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
>  
>  	of_node_put(np); /* Finished with the DMA node; drop the reference */
>  
> -	if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
> +	if (!lp->rx_irq || !lp->tx_irq) {
>  		dev_err(&op->dev, "could not determine irqs\n");
>  		rc = -ENOMEM;
>  		goto err_iounmap_2;
> diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> index 8018d7d..252edf7 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
> @@ -1129,7 +1129,7 @@ static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
>  
>  	/* Get IRQ for the device */
>  	rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
> -	if (rc == NO_IRQ) {
> +	if (!rc) {
>  		dev_err(dev, "no IRQ found\n");
>  		return rc;
>  	}
> -- 
> 1.7.5.4
> 

^ permalink raw reply

* Re: [PATCH 3/4] input: xilinx_ps2: Don't use NO_IRQ
From: Grant Likely @ 2012-01-02  8:21 UTC (permalink / raw)
  To: Michal Simek
  Cc: linux-kernel, netdev, devicetree-discuss, Rob Herring,
	Ryan Mallon
In-Reply-To: <1324477932-19262-3-git-send-email-monstr@monstr.eu>

On Wed, Dec 21, 2011 at 03:32:11PM +0100, Michal Simek wrote:
> Drivers shouldn't use NO_IRQ. Microblaze and PPC
> define NO_IRQ as 0 and this reference will be removed
> in near future.
> 
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> CC: Grant Likely <grant.likely@secretlab.ca>
> CC: Rob Herring <rob.herring@calxeda.com>
> CC: Ryan Mallon <rmallon@gmail.com>

Acked-by: Grant Likely <grant.likely@secretlab.ca>

> ---
>  drivers/input/serio/xilinx_ps2.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
> index d64c5a4..f3e54b9 100644
> --- a/drivers/input/serio/xilinx_ps2.c
> +++ b/drivers/input/serio/xilinx_ps2.c
> @@ -253,7 +253,7 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
>  	}
>  
>  	/* Get IRQ for the device */
> -	if (of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq) == NO_IRQ) {
> +	if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) {
>  		dev_err(dev, "no IRQ found\n");
>  		return -ENODEV;
>  	}
> -- 
> 1.7.5.4
> 

^ permalink raw reply

* Re: [PATCH 4/4] microblaze: Remove NO_IRQ from architecture
From: Grant Likely @ 2012-01-02  8:22 UTC (permalink / raw)
  To: Michal Simek
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Ryan Mallon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1324477932-19262-4-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

On Wed, Dec 21, 2011 at 03:32:12PM +0100, Michal Simek wrote:
> NO_IRQ shouldn't be used by any driver. All Microblaze
> drivers are fixed that's why NO_IRQ can be removed.
> 
> Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
> CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> CC: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
> CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

> ---
>  arch/microblaze/include/asm/irq.h |    2 --
>  arch/microblaze/pci/pci-common.c  |    4 ++--
>  2 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
> index b116a82..a175132 100644
> --- a/arch/microblaze/include/asm/irq.h
> +++ b/arch/microblaze/include/asm/irq.h
> @@ -27,8 +27,6 @@ typedef unsigned long irq_hw_number_t;
>  
>  extern unsigned int nr_irq;
>  
> -#define NO_IRQ 0
> -
>  struct pt_regs;
>  extern void do_IRQ(struct pt_regs *regs);
>  
> diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
> index db841c7..0d71b2e 100644
> --- a/arch/microblaze/pci/pci-common.c
> +++ b/arch/microblaze/pci/pci-common.c
> @@ -242,7 +242,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
>  			 line, pin);
>  
>  		virq = irq_create_mapping(NULL, line);
> -		if (virq != NO_IRQ)
> +		if (virq)
>  			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
>  	} else {
>  		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
> @@ -253,7 +253,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
>  		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
>  					     oirq.size);
>  	}
> -	if (virq == NO_IRQ) {
> +	if (!virq) {
>  		pr_debug(" Failed to map !\n");
>  		return -1;
>  	}
> -- 
> 1.7.5.4
> 

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Split driver into .c and .h files.
From: Bjarke Istrup Pedersen @ 2012-01-02  8:44 UTC (permalink / raw)
  To: Francois Romieu
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20120101224909.GA18144@electric-eye.fr.zoreil.com>

2012/1/1 Francois Romieu <romieu@fr.zoreil.com>:
> Bjarke Istrup Pedersen <gurligebis@gentoo.org> :
>> Split the driver into via-rhine.c and via-rhine.h like it should be.
>> There is also a bit of cleanup of checkpatch warnings, other than that,
>> there is no changes to how the code works, it is plain refactoring.
>
> Please don't do that. The .h won't be used elsewhere. It's useless
> (and register definitions stay barely readable).

Hmm, I see your point, was just trying to make the two via drivers more alike :)

> Roger, any comment regarding patches #1 .. #3 ?
>
> rhine_task_{enable / disable} should be balanced in open / close and
> suspend / resume, ok.
>
> --
> Ueimor
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* [PATCH] r6040: use an unique MDIO bus name
From: Florian Fainelli @ 2012-01-02  9:50 UTC (permalink / raw)
  To: davem; +Cc: netdev, vova.kolpakov, Florian Fainelli

We should use an unique MDIO bus name which does not clash with anything
else in the system like the Fixed MDIO bus. The bus is now named:
<dev_name>-<card number> which is unique in the system.

Reported-by: Vladimir Kolpakov <vova.kolpakov@gmail.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
 drivers/net/ethernet/rdc/r6040.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index 4bf68cf..de5e923 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -1188,7 +1188,8 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
 	lp->mii_bus->write = r6040_mdiobus_write;
 	lp->mii_bus->reset = r6040_mdiobus_reset;
 	lp->mii_bus->name = "r6040_eth_mii";
-	snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", card_idx);
+	snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+					dev_name(&pdev->dev), card_idx);
 	lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
 	if (!lp->mii_bus->irq) {
 		dev_err(&pdev->dev, "mii_bus irq allocation failed\n");
-- 
1.7.5.4

^ permalink raw reply related

* Re: [Announce] LARTC wiki available
From: Ed W @ 2012-01-02 12:48 UTC (permalink / raw)
  To: Niccolò Belli
  Cc: lartc, netfilter@vger.kernel.org,
	Linux Networking Developer Mailing List
In-Reply-To: <4EFC9FC2.1090503@linuxsystems.it>

On 29/12/2011 17:13, Niccolò Belli wrote:
> Il 29/12/2011 17:19, Hagen Paul Pfeifer ha scritto:
>> But I don't like the idea to outhouse the existing wiki. Why two wikis?
>
> Because if you need an invite to edit something then it isn't a wiki 
> anymore, for example.

Wikis seem to be massive spam targets at the moment (I run a small wiki, 
I added registration to try and limit spammers, then I added silly 
captchas, then I added some auto spam word recognition.  I'm now at the 
point that for such a small and niche wiki I might just get people to 
apply to me personally for an edit option, it's just too boring dealing 
with the spam...)

Good luck

Ed W


^ permalink raw reply

* Re: [Announce] LARTC wiki available
From: Niccolò Belli @ 2012-01-02 13:07 UTC (permalink / raw)
  To: lartc; +Cc: netfilter@vger.kernel.org,
	Linux Networking Developer Mailing List
In-Reply-To: <4F01A797.1040406@wildgooses.com>

Il 02/01/2012 13:48, Ed W ha scritto:
> Wikis seem to be massive spam targets at the moment (I run a small wiki,
> I added registration to try and limit spammers, then I added silly
> captchas, then I added some auto spam word recognition. I'm now at the
> point that for such a small and niche wiki I might just get people to
> apply to me personally for an edit option, it's just too boring dealing
> with the spam...)

Thank you for your answer, I wanted a wiki because I want lartc to be as 
independent as possible, the final goal is to find someone who can 
assure continuity to the documentation even if I give up (like vger for 
the ml): I want to avoid what happened to lartc.org and the old mailing 
list.

Did you try ReCAPTCHA 
(http://www.mediawiki.org/wiki/Extension:ReCAPTCHA)? Do you use 
mediawiki or something else?

Again, if someone is experienced and willing to help, any help is 
appreciated. I can share ftp/phpmyadmin if someone wants to co-maintain it.

Thanks,
Niccolò

^ permalink raw reply

* [v5 PATCH 0/3] NETFILTER new target module, HMARK
From: Hans Schillstrom @ 2012-01-02 15:06 UTC (permalink / raw)
  To: kaber, pablo, jengelh, netfilter-devel, netdev; +Cc: hans, Hans Schillstrom

The target allows you to create rules in the "raw" and "mangle" tables
which alter the netfilter mark (nfmark) field within a given range.
First a 32 bit hash value is generated then modulus by <limit> and
finally an offset is added before it's written to nfmark.
Prior to routing, the nfmark can influence the routing method (see
"Use netfilter MARK value as routing key") and can also be used by
other subsystems to change their behavior.

The mark match can also be used to match nfmark produced by this module.
See the kernel module for more info.

REVISION
Version 5
	Use length of mask an smask and dmask and whole IPv6 addr (Jan E)
	Modify ipv6_find_hdr() and use it while traversing the IPv6 header.
        Manual changes.
	More or less all comments implemented.

Version 4
	Split of IPv6 and IPv4, use IP_CT_IS_REPLY, as Pablo suggested.
	removed one pskb_may_pull()
	xtoption parse used in the user space part.

Version 3
        Handling of SCTP for IPv6 added.

Version 2
	NAT Added for IPv4
	IPv6 ICMP handling enhanced.
	Usage example added

Version 1
	Initial RFC


We (Ericsson) use hmark in-front of ipvs as a pre-loadbalancer and
handles up to 70 ipvs running in parallel in clusters.
However hmark is not restricted to run in front of IPVS it can also be used as
"poor mans" load balancer.
With this version is also NAT supported as an option, with very high flows
you might not want to use conntrack.

The idea is to generate a direction independent fw mark range to use as input to
the routing (i.e. ip rule add fwmark ...).
Pretty straight forward and simple.


Example:
                                      App Server (Real Server)

                                           +---------+
                                        -->| Service |
     Gateway A                             +---------+
                          /
            +----------+ /     +----+      +---------+
--- if -A---| selector |---->  |ipvs|  --->| Service |
            +----------+ \     +----+      +---------+
                          \
                               +----+      +---------+
                               |ipvs|   -->| Service |
                               +----+      +---------+
      Gateway C
            +----------+ /     +----+
--- if-B ---| selector | --->  |ipvs|
            +----------+ \     +----+      +---------+
                                           | Service |
                                           +---------+
                          /
            +----------+ /     +----+     ..
--- if-B ---| selector | --->  |ipvs|      +---------+
            +----------+ \     +----+      | Service |
                          \                +---------+
#
# Example with four ipvs loadbalancers
#
iptables -t mangle -I PREROUTING -d $IPADDR -j HMARK --hmark-mod 4 --hmark-offs 100

ip rule add fwmark 100 table 100
ip rule add fwmark 101 table 101
ip rule add fwmark 102 table 102
ip rule add fwmark 103 table 103

ip ro ad table 100 default via x.y.z.1 dev bond1
ip ro ad table 101 default via x.y.z.2 dev bond1
ip ro ad table 102 default via x.y.z.3 dev bond1
ip ro ad table 103 default via x.y.z.4 dev bond1


If conntrack doesn't handle the return path,
do the oposite with HMARK and send it back right to ipvs.

Another exmaple of usage could be if you have cluster originated connections
and want to spread the connections over a number of interfaces
(NAT will complpicate things for you in this case)



                     \  Blade 1
                      \ +----------+      +---------+
                    <-- | selector | <--- | Service |
                      / +----------+      +---------+
                     /
   +------+
-- | Gw-A |          \  Blade 2
   +------+           \ +----------+      +---------+
   +------+         <-- | selector | <--- | Service |
-- | Gw-B |           / +----------+      +---------+
   +------+          /
   +------+
-- | Gw-C |          \
   +------+           \ +----------+      +---------+
                    <-- | selector | <--- | Service |
                      / +----------+      +---------+
                     /

                     \  Blande -n
                      \ +----------+      +---------+
                    <-- | selector | <--- | Service |
                      / +----------+      +---------+
                     /


Regards
Hans Schillstrom <hans.schillstrom@ericsson.com>


^ permalink raw reply

* [v5 PATCH 2/3] NETFILTER module xt_hmark, new target for HASH based fwmark
From: Hans Schillstrom @ 2012-01-02 15:06 UTC (permalink / raw)
  To: kaber, pablo, jengelh, netfilter-devel, netdev; +Cc: hans, Hans Schillstrom
In-Reply-To: <1325516801-25488-1-git-send-email-hans.schillstrom@ericsson.com>

The target allows you to create rules in the "raw" and "mangle" tables
which alter the netfilter mark (nfmark) field within a given range.
First a 32 bit hash value is generated then modulus by <limit> and
finally an offset is added before it's written to nfmark.
Prior to routing, the nfmark can influence the routing method (see
"Use netfilter MARK value as routing key") and can also be used by
other subsystems to change their behavior.

man page
   HMARK
       This  module  does  the same as MARK, i.e. set an fwmark,
       but the mark is based on a hash value.  The hash is based on
       saddr, daddr, sport, dport and proto. The same mark will be produced
       independet of direction if no masks is set or the same masks is used for
       src and dest. The hash mark could be adjusted by modulus and finaly an
       offset could be added, i.e the final mark will be within a range.
       ICMP errors will have hash calc based on the original message.
       Note:
        - None of the parameters effect the packet it self
          only the calculated hash value.
       Fragmentation:
        - If a packet is fragmented NONE of the Fragments will include
          ports in the hash calculation.
          When fragments arrives on different machines HMARK will produce
          same fwmark for all frags inpendent of machine so they can be routed
          to the same destination.
        - If nf_defrag_ipv{4,6} is loaded the packets will be defragmented
          before reaching HMARK, i.e. in that case ports (if any) will be used.
          (ICMP Time exceeded will be sent if fragments are lost)

       Parameters: For all masks default is all "1:s", to disable a field
                   use mask 0. For IPv6 it's just the last 32 bits that
                   is included in the hash.

       --hmark-smask length (0-32 or 0-128)
              The value to AND the source address with (saddr & value).

       --hmark-dmask length (0-32 or 0-128)
              The value to AND the dest. address with (daddr & value).

       --hmark-sp-mask value
              A 16 bit value to AND the src port with (sport & value).

       --hmark-dp-mask value
              A 16 bit value to AND the dest port with (dport & value).

       --hmark-sp-set value
              A 16 bit value to OR the src port with (sport | value).

       --hmark-dp-set value
              A 16 bit value to OR the dest port with (dport | value).

       --hmark-spi-mask value
              Value to AND the spi field with (spi & value) valid for proto esp or ah.

       --hmark-spi-set value
              Value to OR the spi field with (spi | value) valid for proto esp or ah.

       --hmark-proto-mask value
              A 16 bit value to AND the L4 proto field with (proto & value).

       --hmark-rnd value
              A 32 bit intitial value for hash calc, default is 0xc175a3b8.

       --hmark-dnat (only IPv4)
              Replace src addr/port with original dst addr/port before calc, hash

       --hmark-snat (only IPv4)
              Replace dst addr/port with original src addr/port before calc, hash

       Final processing of the mark in order of execution.

       --hmark-mod value (must be > 0)
              The easiest way to describe this is:  hash = hash mod <value>

       --hmark-offs alue (must be > 0)
              The easiest way to describe this is:  hash = hash + <value>

       Examples:

       Default rule handles all TCP, UDP, SCTP, ESP & AH
Rev 5
      IPv6 rewritten uses __ipv6_find_hdr() (P. Mc Hardy)
      Full mask and address used for IPv6 smask and dmask (J.Engelhart)
      Changes due to comments by Pablo Neira Ayuso  and Eric Dumazet
      i.e uses of skb_header_pointer() and Null check of info->hmod
      Man page changes

Rev 4
      different targets for IPv4 and IPv6
      Changes based on review by Pablo.

Rev 3
      Support added to SCTP for IPv6
Rev 2
      IPv6 header scan changed to follow RFC 2640
      IPv4 icmp echo fragmented does now use proto as ipv6
      IPv6 pskb_may_pull() check is done in every time in header loop.
      IPv4 nat support added.
      default added in IPv6 loop and null check of hp

Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
 include/linux/netfilter/xt_hmark.h |   62 +++++++
 net/netfilter/Kconfig              |   17 ++
 net/netfilter/Makefile             |    1 +
 net/netfilter/xt_hmark.c           |  332 ++++++++++++++++++++++++++++++++++++
 4 files changed, 412 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/netfilter/xt_hmark.h
 create mode 100644 net/netfilter/xt_hmark.c

diff --git a/include/linux/netfilter/xt_hmark.h b/include/linux/netfilter/xt_hmark.h
new file mode 100644
index 0000000..366ecce
--- /dev/null
+++ b/include/linux/netfilter/xt_hmark.h
@@ -0,0 +1,62 @@
+#ifndef XT_HMARK_H_
+#define XT_HMARK_H_
+
+#include <linux/types.h>
+
+/*
+ * Flags must not start at 0, since it's used as none.
+ */
+enum {
+	XT_HMARK_SADR_AND = 1,	/* SNAT & DNAT are used by the kernel module */
+	XT_HMARK_DADR_AND,
+	XT_HMARK_SPI_AND,
+	XT_HMARK_SPI_OR,
+	XT_HMARK_SPORT_AND,
+	XT_HMARK_DPORT_AND,
+	XT_HMARK_SPORT_OR,
+	XT_HMARK_DPORT_OR,
+	XT_HMARK_PROTO_AND,
+	XT_HMARK_RND,
+	XT_HMARK_MODULUS,
+	XT_HMARK_OFFSET,
+	XT_HMARK_USE_SNAT,
+	XT_HMARK_USE_DNAT,
+	XT_F_HMARK_USE_SNAT = 1 << XT_HMARK_USE_SNAT,
+	XT_F_HMARK_USE_DNAT = 1 << XT_HMARK_USE_DNAT,
+	XT_F_HMARK_SADR_AND = 1 << XT_HMARK_SADR_AND,
+	XT_F_HMARK_DADR_AND = 1 << XT_HMARK_DADR_AND,
+	XT_F_HMARK_SPI_AND = 1 << XT_HMARK_SPI_AND,
+	XT_F_HMARK_SPI_OR = 1 << XT_HMARK_SPI_OR,
+	XT_F_HMARK_SPORT_AND = 1 << XT_HMARK_SPORT_AND,
+	XT_F_HMARK_DPORT_AND = 1 << XT_HMARK_DPORT_AND,
+	XT_F_HMARK_SPORT_OR = 1 << XT_HMARK_SPORT_OR,
+	XT_F_HMARK_DPORT_OR = 1 << XT_HMARK_DPORT_OR,
+	XT_F_HMARK_PROTO_AND = 1 << XT_HMARK_PROTO_AND,
+	XT_F_HMARK_RND = 1 << XT_HMARK_RND,
+	XT_F_HMARK_MODULUS = 1 << XT_HMARK_MODULUS,
+	XT_F_HMARK_OFFSET = 1 << XT_HMARK_OFFSET,
+};
+
+union hports {
+	struct {
+		__u16	src;
+		__u16	dst;
+	} p16;
+	__u32	v32;
+};
+
+struct xt_hmark_info {
+	union nf_inet_addr	smask;		/* Source address mask */
+	union nf_inet_addr	dmask;		/* Dest address mask */
+	union hports		pmask;
+	union hports		pset;
+	__u32			spimask;
+	__u32			spiset;
+	__u16			flags;		/* Print out only */
+	__u16			prmask;		/* L4 Proto mask */
+	__u32			hashrnd;
+	__u32			hmod;		/* Modulus */
+	__u32			hoffs;		/* Offset */
+};
+
+#endif /* XT_HMARK_H_ */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index d5597b7..6e85d7d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -470,6 +470,23 @@ config NETFILTER_XT_TARGET_HL
 	since you can easily create immortal packets that loop
 	forever on the network.
 
+config NETFILTER_XT_TARGET_HMARK
+	tristate '"HMARK" target support'
+	depends on NETFILTER_ADVANCED
+	---help---
+	This option adds the "HMARK" target.
+
+	The target allows you to create rules in the "raw" and "mangle" tables
+	which alter the netfilter mark (nfmark) field within a given range.
+	First a 32 bit hash value is generated then modulus by <limit> and
+	finally an offset is added before it's written to nfmark.
+
+	Prior to routing, the nfmark can influence the routing method (see
+	"Use netfilter MARK value as routing key") and can also be used by
+	other subsystems to change their behavior.
+
+	The mark match can also be used to match nfmark produced by this module.
+
 config NETFILTER_XT_TARGET_IDLETIMER
 	tristate  "IDLETIMER target support"
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 1a02853..359eeb6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_hmark.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
diff --git a/net/netfilter/xt_hmark.c b/net/netfilter/xt_hmark.c
new file mode 100644
index 0000000..1a854a9
--- /dev/null
+++ b/net/netfilter/xt_hmark.c
@@ -0,0 +1,332 @@
+/*
+ * xt_hmark - Netfilter module to set mark as hash value
+ *
+ * (C) 2011 Hans Schillstrom <hans.schillstrom@ericsson.com>
+ *
+ *Description:
+ *	This module calculates a hash value that can be modified by modulus
+ *	and an offset, i.e. it is possible to produce a skb->mark within a range
+ *	The hash value is based on a direction independent five tuple:
+ *	src & dst addr src & dst ports and protocol.
+ *	However src & dst port can be masked and are not used for fragmented
+ *	packets, ESP and AH don't have ports so SPI will be used instead.
+ *	AH will not use ports even if it might be possible.
+ *	Tunnels - only the outer saddr and daddr will beused,
+ *
+ *	For ICMP error messages the hash mark values will be calculated on
+ *	the source packet i.e. the packet caused the error (If sufficient
+ *	amount of data exists).
+ *
+ *Note:	None of the fragments will include ports/spi in the calculation of
+ *	the hash value. (i.e. all frags must the same hash value.)
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License version 2 as
+ *	published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <linux/icmp.h>
+
+#include <linux/netfilter/xt_hmark.h>
+#include <linux/netfilter/x_tables.h>
+#include <net/netfilter/nf_nat.h>
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#	define WITH_IPV6 1
+#include <net/ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Hans Schillstrom <hans.schillstrom@ericsson.com>");
+MODULE_DESCRIPTION("Xtables: packet range mark operations by hash value");
+MODULE_ALIAS("ipt_HMARK");
+MODULE_ALIAS("ip6t_HMARK");
+
+/*
+ * ICMP, get inner header so calc can be made on the source message
+ *
+ * iphsz: ip header size in bytes
+ * nhoff: network header offset
+ * return; updated nhoff if an icmp error
+ */
+static int get_inner_hdr(struct sk_buff *skb, int iphsz, int nhoff)
+{
+	const struct icmphdr *icmph;
+	struct icmphdr _ih;
+
+	/* Not enough header? */
+	icmph = skb_header_pointer(skb, nhoff + iphsz, sizeof(_ih), &_ih);
+	if (icmph == NULL)
+		return nhoff;
+
+	if (icmph->type > NR_ICMP_TYPES)
+		return nhoff;
+
+	/* Error message? */
+	if (icmph->type != ICMP_DEST_UNREACH &&
+	    icmph->type != ICMP_SOURCE_QUENCH &&
+	    icmph->type != ICMP_TIME_EXCEEDED &&
+	    icmph->type != ICMP_PARAMETERPROB &&
+	    icmph->type != ICMP_REDIRECT)
+		return nhoff;
+
+	return nhoff + iphsz + sizeof(_ih);
+}
+
+#ifdef WITH_IPV6
+/* Dummy header used for size calculation of an error header */
+struct _icmpv6_errh {
+	__u8		icmp6_type;
+	__u8		icmp6_code;
+	__u16		icmp6_cksum;
+	__u32		icmp6_nu;
+};
+/*
+ * Get ipv6 header offset if icmp type < 128 i.e. an error.
+ * @param: offset  input: where ICMPv6 header starts
+ *                output: where ipv6 header starts / unchanged.
+ *
+ * Returns true if it's an icmp error
+ *              and updates *offset to where ipv6 header starts
+ */
+static int get_inner6_hdr(struct sk_buff *skb, int *offset)
+{
+	struct icmp6hdr *icmp6h, _ih6;
+
+	icmp6h = skb_header_pointer(skb, *offset, sizeof(_ih6), &_ih6);
+	if (icmp6h == NULL)
+		return 0;
+
+	if (icmp6h->icmp6_type && icmp6h->icmp6_type < 128) {
+		*offset +=  sizeof(struct _icmpv6_errh);
+		return 1;
+	}
+	return 0;
+}
+/*
+ * Calculate hash based fw-mark, on the five tuple if possible.
+ * special cases :
+ *  - Fragments do not use ports not even on the first fragment,
+ *    nf_defrag_ipv6.ko don't defrag for us like it do in ipv4.
+ *    This might be changed in the future.
+ *  - On ICMP errors the inner header will be used.
+ *  - Tunnels no ports
+ *  - ESP & AH uses SPI
+ * @returns XT_CONTINUE
+ */
+__u32 hmark_v6(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	struct xt_hmark_info *info = (struct xt_hmark_info *)par->targinfo;
+	struct ipv6hdr *ip6, _ip6;
+	int poff, flag = IP6T_FH_F_AUTH; /* Ports offset, find_hdr flags */
+	u32 addr1, addr2, hash, nhoffs;
+	u8 nexthdr;
+	union hports uports = { .v32 = 0 };
+	unsigned short fragoff = 0;
+
+	if (!info->hmod)
+		return XT_CONTINUE;
+
+	nhoffs = skb_network_offset(skb);
+	ip6 = (struct ipv6hdr *) (skb->data + nhoffs);
+
+	/* Try to get transport header */
+	nexthdr = __ipv6_find_hdr(skb, &nhoffs, -1, &fragoff, &flag);
+	if (nexthdr < 0)
+		return XT_CONTINUE;
+	/* dont check for icmp on fragments */
+	if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
+		goto noicmp;
+	/* ICMP: if an error then move ptr to inner header */
+	if (get_inner6_hdr(skb, &nhoffs)) {
+		ip6 = skb_header_pointer(skb, nhoffs, sizeof(_ip6), &_ip6);
+		if (!ip6)
+			return XT_CONTINUE;
+		nhoffs += sizeof(_ip6);
+		flag = IP6T_FH_F_AUTH;
+		nexthdr = __ipv6_find_hdr(skb, &nhoffs, -1, &fragoff, &flag);
+		if (nexthdr < 0)
+			return XT_CONTINUE;
+	}
+noicmp:
+	/* Mask of the address and xor it into a u32 */
+	addr1 = (__force u32)
+		(ip6->saddr.s6_addr32[0] & info->smask.in6.s6_addr32[0]) ^
+		(ip6->saddr.s6_addr32[1] & info->smask.in6.s6_addr32[1]) ^
+		(ip6->saddr.s6_addr32[2] & info->smask.in6.s6_addr32[2]) ^
+		(ip6->saddr.s6_addr32[3] & info->smask.in6.s6_addr32[3]);
+	addr2 = (__force u32)
+		(ip6->daddr.s6_addr32[0] & info->dmask.in6.s6_addr32[0]) ^
+		(ip6->daddr.s6_addr32[1] & info->dmask.in6.s6_addr32[1]) ^
+		(ip6->daddr.s6_addr32[2] & info->dmask.in6.s6_addr32[2]) ^
+		(ip6->daddr.s6_addr32[3] & info->dmask.in6.s6_addr32[3]);
+
+	/* Is next header valid for port or SPI calculation ? */
+	poff = proto_ports_offset(nexthdr);
+	if ((flag & IP6T_FH_F_FRAG) || poff < 0)
+		goto no6ports;
+	nhoffs += poff;
+	/* Since uports is modified, skb_header_pointer() can't be used */
+	 if (!pskb_may_pull(skb, nhoffs + 4))
+		goto no6ports;
+	uports.v32 = * (__force u32 *) (skb->data + nhoffs);
+
+	if ((nexthdr == IPPROTO_ESP) || (nexthdr == IPPROTO_AH)) {
+		uports.v32 = (uports.v32 & info->spimask) | info->spiset;
+	} else {
+		uports.v32 = (uports.v32 & info->pmask.v32) | info->pset.v32;
+		/* get a consistent hash (same value on both flow directions) */
+		if (uports.p16.dst < uports.p16.src)
+			swap(uports.p16.dst, uports.p16.src);
+	}
+
+no6ports:
+	nexthdr &= info->prmask;
+	/* get a consistent hash (same value on both flow directions) */
+	if (addr2 < addr1)
+		swap(addr1, addr2);
+
+	hash = jhash_3words(addr1, addr2, uports.v32, info->hashrnd) ^ nexthdr;
+	skb->mark = (hash % info->hmod) + info->hoffs;
+	return XT_CONTINUE;
+}
+#endif
+/*
+ * Calculate hash based fw-mark, on the five tuple if possible.
+ * special cases :
+ *  - Fragments do not use ports not even on the first fragment,
+ *    unless nf_defrag_xx.ko is used.
+ *  - On ICMP errors the inner header will be used.
+ *  - Tunnels no ports
+ *  - ESP & AH uses SPI
+ * @returns XT_CONTINUE
+ */
+unsigned int hmark_v4(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	struct xt_hmark_info *info = (struct xt_hmark_info *)par->targinfo;
+	int nhoff, poff, frag = 0;
+	struct iphdr *ip, _ip;
+	u8 ip_proto;
+	u32 addr1, addr2, hash;
+	u16 snatport = 0, dnatport = 0;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+	union hports uports;
+
+	if (!info->hmod)
+		return XT_CONTINUE;
+
+	nhoff = skb_network_offset(skb);
+	uports.v32 = 0;
+
+	ip = (struct iphdr *) (skb->data + nhoff);
+	if (ip->protocol == IPPROTO_ICMP) {
+		/* calc hash on inner header if an icmp error */
+		nhoff = get_inner_hdr(skb, ip->ihl * 4, nhoff);
+		ip = skb_header_pointer(skb, nhoff, sizeof(_ip), &_ip);
+		if (!ip)
+			return XT_CONTINUE;
+	}
+
+	ip_proto = ip->protocol;
+	if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+		frag = 1;
+
+	addr1 = (__force u32) ip->saddr & info->smask.ip;
+	addr2 = (__force u32) ip->daddr & info->dmask.ip;
+
+	if (ct && test_bit(IP_CT_IS_REPLY, &ct->status)) {
+		struct nf_conntrack_tuple *otuple;
+
+		otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+		/*
+		 * On the "return flow", to get the original address
+		 */
+		if ((ct->status & IPS_DST_NAT) &&
+			(info->flags & XT_HMARK_USE_DNAT)) {
+			addr1 = (__force u32) otuple->dst.u3.in.s_addr;
+			dnatport = otuple->dst.u.udp.port;
+		}
+		if ((ct->status & IPS_SRC_NAT) &&
+			(info->flags & XT_HMARK_USE_SNAT)) {
+			addr2 = (__force u32) otuple->src.u3.in.s_addr;
+			snatport = otuple->src.u.udp.port;
+		}
+	}
+	/* Check if ports can be used in hash calculation. */
+	poff = proto_ports_offset(ip_proto);
+	if (frag || poff < 0)
+		goto noports;
+
+	nhoff += (ip->ihl * 4) + poff;
+	if (!pskb_may_pull(skb, nhoff + 4))
+		goto noports;
+
+	uports.v32 = * (__force u32 *) (skb->data + nhoff);
+	if (ip_proto == IPPROTO_ESP || ip_proto == IPPROTO_AH) {
+		uports.v32 = (uports.v32 & info->spimask) | info->spiset;
+	} else {
+		if (snatport)	/* Replace nat'ed port(s) */
+			uports.p16.dst = snatport;
+		if (dnatport)
+			uports.p16.src = dnatport;
+		uports.v32 = (uports.v32 & info->pmask.v32) |
+				info->pset.v32;
+		/* get a consistent hash (same value on both flow directions) */
+		if (uports.p16.dst < uports.p16.src)
+			swap(uports.p16.src, uports.p16.dst);
+	}
+
+noports:
+	ip_proto &= info->prmask;
+	/* get a consistent hash (same value on both flow directions) */
+	if (addr2 < addr1)
+		swap(addr1, addr2);
+
+	hash = jhash_3words(addr1, addr2, uports.v32, info->hashrnd) ^ ip_proto;
+	skb->mark = (hash % info->hmod) + info->hoffs;
+	return XT_CONTINUE;
+}
+
+static struct xt_target hmark_tg_reg[] __read_mostly = {
+	{
+		.name           = "HMARK",
+		.revision       = 0,
+		.family         = NFPROTO_IPV4,
+		.target         = hmark_v4,
+		.targetsize     = sizeof(struct xt_hmark_info),
+		.me             = THIS_MODULE,
+	},
+#ifdef WITH_IPV6
+	{
+		.name           = "HMARK",
+		.revision       = 0,
+		.family         = NFPROTO_IPV6,
+		.target         = hmark_v6,
+		.targetsize     = sizeof(struct xt_hmark_info),
+		.me             = THIS_MODULE,
+	},
+#endif
+};
+
+static int __init hmark_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static void __exit hmark_mt_exit(void)
+{
+	xt_unregister_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
+}
+
+module_init(hmark_mt_init);
+module_exit(hmark_mt_exit);
-- 
1.7.2.3


^ permalink raw reply related

* [v5 PATCH 3/3] NETFILTER userspace part for target HMARK
From: Hans Schillstrom @ 2012-01-02 15:06 UTC (permalink / raw)
  To: kaber, pablo, jengelh, netfilter-devel, netdev; +Cc: hans, Hans Schillstrom
In-Reply-To: <1325516801-25488-1-git-send-email-hans.schillstrom@ericsson.com>

    The target allows you to create rules in the "raw" and "mangle" tables
    which alter the netfilter mark (nfmark) field within a given range.
    First a 32 bit hash value is generated then modulus by <limit> and
    finally an offset is added before it's written to nfmark.
    Prior to routing, the nfmark can influence the routing method (see
    "Use netfilter MARK value as routing key") and can also be used by
    other subsystems to change their behaviour.

    The mark match can also be used to match nfmark produced by this module.
    Ver 5
      smask and dmask changed to length

    Ver 4
      xtoptions used for parsing.

    Ver 3
       -

    Ver 2
      IPv4 NAT added
      iptables ver 1.4.12.1 adaptions.

Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
 extensions/libxt_HMARK.c           |  335 ++++++++++++++++++++++++++++++++++++
 extensions/libxt_HMARK.man         |   65 +++++++
 include/linux/netfilter/xt_hmark.h |   62 +++++++
 3 files changed, 462 insertions(+), 0 deletions(-)
 create mode 100644 extensions/libxt_HMARK.c
 create mode 100644 extensions/libxt_HMARK.man
 create mode 100644 include/linux/netfilter/xt_hmark.h

diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
new file mode 100644
index 0000000..ec74a19
--- /dev/null
+++ b/extensions/libxt_HMARK.c
@@ -0,0 +1,335 @@
+/*
+ * Shared library add-on to iptables to add HMARK target support.
+ *
+ * The kernel module calculates a hash value that can be modified by modulus
+ * and an offset. The hash value is based on a direction independent
+ * five tuple: src & dst addr src & dst ports and protocol.
+ * However src & dst port can be masked and are not used for fragmented
+ * packets, ESP and AH don't have ports so SPI will be used instead.
+ * For ICMP error messages the hash mark values will be calculated on
+ * the source packet i.e. the packet caused the error (If sufficient
+ * amount of data exists).
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_hmark.h>
+
+
+#define DEF_HRAND 0xc175a3b8	/* Default "random" value to jhash */
+
+static void HMARK_help(void)
+{
+	printf(
+"HMARK target options, i.e. modify hash calculation by:\n"
+"  --hmark-smask length               Source address mask length\n"
+"  --hmark-dmask length               Dest address mask length\n"
+"  --hmark-sp-mask value              Mask src port with value\n"
+"  --hmark-dp-mask value              Mask dst port with value\n"
+"  --hmark-spi-mask value             For esp and ah AND spi with value\n"
+"  --hmark-sp-set value               OR src port with value\n"
+"  --hmark-dp-set value               OR dst port with value\n"
+"  --hmark-spi-set value              For esp and ah OR spi with value\n"
+"  --hmark-proto-mask value           Mask Protocol with value\n"
+"  --hmark-rnd                        Random value to hash cacl.\n"
+"  Limit/modify the calculated hash mark by:\n"
+"  --hmark-mod value                  nfmark modulus value\n"
+"  --hmark-offs value                 Last action add value to nfmark\n"
+" For NAT in IPv4 the original address can be used in the return path.\n"
+" Make sure to qualify the statement in a proper way when using nat flags\n"
+"  --hmark-dnat                       Replace src addr with original dst addr\n"
+"  --hmark-snat                       Replace dst addr with original src addr\n"
+" In many cases hmark can be omitted i.e. --smask can be used\n");
+}
+
+#define hi struct xt_hmark_info
+
+static const struct xt_option_entry HMARK_opts[] = {
+	{ .name = "hmark-smask",      .type = XTTYPE_PLENMASK, .id = XT_HMARK_SADR_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, smask)
+	},
+	{ .name = "hmark-dmask",      .type = XTTYPE_PLENMASK, .id = XT_HMARK_DADR_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, dmask)
+	},
+	{ .name = "hmark-sp-mask",    .type = XTTYPE_UINT16, .id = XT_HMARK_SPORT_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, pmask.p16.src)
+	},
+	{ .name = "hmark-dp-mask",    .type = XTTYPE_UINT16, .id = XT_HMARK_DPORT_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, pmask.p16.dst)
+	},
+	{ .name = "hmark-spi-mask",   .type = XTTYPE_UINT32, .id = XT_HMARK_SPI_AND,
+	  .flags = XTOPT_PUT,  XTOPT_POINTER(hi, spimask)
+	},
+	{ .name = "hmark-sp-set",     .type = XTTYPE_UINT16, .id = XT_HMARK_SPORT_OR,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, pset.p16.src)
+	},
+	{ .name = "hmark-dp-set",     .type = XTTYPE_UINT16, .id = XT_HMARK_DPORT_OR,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, pset.p16.dst)
+	},
+	{ .name = "hmark-spi-set",    .type = XTTYPE_UINT32, .id = XT_HMARK_SPI_OR,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, spiset)
+	},
+	{ .name = "hmark-proto-mask", .type = XTTYPE_UINT16, .id = XT_HMARK_PROTO_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, prmask)
+	},
+	{ .name = "hmark-rnd",        .type = XTTYPE_UINT32, .id = XT_HMARK_RND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
+	},
+	{ .name = "hmark-mod",        .type = XTTYPE_UINT32, .id = XT_HMARK_MODULUS,
+	  .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmod)
+	},
+	{ .name = "hmark-offs",       .type = XTTYPE_UINT32, .id = XT_HMARK_OFFSET,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffs)
+	},
+	{ .name = "hmark-dnat",       .type = XTTYPE_NONE,   .id = XT_HMARK_USE_DNAT },
+	{ .name = "hmark-snat",       .type = XTTYPE_NONE,   .id = XT_HMARK_USE_SNAT },
+
+	{ .name = "smask",      .type = XTTYPE_PLENMASK, .id = XT_HMARK_SADR_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, smask)
+	},
+	{ .name = "dmask",      .type = XTTYPE_PLENMASK, .id = XT_HMARK_DADR_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, dmask)
+	},
+	{ .name = "sp-mask",    .type = XTTYPE_UINT16, .id = XT_HMARK_SPORT_AND,
+	  .flags = XTOPT_PUT,  XTOPT_POINTER(hi, pmask.p16.src)
+	},
+	{ .name = "dp-mask",    .type = XTTYPE_UINT16, .id = XT_HMARK_DPORT_AND,
+	  .flags = XTOPT_PUT,  XTOPT_POINTER(hi, pmask.p16.dst)
+	},
+	{ .name = "spi-mask",   .type = XTTYPE_UINT32, .id = XT_HMARK_SPI_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, spimask)
+	},
+	{ .name = "sp-set",     .type = XTTYPE_UINT16, .id = XT_HMARK_SPORT_OR,
+	  .flags = XTOPT_PUT,  XTOPT_POINTER(hi, pset.p16.src)
+	},
+	{ .name = "dp-set",     .type = XTTYPE_UINT16, .id = XT_HMARK_DPORT_OR,
+	  .flags = XTOPT_PUT,  XTOPT_POINTER(hi, pset.p16.dst)
+	},
+	{ .name = "spi-set",    .type = XTTYPE_UINT32, .id = XT_HMARK_SPI_OR,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, spiset)
+	},
+	{ .name = "proto-mask", .type = XTTYPE_UINT16, .id = XT_HMARK_PROTO_AND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, prmask)
+	},
+	{ .name = "rnd",        .type = XTTYPE_UINT32, .id = XT_HMARK_RND,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
+	},
+	{ .name = "mod",        .type = XTTYPE_UINT32, .id = XT_HMARK_MODULUS,
+	  .flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmod)
+	},
+	{ .name = "offs",       .type = XTTYPE_UINT32, .id = XT_HMARK_OFFSET,
+	  .flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffs)
+	},
+	{ .name = "dnat",       .type = XTTYPE_NONE,   .id = XT_HMARK_USE_DNAT },
+	{ .name = "snat",       .type = XTTYPE_NONE,   .id = XT_HMARK_USE_SNAT },
+	XTOPT_TABLEEND,
+};
+
+static void HMARK_parse(struct xt_option_call *cb)
+{
+	struct xt_hmark_info *info = cb->data;
+
+	if (!cb->xflags) {
+		memset(info, 0xff, sizeof(struct xt_hmark_info));
+		info->pset.v32 = 0;
+		info->flags = 0;
+		info->spiset = 0;
+		info->hoffs = 0;
+		info->hashrnd = DEF_HRAND;
+	}
+	xtables_option_parse(cb);
+
+	switch (cb->entry->id) {
+	case XT_HMARK_SPI_AND:
+		info->spimask = htonl(cb->val.u32);
+		break;
+	case XT_HMARK_SPI_OR:
+		info->spiset = htonl(cb->val.u32);
+		break;
+	case XT_HMARK_SPORT_AND:
+		info->pmask.p16.src = htons(cb->val.u16);
+		break;
+	case XT_HMARK_DPORT_AND:
+		info->pmask.p16.dst = htons(cb->val.u16);
+		break;
+	case XT_HMARK_SPORT_OR:
+		info->pset.p16.src = htons(cb->val.u16);
+		break;
+	case XT_HMARK_DPORT_OR:
+		info->pset.p16.dst = htons(cb->val.u16);
+		break;
+	case XT_HMARK_MODULUS:
+		if (info->hmod == 0) {
+			xtables_error(PARAMETER_PROBLEM,
+				      "xxx modulus 0 ? "
+				      "thats a div by 0");
+			info->hmod = 0xffffffff;
+		}
+		break;
+	}
+	info->flags = cb->xflags;
+}
+
+static void HMARK_check(struct xt_fcheck_call *cb)
+{
+	if (!(cb->xflags & XT_F_HMARK_MODULUS))
+		xtables_error(PARAMETER_PROBLEM, "HMARK: the --hmark-mod, "
+			   "is not set, that means the nfmark will be in range"
+			   " 0 - 0xffffffff");
+}
+/*
+ * Common print for IPv4 & IPv6
+ */
+static void HMARK_print(const struct xt_hmark_info *info)
+{
+	if (info->flags & (1 << XT_HMARK_SPORT_AND))
+		printf("sp-mask 0x%x ", htons(info->pmask.p16.src));
+	if (info->flags & (1 << XT_HMARK_DPORT_AND))
+		printf("dp-mask 0x%x ", htons(info->pmask.p16.dst));
+	if (info->flags & (1 << XT_HMARK_SPI_AND))
+		printf("spi-mask 0x%x ", htonl(info->spimask));
+	if (info->flags & (1 << XT_HMARK_SPORT_OR))
+		printf("sp-set 0x%x ", htons(info->pset.p16.src));
+	if (info->flags & (1 << XT_HMARK_DPORT_OR))
+		printf("dp-set 0x%x ", htons(info->pset.p16.dst));
+	if (info->flags & (1 << XT_HMARK_SPI_OR))
+		printf("spi-set 0x%x ", htonl(info->spiset));
+	if (info->flags & (1 << XT_HMARK_PROTO_AND))
+		printf("proto-mask 0x%x ", info->prmask);
+	if (info->flags & (1 << XT_HMARK_RND))
+		printf("rnd 0x%x ", info->hashrnd);
+}
+
+static void HMARK_ip6_print(const void *ip, const struct xt_entry_target *target,
+			int numeric)
+{
+	const struct xt_hmark_info *info =
+			(const struct xt_hmark_info *)target->data;
+
+	printf(" HMARK ");
+	if (info->flags & (1 << XT_HMARK_MODULUS))
+		printf("%% 0x%x ", info->hmod);
+	if (info->flags & (1 << XT_HMARK_OFFSET))
+		printf("+ 0x%x ", info->hoffs);
+	if (info->flags & (1 << XT_HMARK_USE_SNAT))
+		printf("snat, ");
+	if (info->flags & (1 << XT_HMARK_SADR_AND))
+		printf("smask %s ", xtables_ip6mask_to_numeric(&info->smask.in6) + 1);
+	if (info->flags & (1 << XT_HMARK_USE_DNAT))
+		printf("dnat, ");
+	if (info->flags & (1 << XT_HMARK_DADR_AND))
+		printf("dmask %s ", xtables_ip6mask_to_numeric(&info->dmask.in6) + 1);
+	HMARK_print(info);
+}
+static void HMARK_ip4_print(const void *ip, const struct xt_entry_target *target, int numeric)
+{
+	const struct xt_hmark_info *info = (const struct xt_hmark_info *)target->data;
+
+	printf(" HMARK ");
+	if (info->flags & (1 << XT_HMARK_MODULUS))
+		printf("%% 0x%x ", info->hmod);
+	if (info->flags & (1 << XT_HMARK_OFFSET))
+		printf("+ 0x%x ", info->hoffs);
+	if (info->flags & (1 << XT_HMARK_USE_SNAT))
+		printf("snat, ");
+	if (info->flags & (1 << XT_HMARK_SADR_AND))
+		printf("smask %s ", xtables_ipmask_to_numeric(&info->smask.in) + 1);
+	if (info->flags & (1 << XT_HMARK_USE_DNAT))
+		printf("dnat, ");
+	if (info->flags & (1 << XT_HMARK_DADR_AND))
+		printf("dmask %s ", xtables_ipmask_to_numeric(&info->dmask.in) + 1);
+	HMARK_print(info);
+}
+static void HMARK_save(const struct xt_hmark_info *info)
+{
+	if (info->flags & (1 << XT_HMARK_SPORT_AND))
+		printf(" --hmark-sp-mask 0x%x", htons(info->pmask.p16.src));
+	if (info->flags & (1 << XT_HMARK_DPORT_AND))
+		printf(" --hmark-dp-mask 0x%x", htons(info->pmask.p16.dst));
+	if (info->flags & (1 << XT_HMARK_SPI_AND))
+		printf(" --hmark-spi-mask 0x%x", htonl(info->spimask));
+	if (info->flags & (1 << XT_HMARK_SPORT_OR))
+		printf(" --hmark-sp-set 0x%x", htons(info->pset.p16.src));
+	if (info->flags & (1 << XT_HMARK_DPORT_OR))
+		printf(" --hmark-dp-set 0x%x", htons(info->pset.p16.dst));
+	if (info->flags & (1 << XT_HMARK_SPI_OR))
+		printf(" --hmark-spi-set 0x%x", htonl(info->spiset));
+	if (info->flags & (1 << XT_HMARK_PROTO_AND))
+		printf(" --hmark-proto-mask 0x%x", info->prmask);
+	if (info->flags & (1 << XT_HMARK_RND))
+		printf(" --hmark-rnd 0x%x", info->hashrnd);
+	if (info->flags & (1 << XT_HMARK_MODULUS))
+		printf(" --hmark-mod 0x%x", info->hmod);
+	if (info->flags & (1 << XT_HMARK_OFFSET))
+		printf(" --hmark-offs 0x%x", info->hoffs);
+	if (info->flags & (1 << XT_HMARK_USE_DNAT))
+		printf(" --hmark-dnat");
+	if (info->flags & (1 << XT_HMARK_USE_SNAT))
+		printf(" --hmark-snat");
+}
+
+static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
+{
+	const struct xt_hmark_info *info =
+		(const struct xt_hmark_info *)target->data;
+
+	if (info->flags & (1 << XT_HMARK_SADR_AND))
+		printf(" --hmark-smask %s", xtables_ip6mask_to_numeric(&info->smask.in6) + 1);
+	if (info->flags & (1 << XT_HMARK_DADR_AND))
+		printf(" --hmark-dmask %s", xtables_ip6mask_to_numeric(&info->dmask.in6) + 1);
+	HMARK_save(info);
+}
+
+static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
+{
+	const struct xt_hmark_info *info =
+		(const struct xt_hmark_info *)target->data;
+
+	if (info->flags & (1 << XT_HMARK_SADR_AND))
+		printf(" --hmark-smask %s", xtables_ipmask_to_numeric(&info->smask.in) + 1);
+	if (info->flags & (1 << XT_HMARK_DADR_AND))
+		printf(" --hmark-dmask %s", xtables_ipmask_to_numeric(&info->dmask.in) + 1);
+	HMARK_save(info);
+}
+
+static struct xtables_target mark_tg_reg[] = {
+	{
+		.family        = NFPROTO_IPV4,
+		.name          = "HMARK",
+		.version       = XTABLES_VERSION,
+		.revision      = 0,
+		.size          = XT_ALIGN(sizeof(struct xt_hmark_info)),
+		.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+		.help          = HMARK_help,
+		.print         = HMARK_ip4_print,
+		.save          = HMARK_ip4_save,
+		.x6_parse      = HMARK_parse,
+		.x6_fcheck     = HMARK_check,
+		.x6_options    = HMARK_opts,
+	},
+	{
+		.family        = NFPROTO_IPV6,
+		.name          = "HMARK",
+		.version       = XTABLES_VERSION,
+		.revision      = 0,
+		.size          = XT_ALIGN(sizeof(struct xt_hmark_info)),
+		.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
+		.help          = HMARK_help,
+		.print         = HMARK_ip6_print,
+		.save          = HMARK_ip6_save,
+		.x6_parse      = HMARK_parse,
+		.x6_fcheck     = HMARK_check,
+		.x6_options    = HMARK_opts,
+	},
+};
+
+void _init(void)
+{
+	xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
+}
+
diff --git a/extensions/libxt_HMARK.man b/extensions/libxt_HMARK.man
new file mode 100644
index 0000000..74beb64
--- /dev/null
+++ b/extensions/libxt_HMARK.man
@@ -0,0 +1,65 @@
+This module does the same as MARK, i.e. set an fwmark, but the mark is based on a hash value.
+The hash is based on saddr, daddr, sport, dport and proto. The same mark will be produced independet of direction if no masks is set or the same masks is used for src and dest.
+The hash mark could be adjusted by modulus and finally an offset could be added, i.e the final mark will be within a range.
+ICMP error will use the the original message for hash calculation not the icmp it self.
+Fragmented packets will not use ports/spi not even the first packet.
+
+Note: IPv4 packets with nf_defrag_ipv4 loaded will be defragmented before they reach hmark,
+      IPv6 nf_defrag is not implemented this way, hence fragmented ipv6 packets will reach hmark.
+      None of the parameters effect the packet it self only the calculated hash value.
+.PP
+Parameters:
+For all masks default is all "1:s", to disable a field use mask 0
+For IPv6 it's just the last 32 bits that is included in the hash
+.TP
+\fB\-\-hmark\-smask\fP \fIlength\fP
+The length of the mask to AND the source address with (saddr & value).
+.TP
+\fB\-\-hmark\-dmask\fP \fIlength\fP
+The length of the mask to AND the dest. address with (daddr & value).
+.TP
+\fB\-\-hmark\-sp\-mask\fP \fIvalue\fP
+A 16 bit value to AND the src port with (sport & value).
+.TP
+\fB\-\-hmark\-dp\-mask\fP \fIvalue\fP
+A 16 bit value to AND the dest port with (dport & value).
+.TP
+\fB\-\-hmark\-sp\-set\fP \fIvalue\fP
+A 16 bit value to OR the src port with (sport | value).
+.TP
+\fB\-\-hmark\-dp\-set\fP \fIvalue\fP
+A 16 bit value to OR the dest port with (dport | value).
+.TP
+\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
+Value to AND the spi field with (spi & value) valid for proto esp or ah.
+.TP
+\fB\-\-hmark\-spi\-set\fP \fIvalue\fP
+Value to OR the spi field with (spi | value) valid for proto esp or ah.
+.TP
+\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
+An 8 bit value to AND the L4 proto field with (proto & value).
+.TP
+\fB\-\-hmark\-rnd\fP \fIvalue\fP
+A 32 bit initial value for hash calc, default is 0xc175a3b8.
+.PP
+Final processing of the mark in order of execution.
+.TP
+\fB\-\-hmark\-mod\fP \fvalue (must be > 0)\fP
+The easiest way to describe this is:  hash = hash mod <value>
+.TP
+\fB\-\-hmark\-offs\fP \fvalue\fP
+The easiest way to describe this is:  hash = hash + <value>
+.PP
+\fIExamples:\fP
+.PP
+Default rule handles all TCP, UDP, SCTP, ESP & AH
+.IP
+iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW,ESTABLISHED,RELATED
+ \-j HMARK \-\-hmark-offs 10000 \-\-hmark-mod 10
+.PP
+Handle SCTP and hash dest port only and produce a nfmark between 100-119.
+.IP
+iptables \-t mangle \-A PREROUTING -p SCTP \-j HMARK \-\-smask 0 \-\-dmask 0
+ \-\-sp\-mask 0 \-\-offs 100 \-\-mod 20
+.PP
+
diff --git a/include/linux/netfilter/xt_hmark.h b/include/linux/netfilter/xt_hmark.h
new file mode 100644
index 0000000..366ecce
--- /dev/null
+++ b/include/linux/netfilter/xt_hmark.h
@@ -0,0 +1,62 @@
+#ifndef XT_HMARK_H_
+#define XT_HMARK_H_
+
+#include <linux/types.h>
+
+/*
+ * Flags must not start at 0, since it's used as none.
+ */
+enum {
+	XT_HMARK_SADR_AND = 1,	/* SNAT & DNAT are used by the kernel module */
+	XT_HMARK_DADR_AND,
+	XT_HMARK_SPI_AND,
+	XT_HMARK_SPI_OR,
+	XT_HMARK_SPORT_AND,
+	XT_HMARK_DPORT_AND,
+	XT_HMARK_SPORT_OR,
+	XT_HMARK_DPORT_OR,
+	XT_HMARK_PROTO_AND,
+	XT_HMARK_RND,
+	XT_HMARK_MODULUS,
+	XT_HMARK_OFFSET,
+	XT_HMARK_USE_SNAT,
+	XT_HMARK_USE_DNAT,
+	XT_F_HMARK_USE_SNAT = 1 << XT_HMARK_USE_SNAT,
+	XT_F_HMARK_USE_DNAT = 1 << XT_HMARK_USE_DNAT,
+	XT_F_HMARK_SADR_AND = 1 << XT_HMARK_SADR_AND,
+	XT_F_HMARK_DADR_AND = 1 << XT_HMARK_DADR_AND,
+	XT_F_HMARK_SPI_AND = 1 << XT_HMARK_SPI_AND,
+	XT_F_HMARK_SPI_OR = 1 << XT_HMARK_SPI_OR,
+	XT_F_HMARK_SPORT_AND = 1 << XT_HMARK_SPORT_AND,
+	XT_F_HMARK_DPORT_AND = 1 << XT_HMARK_DPORT_AND,
+	XT_F_HMARK_SPORT_OR = 1 << XT_HMARK_SPORT_OR,
+	XT_F_HMARK_DPORT_OR = 1 << XT_HMARK_DPORT_OR,
+	XT_F_HMARK_PROTO_AND = 1 << XT_HMARK_PROTO_AND,
+	XT_F_HMARK_RND = 1 << XT_HMARK_RND,
+	XT_F_HMARK_MODULUS = 1 << XT_HMARK_MODULUS,
+	XT_F_HMARK_OFFSET = 1 << XT_HMARK_OFFSET,
+};
+
+union hports {
+	struct {
+		__u16	src;
+		__u16	dst;
+	} p16;
+	__u32	v32;
+};
+
+struct xt_hmark_info {
+	union nf_inet_addr	smask;		/* Source address mask */
+	union nf_inet_addr	dmask;		/* Dest address mask */
+	union hports		pmask;
+	union hports		pset;
+	__u32			spimask;
+	__u32			spiset;
+	__u16			flags;		/* Print out only */
+	__u16			prmask;		/* L4 Proto mask */
+	__u32			hashrnd;
+	__u32			hmod;		/* Modulus */
+	__u32			hoffs;		/* Offset */
+};
+
+#endif /* XT_HMARK_H_ */
-- 
1.7.2.3

^ permalink raw reply related

* [v5 PATCH 1/3] NETFILTER added flags to __ipv6_find_hdr()
From: Hans Schillstrom @ 2012-01-02 15:06 UTC (permalink / raw)
  To: kaber, pablo, jengelh, netfilter-devel, netdev; +Cc: hans, Hans Schillstrom
In-Reply-To: <1325516801-25488-1-git-send-email-hans.schillstrom@ericsson.com>

Two new flags to __ipv6_find_hdr,
One that tells us that this is a fragemnt.
One that stops at AH if any i.e. treat it like a transport header.
i.e. make handling of ESP and AH the same.

Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
 include/linux/netfilter_ipv6/ip6_tables.h |   16 ++++++++++++++--
 net/ipv6/netfilter/ip6_tables.c           |   19 ++++++++++++++-----
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f549adc..ee0c68e 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -288,9 +288,21 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb,
 
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);
+enum {
+	IP6T_FH_FRAG,
+	IP6T_FH_AUTH,
+	IP6T_FH_F_FRAG = 1 << IP6T_FH_FRAG,
+	IP6T_FH_F_AUTH = 1 << IP6T_FH_AUTH,
+};
 /* find specified header and get offset to it */
-extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-			 int target, unsigned short *fragoff);
+extern int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+			 int target, unsigned short *fragoff, int *fragflg);
+
+static inline int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+		  int target, unsigned short *fragoff)
+{
+	return __ipv6_find_hdr(skb, offset, target, fragoff, NULL);
+}
 
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 94874b0..8729bff 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -2302,9 +2302,13 @@ static void __exit ip6_tables_fini(void)
  * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
  * isn't NULL.
  *
+ * if flags != NULL AND
+ *    it's a fragment the frag flag "IP6T_FH_F_FRAG" will be set
+ *    it's an AH header and IP6T_FH_F_AUTH is set and target < 0
+ *      stop at AH (i.e. treat is as a transport header)
  */
-int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-		  int target, unsigned short *fragoff)
+int __ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+		  int target, unsigned short *fragoff, int *flags)
 {
 	unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
 	u8 nexthdr = ipv6_hdr(skb)->nexthdr;
@@ -2329,6 +2333,9 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			unsigned short _frag_off;
 			__be16 *fp;
+
+			if (flags)	/* Indicate that this is a fragment */
+				*flags |= IP6T_FH_F_FRAG;
 			fp = skb_header_pointer(skb,
 						start+offsetof(struct frag_hdr,
 							       frag_off),
@@ -2349,9 +2356,11 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 				return -ENOENT;
 			}
 			hdrlen = 8;
-		} else if (nexthdr == NEXTHDR_AUTH)
+		} else if (nexthdr == NEXTHDR_AUTH) {
+			if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
+				break;
 			hdrlen = (hp->hdrlen + 2) << 2;
-		else
+		} else
 			hdrlen = ipv6_optlen(hp);
 
 		nexthdr = hp->nexthdr;
@@ -2367,7 +2376,7 @@ EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
 EXPORT_SYMBOL(ip6t_ext_hdr);
-EXPORT_SYMBOL(ipv6_find_hdr);
+EXPORT_SYMBOL(__ipv6_find_hdr);
 
 module_init(ip6_tables_init);
 module_exit(ip6_tables_fini);
-- 
1.7.2.3

^ permalink raw reply related

* TCP communication for raw image transmission
From: Jean-Michel Hautbois @ 2012-01-02 15:21 UTC (permalink / raw)
  To: netdev

Hi all,

I am currently working on a way to send raw images (~400*300 YUV
4:2:0) at a relative high speed (raw image and not compressed image
due to specific codec issues).
This would represent about 57MBps/sec on a 100Mbps ethernet link.
This link is direct, nothing else will pass through it.

My question is a performance and efficiency question. Here is what I
am thinking about :
- I have the image on one computer at a known memory adress
- I want top transmit this picture using TCP packets with the rule
"1row = 1packet", maybe "2rows=1packet"
- All these packets have to go on an ethernet link and will be
received on another computer starting at a known memory adress
Something like this :
http://imageshack.us/photo/my-images/15/tcpmemory.png/

I was thinking about using TCP socket (of course) and the sendfile
syscall on sender side, splice syscall on the receiver side, but I
don't know if this is the best (and fastest) way to do it ?
I would like to avoid memory copy as much as possible as the systems
on which it will be done are embedded arm computers.
TCP is chosen in order to get ordered packets, but maybe am I wrong ?

Thanks for any clues you can give !
Regards,
JM

^ permalink raw reply

* [PATCH] sch_qfq: fix overflow in qfq_update_start()
From: Eric Dumazet @ 2012-01-02 15:47 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Stephen Hemminger, Dave Taht

grp->slot_shift is between 22 and 41, so using 32bit wide variables is
probably a typo.

This could explain QFQ hangs Dave reported to me, after 2^23 packets ?

(23 = 64 - 41)

Reported-by: Dave Taht <dave.taht@gmail.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Dave Taht <dave.taht@gmail.com>
---
 net/sched/sch_qfq.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 1033434..7b03254 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -817,11 +817,11 @@ skip_unblock:
 static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
 {
 	unsigned long mask;
-	uint32_t limit, roundedF;
+	u64 limit, roundedF;
 	int slot_shift = cl->grp->slot_shift;
 
 	roundedF = qfq_round_down(cl->F, slot_shift);
-	limit = qfq_round_down(q->V, slot_shift) + (1UL << slot_shift);
+	limit = qfq_round_down(q->V, slot_shift) + (1ULL << slot_shift);
 
 	if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) {
 		/* timestamp was stale */

^ permalink raw reply related

* Re: TCP communication for raw image transmission
From: Eric Dumazet @ 2012-01-02 15:59 UTC (permalink / raw)
  To: Jean-Michel Hautbois; +Cc: netdev
In-Reply-To: <CAL8zT=iSiKZfENdtng9gDtuRSuFNn4WZ69uuGapLVVEduFRVyQ@mail.gmail.com>

Le lundi 02 janvier 2012 à 16:21 +0100, Jean-Michel Hautbois a écrit :
> Hi all,
> 
> I am currently working on a way to send raw images (~400*300 YUV
> 4:2:0) at a relative high speed (raw image and not compressed image
> due to specific codec issues).
> This would represent about 57MBps/sec on a 100Mbps ethernet link.
> This link is direct, nothing else will pass through it.
> 
> My question is a performance and efficiency question. Here is what I
> am thinking about :
> - I have the image on one computer at a known memory adress
> - I want top transmit this picture using TCP packets with the rule
> "1row = 1packet", maybe "2rows=1packet"
> - All these packets have to go on an ethernet link and will be
> received on another computer starting at a known memory adress
> Something like this :
> http://imageshack.us/photo/my-images/15/tcpmemory.png/
> 
> I was thinking about using TCP socket (of course) and the sendfile
> syscall on sender side, splice syscall on the receiver side, but I
> don't know if this is the best (and fastest) way to do it ?
> I would like to avoid memory copy as much as possible as the systems
> on which it will be done are embedded arm computers.
> TCP is chosen in order to get ordered packets, but maybe am I wrong ?
> 
> Thanks for any clues you can give !
> Regards,
> JM
> --

Do you really need full image, or are some missing lines allowed ?

What is the length in bytes for a line ?

TCP stream and your bandwidth requirements would work only if you
guarantee not a single packet loss.

Using UDP (RTP) would allow you to respect any time limits at the
sender, yet allowing some drops on the network.

If you use a direct link, packets wont be re-ordered.

Is your ARM platform so slow it cannot afford copying 10 Mbytes per
second in skb ?

^ permalink raw reply

* Re: TCP communication for raw image transmission
From: Jean-Michel Hautbois @ 2012-01-02 16:08 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1325519943.2375.31.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

2012/1/2 Eric Dumazet <eric.dumazet@gmail.com>:
> Le lundi 02 janvier 2012 à 16:21 +0100, Jean-Michel Hautbois a écrit :
>> Hi all,
>>
>> I am currently working on a way to send raw images (~400*300 YUV
>> 4:2:0) at a relative high speed (raw image and not compressed image
>> due to specific codec issues).
>> This would represent about 57MBps/sec on a 100Mbps ethernet link.
>> This link is direct, nothing else will pass through it.
>>
>> My question is a performance and efficiency question. Here is what I
>> am thinking about :
>> - I have the image on one computer at a known memory adress
>> - I want top transmit this picture using TCP packets with the rule
>> "1row = 1packet", maybe "2rows=1packet"
>> - All these packets have to go on an ethernet link and will be
>> received on another computer starting at a known memory adress
>> Something like this :
>> http://imageshack.us/photo/my-images/15/tcpmemory.png/
>>
>> I was thinking about using TCP socket (of course) and the sendfile
>> syscall on sender side, splice syscall on the receiver side, but I
>> don't know if this is the best (and fastest) way to do it ?
>> I would like to avoid memory copy as much as possible as the systems
>> on which it will be done are embedded arm computers.
>> TCP is chosen in order to get ordered packets, but maybe am I wrong ?
>>
>> Thanks for any clues you can give !
>> Regards,
>> JM
>> --
>
> Do you really need full image, or are some missing lines allowed ?
>
> What is the length in bytes for a line ?

I can't accept any missing line, and line length in bytes is to be
decided but I think it would be something like 672bytes. This is why I
would put two lines per packet.

> TCP stream and your bandwidth requirements would work only if you
> guarantee not a single packet loss.
>
> Using UDP (RTP) would allow you to respect any time limits at the
> sender, yet allowing some drops on the network.

Yes, and again, I don't want any missing lines :).

> If you use a direct link, packets wont be re-ordered.
>
> Is your ARM platform so slow it cannot afford copying 10 Mbytes per
> second in skb ?

I don't really know what it can do, but it has to do encoding (even if
it is a SoC, with dedicated devices, memory has to be used).
The main problem I have, is that I don't have the two boards with me
today, and even if I can prototype on x86, I can't conclude as far as
I don't test on the real HW.
This is also why I want to prototype my best bet in the first try :).
And this is mainly a networking/memory problem.

Thanks for answering.
JM

^ permalink raw reply

* [PATCH net-next 1/2] mlx4_core: fix mtt range deallocation
From: Yevgeny Petrilin @ 2012-01-02 14:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp, marcela

From: Marcel Apfelbaum <marcela@mellanox.co.il>

The mtt range was allocated in mtt units but deallocated
in segments. Among the rest, this caused crash during hotplug removal

Reported-by: Yinghai Lu <yinghai@kernel.org> 
Signed-off-by: Marcel Apfelbaum <marcela@mellanox.co.il>
Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
---
 drivers/net/ethernet/mellanox/mlx4/mr.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index f7243b2..01df556 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -239,8 +239,8 @@ void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 	first_seg = offset / (1 << log_mtts_per_seg);
 
 	mlx4_buddy_free(&mr_table->mtt_buddy, first_seg, seg_order);
-	mlx4_table_put_range(dev, &mr_table->mtt_table, first_seg,
-			     first_seg + (1 << seg_order) - 1);
+	mlx4_table_put_range(dev, &mr_table->mtt_table, offset,
+			     offset + (1 << order) - 1);
 }
 
 static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
-- 
1.7.7

^ permalink raw reply related

* [PATCH net-next 2/2] mlx4_core: Elaborating limitation on VF port options
From: Yevgeny Petrilin @ 2012-01-02 14:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp

From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>

Showing which capabilities are not passed to VF
when executing QUERY_PORT

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/ethernet/mellanox/mlx4/fw.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 8bcc66f..a424a19 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -657,7 +657,12 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
 	u8 port_type;
 	int err;
 
-#define MLX4_VF_PORT_ETH_ONLY_MASK	0xE6
+#define MLX4_PORT_SUPPORT_IB		(1 << 0)
+#define MLX4_PORT_SUGGEST_TYPE		(1 << 3)
+#define MLX4_PORT_DEFAULT_SENSE		(1 << 4)
+#define MLX4_VF_PORT_ETH_ONLY_MASK	(0xff & ~MLX4_PORT_SUPPORT_IB & \
+					 ~MLX4_PORT_SUGGEST_TYPE & \
+					 ~MLX4_PORT_DEFAULT_SENSE)
 
 	err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0,
 			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
-- 
1.7.7

^ permalink raw reply related

* Re: TCP communication for raw image transmission
From: Eric Dumazet @ 2012-01-02 16:29 UTC (permalink / raw)
  To: Jean-Michel Hautbois; +Cc: netdev
In-Reply-To: <CAL8zT=giNe46FYQYxPkbshVfyG-DvCTKS0RLdiN8Kz+e-x-JFw@mail.gmail.com>

Le lundi 02 janvier 2012 à 17:08 +0100, Jean-Michel Hautbois a écrit :

> Yes, and again, I don't want any missing lines :).
> 

Go for tcp :)


> I don't really know what it can do, but it has to do encoding (even if
> it is a SoC, with dedicated devices, memory has to be used).
> The main problem I have, is that I don't have the two boards with me
> today, and even if I can prototype on x86, I can't conclude as far as
> I don't test on the real HW.

Thats going to be tough. You could at least use one board and test if it
can send 100Mbits using netperf (on a x86 target), and check cpu usage.

> This is also why I want to prototype my best bet in the first try :).
> And this is mainly a networking/memory problem.

If the 'no packet loss happens in the network' requirement is OK, then a
plain sendfile() [ or splice() ] will work.

Limiting each tcp frame to a 1 or 2 lines of your image is about
limiting MSS on your tcp session (setsockopt( ... TCP_MAXSEG ))

^ permalink raw reply

* Re: TCP communication for raw image transmission
From: Jean-Michel Hautbois @ 2012-01-02 16:40 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1325521745.18116.5.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

>> I don't really know what it can do, but it has to do encoding (even if
>> it is a SoC, with dedicated devices, memory has to be used).
>> The main problem I have, is that I don't have the two boards with me
>> today, and even if I can prototype on x86, I can't conclude as far as
>> I don't test on the real HW.
>
> Thats going to be tough. You could at least use one board and test if it
> can send 100Mbits using netperf (on a x86 target), and check cpu usage.

Mmmh, using netperf you would like to know what the client (my ARM
board) can do ?
How would you test it ? I can have an ARM board on one side, and the
x86 on the other...

>> This is also why I want to prototype my best bet in the first try :).
>> And this is mainly a networking/memory problem.
>
> If the 'no packet loss happens in the network' requirement is OK, then a
> plain sendfile() [ or splice() ] will work.
>
> Limiting each tcp frame to a 1 or 2 lines of your image is about
> limiting MSS on your tcp session (setsockopt( ... TCP_MAXSEG ))

Yes, the idea of limiting tcp frame to 2 lines is to avoid
fragmenting. So, with a MTU at 1500, MSS=1460, I can put 2 lines <=
730bytes. I will probably have ~700bytes.

JM

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox