* Re: [PATCH] bridge: assign random address
From: Andrew Morton @ 2007-12-12 0:02 UTC (permalink / raw)
To: Stephen Hemminger
Cc: davem, netdev, bugme-daemon, berrange, jeff, herbert, rjw
In-Reply-To: <20071211154835.75ace6bc@freepuppy.rosehill>
On Tue, 11 Dec 2007 15:48:35 -0800
Stephen Hemminger <shemminger@linux-foundation.org> wrote:
> Assigning a valid random address to bridge device solves problems
> when bridge device is brought up before adding real device to bridge.
> When the first real device is added to the bridge, it's address
> will overide the bridges random address.
>
> Note: any device added to a bridge must already have a valid
> ethernet address.
> br_add_if -> br_fdb_insert -> fdb_insert -> is_valid_ether_addr
>
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
>
> --- a/net/bridge/br_device.c 2007-10-16 16:48:21.000000000 -0700
> +++ b/net/bridge/br_device.c 2007-12-11 15:36:52.000000000 -0800
> @@ -157,8 +157,7 @@ static struct ethtool_ops br_ethtool_ops
>
> void br_dev_setup(struct net_device *dev)
> {
> - memset(dev->dev_addr, 0, ETH_ALEN);
> -
> + random_ether_addr(dev->dev_addr);
> ether_setup(dev);
>
> dev->do_ioctl = br_dev_ioctl;
I'd have thought that a comment is needed here as it is rather unobvious
what that code is there for.
^ permalink raw reply
* Re: [2.6 patch] drivers/net/ipg.c: add __devexit annotation
From: Francois Romieu @ 2007-12-11 23:59 UTC (permalink / raw)
To: Adrian Bunk; +Cc: sorbica, jesse, netdev, linux-kernel
In-Reply-To: <20071211222030.GD14204@stusta.de>
Adrian Bunk <bunk@kernel.org> :
> ipg_remove() can become __devexit.
>
> Signed-off-by: Adrian Bunk <bunk@kernel.org>
I'll add it to the pending ipg queue.
--
Ueimor
^ permalink raw reply
* Re: [PATCH] [NET]: Fix Ooops of napi net_rx_action.
From: Joonwoo Park @ 2007-12-12 0:12 UTC (permalink / raw)
To: Brandeburg, Jesse
Cc: David Miller, netdev, linux-kernel, herbert, Kok, Auke-jan H
In-Reply-To: <36D9DB17C6DE9E40B059440DB8D95F5203F82FC3@orsmsx418.amr.corp.intel.com>
2007/12/12, Brandeburg, Jesse <jesse.brandeburg@intel.com>:
>
> all drivers using NAPI in 2.6.24+ (NNAPI??) must return zero here, after
> calling netif_rx_complete. netif_rx_complete plus work_done != 0 causes
> a bug.
>
Brandeburg,
Don't we need to return non-zero work_done after netif_rx_complete if
work_done != weight?
Thanks,
Joonwoo
^ permalink raw reply
* Re: [RFC PATCH net-2.6.25 uncompilable] [TCP]: Avoid breaking GSOed skbs when SACKed one-by-one
From: Lachlan Andrew @ 2007-12-12 0:14 UTC (permalink / raw)
To: David Miller; +Cc: ilpo.jarvinen, netdev, quetchen
In-Reply-To: <20071211.043239.224938181.davem@davemloft.net>
Greetings all,
On 11/12/2007, David Miller <davem@davemloft.net> wrote:
>
> we should
> get it right as it might have network driver interface implications.
If you're redoing the driver interface, could I put in a request for
packet time-stamping at a lower level?
This thread started because TCP processing interferes with RTT
estimation. This problem would be eliminated if time-stamping were
done as soon as the packet comes off the NIC.
$0.02
Lachlan
--
Lachlan Andrew Dept of Computer Science, Caltech
1200 E California Blvd, Mail Code 256-80, Pasadena CA 91125, USA
Ph: +1 (626) 395-8820 Fax: +1 (626) 568-3603
http://netlab.caltech.edu/~lachlan
^ permalink raw reply
* RE: [PATCH] [NET]: Fix Ooops of napi net_rx_action.
From: Brandeburg, Jesse @ 2007-12-12 0:38 UTC (permalink / raw)
To: Joonwoo Park; +Cc: David Miller, netdev, linux-kernel, herbert, Kok, Auke-jan H
In-Reply-To: <b25c3fa70712111612o16a62b49g6709aa728f31e27a@mail.gmail.com>
Joonwoo Park wrote:
> 2007/12/12, Brandeburg, Jesse <jesse.brandeburg@intel.com>:
>>
>> all drivers using NAPI in 2.6.24+ (NNAPI??) must return zero here,
>> after calling netif_rx_complete. netif_rx_complete plus work_done
>> != 0 causes a bug.
>>
>
> Brandeburg,
> Don't we need to return non-zero work_done after netif_rx_complete if
> work_done != weight?
Actually we just need to make sure we don't return work_done == weight
as it is checked on line 2210 of dev.c.
I should also note that I was wrong above, and that the requirement is
that we MUST not return work_done == weight when indicating
netif_rx_complete.
So, returning 0 when we actually did some work, but are being removed
from the poll list because something like !netif_running, is probably
okay, but I'm sure someone will disagree with me. Maybe returning like
this would be better
diff --git a/drivers/net/e1000/e1000_main.c
b/drivers/net/e1000/e1000_main.c
index 724f067..76d5e3b 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3933,6 +3933,10 @@ quit_polling:
e1000_set_itr(adapter);
netif_rx_complete(poll_dev, napi);
e1000_irq_enable(adapter);
+ if (work_done == weight)
+ return work_done - 1;
+ else
+ return work_done;
}
return work_done;
Jesse
^ permalink raw reply related
* Re: [patch 1/1] Convert the semaphore to a mutex in net/tipc/socket.c
From: Andrew Morton @ 2007-12-12 0:44 UTC (permalink / raw)
To: Kevin Winchester
Cc: mingo, per.liden, jon.maloy, allan.stephens, tipc-discussion,
linux-kernel, kjwinchester, netdev, David S. Miller
In-Reply-To: <20071210011800.543055487@gmail.com>
On Sun, 09 Dec 2007 21:17:42 -0400
Kevin Winchester <kjwinchester@gmail.com> wrote:
> Note also that in the release method, down_interruptible() was being called
> without checking the return value. I converted it to mutex_lock_interruptible()
> and made the interrupted case return -ERESTARTSYS, as was done for all other
> calls to down_interruptible() in the file.
That's an outright bug.
static int release(struct socket *sock)
{
struct tipc_sock *tsock = tipc_sk(sock->sk);
struct sock *sk = sock->sk;
int res = TIPC_OK;
struct sk_buff *buf;
dbg("sock_delete: %x\n",tsock);
if (!tsock)
return 0;
down_interruptible(&tsock->sem);
if (!sock->sk) {
up(&tsock->sem);
return 0;
}
...
up(&tsock->sem);
...
}
So if the calling process has signal_pending(), down_interruptible() will
return without having downed the semaphore and then we merrily proceed to
do up() on it, so a subsequent down() won't actually take the lock and
things will deteriorate from there.
So I'd propose this:
--- a/net/tipc/socket.c~a
+++ a/net/tipc/socket.c
@@ -253,7 +253,7 @@ static int release(struct socket *sock)
dbg("sock_delete: %x\n",tsock);
if (!tsock)
return 0;
- down_interruptible(&tsock->sem);
+ down(&tsock->sem);
if (!sock->sk) {
up(&tsock->sem);
return 0;
_
as a for-2.6.24 bugfix. And for 2.6.23. But someone who knows what
they're doing should take a look at this...
^ permalink raw reply
* Re: [PATCH] iproute2: support dotted-quad netmask notation.
From: Stephen Hemminger @ 2007-12-12 1:14 UTC (permalink / raw)
To: Andreas Henriksson; +Cc: netdev
In-Reply-To: <1197220222.4392.9.camel@localhost.localdomain>
On Sun, 09 Dec 2007 18:10:22 +0100
Andreas Henriksson <andreas@fatal.se> wrote:
>
> On lör, 2007-12-08 at 00:41 +0100, Andreas Henriksson wrote:
> > On tor, 2007-12-06 at 11:53 -0800, Stephen Hemminger wrote:
> > > On Tue, 4 Dec 2007 14:58:18 +0100
> > > Andreas Henriksson <andreas@fatal.se> wrote:
> > >
> > > > Suggested patch for allowing netmask to be specified in dotted quad format.
> > > > See http://bugs.debian.org/357172
> > > >
> > Updated patch, added your netmask validation code but without the check
> > that made 0.0.0.0 (default) and 255.255.255.255 (one address) invalid
> > netmasks as they are permitted in CIDR format.
>
> I think both previous patches where broken on big-endian platforms.
> Here's an updated patch again. I'm very sorry for the inconvenience!
>
> Signed-off-by: Andreas Henriksson <andreas@fatal.se>
>
>
> diff --git a/lib/utils.c b/lib/utils.c
> index 4c42dfd..bb88cf7 100644
> --- a/lib/utils.c
> +++ b/lib/utils.c
> @@ -47,6 +47,41 @@ int get_integer(int *val, const char *arg, int base)
> return 0;
> }
>
> +/* a valid netmask must be 2^n - 1 (n = 1..31) */
> +static int is_valid_netmask(const inet_prefix *addr)
> +{
> + uint32_t host;
> +
> + if (addr->family != AF_INET)
> + return 0;
> +
> + host = ~ntohl(addr->data[0]);
> +
> + return (host & (host + 1)) == 0;
> +}
> +
> +static int get_netmask(unsigned *val, const char *arg, int base)
> +{
> + inet_prefix addr;
> +
> + if (!get_unsigned(val, arg, base))
> + return 0;
> +
> + /* try coverting dotted quad to CIDR */
> + if (!get_addr_1(&addr, arg, AF_INET)) {
> + u_int32_t mask;
> +
> + *val=0;
> + for (mask = ntohl(addr.data[0]); mask; mask <<= 1)
> + (*val)++;
> +
> + if (is_valid_netmask(&addr))
> + return 0;
> + }
> +
> + return -1;
> +}
> +
> int get_unsigned(unsigned *val, const char *arg, int base)
> {
> unsigned long res;
> @@ -304,7 +339,8 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
> dst->bitlen = 32;
> }
> if (slash) {
> - if (get_unsigned(&plen, slash+1, 0) || plen > dst->bitlen) {
> + if (get_netmask(&plen, slash+1, 0)
> + || plen > dst->bitlen) {
> err = -1;
> goto done;
> }
>
>
>
>
applied
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* Re: [PATCH 2/2] [IPSEC]: Add ICMP host relookup support
From: Herbert Xu @ 2007-12-12 1:25 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20071211.091056.161097349.davem@davemloft.net>
On Tue, Dec 11, 2007 at 09:10:56AM -0800, David Miller wrote:
>
> This enumeration doesn't exist in my tree, what are you generating
> these patches against?
Sorry, I forgot to include the first patch because I made it
before the xfrm_lookup bug fix.
Here's the complete set against net-2.6.25.
Thanks,
--
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
* Re: [PATCH RFC] [3/9] modpost: Declare the modpost error functions as printf like
From: Rusty Russell @ 2007-12-12 1:37 UTC (permalink / raw)
To: Sam Ravnborg; +Cc: Andi Kleen, netdev, linux-kernel
In-Reply-To: <20071210185008.GA17315@uranus.ravnborg.org>
On Tuesday 11 December 2007 05:50:08 Sam Ravnborg wrote:
> On Thu, Nov 22, 2007 at 03:43:08AM +0100, Andi Kleen wrote:
> > This way gcc can warn for wrong format strings
>
> This loks good. Can I get i s-o-b then I will apply it.
Even better, switch the code to the standard warn/warnx/err/errx.
Cheers,
Rusty.
^ permalink raw reply
* Re: [PATCH resend] virtio_net: remove double ether_setup
From: Rusty Russell @ 2007-12-12 1:41 UTC (permalink / raw)
To: Christian Borntraeger
Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
virtualization-qjLDD68F18O7TbgM5vRIOg,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <200712111238.53960.borntraeger-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
On Tuesday 11 December 2007 22:38:53 Christian Borntraeger wrote:
> Hello Rusty,
>
> this is a small fix for virtio_net.
> virtnet_probe already calls alloc_etherdev, which calls ether_setup.
> There is no need to do that again.
>
> Signed-off-by: Christian Borntraeger <borntraeger-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Acked-by: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
Can you send straight to akpm or davem? I'm supposed to be on vacation at the
moment (and not doing a very good job :)
Thanks,
Rusty.
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
^ permalink raw reply
* Re: [Bugme-new] [Bug 9545] New: Cannot bring up a bridge interface without a MAC address set
From: Herbert Xu @ 2007-12-12 1:51 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Andrew Morton, netdev, bugme-daemon, berrange, Jeff Garzik,
Rafael J. Wysocki
In-Reply-To: <20071211145243.66e1f66a@freepuppy.rosehill>
On Tue, Dec 11, 2007 at 02:52:43PM -0800, Stephen Hemminger wrote:
>
> The tap devices have to have addresses don't they. So bringing up an empty
> bridge is meaningless. If you just add the device first then it will work.
Actually bringing up a bridge with no constituents is useful for
a bridge that's made up of only virtual interfaces. Since each
vritual interface may be created or destroyed at run-time it'd
be quite awkward to check every time to see if that's the last
or first and act differently on the bridge.
More importantly constiuents can be added to and removed from a
bridge without taking it down.
> Could be fixed to prevent errors from existing scripts but it is not a complete showstopper.
Well this stops FC8 working with Xen so for that it's a showstopper :)
> The problem is that when device is brought up it propogates events up to
> other layers and applications, these layers will then query and see a bogus
> address.
What exactly would it break for this scenario though?
Cheersk,
--
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
* Re: [IPSEC] RFC 4301 PFP Support
From: Herbert Xu @ 2007-12-12 1:52 UTC (permalink / raw)
To: Tyler Hicks; +Cc: netdev, latten, davem
In-Reply-To: <20071211213445.GA11887@hestia>
On Tue, Dec 11, 2007 at 01:34:45PM -0800, Tyler Hicks wrote:
>
> Should we just use the larval selectors or should we assume that
> openswan will begin to send valid selectors? I asked for the openswan
> dev's opinions and they referred me to Herbert Xu. It seems as though
> the correct solution would be for openswan to pass valid selectors in
> UPDSA messages, even if it is the larval selectors we gave them.
Yes we should patch openswan to generate the correct SA selectors.
With the previous standard SA selectors were redundant due to the
presence of policy selectors. But with RFC 4301 the KM should
start setting them.
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
* Re: [kvm-devel] [PATCH resent] virtio_net: Fix stalled inbound trafficon early packets
From: Rusty Russell @ 2007-12-12 1:54 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: dor.laor, kvm-devel, netdev, virtualization
In-Reply-To: <200712111416.12655.borntraeger@de.ibm.com>
On Wednesday 12 December 2007 00:16:12 Christian Borntraeger wrote:
> That would also work. We already have VRING_AVAIL_F_NO_INTERRUPT in
> virtio_ring.c - maybe we can use that. Its hidden in callback and
> restart handling, what about adding an explicit startup?
Yes, I debated whether to make this a separate hook or not; the current method
reduces the number of function calls without having two ways of disabling
callbacks.
In this case, simply starting devices with callbacks disabled and
renaming 'restart' to 'enable' (or something) and calling it at the beginning
is probably sufficient?
Thanks for all this debugging! Will apply next week when I'm back...
> Ok, didnt know that. At the moment I can live with my private patch
> while we work on a final solution. Meanwhile I will try to debug virtio
> on SMP guests - I still see some strange races on our test system. (But
> block and net is now working on s390 and can cope with medium load. )
Obviously SMP is not something I tested under lguest, so can believe there are
nasty lurking bugs. Hope they're not too deep...
Thanks!
Rusty.
^ permalink raw reply
* [PATCH 1/3] [IPSEC]: Make xfrm_lookup flags argument a bit-field
From: Herbert Xu @ 2007-12-12 1:57 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20071212012552.GA20618@gondor.apana.org.au>
[IPSEC]: Make xfrm_lookup flags argument a bit-field
This patch introduces an enum for bits in the flags argument of xfrm_lookup.
This is so that we can cram more information into it later.
Since all current users use just the values 0 and 1, XFRM_LOOKUP_WAIT has
been added with the value 1 << 0 to represent the current meaning of flags.
The test in __xfrm_lookup has been changed accordingly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/dst.h | 5 +++++
net/xfrm/xfrm_policy.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index e86b9a0..aaa2dbb 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -265,6 +265,11 @@ static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
extern void dst_init(void);
+/* Flags for xfrm_lookup flags argument. */
+enum {
+ XFRM_LOOKUP_WAIT = 1 << 0,
+};
+
struct flowi;
#ifndef CONFIG_XFRM
static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 39805b4..265c679 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1565,7 +1565,7 @@ restart:
xfrm_pol_put(policy);
return -EREMOTE;
}
- if (err == -EAGAIN && flags) {
+ if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) {
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&km_waitq, &wait);
^ permalink raw reply related
* [PATCH 3/3] [IPSEC]: Add ICMP host relookup support
From: Herbert Xu @ 2007-12-12 1:58 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20071212012552.GA20618@gondor.apana.org.au>
[IPSEC]: Add ICMP host relookup support
RFC 4301 requires us to relookup ICMP traffic that does not match any
policies using the reverse of its payload. This patch implements this
for ICMP traffic that originates from or terminates on localhost.
This is activated on outbound with the new policy flag XFRM_POLICY_ICMP,
and on inbound by the new state flag XFRM_STATE_ICMP.
On inbound the policy check is now performed by the ICMP protocol so
that it can repeat the policy check where necessary.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/xfrm.h | 3 +
include/net/dst.h | 1
net/ipv4/af_inet.c | 1
net/ipv4/icmp.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++--
net/ipv6/icmp.c | 60 +++++++++++++++++++++++++++++++++--
net/xfrm/xfrm_policy.c | 17 ++++++++--
6 files changed, 154 insertions(+), 10 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index c0e41e0..1131eab 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -329,6 +329,7 @@ struct xfrm_usersa_info {
#define XFRM_STATE_DECAP_DSCP 2
#define XFRM_STATE_NOPMTUDISC 4
#define XFRM_STATE_WILDRECV 8
+#define XFRM_STATE_ICMP 16
};
struct xfrm_usersa_id {
@@ -363,6 +364,8 @@ struct xfrm_userpolicy_info {
#define XFRM_POLICY_BLOCK 1
__u8 flags;
#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
+ /* Automatically expand selector to include matching ICMP payloads. */
+#define XFRM_POLICY_ICMP 2
__u8 share;
};
diff --git a/include/net/dst.h b/include/net/dst.h
index aaa2dbb..31468c9 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -268,6 +268,7 @@ extern void dst_init(void);
/* Flags for xfrm_lookup flags argument. */
enum {
XFRM_LOOKUP_WAIT = 1 << 0,
+ XFRM_LOOKUP_ICMP = 1 << 1,
};
struct flowi;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 7f8b27f..5089a36 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1291,6 +1291,7 @@ static struct net_protocol udp_protocol = {
static struct net_protocol icmp_protocol = {
.handler = icmp_rcv,
+ .no_policy = 1,
};
static int __init init_ipv4_mibs(void)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index c0898c5..4e3bfcd 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -92,6 +92,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <net/checksum.h>
+#include <net/xfrm.h>
/*
* Build xmit assembly blocks
@@ -564,11 +565,71 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
}
}
};
+ int err;
+ struct rtable *rt2;
+
security_skb_classify_flow(skb_in, &fl);
- if (ip_route_output_key(&rt, &fl))
+ if (__ip_route_output_key(&rt, &fl))
+ goto out_unlock;
+
+ /* No need to clone since we're just using its address. */
+ rt2 = rt;
+
+ err = xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
+ switch (err) {
+ case 0:
+ if (rt != rt2)
+ goto route_done;
+ break;
+ case -EPERM:
+ rt = NULL;
+ break;
+ default:
+ goto out_unlock;
+ }
+
+ if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
+ goto out_unlock;
+
+ if (inet_addr_type(fl.fl4_src) == RTN_LOCAL)
+ err = __ip_route_output_key(&rt2, &fl);
+ else {
+ struct flowi fl2 = {};
+ struct dst_entry *odst;
+
+ fl2.fl4_dst = fl.fl4_src;
+ if (ip_route_output_key(&rt2, &fl2))
+ goto out_unlock;
+
+ /* Ugh! */
+ odst = skb_in->dst;
+ err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
+ RT_TOS(tos), rt2->u.dst.dev);
+
+ dst_release(&rt2->u.dst);
+ rt2 = (struct rtable *)skb_in->dst;
+ skb_in->dst = odst;
+ }
+
+ if (err)
+ goto out_unlock;
+
+ err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
+ XFRM_LOOKUP_ICMP);
+ if (err == -ENOENT) {
+ if (!rt)
+ goto out_unlock;
+ goto route_done;
+ }
+
+ dst_release(&rt->u.dst);
+ rt = rt2;
+
+ if (err)
goto out_unlock;
}
+route_done:
if (!icmpv4_xrlim_allow(rt, type, code))
goto ende;
@@ -917,6 +978,22 @@ int icmp_rcv(struct sk_buff *skb)
struct icmphdr *icmph;
struct rtable *rt = (struct rtable *)skb->dst;
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb) &&
+ skb->sp->xvec[skb->sp->len - 1]->props.flags & XFRM_STATE_ICMP) {
+ int nh;
+
+ if (!pskb_may_pull(skb, sizeof(*icmph) + sizeof(struct iphdr)))
+ goto drop;
+
+ nh = skb_network_offset(skb);
+ skb_set_network_header(skb, sizeof(*icmph));
+
+ if (!xfrm4_policy_check_reverse(NULL, XFRM_POLICY_IN, skb))
+ goto drop;
+
+ skb_set_network_header(skb, nh);
+ }
+
ICMP_INC_STATS_BH(ICMP_MIB_INMSGS);
switch (skb->ip_summed) {
@@ -930,8 +1007,7 @@ int icmp_rcv(struct sk_buff *skb)
goto error;
}
- if (!pskb_pull(skb, sizeof(struct icmphdr)))
- goto error;
+ __skb_pull(skb, sizeof(*icmph));
icmph = icmp_hdr(skb);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 4582bbc..478ee77 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -63,6 +63,7 @@
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/icmp.h>
+#include <net/xfrm.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -86,7 +87,7 @@ static int icmpv6_rcv(struct sk_buff *skb);
static struct inet6_protocol icmpv6_protocol = {
.handler = icmpv6_rcv,
- .flags = INET6_PROTO_FINAL,
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
static __inline__ int icmpv6_xmit_lock(void)
@@ -310,8 +311,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
struct ipv6_pinfo *np;
struct in6_addr *saddr = NULL;
struct dst_entry *dst;
+ struct dst_entry *dst2;
struct icmp6hdr tmp_hdr;
struct flowi fl;
+ struct flowi fl2;
struct icmpv6_msg msg;
int iif = 0;
int addr_type = 0;
@@ -418,9 +421,42 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
goto out_dst_release;
}
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ /* No need to clone since we're just using its address. */
+ dst2 = dst;
+
+ err = xfrm_lookup(&dst, &fl, sk, 0);
+ switch (err) {
+ case 0:
+ if (dst != dst2)
+ goto route_done;
+ break;
+ case -EPERM:
+ dst = NULL;
+ break;
+ default:
+ goto out;
+ }
+
+ if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
+ goto out;
+
+ if (ip6_dst_lookup(sk, &dst2, &fl))
goto out;
+ err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP);
+ if (err == -ENOENT) {
+ if (!dst)
+ goto out;
+ goto route_done;
+ }
+
+ dst_release(dst);
+ dst = dst2;
+
+ if (err)
+ goto out;
+
+route_done:
if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops;
else
@@ -610,6 +646,22 @@ static int icmpv6_rcv(struct sk_buff *skb)
struct icmp6hdr *hdr;
int type;
+ if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb) &&
+ skb->sp->xvec[skb->sp->len - 1]->props.flags & XFRM_STATE_ICMP) {
+ int nh;
+
+ if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(*orig_hdr)))
+ goto drop_no_count;
+
+ nh = skb_network_offset(skb);
+ skb_set_network_header(skb, sizeof(*hdr));
+
+ if (!xfrm6_policy_check_reverse(NULL, XFRM_POLICY_IN, skb))
+ goto drop_no_count;
+
+ skb_set_network_header(skb, nh);
+ }
+
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS);
saddr = &ipv6_hdr(skb)->saddr;
@@ -632,8 +684,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
}
}
- if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
- goto discard_it;
+ __skb_pull(skb, sizeof(*hdr));
hdr = icmp6_hdr(skb);
@@ -719,6 +770,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
discard_it:
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS);
+drop_no_count:
kfree_skb(skb);
return 0;
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 55fd8b7..b04d88c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1469,11 +1469,13 @@ restart:
goto dropdst;
}
+ err = -ENOENT;
+
if (!policy) {
/* To accelerate a bit... */
if ((dst_orig->flags & DST_NOXFRM) ||
!xfrm_policy_count[XFRM_POLICY_OUT])
- return 0;
+ goto nopol;
policy = flow_cache_lookup(fl, dst_orig->ops->family,
dir, xfrm_policy_lookup);
@@ -1483,14 +1485,18 @@ restart:
}
if (!policy)
- return 0;
+ goto nopol;
family = dst_orig->ops->family;
- policy->curlft.use_time = get_seconds();
pols[0] = policy;
npols ++;
xfrm_nr += pols[0]->xfrm_nr;
+ if ((flags & XFRM_LOOKUP_ICMP) && !(policy->flags & XFRM_POLICY_ICMP))
+ goto error;
+
+ policy->curlft.use_time = get_seconds();
+
switch (policy->action) {
default:
case XFRM_POLICY_BLOCK:
@@ -1649,6 +1655,11 @@ dropdst:
dst_release(dst_orig);
*dst_p = NULL;
return err;
+
+nopol:
+ if (flags & XFRM_LOOKUP_ICMP)
+ goto dropdst;
+ return 0;
}
EXPORT_SYMBOL(__xfrm_lookup);
^ permalink raw reply related
* [PATCH 2/3] [IPSEC]: Added xfrm_decode_session_reverse and xfrmX_policy_check_reverse
From: Herbert Xu @ 2007-12-12 1:58 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20071212012552.GA20618@gondor.apana.org.au>
[IPSEC]: Added xfrm_decode_session_reverse and xfrmX_policy_check_reverse
RFC 4301 requires us to relookup ICMP traffic that does not match any
policies using the reverse of its payload. This patch adds the functions
xfrm_decode_session_reverse and xfrmX_policy_check_reverse so we can get
the reverse flow to perform such a lookup.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/xfrm.h | 1
include/net/xfrm.h | 63 ++++++++++++++++++++++++++++++++++++++++++++----
net/ipv4/xfrm4_policy.c | 10 +++----
net/ipv6/xfrm6_policy.c | 10 +++----
net/xfrm/xfrm_policy.c | 17 ++++++++----
5 files changed, 80 insertions(+), 21 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index b58adc5..c0e41e0 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -114,6 +114,7 @@ enum
XFRM_POLICY_IN = 0,
XFRM_POLICY_OUT = 1,
XFRM_POLICY_FWD = 2,
+ XFRM_POLICY_MASK = 3,
XFRM_POLICY_MAX = 3
};
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0c380d9..32b99e2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -239,7 +239,8 @@ struct xfrm_policy_afinfo {
int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);
struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
void (*decode_session)(struct sk_buff *skb,
- struct flowi *fl);
+ struct flowi *fl,
+ int reverse);
int (*get_tos)(struct flowi *fl);
int (*fill_dst)(struct xfrm_dst *xdst,
struct net_device *dev);
@@ -844,14 +845,23 @@ xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short
#ifdef CONFIG_XFRM
extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
-static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+static inline int __xfrm_policy_check2(struct sock *sk, int dir,
+ struct sk_buff *skb,
+ unsigned int family, int reverse)
{
+ int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0);
+
if (sk && sk->sk_policy[XFRM_POLICY_IN])
- return __xfrm_policy_check(sk, dir, skb, family);
+ return __xfrm_policy_check(sk, ndir, skb, family);
return (!xfrm_policy_count[dir] && !skb->sp) ||
(skb->dst->flags & DST_NOPOLICY) ||
- __xfrm_policy_check(sk, dir, skb, family);
+ __xfrm_policy_check(sk, ndir, skb, family);
+}
+
+static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+{
+ return __xfrm_policy_check2(sk, dir, skb, family, 0);
}
static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
@@ -864,7 +874,34 @@ static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *s
return xfrm_policy_check(sk, dir, skb, AF_INET6);
}
-extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
+static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return __xfrm_policy_check2(sk, dir, skb, AF_INET, 1);
+}
+
+static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1);
+}
+
+extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family, int reverse);
+
+static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family)
+{
+ return __xfrm_decode_session(skb, fl, family, 0);
+}
+
+static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
+ struct flowi *fl,
+ unsigned int family)
+{
+ return __xfrm_decode_session(skb, fl, family, 1);
+}
+
extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
@@ -925,6 +962,22 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk
{
return 1;
}
+static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
+ struct flowi *fl,
+ unsigned int family)
+{
+ return -ENOSYS;
+}
+static inline int xfrm4_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return 1;
+}
+static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
+ struct sk_buff *skb)
+{
+ return 1;
+}
#endif
static __inline__
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 10b72d1..5ccae3a 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -115,7 +115,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
}
static void
-_decode_session4(struct sk_buff *skb, struct flowi *fl)
+_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
{
struct iphdr *iph = ip_hdr(skb);
u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
@@ -131,8 +131,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ports = (__be16 *)xprth;
- fl->fl_ip_sport = ports[0];
- fl->fl_ip_dport = ports[1];
+ fl->fl_ip_sport = ports[!!reverse];
+ fl->fl_ip_dport = ports[!reverse];
}
break;
@@ -174,8 +174,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
}
}
fl->proto = iph->protocol;
- fl->fl4_dst = iph->daddr;
- fl->fl4_src = iph->saddr;
+ fl->fl4_dst = reverse ? iph->saddr : iph->daddr;
+ fl->fl4_src = reverse ? iph->daddr : iph->saddr;
fl->fl4_tos = iph->tos;
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 181cf91..d26b7dc 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -123,7 +123,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
}
static inline void
-_decode_session6(struct sk_buff *skb, struct flowi *fl)
+_decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
{
u16 offset = skb_network_header_len(skb);
struct ipv6hdr *hdr = ipv6_hdr(skb);
@@ -132,8 +132,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
u8 nexthdr = nh[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi));
- ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
- ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
+ ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
+ ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
nh = skb_network_header(skb);
@@ -156,8 +156,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
__be16 *ports = (__be16 *)exthdr;
- fl->fl_ip_sport = ports[0];
- fl->fl_ip_dport = ports[1];
+ fl->fl_ip_sport = ports[!!reverse];
+ fl->fl_ip_dport = ports[!reverse];
}
fl->proto = nexthdr;
return;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 265c679..55fd8b7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1732,8 +1732,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
return start;
}
-int
-xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
+int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family, int reverse)
{
struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
int err;
@@ -1741,12 +1741,12 @@ xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family
if (unlikely(afinfo == NULL))
return -EAFNOSUPPORT;
- afinfo->decode_session(skb, fl);
+ afinfo->decode_session(skb, fl, reverse);
err = security_xfrm_decode_session(skb, &fl->secid);
xfrm_policy_put_afinfo(afinfo);
return err;
}
-EXPORT_SYMBOL(xfrm_decode_session);
+EXPORT_SYMBOL(__xfrm_decode_session);
static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp)
{
@@ -1768,11 +1768,16 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
int npols = 0;
int xfrm_nr;
int pi;
+ int reverse;
struct flowi fl;
- u8 fl_dir = policy_to_flow_dir(dir);
+ u8 fl_dir;
int xerr_idx = -1;
- if (xfrm_decode_session(skb, &fl, family) < 0)
+ reverse = dir & ~XFRM_POLICY_MASK;
+ dir &= XFRM_POLICY_MASK;
+ fl_dir = policy_to_flow_dir(dir);
+
+ if (__xfrm_decode_session(skb, &fl, family, reverse) < 0)
return 0;
nf_nat_decode_session(skb, &fl, family);
^ permalink raw reply related
* [PATCH] HDLC driver: use unregister_netdev instead of unregister_netdevice
From: Wang Chen @ 2007-12-12 2:35 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Krzysztof Halasa, netdev, David S. Miller
[PATCH] HDLC driver: use unregister_netdev instead of unregister_netdevice
Since the caller and the upper caller doesn't hod the rtnl semaphore.
We should use unregister_netdev instead of unregister_netdevice.
Signed-off-by: Wang Chen <wangchen@cn.fujitsu.com>
---
hdlc_fr.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
--- linux-2.6.24.rc5.org/drivers/net/wan/hdlc_fr.c 2007-10-10 04:31:38.000000000 +0800
+++ linux-2.6.24.rc5/drivers/net/wan/hdlc_fr.c 2007-12-12 10:25:13.000000000 +0800
@@ -1177,7 +1177,7 @@ static int fr_del_pvc(hdlc_device *hdlc,
if (dev->flags & IFF_UP)
return -EBUSY; /* PVC in use */
- unregister_netdevice(dev); /* the destructor will free_netdev(dev) */
+ unregister_netdev(dev); /* the destructor will free_netdev(dev) */
*get_dev_p(pvc, type) = NULL;
if (!pvc_is_used(pvc)) {
@@ -1202,10 +1202,10 @@ static void fr_destroy(struct net_device
pvc_device *next = pvc->next;
/* destructors will free_netdev() main and ether */
if (pvc->main)
- unregister_netdevice(pvc->main);
+ unregister_netdev(pvc->main);
if (pvc->ether)
- unregister_netdevice(pvc->ether);
+ unregister_netdev(pvc->ether);
kfree(pvc);
pvc = next;
^ permalink raw reply
* [PATCH] [IPSEC]: Add populate from packet (PFP) support
From: Tyler Hicks @ 2007-12-12 3:23 UTC (permalink / raw)
To: linux netdev, David Miller; +Cc: Herbert Xu, Joy Latten
RFC 4301 requires us to associate each SPD entry with a set of flags to
determine how to assign the selector values when creating a new SAD entry.
Each selector in the new xfrm_state can either be assigned using the
corresponding selector in the xfrm_policy or with the corresponding value
in the flowi. Prior to this patch, the fields in the flowi were always
used.
Signed-off-by: Tyler Hicks <tyhicks@ou.edu>
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index b58adc5..ce6b1b5 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -362,6 +362,11 @@ struct xfrm_userpolicy_info {
#define XFRM_POLICY_BLOCK 1
__u8 flags;
#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
+#define XFRM_POLICY_PFP_SADDR 2
+#define XFRM_POLICY_PFP_DADDR 4
+#define XFRM_POLICY_PFP_PROTO 8
+#define XFRM_POLICY_PFP_SPORT 16
+#define XFRM_POLICY_PFP_DPORT 32
__u8 share;
};
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 58dfa82..5a039a2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -261,9 +261,12 @@ struct xfrm_state_afinfo {
struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
int (*init_flags)(struct xfrm_state *x);
- void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
+ void (*init_tempsel)(struct xfrm_state *x,
+ struct flowi *fl,
struct xfrm_tmpl *tmpl,
- xfrm_address_t *daddr, xfrm_address_t *saddr);
+ struct xfrm_policy *pol,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
int (*output)(struct sk_buff *skb);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 13d54a1..0fb1092 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -23,18 +23,39 @@ static int xfrm4_init_flags(struct xfrm_state *x)
static void
__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr)
{
- x->sel.daddr.a4 = fl->fl4_dst;
- x->sel.saddr.a4 = fl->fl4_src;
- x->sel.dport = xfrm_flowi_dport(fl);
- x->sel.dport_mask = htons(0xffff);
- x->sel.sport = xfrm_flowi_sport(fl);
- x->sel.sport_mask = htons(0xffff);
- x->sel.prefixlen_d = 32;
- x->sel.prefixlen_s = 32;
- x->sel.proto = fl->proto;
+ if (pol->flags & XFRM_POLICY_PFP_DADDR) {
+ x->sel.daddr.a4 = fl->fl4_dst;
+ x->sel.prefixlen_d = 32;
+ } else {
+ x->sel.daddr.a4 = pol->selector.daddr.a4;
+ x->sel.prefixlen_d = pol->selector.prefixlen_d;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SADDR) {
+ x->sel.saddr.a4 = fl->fl4_src;
+ x->sel.prefixlen_s = 32;
+ } else {
+ x->sel.saddr.a4 = pol->selector.saddr.a4;
+ x->sel.prefixlen_s = pol->selector.prefixlen_s;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_DPORT) {
+ x->sel.dport = xfrm_flowi_dport(fl);
+ x->sel.dport_mask = htons(0xffff);
+ } else {
+ x->sel.dport = pol->selector.dport;
+ x->sel.dport_mask = pol->selector.dport_mask;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SPORT) {
+ x->sel.sport = xfrm_flowi_sport(fl);
+ x->sel.sport_mask = htons(0xffff);
+ } else {
+ x->sel.sport = pol->selector.sport;
+ x->sel.sport = pol->selector.sport_mask;
+ }
+ x->sel.proto = pol->flags & XFRM_POLICY_PFP_PROTO ?
+ fl->proto : pol->selector.proto;
x->sel.ifindex = fl->oif;
x->id = tmpl->id;
if (x->id.daddr.a4 == 0)
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index b392bee..213d92d 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -21,20 +21,43 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo;
static void
__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr)
{
/* Initialize temporary selector matching only
* to current session. */
- ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
- ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
- x->sel.dport = xfrm_flowi_dport(fl);
- x->sel.dport_mask = htons(0xffff);
- x->sel.sport = xfrm_flowi_sport(fl);
- x->sel.sport_mask = htons(0xffff);
- x->sel.prefixlen_d = 128;
- x->sel.prefixlen_s = 128;
- x->sel.proto = fl->proto;
+ if (pol->flags & XFRM_POLICY_PFP_DADDR) {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
+ x->sel.prefixlen_d = 128;
+ } else {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.daddr,
+ (struct in6_addr *)&pol->selector.daddr);
+ x->sel.prefixlen_d = pol->selector.prefixlen_d;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SADDR) {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
+ x->sel.prefixlen_s = 128;
+ } else {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.saddr,
+ (struct in6_addr *)&pol->selector.saddr);
+ x->sel.prefixlen_s = pol->selector.prefixlen_s;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_DPORT) {
+ x->sel.dport = xfrm_flowi_dport(fl);
+ x->sel.dport_mask = htons(0xffff);
+ } else {
+ x->sel.dport = pol->selector.dport;
+ x->sel.dport_mask = pol->selector.dport_mask;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SPORT) {
+ x->sel.sport = xfrm_flowi_sport(fl);
+ x->sel.sport_mask = htons(0xffff);
+ } else {
+ x->sel.sport = pol->selector.sport;
+ x->sel.sport_mask = pol->selector.sport_mask;
+ }
+ x->sel.proto = pol->flags & XFRM_POLICY_PFP_PROTO ?
+ fl->proto : pol->selector.proto;
x->sel.ifindex = fl->oif;
x->id = tmpl->id;
if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 224b44e..2dab50e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -654,14 +654,14 @@ EXPORT_SYMBOL(xfrm_sad_getinfo);
static int
xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr,
unsigned short family)
{
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
if (!afinfo)
return -1;
- afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
+ afinfo->init_tempsel(x, fl, tmpl, pol, daddr, saddr);
xfrm_state_put_afinfo(afinfo);
return 0;
}
@@ -824,7 +824,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
}
/* Initialize temporary selector matching only
* to current session. */
- xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
+ xfrm_init_tempsel(x, fl, tmpl, pol, daddr, saddr, family);
error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
if (error) {
--
1.5.3.4
^ permalink raw reply related
* [PATCH 7/7] [NETDEV]: myri10ge Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: jgarzik, help
[NETDEV]: myri10ge Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/myri10ge/myri10ge.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 8def865..57311ed 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1242,6 +1242,8 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
if (work_done < budget || !netif_running(netdev)) {
netif_rx_complete(netdev, napi);
put_be32(htonl(3), mgp->irq_claim);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
}
---
^ permalink raw reply related
* [PATCH 6/7] : tehuti Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: jgarzik, baum, andy
[NETDEV]: tehuti Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/tehuti.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 21230c9..955e749 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -305,6 +305,8 @@ static int bdx_poll(struct napi_struct *napi, int budget)
netif_rx_complete(dev, napi);
bdx_enable_interrupts(priv);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
}
---
^ permalink raw reply related
* [PATCH 5/7] : e100 Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: 'Kok, Auke', jesse.brandeburg, jgarzik
[NETDEV]: e100 Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/e100.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e1c8a0d..7cb4ed0 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2000,6 +2000,8 @@ static int e100_poll(struct napi_struct *napi, int budget)
if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
netif_rx_complete(netdev, napi);
e100_enable_irq(nic);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
---
^ permalink raw reply related
* [PATCH 4/7] : ixgbe Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: 'Kok, Auke', jesse.brandeburg, jgarzik
[NETDEV]: ixgbe Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/ixgbe/ixgbe_main.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 00bc525..0b3ae8f 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -583,6 +583,8 @@ quit_polling:
if (!test_bit(__IXGBE_DOWN, &adapter->state))
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
rxr->eims_value);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
@@ -1485,6 +1487,8 @@ static int ixgbe_clean(struct napi_struct *napi, int budget)
quit_polling:
netif_rx_complete(netdev, napi);
ixgbe_irq_enable(adapter);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
---
^ permalink raw reply related
* [PATCH 3/7] : ixgb Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: 'Kok, Auke', jesse.brandeburg, jgarzik
[NETDEV]: ixgb Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/ixgb/ixgb_main.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 3021234..afe95d1 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1785,6 +1785,8 @@ ixgb_clean(struct napi_struct *napi, int budget)
if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
netif_rx_complete(netdev, napi);
ixgb_irq_enable(adapter);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
---
^ permalink raw reply related
* [PATCH 2/7] : e1000e Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: 'Kok, Auke', jesse.brandeburg, jgarzik
[NETDEV]: e1000e Fix possible causing oops of net_rx_action
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/e1000e/netdev.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 4fd2e23..8e4861a 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1412,6 +1412,8 @@ quit_polling:
e1000_set_itr(adapter);
netif_rx_complete(poll_dev, napi);
e1000_irq_enable(adapter);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
---
^ permalink raw reply related
* [PATCH 1/7] : e1000 Fix possible causing oops of net_rx_action
From: Joonwoo Park @ 2007-12-12 4:01 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: 'Kok, Auke', jesse.brandeburg, jgarzik
[NETDEV]: e1000 Fix possible causing oops of net_rx_action
returning work_done == weight as true after calling netif_rx_complete will cause oops in net_rx_action.
Thanks
Joonwoo
Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
---
drivers/net/e1000/e1000_main.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 4f37506..4dd61e3 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3949,6 +3949,8 @@ quit_polling:
e1000_set_itr(adapter);
netif_rx_complete(poll_dev, napi);
e1000_irq_enable(adapter);
+ if (unlikely(work_done == napi->weight))
+ return work_done - 1;
}
return work_done;
---
^ permalink raw reply related
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