Subject: Re: bad nat connection tracking performance with ip_gre

From: Timo Teräs <[email-masked]>
Date: Tue, 18 Aug 2009 15:45:07 +0300

Patrick McHardy wrote:
> Timo Teräs wrote:
>> However, if a local process on the router box is sending
>> packets that go to gre tunnel, each packet causes a new
>> lookup on nat table OUTPUT chain. This is easily verified
>> by doing flood ping on router box on private IP and the
>> counters on nat table OUTPUT chain default policy start
>> to get incremented wildly.

So ping test is not good as the connection tracking entry
is apparently removed once ICMP reply is received.

The one way to reliably to reproduce this is when I'm
sending packets with sendto() from user-land to nbma gre 
tunnel and specifying the nbma ip address.

>> Monitoring the connection tracking stats, it looks like
>> all packets are reusing the proper connection tracking
>> cache entry. But somehow the nat target still gets
>> called for the locally originating packets to gre.
>>
>> Any ideas how to fix this?
> 
> Please use the TRACE target in raw/OUTPUT to trace the flow of
> packets through the netfilter hooks:
> 
> modprobe ipt_LOG
> iptables -t raw -A OUTPUT -j TRACE

FORWARDED PACKET, does not hog CPU
----------------------------------

IN=eth1 OUT= MAC=x:x:x:x:x SRC=10.252.5.10 DST=239.255.12.42
LEN=1428 TOS=0x00 PREC=0x00 TTL=8 ID=31320 DF PROTO=UDP
SPT=34757 DPT=50002 LEN=1408
	1. mangle:INPUT
	2. filter:INPUT
	3. raw:PREROUTING
	4. mangle:PREROUTING

Next it turns it to GRE encapsulated packet like:

IN=eth1 OUT=gre1 SRC=0.0.0.0 DST=re.mo.te.ip LEN=0
TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=47
	1. mangle:FORWARD
	2. filter:FORWARD

Gets proper SRC and LEN at this point and:
	1. raw:OUTPUT
	2. mangle:OUTPUT
	3. nat:OUTPUT
	4. filter:OUTPUT

LOCALLY GENERATED PACKET, hogs CPU
----------------------------------

IN= OUT=eth1 SRC=10.252.5.1 DST=239.255.12.42 LEN=1344
TOS=0x00 PREC=0x00 TTL=8 ID=41664 DF PROTO=UDP SPT=47920
DPT=1234 LEN=1324 UID=1007 GID=1007
	1. raw:OUTPUT
	2. mangle:OUTPUT
	3. filter:OUTPUT
	4. mangle:POSTROUTING

Picked up by multicast routing.

IN=eth1 OUT= MAC= SRC=10.252.5.1 DST=239.255.12.42 LEN=1344
TOS=0x00 PREC=0x00 TTL=8 ID=41664 DF PROTO=UDP SPT=47920
DPT=1234 LEN=1324
	1. raw:PREROUTING
	2. mangle:PREROUTING

Forwarded to GRE tunnel.

IN=eth1 OUT=gre1 SRC=0.0.0.0 DST=re.mo.te.ip LEN=0 TOS=0x00
PREC=0x00 TTL=64 ID=0 DF PROTO=47
	1. mangle:FORWARD
	2. filter:FORWARD

Apparently GRE xmit code fixes it to:

IN= OUT=eth0 SRC=my.pub.lic.ip DST=re.mo.te.ip LEN=1372 TOS=0x00
PREC=0x00 TTL=64 ID=0 DF PROTO=47
	1. raw:OUTPUT
	2. mangle:OUTPUT

---

It's starting to smell like ip_gre problem. ipgre_header() seems
to set only the destination IP address. And that probably confuses
the connection tracking code for locally originating packets.

I suppose we should construct almost full IP header in ipgre_header().

- Timo