* Re: [PATCH 2/2] vhost_net: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-08-13 14:41 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: virtualization, netdev, Ira W. Snyder, linux-kernel, kvm
In-Reply-To: <200908131548.35199.arnd@arndb.de>
On Thu, Aug 13, 2009 at 03:48:35PM +0200, Arnd Bergmann wrote:
> On Thursday 13 August 2009, Arnd Bergmann wrote:
> > Unfortunately, this also implies that you could no longer simply use the
> > packet socket interface as you do currently, as I realized only now.
> > This obviously has a significant impact on your user space interface.
>
> Also, if we do the copy in the transport, it definitely means that we
> can't get to zero-copy RX/TX from guest space any more. The current
> vhost_net driver doesn't do that yet, but could be extended in the
> same way that I'm hoping to do it for macvtap.
>
> Arnd <><
The best way to do this IMO would be to add zero copy support to raw
sockets, vhost will then get it basically for free.
--
MST
^ permalink raw reply
* Re: [PATCH 2/2] vhost_net: a kernel-level virtio server
From: Arnd Bergmann @ 2009-08-13 14:53 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: virtualization, netdev, Ira W. Snyder, linux-kernel, kvm
In-Reply-To: <20090813144129.GB5080@redhat.com>
On Thursday 13 August 2009, Michael S. Tsirkin wrote:
> The best way to do this IMO would be to add zero copy support to raw
> sockets, vhost will then get it basically for free.
Yes, that would be nice. I wonder if that could lead to security
problems on TX though. I guess It will only bring significant performance
improvements if we leave the data writable in the user space or guest
during the operation. If the user finds the right timing, it could
modify the frame headers after they have been checked using netfilter,
or while the frames are being consumed in the kernel (e.g. an NFS
server running in a guest).
Ardn <><
^ permalink raw reply
* Re: [PATCH 2/2] vhost_net: a kernel-level virtio server
From: Arnd Bergmann @ 2009-08-13 14:58 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: virtualization, Ira W. Snyder, netdev, kvm, linux-kernel
In-Reply-To: <20090813143922.GA5080@redhat.com>
On Thursday 13 August 2009, Michael S. Tsirkin wrote:
> > Right now, the number of copy operations in your code is the same.
> > You are doing the copy a little bit later in skb_copy_datagram_iovec(),
> > which is indeed a very nice hack. Changing to a virtqueue based method
> > would imply that the host needs to add each skb_frag_t to its outbound
> > virtqueue, which then gets copied into the guests inbound virtqueue.
>
> Which is a lot more code than just calling skb_copy_datagram_iovec.
Well, I don't see this part as much of a problem, because the code
already exists in virtio_net. If we really wanted to go down that road,
just using virtio_net would solve the problem of frame handling
entirely, but create new problems elsewhere, as we have mentioned.
Arnd <><
^ permalink raw reply
* Re: [PATCH 0/3] net: Add ftracer to help optimize process scheduling based on incomming frame allocations (v3)
From: Neil Horman @ 2009-08-13 14:59 UTC (permalink / raw)
To: netdev; +Cc: davem, rostedt
In-Reply-To: <20090807202130.GA26677@hmsreliant.think-freely.org>
Hey all-
I put out an RFC about this awhile ago and didn't get any loud screams,
so I've gone ahead and implemented it
Currently, our network infrastructure allows net device drivers to
allocate skbs based on the the numa node the device itself is local to. This of
course cuts down on cross numa chatter when the device is DMA-ing network
traffic to the driver. Unfortuantely no such corresponding infrastrucuture
exists at the process level. The scheduler has no insight into the numa
locality of incomming data packets for a given process (and arguably it
shouldn't), and so there is every chance that a process will run on a different
numa node than the packets that its receiving lives on, creating cross numa node
traffic.
This patch aims to provide userspace with the opportunity to optimize
that scheduling. It consists of a tracepoint and an ftrace module which exports
a history of the packets each process receives, along with the numa node each
packet was received on, as well as the numa node the process was running on when
it copied the buffer to user space. With this information, exported via the
ftrace infrastructure to user space, a sysadim can identify high prirority
processes, and optimize their scheduling so that they are more likely to run on
the same node that they are primarily receiving data on, thereby cutting down
cross numa node traffic.
Tested by me, working well, applies against the head of the net-next tree
Version 3 change notes:
Respun on davems request to apply to the head of the net-next tree. No other
changes
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [PATCH 2/2] vhost_net: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-08-13 15:03 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: virtualization, Ira W. Snyder, netdev, kvm, linux-kernel
In-Reply-To: <200908131658.06522.arnd@arndb.de>
On Thu, Aug 13, 2009 at 04:58:06PM +0200, Arnd Bergmann wrote:
> On Thursday 13 August 2009, Michael S. Tsirkin wrote:
> > > Right now, the number of copy operations in your code is the same.
> > > You are doing the copy a little bit later in skb_copy_datagram_iovec(),
> > > which is indeed a very nice hack. Changing to a virtqueue based method
> > > would imply that the host needs to add each skb_frag_t to its outbound
> > > virtqueue, which then gets copied into the guests inbound virtqueue.
> >
> > Which is a lot more code than just calling skb_copy_datagram_iovec.
>
> Well, I don't see this part as much of a problem, because the code
> already exists in virtio_net.
I am talking about the copying done in low level transport, here.
> If we really wanted to go down that road,
> just using virtio_net would solve the problem of frame handling
> entirely, but create new problems elsewhere, as we have mentioned.
>
> Arnd <><
^ permalink raw reply
* [PATCH net-next-2.6] bonding: introduce primary_lazy option
From: Jiri Pirko @ 2009-08-13 15:05 UTC (permalink / raw)
To: davem; +Cc: fubar, bonding-devel, netdev
In some cases there is not desirable to switch back to primary interface when
it's link recovers and rather stay wiith currently active one. We need to avoid
packetloss as much as we can in some cases. This is solved by introducing
primary_lazy option. Note that enslaved primary slave is set as current
active no matter what.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index d5181ce..f1b82af 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -614,6 +614,15 @@ primary
The primary option is only valid for active-backup mode.
+primary_lazy
+
+ Specifies the behaviour of the primary slave in case of
+ it's link recovery has been detected. By default (value 0) the
+ primary slave is set as active slave immediately after the link
+ recovery. If the value is 1 then current active slave doesn't
+ change as long as it's link status doesn't change. This prevents
+ the bonding device from flip-flopping.
+
updelay
Specifies the time, in milliseconds, to wait before enabling a
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3bf0cc6..00fbb9d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -94,6 +94,7 @@ static int downdelay;
static int use_carrier = 1;
static char *mode;
static char *primary;
+static int primary_lazy;
static char *lacp_rate;
static char *ad_select;
static char *xmit_hash_policy;
@@ -126,6 +127,9 @@ MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
"6 for balance-alb");
module_param(primary, charp, 0);
MODULE_PARM_DESC(primary, "Primary network device to use");
+module_param(primary_lazy, int, 0);
+MODULE_PARM_DESC(primary_lazy, "Do not set primary slave active once it comes up; "
+ "0 for off (default), 1 for on");
module_param(lacp_rate, charp, 0);
MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
"(slow/fast)");
@@ -1067,7 +1071,6 @@ out:
}
-
/**
* find_best_interface - select the best available slave to be the active one
* @bond: our bonding struct
@@ -1097,9 +1100,11 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
* and primary_slave that may be up and able to arp
*/
if ((bond->primary_slave) &&
- (!bond->params.arp_interval) &&
- (IS_UP(bond->primary_slave->dev))) {
+ (IS_UP(bond->primary_slave->dev)) &&
+ (!(bond->params.primary_lazy && old_active &&
+ (IS_UP(old_active->dev))) || bond->force_primary)) {
new_active = bond->primary_slave;
+ bond->force_primary = false;
}
/* remember where to stop iterating over the slaves */
@@ -1674,8 +1679,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */
- if (strcmp(bond->params.primary, new_slave->dev->name) == 0)
+ if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
bond->primary_slave = new_slave;
+ bond->force_primary = true;
+ }
}
write_lock_bh(&bond->curr_slave_lock);
@@ -2929,7 +2936,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
*/
if (bond->primary_slave &&
(bond->primary_slave != bond->curr_active_slave) &&
- (bond->primary_slave->link == BOND_LINK_UP))
+ (bond->primary_slave->link == BOND_LINK_UP) &&
+ !(bond->params.primary_lazy && bond->curr_active_slave &&
+ bond->curr_active_slave->link == BOND_LINK_UP))
commit++;
read_unlock(&bond->curr_slave_lock);
@@ -3035,7 +3044,9 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
*/
if (bond->primary_slave &&
(bond->primary_slave != bond->curr_active_slave) &&
- (bond->primary_slave->link == BOND_LINK_UP)) {
+ (bond->primary_slave->link == BOND_LINK_UP) &&
+ !(bond->params.primary_lazy && bond->curr_active_slave &&
+ bond->curr_active_slave->link == BOND_LINK_UP)) {
write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, bond->primary_slave);
write_unlock_bh(&bond->curr_slave_lock);
@@ -4987,6 +4998,17 @@ static int bond_check_params(struct bond_params *params)
primary = NULL;
}
+ if (primary) {
+ if ((primary_lazy != 0) && (primary_lazy != 1)) {
+ pr_warning(DRV_NAME
+ ": Warning: primary_lazy module parameter "
+ "(%d), not of valid value (0/1), so it was "
+ "set to 0\n",
+ primary_lazy);
+ primary_lazy = 1;
+ }
+ }
+
if (fail_over_mac) {
fail_over_mac_value = bond_parse_parm(fail_over_mac,
fail_over_mac_tbl);
@@ -5018,6 +5040,7 @@ static int bond_check_params(struct bond_params *params)
params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast;
params->primary[0] = 0;
+ params->primary_lazy = primary_lazy;
params->fail_over_mac = fail_over_mac_value;
if (primary) {
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 55bf34f..573fe82 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1209,6 +1209,59 @@ static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
bonding_show_primary, bonding_store_primary);
/*
+ * Show and set the primary_lazy flag.
+ */
+static ssize_t bonding_show_primary_lazy(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.primary_lazy);
+}
+
+static ssize_t bonding_store_primary_lazy(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ pr_err(DRV_NAME
+ ": %s: no primary_lazy value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.primary_lazy = new_value;
+ pr_info(DRV_NAME ": %s: Setting primary_lazy to %d.\n",
+ bond->dev->name, new_value);
+ if (!bond->params.primary_lazy) {
+ bond->force_primary = true;
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+ bond_select_active_slave(bond);
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+ }
+ } else {
+ pr_info(DRV_NAME
+ ": %s: Ignoring invalid primary_lazy value %d.\n",
+ bond->dev->name, new_value);
+ }
+out:
+ rtnl_unlock();
+ return count;
+}
+static DEVICE_ATTR(primary_lazy, S_IRUGO | S_IWUSR,
+ bonding_show_primary_lazy, bonding_store_primary_lazy);
+
+/*
* Show and set the use_carrier flag.
*/
static ssize_t bonding_show_carrier(struct device *d,
@@ -1497,6 +1550,7 @@ static struct attribute *per_bond_attrs[] = {
&dev_attr_num_unsol_na.attr,
&dev_attr_miimon.attr,
&dev_attr_primary.attr,
+ &dev_attr_primary_lazy.attr,
&dev_attr_use_carrier.attr,
&dev_attr_active_slave.attr,
&dev_attr_mii_status.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 6290a50..ac35c6c 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -131,6 +131,7 @@ struct bond_params {
int lacp_fast;
int ad_select;
char primary[IFNAMSIZ];
+ int primary_lazy;
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
};
@@ -190,6 +191,7 @@ struct bonding {
struct slave *curr_active_slave;
struct slave *current_arp_slave;
struct slave *primary_slave;
+ bool force_primary;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
rwlock_t lock;
rwlock_t curr_slave_lock;
^ permalink raw reply related
* Re: [RFC] ipv6: Change %pI6 format to output compacted addresses?
From: Joe Perches @ 2009-08-13 15:07 UTC (permalink / raw)
To: Jens Rosenboom; +Cc: Brian Haley, Linux Network Developers
In-Reply-To: <1250171543.6641.78.camel@fnki-nb00130>
On Thu, 2009-08-13 at 15:52 +0200, Jens Rosenboom wrote:
> On Thu, 2009-08-13 at 03:39 -0700, Joe Perches wrote:
> > You'll need to invent a new %p qualifier type to allow
> > compressed representation. Your patch will change current uses
> > with seq_<foo> output in net, which could break userspace.
>
> Would it be possible to transform this to using %pi6, as most of teh
> seq_* stuff already does?
No.
There are applications that depend on the
current output representation.
I think it should be done with something like "%pi6c"
rather than using another %p character because there
are a limited number of single characters available.
^ permalink raw reply
* Re: [RFC] ipv6: Change %pI6 format to output compacted addresses?
From: Chuck Lever @ 2009-08-13 15:14 UTC (permalink / raw)
To: Jens Rosenboom; +Cc: Brian Haley, Linux Network Developers
In-Reply-To: <1250174390.6641.89.camel@fnki-nb00130>
On Aug 13, 2009, at 10:39 AM, Jens Rosenboom wrote:
> On Wed, 2009-08-12 at 21:33 -0400, Brian Haley wrote:
>> Jens Rosenboom wrote:
>>> Currently the output looks like
>>> 2001:0db8:0000:0000:0000:0000:0000:0001
>>> which might be compacted to 2001:db8::1. The code to do this could
>>> be
>>> adapted from inet_ntop in glibc, which would add about 80 lines to
>>> lib/vsprintf.c. How do you guys value the tradeoff between more
>>> readable
>>> logging and increased kernel size?
>>>
>>> This was already mentioned in
>>> http://kerneltrap.org/mailarchive/linux-netdev/2008/11/25/4231684
>>> but
>>> noone seems to have taken up on it.
>>
>> I think if any changes are made they should try and follow:
>>
>> http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
>>
>> For one thing, the code today doesn't print things like the v4-mapped
>> address correctly.
>>
>> Anyways, can you try this patch, it's less than 40 new lines :)
>> It might be good enough, but could probably use some help.
>
> For a start, it didn't even compile. ;-) Here is a new version that
> also
> fixes
>
> - Leave %pi6 alone
> - Don't compress a single :0:
> - Do output 0
>
> The results and also the remaining issues can be seen with the
> attached
> test program, that also exposes a bug in glibc for v4-mapped addresses
> from 0/16.
>
> To fully conform to the cited draft, we would still have to implement
> v4-mapped and also check whether a second run of zeros would be longer
> than the first one, although the draft also suggests that operators
> should avoid using this kind of addresses, so maybe this second issue
> can be neglected.
If it is at all helpful, I recently proposed adding rpc_ntop() to
sunrpc.ko to provide proper IPv6 shorthanding without changing %p[iI]6
at all. The patch was rejected, but there may be something here you
can use. The version of rpc_ntop() accepted for 2.6.32 does not
provide shorthanding.
See the archived mail at http://www.spinics.net/lists/linux-nfs/msg08363.html
If you get proper IPv6 shorthanding into the kernel, RPC is one more
consumer for you.
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 756ccaf..5710c65 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -652,13 +652,53 @@ static char *ip6_addr_string(char *buf, char
> *end,
> u8 *addr,
> {
> char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing
> zero */
> char *p = ip6_addr;
> - int i;
> + int i, needcolon = 0, printhi;
> + u16 *addr16 = (u16 *)addr;
> + enum { DC_START, DC_MIDDLE, DC_DONE } colon = DC_START;
> +
> + /* omit leading zeros and shorten using "::" */
>
> - for (i = 0; i < 8; i++) {
> - p = pack_hex_byte(p, addr[2 * i]);
> - p = pack_hex_byte(p, addr[2 * i + 1]);
> - if (!(spec.flags & SPECIAL) && i != 7)
> + if (!(spec.flags & SPECIAL)) {
> + for (i = 0; i < 8; i++) {
> + if (addr16[i] == 0 && addr16[i+1] == 0 && colon == DC_START) {
> + colon = DC_MIDDLE;
> + continue;
> + }
> + if (colon == DC_MIDDLE) {
> + if (addr16[i] == 0)
> + continue;
> + colon = DC_DONE;
> + *p++ = ':';
> + *p++ = ':';
> + } else if (needcolon)
> + *p++ = ':';
> + printhi = 0;
> + if (addr[2 * i]) {
> + if (addr[2 * i] > 0x0f)
> + p = pack_hex_byte(p, addr[2 * i]);
> + else
> + *p++ = hex_asc_lo(addr[2 * i]);
> + printhi++;
> + }
> + /*
> + * If we printed the high-order bits we must print the
> + * low-order ones, even if they're all zeros.
> + */
> + if (printhi || addr[2 * i + 1] > 0x0f)
> + p = pack_hex_byte(p, addr[2 * i + 1]);
> + else
> + *p++ = hex_asc_lo(addr[2 * i + 1]);
> + needcolon++;
> + }
> + if (colon == DC_MIDDLE) {
> *p++ = ':';
> + *p++ = ':';
> + }
> + } else {
> + for (i = 0; i < 8; i++) {
> + p = pack_hex_byte(p, addr[2 * i]);
> + p = pack_hex_byte(p, addr[2 * i + 1]);
> + }
> }
> *p = '\0';
> spec.flags &= ~SPECIAL;
>
> <test.c>
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
^ permalink raw reply
* Re: [PATCH 1/3] net: skb ftracer - add tracepoint to skb_copy_datagram_iovec (v3)
From: Neil Horman @ 2009-08-13 15:19 UTC (permalink / raw)
To: netdev; +Cc: davem, rostedt
In-Reply-To: <20090813145917.GA16521@hmsreliant.think-freely.org>
skb allocation / cosumption tracer - Add consumption tracepoint
This patch adds a tracepoint to skb_copy_datagram_iovec, which is called each
time a userspace process copies a frame from a socket receive queue to a user
space buffer. It allows us to hook in and examine each sk_buff that the system
receives on a per-socket bases, and can be use to compile a list of which skb's
were received by which processes.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
include/trace/events/skb.h | 20 ++++++++++++++++++++
net/core/datagram.c | 3 +++
2 files changed, 23 insertions(+)
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index e499863..4b2be6d 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -5,6 +5,7 @@
#define _TRACE_SKB_H
#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <linux/tracepoint.h>
/*
@@ -34,6 +35,25 @@ TRACE_EVENT(kfree_skb,
__entry->skbaddr, __entry->protocol, __entry->location)
);
+TRACE_EVENT(skb_copy_datagram_iovec,
+
+ TP_PROTO(const struct sk_buff *skb, int len),
+
+ TP_ARGS(skb, len),
+
+ TP_STRUCT__entry(
+ __field( const void *, skbaddr )
+ __field( int, len )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->len = len;
+ ),
+
+ TP_printk("skbaddr=%p len=%d", __entry->skbaddr, __entry->len)
+);
+
#endif /* _TRACE_SKB_H */
/* This part must be outside protection */
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b0fe692..1c6cf3a 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -55,6 +55,7 @@
#include <net/checksum.h>
#include <net/sock.h>
#include <net/tcp_states.h>
+#include <trace/events/skb.h>
/*
* Is a socket 'connection oriented' ?
@@ -284,6 +285,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
int i, copy = start - offset;
struct sk_buff *frag_iter;
+ trace_skb_copy_datagram_iovec(skb, len);
+
/* Copy header. */
if (copy > 0) {
if (copy > len)
^ permalink raw reply related
* Re: [PATCH 2/3] net: skb ftracer - Add config option to enable new ftracer (v3)
From: Neil Horman @ 2009-08-13 15:20 UTC (permalink / raw)
To: netdev; +Cc: davem, rostedt
In-Reply-To: <20090813145917.GA16521@hmsreliant.think-freely.org>
skb allocation / consumption corelator - Add config option
This patch adds a Kconfig option to enable the addtition of the skb source
tracer.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Kconfig | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 019f380..dcb263d 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -234,6 +234,16 @@ config BOOT_TRACER
You must pass in initcall_debug and ftrace=initcall to the kernel
command line to enable this on bootup.
+config SKB_SOURCES_TRACER
+ bool "Trace skb source information
+ select GENERIC_TRACER
+ help
+ This tracer helps developers/sysadmins correlate skb allocation and
+ consumption. The idea being that some processes will primarily consume data
+ that was allocated on certain numa nodes. By being able to visualize which
+ nodes the data was allocated on, a sysadmin or developer can optimize the
+ scheduling of those processes to cut back on cross node chatter.
+
config TRACE_BRANCH_PROFILING
bool
select GENERIC_TRACER
^ permalink raw reply related
* Re: WARNING: at net/ipv4/af_inet.c:155 inet_sock_destruct+0x122/0x13a()
From: John Dykstra @ 2009-08-13 15:21 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: Eric Dumazet, David Miller, mangoo, netdev
In-Reply-To: <4A831F69.1080703@hp.com>
On Wed, 2009-08-12 at 16:00 -0400, Vlad Yasevich wrote:
> BTW, I've seen the same issue in 2.6.28 and 2.6.29 while doing a bunch
> of NFS-over-UDP testing. I've seen the issue reported in 2.6.27 as well,
> but it went by ignored. It's not easy to reproduce as it seems like it
> requires quite a bit traffic over over multiple interfaces.
I've been unable to reproduce it so far. Has bonding always been
present in the cases you've seen, or are multiple independent interfaces
sufficient?
In the case you reported initially, openvpn was using UDP, but the peer
was dead, so there presumably wasn't much traffic from that app. Was
there lots of NFS-over-UDP traffic also going on?
Where was the independent report on 2.6.27?
-- John
^ permalink raw reply
* Re: [PATCH 3/3] net: skb ftracer - Add actual ftrace code to kernel (v3)
From: Neil Horman @ 2009-08-13 15:23 UTC (permalink / raw)
To: netdev; +Cc: davem, rostedt
In-Reply-To: <20090813145917.GA16521@hmsreliant.think-freely.org>
skb allocation / consumption correlator
Add ftracer module to kernel to print out a list that correlates a process id,
an skb it read, and the numa nodes on wich the process was running when it was
read along with the numa node the skbuff was allocated on.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Makefile | 1
trace.h | 19 ++++++
trace_skb_sources.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 174 insertions(+)
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 844164d..ee5e5b1 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
ifeq ($(CONFIG_BLOCK),y)
obj-$(CONFIG_EVENT_TRACING) += blktrace.o
endif
+obj-$(CONFIG_SKB_SOURCES_TRACER) += trace_skb_sources.o
obj-$(CONFIG_EVENT_TRACING) += trace_events.o
obj-$(CONFIG_EVENT_TRACING) += trace_export.o
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8b9f4f6..8a6281b 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -11,6 +11,7 @@
#include <trace/boot.h>
#include <linux/kmemtrace.h>
#include <trace/power.h>
+#include <trace/events/skb.h>
#include <linux/trace_seq.h>
#include <linux/ftrace_event.h>
@@ -40,6 +41,7 @@ enum trace_type {
TRACE_KMEM_FREE,
TRACE_POWER,
TRACE_BLK,
+ TRACE_SKB_SOURCE,
__TRACE_LAST_TYPE,
};
@@ -171,6 +173,21 @@ struct trace_power {
struct power_trace state_data;
};
+struct skb_record {
+ pid_t pid; /* pid of the copying process */
+ int anid; /* node where skb was allocated */
+ int cnid; /* node to which skb was copied in userspace */
+ char ifname[IFNAMSIZ]; /* Name of the receiving interface */
+ int rx_queue; /* The rx queue the skb was received on */
+ int ccpu; /* Cpu the application got this frame from */
+ int len; /* length of the data copied */
+};
+
+struct trace_skb_event {
+ struct trace_entry ent;
+ struct skb_record event_data;
+};
+
enum kmemtrace_type_id {
KMEMTRACE_TYPE_KMALLOC = 0, /* kmalloc() or kfree(). */
KMEMTRACE_TYPE_CACHE, /* kmem_cache_*(). */
@@ -323,6 +340,8 @@ extern void __ftrace_bad_type(void);
TRACE_SYSCALL_ENTER); \
IF_ASSIGN(var, ent, struct syscall_trace_exit, \
TRACE_SYSCALL_EXIT); \
+ IF_ASSIGN(var, ent, struct trace_skb_event, \
+ TRACE_SKB_SOURCE); \
__ftrace_bad_type(); \
} while (0)
diff --git a/kernel/trace/trace_skb_sources.c b/kernel/trace/trace_skb_sources.c
new file mode 100644
index 0000000..4ba3671
--- /dev/null
+++ b/kernel/trace/trace_skb_sources.c
@@ -0,0 +1,154 @@
+/*
+ * ring buffer based tracer for analyzing per-socket skb sources
+ *
+ * Neil Horman <nhorman@tuxdriver.com>
+ * Copyright (C) 2009
+ *
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <trace/events/skb.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(skb_copy_datagram_iovec);
+
+static struct trace_array *skb_trace;
+static int __read_mostly trace_skb_source_enabled;
+
+static void probe_skb_dequeue(const struct sk_buff *skb, int len)
+{
+ struct ring_buffer_event *event;
+ struct trace_skb_event *entry;
+ struct trace_array *tr = skb_trace;
+ struct net_device *dev;
+
+ if (!trace_skb_source_enabled)
+ return;
+
+ if (in_interrupt())
+ return;
+
+ event = trace_buffer_lock_reserve(tr, TRACE_SKB_SOURCE,
+ sizeof(*entry), 0, 0);
+ if (!event)
+ return;
+ entry = ring_buffer_event_data(event);
+
+ entry->event_data.pid = current->pid;
+ entry->event_data.anid = page_to_nid(virt_to_page(skb->data));
+ entry->event_data.cnid = cpu_to_node(smp_processor_id());
+ entry->event_data.len = len;
+ entry->event_data.rx_queue = skb->queue_mapping;
+ entry->event_data.ccpu = smp_processor_id();
+
+ dev = dev_get_by_index(sock_net(skb->sk), skb->iif);
+ if (dev) {
+ memcpy(entry->event_data.ifname, dev->name, IFNAMSIZ);
+ dev_put(dev);
+ } else {
+ strcpy(entry->event_data.ifname, "Unknown");
+ }
+
+ trace_buffer_unlock_commit(tr, event, 0, 0);
+}
+
+static int tracing_skb_source_register(void)
+{
+ int ret;
+
+ ret = register_trace_skb_copy_datagram_iovec(probe_skb_dequeue);
+ if (ret)
+ pr_info("skb source trace: Couldn't activate dequeue tracepoint");
+
+ return ret;
+}
+
+static void start_skb_source_trace(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 1;
+}
+
+static void stop_skb_source_trace(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 0;
+}
+
+static void skb_source_trace_reset(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 0;
+ unregister_trace_skb_copy_datagram_iovec(probe_skb_dequeue);
+}
+
+
+static int skb_source_trace_init(struct trace_array *tr)
+{
+ int cpu;
+ skb_trace = tr;
+
+ trace_skb_source_enabled = 1;
+ tracing_skb_source_register();
+
+ for_each_cpu(cpu, cpu_possible_mask)
+ tracing_reset(tr, cpu);
+ return 0;
+}
+
+static enum print_line_t skb_source_print_line(struct trace_iterator *iter)
+{
+ int ret = 0;
+ struct trace_entry *entry = iter->ent;
+ struct trace_skb_event *event;
+ struct skb_record *record;
+ struct trace_seq *s = &iter->seq;
+
+ trace_assign_type(event, entry);
+ record = &event->event_data;
+ if (entry->type != TRACE_SKB_SOURCE)
+ return TRACE_TYPE_UNHANDLED;
+
+ ret = trace_seq_printf(s, " %d %d %d %s %d %d %d\n",
+ record->pid,
+ record->anid,
+ record->cnid,
+ record->ifname,
+ record->rx_queue,
+ record->ccpu,
+ record->len);
+
+ if (!ret)
+ return TRACE_TYPE_PARTIAL_LINE;
+
+ return TRACE_TYPE_HANDLED;
+}
+
+static void skb_source_print_header(struct seq_file *s)
+{
+ seq_puts(s, "# PID ANID CNID IFC RXQ CCPU LEN\n");
+ seq_puts(s, "# | | | | | | |\n");
+}
+
+static struct tracer skb_source_tracer __read_mostly =
+{
+ .name = "skb_sources",
+ .init = skb_source_trace_init,
+ .start = start_skb_source_trace,
+ .stop = stop_skb_source_trace,
+ .reset = skb_source_trace_reset,
+ .print_line = skb_source_print_line,
+ .print_header = skb_source_print_header,
+};
+
+static int init_skb_source_trace(void)
+{
+ return register_tracer(&skb_source_tracer);
+}
+device_initcall(init_skb_source_trace);
^ permalink raw reply related
* Re: [PATCH 2/3] security: introducing security_request_module
From: Eric Paris @ 2009-08-13 15:28 UTC (permalink / raw)
To: Serge E. Hallyn
Cc: linux-kernel, selinux, netdev, linux-security-module, sds, davem,
shemminger, kees, morgan, casey, dwalsh
In-Reply-To: <20090813140306.GC30731@us.ibm.com>
On Thu, 2009-08-13 at 09:03 -0500, Serge E. Hallyn wrote:
> Quoting Eric Paris (eparis@redhat.com):
> > Calling request_module() will trigger a userspace upcall which will load a
> > new module into the kernel. This can be a dangerous event if the process
> > able to trigger request_module() is able to control either the modprobe
> > binary or the module binary. This patch adds a new security hook to
> > request_module() which can be used by an LSM to control a processes ability
> > to call request_module().
>
> Is there a specific case in which you'd want to deny this ability
> from a real task?
qemu and any network facing daemon are all programs I don't want to be
able to even ask the kernel to load a module. Clearly you are right,
that the best protection is done by controlling access to modprobe and
the modules on disk (which we are working to fix vs what happened in the
xen fb exploit I showed earlier) but stopping it from the other
direction is, I feel, a useful defense in depth.
If they can't get modprobe called, they can't take over the system
directly, even if they did change a module or change modprobe. I agree
it's not strong security as if they can change modprobe or modules they
might be able to just wait until something else calls modprobe (next
reboot maybe?) to take over the system. But I'd find it very
interesting to know that a high threat target tried to do anything which
attempted to load a module....
-Eric
^ permalink raw reply
* Re: [PATCH 2/2] vhost_net: a kernel-level virtio server
From: Avi Kivity @ 2009-08-13 15:37 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Michael S. Tsirkin, virtualization, netdev, Ira W. Snyder,
linux-kernel, kvm
In-Reply-To: <200908131653.47029.arnd@arndb.de>
On 08/13/2009 05:53 PM, Arnd Bergmann wrote:
> On Thursday 13 August 2009, Michael S. Tsirkin wrote:
>
>> The best way to do this IMO would be to add zero copy support to raw
>> sockets, vhost will then get it basically for free.
>>
>
> Yes, that would be nice. I wonder if that could lead to security
> problems on TX though. I guess It will only bring significant performance
> improvements if we leave the data writable in the user space or guest
> during the operation. If the user finds the right timing, it could
> modify the frame headers after they have been checked using netfilter,
> or while the frames are being consumed in the kernel (e.g. an NFS
> server running in a guest).
>
IIRC when the kernel consumes data it linearizes the skb. We just need
to make sure all the zerocopy data is in the nonlinear part, and the
kernel will copy if/when it needs to access packet data.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply
* Re: [PATCH net-next-2.6] bonding: introduce primary_lazy option
From: Jay Vosburgh @ 2009-08-13 15:44 UTC (permalink / raw)
To: Jiri Pirko; +Cc: davem, bonding-devel, netdev
In-Reply-To: <20090813150513.GB10449@psychotron.englab.brq.redhat.com>
Jiri Pirko <jpirko@redhat.com> wrote:
>In some cases there is not desirable to switch back to primary interface when
>it's link recovers and rather stay wiith currently active one. We need to avoid
>packetloss as much as we can in some cases. This is solved by introducing
>primary_lazy option. Note that enslaved primary slave is set as current
>active no matter what.
Are you just looking for a way to insure that, when the bond
first comes up (is configured at boot, for example), a particular slave
is the active slave? In that case, why can't an explicit selection be
made via either ifenslave -c or /sys/class/net/bond0/bonding/active ?
-J
>Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>
>diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
>index d5181ce..f1b82af 100644
>--- a/Documentation/networking/bonding.txt
>+++ b/Documentation/networking/bonding.txt
>@@ -614,6 +614,15 @@ primary
>
> The primary option is only valid for active-backup mode.
>
>+primary_lazy
>+
>+ Specifies the behaviour of the primary slave in case of
>+ it's link recovery has been detected. By default (value 0) the
>+ primary slave is set as active slave immediately after the link
>+ recovery. If the value is 1 then current active slave doesn't
>+ change as long as it's link status doesn't change. This prevents
>+ the bonding device from flip-flopping.
>+
> updelay
>
> Specifies the time, in milliseconds, to wait before enabling a
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index 3bf0cc6..00fbb9d 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c
>@@ -94,6 +94,7 @@ static int downdelay;
> static int use_carrier = 1;
> static char *mode;
> static char *primary;
>+static int primary_lazy;
> static char *lacp_rate;
> static char *ad_select;
> static char *xmit_hash_policy;
>@@ -126,6 +127,9 @@ MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
> "6 for balance-alb");
> module_param(primary, charp, 0);
> MODULE_PARM_DESC(primary, "Primary network device to use");
>+module_param(primary_lazy, int, 0);
>+MODULE_PARM_DESC(primary_lazy, "Do not set primary slave active once it comes up; "
>+ "0 for off (default), 1 for on");
> module_param(lacp_rate, charp, 0);
> MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
> "(slow/fast)");
>@@ -1067,7 +1071,6 @@ out:
>
> }
>
>-
> /**
> * find_best_interface - select the best available slave to be the active one
> * @bond: our bonding struct
>@@ -1097,9 +1100,11 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
> * and primary_slave that may be up and able to arp
> */
> if ((bond->primary_slave) &&
>- (!bond->params.arp_interval) &&
>- (IS_UP(bond->primary_slave->dev))) {
>+ (IS_UP(bond->primary_slave->dev)) &&
>+ (!(bond->params.primary_lazy && old_active &&
>+ (IS_UP(old_active->dev))) || bond->force_primary)) {
> new_active = bond->primary_slave;
>+ bond->force_primary = false;
> }
>
> /* remember where to stop iterating over the slaves */
>@@ -1674,8 +1679,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
>
> if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
> /* if there is a primary slave, remember it */
>- if (strcmp(bond->params.primary, new_slave->dev->name) == 0)
>+ if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
> bond->primary_slave = new_slave;
>+ bond->force_primary = true;
>+ }
> }
>
> write_lock_bh(&bond->curr_slave_lock);
>@@ -2929,7 +2936,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
> */
> if (bond->primary_slave &&
> (bond->primary_slave != bond->curr_active_slave) &&
>- (bond->primary_slave->link == BOND_LINK_UP))
>+ (bond->primary_slave->link == BOND_LINK_UP) &&
>+ !(bond->params.primary_lazy && bond->curr_active_slave &&
>+ bond->curr_active_slave->link == BOND_LINK_UP))
> commit++;
>
> read_unlock(&bond->curr_slave_lock);
>@@ -3035,7 +3044,9 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
> */
> if (bond->primary_slave &&
> (bond->primary_slave != bond->curr_active_slave) &&
>- (bond->primary_slave->link == BOND_LINK_UP)) {
>+ (bond->primary_slave->link == BOND_LINK_UP) &&
>+ !(bond->params.primary_lazy && bond->curr_active_slave &&
>+ bond->curr_active_slave->link == BOND_LINK_UP)) {
> write_lock_bh(&bond->curr_slave_lock);
> bond_change_active_slave(bond, bond->primary_slave);
> write_unlock_bh(&bond->curr_slave_lock);
>@@ -4987,6 +4998,17 @@ static int bond_check_params(struct bond_params *params)
> primary = NULL;
> }
>
>+ if (primary) {
>+ if ((primary_lazy != 0) && (primary_lazy != 1)) {
>+ pr_warning(DRV_NAME
>+ ": Warning: primary_lazy module parameter "
>+ "(%d), not of valid value (0/1), so it was "
>+ "set to 0\n",
>+ primary_lazy);
>+ primary_lazy = 1;
>+ }
>+ }
>+
> if (fail_over_mac) {
> fail_over_mac_value = bond_parse_parm(fail_over_mac,
> fail_over_mac_tbl);
>@@ -5018,6 +5040,7 @@ static int bond_check_params(struct bond_params *params)
> params->use_carrier = use_carrier;
> params->lacp_fast = lacp_fast;
> params->primary[0] = 0;
>+ params->primary_lazy = primary_lazy;
> params->fail_over_mac = fail_over_mac_value;
>
> if (primary) {
>diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
>index 55bf34f..573fe82 100644
>--- a/drivers/net/bonding/bond_sysfs.c
>+++ b/drivers/net/bonding/bond_sysfs.c
>@@ -1209,6 +1209,59 @@ static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
> bonding_show_primary, bonding_store_primary);
>
> /*
>+ * Show and set the primary_lazy flag.
>+ */
>+static ssize_t bonding_show_primary_lazy(struct device *d,
>+ struct device_attribute *attr,
>+ char *buf)
>+{
>+ struct bonding *bond = to_bond(d);
>+
>+ return sprintf(buf, "%d\n", bond->params.primary_lazy);
>+}
>+
>+static ssize_t bonding_store_primary_lazy(struct device *d,
>+ struct device_attribute *attr,
>+ const char *buf, size_t count)
>+{
>+ int new_value, ret = count;
>+ struct bonding *bond = to_bond(d);
>+
>+ if (!rtnl_trylock())
>+ return restart_syscall();
>+
>+ if (sscanf(buf, "%d", &new_value) != 1) {
>+ pr_err(DRV_NAME
>+ ": %s: no primary_lazy value specified.\n",
>+ bond->dev->name);
>+ ret = -EINVAL;
>+ goto out;
>+ }
>+ if ((new_value == 0) || (new_value == 1)) {
>+ bond->params.primary_lazy = new_value;
>+ pr_info(DRV_NAME ": %s: Setting primary_lazy to %d.\n",
>+ bond->dev->name, new_value);
>+ if (!bond->params.primary_lazy) {
>+ bond->force_primary = true;
>+ read_lock(&bond->lock);
>+ write_lock_bh(&bond->curr_slave_lock);
>+ bond_select_active_slave(bond);
>+ write_unlock_bh(&bond->curr_slave_lock);
>+ read_unlock(&bond->lock);
>+ }
>+ } else {
>+ pr_info(DRV_NAME
>+ ": %s: Ignoring invalid primary_lazy value %d.\n",
>+ bond->dev->name, new_value);
>+ }
>+out:
>+ rtnl_unlock();
>+ return count;
>+}
>+static DEVICE_ATTR(primary_lazy, S_IRUGO | S_IWUSR,
>+ bonding_show_primary_lazy, bonding_store_primary_lazy);
>+
>+/*
> * Show and set the use_carrier flag.
> */
> static ssize_t bonding_show_carrier(struct device *d,
>@@ -1497,6 +1550,7 @@ static struct attribute *per_bond_attrs[] = {
> &dev_attr_num_unsol_na.attr,
> &dev_attr_miimon.attr,
> &dev_attr_primary.attr,
>+ &dev_attr_primary_lazy.attr,
> &dev_attr_use_carrier.attr,
> &dev_attr_active_slave.attr,
> &dev_attr_mii_status.attr,
>diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
>index 6290a50..ac35c6c 100644
>--- a/drivers/net/bonding/bonding.h
>+++ b/drivers/net/bonding/bonding.h
>@@ -131,6 +131,7 @@ struct bond_params {
> int lacp_fast;
> int ad_select;
> char primary[IFNAMSIZ];
>+ int primary_lazy;
> __be32 arp_targets[BOND_MAX_ARP_TARGETS];
> };
>
>@@ -190,6 +191,7 @@ struct bonding {
> struct slave *curr_active_slave;
> struct slave *current_arp_slave;
> struct slave *primary_slave;
>+ bool force_primary;
> s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
> rwlock_t lock;
> rwlock_t curr_slave_lock;
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* Re: [RFC] ipv6: Change %pI6 format to output compacted addresses?
From: Brian Haley @ 2009-08-13 16:27 UTC (permalink / raw)
To: Jens Rosenboom; +Cc: Linux Network Developers
In-Reply-To: <1250174390.6641.89.camel@fnki-nb00130>
Jens Rosenboom wrote:
>> Anyways, can you try this patch, it's less than 40 new lines :)
>> It might be good enough, but could probably use some help.
>
> For a start, it didn't even compile. ;-)
It did on net-next-2.6 last night, weird.
> Here is a new version that also
> fixes
>
> - Leave %pi6 alone
> - Don't compress a single :0:
> - Do output 0
>
> The results and also the remaining issues can be seen with the attached
> test program, that also exposes a bug in glibc for v4-mapped addresses
> from 0/16.
>
> To fully conform to the cited draft, we would still have to implement
> v4-mapped and also check whether a second run of zeros would be longer
> than the first one, although the draft also suggests that operators
> should avoid using this kind of addresses, so maybe this second issue
> can be neglected.
Yes, the "compress the most zeros" would be harder, and require two
passes over the address. I had to cut corners somewhere :)
And regarding v4-mapped, the easy fix to that is just detect it and
call the IPv4 routine. The attached patch does that, but without the
::ffff:
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 756ccaf..5710c65 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -652,13 +652,53 @@ static char *ip6_addr_string(char *buf, char *end,
> u8 *addr,
> {
> char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing
> zero */
> char *p = ip6_addr;
> - int i;
> + int i, needcolon = 0, printhi;
> + u16 *addr16 = (u16 *)addr;
> + enum { DC_START, DC_MIDDLE, DC_DONE } colon = DC_START;
> +
> + /* omit leading zeros and shorten using "::" */
>
> - for (i = 0; i < 8; i++) {
> - p = pack_hex_byte(p, addr[2 * i]);
> - p = pack_hex_byte(p, addr[2 * i + 1]);
> - if (!(spec.flags & SPECIAL) && i != 7)
> + if (!(spec.flags & SPECIAL)) {
> + for (i = 0; i < 8; i++) {
> + if (addr16[i] == 0 && addr16[i+1] == 0 && colon == DC_START) {
This will access the array out-of-bounds when i=7.
Another hack below.
-Brian
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 756ccaf..ba70f2a 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -647,25 +647,6 @@ static char *mac_address_string(char *buf, char *end, u8 *addr,
return string(buf, end, mac_addr, spec);
}
-static char *ip6_addr_string(char *buf, char *end, u8 *addr,
- struct printf_spec spec)
-{
- char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
- char *p = ip6_addr;
- int i;
-
- for (i = 0; i < 8; i++) {
- p = pack_hex_byte(p, addr[2 * i]);
- p = pack_hex_byte(p, addr[2 * i + 1]);
- if (!(spec.flags & SPECIAL) && i != 7)
- *p++ = ':';
- }
- *p = '\0';
- spec.flags &= ~SPECIAL;
-
- return string(buf, end, ip6_addr, spec);
-}
-
static char *ip4_addr_string(char *buf, char *end, u8 *addr,
struct printf_spec spec)
{
@@ -688,6 +669,73 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr,
return string(buf, end, ip4_addr, spec);
}
+static char *ip6_addr_string(char *buf, char *end, u8 *addr,
+ struct printf_spec spec)
+{
+ char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
+ char *p = ip6_addr;
+ int i, needcolon, printhi;
+ u16 *addr16 = (u16 *)addr;
+ u32 *addr32 = (u32 *)addr;
+ enum { DC_START, DC_MIDDLE, DC_DONE } colon = DC_START;
+
+ if (!(spec.flags & SPECIAL)) {
+ /* omit leading zeros and shorten using "::" */
+
+ /* v4mapped */
+ if ((addr32[0] | addr32[1] |
+ (addr32[2] ^ htonl(0x0000ffff))) == 0)
+ return ip4_addr_string(buf, end, &addr[12], spec);
+
+ needcolon = 0;
+ for (i = 0; i < 8; i++) {
+ if (addr16[i] == 0 && i < 7 && addr16[i+1] == 0 &&
+ colon == DC_START) {
+ colon = DC_MIDDLE;
+ continue;
+ }
+ if (colon == DC_MIDDLE) {
+ if (addr16[i] == 0)
+ continue;
+ colon = DC_DONE;
+ *p++ = ':';
+ *p++ = ':';
+ } else if (needcolon)
+ *p++ = ':';
+ printhi = 0;
+ if (addr[2 * i]) {
+ if (addr[2 * i] > 0x0f)
+ p = pack_hex_byte(p, addr[2 * i]);
+ else
+ *p++ = hex_asc_lo(addr[2 * i]);
+ printhi++;
+ }
+ /*
+ * If we printed the high-order bits we must print the
+ * low-order ones, even if they're all zeros.
+ */
+ if (printhi || addr[2 * i + 1] > 0x0f)
+ p = pack_hex_byte(p, addr[2 * i + 1]);
+ else
+ *p++ = hex_asc_lo(addr[2 * i + 1]);
+ needcolon++;
+ }
+ if (colon == DC_MIDDLE) {
+ *p++ = ':';
+ *p++ = ':';
+ }
+ } else {
+ for (i = 0; i < 8; i++) {
+ p = pack_hex_byte(p, addr[2 * i]);
+ p = pack_hex_byte(p, addr[2 * i + 1]);
+ }
+ }
+ *p = '\0';
+ spec.flags &= ~SPECIAL;
+
+ return string(buf, end, ip6_addr, spec);
+}
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
^ permalink raw reply related
* [PATCH] net/bridge: Add 'hairpin' port forwarding mode
From: Fischer, Anna @ 2009-08-13 16:55 UTC (permalink / raw)
To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Cc: Stephen Hemminger, Paul Congdon (UC Davis), evb@yahoogroups.com,
bridge@lists.linux-foundation.org, davem@davemloft.net,
virtualization@lists.linux-foundation.org, kaber@trash.net,
Arnd Bergmann, Dickson, Mike (ISS Software), adobriyan@gmail.com,
bridge@osdl.org
This patch adds a 'hairpin' (also called 'reflective relay') mode
port configuration to the Linux Ethernet bridge kernel module.
A bridge supporting hairpin forwarding mode can send frames back
out through the port the frame was received on.
Hairpin mode is required to support basic VEPA (Virtual
Ethernet Port Aggregator) capabilities.
You can find additional information on VEPA here:
http://tech.groups.yahoo.com/group/evb/
http://www.ieee802.org/1/files/public/docs2009/new-hudson-vepa_seminar-20090514d.pdf
http://www.internet2.edu/presentations/jt2009jul/20090719-congdon.pdf
An additional patch 'bridge-utils: Add 'hairpin' port forwarding mode'
is provided to allow configuring hairpin mode from userspace tools.
Signed-off-by: Paul Congdon <paul.congdon@hp.com>
Signed-off-by: Anna Fischer <anna.fischer@hp.com>
---
net/bridge/br_forward.c | 3 ++-
net/bridge/br_if.c | 1 +
net/bridge/br_private.h | 3 +++
net/bridge/br_sysfs_if.c | 17 +++++++++++++++++
4 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c8..bc1704a 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -22,7 +22,8 @@
static inline int should_deliver(const struct net_bridge_port *p,
const struct sk_buff *skb)
{
- return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
+ return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
+ p->state == BR_STATE_FORWARDING);
}
static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index eb404dc..e486f1f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -256,6 +256,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
p->port_no = index;
+ p->flags = 0;
br_init_port(p);
p->state = BR_STATE_DISABLED;
br_stp_port_timer_init(p);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d5b5537..8319247 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -81,6 +81,9 @@ struct net_bridge_port
struct timer_list message_age_timer;
struct kobject kobj;
struct rcu_head rcu;
+
+ unsigned long flags;
+#define BR_HAIRPIN_MODE 0x00000001
};
struct net_bridge
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 4a3cdf8..820643a 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,22 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
}
static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
+static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
+{
+ int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
+ return sprintf(buf, "%d\n", hairpin_mode);
+}
+static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
+{
+ if (v)
+ p->flags |= BR_HAIRPIN_MODE;
+ else
+ p->flags &= ~BR_HAIRPIN_MODE;
+ return 0;
+}
+static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
+ show_hairpin_mode, store_hairpin_mode);
+
static struct brport_attribute *brport_attrs[] = {
&brport_attr_path_cost,
&brport_attr_priority,
@@ -159,6 +175,7 @@ static struct brport_attribute *brport_attrs[] = {
&brport_attr_forward_delay_timer,
&brport_attr_hold_timer,
&brport_attr_flush,
+ &brport_attr_hairpin_mode,
NULL
};
^ permalink raw reply related
* [PATCH 2/2] netxen: free napi resources during detach
From: Dhananjay Phadke @ 2009-08-13 17:03 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1250182981-27594-1-git-send-email-dhananjay@netxen.com>
o Defer napi resouce allocation to device attach.
o Free napi resources and delete napi during detach.
This ensures right behavior across firmware reset.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic_init.c | 7 -------
drivers/net/netxen/netxen_nic_main.c | 32 ++++++++++++++++++++++++--------
2 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 7acf204..5d3343e 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -184,13 +184,6 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter)
kfree(recv_ctx->rds_rings);
skip_rds:
- if (recv_ctx->sds_rings == NULL)
- goto skip_sds;
-
- for(ring = 0; ring < adapter->max_sds_rings; ring++)
- recv_ctx->sds_rings[ring].consumer = 0;
-
-skip_sds:
if (adapter->tx_ring == NULL)
return;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index d24e1cb..28f270f 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -167,6 +167,8 @@ netxen_free_sds_rings(struct netxen_recv_context *recv_ctx)
{
if (recv_ctx->sds_rings != NULL)
kfree(recv_ctx->sds_rings);
+
+ recv_ctx->sds_rings = NULL;
}
static int
@@ -189,6 +191,21 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
}
static void
+netxen_napi_del(struct netxen_adapter *adapter)
+{
+ int ring;
+ struct nx_host_sds_ring *sds_ring;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+ for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+ sds_ring = &recv_ctx->sds_rings[ring];
+ netif_napi_del(&sds_ring->napi);
+ }
+
+ netxen_free_sds_rings(&adapter->recv_ctx);
+}
+
+static void
netxen_napi_enable(struct netxen_adapter *adapter)
{
int ring;
@@ -889,10 +906,12 @@ netxen_nic_attach(struct netxen_adapter *adapter)
struct nx_host_tx_ring *tx_ring;
err = netxen_init_firmware(adapter);
- if (err != 0) {
- printk(KERN_ERR "Failed to init firmware\n");
- return -EIO;
- }
+ if (err)
+ return err;
+
+ err = netxen_napi_add(adapter, netdev);
+ if (err)
+ return err;
if (adapter->fw_major < 4)
adapter->max_rds_rings = 3;
@@ -956,6 +975,7 @@ netxen_nic_detach(struct netxen_adapter *adapter)
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_nic_free_irq(adapter);
+ netxen_napi_del(adapter);
netxen_free_sw_resources(adapter);
adapter->is_up = 0;
@@ -1100,9 +1120,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->irq = adapter->msix_entries[0].vector;
- if (netxen_napi_add(adapter, netdev))
- goto err_out_disable_msi;
-
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &netxen_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -1183,7 +1200,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_free_adapter_offload(adapter);
netxen_teardown_intr(adapter);
- netxen_free_sds_rings(&adapter->recv_ctx);
netxen_cleanup_pci_map(adapter);
--
1.6.0.2
^ permalink raw reply related
* [PATCH 1/2] netxen: remove netxen workqueue
From: Dhananjay Phadke @ 2009-08-13 17:03 UTC (permalink / raw)
To: davem; +Cc: netdev, Amit Kumar Salecha
In-Reply-To: <1250182981-27594-1-git-send-email-dhananjay@netxen.com>
From: Amit Kumar Salecha <amit@qlogic.com>
o Remove private workqueue in the driver, move all
scheduled tasks to keventd workqueues. This makes
ports (interfaces) of same / different NIC boards
independent, in terms of their link watchdog and
reset tasks.
o Move quick checks for link status and temperature
in timer callback, schedule watchdog task only if
link status changed or temperature reached critical
threshold.
This also fixes deadlock when thermal panic occurs,
watchdog work was flushing workqueue that it was
sitting on.
Signed-off-by: Amit Kumar Salecha <amit@qlogic.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic.h | 2 +-
drivers/net/netxen/netxen_nic_main.c | 69 ++++++++++++++++++++--------------
2 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index f86e050..a9c1fcc 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1254,7 +1254,7 @@ struct netxen_adapter {
u8 mc_enabled;
u8 max_mc_count;
u8 rss_supported;
- u8 resv2;
+ u8 link_changed;
u32 resv3;
u8 has_link_events;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 70c05c4..d24e1cb 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -94,10 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
-static struct workqueue_struct *netxen_workq;
-#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
-#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
-
static void netxen_watchdog(unsigned long);
static uint32_t crb_cmd_producer[4] = {
@@ -880,7 +876,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
spin_unlock(&adapter->tx_clean_lock);
del_timer_sync(&adapter->watchdog_timer);
- FLUSH_SCHEDULED_WORK();
}
@@ -1177,6 +1172,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
+ cancel_work_sync(&adapter->watchdog_task);
+ cancel_work_sync(&adapter->tx_timeout_task);
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
netxen_nic_detach(adapter);
}
@@ -1211,6 +1209,9 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
+ cancel_work_sync(&adapter->watchdog_task);
+ cancel_work_sync(&adapter->tx_timeout_task);
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
netxen_nic_detach(adapter);
@@ -1549,11 +1550,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
"%s: Device temperature %d degrees C exceeds"
" maximum allowed. Hardware has been shut down.\n",
netdev->name, temp_val);
-
- netif_device_detach(netdev);
- netxen_nic_down(adapter, netdev);
- netxen_nic_detach(adapter);
-
rv = 1;
} else if (temp_state == NX_TEMP_WARN) {
if (adapter->temp == NX_TEMP_NORMAL) {
@@ -1587,10 +1583,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
-
- if (!adapter->has_link_events)
- netxen_nic_set_link_parameters(adapter);
-
+ adapter->link_changed = !adapter->has_link_events;
} else if (!adapter->ahw.linkup && linkup) {
printk(KERN_INFO "%s: %s NIC Link is up\n",
netxen_nic_driver_name, netdev->name);
@@ -1599,9 +1592,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
-
- if (!adapter->has_link_events)
- netxen_nic_set_link_parameters(adapter);
+ adapter->link_changed = !adapter->has_link_events;
}
}
@@ -1628,11 +1619,36 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netxen_advert_link_change(adapter, linkup);
}
+static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ netif_device_detach(netdev);
+ netxen_nic_down(adapter, netdev);
+ netxen_nic_detach(adapter);
+}
+
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
- SCHEDULE_WORK(&adapter->watchdog_task);
+ if (netxen_nic_check_temp(adapter))
+ goto do_sched;
+
+ if (!adapter->has_link_events) {
+ netxen_nic_handle_phy_intr(adapter);
+
+ if (adapter->link_changed)
+ goto do_sched;
+ }
+
+ if (netif_running(adapter->netdev))
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+
+ return;
+
+do_sched:
+ schedule_work(&adapter->watchdog_task);
}
void netxen_watchdog_task(struct work_struct *work)
@@ -1640,11 +1656,13 @@ void netxen_watchdog_task(struct work_struct *work)
struct netxen_adapter *adapter =
container_of(work, struct netxen_adapter, watchdog_task);
- if (netxen_nic_check_temp(adapter))
+ if (adapter->temp == NX_TEMP_PANIC) {
+ netxen_nic_thermal_shutdown(adapter);
return;
+ }
- if (!adapter->has_link_events)
- netxen_nic_handle_phy_intr(adapter);
+ if (adapter->link_changed)
+ netxen_nic_set_link_parameters(adapter);
if (netif_running(adapter->netdev))
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1652,9 +1670,8 @@ void netxen_watchdog_task(struct work_struct *work)
static void netxen_tx_timeout(struct net_device *netdev)
{
- struct netxen_adapter *adapter = (struct netxen_adapter *)
- netdev_priv(netdev);
- SCHEDULE_WORK(&adapter->tx_timeout_task);
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ schedule_work(&adapter->tx_timeout_task);
}
static void netxen_tx_timeout_task(struct work_struct *work)
@@ -1811,9 +1828,6 @@ static int __init netxen_init_module(void)
{
printk(KERN_INFO "%s\n", netxen_nic_driver_string);
- if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL)
- return -ENOMEM;
-
return pci_register_driver(&netxen_driver);
}
@@ -1822,7 +1836,6 @@ module_init(netxen_init_module);
static void __exit netxen_exit_module(void)
{
pci_unregister_driver(&netxen_driver);
- destroy_workqueue(netxen_workq);
}
module_exit(netxen_exit_module);
--
1.6.0.2
^ permalink raw reply related
* [PATCH 0/2] netxen: bug fixes
From: Dhananjay Phadke @ 2009-08-13 17:02 UTC (permalink / raw)
To: davem; +Cc: netdev
Dave,
2 more fixes for 2.6.31. These will conflict with
while merging with net-next-2.6 tree, will require
simple manual merge.
Please apply.
Thanks,
Dhananjay
^ permalink raw reply
* [PATCH] bridge-utils: Add 'hairpin' port forwarding mode
From: Fischer, Anna @ 2009-08-13 17:02 UTC (permalink / raw)
To: Stephen Hemminger, netdev@vger.kernel.org
Cc: Paul Congdon (UC Davis), evb@yahoogroups.com,
bridge@lists.linux-foundation.org, davem@davemloft.net,
virtualization@lists.linux-foundation.org, kaber@trash.net,
Arnd Bergmann, Dickson, Mike (ISS Software), adobriyan@gmail.com,
bridge@osdl.org, linux-kernel@vger.kernel.org
This patch adds a 'hairpin' (also called 'reflective relay') mode
port configuration to the Linux Ethernet bridge utilities.
A bridge supporting hairpin forwarding mode can send frames back
out through the port the frame was received on.
Hairpin mode is required to support basic VEPA (Virtual
Ethernet Port Aggregator) capabilities.
You can find additional information on VEPA here:
http://tech.groups.yahoo.com/group/evb/
http://www.ieee802.org/1/files/public/docs2009/new-hudson-vepa_seminar-20090514d.pdf
http://www.internet2.edu/presentations/jt2009jul/20090719-congdon.pdf
Hairpin forwarding requires support from the kernel. A further kernel
patch 'net/bridge: Add 'hairpin' port forwarding mode' is provided
for this.
Signed-off-by: Paul Congdon <paul.congdon@hp.com>
Signed-off-by: Anna Fischer <anna.fischer@hp.com>
---
brctl/brctl_cmd.c | 38 ++++++++++++++++++++++++++++++++++++++
brctl/brctl_disp.c | 2 ++
libbridge/libbridge.h | 3 +++
libbridge/libbridge_devif.c | 24 ++++++++++++++++++++++++
4 files changed, 67 insertions(+), 0 deletions(-)
diff --git a/brctl/brctl_cmd.c b/brctl/brctl_cmd.c
index c93dd55..d37e99c 100644
--- a/brctl/brctl_cmd.c
+++ b/brctl/brctl_cmd.c
@@ -395,6 +395,42 @@ static int br_cmd_showmacs(int argc, char *const* argv)
return 0;
}
+static int br_cmd_hairpin(int argc, char *const* argv)
+{
+ int hairpin, err;
+ const char *brname = *++argv;
+ const char *ifname = *++argv;
+ const char *hpmode = *++argv;
+
+ if (!strcmp(hpmode, "on") || !strcmp(hpmode, "yes")
+ || !strcmp(hpmode, "1"))
+ hairpin = 1;
+ else if (!strcmp(hpmode, "off") || !strcmp(hpmode, "no")
+ || !strcmp(hpmode, "0"))
+ hairpin = 0;
+ else {
+ fprintf(stderr, "expect on/off for argument\n");
+ return 1;
+ }
+ if (if_nametoindex(ifname) == 0) {
+ fprintf(stderr, "interface %s does not exist!\n",
+ ifname);
+ return 1;
+ } else if (if_nametoindex(brname) == 0) {
+ fprintf(stderr, "bridge %s does not exist!\n",
+ brname);
+ return 1;
+ }
+
+ err = br_set_hairpin_mode(brname, ifname, hairpin);
+
+ if (err) {
+ fprintf(stderr, "can't set %s to hairpin on bridge %s: %s\n",
+ ifname, brname, strerror(err));
+ }
+ return err != 0;
+}
+
static const struct command commands[] = {
{ 1, "addbr", br_cmd_addbr, "<bridge>\t\tadd bridge" },
{ 1, "delbr", br_cmd_delbr, "<bridge>\t\tdelete bridge" },
@@ -402,6 +438,8 @@ static const struct command commands[] = {
"<bridge> <device>\tadd interface to bridge" },
{ 2, "delif", br_cmd_delif,
"<bridge> <device>\tdelete interface from bridge" },
+ { 3, "hairpin", br_cmd_hairpin,
+ "<bridge> <port> {on|off}\tturn hairpin on/off" },
{ 2, "setageing", br_cmd_setageing,
"<bridge> <time>\t\tset ageing time" },
{ 2, "setbridgeprio", br_cmd_setbridgeprio,
diff --git a/brctl/brctl_disp.c b/brctl/brctl_disp.c
index 27ce6d2..3e81241 100644
--- a/brctl/brctl_disp.c
+++ b/brctl/brctl_disp.c
@@ -93,6 +93,8 @@ static int dump_port_info(const char *br, const char *p, void *arg)
printf("CONFIG_PENDING ");
if (pinfo.top_change_ack)
printf("TOPOLOGY_CHANGE_ACK ");
+ if (pinfo.hairpin_mode)
+ printf("\n hairpin mode\t\t\%4i", pinfo.hairpin_mode);
printf("\n");
printf("\n");
return 0;
diff --git a/libbridge/libbridge.h b/libbridge/libbridge.h
index 016acea..39964f2 100644
--- a/libbridge/libbridge.h
+++ b/libbridge/libbridge.h
@@ -80,6 +80,7 @@ struct port_info
struct timeval message_age_timer_value;
struct timeval forward_delay_timer_value;
struct timeval hold_timer_value;
+ unsigned char hairpin_mode;
};
extern int br_init(void);
@@ -113,4 +114,6 @@ extern int br_set_path_cost(const char *br, const char *p,
int path_cost);
extern int br_read_fdb(const char *br, struct fdb_entry *fdbs,
unsigned long skip, int num);
+extern int br_set_hairpin_mode(const char *bridge, const char *dev,
+ int hairpin_mode);
#endif
diff --git a/libbridge/libbridge_devif.c b/libbridge/libbridge_devif.c
index 34e3cc8..ca40325 100644
--- a/libbridge/libbridge_devif.c
+++ b/libbridge/libbridge_devif.c
@@ -36,6 +36,14 @@ static FILE *fpopen(const char *dir, const char *name)
return fopen(path, "r");
}
+static int fpaccess(const char *dir, const char *name)
+{
+ char path[SYSFS_PATH_MAX];
+
+ snprintf(path, SYSFS_PATH_MAX, "%s/%s", dir, name);
+ return access(path, F_OK);
+}
+
static void fetch_id(const char *dev, const char *name, struct bridge_id *id)
{
FILE *f = fpopen(dev, name);
@@ -73,6 +81,12 @@ static void fetch_tv(const char *dev, const char *name,
__jiffies_to_tv(tv, fetch_int(dev, name));
}
+/* Check if a feature is supported. */
+static int feature_supported(const char *dev, const char *feature)
+{
+ return !fpaccess(dev, feature);
+}
+
/*
* Convert device name to an index in the list of ports in bridge.
*
@@ -239,6 +253,7 @@ static int old_get_port_info(const char *brname, const char *port,
__jiffies_to_tv(&info->forward_delay_timer_value,
i.forward_delay_timer_value);
__jiffies_to_tv(&info->hold_timer_value, i.hold_timer_value);
+ info->hairpin_mode = 0;
return 0;
}
@@ -271,6 +286,10 @@ int br_get_port_info(const char *brname, const char *port,
fetch_tv(path, "message_age_timer", &info->message_age_timer_value);
fetch_tv(path, "forward_delay_timer", &info->forward_delay_timer_value);
fetch_tv(path, "hold_timer", &info->hold_timer_value);
+ if (feature_supported(path, "hairpin_mode"))
+ info->hairpin_mode = fetch_int(path, "hairpin_mode");
+ else
+ info->hairpin_mode = 0;
closedir(d);
return 0;
@@ -381,6 +400,11 @@ int br_set_path_cost(const char *bridge, const char *port, int cost)
return port_set(bridge, port, "path_cost", cost, BRCTL_SET_PATH_COST);
}
+int br_set_hairpin_mode(const char *bridge, const char *port, int hairpin_mode)
+{
+ return port_set(bridge, port, "hairpin_mode", hairpin_mode, 0);
+}
+
static inline void __copy_fdb(struct fdb_entry *ent,
const struct __fdb_entry *f)
{
^ permalink raw reply related
* Re: WARNING: at net/ipv4/af_inet.c:155 inet_sock_destruct+0x122/0x13a()
From: Vlad Yasevich @ 2009-08-13 17:04 UTC (permalink / raw)
To: John Dykstra; +Cc: Eric Dumazet, David Miller, mangoo, netdev
In-Reply-To: <1250176905.7289.7.camel@Maple>
John Dykstra wrote:
> On Wed, 2009-08-12 at 16:00 -0400, Vlad Yasevich wrote:
>> BTW, I've seen the same issue in 2.6.28 and 2.6.29 while doing a bunch
>> of NFS-over-UDP testing. I've seen the issue reported in 2.6.27 as well,
>> but it went by ignored. It's not easy to reproduce as it seems like it
>> requires quite a bit traffic over over multiple interfaces.
>
> I've been unable to reproduce it so far. Has bonding always been
> present in the cases you've seen, or are multiple independent interfaces
> sufficient?
Bonding wasn't used in this case, ie. no bonding interfaces were configured.
>
> In the case you reported initially, openvpn was using UDP, but the peer
> was dead, so there presumably wasn't much traffic from that app. Was
> there lots of NFS-over-UDP traffic also going on?
The openvpn case wasn't mine. I didn't use any vpn traffic. Just 2
systems back-to-back with NFS traffic between them.
Yes, there was a lot of NFS over UDP traffic and not much other UDP traffic.
>
> Where was the independent report on 2.6.27
http://article.gmane.org/gmane.linux.nfs/22887
http://kerneltrap.org/mailarchive/linux-netdev/2008/11/26/4244994
-vlad
>
> -- John
>
^ permalink raw reply
* Re: [PATCH] net/bridge: Add 'hairpin' port forwarding mode
From: Arnd Bergmann @ 2009-08-13 17:06 UTC (permalink / raw)
To: Fischer, Anna
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
Stephen Hemminger, Paul Congdon (UC Davis), evb@yahoogroups.com,
bridge@lists.linux-foundation.org, davem@davemloft.net,
virtualization@lists.linux-foundation.org, kaber@trash.net,
Dickson, Mike (ISS Software), adobriyan@gmail.com,
bridge@osdl.org
In-Reply-To: <0199E0D51A61344794750DC57738F58E6D6B0C70D9@GVW1118EXC.americas.hpqcorp.net>
On Thursday 13 August 2009, Fischer, Anna wrote:
> This patch adds a 'hairpin' (also called 'reflective relay') mode
> port configuration to the Linux Ethernet bridge kernel module.
> A bridge supporting hairpin forwarding mode can send frames back
> out through the port the frame was received on.
>
> Hairpin mode is required to support basic VEPA (Virtual
> Ethernet Port Aggregator) capabilities.
>
> You can find additional information on VEPA here:
> http://tech.groups.yahoo.com/group/evb/
> http://www.ieee802.org/1/files/public/docs2009/new-hudson-vepa_seminar-20090514d.pdf
> http://www.internet2.edu/presentations/jt2009jul/20090719-congdon.pdf
>
> An additional patch 'bridge-utils: Add 'hairpin' port forwarding mode'
> is provided to allow configuring hairpin mode from userspace tools.
>
> Signed-off-by: Paul Congdon <paul.congdon@hp.com>
> Signed-off-by: Anna Fischer <anna.fischer@hp.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH 2/3] security: introducing security_request_module
From: Daniel J Walsh @ 2009-08-13 17:17 UTC (permalink / raw)
To: Eric Paris
Cc: linux-kernel, selinux, netdev, linux-security-module, sds, davem,
shemminger, kees, morgan, casey
In-Reply-To: <20090813033543.27287.95970.stgit@paris.rdu.redhat.com>
On 08/12/2009 11:35 PM, Eric Paris wrote:
> Calling request_module() will trigger a userspace upcall which will load a
> new module into the kernel. This can be a dangerous event if the process
> able to trigger request_module() is able to control either the modprobe
> binary or the module binary. This patch adds a new security hook to
> request_module() which can be used by an LSM to control a processes ability
> to call request_module().
>
> Signed-off-by: Eric Paris <eparis@redhat.com>
> ---
>
> include/linux/security.h | 10 ++++++++++
> kernel/kmod.c | 4 ++++
> security/capability.c | 6 ++++++
> security/security.c | 5 +++++
> 4 files changed, 25 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/security.h b/include/linux/security.h
> index d5f6578..34c5465 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -678,6 +678,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
> * @inode points to the inode to use as a reference.
> * The current task must be the one that nominated @inode.
> * Return 0 if successful.
> + * @kernel_module_request:
> + * Ability to trigger the kernel to automatically upcall to userspace for
> + * userspace to load a kernel module with the given name.
> * @task_setuid:
> * Check permission before setting one or more of the user identity
> * attributes of the current process. The @flags parameter indicates
> @@ -1500,6 +1503,7 @@ struct security_operations {
> void (*cred_commit)(struct cred *new, const struct cred *old);
> int (*kernel_act_as)(struct cred *new, u32 secid);
> int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
> + int (*kernel_module_request)(void);
> int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
> int (*task_fix_setuid) (struct cred *new, const struct cred *old,
> int flags);
> @@ -1755,6 +1759,7 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
> void security_commit_creds(struct cred *new, const struct cred *old);
> int security_kernel_act_as(struct cred *new, u32 secid);
> int security_kernel_create_files_as(struct cred *new, struct inode *inode);
> +int security_kernel_module_request(void);
> int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
> int security_task_fix_setuid(struct cred *new, const struct cred *old,
> int flags);
> @@ -2306,6 +2311,11 @@ static inline int security_kernel_create_files_as(struct cred *cred,
> return 0;
> }
>
> +static inline int security_kernel_module_request(void)
> +{
> + return 0;
> +}
> +
> static inline int security_task_setuid(uid_t id0, uid_t id1, uid_t id2,
> int flags)
> {
> diff --git a/kernel/kmod.c b/kernel/kmod.c
> index 385c31a..5a7ae57 100644
> --- a/kernel/kmod.c
> +++ b/kernel/kmod.c
> @@ -78,6 +78,10 @@ int __request_module(bool wait, const char *fmt, ...)
> #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
> static int kmod_loop_msg;
>
> + ret = security_kernel_module_request();
> + if (ret)
> + return ret;
> +
> va_start(args, fmt);
> ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
> va_end(args);
> diff --git a/security/capability.c b/security/capability.c
> index 4f23f4f..06400cf 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -396,6 +396,11 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
> return 0;
> }
>
> +static int cap_kernel_module_request(void)
> +{
> + return 0;
> +}
> +
> static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
> {
> return 0;
> @@ -961,6 +966,7 @@ void security_fixup_ops(struct security_operations *ops)
> set_to_cap_if_null(ops, cred_commit);
> set_to_cap_if_null(ops, kernel_act_as);
> set_to_cap_if_null(ops, kernel_create_files_as);
> + set_to_cap_if_null(ops, kernel_module_request);
> set_to_cap_if_null(ops, task_setuid);
> set_to_cap_if_null(ops, task_fix_setuid);
> set_to_cap_if_null(ops, task_setgid);
> diff --git a/security/security.c b/security/security.c
> index b98c684..f88eaf6 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -709,6 +709,11 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
> return security_ops->kernel_create_files_as(new, inode);
> }
>
> +int security_kernel_module_request(void)
> +{
> + return security_ops->kernel_module_request();
> +}
> +
> int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
> {
> return security_ops->task_setuid(id0, id1, id2, flags);
>
Every domain that I know of that currently causes this sys_module has net_admin privs, so this will allow us to run a tighter policy.
^ permalink raw reply
* Re: [PATCH] libertas: name the network device wlan%d
From: Dan Williams @ 2009-08-13 17:28 UTC (permalink / raw)
To: Daniel Drake
Cc: netdev, Roel Kluin, John W. Linville, Daniel Mack, libertas-dev
In-Reply-To: <818423da0908122048p1fa69a2bnd570071f11336089@mail.gmail.com>
On Thu, 2009-08-13 at 09:33 +0545, Daniel Drake wrote:
> 2009/8/12 Dan Williams <dcbw@redhat.com>:
> > Daniel, is it a problem for you guys if the libertas wifi interface name
> > went from 'eth' -> 'wlan' ? Mesh name would be unchanged.
>
> I can't think of any problems.
In that case:
Acked-by: Dan Williams <dcbw@redhat.com>
^ 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