* Re: Fw: [Bugme-new] [Bug 6495] New: Vlan MTU Fragmentation
From: Ben Greear @ 2006-05-06 17:20 UTC (permalink / raw)
To: Andrew Morton; +Cc: netdev, bugme-daemon, slavon
In-Reply-To: <20060505231759.5ad77e95.akpm@osdl.org>
Andrew Morton wrote:
> I guess I can type simple commands and add printks. Do you have time to
> take a look at the driver and suggest what I should be looking for?
I can only offer vague hints:
TX usually works, but RX often has isues. There is usually a bit
or two that needs setting to enable the larger than MTU pkt RX.
It seems some older chipsets had issues with doing checksum offload
for VLAN packets, so could try disabling the UDP/TCP checksum logic
and see if that helps.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH] fix IP-over-ATM and ARP interaction - formatting fixed.
From: Simon Kelley @ 2006-05-06 17:02 UTC (permalink / raw)
To: davem, netdev
The classical IP over ATM code maintains its own IPv4 <-> <ATM stuff>
ARP table, using the standard neighbour-table code. The
neigh_table_init function adds this neighbour table to a linked
list of all neighbor tables which is used by the functions
neigh_delete() neigh_add() and neightbl_set(), all called by
the netlink code.
Once the ATM neighbour table is added to the list, there are two tables
with family == AF_INET there, and ARP entries sent via netlink go into
the first table with matching family. This is indeterminate and often wrong.
To see the bug, on a kernel with CLIP enabled, create a standard IPv4
ARP entry by pinging an unused address on a local subnet. Then attempt
to complete that entry by doing
ip neigh replace <ip address> lladdr <some mac address> nud reachable
Looking at the ARP tables by using
ip neigh show
will reveal two ARP entries for the same address. One of these can be
found in /proc/net/arp, and the other in /proc/net/atm/arp.
This patch adds a new function, neigh_table_init_no_netlink() which
does everything the neigh_table_init() does, except add the table to
the netlink all-arp-tables chain. In addition neigh_table_init() has a
check that all tables on the chain have a distinct address family.
The init call in clip.c is changed to call neigh_table_init_no_netlink().
Since ATM ARP tables are rather more complicated than can currently be
handled by the available rtattrs in the netlink protocol, no
functionality is lost by this patch, and non-ATM ARP manipulation via
netlink is rescued. A more complete solution would involve a rtattr for
ATM ARP entries and some way for the netlink code to give neigh_add
and friends more information than just address family with which to find
the correct ARP table.
Signed-off-by: Simon Kelley <simon@thekelleys.org.uk>
--
diff -Naur linux-2.6.16.11.orig/include/net/neighbour.h linux-2.6.16.11/include/net/neighbour.h
--- linux-2.6.16.11.orig/include/net/neighbour.h 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/include/net/neighbour.h 2006-05-04 20:09:17.000000000 +0100
@@ -211,6 +211,7 @@
#define NEIGH_UPDATE_F_ADMIN 0x80000000
extern void neigh_table_init(struct neigh_table *tbl);
+extern void neigh_table_init_no_netlink(struct neigh_table *tbl);
extern int neigh_table_clear(struct neigh_table *tbl);
extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
const void *pkey,
diff -Naur linux-2.6.16.11.orig/net/atm/clip.c linux-2.6.16.11/net/atm/clip.c
--- linux-2.6.16.11.orig/net/atm/clip.c 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/net/atm/clip.c 2006-05-04 20:10:00.000000000 +0100
@@ -995,7 +995,7 @@
static int __init atm_clip_init(void)
{
- neigh_table_init(&clip_tbl);
+ neigh_table_init_no_netlink(&clip_tbl);
clip_tbl_hook = &clip_tbl;
register_atm_ioctl(&clip_ioctl_ops);
diff -Naur linux-2.6.16.11.orig/net/core/neighbour.c linux-2.6.16.11/net/core/neighbour.c
--- linux-2.6.16.11.orig/net/core/neighbour.c 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/net/core/neighbour.c 2006-05-06 17:44:30.000000000 +0100
@@ -1322,8 +1322,7 @@
kfree(parms);
}
-
-void neigh_table_init(struct neigh_table *tbl)
+void neigh_table_init_no_netlink(struct neigh_table *tbl)
{
unsigned long now = jiffies;
unsigned long phsize;
@@ -1381,7 +1380,16 @@
tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20;
+}
+
+void neigh_table_init(struct neigh_table *tbl)
+{
+ struct neigh_table *tmp;
+
+ neigh_table_init_no_netlink(tbl);
write_lock(&neigh_tbl_lock);
+ for (tmp = neigh_tables; tmp; tmp = tmp->next)
+ BUG_ON(tmp->family == tbl->family);
tbl->next = neigh_tables;
neigh_tables = tbl;
write_unlock(&neigh_tbl_lock);
@@ -2655,6 +2663,7 @@
EXPORT_SYMBOL(neigh_resolve_output);
EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(neigh_table_init);
+EXPORT_SYMBOL(neigh_table_init_no_netlink);
EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);
^ permalink raw reply
* Re: [PATCH] fix IP-over-ATM and ARP interaction.
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-05-06 16:31 UTC (permalink / raw)
To: simon; +Cc: davem, netdev, yoshfuji
In-Reply-To: <E1FcPPN-0004xi-00@thekelleys.org.uk>
In article <E1FcPPN-0004xi-00@thekelleys.org.uk> (at Sat, 06 May 2006 17:13:29 +0100), Simon Kelley <simon@thekelleys.org.uk> says:
> +void neigh_table_init(struct neigh_table *tbl)
> +{
> + struct neigh_table *tmp;
> +
> + neigh_table_init_no_netlink(tbl);
> + write_lock(&neigh_tbl_lock);
> + for (tmp = neigh_tables; tmp; tmp = tmp->next)
> + BUG_ON(tmp->family == tbl->family);
> + tbl->next = neigh_tables;
> + neigh_tables = tbl;
> + write_unlock(&neigh_tbl_lock);
> }
>
> int neigh_table_clear(struct neigh_table *tbl)
Please fix the coding style; use tab for indent, please.
--yoshfuji
^ permalink raw reply
* Fw: [Bugme-new] [Bug 6502] New: SIOCSIFHWBROADCAST needs compat layer
From: Andrew Morton @ 2006-05-06 16:27 UTC (permalink / raw)
To: netdev; +Cc: bugme-daemon@kernel-bugs.osdl.org
Begin forwarded message:
Date: Sat, 6 May 2006 08:24:25 -0700
From: bugme-daemon@bugzilla.kernel.org
To: bugme-new@lists.osdl.org
Subject: [Bugme-new] [Bug 6502] New: SIOCSIFHWBROADCAST needs compat layer
http://bugzilla.kernel.org/show_bug.cgi?id=6502
Summary: SIOCSIFHWBROADCAST needs compat layer
Kernel Version: 2.6.15
Status: NEW
Severity: normal
Owner: ak@suse.de
Submitter: Alexandra.Kossovsky@oktetlabs.ru
Most recent kernel where this bug did not occur: all kernels has this problem;
I've tested 2.6.8, 2.6.9, 2.6.15
Distribution:
Hardware Environment: ethernet interface
Software Environment: 32-bit libc with 64-bit kernel
Problem Description:
32-bit program running with 64-bit kernel fails to set hardware broadcast
address via ioctl(SIOCSIFHWBROADCAST).
Steps to reproduce:
Compile the following sample program:
#include <stdio.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
main()
{
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct ifreq req;
int rc;
if (s < 0)
{
perror("failed to open socket");
return -1;
}
strcpy(req.ifr_name, "eth0");
req.ifr_hwaddr.sa_family = AF_LOCAL;
memset(req.ifr_hwaddr.sa_data, 0xff, 6);
rc = ioctl(s, SIOCSIFHWBROADCAST, &req);
if (rc != 0)
{
perror("ioctl failed");
return -1;
}
printf("ioctl(SIOCSIFHWBROADCAST) passed\n");
return 0;
}
When compiled to 64-bit binary, it works OK:
ioctl(SIOCSIFHWBROADCAST) passed
When compiled to 32-bit binary, it does not work:
ioctl failed: Invalid argument
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
^ permalink raw reply
* [PATCH] fix IP-over-ATM and ARP interaction.
From: Simon Kelley @ 2006-05-06 16:13 UTC (permalink / raw)
To: davem, netdev
The classical IP over ATM code maintains its own IPv4 <-> <ATM stuff>
ARP table, using the standard neighbour-table code. The
neigh_table_init function adds this neighbour table to a linked
list of all neighbor tables which is used by the functions
neigh_delete() neigh_add() and neightbl_set(), all called by
the netlink code.
Once the ATM neighbour table is added to the list, there are two tables
with family == AF_INET there, and ARP entries sent via netlink go into
the first table with matching family. This is indeterminate and often wrong.
To see the bug, on a kernel with CLIP enabled, create a standard IPv4
ARP entry by pinging an unused address on a local subnet. Then attempt
to complete that entry by doing
ip neigh replace <ip address> lladdr <some mac address> nud reachable
Looking at the ARP tables by using
ip neigh show
will reveal two ARP entries for the same address. One of these can be
found in /proc/net/arp, and the other in /proc/net/atm/arp.
This patch adds a new function, neigh_table_init_no_netlink() which
does everything the neigh_table_init() does, except add the table to
the netlink all-arp-tables chain. In addition neigh_table_init() has a
check that all tables on the chain have a distinct address family.
The init call in clip.c is changed to call neigh_table_init_no_netlink().
Since ATM ARP tables are rather more complicated than can currently be
handled by the available rtattrs in the netlink protocol, no
functionality is lost by this patch, and non-ATM ARP manipulation via
netlink is rescued. A more complete solution would involve a rtattr for
ATM ARP entries and some way for the netlink code to give neigh_add
and friends more information than just address family with which to find
the correct ARP table.
Signed-off-by: Simon Kelley <simon@thekelleys.org.uk>
--
diff -Naur linux-2.6.16.11.orig/include/net/neighbour.h linux-2.6.16.11/include/net/neighbour.h
--- linux-2.6.16.11.orig/include/net/neighbour.h 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/include/net/neighbour.h 2006-05-04 20:09:17.000000000 +0100
@@ -211,6 +211,7 @@
#define NEIGH_UPDATE_F_ADMIN 0x80000000
extern void neigh_table_init(struct neigh_table *tbl);
+extern void neigh_table_init_no_netlink(struct neigh_table *tbl);
extern int neigh_table_clear(struct neigh_table *tbl);
extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
const void *pkey,
diff -Naur linux-2.6.16.11.orig/net/atm/clip.c linux-2.6.16.11/net/atm/clip.c
--- linux-2.6.16.11.orig/net/atm/clip.c 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/net/atm/clip.c 2006-05-04 20:10:00.000000000 +0100
@@ -995,7 +995,7 @@
static int __init atm_clip_init(void)
{
- neigh_table_init(&clip_tbl);
+ neigh_table_init_no_netlink(&clip_tbl);
clip_tbl_hook = &clip_tbl;
register_atm_ioctl(&clip_ioctl_ops);
diff -Naur linux-2.6.16.11.orig/net/core/neighbour.c linux-2.6.16.11/net/core/neighbour.c
--- linux-2.6.16.11.orig/net/core/neighbour.c 2006-04-24 21:20:24.000000000 +0100
+++ linux-2.6.16.11/net/core/neighbour.c 2006-05-04 20:07:55.000000000 +0100
@@ -1322,8 +1322,7 @@
kfree(parms);
}
-
-void neigh_table_init(struct neigh_table *tbl)
+void neigh_table_init_no_netlink(struct neigh_table *tbl)
{
unsigned long now = jiffies;
unsigned long phsize;
@@ -1381,10 +1380,19 @@
tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20;
- write_lock(&neigh_tbl_lock);
- tbl->next = neigh_tables;
- neigh_tables = tbl;
- write_unlock(&neigh_tbl_lock);
+}
+
+void neigh_table_init(struct neigh_table *tbl)
+{
+ struct neigh_table *tmp;
+
+ neigh_table_init_no_netlink(tbl);
+ write_lock(&neigh_tbl_lock);
+ for (tmp = neigh_tables; tmp; tmp = tmp->next)
+ BUG_ON(tmp->family == tbl->family);
+ tbl->next = neigh_tables;
+ neigh_tables = tbl;
+ write_unlock(&neigh_tbl_lock);
}
int neigh_table_clear(struct neigh_table *tbl)
@@ -2655,6 +2663,7 @@
EXPORT_SYMBOL(neigh_resolve_output);
EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(neigh_table_init);
+EXPORT_SYMBOL(neigh_table_init_no_netlink);
EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);
^ permalink raw reply
* 2.4 kern: want to print TCP cwnd with every packet
From: George P Nychis @ 2006-05-06 14:19 UTC (permalink / raw)
To: netdev
Hi,
I'd like to print the TCP cwnd for the sender, with every packet before it is sent out. This way i could plot the sender window over time to show TCP's behavior in certain conditions.
I see in tcp_input.c several places where i could print the current window, but i'd have to add code in multiple places. I was wondering if there is any 1 place, right before a packet is sent out, that i could printk() tp->snd_cwnd
Thanks!
George
^ permalink raw reply
* Re: Please pull upstream-fixes branch of wireless-2.6
From: John W. Linville @ 2006-05-06 13:45 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Linus Torvalds, Andrew Morton, netdev, jeff
In-Reply-To: <445C2219.5060204@osdl.org>
On Fri, May 05, 2006 at 09:12:09PM -0700, Stephen Hemminger wrote:
> Linus Torvalds wrote:
> >On Fri, 5 May 2006, Andrew Morton wrote:
> >
> >>On Fri, 5 May 2006 21:06:18 -0400
> >>"John W. Linville" <linville@tuxdriver.com> wrote:
> >>
> >>>These are fixes intended for 2.6.17...thanks!
> >>>
> >>Jeff is offline for a couple of weeks. Please prepare a pull for Linus.
> >>
> >
> >Actually, while Jeff is off, Steve Hemminger is supposed to be the network
> >driver overlord ("All bow down before the mighty Shemminger"), so please
> >do synchronize with him.
> >
> >Of course, that might be just Steve taking a look and telling me "yeah,
> >please pull directly from John".
> >
> > Linus
> >
> I had a bunch ready for monday...
So, Stephen, you will pull from me and have Linus pull all from you?
Just trying to clarify the plan... :-)
It makes no difference to me. I'll include the git url "just in case":
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream-fixes
Thanks!
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Dscape ieee80211: enabling/disabling the radio
From: Ivo van Doorn @ 2006-05-06 12:00 UTC (permalink / raw)
To: netdev; +Cc: Jiri Benc
[-- Attachment #1: Type: text/plain, Size: 2282 bytes --]
Hi,
While working on the rt2x00 driver, I keep hitting against some problems with scanning.
Basicly the dscape stack handles scanning in 2 ways, through the
passive_scan() handler in the ieee80211_hw structure, and by calling
the config() handler in the ieee80211_hw stucture.
The usage of the first handler, does not give any problems at this time.
The main source of problems during scanning in rt2x00 seems to come
when the config() handler is used.
In rt2x00 the config() handler schedules all configuration changes by using a workqueue,
this is required since several configuration changes in rt2x00 need sleeping and for
USB devices all register access requires sleeping. And the config() handler is often
called from interrupt context so it complains a lot when the workqueue is not used.
This seemed fine, untill the radio_enabled field was introduced to the configuration structure.
When the radio_enable field is set, the radio must be enabled, but enabling
the radio is something that can (at least in rt2x00) fail. So scheduling the enabling of the radio
to the workqueue is not something that is desired since the stack can not be notified that the
device is not able to enable the radio.
Moving the enabling of the radio outside the workqueue function and into the config()
handler results in scheduling while atomic issues since the enabling of the radio requires
sleeping for both PCI and USB devices.
Instead of using a config field radio_enabled, wouldn't it be better to add 2 handlers
to the ieee80211_hw structure, something like enable_radio() and disable_radio()?
If these functions are called from normal context the dscape stack can still enable
and disable the radio whenever it is desired, and it is able to check the return value
to see if the request has actually succeeded.
What I am wondering about afterwards is what exactly should happen when the open()
and stop() handlers are being called? Because those are basicly intented to enable
and stop the radio as well. I checked bcm43xx to see what they do, and they don't seem
to check the radio_enabled field, so I don't know what they do besides enabling the radio.
Well this was just some stuff I have been trying to figure out while trying to solve several
rt2x00 bugs... ;)
Regards,
Ivo
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [RFC 3/3] [IPSEC]: Abstract out transport mode input code
From: Herbert Xu @ 2006-05-06 11:24 UTC (permalink / raw)
To: Miika Komu; +Cc: Diego Beltrami, David S. Miller, netdev
In-Reply-To: <20060506112026.GA27671@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 561 bytes --]
Hi:
This patch is totally untested but shows how we can use xfrm_mode to
remove unnecessary code sharing between modes that in fact end up
slowing things down. In particular, notice how we've eliminated a
double IP header copying for tunnel mode which is in fact the common
case.
I need to finish it for IPv6 and actually test this one :)
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p3.patch --]
[-- Type: text/plain, Size: 3551 bytes --]
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e2e4771..30524b9 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -172,11 +172,8 @@
}
}
((struct iphdr*)work_buf)->protocol = ah->nexthdr;
- skb->nh.raw = skb_pull(skb, ah_hlen);
- memcpy(skb->nh.raw, work_buf, iph->ihl*4);
- skb->nh.iph->tot_len = htons(skb->len);
- skb_pull(skb, skb->nh.iph->ihl*4);
- skb->h.raw = skb->data;
+ skb->h.raw = memcpy(skb->nh.raw, work_buf, iph->ihl * 4) + ah_hlen;
+ __skb_pull(skb, ah_hlen + iph->ihl * 4);
return 0;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 9d1881c..451803e 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -143,10 +143,8 @@
int alen = esp->auth.icv_trunc_len;
int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
int nfrags;
- int encap_len = 0;
u8 nexthdr[2];
struct scatterlist *sg;
- u8 workbuf[60];
int padlen;
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
@@ -209,7 +207,6 @@
struct udphdr *uh;
uh = (struct udphdr *)(iph + 1);
- encap_len = (void*)esph - (void*)uh;
/*
* 1) if the NAT-T peer's IP or port changed then
@@ -246,11 +243,9 @@
iph->protocol = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
- memcpy(workbuf, skb->nh.raw, iph->ihl*4);
- skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
- skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
- memcpy(skb->nh.raw, workbuf, iph->ihl*4);
- skb->nh.iph->tot_len = htons(skb->len);
+ skb->h.raw = __skb_pull(skb,
+ sizeof(struct ip_esp_hdr) + esp->conf.ivlen) -
+ iph->ihl * 4;
return 0;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index cd810f4..704937b 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -45,7 +45,6 @@
static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
{
int err, plen, dlen;
- struct iphdr *iph;
struct ipcomp_data *ipcd = x->data;
u8 *start, *scratch;
struct crypto_tfm *tfm;
@@ -74,8 +73,6 @@
skb_put(skb, dlen - plen);
memcpy(skb->data, scratch, dlen);
- iph = skb->nh.iph;
- iph->tot_len = htons(dlen + iph->ihl * 4);
out:
put_cpu();
return err;
@@ -108,9 +105,8 @@
skb->nh.raw += sizeof(struct ip_comp_hdr);
memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
iph = skb->nh.iph;
- iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
iph->protocol = nexthdr;
- skb->h.raw = skb->data;
+ skb->h.raw = skb->nh.raw;
err = ipcomp_decompress(x, skb);
out:
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index e46d9a4..c2e507e 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -40,6 +40,11 @@
static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
{
+ if (skb->h.raw != skb->nh.raw)
+ skb->nh.raw = memmove(skb->h.raw, skb->nh.raw,
+ skb->nh.iph->ihl * 4);
+ skb->nh.iph->tot_len = htons(skb->len);
+ skb->h.raw = skb->data;
return 0;
}
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index f8d880b..a304d1d 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -73,9 +73,11 @@
static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
- struct iphdr *iph = skb->nh.iph;
+ struct iphdr *iph;
int err = -EINVAL;
+ skb->nh.raw = skb->data;
+ iph = skb->nh.iph;
if (iph->protocol != IPPROTO_IPIP)
goto out;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
^ permalink raw reply related
* [RFC 2/3] [IPSEC] xfrm: Abstract out encapsulation modes
From: Herbert Xu @ 2006-05-06 11:21 UTC (permalink / raw)
To: Miika Komu; +Cc: Diego Beltrami, David S. Miller, netdev
In-Reply-To: <20060506112026.GA27671@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 604 bytes --]
Hi:
This patch adds the structure xfrm_mode. It is meant to represent
the operations carried out by transport/tunnel modes.
By doing this we allow additional encapsulation modes to be added
without clogging up the xfrm_input/xfrm_output paths.
Candidate modes include 4-to-6 tunnel mode, 6-to-4 tunnel mode, and
BEET modes.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p2.patch --]
[-- Type: text/plain, Size: 25668 bytes --]
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -118,6 +118,10 @@ enum
XFRM_SHARE_UNIQUE /* Use once */
};
+#define XFRM_MODE_TRANSPORT 0
+#define XFRM_MODE_TUNNEL 1
+#define XFRM_MODE_MAX 2
+
/* Netlink configuration messages. */
enum {
XFRM_MSG_BASE = 0x10,
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -20,6 +20,8 @@
#include <net/ip6_fib.h>
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
+#define MODULE_ALIAS_XFRM_MODE(family, encap) \
+ MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
extern struct sock *xfrm_nl;
extern u32 sysctl_xfrm_aevent_etime;
@@ -164,6 +166,7 @@ struct xfrm_state
/* Reference to data common to all the instances of this
* transformer. */
struct xfrm_type *type;
+ struct xfrm_mode *mode;
/* Security context */
struct xfrm_sec_ctx *security;
@@ -205,6 +208,7 @@ struct xfrm_dst;
struct xfrm_policy_afinfo {
unsigned short family;
struct xfrm_type *type_map[256];
+ struct xfrm_mode *mode_map[XFRM_MODE_MAX];
struct dst_ops *dst_ops;
void (*garbage_collect)(void);
int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -267,6 +271,19 @@ extern int xfrm_unregister_type(struct x
extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
extern void xfrm_put_type(struct xfrm_type *type);
+struct xfrm_mode {
+ int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+ int (*output)(struct sk_buff *skb);
+
+ struct module *owner;
+ int encap;
+};
+
+extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+extern struct xfrm_mode *xfrm_get_mode(int encap, int family);
+extern void xfrm_put_mode(struct xfrm_mode *mode);
+
struct xfrm_tmpl
{
/* id in template is interpreted as:
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -414,6 +414,24 @@ config INET_TUNNEL
tristate
default n
+config INET_XFRM_MODE_TRANSPORT
+ tristate "IP: IPsec transport mode"
+ default y
+ select XFRM
+ ---help---
+ Support for IPsec transport mode.
+
+ If unsure, say Y.
+
+config INET_XFRM_MODE_TUNNEL
+ tristate "IP: IPsec tunnel mode"
+ default y
+ select XFRM
+ ---help---
+ Support for IPsec tunnel mode.
+
+ If unsure, say Y.
+
config INET_DIAG
tristate "INET: socket monitoring interface"
default y
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
+obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
+obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -13,7 +13,6 @@
#include <linux/string.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>
@@ -24,15 +23,6 @@ int xfrm4_rcv(struct sk_buff *skb)
EXPORT_SYMBOL(xfrm4_rcv);
-static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
-{
- struct iphdr *outer_iph = skb->nh.iph;
- struct iphdr *inner_iph = skb->h.ipiph;
-
- if (INET_ECN_is_ce(outer_iph->tos))
- IP_ECN_set_ce(inner_iph);
-}
-
static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
switch (nexthdr) {
@@ -113,24 +103,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb,
xfrm_vec[xfrm_nr++] = x;
- iph = skb->nh.iph;
+ if (x->mode->input(x, skb))
+ goto drop;
if (x->props.mode) {
- if (iph->protocol != IPPROTO_IPIP)
- goto drop;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- goto drop;
- if (skb_cloned(skb) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
- goto drop;
- if (x->props.flags & XFRM_STATE_DECAP_DSCP)
- ipv4_copy_dscp(iph, skb->h.ipiph);
- if (!(x->props.flags & XFRM_STATE_NOECN))
- ipip_ecn_decapsulate(skb);
- skb->mac.raw = memmove(skb->data - skb->mac_len,
- skb->mac.raw, skb->mac_len);
- skb->nh.raw = skb->data;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
decaps = 1;
break;
}
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
new file mode 100644
--- /dev/null
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -0,0 +1,69 @@
+/*
+ * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header will be moved forward to make space for the encapsulation
+ * header.
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_transport_output(struct sk_buff *skb)
+{
+ struct xfrm_state *x;
+ struct iphdr *iph;
+ int ihl;
+
+ iph = skb->nh.iph;
+ skb->h.ipiph = iph;
+
+ ihl = iph->ihl * 4;
+ skb->h.raw += ihl;
+
+ x = skb->dst->xfrm;
+ skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
+ return 0;
+}
+
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ return 0;
+}
+
+static struct xfrm_mode xfrm4_transport_mode = {
+ .input = xfrm4_transport_input,
+ .output = xfrm4_transport_output,
+ .owner = THIS_MODULE,
+ .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm4_transport_init(void)
+{
+ return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
+}
+
+static void __exit xfrm4_transport_exit(void)
+{
+ int err;
+
+ err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
+ BUG_ON(err);
+}
+
+module_init(xfrm4_transport_init);
+module_exit(xfrm4_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
new file mode 100644
--- /dev/null
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -0,0 +1,125 @@
+/*
+ * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
+{
+ struct iphdr *outer_iph = skb->nh.iph;
+ struct iphdr *inner_iph = skb->h.ipiph;
+
+ if (INET_ECN_is_ce(outer_iph->tos))
+ IP_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401. The following fields
+ * in it shall be filled in by x->type->output:
+ * tot_len
+ * check
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_tunnel_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct xfrm_state *x = dst->xfrm;
+ struct iphdr *iph, *top_iph;
+ int flags;
+
+ iph = skb->nh.iph;
+ skb->h.ipiph = iph;
+
+ skb->nh.raw = skb_push(skb, x->props.header_len);
+ top_iph = skb->nh.iph;
+
+ top_iph->ihl = 5;
+ top_iph->version = 4;
+
+ /* DS disclosed */
+ top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+
+ flags = x->props.flags;
+ if (flags & XFRM_STATE_NOECN)
+ IP_ECN_clear(top_iph);
+
+ top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+ 0 : (iph->frag_off & htons(IP_DF));
+ if (!top_iph->frag_off)
+ __ip_select_ident(top_iph, dst->child, 0);
+
+ top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
+
+ top_iph->saddr = x->props.saddr.a4;
+ top_iph->daddr = x->id.daddr.a4;
+ top_iph->protocol = IPPROTO_IPIP;
+
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ return 0;
+}
+
+static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ int err = -EINVAL;
+
+ if (iph->protocol != IPPROTO_IPIP)
+ goto out;
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ goto out;
+
+ if (skb_cloned(skb) &&
+ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ goto out;
+
+ if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+ ipv4_copy_dscp(iph, skb->h.ipiph);
+ if (!(x->props.flags & XFRM_STATE_NOECN))
+ ipip_ecn_decapsulate(skb);
+ skb->mac.raw = memmove(skb->data - skb->mac_len,
+ skb->mac.raw, skb->mac_len);
+ skb->nh.raw = skb->data;
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ err = 0;
+
+out:
+ return err;
+}
+
+static struct xfrm_mode xfrm4_tunnel_mode = {
+ .input = xfrm4_tunnel_input,
+ .output = xfrm4_tunnel_output,
+ .owner = THIS_MODULE,
+ .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm4_tunnel_init(void)
+{
+ return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
+}
+
+static void __exit xfrm4_tunnel_exit(void)
+{
+ int err;
+
+ err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
+ BUG_ON(err);
+}
+
+module_init(xfrm4_tunnel_init);
+module_exit(xfrm4_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -12,67 +12,10 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/icmp.h>
-/* Add encapsulation header.
- *
- * In transport mode, the IP header will be moved forward to make space
- * for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- * tot_len
- * check
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
- */
-static void xfrm4_encap(struct sk_buff *skb)
-{
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
- struct iphdr *iph, *top_iph;
- int flags;
-
- iph = skb->nh.iph;
- skb->h.ipiph = iph;
-
- skb->nh.raw = skb_push(skb, x->props.header_len);
- top_iph = skb->nh.iph;
-
- if (!x->props.mode) {
- skb->h.raw += iph->ihl*4;
- memmove(top_iph, iph, iph->ihl*4);
- return;
- }
-
- top_iph->ihl = 5;
- top_iph->version = 4;
-
- /* DS disclosed */
- top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-
- flags = x->props.flags;
- if (flags & XFRM_STATE_NOECN)
- IP_ECN_clear(top_iph);
-
- top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
- 0 : (iph->frag_off & htons(IP_DF));
- if (!top_iph->frag_off)
- __ip_select_ident(top_iph, dst->child, 0);
-
- top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
-
- top_iph->saddr = x->props.saddr.a4;
- top_iph->daddr = x->id.daddr.a4;
- top_iph->protocol = IPPROTO_IPIP;
-
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-}
-
static int xfrm4_tunnel_check_size(struct sk_buff *skb)
{
int mtu, ret = 0;
@@ -121,7 +64,9 @@ static int xfrm4_output_one(struct sk_bu
if (err)
goto error;
- xfrm4_encap(skb);
+ err = x->mode->output(skb);
+ if (err)
+ goto error;
err = x->type->output(x, skb);
if (err)
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -106,6 +106,26 @@ config INET6_TUNNEL
tristate
default n
+config INET6_XFRM_MODE_TRANSPORT
+ tristate "IPv6: IPsec transport mode"
+ depends on IPV6
+ default IPV6
+ select XFRM
+ ---help---
+ Support for IPsec transport mode.
+
+ If unsure, say Y.
+
+config INET6_XFRM_MODE_TUNNEL
+ tristate "IPv6: IPsec tunnel mode"
+ depends on IPV6
+ default IPV6
+ select XFRM
+ ---help---
+ Support for IPsec tunnel mode.
+
+ If unsure, say Y.
+
config IPV6_TUNNEL
tristate "IPv6: IPv6-in-IPv6 tunnel"
select INET6_TUNNEL
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -20,6 +20,8 @@ obj-$(CONFIG_INET6_ESP) += esp6.o
obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
+obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
+obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -39,6 +39,7 @@
#include <linux/in6.h>
#include <linux/tcp.h>
#include <linux/route.h>
+#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
@@ -488,6 +489,7 @@ int ip6_find_1stfragopt(struct sk_buff *
return offset;
}
+EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
{
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -13,21 +13,9 @@
#include <linux/string.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
-#include <net/ip.h>
#include <net/ipv6.h>
#include <net/xfrm.h>
-static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
-{
- struct ipv6hdr *outer_iph = skb->nh.ipv6h;
- struct ipv6hdr *inner_iph = skb->h.ipv6h;
-
- if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
- IP6_ECN_set_ce(inner_iph);
-}
-
int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
{
int err;
@@ -81,21 +69,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u
xfrm_vec[xfrm_nr++] = x;
+ if (x->mode->input(x, skb))
+ goto drop;
+
if (x->props.mode) { /* XXX */
- if (nexthdr != IPPROTO_IPV6)
- goto drop;
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
- goto drop;
- if (skb_cloned(skb) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
- goto drop;
- if (x->props.flags & XFRM_STATE_DECAP_DSCP)
- ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
- if (!(x->props.flags & XFRM_STATE_NOECN))
- ipip6_ecn_decapsulate(skb);
- skb->mac.raw = memmove(skb->data - skb->mac_len,
- skb->mac.raw, skb->mac_len);
- skb->nh.raw = skb->data;
decaps = 1;
break;
}
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
new file mode 100644
--- /dev/null
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -0,0 +1,73 @@
+/*
+ * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the encapsulation header.
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header. The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_transport_output(struct sk_buff *skb)
+{
+ struct xfrm_state *x = skb->dst->xfrm;
+ struct ipv6hdr *iph;
+ u8 *prevhdr;
+ int hdr_len;
+
+ skb_push(skb, x->props.header_len);
+ iph = skb->nh.ipv6h;
+
+ hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+ skb->nh.raw = prevhdr - x->props.header_len;
+ skb->h.raw = skb->data + hdr_len;
+ memmove(skb->data, iph, hdr_len);
+ return 0;
+}
+
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ return 0;
+}
+
+static struct xfrm_mode xfrm6_transport_mode = {
+ .input = xfrm6_transport_input,
+ .output = xfrm6_transport_output,
+ .owner = THIS_MODULE,
+ .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm6_transport_init(void)
+{
+ return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
+}
+
+static void __exit xfrm6_transport_exit(void)
+{
+ int err;
+
+ err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
+ BUG_ON(err);
+}
+
+module_init(xfrm6_transport_init);
+module_exit(xfrm6_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
new file mode 100644
--- /dev/null
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -0,0 +1,121 @@
+/*
+ * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dsfield.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
+{
+ struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+ struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+ if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+ IP6_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401. The following fields
+ * in it shall be filled in by x->type->output:
+ * payload_len
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header. The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_tunnel_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct xfrm_state *x = dst->xfrm;
+ struct ipv6hdr *iph, *top_iph;
+ int dsfield;
+
+ skb_push(skb, x->props.header_len);
+ iph = skb->nh.ipv6h;
+
+ skb->nh.raw = skb->data;
+ top_iph = skb->nh.ipv6h;
+ skb->nh.raw = &top_iph->nexthdr;
+ skb->h.ipv6h = top_iph + 1;
+
+ top_iph->version = 6;
+ top_iph->priority = iph->priority;
+ top_iph->flow_lbl[0] = iph->flow_lbl[0];
+ top_iph->flow_lbl[1] = iph->flow_lbl[1];
+ top_iph->flow_lbl[2] = iph->flow_lbl[2];
+ dsfield = ipv6_get_dsfield(top_iph);
+ dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+ if (x->props.flags & XFRM_STATE_NOECN)
+ dsfield &= ~INET_ECN_MASK;
+ ipv6_change_dsfield(top_iph, 0, dsfield);
+ top_iph->nexthdr = IPPROTO_IPV6;
+ top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+ ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+ ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+ return 0;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int err = -EINVAL;
+
+ if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
+ goto out;
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ goto out;
+
+ if (skb_cloned(skb) &&
+ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ goto out;
+
+ if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+ ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
+ if (!(x->props.flags & XFRM_STATE_NOECN))
+ ipip6_ecn_decapsulate(skb);
+ skb->mac.raw = memmove(skb->data - skb->mac_len,
+ skb->mac.raw, skb->mac_len);
+ skb->nh.raw = skb->data;
+ err = 0;
+
+out:
+ return err;
+}
+
+static struct xfrm_mode xfrm6_tunnel_mode = {
+ .input = xfrm6_tunnel_input,
+ .output = xfrm6_tunnel_output,
+ .owner = THIS_MODULE,
+ .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm6_tunnel_init(void)
+{
+ return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
+}
+
+static void __exit xfrm6_tunnel_exit(void)
+{
+ int err;
+
+ err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
+ BUG_ON(err);
+}
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -14,68 +14,9 @@
#include <linux/spinlock.h>
#include <linux/icmpv6.h>
#include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
#include <net/ipv6.h>
#include <net/xfrm.h>
-/* Add encapsulation header.
- *
- * In transport mode, the IP header and mutable extension headers will be moved
- * forward to make space for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- * payload_len
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and skb->nh will be set to the nextheader field
- * of the extension header directly preceding the encapsulation header, or in
- * its absence, that of the top IP header. The value of skb->data will always
- * point to the top IP header.
- */
-static void xfrm6_encap(struct sk_buff *skb)
-{
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
- struct ipv6hdr *iph, *top_iph;
- int dsfield;
-
- skb_push(skb, x->props.header_len);
- iph = skb->nh.ipv6h;
-
- if (!x->props.mode) {
- u8 *prevhdr;
- int hdr_len;
-
- hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
- skb->nh.raw = prevhdr - x->props.header_len;
- skb->h.raw = skb->data + hdr_len;
- memmove(skb->data, iph, hdr_len);
- return;
- }
-
- skb->nh.raw = skb->data;
- top_iph = skb->nh.ipv6h;
- skb->nh.raw = &top_iph->nexthdr;
- skb->h.ipv6h = top_iph + 1;
-
- top_iph->version = 6;
- top_iph->priority = iph->priority;
- top_iph->flow_lbl[0] = iph->flow_lbl[0];
- top_iph->flow_lbl[1] = iph->flow_lbl[1];
- top_iph->flow_lbl[2] = iph->flow_lbl[2];
- dsfield = ipv6_get_dsfield(top_iph);
- dsfield = INET_ECN_encapsulate(dsfield, dsfield);
- if (x->props.flags & XFRM_STATE_NOECN)
- dsfield &= ~INET_ECN_MASK;
- ipv6_change_dsfield(top_iph, 0, dsfield);
- top_iph->nexthdr = IPPROTO_IPV6;
- top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
- ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
- ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
-}
-
static int xfrm6_tunnel_check_size(struct sk_buff *skb)
{
int mtu, ret = 0;
@@ -118,7 +59,9 @@ static int xfrm6_output_one(struct sk_bu
if (err)
goto error;
- xfrm6_encap(skb);
+ err = x->mode->output(skb);
+ if (err)
+ goto error;
err = x->type->output(x, skb);
if (err)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -138,6 +138,76 @@ void xfrm_put_type(struct xfrm_type *typ
module_put(type->owner);
}
+int xfrm_register_mode(struct xfrm_mode *mode, int family)
+{
+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+ struct xfrm_mode **modemap;
+ int err = 0;
+
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+ modemap = afinfo->mode_map;
+
+ if (likely(modemap[mode->encap] == NULL))
+ modemap[mode->encap] = mode;
+ else
+ err = -EEXIST;
+ xfrm_policy_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_register_mode);
+
+int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
+{
+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+ struct xfrm_mode **modemap;
+ int err = 0;
+
+ if (unlikely(afinfo == NULL))
+ return -EAFNOSUPPORT;
+ modemap = afinfo->mode_map;
+
+ if (unlikely(modemap[mode->encap] != mode))
+ err = -ENOENT;
+ else
+ modemap[mode->encap] = NULL;
+ xfrm_policy_unlock_afinfo(afinfo);
+ return err;
+}
+EXPORT_SYMBOL(xfrm_unregister_mode);
+
+struct xfrm_mode *xfrm_get_mode(int encap, int family)
+{
+ struct xfrm_policy_afinfo *afinfo;
+ struct xfrm_mode **modemap;
+ struct xfrm_mode *mode;
+ int modload_attempted = 0;
+
+retry:
+ afinfo = xfrm_policy_get_afinfo(family);
+ if (unlikely(afinfo == NULL))
+ return NULL;
+ modemap = afinfo->mode_map;
+
+ mode = modemap[encap];
+ if (unlikely(mode && !try_module_get(mode->owner)))
+ mode = NULL;
+ if (!mode && !modload_attempted) {
+ xfrm_policy_put_afinfo(afinfo);
+ request_module("xfrm-mode-%d-%d", family, encap);
+ modload_attempted = 1;
+ goto retry;
+ }
+
+ xfrm_policy_put_afinfo(afinfo);
+ return mode;
+}
+
+void xfrm_put_mode(struct xfrm_mode *mode)
+{
+ module_put(mode->owner);
+}
+
static inline unsigned long make_jiffies(long secs)
{
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -77,6 +77,8 @@ static void xfrm_state_gc_destroy(struct
kfree(x->ealg);
kfree(x->calg);
kfree(x->encap);
+ if (x->mode)
+ xfrm_put_mode(x->mode);
if (x->type) {
x->type->destructor(x);
xfrm_put_type(x->type);
@@ -1193,6 +1195,10 @@ int xfrm_init_state(struct xfrm_state *x
if (err)
goto error;
+ x->mode = xfrm_get_mode(x->props.mode, family);
+ if (x->mode == NULL)
+ goto error;
+
x->km.state = XFRM_STATE_VALID;
error:
^ permalink raw reply
* [RFC 1/3] [IPSEC] xfrm: Undo afinfo lock proliferation
From: Herbert Xu @ 2006-05-06 11:21 UTC (permalink / raw)
To: Miika Komu; +Cc: Diego Beltrami, David S. Miller, netdev
In-Reply-To: <20060506112026.GA27671@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 1029 bytes --]
Hi:
The number of locks used to manage afinfo structures can easily be reduced
down to one each for policy and state respectively. This is based on the
observation that the write locks are only held by module insertion/removal
which are very rare events so there is no need to further differentiate
between the insertion of modules like ipv6 versus esp6.
The removal of the read locks in xfrm4_policy.c/xfrm6_policy.c might look
suspicious at first. However, after you realise that nobody ever takes
the corresponding write lock you'll feel better :)
As far as I can gather it's an attempt to guard against the removal of
the corresponding modules. Since neither module can be unloaded at all
we can leave it to whoever fixes up IPv6 unloading :)
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p1.patch --]
[-- Type: text/plain, Size: 8506 bytes --]
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -204,8 +204,7 @@ struct xfrm_type;
struct xfrm_dst;
struct xfrm_policy_afinfo {
unsigned short family;
- rwlock_t lock;
- struct xfrm_type_map *type_map;
+ struct xfrm_type *type_map[256];
struct dst_ops *dst_ops;
void (*garbage_collect)(void);
int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -232,7 +231,6 @@ extern int __xfrm_state_delete(struct xf
struct xfrm_state_afinfo {
unsigned short family;
- rwlock_t lock;
struct list_head *state_bydst;
struct list_head *state_byspi;
int (*init_flags)(struct xfrm_state *x);
@@ -264,11 +262,6 @@ struct xfrm_type
u32 (*get_max_size)(struct xfrm_state *, int size);
};
-struct xfrm_type_map {
- rwlock_t lock;
- struct xfrm_type *map[256];
-};
-
extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -17,8 +17,6 @@
static struct dst_ops xfrm4_dst_ops;
static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
-static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
-
static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
{
return __ip_route_output_key((struct rtable**)dst, fl);
@@ -237,9 +235,7 @@ _decode_session4(struct sk_buff *skb, st
static inline int xfrm4_garbage_collect(void)
{
- read_lock(&xfrm4_policy_afinfo.lock);
xfrm4_policy_afinfo.garbage_collect();
- read_unlock(&xfrm4_policy_afinfo.lock);
return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
}
@@ -299,8 +295,6 @@ static struct dst_ops xfrm4_dst_ops = {
static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
.family = AF_INET,
- .lock = RW_LOCK_UNLOCKED,
- .type_map = &xfrm4_type_map,
.dst_ops = &xfrm4_dst_ops,
.dst_lookup = xfrm4_dst_lookup,
.find_bundle = __xfrm4_find_bundle,
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -131,7 +131,6 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8
static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
- .lock = RW_LOCK_UNLOCKED,
.init_flags = xfrm4_init_flags,
.init_tempsel = __xfrm4_init_tempsel,
.state_lookup = __xfrm4_state_lookup,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -23,8 +23,6 @@
static struct dst_ops xfrm6_dst_ops;
static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
-static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
-
static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
{
int err = 0;
@@ -249,9 +247,7 @@ _decode_session6(struct sk_buff *skb, st
static inline int xfrm6_garbage_collect(void)
{
- read_lock(&xfrm6_policy_afinfo.lock);
xfrm6_policy_afinfo.garbage_collect();
- read_unlock(&xfrm6_policy_afinfo.lock);
return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
}
@@ -311,8 +307,6 @@ static struct dst_ops xfrm6_dst_ops = {
static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
.family = AF_INET6,
- .lock = RW_LOCK_UNLOCKED,
- .type_map = &xfrm6_type_map,
.dst_ops = &xfrm6_dst_ops,
.dst_lookup = xfrm6_dst_lookup,
.find_bundle = __xfrm6_find_bundle,
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -135,7 +135,6 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8
static struct xfrm_state_afinfo xfrm6_state_afinfo = {
.family = AF_INET6,
- .lock = RW_LOCK_UNLOCKED,
.init_tempsel = __xfrm6_init_tempsel,
.state_lookup = __xfrm6_state_lookup,
.find_acq = __xfrm6_find_acq,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -46,45 +46,43 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lo
static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
int xfrm_register_type(struct xfrm_type *type, unsigned short family)
{
- struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
- struct xfrm_type_map *typemap;
+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+ struct xfrm_type **typemap;
int err = 0;
if (unlikely(afinfo == NULL))
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock_bh(&typemap->lock);
- if (likely(typemap->map[type->proto] == NULL))
- typemap->map[type->proto] = type;
+ if (likely(typemap[type->proto] == NULL))
+ typemap[type->proto] = type;
else
err = -EEXIST;
- write_unlock_bh(&typemap->lock);
- xfrm_policy_put_afinfo(afinfo);
+ xfrm_policy_unlock_afinfo(afinfo);
return err;
}
EXPORT_SYMBOL(xfrm_register_type);
int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
{
- struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
- struct xfrm_type_map *typemap;
+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+ struct xfrm_type **typemap;
int err = 0;
if (unlikely(afinfo == NULL))
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock_bh(&typemap->lock);
- if (unlikely(typemap->map[type->proto] != type))
+ if (unlikely(typemap[type->proto] != type))
err = -ENOENT;
else
- typemap->map[type->proto] = NULL;
- write_unlock_bh(&typemap->lock);
- xfrm_policy_put_afinfo(afinfo);
+ typemap[type->proto] = NULL;
+ xfrm_policy_unlock_afinfo(afinfo);
return err;
}
EXPORT_SYMBOL(xfrm_unregister_type);
@@ -92,7 +90,7 @@ EXPORT_SYMBOL(xfrm_unregister_type);
struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
{
struct xfrm_policy_afinfo *afinfo;
- struct xfrm_type_map *typemap;
+ struct xfrm_type **typemap;
struct xfrm_type *type;
int modload_attempted = 0;
@@ -102,11 +100,9 @@ retry:
return NULL;
typemap = afinfo->type_map;
- read_lock(&typemap->lock);
- type = typemap->map[proto];
+ type = typemap[proto];
if (unlikely(type && !try_module_get(type->owner)))
type = NULL;
- read_unlock(&typemap->lock);
if (!type && !modload_attempted) {
xfrm_policy_put_afinfo(afinfo);
request_module("xfrm-type-%d-%d",
@@ -1306,17 +1302,31 @@ static struct xfrm_policy_afinfo *xfrm_p
return NULL;
read_lock(&xfrm_policy_afinfo_lock);
afinfo = xfrm_policy_afinfo[family];
- if (likely(afinfo != NULL))
- read_lock(&afinfo->lock);
- read_unlock(&xfrm_policy_afinfo_lock);
+ if (unlikely(!afinfo))
+ read_unlock(&xfrm_policy_afinfo_lock);
return afinfo;
}
static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
{
- if (unlikely(afinfo == NULL))
- return;
- read_unlock(&afinfo->lock);
+ read_unlock(&xfrm_policy_afinfo_lock);
+}
+
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
+{
+ struct xfrm_policy_afinfo *afinfo;
+ if (unlikely(family >= NPROTO))
+ return NULL;
+ write_lock_bh(&xfrm_policy_afinfo_lock);
+ afinfo = xfrm_policy_afinfo[family];
+ if (unlikely(!afinfo))
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
+ return afinfo;
+}
+
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
}
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1103,17 +1103,14 @@ static struct xfrm_state_afinfo *xfrm_st
return NULL;
read_lock(&xfrm_state_afinfo_lock);
afinfo = xfrm_state_afinfo[family];
- if (likely(afinfo != NULL))
- read_lock(&afinfo->lock);
- read_unlock(&xfrm_state_afinfo_lock);
+ if (unlikely(!afinfo))
+ read_unlock(&xfrm_state_afinfo_lock);
return afinfo;
}
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
{
- if (unlikely(afinfo == NULL))
- return;
- read_unlock(&afinfo->lock);
+ read_unlock(&xfrm_state_afinfo_lock);
}
/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
^ permalink raw reply
* [RFC 0/3] [IPSEC]: Add xfrm_mode support
From: Herbert Xu @ 2006-05-06 11:20 UTC (permalink / raw)
To: Miika Komu; +Cc: Diego Beltrami, David S. Miller, netdev
In-Reply-To: <Pine.SOL.4.64.0604191529100.11141@kekkonen.cs.hut.fi>
Hi:
These patches abstract out the protocol-specific encapsulation parts of
IPsec into what I've termed xfrm_mode objects. This allows us to share
a little bit more code. But more importantly, it allows us to add new
encapsulation modes such as BEET or v4/v6 and v6/v4 without polluting
the generic xfrm_input/xfrm_output paths.
These patches are not yet ready to be applied as I need to test them
a bit more.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH,RFT] bcm43xx: use softmac-suggested TX rate
From: Daniel Drake @ 2006-05-06 9:16 UTC (permalink / raw)
To: netdev
Can a bcm43xx user please test this. It uses the new txrate stuff found in
the wireless-dev tree.
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Index: linux/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
===================================================================
--- linux.orig/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ linux/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -296,11 +296,14 @@ void bcm43xx_generate_txhdr(struct bcm43
u16 control = 0;
u16 wsec_rate = 0;
u16 encrypt_frame;
+ u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
+ int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0;
/* Now construct the TX header. */
memset(txhdr, 0, sizeof(*txhdr));
- bitrate = bcm->softmac->txrates.default_rate;
+ bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
+ is_multicast_ether_addr(wireless_header->addr1), is_mgt);
ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
^ permalink raw reply
* Re: VJ Channel API - driver level (PATCH)
From: Evgeniy Polyakov @ 2006-05-06 8:57 UTC (permalink / raw)
To: David S. Miller; +Cc: alex, caitlinb, Leonid.Grossman, shemminger, netdev
In-Reply-To: <20060506084238.GB16558@2ka.mipt.ru>
On Sat, May 06, 2006 at 12:42:38PM +0400, Evgeniy Polyakov (johnpol@2ka.mipt.ru) wrote:
> On Fri, May 05, 2006 at 05:35:33PM -0700, David S. Miller (davem@davemloft.net) wrote:
> > From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> > Date: Fri, 5 May 2006 13:36:56 +0400
> >
> > > Hardware folks could also create it's own implementation and show
> > > community if theirs approach is good or not.
> >
> > Designing hardware for non-existing software infrastructure is
> > risky buisness :-)
>
> There are companies that do TOE and crypto accelerators without
> support from even windows :)
And actually most of them have research departments which do new
interesting developments.
It is Open Source after all - just do everything you want and show
community that it is usefull. Neterion did that right with UFO and LRO.
IBM started to do it with netchannels.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: VJ Channel API - driver level (PATCH)
From: Evgeniy Polyakov @ 2006-05-06 8:42 UTC (permalink / raw)
To: David S. Miller; +Cc: alex, caitlinb, Leonid.Grossman, shemminger, netdev
In-Reply-To: <20060505.173533.55820251.davem@davemloft.net>
On Fri, May 05, 2006 at 05:35:33PM -0700, David S. Miller (davem@davemloft.net) wrote:
> From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> Date: Fri, 5 May 2006 13:36:56 +0400
>
> > Hardware folks could also create it's own implementation and show
> > community if theirs approach is good or not.
>
> Designing hardware for non-existing software infrastructure is
> risky buisness :-)
There are companies that do TOE and crypto accelerators without
support from even windows :)
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [1/1] connector: export cn_already_initialized.
From: Evgeniy Polyakov @ 2006-05-06 8:40 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
In-Reply-To: <20060505.171646.65488074.davem@davemloft.net>
On Fri, May 05, 2006 at 05:16:46PM -0700, David S. Miller (davem@davemloft.net) wrote:
> From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> Date: Thu, 4 May 2006 16:24:22 +0400
>
> > No in-kernel users require it to be exported, so if you do think it
> > should not be exported I will force external module changes.
>
> What are the alternatives?
This flag shows that connector has finished it's initialization and now
it's calbacks can be safely added. In-kernel users (like various
accountings) which are initialized first (like fs) use that flag to
check if connector can be added or not.
Some external patches, which can be built both as static build and as
module just check that value, and thus will fail with unresolved symbol
when cn and module are built as modules.
The right set of operations should be following:
If external module is loaded and cn is not loaded or compiled into the
kernel, insmod will just fail with unresolved symbol (cn_add_callback and others),
if cn is already loaded or was built into the tree, then it has been
initialized already and there is no need to check that value, external
module should be just loaded.
I think the right solution is to call external init functions after cn
init function, but it's ordering is not always known.
While writing this I've thought another solution, when
cn_add_callback() will just return -EINPROGRESS or other special error,
which means that it is too early to call it and it must be run later.
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 3589707..f852e68 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -308,6 +308,9 @@ int cn_add_callback(struct cb_id *id, ch
int err;
struct cn_dev *dev = &cdev;
+ if (!cn_already_initialized)
+ return -EINPROGRESS;
+
err = cn_queue_add_callback(dev->cbdev, name, id, callback);
if (err)
return err;
@@ -456,6 +459,8 @@ static int __init cn_init(void)
sock_release(dev->nls->sk_socket);
return -EINVAL;
}
+
+ cn_already_initialized = 1;
err = cn_add_callback(&dev->id, "connector", &cn_callback);
if (err) {
@@ -465,8 +470,6 @@ static int __init cn_init(void)
return -EINVAL;
}
- cn_already_initialized = 1;
-
return 0;
}
--
Evgeniy Polyakov
^ permalink raw reply related
* Re: Fw: [Bugme-new] [Bug 6495] New: Vlan MTU Fragmentation
From: Andrew Morton @ 2006-05-06 6:17 UTC (permalink / raw)
To: Ben Greear; +Cc: netdev, bugme-daemon, slavon
In-Reply-To: <445C2872.5060208@candelatech.com>
On Fri, 05 May 2006 21:39:14 -0700
Ben Greear <greearb@candelatech.com> wrote:
> Andrew Morton wrote:
>
> > Sorry, I should have added Badalian to Cc:. He's using 3c905C (3c59x.c,
> > allegedly maintained by myself).
> >
> > (Badalian, please use emailed reply-to-all rather than the bugzilla
> > interface for the remainder of this discussion, thanks).
> >
>
> There is an ancient patch on this page:
>
> http://www.bewley.net/linux/vlan/patches/
>
> I have no idea if this would apply or if it has already been put into the
> kernel. I also don't have any 3com nics to test with, but there are probably
> folks on the vlan mailing list that could try patches...
>
Yeah, that was merged ages ago.
I guess I can type simple commands and add printks. Do you have time to
take a look at the driver and suggest what I should be looking for?
^ permalink raw reply
* Re: [PATCH 2/2] netdev: create attribute_groups with class_device_add
From: David S. Miller @ 2006-05-06 6:00 UTC (permalink / raw)
To: greg; +Cc: shemminger, netdev, linux-kernel
In-Reply-To: <20060506040839.GA12636@kroah.com>
From: Greg KH <greg@kroah.com>
Date: Fri, 5 May 2006 21:08:39 -0700
> On Fri, May 05, 2006 at 06:41:58PM -0700, David S. Miller wrote:
> > From: Stephen Hemminger <shemminger@osdl.org>
> > Date: Fri, 21 Apr 2006 12:54:38 -0700
> >
> > > Atomically create attributes when class device is added. This avoids the
> > > race between registering class_device (which generates hotplug event),
> > > and the creation of attribute groups.
> > >
> > > Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
> >
> > Did the first patch that adds the attribute_group creation
> > infrastructure go in so that we can get this networking fix in?
>
> It and the netdev patch are setting in my tree which is showing up in
> -mm. I'm going to wait until 2.6.17 is out to send the first patch. I
> can send the second one then too if you want me to (probably make it
> easier that way.)
The networking bit by Stephen is a bug fix.
^ permalink raw reply
* Re: [RFC] Proposed structure for Regulatory/Geographical Wireless database
From: Uli Kunitz @ 2006-05-06 5:07 UTC (permalink / raw)
To: Larry Finger
Cc: Uli Kunitz, netdev, Faidon Liambotis, Rick Jones, Harald Welte,
Jouni Malinen, Christoph Hellwig
In-Reply-To: <445BC234.4060909@lwfinger.net>
Larry Finger wrote:
> Uli Kunitz wrote:
> > Larry Finger wrote:
> >
> > > * A new routine (ieee80211_init_geo ?) will be written to be called by the
> > > driver to load the geo structure into the kernel. Information passed to
> > > the
> > > daemon will be the country code in ASCII and whether the interface is to
> > > be
> > > used indoors or outdoors.
> >
> > Would it be possible to support the regulatory domain codes as
> > used in the outdated table 105 in Corrigendum 1 for 802.11b? The
> > ZD1211 EEPROM contains only this code. An easy translation
> > function would be sufficient. Maybe the group codes could be
> > misused for it.
>
> That certainly shouldn't be any difficulty. It could be done in the ZD1211
> driver before it calls the ieee80211_init_geo routine, or it could be done in
> the regulatory daemon. I assume that the EEPROM contains X'10' for FCC
> regulations, X'31' for Spain, etc.
>
> Larry
Yes, it could be done in the driver. But if there are other
drivers having the same issue, the helper function should be
integrated in the geo code.
Uli
--
Uli Kunitz - kune@deine-taler.de
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 6495] New: Vlan MTU Fragmentation
From: Ben Greear @ 2006-05-06 4:39 UTC (permalink / raw)
To: Andrew Morton; +Cc: netdev, bugme-daemon, slavon
In-Reply-To: <20060505193903.249feaf8.akpm@osdl.org>
Andrew Morton wrote:
> Sorry, I should have added Badalian to Cc:. He's using 3c905C (3c59x.c,
> allegedly maintained by myself).
>
> (Badalian, please use emailed reply-to-all rather than the bugzilla
> interface for the remainder of this discussion, thanks).
>
There is an ancient patch on this page:
http://www.bewley.net/linux/vlan/patches/
I have no idea if this would apply or if it has already been put into the
kernel. I also don't have any 3com nics to test with, but there are probably
folks on the vlan mailing list that could try patches...
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: Please pull upstream-fixes branch of wireless-2.6
From: Stephen Hemminger @ 2006-05-06 4:12 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andrew Morton, John W. Linville, netdev, jeff
In-Reply-To: <Pine.LNX.4.64.0605052017070.16343@g5.osdl.org>
Linus Torvalds wrote:
> On Fri, 5 May 2006, Andrew Morton wrote:
>
>> On Fri, 5 May 2006 21:06:18 -0400
>> "John W. Linville" <linville@tuxdriver.com> wrote:
>>
>>> These are fixes intended for 2.6.17...thanks!
>>>
>> Jeff is offline for a couple of weeks. Please prepare a pull for Linus.
>>
>
> Actually, while Jeff is off, Steve Hemminger is supposed to be the network
> driver overlord ("All bow down before the mighty Shemminger"), so please
> do synchronize with him.
>
> Of course, that might be just Steve taking a look and telling me "yeah,
> please pull directly from John".
>
> Linus
>
I had a bunch ready for monday...
^ permalink raw reply
* Re: [PATCH 2/2] netdev: create attribute_groups with class_device_add
From: Greg KH @ 2006-05-06 4:08 UTC (permalink / raw)
To: David S. Miller; +Cc: shemminger, netdev, linux-kernel
In-Reply-To: <20060505.184158.131584956.davem@davemloft.net>
On Fri, May 05, 2006 at 06:41:58PM -0700, David S. Miller wrote:
> From: Stephen Hemminger <shemminger@osdl.org>
> Date: Fri, 21 Apr 2006 12:54:38 -0700
>
> > Atomically create attributes when class device is added. This avoids the
> > race between registering class_device (which generates hotplug event),
> > and the creation of attribute groups.
> >
> > Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
>
> Did the first patch that adds the attribute_group creation
> infrastructure go in so that we can get this networking fix in?
It and the netdev patch are setting in my tree which is showing up in
-mm. I'm going to wait until 2.6.17 is out to send the first patch. I
can send the second one then too if you want me to (probably make it
easier that way.)
thanks,
greg k-h
^ permalink raw reply
* Re: Please pull upstream-fixes branch of wireless-2.6
From: Linus Torvalds @ 2006-05-06 3:20 UTC (permalink / raw)
To: Andrew Morton; +Cc: John W. Linville, netdev, jeff, shemminger
In-Reply-To: <20060505200812.1e76785c.akpm@osdl.org>
On Fri, 5 May 2006, Andrew Morton wrote:
> On Fri, 5 May 2006 21:06:18 -0400
> "John W. Linville" <linville@tuxdriver.com> wrote:
> >
> > These are fixes intended for 2.6.17...thanks!
>
> Jeff is offline for a couple of weeks. Please prepare a pull for Linus.
Actually, while Jeff is off, Steve Hemminger is supposed to be the network
driver overlord ("All bow down before the mighty Shemminger"), so please
do synchronize with him.
Of course, that might be just Steve taking a look and telling me "yeah,
please pull directly from John".
Linus
^ permalink raw reply
* Re: Please pull upstream-fixes branch of wireless-2.6
From: Andrew Morton @ 2006-05-06 3:08 UTC (permalink / raw)
To: John W. Linville; +Cc: netdev, jeff, shemminger, Linus Torvalds
In-Reply-To: <20060506010613.GA26189@tuxdriver.com>
On Fri, 5 May 2006 21:06:18 -0400
"John W. Linville" <linville@tuxdriver.com> wrote:
> These are fixes intended for 2.6.17...thanks!
Jeff is offline for a couple of weeks. Please prepare a pull for Linus.
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 6495] New: Vlan MTU Fragmentation
From: Andrew Morton @ 2006-05-06 2:39 UTC (permalink / raw)
To: Ben Greear; +Cc: netdev, bugme-daemon, slavon
In-Reply-To: <445B75D2.6080702@candelatech.com>
On Fri, 05 May 2006 08:57:06 -0700
Ben Greear <greearb@candelatech.com> wrote:
> Andrew Morton wrote:
> >
> > Begin forwarded message:
> >
> > Date: Thu, 4 May 2006 23:15:56 -0700
> > From: bugme-daemon@bugzilla.kernel.org
> > To: bugme-new@lists.osdl.org
> > Subject: [Bugme-new] [Bug 6495] New: Vlan MTU Fragmentation
> >
> >
> > http://bugzilla.kernel.org/show_bug.cgi?id=6495
> >
> > Summary: Vlan MTU Fragmentation
> > Kernel Version: 2.6.16.12
> > Status: NEW
> > Severity: normal
> > Owner: shemminger@osdl.org
> > Submitter: slavon@bigtelecom.ru
> >
> >
> > Steps to reproduce:
> >
> > ifconfing eth0 mtu 1500
> > ifconfing eth0.100 mtu 1500
> >
> > ping www.ru -s 2000
> > -- BAD --
> >
> > ----------------
> >
> > ifconfing eth0 mtu 1500
> > ifconfing eth0.100 mtu 1496
> >
> > ping www.ru -s 2000
> > --NORMAL--
>
> This is almost definately a bug in the ethernet driver. The driver needs
> to be modified so that it can send/receive pkts that are MTU + 4 bytes for the
> VLAN header.
>
> We need to know what NIC/driver this user is using...
>
> Ben
>
Sorry, I should have added Badalian to Cc:. He's using 3c905C (3c59x.c,
allegedly maintained by myself).
(Badalian, please use emailed reply-to-all rather than the bugzilla
interface for the remainder of this discussion, thanks).
^ 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