* RE: [openib-general] Re: [PATCH 1/2] iWARP Connection Manager.
From: Steve Wise @ 2006-06-02 13:57 UTC (permalink / raw)
To: Caitlin Bestler
Cc: Tom Tucker, Sean Hefty, netdev, rdreier, linux-kernel,
openib-general
In-Reply-To: <54AD0F12E08D1541B826BE97C98F99F150D3E6@NT-SJCA-0751.brcm.ad.broadcom.com>
> >
> > The problem is that we can't synchronously cancel an
> > outstanding connect request. Once we've asked the adapter to
> > connect, we can't tell him to stop, we have to wait for it to
> > fail. During the time period between when we ask to connect
> > and the adapter says yeah-or-nay, the user hits ctrl-C. This
> > is the case where disconnect and/or destroy gets called and
> > we have to block it waiting for the outstanding connect
> > request to complete.
> >
> > One alternative to this approach is to do the kfree of the
> > cm_id in the deref logic. This was the original design and
> > leaves the object around to handle the completion of the
> > connect and still allows the app to clean up and go away
> > without all this waitin' around. When the adapter finally
> > finishes and releases it's reference, the object is kfree'd.
> >
> > Hope this helps.
> >
> Why couldn't you synchronously put the cm_id in a state of
> "pending delete" and do the actual delete when the RNIC
> provides a response to the request?
This is Tom's "alternative" mentioned above. The provider already keeps
an explicit reference on the cm_id while it might possibly deliver an
event on that cm_id. So if you change deref to kfree the cm_id on its
last deref (when the refcnt reaches 0), then you can avoid blocking
during destroy...
> There could even be
> an optional method to see if the device is capable of
> cancelling the request. I know it can't yank a SYN back
> from the wire, but it could refrain from retransmitting.
I would suggest we don't add this optional method until we see an RNIC
that supports canceling a connect request or accept synchronously...
Steve.
^ permalink raw reply
* Re: [Bugme-new] [Bug 6613] New: iptables broken on 32-bit PReP (ARCH=ppc)
From: Patrick McHardy @ 2006-06-02 13:56 UTC (permalink / raw)
To: Meelis Roos; +Cc: Andrew Morton, bugme-daemon, netdev
In-Reply-To: <Pine.SOC.4.61.0606021617480.1298@math.ut.ee>
Meelis Roos wrote:
>> Very strange, this means that the initial table data must somehow
>> be wrong, but for some reason it still seems to get past the
>> size and offset checks for the filter table. I can't see how
>> loading the filter table could fail after the "Finished chain .."
>> messages without another message. Which kernel version did you
>> perform these test on?
>
>
> Yesterdays 2.6.17-rc5+git.
Please enable DEBUG_IP_FIREWALL_USER in net/netfilter/x_tables.c as well
and retry. Results of the raw or mangle table would also be interesting
because they contain a different number of built-in chains.
^ permalink raw reply
* Greeting!
From: Bibian M. @ 2006-06-02 13:43 UTC (permalink / raw)
To: Steffen
Hi my Dear Stranger!
I want to start my first letter from a question: "Is it possible to be happy without LOVE?"
I think that you will agree with me if the answer will be "NO WAY". Love is the most beautiful and exciting thing
that may happen between man and woman! It inspires us only for doing positive things towards each other.
One very famous writer said: "The beauty will rescue the world" i agree with his words but still i would add :
" LOVE and Beauty will rescure the world".
I hope you agree with me that Love is a big notion.
There's love to God, to Mother, to a child to the country where you were born, and there's love that joins a man
and woman for all their life. That is the LOVE i'm looking for! And i'm seeking for the man who is also eager to have
this life long adventure full of surprises and new experience we can share together! Will you join me for this trip?
I do realise that it should be very difficult to say "Yes" from the first letter having no idea about me.
That's why i just offer to get to know each other better though correspondence that will help us to reveal many things
about each other whether we mach perfectly or not. In addition you can look at my pictures and read some info about me here
http://ojbf5HinfFcJyKG9bDUk.i-am-waiting4love.net/
I hope you'll like what you see and read there.
Well closing my first letter to you i just want to thank you for reading it and i really hope that you'll share
my point of view on what i said above. I do really hope that you'll answer me soon.
so long...
Bi M.
^ permalink raw reply
* Re: [Bugme-new] [Bug 6613] New: iptables broken on 32-bit PReP (ARCH=ppc)
From: Meelis Roos @ 2006-06-02 13:18 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Andrew Morton, bugme-daemon, netdev
In-Reply-To: <4480385C.7080405@trash.net>
> Very strange, this means that the initial table data must somehow
> be wrong, but for some reason it still seems to get past the
> size and offset checks for the filter table. I can't see how
> loading the filter table could fail after the "Finished chain .."
> messages without another message. Which kernel version did you
> perform these test on?
Yesterdays 2.6.17-rc5+git.
--
Meelis Roos (mroos@linux.ee)
^ permalink raw reply
* Re: [Bugme-new] [Bug 6613] New: iptables broken on 32-bit PReP (ARCH=ppc)
From: Patrick McHardy @ 2006-06-02 13:08 UTC (permalink / raw)
To: Meelis Roos; +Cc: Andrew Morton, bugme-daemon, netdev
In-Reply-To: <Pine.SOC.4.61.0606012346350.28838@math.ut.ee>
Meelis Roos wrote:
>> Then lets try something different. Please enable the
>> DEBUG_IP_FIREWALL_USER define in net/ipv4/netfilter/ip_tables.c and
>> post the results, if any.
>
>
> On bootup I get this in dmesg (one Bad offset has been added):
>
> ip_tables: (C) 2000-2006 Netfilter Core Team
> Netfilter messages via NETLINK v0.30.
> ip_conntrack version 2.4 (1536 buckets, 12288 max) - 224 bytes per
> conntrack
> translate_table: size 632
> Bad offset cb437924
> ip_nat_init: can't setup rules.
>
> And on iptables -t nat -L
>
> translate_table: size 632
> Bad offset cb4368f4
> ip_nat_init: can't setup rules.
> translate_table: size 632
> Bad offset cb4368f4
> ip_nat_init: can't setup rules.
>
> Seems iptable_nat does not load at all this time.
>
> Modprobe iptable_filter still fails, dmesg contains
> translate_table: size 632
> Finished chain 1
> Finished chain 2
> Finished chain 3
>
> Next modprobe iptable_nat gives
>
> translate_table: size 632
> Bad offset c8e01944
> ip_nat_init: can't setup rules.
Very strange, this means that the initial table data must somehow
be wrong, but for some reason it still seems to get past the
size and offset checks for the filter table. I can't see how
loading the filter table could fail after the "Finished chain .."
messages without another message. Which kernel version did you
perform these test on?
^ permalink raw reply
* Re: 2.6.17-rc4: netfilter LOG messages truncated via NETCONSOLE
From: Frank van Maarseveen @ 2006-06-02 12:35 UTC (permalink / raw)
To: Patrick McHardy; +Cc: linux-kernel, Kernel Netdev Mailing List
In-Reply-To: <447F2537.1080807@trash.net>
On Thu, Jun 01, 2006 at 07:34:47PM +0200, Patrick McHardy wrote:
> Frank van Maarseveen wrote:
> > ok, now "tc -s -d qdisc show" says (after noticing missing netconsole
> > packets):
> >
> > qdisc pfifo_fast 0: dev eth0 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
> > Sent 155031 bytes 2067 pkt (dropped 0, overlimits 0 requeues 0)
> > backlog 0b 0p requeues 0
>
>
> Mhh no dropped packets. I tried to reproduce the problem by changing
> netconsole to always use the dev_queue_xmit path, but works flawlessly
> for me. Please try to find out if the packets are lost before or after
> the qdisc by looking at the packet counter.
qdisc pfifo_fast 0: dev eth0 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Sent 155031 bytes 2067 pkt (dropped 0, overlimits 0 requeues 0)
^^^^
This packet counter increases by 17: the TCP RST plus 16 netconsole
packets which are received. But it should have been 27 (TCP RST plus 26):
10 are missing (I thought 9 but it's 10).
>
> BTW: You still haven't sent me the packet dump (from the originating
> machine).
tcpdump:
10:50:22.811044 00:12:3f:85:17:52 > 00:08:c7:69:29:ae, ethertype IPv4 (0x0800), length 74: IP espoo.38629 > posio.21212: S 2489079094:2489079094(0) win 5840 <mss 1460,sackOK,timestamp 1359482768 0,nop,wscale 7>
10:50:22.811679 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 54: IP posio.21212 > espoo.38629: R 0:0(0) ack 2489079095 win 0
10:50:22.811731 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 55: IP posio.6665 > espoo.syslog: UDP, length: 13
10:50:22.811738 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 46: IP posio.6665 > espoo.syslog: UDP, length: 4
10:50:22.811745 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811752 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811760 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811766 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811773 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811780 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811787 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811795 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811801 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811809 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811816 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811823 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811830 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
10:50:22.811839 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
On "espoo" I do a "netcat posio 21212" to trigger the netfilter rule on
posio (there's only 1 rule):
Chain INPUT (policy ACCEPT 2876 packets, 743K bytes)
pkts bytes target prot opt in out source destination
1 60 LOG tcp -- * * 172.17.1.64 0.0.0.0/0 tcp dpt:21212 LOG flags 0 level 4
The netfilter message is sent back via netconsole from "posio" to "espoo"
except for 10 packets. This is a tcpdump done after rebooting "posio"
to 2.6.13.2 showing how it should have looked:
12:28:29.900384 00:12:3f:85:17:52 > 00:08:c7:69:29:ae, ethertype IPv4 (0x0800), length 74: IP espoo.45517 > posio.21212: S 122190451:122190451(0) win 5840 <mss 1460,sackOK,timestamp 1365370072 0,nop,wscale 7>
12:28:29.900939 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 54: IP posio.21212 > espoo.45517: R 0:0(0) ack 122190452 win 0
12:28:29.900995 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 55: IP posio.6665 > espoo.syslog: UDP, length: 13
12:28:29.901026 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 46: IP posio.6665 > espoo.syslog: UDP, length: 4
12:28:29.901055 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901082 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901112 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901158 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901185 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901212 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901238 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901275 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901301 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901308 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901314 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901319 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901326 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901332 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 45: IP posio.6665 > espoo.syslog: UDP, length: 3
12:28:29.901342 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901348 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901354 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901360 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901366 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901372 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901405 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901411 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901418 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
12:28:29.901423 00:08:c7:69:29:ae > 00:12:3f:85:17:52, ethertype IPv4 (0x0800), length 75: IP posio.6665 > espoo.syslog: UDP, length: 33
I'm unable to get the exact text due to varying packet loss at some
other place right now (verified by running tcpdump at both ends) but
it should be something like this (different machine, different case but
just to give an impression about the formatting):
May 31 10:39:02 sirkka IN=eth0 OUT=
May 31 10:39:02 sirkka MAC=
May 31 10:39:02 sirkka 00:
May 31 10:39:02 sirkka 60:
May 31 10:39:02 sirkka 97:
May 31 10:39:02 sirkka bc:
May 31 10:39:02 sirkka 4b:
May 31 10:39:02 sirkka a3:
May 31 10:39:02 sirkka 00:
May 31 10:39:02 sirkka 04:
May 31 10:39:02 sirkka 9a:
May 31 10:39:02 sirkka a0:
May 31 10:39:02 sirkka 1d:
May 31 10:39:02 sirkka d1:
May 31 10:39:02 sirkka 08:
May 31 10:39:02 sirkka 00
May 31 10:39:02 sirkka SRC=172.19.1.4 DST=172.17.1.110
May 31 10:39:02 sirkka LEN=48 TOS=0x00 PREC=0x00 TTL=126 ID=10359
May 31 10:39:02 sirkka DF
May 31 10:39:02 sirkka PROTO=TCP
May 31 10:39:02 sirkka SPT=1681 DPT=445
May 31 10:39:02 sirkka WINDOW=64512
May 31 10:39:02 sirkka RES=0x00
May 31 10:39:02 sirkka SYN
May 31 10:39:02 sirkka URGP=0
May 31 10:39:02 sirkka
--
Frank
^ permalink raw reply
* Re: [PATCH] softmac: Fix handling of authentication failure
From: John W. Linville @ 2006-06-02 12:04 UTC (permalink / raw)
To: Daniel Drake; +Cc: Larry Finger, netdev, johannes
In-Reply-To: <44800E74.9070605@gentoo.org>
On Fri, Jun 02, 2006 at 11:09:56AM +0100, Daniel Drake wrote:
> Larry Finger wrote:
> >This statement fails to compile on my system using Linus' tree, because
> >ieee80211softmac_disassoc needs a second argument - the reason. It seems
> >as if WLAN_REASON_PREV_AUTH_NOT_VALID would be appropriate.
>
> Thanks for pointing that out. This patch depends on a patch titled
> "softmac: deauthentication implies deassociation" which is apparently
> not present in Linus' tree.
That patch is in the upstream branch (also available in the master
branch) of wireless-2.6, which is probably what anyone doing wireless
patches should(*) be using.
The approved release process only allows for non-bugfix patches
in the first two weeks after a Linus blesses a new kernel release.
After that only bugfixes are allowed, with non-bugfix patches getting
queued for the next merge window. The upstream branch represents
that queue of patches.
Hth!
John
(*) The exception being those workign on Devicescape-related patches,
who should be working off the master branch of wireless-dev.
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* new driver for IBM ethernet chip
From: Christoph Raisch @ 2006-06-02 11:02 UTC (permalink / raw)
To: netdev; +Cc: Marcus Eder, Jan-Bernd Themann
We're currently developing a new Ethernet device driver for a 10G IBM chip
for System p. (ppc64)
A later version of the driver should end up in mainline kernel.
How should we proceed to get first comments by the community?
Either post this code as a patch to netdev or
put a full tarball on for example sourceforge?
Gruss / Regards . . . Christoph Raisch
christoph raisch, HCAD teamlead, IODF2 (d/3627), ibm boeblingen lab,
phone: (+49/0)7031-16 4584, fax: -16 2042, loc: 71032-05-003, internet:
raisch@de.ibm.com
^ permalink raw reply
* Re: netif_tx_disable and lockless TX
From: Robert Olsson @ 2006-06-02 10:46 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Robert Olsson, hadi, Herbert Xu, netdev, jgarzik, mchan,
David Miller, Andi Kleen
In-Reply-To: <447FAFAD.9000503@osdl.org>
Stephen Hemminger writes:
> I also noticed that you really don't save much by doing TX cleaning at
> hardirq, because in hardirq you need to do dev_kfree_irq and that causes
> a softirq (for the routing case where users=1). So when routing it
> doesn't make much difference, both methods cause the softirq delayed
> processing to be invoked. For locally generated packets which are
> cloned, the hardirq will drop the ref count, and that is faster than
> doing the whole softirq round trip.
Right. Also the other way around, repeated ->poll can avoid TX hardirq's.
Cheers.
--ro
^ permalink raw reply
* Netchannel: TCP memcpy() to mapped support. Patch.
From: Evgeniy Polyakov @ 2006-06-02 10:29 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, caitlinb, kelly, rusty
In-Reply-To: <20060602093739.GA6770@2ka.mipt.ru>
Hello, developers.
Attached netchannel psubsystem patch which implements TCP memcpy()
(into preallocated area which could be mapped) reading and
UDP copy_to_user()/memcpy() reading.
Implementations fairly ugly yet.
Netchannels currently use two queue dereferencings to work with socket's
queue processing:
- from netchannel's queue which is filled in interrupt
- from socket's queue which is filled in process context
Patch, userspace and implementation details can be found
on netchannel homepage:
http://tservice.net.ru/~s0mbre/old/?section=projects&item=netchannel
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index f48bef1..7a4a758 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -315,3 +315,5 @@ ENTRY(sys_call_table)
.long sys_splice
.long sys_sync_file_range
.long sys_tee /* 315 */
+ .long sys_vmsplice
+ .long sys_netchannel_control
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5a92fed..fdfb997 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -696,4 +696,5 @@ ia32_sys_call_table:
.quad sys_sync_file_range
.quad sys_tee
.quad compat_sys_vmsplice
+ .quad sys_netchannel_control
ia32_syscall_end:
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index eb4b152..777cd85 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -322,8 +322,9 @@
#define __NR_sync_file_range 314
#define __NR_tee 315
#define __NR_vmsplice 316
+#define __NR_netchannel_control 317
-#define NR_syscalls 317
+#define NR_syscalls 318
/*
* user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index feb77cb..08c230e 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -617,8 +617,10 @@ __SYSCALL(__NR_tee, sys_tee)
__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
#define __NR_vmsplice 278
__SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_netchannel_control 279
+__SYSCALL(__NR_vmsplice, sys_netchannel_control)
-#define __NR_syscall_max __NR_vmsplice
+#define __NR_syscall_max __NR_netchannel_control
#ifndef __NO_STUBS
diff --git a/include/linux/netchannel.h b/include/linux/netchannel.h
new file mode 100644
index 0000000..abb0b8d
--- /dev/null
+++ b/include/linux/netchannel.h
@@ -0,0 +1,102 @@
+/*
+ * netchannel.h
+ *
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __NETCHANNEL_H
+#define __NETCHANNEL_H
+
+#include <linux/types.h>
+
+enum netchannel_commands {
+ NETCHANNEL_CREATE = 0,
+ NETCHANNEL_REMOVE,
+ NETCHANNEL_BIND,
+ NETCHANNEL_READ,
+ NETCHANNEL_DUMP,
+};
+
+enum netchannel_type {
+ NETCHANNEL_COPY_USER = 0,
+ NETCHANNEL_MMAP,
+ NETCHANEL_VM_HACK,
+};
+
+struct unetchannel
+{
+ __u32 src, dst; /* source/destination hashes */
+ __u16 sport, dport; /* source/destination ports */
+ __u8 proto; /* IP protocol number */
+ __u8 type; /* Netchannel type */
+ __u8 memory_limit_order; /* Memor limit order */
+ __u8 reserved;
+};
+
+struct unetchannel_control
+{
+ struct unetchannel unc;
+ __u32 cmd;
+ __u32 len;
+ __u32 flags;
+ __u32 timeout;
+ unsigned int fd;
+};
+
+#ifdef __KERNEL__
+
+struct netchannel
+{
+ struct hlist_node node;
+ atomic_t refcnt;
+ struct rcu_head rcu_head;
+ struct unetchannel unc;
+ unsigned long hit;
+
+ struct page * (*nc_alloc_page)(unsigned int size);
+ void (*nc_free_page)(struct page *page);
+ int (*nc_read_data)(struct netchannel *, unsigned int *timeout, unsigned int *len, void *arg);
+
+ struct sk_buff_head recv_queue;
+ wait_queue_head_t wait;
+
+ unsigned int qlen;
+
+ void *priv;
+
+ struct inode *inode;
+};
+
+struct netchannel_cache_head
+{
+ struct hlist_head head;
+ struct mutex mutex;
+};
+
+#define NETCHANNEL_MAX_ORDER 31
+#define NETCHANNEL_MIN_ORDER PAGE_SHIFT
+
+struct netchannel_mmap
+{
+ struct page **page;
+ unsigned int pnum;
+ unsigned int poff;
+};
+
+#endif /* __KERNEL__ */
+#endif /* __NETCHANNEL_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a461b51..9924911 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -684,6 +684,15 @@ extern void dev_queue_xmit_nit(struct s
extern void dev_init(void);
+#ifdef CONFIG_NETCHANNEL
+extern int netchannel_recv(struct sk_buff *skb);
+#else
+static int netchannel_recv(struct sk_buff *skb)
+{
+ return -1;
+}
+#endif
+
extern int netdev_nit;
extern int netdev_budget;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f8f2347..69f0c32 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -265,7 +265,8 @@ struct sk_buff {
nfctinfo:3;
__u8 pkt_type:3,
fclone:2,
- ipvs_property:1;
+ ipvs_property:1,
+ netchannel:1;
__be16 protocol;
void (*destructor)(struct sk_buff *skb);
@@ -314,6 +315,18 @@ static inline struct sk_buff *alloc_skb(
return __alloc_skb(size, priority, 0);
}
+#ifdef CONFIG_NETCHANNEL
+struct unetchannel;
+extern struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size,
+ unsigned int total_size, gfp_t gfp_mask);
+#else
+static struct sk_buff *netchannel_alloc(void *unc, unsigned int header_size,
+ unsigned int total_size, gfp_t gfp_mask)
+{
+ return NULL;
+}
+#endif
+
static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
gfp_t priority)
{
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9ab2ddd..036a221 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -298,6 +298,7 @@ extern int csum_partial_copy_fromiovecen
extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int memcpy_toiovec_copy(struct iovec *v, unsigned char *kdata, int len);
extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen);
extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3996960..8c22875 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -582,4 +582,6 @@ asmlinkage long sys_tee(int fdin, int fd
asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
unsigned int flags);
+asmlinkage long sys_netchannel_control(void __user *arg);
+
#endif
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5433195..1747fc3 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -132,3 +132,5 @@ cond_syscall(sys_mincore);
cond_syscall(sys_madvise);
cond_syscall(sys_mremap);
cond_syscall(sys_remap_file_pages);
+
+cond_syscall(sys_netchannel_control);
diff --git a/net/Kconfig b/net/Kconfig
index 4193cdc..465e37b 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -66,6 +66,14 @@ source "net/ipv6/Kconfig"
endif # if INET
+config NETCHANNEL
+ bool "Network channels"
+ ---help---
+ Network channels are peer-to-peer abstraction, which allows to create
+ high performance communications.
+ Main advantages are unified address cache, protocol processing moved
+ to userspace, receiving zero-copy support and other interesting features.
+
menuconfig NETFILTER
bool "Network packet filtering (replaces ipchains)"
---help---
diff --git a/net/core/Makefile b/net/core/Makefile
index 79fe12c..7119812 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_WIRELESS_EXT) += wireless.o
obj-$(CONFIG_NETPOLL) += netpoll.o
+obj-$(CONFIG_NETCHANNEL) += netchannel.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index aecddcc..3db8873 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -235,6 +235,8 @@ void skb_kill_datagram(struct sock *sk,
EXPORT_SYMBOL(skb_kill_datagram);
+typedef int (* copy_iovec_t)(struct iovec *iov, unsigned char *kdata, int len);
+
/**
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
* @skb: buffer to copy
@@ -249,12 +251,13 @@ int skb_copy_datagram_iovec(const struct
{
int start = skb_headlen(skb);
int i, copy = start - offset;
+ copy_iovec_t func = (skb->netchannel)?&memcpy_toiovec_copy:&memcpy_toiovec;
/* Copy header. */
if (copy > 0) {
if (copy > len)
copy = len;
- if (memcpy_toiovec(to, skb->data + offset, copy))
+ if (func(to, skb->data + offset, copy))
goto fault;
if ((len -= copy) == 0)
return 0;
@@ -277,7 +280,7 @@ int skb_copy_datagram_iovec(const struct
if (copy > len)
copy = len;
vaddr = kmap(page);
- err = memcpy_toiovec(to, vaddr + frag->page_offset +
+ err = func(to, vaddr + frag->page_offset +
offset - start, copy);
kunmap(page);
if (err)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9ab3cfa..2721111 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1712,6 +1712,10 @@ int netif_receive_skb(struct sk_buff *sk
}
}
+ ret = netchannel_recv(skb);
+ if (!ret)
+ goto out;
+
#ifdef CONFIG_NET_CLS_ACT
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 65e4b56..8d19ed7 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -98,6 +98,23 @@ int memcpy_toiovec(struct iovec *iov, un
return 0;
}
+int memcpy_toiovec_copy(struct iovec *iov, unsigned char *kdata, int len)
+{
+ while (len > 0) {
+ if (iov->iov_len) {
+ int copy = min_t(unsigned int, iov->iov_len, len);
+ memcpy(iov->iov_base, kdata, copy);
+ kdata += copy;
+ len -= copy;
+ iov->iov_len -= copy;
+ iov->iov_base += copy;
+ }
+ iov++;
+ }
+
+ return 0;
+}
+
/*
* Copy iovec to kernel. Returns -EFAULT on error.
*
@@ -237,3 +254,4 @@ EXPORT_SYMBOL(csum_partial_copy_fromiove
EXPORT_SYMBOL(memcpy_fromiovec);
EXPORT_SYMBOL(memcpy_fromiovecend);
EXPORT_SYMBOL(memcpy_toiovec);
+EXPORT_SYMBOL(memcpy_toiovec_copy);
diff --git a/net/core/netchannel.c b/net/core/netchannel.c
new file mode 100644
index 0000000..e5493b7
--- /dev/null
+++ b/net/core/netchannel.c
@@ -0,0 +1,1157 @@
+/*
+ * netchannel.c
+ *
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/linkage.h>
+#include <linux/notifier.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/netchannel.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <linux/udp.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
+
+#include <asm/uaccess.h>
+
+static unsigned int netchannel_hash_order = 8;
+static struct netchannel_cache_head ***netchannel_hash_table;
+static kmem_cache_t *netchannel_cache;
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inetaddr_notifier = {
+ .notifier_call = &netchannel_inetaddr_notifier_call
+};
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inet6addr_notifier = {
+ .notifier_call = &netchannel_inet6addr_notifier_call
+};
+#endif
+
+static inline unsigned int netchannel_hash(struct unetchannel *unc)
+{
+ unsigned int h = (unc->dst ^ unc->dport) ^ (unc->src ^ unc->sport);
+ h ^= h >> 16;
+ h ^= h >> 8;
+ h ^= unc->proto;
+ return h & ((1 << 2*netchannel_hash_order) - 1);
+}
+
+static inline void netchannel_convert_hash(unsigned int hash, unsigned int *col, unsigned int *row)
+{
+ *row = hash & ((1 << netchannel_hash_order) - 1);
+ *col = (hash >> netchannel_hash_order) & ((1 << netchannel_hash_order) - 1);
+}
+
+static struct netchannel_cache_head *netchannel_bucket(struct unetchannel *unc)
+{
+ unsigned int hash = netchannel_hash(unc);
+ unsigned int col, row;
+
+ netchannel_convert_hash(hash, &col, &row);
+ return netchannel_hash_table[col][row];
+}
+
+static inline int netchannel_hash_equal_full(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+ return (unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) &&
+ (unc1->sport == unc2->sport) && (unc1->src == unc2->src) &&
+ (unc1->proto == unc2->proto);
+}
+
+static inline int netchannel_hash_equal_dest(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+ return ((unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) && (unc1->proto == unc2->proto));
+}
+
+static struct netchannel *netchannel_check_dest(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+ struct netchannel *nc;
+ struct hlist_node *node;
+ int found = 0;
+
+ hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+ if (netchannel_hash_equal_dest(&nc->unc, unc)) {
+ found = 1;
+ break;
+ }
+ }
+
+ return (found)?nc:NULL;
+}
+
+static struct netchannel *netchannel_check_full(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+ struct netchannel *nc;
+ struct hlist_node *node;
+ int found = 0;
+
+ hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+ if (netchannel_hash_equal_full(&nc->unc, unc)) {
+ found = 1;
+ break;
+ }
+ }
+
+ return (found)?nc:NULL;
+}
+
+static void netchannel_mmap_cleanup(struct netchannel *nc)
+{
+ unsigned int i;
+ struct netchannel_mmap *m = nc->priv;
+
+ for (i=0; i<m->pnum; ++i)
+ __free_page(m->page[i]);
+
+ kfree(m);
+}
+
+static void netchannel_cleanup(struct netchannel *nc)
+{
+ switch (nc->unc.type) {
+ case NETCHANNEL_COPY_USER:
+ break;
+ case NETCHANNEL_MMAP:
+ netchannel_mmap_cleanup(nc);
+ break;
+ default:
+ break;
+ }
+}
+
+static void netchannel_free_rcu(struct rcu_head *rcu)
+{
+ struct netchannel *nc = container_of(rcu, struct netchannel, rcu_head);
+
+ netchannel_cleanup(nc);
+ kmem_cache_free(netchannel_cache, nc);
+}
+
+static inline void netchannel_get(struct netchannel *nc)
+{
+ atomic_inc(&nc->refcnt);
+}
+
+static inline void netchannel_put(struct netchannel *nc)
+{
+ if (atomic_dec_and_test(&nc->refcnt))
+ call_rcu(&nc->rcu_head, &netchannel_free_rcu);
+}
+
+static inline void netchannel_dump_info_unc(struct unetchannel *unc, char *prefix, unsigned long hit, int err)
+{
+ u32 src, dst;
+ u16 sport, dport;
+
+ dst = unc->dst;
+ src = unc->src;
+ dport = ntohs(unc->dport);
+ sport = ntohs(unc->sport);
+
+ printk(KERN_NOTICE "netchannel: %s %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u, "
+ "proto: %u, type: %u, order: %u, hit: %lu, err: %d.\n",
+ prefix, NIPQUAD(src), sport, NIPQUAD(dst), dport,
+ unc->proto, unc->type, unc->memory_limit_order, hit, err);
+}
+
+static int netchannel_convert_skb_ipv6(struct sk_buff *skb, struct unetchannel *unc)
+{
+ /*
+ * Hash IP addresses into src/dst. Setup TCP/UDP ports.
+ * Not supported yet.
+ */
+ return -1;
+}
+
+static int netchannel_convert_skb_ipv4(struct sk_buff *skb, struct unetchannel *unc)
+{
+ struct iphdr *iph;
+ u32 len;
+ struct tcphdr *th;
+ struct udphdr *uh;
+
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ goto inhdr_error;
+
+ iph = skb->nh.iph;
+
+ if (iph->ihl < 5 || iph->version != 4)
+ goto inhdr_error;
+
+ if (!pskb_may_pull(skb, iph->ihl*4))
+ goto inhdr_error;
+
+ iph = skb->nh.iph;
+
+ if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+ goto inhdr_error;
+
+ len = ntohs(iph->tot_len);
+ if (skb->len < len || len < (iph->ihl*4))
+ goto inhdr_error;
+
+ if (pskb_trim_rcsum(skb, len))
+ goto inhdr_error;
+
+ unc->dst = iph->daddr;
+ unc->src = iph->saddr;
+ unc->proto = iph->protocol;
+
+ len = skb->len;
+
+ skb->h.raw = skb->nh.raw + iph->ihl*4;
+
+ switch (unc->proto) {
+ case IPPROTO_TCP:
+ if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
+ goto inhdr_error;
+ th = skb->h.th;
+
+ if (th->doff < sizeof(struct tcphdr) / 4)
+ goto inhdr_error;
+
+ unc->dport = th->dest;
+ unc->sport = th->source;
+ break;
+ case IPPROTO_UDP:
+ if (!pskb_may_pull(skb, sizeof(struct udphdr)))
+ goto inhdr_error;
+ uh = skb->h.uh;
+
+ if (ntohs(uh->len) < sizeof(struct udphdr))
+ goto inhdr_error;
+
+ unc->dport = uh->dest;
+ unc->sport = uh->source;
+ break;
+ default:
+ goto inhdr_error;
+ }
+
+ return 0;
+
+inhdr_error:
+ return -1;
+}
+
+static int netchannel_convert_skb(struct sk_buff *skb, struct unetchannel *unc)
+{
+ if (skb->pkt_type == PACKET_OTHERHOST)
+ return -1;
+
+ switch (ntohs(skb->protocol)) {
+ case ETH_P_IP:
+ return netchannel_convert_skb_ipv4(skb, unc);
+ case ETH_P_IPV6:
+ return netchannel_convert_skb_ipv6(skb, unc);
+ default:
+ return -1;
+ }
+}
+
+/*
+ * By design netchannels allow to "allocate" data
+ * not only from SLAB cache, but get it from mapped area
+ * or from VFS cache (requires process' context or preallocation).
+ */
+struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size,
+ unsigned int total_size, gfp_t gfp_mask)
+{
+ struct netchannel *nc;
+ struct netchannel_cache_head *bucket;
+ int err;
+ struct sk_buff *skb = NULL;
+ unsigned int size, pnum, i;
+
+ skb = alloc_skb(header_size, gfp_mask);
+ if (!skb)
+ return NULL;
+
+ rcu_read_lock();
+ bucket = netchannel_bucket(unc);
+ nc = netchannel_check_full(unc, bucket);
+ if (!nc) {
+ err = -ENODEV;
+ goto err_out_free_skb;
+ }
+
+ if (!nc->nc_alloc_page || !nc->nc_free_page) {
+ err = -EINVAL;
+ goto err_out_free_skb;
+ }
+
+ netchannel_get(nc);
+
+ size = total_size - header_size;
+ pnum = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+ for (i=0; i<pnum; ++i) {
+ unsigned int cs = min_t(unsigned int, PAGE_SIZE, size);
+ struct page *page;
+
+ page = nc->nc_alloc_page(cs);
+ if (!page)
+ break;
+
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, cs);
+
+ skb->len += cs;
+ skb->data_len += cs;
+ skb->truesize += cs;
+
+ size -= cs;
+ }
+
+ if (i < pnum) {
+ pnum = i;
+ err = -ENOMEM;
+ goto err_out_free_frags;
+ }
+
+ rcu_read_unlock();
+
+ return skb;
+
+err_out_free_frags:
+ for (i=0; i<pnum; ++i) {
+ unsigned int cs = skb_shinfo(skb)->frags[i].size;
+ struct page *page = skb_shinfo(skb)->frags[i].page;
+
+ nc->nc_free_page(page);
+
+ skb->len -= cs;
+ skb->data_len -= cs;
+ skb->truesize -= cs;
+ }
+
+err_out_free_skb:
+ kfree_skb(skb);
+ return NULL;
+}
+
+int netchannel_recv(struct sk_buff *skb)
+{
+ struct netchannel *nc;
+ struct unetchannel unc;
+ struct netchannel_cache_head *bucket;
+ int err;
+
+ if (!netchannel_hash_table)
+ return -ENODEV;
+
+ rcu_read_lock();
+
+ err = netchannel_convert_skb(skb, &unc);
+ if (err)
+ goto unlock;
+
+ bucket = netchannel_bucket(&unc);
+ nc = netchannel_check_full(&unc, bucket);
+ if (!nc) {
+ err = -ENODEV;
+ goto unlock;
+ }
+
+ nc->hit++;
+#if 0
+ if (nc->qlen + skb->len > (1 << nc->unc.memory_limit_order)) {
+ kfree_skb(skb);
+ err = 0;
+ goto unlock;
+ }
+#endif
+ nc->qlen += skb->len;
+ skb_queue_tail(&nc->recv_queue, skb);
+ wake_up(&nc->wait);
+
+unlock:
+ rcu_read_unlock();
+
+ return err;
+}
+
+static int netchannel_wait_for_packet(struct netchannel *nc, long *timeo_p)
+{
+ int error = 0;
+ DEFINE_WAIT(wait);
+
+ prepare_to_wait_exclusive(&nc->wait, &wait, TASK_INTERRUPTIBLE);
+
+ if (skb_queue_empty(&nc->recv_queue)) {
+ if (signal_pending(current))
+ goto interrupted;
+
+ *timeo_p = schedule_timeout(*timeo_p);
+ }
+out:
+ finish_wait(&nc->wait, &wait);
+ return error;
+interrupted:
+ error = (*timeo_p == MAX_SCHEDULE_TIMEOUT) ? -ERESTARTSYS : -EINTR;
+ goto out;
+}
+
+static struct sk_buff *netchannel_get_skb(struct netchannel *nc, unsigned int *timeout, int *error)
+{
+ struct sk_buff *skb = NULL;
+ long tm = *timeout;
+
+ *error = 0;
+
+ while (1) {
+ skb = skb_dequeue(&nc->recv_queue);
+ if (skb) {
+ nc->qlen -= skb->len;
+ break;
+ }
+
+ if (*timeout) {
+ *error = netchannel_wait_for_packet(nc, &tm);
+ if (*error) {
+ *timeout = tm;
+ break;
+ }
+ tm = *timeout;
+ } else {
+ *error = -EAGAIN;
+ break;
+ }
+ }
+
+ return skb;
+}
+
+static int netchannel_copy_to_user_tcp(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+ struct tcphdr *th;
+ int err = -ENODEV;
+ struct socket *sock;
+ struct sock *sk;
+ struct sk_buff *skb;
+ struct iovec iov;
+ struct msghdr msg;
+ unsigned flags = MSG_DONTWAIT;
+ unsigned int size = *len, read = 0, osize = *len;
+ unsigned int slen, process;
+
+ if (!nc->inode)
+ goto err_out;
+ sock = SOCKET_I(nc->inode);
+ if (!sock || !sock->sk)
+ goto err_out;
+
+ sk = sock->sk;
+
+ while (size) {
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ msg.msg_iovlen=1;
+ msg.msg_iov=&iov;
+ msg.msg_name=NULL;
+ msg.msg_namelen=0;
+ msg.msg_flags = flags;
+ iov.iov_len=size;
+ iov.iov_base=arg;
+
+ err = sock_recvmsg(sock, &msg, iov.iov_len, flags);
+
+ if (err > 0) {
+ size -= err;
+ read += err;
+
+ if (!size) {
+ err = 0;
+ break;
+ }
+ } else if (err && err != -EAGAIN)
+ break;
+
+ err = 0;
+ process = 0;
+ slen = 0;
+
+ while (slen < size) {
+ if (skb_queue_empty(&nc->recv_queue) && slen)
+ break;
+ skb = netchannel_get_skb(nc, timeout, &err);
+ if (!skb)
+ break;
+ skb->netchannel = 1;
+
+ __skb_pull(skb, skb->nh.iph->ihl*4);
+
+ skb->h.raw = skb->data;
+
+ th = skb->h.th;
+ TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+ TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+ skb->len - th->doff * 4);
+ TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+ TCP_SKB_CB(skb)->when = 0;
+ TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ if (sk->sk_backlog_rcv) {
+ err = sk->sk_backlog_rcv(sk, skb);
+ if (err)
+ break;
+ }
+
+ slen += skb->len;
+ }
+ }
+
+ *len = read;
+
+ return err;
+
+err_out:
+ return err;
+}
+
+static int netchannel_copy_to_user(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+ unsigned int copied;
+ struct sk_buff *skb;
+ struct iovec to;
+ int err;
+
+ skb = netchannel_get_skb(nc, timeout, &err);
+ if (!skb)
+ return err;
+
+ to.iov_base = arg;
+ to.iov_len = *len;
+
+ copied = skb->len;
+ if (copied > *len)
+ copied = *len;
+
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ err = skb_copy_datagram_iovec(skb, 0, &to, copied);
+ } else {
+ err = skb_copy_and_csum_datagram_iovec(skb,0, &to);
+ }
+
+ *len = (err == 0)?copied:0;
+
+ kfree_skb(skb);
+
+ return err;
+}
+
+int netchannel_skb_copy_datagram(const struct sk_buff *skb, int offset,
+ void *to, int len)
+{
+ int start = skb_headlen(skb);
+ int i, copy = start - offset;
+
+ /* Copy header. */
+ if (copy > 0) {
+ if (copy > len)
+ copy = len;
+ memcpy(to, skb->data + offset, copy);
+
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ to += copy;
+ }
+
+ /* Copy paged appendix. Hmm... why does this look so complicated? */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + skb_shinfo(skb)->frags[i].size;
+ if ((copy = end - offset) > 0) {
+ u8 *vaddr;
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ struct page *page = frag->page;
+
+ if (copy > len)
+ copy = len;
+ vaddr = kmap(page);
+ memcpy(to, vaddr + frag->page_offset +
+ offset - start, copy);
+ kunmap(page);
+ if (!(len -= copy))
+ return 0;
+ offset += copy;
+ to += copy;
+ }
+ start = end;
+ }
+
+ if (skb_shinfo(skb)->frag_list) {
+ struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+ for (; list; list = list->next) {
+ int end;
+
+ BUG_TRAP(start <= offset + len);
+
+ end = start + list->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ if (netchannel_skb_copy_datagram(list,
+ offset - start,
+ to, copy))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ to += copy;
+ }
+ start = end;
+ }
+ }
+ if (!len)
+ return 0;
+
+fault:
+ return -EFAULT;
+}
+
+static int netchannel_copy_to_mem(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+ struct netchannel_mmap *m = nc->priv;
+ unsigned int copied, skb_offset = 0;
+ struct sk_buff *skb;
+ int err;
+
+ skb = netchannel_get_skb(nc, timeout, &err);
+ if (!skb)
+ return err;
+
+ copied = skb->len;
+
+ while (copied) {
+ int pnum = ((m->poff % PAGE_SIZE) % m->pnum);
+ struct page *page = m->page[pnum];
+ void *page_map, *ptr;
+ unsigned int sz, left;
+
+ left = PAGE_SIZE - (m->poff % (PAGE_SIZE - 1));
+ sz = min_t(unsigned int, left, copied);
+
+ if (!sz) {
+ err = -ENOSPC;
+ goto err_out;
+ }
+
+ page_map = kmap_atomic(page, KM_USER0);
+ if (!page_map) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ ptr = page_map + (m->poff % (PAGE_SIZE - 1));
+
+ err = netchannel_skb_copy_datagram(skb, skb_offset, ptr, sz);
+ if (err) {
+ kunmap_atomic(page_map, KM_USER0);
+ goto err_out;
+ }
+ kunmap_atomic(page_map, KM_USER0);
+
+ copied -= sz;
+ m->poff += sz;
+ skb_offset += sz;
+#if 1
+ if (m->poff >= PAGE_SIZE * m->pnum) {
+ //netchannel_dump_info_unc(&nc->unc, "rewind", nc->hit, 0);
+ m->poff = 0;
+ }
+#endif
+ }
+ *len = skb->len;
+
+ err = 0;
+
+err_out:
+ kfree_skb(skb);
+
+ return err;
+}
+
+static int netchannel_mmap_setup(struct netchannel *nc)
+{
+ struct netchannel_mmap *m;
+ unsigned int i, pnum;
+
+ pnum = (1 << (nc->unc.memory_limit_order - NETCHANNEL_MIN_ORDER));
+
+ m = kzalloc(sizeof(struct netchannel_mmap) + sizeof(struct page *) * pnum, GFP_KERNEL);
+ if (!m)
+ return -ENOMEM;
+
+ m->page = (struct page **)(m + 1);
+ m->pnum = pnum;
+
+ for (i=0; i<pnum; ++i) {
+ m->page[i] = alloc_page(GFP_KERNEL);
+ if (!m->page[i])
+ break;
+ }
+
+ if (i < pnum) {
+ pnum = i;
+ goto err_out_free;
+ }
+
+ nc->priv = m;
+
+ switch (nc->unc.proto) {
+ case IPPROTO_TCP:
+ nc->nc_read_data = &netchannel_copy_to_user_tcp;
+ break;
+ case IPPROTO_UDP:
+ default:
+ nc->nc_read_data = &netchannel_copy_to_mem;
+ break;
+ }
+
+ return 0;
+
+err_out_free:
+ for (i=0; i<pnum; ++i)
+ __free_page(m->page[i]);
+
+ kfree(m);
+
+ return -ENOMEM;
+
+}
+
+static int netchannel_copy_user_setup(struct netchannel *nc)
+{
+ int ret = 0;
+
+ switch (nc->unc.proto) {
+ case IPPROTO_UDP:
+ nc->nc_read_data = &netchannel_copy_to_user;
+ break;
+ case IPPROTO_TCP:
+ nc->nc_read_data = &netchannel_copy_to_user_tcp;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int netchannel_setup(struct netchannel *nc)
+{
+ int ret = 0;
+
+ if (nc->unc.memory_limit_order > NETCHANNEL_MAX_ORDER)
+ nc->unc.memory_limit_order = NETCHANNEL_MAX_ORDER;
+
+ if (nc->unc.memory_limit_order < NETCHANNEL_MIN_ORDER)
+ nc->unc.memory_limit_order = NETCHANNEL_MIN_ORDER;
+
+ switch (nc->unc.type) {
+ case NETCHANNEL_COPY_USER:
+ ret = netchannel_copy_user_setup(nc);
+ break;
+ case NETCHANNEL_MMAP:
+ ret = netchannel_mmap_setup(nc);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int netchannel_bind(struct unetchannel_control *ctl)
+{
+ struct netchannel *nc;
+ int err = -EINVAL, fput_needed;
+ struct netchannel_cache_head *bucket;
+ struct file *file;
+ struct inode *inode;
+
+ file = fget_light(ctl->fd, &fput_needed);
+ if (!file)
+ goto err_out_exit;
+
+ inode = igrab(file->f_dentry->d_inode);
+ if (!inode)
+ goto err_out_fput;
+
+ bucket = netchannel_bucket(&ctl->unc);
+
+ mutex_lock(&bucket->mutex);
+
+ nc = netchannel_check_full(&ctl->unc, bucket);
+ if (!nc) {
+ err = -ENODEV;
+ goto err_out_unlock;
+ }
+
+ nc->inode = inode;
+
+ fput_light(file, fput_needed);
+ mutex_unlock(&bucket->mutex);
+
+ return 0;
+
+err_out_unlock:
+ mutex_unlock(&bucket->mutex);
+err_out_fput:
+ fput_light(file, fput_needed);
+err_out_exit:
+ return err;
+}
+
+static int netchannel_create(struct unetchannel *unc)
+{
+ struct netchannel *nc;
+ int err = -ENOMEM;
+ struct netchannel_cache_head *bucket;
+
+ nc = kmem_cache_alloc(netchannel_cache, GFP_KERNEL);
+ if (!nc)
+ return -ENOMEM;
+
+ memset(nc, 0, sizeof(struct netchannel));
+
+ nc->hit = 0;
+ skb_queue_head_init(&nc->recv_queue);
+ init_waitqueue_head(&nc->wait);
+ atomic_set(&nc->refcnt, 1);
+ memcpy(&nc->unc, unc, sizeof(struct unetchannel));
+
+ err = netchannel_setup(nc);
+ if (err)
+ goto err_out_free;
+
+ bucket = netchannel_bucket(unc);
+
+ mutex_lock(&bucket->mutex);
+
+ if (netchannel_check_full(unc, bucket)) {
+ err = -EEXIST;
+ goto err_out_unlock;
+ }
+
+ hlist_add_head_rcu(&nc->node, &bucket->head);
+ err = 0;
+
+ mutex_unlock(&bucket->mutex);
+
+ netchannel_dump_info_unc(unc, "create", 0, err);
+
+ return err;
+
+err_out_unlock:
+ mutex_unlock(&bucket->mutex);
+
+ netchannel_cleanup(nc);
+
+err_out_free:
+ kmem_cache_free(netchannel_cache, nc);
+
+ return err;
+}
+
+static int netchannel_remove(struct unetchannel *unc)
+{
+ struct netchannel *nc;
+ int err = -ENODEV;
+ struct netchannel_cache_head *bucket;
+ unsigned long hit = 0;
+
+ if (!netchannel_hash_table)
+ return -ENODEV;
+
+ bucket = netchannel_bucket(unc);
+
+ mutex_lock(&bucket->mutex);
+
+ nc = netchannel_check_full(unc, bucket);
+ if (!nc)
+ nc = netchannel_check_dest(unc, bucket);
+
+ if (!nc)
+ goto out_unlock;
+
+ hlist_del_rcu(&nc->node);
+ hit = nc->hit;
+
+ if (nc->inode) {
+ iput(nc->inode);
+ nc->inode = NULL;
+ }
+
+ netchannel_put(nc);
+ err = 0;
+
+out_unlock:
+ mutex_unlock(&bucket->mutex);
+ netchannel_dump_info_unc(unc, "remove", hit, err);
+ return err;
+}
+
+static int netchannel_recv_data(struct unetchannel_control *ctl, void __user *data)
+{
+ int ret = -ENODEV;
+ struct netchannel_cache_head *bucket;
+ struct netchannel *nc;
+
+ bucket = netchannel_bucket(&ctl->unc);
+
+ mutex_lock(&bucket->mutex);
+
+ nc = netchannel_check_full(&ctl->unc, bucket);
+ if (!nc)
+ nc = netchannel_check_dest(&ctl->unc, bucket);
+
+ if (!nc)
+ goto err_out_unlock;
+
+ netchannel_get(nc);
+ mutex_unlock(&bucket->mutex);
+
+ ret = nc->nc_read_data(nc, &ctl->timeout, &ctl->len, data);
+
+ netchannel_put(nc);
+ return ret;
+
+err_out_unlock:
+ mutex_unlock(&bucket->mutex);
+ return ret;
+}
+
+static int netchannel_dump_info(struct unetchannel *unc)
+{
+ struct netchannel_cache_head *bucket;
+ struct netchannel *nc;
+ char *ncs = "none";
+ unsigned long hit = 0;
+ int err;
+
+ bucket = netchannel_bucket(unc);
+
+ mutex_lock(&bucket->mutex);
+ nc = netchannel_check_full(unc, bucket);
+ if (!nc) {
+ nc = netchannel_check_dest(unc, bucket);
+ if (nc)
+ ncs = "dest";
+ } else
+ ncs = "full";
+ if (nc)
+ hit = nc->hit;
+ mutex_unlock(&bucket->mutex);
+ err = (nc)?0:-ENODEV;
+
+ netchannel_dump_info_unc(unc, ncs, hit, err);
+
+ return err;
+}
+
+asmlinkage long sys_netchannel_control(void __user *arg)
+{
+ struct unetchannel_control ctl;
+ int ret;
+
+ if (!netchannel_hash_table)
+ return -ENODEV;
+
+ if (copy_from_user(&ctl, arg, sizeof(struct unetchannel_control)))
+ return -ERESTARTSYS;
+
+ switch (ctl.cmd) {
+ case NETCHANNEL_CREATE:
+ ret = netchannel_create(&ctl.unc);
+ break;
+ case NETCHANNEL_BIND:
+ ret = netchannel_bind(&ctl);
+ break;
+ case NETCHANNEL_REMOVE:
+ ret = netchannel_remove(&ctl.unc);
+ break;
+ case NETCHANNEL_READ:
+ ret = netchannel_recv_data(&ctl, arg + sizeof(struct unetchannel_control));
+ break;
+ case NETCHANNEL_DUMP:
+ ret = netchannel_dump_info(&ctl.unc);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (copy_to_user(arg, &ctl, sizeof(struct unetchannel_control)))
+ return -ERESTARTSYS;
+
+ return ret;
+}
+
+static inline void netchannel_dump_addr(struct in_ifaddr *ifa, char *str)
+{
+ printk("netchannel: %s %u.%u.%u.%u/%u.%u.%u.%u\n", str, NIPQUAD(ifa->ifa_local), NIPQUAD(ifa->ifa_mask));
+}
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct in_ifaddr *ifa = ptr;
+
+ switch (event) {
+ case NETDEV_UP:
+ netchannel_dump_addr(ifa, "add");
+ break;
+ case NETDEV_DOWN:
+ netchannel_dump_addr(ifa, "del");
+ break;
+ default:
+ netchannel_dump_addr(ifa, "unk");
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct inet6_ifaddr *ifa = ptr;
+
+ printk("netchannel: inet6 event=%lx, ifa=%p.\n", event, ifa);
+ return NOTIFY_DONE;
+}
+#endif
+
+static int __init netchannel_init(void)
+{
+ unsigned int i, j, size;
+ int err = -ENOMEM;
+
+ size = (1 << netchannel_hash_order);
+
+ netchannel_hash_table = kzalloc(size * sizeof(void *), GFP_KERNEL);
+ if (!netchannel_hash_table)
+ goto err_out_exit;
+
+ for (i=0; i<size; ++i) {
+ struct netchannel_cache_head **col;
+
+ col = kzalloc(size * sizeof(void *), GFP_KERNEL);
+ if (!col)
+ break;
+
+ for (j=0; j<size; ++j) {
+ struct netchannel_cache_head *head;
+
+ head = kzalloc(sizeof(struct netchannel_cache_head), GFP_KERNEL);
+ if (!head)
+ break;
+
+ INIT_HLIST_HEAD(&head->head);
+ mutex_init(&head->mutex);
+
+ col[j] = head;
+ }
+
+ if (j<size && j>0) {
+ while (j >= 0)
+ kfree(col[j--]);
+ kfree(col);
+ break;
+ }
+
+ netchannel_hash_table[i] = col;
+ }
+
+ if (i<size) {
+ size = i;
+ goto err_out_free;
+ }
+
+ netchannel_cache = kmem_cache_create("netchannel", sizeof(struct netchannel), 0, 0,
+ NULL, NULL);
+ if (!netchannel_cache)
+ goto err_out_free;
+
+ register_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+ register_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+
+ printk("netchannel: Created %u order two-dimensional hash table.\n",
+ netchannel_hash_order);
+
+ return 0;
+
+err_out_free:
+ for (i=0; i<size; ++i) {
+ for (j=0; j<(1 << netchannel_hash_order); ++j)
+ kfree(netchannel_hash_table[i][j]);
+ kfree(netchannel_hash_table[i]);
+ }
+ kfree(netchannel_hash_table);
+err_out_exit:
+
+ printk("netchannel: Failed to create %u order two-dimensional hash table.\n",
+ netchannel_hash_order);
+ return err;
+}
+
+static void __exit netchannel_exit(void)
+{
+ unsigned int i, j;
+
+ unregister_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+ unregister_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+ kmem_cache_destroy(netchannel_cache);
+
+ for (i=0; i<(1 << netchannel_hash_order); ++i) {
+ for (j=0; j<(1 << netchannel_hash_order); ++j)
+ kfree(netchannel_hash_table[i][j]);
+ kfree(netchannel_hash_table[i]);
+ }
+ kfree(netchannel_hash_table);
+}
+
+late_initcall(netchannel_init);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fb3770f..f979fd6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -437,6 +437,7 @@ struct sk_buff *skb_clone(struct sk_buff
C(pkt_type);
C(ip_summed);
C(priority);
+ C(netchannel);
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
C(ipvs_property);
#endif
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 672950e..eb2dc12 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -727,7 +727,10 @@ int tcp_v4_conn_request(struct sock *sk,
#endif
/* Never answer to SYNs send to broadcast or multicast */
- if (((struct rtable *)skb->dst)->rt_flags &
+ if (!skb->dst) {
+ if (MULTICAST(daddr))
+ goto drop;
+ } else if (((struct rtable *)skb->dst)->rt_flags &
(RTCF_BROADCAST | RTCF_MULTICAST))
goto drop;
@@ -924,15 +927,21 @@ static struct sock *tcp_v4_hnd_req(struc
struct iphdr *iph = skb->nh.iph;
struct sock *nsk;
struct request_sock **prev;
+ int iif;
/* Find possible connection requests. */
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
iph->saddr, iph->daddr);
if (req)
return tcp_check_req(sk, skb, req, prev);
+ if (!skb->dst)
+ iif = 0;
+ else
+ iif = inet_iif(skb);
+
nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
th->source, skb->nh.iph->daddr,
- ntohs(th->dest), inet_iif(skb));
+ ntohs(th->dest), iif);
if (nsk) {
if (nsk->sk_state != TCP_TIME_WAIT) {
--
Evgeniy Polyakov
--
Evgeniy Polyakov
^ permalink raw reply related
* Re: [PATCH] softmac: Fix handling of authentication failure
From: Daniel Drake @ 2006-06-02 10:09 UTC (permalink / raw)
To: Larry Finger; +Cc: linville, netdev, johannes
In-Reply-To: <447FA5B5.8020707@lwfinger.net>
Larry Finger wrote:
> This statement fails to compile on my system using Linus' tree, because
> ieee80211softmac_disassoc needs a second argument - the reason. It seems
> as if WLAN_REASON_PREV_AUTH_NOT_VALID would be appropriate.
Thanks for pointing that out. This patch depends on a patch titled
"softmac: deauthentication implies deassociation" which is apparently
not present in Linus' tree.
Daniel
^ permalink raw reply
* Netchannel: TCP memcpy() to mapped are support. Benchmarks.
From: Evgeniy Polyakov @ 2006-06-02 9:37 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, caitlinb, kelly, rusty
[-- Attachment #1: Type: text/plain, Size: 1094 bytes --]
Hello, developers.
Attached initial benchmark of netchannel with memcpy() into kernelspace
area, which could be mapped from userspace versus socket code using
1gbit link.
As you can see from the graph, netchannels outperforms sockets in speed,
but it's CPU usage is higher too.
It is possible, that it is the price, i.e. socket code would increase
it's CPU usage if it could increase it's processing speed.
Implementationis fairly ugly yet. It is required a some changes in
generic TCP state machine processing logic to clean things up,
so it would be performed not on top of sockets,
but using skbs from queues with appropriate parameters (timeout,
flags) provided either as new structure (so it would be embedded into
struct sock and netchannel) or as function parameters.
Netchannels currently use two queue dereferencings to work with socket's
queue processing:
- from netchannel's queue which is filled in interrupt
- from socket's queue which is filled in process context
which is a source of some speed problems too.
It still requires some thinking...
--
Evgeniy Polyakov
[-- Attachment #2: netchannel_speed.png --]
[-- Type: image/png, Size: 8322 bytes --]
^ permalink raw reply
* Re: Question about tcp hash function tcp_hashfn()
From: Evgeniy Polyakov @ 2006-06-02 7:48 UTC (permalink / raw)
To: Florian Weimer
Cc: David Miller, draghuram, linux-kernel, netdev,
Brian F. G. Bidulock
In-Reply-To: <87y7wgaze1.fsf@mid.deneb.enyo.de>
On Fri, Jun 02, 2006 at 07:40:38AM +0200, Florian Weimer (fw@deneb.enyo.de) wrote:
> * Evgeniy Polyakov:
>
> > That is wrong. And I have a code and picture to show that,
> > and you dont - prove me wrong :)
>
> Here we go:
>
> static inline num2ip(__u8 a1, __u8 a2, __u8 a3, __u8 a4)
> {
> __u32 a = 0;
>
> a |= a1;
> a << 8;
> a |= a2;
> a << 8;
> a |= a3;
> a << 8;
> a |= a4;
>
> return a;
> }
>
> "gcc -Wall" was pretty illuminating. 8-P After fixing this and
> switching to a better PRNG, I get something which looks pretty normal.
:) thats true, but to be 100% honest I used different code to test for
hash artifacts...
That code was created to show that it is possible to _have_ artifacts,
but not specially to _find_ them.
But it still does not fix artifacts with for example const IP and random
ports or const IP and linear port selection.
Values must be specially tuned to be used with Jenkins hash, for example
linear port with const IP produce following hash buckets:
100 24397
200 12112
300 3952
400 975
500 178
600 40
700 3
800 1
i.e. one 800-entries bucket (!) while xor one always have only 100 of
them (for 100*hash_size number of iterations).
So, your prove does not valid :)
--
Evgeniy Polyakov
^ permalink raw reply
* Re: Question about tcp hash function tcp_hashfn()
From: Florian Weimer @ 2006-06-02 5:40 UTC (permalink / raw)
To: Evgeniy Polyakov
Cc: David Miller, draghuram, linux-kernel, netdev,
Brian F. G. Bidulock
In-Reply-To: <20060601060424.GA28087@2ka.mipt.ru>
* Evgeniy Polyakov:
> That is wrong. And I have a code and picture to show that,
> and you dont - prove me wrong :)
Here we go:
static inline num2ip(__u8 a1, __u8 a2, __u8 a3, __u8 a4)
{
__u32 a = 0;
a |= a1;
a << 8;
a |= a2;
a << 8;
a |= a3;
a << 8;
a |= a4;
return a;
}
"gcc -Wall" was pretty illuminating. 8-P After fixing this and
switching to a better PRNG, I get something which looks pretty normal.
^ permalink raw reply
* Re: Question about tcp hash function tcp_hashfn()
From: Evgeniy Polyakov @ 2006-06-02 7:01 UTC (permalink / raw)
To: David Miller, draghuram, linux-kernel, netdev; +Cc: Brian F. G. Bidulock
In-Reply-To: <20060601124010.C554@openss7.org>
On Thu, Jun 01, 2006 at 12:40:10PM -0600, Brian F. G. Bidulock (bidulock@openss7.org) wrote:
> So what are your thoughts about my sequence number approach (for
> connected sockets)?
Depending on how you are going to use it.
Generic socket code does not have TCP sequence numbers since it must
work with all supported protocols.
Netchannels also do not know about internals of the packet by design,
since all protocol processing is performed at the end peer.
Sequence number can be wrapped in minutes in current networks and even
faster tomorrow, that is why PAWS was created.
Your idea about reinserting the socket does not scale in 1Gbit
environment, and definitely will not in 10Gbit.
Probably it is possible to create second hash table for TCP sockets only
and use that table first in protocol handler, but it requires some
research to prove the idea.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [patch, -rc5-mm1] lock validator: special locking: net/ipv4/igmp.c #2
From: Jesse Brandeburg @ 2006-06-02 6:47 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Linux-Kernel,, Andrew Morton, Arjan van de Ven, NetDEV list
In-Reply-To: <20060601063537.GA19931@elte.hu>
On 5/31/06, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Jesse Brandeburg <jesse.brandeburg@gmail.com> wrote:
>
> > well, when running e1000 through some code paths on FC4 +
> > 2.6.17-rc5-mm1 + ingo's latest rollup patch, with this lockdep debug
> > option enabled I got this:
> >
> > e1000: eth1: e1000_watchdog_task: NIC Link is Up 1000 Mbps Full Duplex
> >
> > ======================================
> > [ BUG: bad unlock ordering detected! ]
> > --------------------------------------
> > mDNSResponder/2361 is trying to release lock (&in_dev->mc_list_lock) at:
> > [<ffffffff81233f5a>] ip_mc_add_src+0x85/0x1f8
>
> ok, could you try the patch below? (i also updated the rollup with this
> fix)
>
> Ingo
>
> ---------------------
> Subject: lock validator: special locking: net/ipv4/igmp.c #2
> From: Ingo Molnar <mingo@elte.hu>
>
> another case of non-nested unlocking igmp.c.
>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
> ---
> net/ipv4/igmp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> Index: linux/net/ipv4/igmp.c
> ===================================================================
> --- linux.orig/net/ipv4/igmp.c
> +++ linux/net/ipv4/igmp.c
> @@ -1646,7 +1646,7 @@ static int ip_mc_add_src(struct in_devic
> return -ESRCH;
> }
> spin_lock_bh(&pmc->lock);
> - read_unlock(&in_dev->mc_list_lock);
> + read_unlock_non_nested(&in_dev->mc_list_lock);
>
> #ifdef CONFIG_IP_MULTICAST
> sf_markstate(pmc);
>
yep, this fixes it.
^ permalink raw reply
* Re: orinoco encodeext + auth patch on lkml
From: Pavel Roskin @ 2006-06-02 5:38 UTC (permalink / raw)
To: Dan Williams; +Cc: netdev
In-Reply-To: <1149076999.2805.2.camel@localhost.localdomain>
Hello, Dan!
On Wed, 2006-05-31 at 08:03 -0400, Dan Williams wrote:
> Pavel,
>
> Unsure if you saw this. Slightly annoying he didn't send to netdev, but
> would be good to take a look at and possibly integrate. Looks sane to
> me from 10,000ft.
>
> http://lkml.org/lkml/2006/5/30/433
Thanks for heads up. Actually, this e-mail was copied to the orinoco
mailing list, so I'm aware of it.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: [patch 16/17] recent match: fix "sleeping function called from invalid context"
From: Andrew Morton @ 2006-06-02 3:34 UTC (permalink / raw)
To: davem, netdev, kaber
In-Reply-To: <200606020328.k523SKhS028868@shell0.pdx.osdl.net>
oops, sorry, I didn't mean to send 16 and 17.
^ permalink raw reply
* [patch 14/17] irda: missing allocation result check in irlap_change_speed()
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, fmalita, samuel
From: Florin Malita <fmalita@gmail.com>
The skb allocation may fail, which can result in a NULL pointer dereference
in irlap_queue_xmit().
Coverity CID: 434.
davem: "If the allocation fails we should probably do something more
interesting here, such as schedule a timer to try again later. Otherwise the
speed change will silently never occur."
Signed-off-by: Florin Malita <fmalita@gmail.com>
Cc: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
net/irda/irlap.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff -puN net/irda/irlap.c~irda-missing-allocation-result-check-in-irlap_change_speed net/irda/irlap.c
--- devel/net/irda/irlap.c~irda-missing-allocation-result-check-in-irlap_change_speed 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/irda/irlap.c 2006-06-01 20:31:50.000000000 -0700
@@ -884,7 +884,8 @@ static void irlap_change_speed(struct ir
if (now) {
/* Send down empty frame to trigger speed change */
skb = dev_alloc_skb(0);
- irlap_queue_xmit(self, skb);
+ if (skb)
+ irlap_queue_xmit(self, skb);
}
}
_
^ permalink raw reply
* [patch 16/17] recent match: fix "sleeping function called from invalid context"
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, kaber
From: Patrick McHardy <kaber@trash.net>
create_proc_entry must not be called with locks held. Use a mutex instead
to protect data only changed in user context.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
net/ipv4/netfilter/ipt_recent.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff -puN net/ipv4/netfilter/ipt_recent.c~recent-match-fix-sleeping-function-called-from-invalid-context net/ipv4/netfilter/ipt_recent.c
--- devel/net/ipv4/netfilter/ipt_recent.c~recent-match-fix-sleeping-function-called-from-invalid-context 2006-06-01 20:31:51.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_recent.c 2006-06-01 20:31:51.000000000 -0700
@@ -69,6 +69,7 @@ struct recent_table {
static LIST_HEAD(tables);
static DEFINE_SPINLOCK(recent_lock);
+static DEFINE_MUTEX(recent_mutex);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_dir;
@@ -249,7 +250,7 @@ ipt_recent_checkentry(const char *tablen
strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
return 0;
- spin_lock_bh(&recent_lock);
+ mutex_lock(&recent_mutex);
t = recent_table_lookup(info->name);
if (t != NULL) {
t->refcnt++;
@@ -258,7 +259,7 @@ ipt_recent_checkentry(const char *tablen
}
t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (t == NULL)
goto out;
strcpy(t->name, info->name);
@@ -274,10 +275,12 @@ ipt_recent_checkentry(const char *tablen
t->proc->proc_fops = &recent_fops;
t->proc->data = t;
#endif
+ spin_lock_bh(&recent_lock);
list_add_tail(&t->list, &tables);
+ spin_unlock_bh(&recent_lock);
ret = 1;
out:
- spin_unlock_bh(&recent_lock);
+ mutex_unlock(&recent_mutex);
return ret;
}
@@ -288,17 +291,19 @@ ipt_recent_destroy(const struct xt_match
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
- spin_lock_bh(&recent_lock);
+ mutex_lock(&recent_mutex);
t = recent_table_lookup(info->name);
if (--t->refcnt == 0) {
+ spin_lock_bh(&recent_lock);
list_del(&t->list);
+ spin_unlock_bh(&recent_lock);
recent_table_flush(t);
#ifdef CONFIG_PROC_FS
remove_proc_entry(t->name, proc_dir);
#endif
kfree(t);
}
- spin_unlock_bh(&recent_lock);
+ mutex_unlock(&recent_mutex);
}
#ifdef CONFIG_PROC_FS
_
^ permalink raw reply
* [patch 17/17] recent match: missing refcnt initialization
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, kaber
From: Patrick McHardy <kaber@trash.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
net/ipv4/netfilter/ipt_recent.c | 1 +
1 file changed, 1 insertion(+)
diff -puN net/ipv4/netfilter/ipt_recent.c~recent-match-missing-refcnt-initialization net/ipv4/netfilter/ipt_recent.c
--- devel/net/ipv4/netfilter/ipt_recent.c~recent-match-missing-refcnt-initialization 2006-06-01 20:31:51.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_recent.c 2006-06-01 20:31:51.000000000 -0700
@@ -262,6 +262,7 @@ ipt_recent_checkentry(const char *tablen
GFP_KERNEL);
if (t == NULL)
goto out;
+ t->refcnt = 1;
strcpy(t->name, info->name);
INIT_LIST_HEAD(&t->lru_list);
for (i = 0; i < ip_list_hash_size; i++)
_
^ permalink raw reply
* [patch 13/17] secmark: Add new packet controls to SELinux
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, jmorris, sds
From: James Morris <jmorris@namei.org>
Add new per-packet access controls to SELinux, replacing the old packet
controls.
Packets are labeled with the iptables SECMARK and CONNSECMARK targets, then
security policy for the packets is enforced with these controls.
To allow for a smooth transition to the new controls, the old code is still
present, but not active by default. To restore previous behavior, the old
controls may be activated at runtime by writing a '1' to /selinux/compat_net,
and also via the kernel boot parameter selinux_compat_net. Switching between
the network control models requires the security load_policy permission. The
old controls will probably eventually be removed and any continued use is
discouraged.
With this patch, the new secmark controls for SElinux are disabled by default,
so existing behavior is entirely preserved, and the user is not affected at
all.
It also provides a config option to enable the secmark controls by default
(which can always be overridden at boot and runtime). It is also noted in the
kconfig help that the user will need updated userspace if enabling secmark
controls for SELinux and that they'll probably need the SECMARK and CONNMARK
targets, and conntrack protocol helpers, although such decisions are beyond
the scope of kernel configuration.
Signed-off-by: James Morris <jmorris@namei.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
Documentation/kernel-parameters.txt | 9
security/selinux/Kconfig | 29 +++
security/selinux/hooks.c | 242 ++++++++++++++------------
security/selinux/include/xfrm.h | 2
security/selinux/selinuxfs.c | 66 +++++++
security/selinux/xfrm.c | 12 -
6 files changed, 241 insertions(+), 119 deletions(-)
diff -puN Documentation/kernel-parameters.txt~secmark-add-new-packet-controls-to-selinux Documentation/kernel-parameters.txt
--- devel/Documentation/kernel-parameters.txt~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/Documentation/kernel-parameters.txt 2006-06-01 20:31:50.000000000 -0700
@@ -1405,6 +1405,15 @@ running once the system is up.
If enabled at boot time, /selinux/disable can be used
later to disable prior to initial policy load.
+ selinux_compat_net =
+ [SELINUX] Set initial selinux_compat_net flag value.
+ Format: { "0" | "1" }
+ 0 -- use new secmark-based packet controls
+ 1 -- use legacy packet controls
+ Default value is 0 (preferred).
+ Value can be changed at runtime via
+ /selinux/compat_net.
+
serialnumber [BUGS=IA-32]
sg_def_reserved_size= [SCSI]
diff -puN security/selinux/hooks.c~secmark-add-new-packet-controls-to-selinux security/selinux/hooks.c
--- devel/security/selinux/hooks.c~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/hooks.c 2006-06-01 20:31:50.000000000 -0700
@@ -80,6 +80,7 @@
extern unsigned int policydb_loaded_version;
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern int selinux_compat_net;
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
int selinux_enforcing = 0;
@@ -3216,47 +3217,17 @@ static int selinux_socket_unix_may_send(
return 0;
}
-static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
+ struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
+ u16 family, char *addrp, int len)
{
- u16 family;
- char *addrp;
- int len, err = 0;
+ int err = 0;
u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
- u32 sock_sid = 0;
- u16 sock_class = 0;
- struct socket *sock;
- struct net_device *dev;
- struct avc_audit_data ad;
-
- family = sk->sk_family;
- if (family != PF_INET && family != PF_INET6)
- goto out;
-
- /* Handle mapped IPv4 packets arriving via IPv6 sockets */
- if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
- family = PF_INET;
-
- read_lock_bh(&sk->sk_callback_lock);
- sock = sk->sk_socket;
- if (sock) {
- struct inode *inode;
- inode = SOCK_INODE(sock);
- if (inode) {
- struct inode_security_struct *isec;
- isec = inode->i_security;
- sock_sid = isec->sid;
- sock_class = isec->sclass;
- }
- }
- read_unlock_bh(&sk->sk_callback_lock);
- if (!sock_sid)
- goto out;
- dev = skb->dev;
- if (!dev)
+ if (!skb->dev)
goto out;
- err = sel_netif_sids(dev, &if_sid, NULL);
+ err = sel_netif_sids(skb->dev, &if_sid, NULL);
if (err)
goto out;
@@ -3279,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(s
break;
}
- AVC_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = dev->name;
- ad.u.net.family = family;
-
- err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
- if (err)
- goto out;
-
- err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
+ err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
if (err)
goto out;
- /* Fixme: this lookup is inefficient */
err = security_node_sid(family, addrp, len, &node_sid);
if (err)
goto out;
- err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
+ err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
if (err)
goto out;
if (recv_perm) {
u32 port_sid;
- /* Fixme: make this more efficient */
err = security_port_sid(sk->sk_family, sk->sk_type,
- sk->sk_protocol, ntohs(ad.u.net.sport),
+ sk->sk_protocol, ntohs(ad->u.net.sport),
&port_sid);
if (err)
goto out;
err = avc_has_perm(sock_sid, port_sid,
- sock_class, recv_perm, &ad);
+ sock_class, recv_perm, ad);
}
- if (!err)
- err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+out:
+ return err;
+}
+
+static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ u16 family;
+ u16 sock_class = 0;
+ char *addrp;
+ int len, err = 0;
+ u32 sock_sid = 0;
+ struct socket *sock;
+ struct avc_audit_data ad;
+
+ family = sk->sk_family;
+ if (family != PF_INET && family != PF_INET6)
+ goto out;
+
+ /* Handle mapped IPv4 packets arriving via IPv6 sockets */
+ if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+ family = PF_INET;
+
+ read_lock_bh(&sk->sk_callback_lock);
+ sock = sk->sk_socket;
+ if (sock) {
+ struct inode *inode;
+ inode = SOCK_INODE(sock);
+ if (inode) {
+ struct inode_security_struct *isec;
+ isec = inode->i_security;
+ sock_sid = isec->sid;
+ sock_class = isec->sclass;
+ }
+ }
+ read_unlock_bh(&sk->sk_callback_lock);
+ if (!sock_sid)
+ goto out;
+
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+ ad.u.net.family = family;
+
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+ if (err)
+ goto out;
+
+ if (selinux_compat_net)
+ err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
+ sock_class, family,
+ addrp, len);
+ else
+ err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
+ PACKET__RECV, &ad);
+ if (err)
+ goto out;
+ err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
out:
return err;
}
@@ -3456,42 +3471,18 @@ out:
#ifdef CONFIG_NETFILTER
-static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
- struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *),
- u16 family)
+static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
+ struct inode_security_struct *isec,
+ struct avc_audit_data *ad,
+ u16 family, char *addrp, int len)
{
- char *addrp;
- int len, err = NF_ACCEPT;
+ int err;
u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
- struct sock *sk;
- struct socket *sock;
- struct inode *inode;
- struct sk_buff *skb = *pskb;
- struct inode_security_struct *isec;
- struct avc_audit_data ad;
- struct net_device *dev = (struct net_device *)out;
- sk = skb->sk;
- if (!sk)
- goto out;
-
- sock = sk->sk_socket;
- if (!sock)
- goto out;
-
- inode = SOCK_INODE(sock);
- if (!inode)
- goto out;
-
err = sel_netif_sids(dev, &if_sid, NULL);
if (err)
goto out;
- isec = inode->i_security;
-
switch (isec->sclass) {
case SECCLASS_UDP_SOCKET:
netif_perm = NETIF__UDP_SEND;
@@ -3511,55 +3502,88 @@ static unsigned int selinux_ip_postroute
break;
}
-
- AVC_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = dev->name;
- ad.u.net.family = family;
-
- err = selinux_parse_skb(skb, &ad, &addrp,
- &len, 0) ? NF_DROP : NF_ACCEPT;
- if (err != NF_ACCEPT)
- goto out;
-
- err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
- netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
- if (err != NF_ACCEPT)
+ err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ if (err)
goto out;
- /* Fixme: this lookup is inefficient */
- err = security_node_sid(family, addrp, len,
- &node_sid) ? NF_DROP : NF_ACCEPT;
- if (err != NF_ACCEPT)
+ err = security_node_sid(family, addrp, len, &node_sid);
+ if (err)
goto out;
- err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
- node_perm, &ad) ? NF_DROP : NF_ACCEPT;
- if (err != NF_ACCEPT)
+ err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
+ if (err)
goto out;
if (send_perm) {
u32 port_sid;
- /* Fixme: make this more efficient */
err = security_port_sid(sk->sk_family,
sk->sk_type,
sk->sk_protocol,
- ntohs(ad.u.net.dport),
- &port_sid) ? NF_DROP : NF_ACCEPT;
- if (err != NF_ACCEPT)
+ ntohs(ad->u.net.dport),
+ &port_sid);
+ if (err)
goto out;
err = avc_has_perm(isec->sid, port_sid, isec->sclass,
- send_perm, &ad) ? NF_DROP : NF_ACCEPT;
+ send_perm, ad);
}
+out:
+ return err;
+}
+
+static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *),
+ u16 family)
+{
+ char *addrp;
+ int len, err = 0;
+ struct sock *sk;
+ struct socket *sock;
+ struct inode *inode;
+ struct sk_buff *skb = *pskb;
+ struct inode_security_struct *isec;
+ struct avc_audit_data ad;
+ struct net_device *dev = (struct net_device *)out;
- if (err != NF_ACCEPT)
+ sk = skb->sk;
+ if (!sk)
goto out;
- err = selinux_xfrm_postroute_last(isec->sid, skb);
+ sock = sk->sk_socket;
+ if (!sock)
+ goto out;
+
+ inode = SOCK_INODE(sock);
+ if (!inode)
+ goto out;
+
+ isec = inode->i_security;
+
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = dev->name;
+ ad.u.net.family = family;
+
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+ if (err)
+ goto out;
+
+ if (selinux_compat_net)
+ err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
+ family, addrp, len);
+ else
+ err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
+ PACKET__SEND, &ad);
+ if (err)
+ goto out;
+
+ err = selinux_xfrm_postroute_last(isec->sid, skb);
out:
- return err;
+ return err ? NF_DROP : NF_ACCEPT;
}
static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
diff -puN security/selinux/include/xfrm.h~secmark-add-new-packet-controls-to-selinux security/selinux/include/xfrm.h
--- devel/security/selinux/include/xfrm.h~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/xfrm.h 2006-06-01 20:31:50.000000000 -0700
@@ -49,7 +49,7 @@ static inline int selinux_xfrm_sock_rcv_
static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
{
- return NF_ACCEPT;
+ return 0;
}
static inline int selinux_socket_getpeer_stream(struct sock *sk)
diff -puN security/selinux/Kconfig~secmark-add-new-packet-controls-to-selinux security/selinux/Kconfig
--- devel/security/selinux/Kconfig~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/Kconfig 2006-06-01 20:31:50.000000000 -0700
@@ -1,6 +1,7 @@
config SECURITY_SELINUX
bool "NSA SELinux Support"
depends on SECURITY_NETWORK && AUDIT && NET && INET
+ select NETWORK_SECMARK
default n
help
This selects NSA Security-Enhanced Linux (SELinux).
@@ -95,3 +96,31 @@ config SECURITY_SELINUX_CHECKREQPROT_VAL
via /selinux/checkreqprot if authorized by policy.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+ bool "NSA SELinux enable new secmark network controls by default"
+ depends on SECURITY_SELINUX
+ default n
+ help
+ This option determines whether the new secmark-based network
+ controls will be enabled by default. If not, the old internal
+ per-packet controls will be enabled by default, preserving
+ old behavior.
+
+ If you enable the new controls, you will need updated
+ SELinux userspace libraries, tools and policy. Typically,
+ your distribution will provide these and enable the new controls
+ in the kernel they also distribute.
+
+ Note that this option can be overriden at boot with the
+ selinux_compat_net parameter, and after boot via
+ /selinux/compat_net. See Documentation/kernel-parameters.txt
+ for details on this parameter.
+
+ If you enable the new network controls, you will likely
+ also require the SECMARK and CONNSECMARK targets, as
+ well as any conntrack helpers for protocols which you
+ wish to control.
+
+ If you are unsure what do do here, select N.
+
diff -puN security/selinux/selinuxfs.c~secmark-add-new-packet-controls-to-selinux security/selinux/selinuxfs.c
--- devel/security/selinux/selinuxfs.c~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/selinuxfs.c 2006-06-01 20:31:50.000000000 -0700
@@ -38,6 +38,14 @@
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+#define SELINUX_COMPAT_NET_VALUE 0
+#else
+#define SELINUX_COMPAT_NET_VALUE 1
+#endif
+
+int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
static int __init checkreqprot_setup(char *str)
{
selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -45,6 +53,13 @@ static int __init checkreqprot_setup(cha
}
__setup("checkreqprot=", checkreqprot_setup);
+static int __init selinux_compat_net_setup(char *str)
+{
+ selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
+ return 1;
+}
+__setup("selinux_compat_net=", selinux_compat_net_setup);
+
static DEFINE_MUTEX(sel_mutex);
@@ -85,6 +100,7 @@ enum sel_inos {
SEL_AVC, /* AVC management directory */
SEL_MEMBER, /* compute polyinstantiation membership decision */
SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
+ SEL_COMPAT_NET, /* whether to use old compat network packet controls */
};
#define TMPBUFLEN 12
@@ -364,6 +380,55 @@ static struct file_operations sel_checkr
.write = sel_write_checkreqprot,
};
+static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmpbuf[TMPBUFLEN];
+ ssize_t length;
+
+ length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ char *page;
+ ssize_t length;
+ int new_value;
+
+ length = task_has_security(current, SECURITY__LOAD_POLICY);
+ if (length)
+ return length;
+
+ if (count >= PAGE_SIZE)
+ return -ENOMEM;
+ if (*ppos != 0) {
+ /* No partial writes. */
+ return -EINVAL;
+ }
+ page = (char*)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ length = -EINVAL;
+ if (sscanf(page, "%d", &new_value) != 1)
+ goto out;
+
+ selinux_compat_net = new_value ? 1 : 0;
+ length = count;
+out:
+ free_page((unsigned long) page);
+ return length;
+}
+static struct file_operations sel_compat_net_ops = {
+ .read = sel_read_compat_net,
+ .write = sel_write_compat_net,
+};
+
/*
* Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
*/
@@ -1219,6 +1284,7 @@ static int sel_fill_super(struct super_b
[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
+ [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff -puN security/selinux/xfrm.c~secmark-add-new-packet-controls-to-selinux security/selinux/xfrm.c
--- devel/security/selinux/xfrm.c~secmark-add-new-packet-controls-to-selinux 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/xfrm.c 2006-06-01 20:31:50.000000000 -0700
@@ -356,18 +356,12 @@ int selinux_xfrm_postroute_last(u32 isec
struct xfrm_state *x = dst_test->xfrm;
if (x && selinux_authorizable_xfrm(x))
- goto accept;
+ goto out;
}
}
rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
ASSOCIATION__SENDTO, NULL);
- if (rc)
- goto drop;
-
-accept:
- return NF_ACCEPT;
-
-drop:
- return NF_DROP;
+out:
+ return rc;
}
_
^ permalink raw reply
* [patch 15/17] pppoe: missing result check in __pppoe_xmit()
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, fmalita, mostrows
From: Florin Malita <fmalita@gmail.com>
skb_clone() may fail, we should check the result.
Coverity CID: 1215.
Signed-off-by: Florin Malita <fmalita@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: <mostrows@speakeasy.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
drivers/net/pppoe.c | 3 +++
1 file changed, 3 insertions(+)
diff -puN drivers/net/pppoe.c~pppoe-missing-result-check-in-__pppoe_xmit drivers/net/pppoe.c
--- devel/drivers/net/pppoe.c~pppoe-missing-result-check-in-__pppoe_xmit 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/drivers/net/pppoe.c 2006-06-01 20:31:50.000000000 -0700
@@ -861,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk,
* give dev_queue_xmit something it can free.
*/
skb2 = skb_clone(skb, GFP_ATOMIC);
+
+ if (skb2 == NULL)
+ goto abort;
}
ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
_
^ permalink raw reply
* [patch 05/17] selinux: add security class for appletalk sockets
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, cpebenito, jmorris, sds
From: Christopher J. PeBenito <cpebenito@tresys.com>
Add a security class for appletalk sockets so that they can be
distinguished in SELinux policy. Please apply.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: James Morris <jmorris@namei.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
security/selinux/hooks.c | 2 +
security/selinux/include/av_inherit.h | 1
security/selinux/include/av_permissions.h | 23 +++++++++++++++++++
security/selinux/include/class_to_string.h | 1
security/selinux/include/flask.h | 1
5 files changed, 28 insertions(+)
diff -puN security/selinux/hooks.c~selinux-add-security-class-for-appletalk-sockets security/selinux/hooks.c
--- devel/security/selinux/hooks.c~selinux-add-security-class-for-appletalk-sockets 2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/hooks.c 2006-06-01 20:31:49.000000000 -0700
@@ -696,6 +696,8 @@ static inline u16 socket_type_to_securit
return SECCLASS_PACKET_SOCKET;
case PF_KEY:
return SECCLASS_KEY_SOCKET;
+ case PF_APPLETALK:
+ return SECCLASS_APPLETALK_SOCKET;
}
return SECCLASS_SOCKET;
diff -puN security/selinux/include/av_inherit.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/av_inherit.h
--- devel/security/selinux/include/av_inherit.h~selinux-add-security-class-for-appletalk-sockets 2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/av_inherit.h 2006-06-01 20:31:49.000000000 -0700
@@ -29,3 +29,4 @@
S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
+ S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
diff -puN security/selinux/include/av_permissions.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/av_permissions.h
--- devel/security/selinux/include/av_permissions.h~selinux-add-security-class-for-appletalk-sockets 2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/av_permissions.h 2006-06-01 20:31:49.000000000 -0700
@@ -933,3 +933,26 @@
#define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL
#define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL
+#define APPLETALK_SOCKET__IOCTL 0x00000001UL
+#define APPLETALK_SOCKET__READ 0x00000002UL
+#define APPLETALK_SOCKET__WRITE 0x00000004UL
+#define APPLETALK_SOCKET__CREATE 0x00000008UL
+#define APPLETALK_SOCKET__GETATTR 0x00000010UL
+#define APPLETALK_SOCKET__SETATTR 0x00000020UL
+#define APPLETALK_SOCKET__LOCK 0x00000040UL
+#define APPLETALK_SOCKET__RELABELFROM 0x00000080UL
+#define APPLETALK_SOCKET__RELABELTO 0x00000100UL
+#define APPLETALK_SOCKET__APPEND 0x00000200UL
+#define APPLETALK_SOCKET__BIND 0x00000400UL
+#define APPLETALK_SOCKET__CONNECT 0x00000800UL
+#define APPLETALK_SOCKET__LISTEN 0x00001000UL
+#define APPLETALK_SOCKET__ACCEPT 0x00002000UL
+#define APPLETALK_SOCKET__GETOPT 0x00004000UL
+#define APPLETALK_SOCKET__SETOPT 0x00008000UL
+#define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL
+#define APPLETALK_SOCKET__RECVFROM 0x00020000UL
+#define APPLETALK_SOCKET__SENDTO 0x00040000UL
+#define APPLETALK_SOCKET__RECV_MSG 0x00080000UL
+#define APPLETALK_SOCKET__SEND_MSG 0x00100000UL
+#define APPLETALK_SOCKET__NAME_BIND 0x00200000UL
+
diff -puN security/selinux/include/class_to_string.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/class_to_string.h
--- devel/security/selinux/include/class_to_string.h~selinux-add-security-class-for-appletalk-sockets 2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/class_to_string.h 2006-06-01 20:31:49.000000000 -0700
@@ -58,3 +58,4 @@
S_("nscd")
S_("association")
S_("netlink_kobject_uevent_socket")
+ S_("appletalk_socket")
diff -puN security/selinux/include/flask.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/flask.h
--- devel/security/selinux/include/flask.h~selinux-add-security-class-for-appletalk-sockets 2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/flask.h 2006-06-01 20:31:49.000000000 -0700
@@ -60,6 +60,7 @@
#define SECCLASS_NSCD 53
#define SECCLASS_ASSOCIATION 54
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
+#define SECCLASS_APPLETALK_SOCKET 56
/*
* Security identifier indices for initial entities
_
^ permalink raw reply
* [patch 11/17] secmark: Add secmark support to conntrack
From: akpm @ 2006-06-02 3:32 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, jmorris
From: James Morris <jmorris@namei.org>
Add a secmark field to IP and NF conntracks, so that security markings on
packets can be copied to their associated connections, and also copied back to
packets as required. This is similar to the network mark field currently used
with conntrack, although it is intended for enforcement of security policy
rather than network policy.
Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---
include/linux/netfilter_ipv4/ip_conntrack.h | 4 ++
include/net/netfilter/nf_conntrack.h | 4 ++
include/net/netfilter/nf_conntrack_compat.h | 26 +++++++++++++++++
net/ipv4/netfilter/Kconfig | 12 +++++++
net/ipv4/netfilter/ip_conntrack_core.c | 3 +
net/ipv4/netfilter/ip_conntrack_standalone.c | 5 +++
net/netfilter/Kconfig | 12 +++++++
net/netfilter/nf_conntrack_core.c | 3 +
net/netfilter/nf_conntrack_standalone.c | 5 +++
9 files changed, 74 insertions(+)
diff -puN include/linux/netfilter_ipv4/ip_conntrack.h~secmark-add-secmark-support-to-conntrack include/linux/netfilter_ipv4/ip_conntrack.h
--- devel/include/linux/netfilter_ipv4/ip_conntrack.h~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/linux/netfilter_ipv4/ip_conntrack.h 2006-06-01 20:31:50.000000000 -0700
@@ -120,6 +120,10 @@ struct ip_conntrack
u_int32_t mark;
#endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+ u_int32_t secmark;
+#endif
+
/* Traversed often, so hopefully in different cacheline to top */
/* These are my tuples; original and reply */
struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
diff -puN include/net/netfilter/nf_conntrack_compat.h~secmark-add-secmark-support-to-conntrack include/net/netfilter/nf_conntrack_compat.h
--- devel/include/net/netfilter/nf_conntrack_compat.h~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/net/netfilter/nf_conntrack_compat.h 2006-06-01 20:31:50.000000000 -0700
@@ -20,6 +20,19 @@ static inline u_int32_t *nf_ct_get_mark(
}
#endif /* CONFIG_IP_NF_CONNTRACK_MARK */
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+ u_int32_t *ctinfo)
+{
+ struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+
+ if (ct)
+ return &ct->secmark;
+ else
+ return NULL;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_SECMARK */
+
#ifdef CONFIG_IP_NF_CT_ACCT
static inline struct ip_conntrack_counter *
nf_ct_get_counters(const struct sk_buff *skb)
@@ -70,6 +83,19 @@ static inline u_int32_t *nf_ct_get_mark(
}
#endif /* CONFIG_NF_CONNTRACK_MARK */
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+ u_int32_t *ctinfo)
+{
+ struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+
+ if (ct)
+ return &ct->secmark;
+ else
+ return NULL;
+}
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
#ifdef CONFIG_NF_CT_ACCT
static inline struct ip_conntrack_counter *
nf_ct_get_counters(const struct sk_buff *skb)
diff -puN include/net/netfilter/nf_conntrack.h~secmark-add-secmark-support-to-conntrack include/net/netfilter/nf_conntrack.h
--- devel/include/net/netfilter/nf_conntrack.h~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/net/netfilter/nf_conntrack.h 2006-06-01 20:31:50.000000000 -0700
@@ -113,6 +113,10 @@ struct nf_conn
u_int32_t mark;
#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ u_int32_t secmark;
+#endif
+
/* Storage reserved for other modules: */
union nf_conntrack_proto proto;
diff -puN net/ipv4/netfilter/ip_conntrack_core.c~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/ip_conntrack_core.c
--- devel/net/ipv4/netfilter/ip_conntrack_core.c~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ip_conntrack_core.c 2006-06-01 20:31:50.000000000 -0700
@@ -724,6 +724,9 @@ init_conntrack(struct ip_conntrack_tuple
/* this is ugly, but there is no other place where to put it */
conntrack->nat.masq_index = exp->master->nat.masq_index;
#endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+ conntrack->secmark = exp->master->secmark;
+#endif
nf_conntrack_get(&conntrack->master->ct_general);
CONNTRACK_STAT_INC(expect_new);
} else {
diff -puN net/ipv4/netfilter/ip_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/ip_conntrack_standalone.c
--- devel/net/ipv4/netfilter/ip_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-06-01 20:31:50.000000000 -0700
@@ -189,6 +189,11 @@ static int ct_seq_show(struct seq_file *
return -ENOSPC;
#endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+ if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+ return -ENOSPC;
+#endif
+
if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
return -ENOSPC;
diff -puN net/ipv4/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/Kconfig
--- devel/net/ipv4/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/Kconfig 2006-06-01 20:31:50.000000000 -0700
@@ -55,6 +55,18 @@ config IP_NF_CONNTRACK_MARK
of packets, but this mark value is kept in the conntrack session
instead of the individual packets.
+config IP_NF_CONNTRACK_SECMARK
+ bool 'Connection tracking security mark support'
+ depends on IP_NF_CONNTRACK && NETWORK_SECMARK
+ help
+ This option enables security markings to be applied to
+ connections. Typically they are copied to connections from
+ packets using the CONNSECMARK target and copied back from
+ connections to packets with the same target, with the packets
+ being originally labeled via SECMARK.
+
+ If unsure, say 'N'.
+
config IP_NF_CONNTRACK_EVENTS
bool "Connection tracking events (EXPERIMENTAL)"
depends on EXPERIMENTAL && IP_NF_CONNTRACK
diff -puN net/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack net/netfilter/Kconfig
--- devel/net/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Kconfig 2006-06-01 20:31:50.000000000 -0700
@@ -60,6 +60,18 @@ config NF_CONNTRACK_MARK
of packets, but this mark value is kept in the conntrack session
instead of the individual packets.
+config NF_CONNTRACK_SECMARK
+ bool 'Connection tracking security mark support'
+ depends on NF_CONNTRACK && NETWORK_SECMARK
+ help
+ This option enables security markings to be applied to
+ connections. Typically they are copied to connections from
+ packets using the CONNSECMARK target and copied back from
+ connections to packets with the same target, with the packets
+ being originally labeled via SECMARK.
+
+ If unsure, say 'N'.
+
config NF_CONNTRACK_EVENTS
bool "Connection tracking events (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
diff -puN net/netfilter/nf_conntrack_core.c~secmark-add-secmark-support-to-conntrack net/netfilter/nf_conntrack_core.c
--- devel/net/netfilter/nf_conntrack_core.c~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/nf_conntrack_core.c 2006-06-01 20:31:50.000000000 -0700
@@ -990,6 +990,9 @@ init_conntrack(const struct nf_conntrack
#ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark;
#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ conntrack->secmark = exp->master->secmark;
+#endif
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
} else
diff -puN net/netfilter/nf_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack net/netfilter/nf_conntrack_standalone.c
--- devel/net/netfilter/nf_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack 2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/nf_conntrack_standalone.c 2006-06-01 20:31:50.000000000 -0700
@@ -213,6 +213,11 @@ static int ct_seq_show(struct seq_file *
return -ENOSPC;
#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+ return -ENOSPC;
+#endif
+
if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
return -ENOSPC;
_
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox