* Re: [Bugme-new] [Bug 14546] New: Off-by-two stack buffer overflow in function rpc_uaddr2sockaddr() of net/sunrpc/addr.c
From: Chuck Lever @ 2009-11-10 23:38 UTC (permalink / raw)
To: argp
Cc: bugzilla-daemon, bugme-daemon, Linux Network Developers,
J. Bruce Fields, Trond Myklebust, Neil Brown, Andrew Morton,
Linux NFS Mailing list
In-Reply-To: <20091110152908.7558a471.akpm@linux-foundation.org>
On Nov 10, 2009, at 6:29 PM, Andrew Morton wrote:
>
> (switched to email. Please respond via emailed reply-to-all, not
> via the
> bugzilla web interface).
>
> On Thu, 5 Nov 2009 10:31:03 GMT
> bugzilla-daemon@bugzilla.kernel.org wrote:
>
>> http://bugzilla.kernel.org/show_bug.cgi?id=14546
>>
>> Summary: Off-by-two stack buffer overflow in function
>> rpc_uaddr2sockaddr() of net/sunrpc/addr.c
>> Product: Networking
>> Version: 2.5
>> Kernel Version: 2.6.32-rc6
>> Platform: All
>> OS/Version: Linux
>> Tree: Mainline
>> Status: NEW
>> Severity: normal
>> Priority: P1
>> Component: Other
>> AssignedTo: acme@ghostprotocols.net
>> ReportedBy: argp@census-labs.com
>> CC: argp@census-labs.com
>> Regression: No
>>
>>
>> There is an off-by-two stack buffer overflow in function
>> rpc_uaddr2sockaddr()
>> of file net/sunrpc/addr.c in the Linux kernel SUNRPC implementation.
>>
>> The function rpc_uaddr2sockaddr() that is used to convert a
>> universal address
>> to a socket address takes as an argument the size_t variable
>> uaddr_len (the
>> length of the universal address string). The stack buffer buf is
>> declared in
>> line 315 to be of size RPCBIND_MAXUADDRLEN. If the passed argument
>> uaddr_len is
>> equal to RPCBIND_MAXUADDRLEN then the check at line 319 passes and
>> then at
>> lines 324 and 325 there are two out-of-bounds assignments:
>>
>> 319 if (uaddr_len > sizeof(buf))
>> 320 return 0;
>> ...
>> 324 buf[uaddr_len] = '\n';
>> 325 buf[uaddr_len + 1] = '\0';
>>
>> To fix it please see the attached patch.
>>
>
> Please don't submit patches via bugzilla.
>
> Please prepare this patch as per Documentation/SubmittingPatches and
> email it to all the recipients of this email, thanks.
>
> --- ./net/sunrpc/addr.c.orig 2009-11-05 11:55:45.000000000 +0200
> +++ ./net/sunrpc/addr.c 2009-11-05 12:09:34.000000000 +0200
> @@ -316,7 +316,7 @@
> unsigned long portlo, porthi;
> unsigned short port;
>
> - if (uaddr_len > sizeof(buf))
> + if (uaddr_len > sizeof(buf) - 2)
> return 0;
Why wouldn't you bump the size of the buffer by two as well?
Otherwise valid universal addresses that are RPCBIND_MAXUADDRLEN bytes
long will fail here.
> memcpy(buf, uaddr, uaddr_len);
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
^ permalink raw reply
* Re: [Bugme-new] [Bug 14546] New: Off-by-two stack buffer overflow in function rpc_uaddr2sockaddr() of net/sunrpc/addr.c
From: Andrew Morton @ 2009-11-10 23:29 UTC (permalink / raw)
To: argp-YZAGAMbGdGKGw+nKnLezzg
Cc: bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
bugme-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
netdev-u79uwXL29TY76Z2rM5mHXA, J. Bruce Fields, Trond Myklebust,
Neil Brown, linux-nfs-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <bug-14546-10286-V0hAGp6uBxO456/isadD/XN4h3HLQggn@public.gmane.org/>
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Thu, 5 Nov 2009 10:31:03 GMT
bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r@public.gmane.org wrote:
> http://bugzilla.kernel.org/show_bug.cgi?id=14546
>
> Summary: Off-by-two stack buffer overflow in function
> rpc_uaddr2sockaddr() of net/sunrpc/addr.c
> Product: Networking
> Version: 2.5
> Kernel Version: 2.6.32-rc6
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: normal
> Priority: P1
> Component: Other
> AssignedTo: acme-f8uhVLnGfZaxAyOMLChx1axOck334EZe@public.gmane.org
> ReportedBy: argp-YZAGAMbGdGKGw+nKnLezzg@public.gmane.org
> CC: argp-YZAGAMbGdGKGw+nKnLezzg@public.gmane.org
> Regression: No
>
>
> There is an off-by-two stack buffer overflow in function rpc_uaddr2sockaddr()
> of file net/sunrpc/addr.c in the Linux kernel SUNRPC implementation.
>
> The function rpc_uaddr2sockaddr() that is used to convert a universal address
> to a socket address takes as an argument the size_t variable uaddr_len (the
> length of the universal address string). The stack buffer buf is declared in
> line 315 to be of size RPCBIND_MAXUADDRLEN. If the passed argument uaddr_len is
> equal to RPCBIND_MAXUADDRLEN then the check at line 319 passes and then at
> lines 324 and 325 there are two out-of-bounds assignments:
>
> 319 if (uaddr_len > sizeof(buf))
> 320 return 0;
> ...
> 324 buf[uaddr_len] = '\n';
> 325 buf[uaddr_len + 1] = '\0';
>
> To fix it please see the attached patch.
>
Please don't submit patches via bugzilla.
Please prepare this patch as per Documentation/SubmittingPatches and
email it to all the recipients of this email, thanks.
--- ./net/sunrpc/addr.c.orig 2009-11-05 11:55:45.000000000 +0200
+++ ./net/sunrpc/addr.c 2009-11-05 12:09:34.000000000 +0200
@@ -316,7 +316,7 @@
unsigned long portlo, porthi;
unsigned short port;
- if (uaddr_len > sizeof(buf))
+ if (uaddr_len > sizeof(buf) - 2)
return 0;
memcpy(buf, uaddr, uaddr_len);
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 04/10] AOE: use rcu to find network device
From: Stephen Hemminger @ 2009-11-10 23:06 UTC (permalink / raw)
To: Ed Cashin; +Cc: davem, ecashin, harvey.harrison, bzolnier, netdev
In-Reply-To: <8ffe0a1df67d13a45a413f40d00dd80a@coraid.com>
On Tue, 10 Nov 2009 15:01:49 -0500
Ed Cashin <ecashin@coraid.com> wrote:
> On Tue Nov 10 13:07:37 EST 2009, shemminger@vyatta.com wrote:
> > This gets rid of another use of read_lock(&dev_base_lock) by using
> > RCU. Also, it only increments the reference count of the device actually
> > used rather than holding and releasing every device
> >
> > Compile tested only.
>
> This function runs once a minute when the aoe driver is loaded,
> if you'd like to test it a bit more.
>
> It looks like there's no dev_put corresponding to the dev_hold
> after the changes.
>
Hmm, looks like AOE actually is not ref counting the network device.
So my patch is incorrect.
As it stands (before my patch), it is UNSAFE. It can decide to queue
packets to a device that is removed out from underneath it causing
reference to freed memory.
Moving the rcu_read_lock up to aoecmd_cfg() would solve that but the
whole driver appears to be unsafe about device refcounting and handling
device removal properly.
It needs to:
1. Get a device ref count when it remembers a device: (ie addif)
2. Install a notifier that looks for device removal events
3. In notifier, remove interface, including flushing all pending
skb's for that device.
This obviously is beyond the scope of the RCU stuff.
^ permalink raw reply
* [PATCH 4/4] venet-macvlan: add new driver to connect a venet to a macvlan netdevice
From: Patrick Mullaney @ 2009-11-10 22:28 UTC (permalink / raw)
To: alacrityvm-devel; +Cc: linux-kernel, kaber, arnd, bridge, evb, netdev
In-Reply-To: <20091110222632.24100.14884.stgit@mimic.site>
This driver implements a macvlan device as a venet device that can
be connected to vbus. Since it is a macvlan device, it provides
a more direct path to the underlying adapter by avoiding the
bridge.
Signed-off-by: Patrick Mullaney <pmullaney@novell.com>
---
drivers/net/vbus-enet.c | 8
include/linux/venet.h | 5
kernel/vbus/devices/venet/Kconfig | 11 +
kernel/vbus/devices/venet/Makefile | 10 -
kernel/vbus/devices/venet/device.c | 10 -
kernel/vbus/devices/venet/macvlan.c | 598 +++++++++++++++++++++++++++++++
kernel/vbus/devices/venet/venetdevice.h | 7
7 files changed, 642 insertions(+), 7 deletions(-)
create mode 100644 kernel/vbus/devices/venet/macvlan.c
diff --git a/drivers/net/vbus-enet.c b/drivers/net/vbus-enet.c
index 29b388f..9985020 100644
--- a/drivers/net/vbus-enet.c
+++ b/drivers/net/vbus-enet.c
@@ -832,6 +832,14 @@ vbus_enet_tx_start(struct sk_buff *skb, struct net_device *dev)
vsg->cookie = (u64)(unsigned long)skb;
vsg->len = skb->len;
+ vsg->phdr.transport = skb_transport_header(skb) - skb->head;
+ vsg->phdr.network = skb_network_header(skb) - skb->head;
+
+ if (skb_mac_header_was_set(skb))
+ vsg->phdr.mac = skb_mac_header(skb) - skb->head;
+ else
+ vsg->phdr.mac = ~0U;
+
if (skb->ip_summed == CHECKSUM_PARTIAL) {
vsg->flags |= VENET_SG_FLAG_NEEDS_CSUM;
vsg->csum.start = skb->csum_start - skb_headroom(skb);
diff --git a/include/linux/venet.h b/include/linux/venet.h
index 0578d79..4e5fdf4 100644
--- a/include/linux/venet.h
+++ b/include/linux/venet.h
@@ -78,6 +78,11 @@ struct venet_sg {
__u16 hdrlen;
__u16 size;
} gso;
+ struct {
+ __u32 mac; /* mac offset */
+ __u32 network; /* network offset */
+ __u32 transport; /* transport offset */
+ } phdr;
__u32 count; /* nr of iovs */
struct venet_iov iov[1];
};
diff --git a/kernel/vbus/devices/venet/Kconfig b/kernel/vbus/devices/venet/Kconfig
index 4f89afb..c3b1ac6 100644
--- a/kernel/vbus/devices/venet/Kconfig
+++ b/kernel/vbus/devices/venet/Kconfig
@@ -20,3 +20,14 @@ config VBUS_VENETTAP
If unsure, say N
+config VBUS_VENETMACV
+ tristate "Virtual-Bus Ethernet MACVLAN Device"
+ depends on VBUS_DEVICES && MACVLAN
+ select VBUS_VENETDEV
+ default n
+ help
+ Provides a vbus based virtual ethernet adapter with a macvlan
+ device as its backend.
+
+ If unsure, say N
+
diff --git a/kernel/vbus/devices/venet/Makefile b/kernel/vbus/devices/venet/Makefile
index 185d825..5bf7cb4 100644
--- a/kernel/vbus/devices/venet/Makefile
+++ b/kernel/vbus/devices/venet/Makefile
@@ -1,7 +1,7 @@
-venet-device-objs += device.o
-ifneq ($(CONFIG_VBUS_VENETTAP),n)
-venet-device-objs += tap.o
-endif
+venet-tap-objs := device.o tap.o
+venet-macvlan-objs := device.o macvlan.o
+
+obj-$(CONFIG_VBUS_VENETTAP) += venet-tap.o
+obj-$(CONFIG_VBUS_VENETMACV) += venet-macvlan.o
-obj-$(CONFIG_VBUS_VENETDEV) += venet-device.o
diff --git a/kernel/vbus/devices/venet/device.c b/kernel/vbus/devices/venet/device.c
index 9fd94ca..a30df94 100644
--- a/kernel/vbus/devices/venet/device.c
+++ b/kernel/vbus/devices/venet/device.c
@@ -776,6 +776,12 @@ venetdev_sg_import(struct venetdev *priv, void *ptr, int len)
return NULL;
}
+ if (vsg->phdr.mac != ~0U)
+ skb_set_mac_header(skb, vsg->phdr.mac);
+
+ skb_set_network_header(skb, vsg->phdr.network);
+ skb_set_transport_header(skb, vsg->phdr.transport);
+
if (vsg->flags & VENET_SG_FLAG_GSO) {
struct skb_shared_info *sinfo = skb_shinfo(skb);
@@ -2250,7 +2256,7 @@ host_mac_show(struct vbus_device *dev, struct vbus_device_attribute *attr,
struct vbus_device_attribute attr_hmac =
__ATTR_RO(host_mac);
-static ssize_t
+ssize_t
cmac_store(struct vbus_device *dev, struct vbus_device_attribute *attr,
const char *buf, size_t count)
{
@@ -2282,7 +2288,7 @@ cmac_store(struct vbus_device *dev, struct vbus_device_attribute *attr,
return count;
}
-static ssize_t
+ssize_t
client_mac_show(struct vbus_device *dev, struct vbus_device_attribute *attr,
char *buf)
{
diff --git a/kernel/vbus/devices/venet/macvlan.c b/kernel/vbus/devices/venet/macvlan.c
new file mode 100644
index 0000000..8724e26
--- /dev/null
+++ b/kernel/vbus/devices/venet/macvlan.c
@@ -0,0 +1,598 @@
+/*
+ * venet-macvlan - A Vbus based 802.x virtual network device that utilizes
+ * a macvlan device as the backend
+ *
+ * Copyright (C) 2009 Novell, Patrick Mullaney <pmullaney@novell.com>
+ *
+ * Based on the venet-tap driver from Gregory Haskins
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ioq.h>
+#include <linux/vbus.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/ktime.h>
+#include <linux/macvlan.h>
+
+#include "venetdevice.h"
+
+#include <linux/in6.h>
+#include <asm/checksum.h>
+
+MODULE_AUTHOR("Patrick Mullaney");
+MODULE_LICENSE("GPL");
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef VENETMACVLAN_DEBUG
+# define PDEBUG(fmt, args...) printk(KERN_DEBUG "venet-tap: " fmt, ## args)
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+#endif
+
+struct venetmacv {
+ struct macvlan_dev mdev;
+ unsigned char ll_ifname[IFNAMSIZ];
+ struct venetdev dev;
+ const struct net_device_ops *macvlan_netdev_ops;
+};
+
+static inline struct venetmacv *conn_to_macv(struct vbus_connection *conn)
+{
+ return container_of(conn, struct venetmacv, dev.vbus.conn);
+}
+
+static inline
+struct venetmacv *venetdev_to_macv(struct venetdev *vdev)
+{
+ return container_of(vdev, struct venetmacv, dev);
+}
+
+static inline
+struct venetmacv *vbusintf_to_macv(struct vbus_device_interface *intf)
+{
+ return container_of(intf, struct venetmacv, dev.vbus.intf);
+}
+
+static inline
+struct venetmacv *vbusdev_to_macv(struct vbus_device *vdev)
+{
+ return container_of(vdev, struct venetmacv, dev.vbus.dev);
+}
+
+int
+venetmacv_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+
+ return venetdev_xmit(skb, &priv->dev);
+}
+
+static int venetmacv_receive(struct sk_buff *skb)
+{
+ struct venetmacv *priv = netdev_priv(skb->dev);
+ int err;
+
+ if (netif_queue_stopped(skb->dev)) {
+ PDEBUG("venetmacv_receive: queue congested - dropping..\n");
+ priv->dev.netif.stats.tx_dropped++;
+ return NET_RX_DROP;
+ }
+ err = skb_linearize(skb);
+ if (unlikely(err)) {
+ printk(KERN_WARNING "venetmacv_receive: linearize failure\n");
+ kfree_skb(skb);
+ return -1;
+ }
+ skb_push(skb, ETH_HLEN);
+ return venetmacv_tx(skb, skb->dev);
+}
+
+static void
+venetmacv_vlink_release(struct vbus_connection *conn)
+{
+ struct venetmacv *macv = conn_to_macv(conn);
+ macvlan_unlink_lowerdev(macv->mdev.dev);
+ venetdev_vlink_release(conn);
+}
+
+static void
+venetmacv_vlink_up(struct venetdev *vdev)
+{
+ struct venetmacv *macv = venetdev_to_macv(vdev);
+ int ret;
+
+ if (vdev->netif.link) {
+ rtnl_lock();
+ ret = macv->macvlan_netdev_ops->ndo_open(vdev->netif.dev);
+ rtnl_unlock();
+ if (ret)
+ printk(KERN_ERR "macvlanopen failed %d!\n", ret);
+ }
+}
+
+static void
+venetmacv_vlink_down(struct venetdev *vdev)
+{
+ struct venetmacv *macv = venetdev_to_macv(vdev);
+ int ret;
+
+ if (vdev->netif.link) {
+ rtnl_lock();
+ ret = macv->macvlan_netdev_ops->ndo_stop(vdev->netif.dev);
+ rtnl_unlock();
+ if (ret)
+ printk(KERN_ERR "macvlan close failed %d!\n", ret);
+ }
+}
+
+int
+venetmacv_vlink_call(struct vbus_connection *conn,
+ unsigned long func,
+ void *data,
+ unsigned long len,
+ unsigned long flags)
+{
+ struct venetdev *priv = conn_to_priv(conn);
+ int ret;
+
+ switch (func) {
+ case VENET_FUNC_LINKUP:
+ venetmacv_vlink_up(priv);
+ break;
+ case VENET_FUNC_LINKDOWN:
+ venetmacv_vlink_down(priv);
+ break;
+ }
+ ret = venetdev_vlink_call(conn, func, data, len, flags);
+ return ret;
+}
+
+static struct vbus_connection_ops venetmacv_vbus_link_ops = {
+ .call = venetmacv_vlink_call,
+ .shm = venetdev_vlink_shm,
+ .close = venetdev_vlink_close,
+ .release = venetmacv_vlink_release,
+};
+
+/*
+ * This is called whenever a driver wants to open our device_interface
+ * for communication. The connection is represented by a
+ * vbus_connection object. It is up to the implementation to decide
+ * if it allows more than one connection at a time. This simple example
+ * does not.
+ */
+
+static int
+venetmacv_intf_connect(struct vbus_device_interface *intf,
+ struct vbus_memctx *ctx,
+ int version,
+ struct vbus_connection **conn)
+{
+ struct venetmacv *macv = vbusintf_to_macv(intf);
+ unsigned long flags;
+ int ret;
+
+ PDEBUG("connect\n");
+
+ if (version != VENET_VERSION)
+ return -EINVAL;
+
+ spin_lock_irqsave(&macv->dev.lock, flags);
+
+ /*
+ * We only allow one connection to this device
+ */
+ if (macv->dev.vbus.opened) {
+ spin_unlock_irqrestore(&macv->dev.lock, flags);
+ return -EBUSY;
+ }
+
+ kobject_get(intf->dev->kobj);
+
+ vbus_connection_init(&macv->dev.vbus.conn, &venetmacv_vbus_link_ops);
+
+ macv->dev.vbus.opened = true;
+ macv->dev.vbus.ctx = ctx;
+
+ vbus_memctx_get(ctx);
+
+ if (!macv->mdev.lowerdev)
+ return -ENXIO;
+
+ ret = macvlan_link_lowerdev(macv->mdev.dev, macv->mdev.lowerdev);
+
+ if (ret) {
+ printk(KERN_ERR "macvlan_link_lowerdev: failed\n");
+ return -ENXIO;
+ }
+
+ macvlan_transfer_operstate(macv->mdev.dev);
+
+ macv->mdev.receive = venetmacv_receive;
+
+ spin_unlock_irqrestore(&macv->dev.lock, flags);
+
+ *conn = &macv->dev.vbus.conn;
+
+ return 0;
+}
+
+static void
+venetmacv_intf_release(struct vbus_device_interface *intf)
+{
+ kobject_put(intf->dev->kobj);
+}
+
+static struct vbus_device_interface_ops venetmacv_device_interface_ops = {
+ .connect = venetmacv_intf_connect,
+ .release = venetmacv_intf_release,
+};
+
+/*
+ * This is called whenever the admin creates a symbolic link between
+ * a bus in /config/vbus/buses and our device. It represents a bus
+ * connection. Your device can chose to allow more than one bus to
+ * connect, or it can restrict it to one bus. It can also choose to
+ * register one or more device_interfaces on each bus that it
+ * successfully connects to.
+ *
+ * This example device only registers a single interface
+ */
+static int
+venetmacv_device_bus_connect(struct vbus_device *dev, struct vbus *vbus)
+{
+ struct venetdev *priv = vdev_to_priv(dev);
+ struct vbus_device_interface *intf = &priv->vbus.intf;
+
+ /* We only allow one bus to connect */
+ if (priv->vbus.connected)
+ return -EBUSY;
+
+ kobject_get(dev->kobj);
+
+ intf->name = "default";
+ intf->type = VENET_TYPE;
+ intf->ops = &venetmacv_device_interface_ops;
+
+ priv->vbus.connected = true;
+
+ /*
+ * Our example only registers one interface. If you need
+ * more, simply call interface_register() multiple times
+ */
+ return vbus_device_interface_register(dev, vbus, intf);
+}
+
+/*
+ * This is called whenever the admin removes the symbolic link between
+ * a bus in /config/vbus/buses and our device.
+ */
+static int
+venetmacv_device_bus_disconnect(struct vbus_device *dev, struct vbus *vbus)
+{
+ struct venetdev *priv = vdev_to_priv(dev);
+ struct vbus_device_interface *intf = &priv->vbus.intf;
+
+ if (!priv->vbus.connected)
+ return -EINVAL;
+
+ vbus_device_interface_unregister(intf);
+
+ priv->vbus.connected = false;
+ kobject_put(dev->kobj);
+
+ return 0;
+}
+
+static void
+venetmacv_device_release(struct vbus_device *dev)
+{
+ struct venetmacv *macv = vbusdev_to_macv(dev);
+
+ if (macv->mdev.lowerdev)
+ dev_put(macv->mdev.lowerdev);
+
+ venetdev_netdev_unregister(&macv->dev);
+ free_netdev(macv->mdev.dev);
+}
+
+
+static struct vbus_device_ops venetmacv_device_ops = {
+ .bus_connect = venetmacv_device_bus_connect,
+ .bus_disconnect = venetmacv_device_bus_disconnect,
+ .release = venetmacv_device_release,
+};
+
+#define VENETMACV_TYPE "venet-macvlan"
+static ssize_t
+ll_ifname_store(struct vbus_device *dev, struct vbus_device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct venetmacv *priv = vbusdev_to_macv(dev);
+ size_t len;
+
+ len = strlen(buf);
+
+ if (len >= IFNAMSIZ)
+ return -EINVAL;
+
+ if (priv->dev.vbus.opened)
+ return -EINVAL;
+
+ strncpy(priv->ll_ifname, buf, count-1);
+
+ if (priv->mdev.lowerdev) {
+ dev_put(priv->mdev.lowerdev);
+ priv->mdev.lowerdev = NULL;
+ }
+
+ priv->mdev.lowerdev = dev_get_by_name(dev_net(priv->mdev.dev),
+ priv->ll_ifname);
+
+ if (!priv->mdev.lowerdev)
+ return -ENXIO;
+
+ return len;
+}
+
+static ssize_t
+ll_ifname_show(struct vbus_device *dev, struct vbus_device_attribute *attr,
+ char *buf)
+{
+ struct venetmacv *priv = vbusdev_to_macv(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", priv->ll_ifname);
+}
+
+static struct vbus_device_attribute attr_ll_ifname =
+__ATTR(ll_ifname, S_IRUGO | S_IWUSR, ll_ifname_show, ll_ifname_store);
+
+ssize_t
+clientmac_store(struct vbus_device *dev, struct vbus_device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct venetmacv *macv = vbusdev_to_macv(dev);
+ int ret;
+
+ ret = attr_cmac.store(dev, attr, buf, count);
+
+ if (ret == count)
+ memcpy(macv->mdev.dev->dev_addr, macv->dev.cmac, ETH_ALEN);
+
+ return ret;
+}
+
+struct vbus_device_attribute attr_clientmac =
+ __ATTR(client_mac, S_IRUGO | S_IWUSR, client_mac_show, clientmac_store);
+
+static struct attribute *attrs[] = {
+ &attr_clientmac.attr,
+ &attr_enabled.attr,
+ &attr_burstthresh.attr,
+ &attr_txmitigation.attr,
+ &attr_ifname.attr,
+ &attr_ll_ifname.attr,
+ NULL,
+};
+
+static struct attribute_group venetmacv_attr_group = {
+ .attrs = attrs,
+};
+
+static int
+venetmacv_netdev_open(struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+ int ret = 0;
+
+ venetdev_open(&priv->dev);
+
+ if (priv->dev.vbus.link) {
+ rtnl_lock();
+ ret = priv->macvlan_netdev_ops->ndo_open(priv->mdev.dev);
+ rtnl_unlock();
+ }
+
+ return ret;
+}
+
+static int
+venetmacv_netdev_stop(struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+ int needs_stop = false;
+ int ret = 0;
+
+ if (priv->dev.netif.link)
+ needs_stop = true;
+
+ venetdev_stop(&priv->dev);
+
+ if (priv->dev.vbus.link && needs_stop) {
+ rtnl_lock();
+ ret = priv->macvlan_netdev_ops->ndo_stop(dev);
+ rtnl_unlock();
+ }
+
+ return ret;
+}
+
+/*
+ * out routine for macvlan
+ */
+
+static int
+venetmacv_out(struct venetdev *vdev, struct sk_buff *skb)
+{
+ struct venetmacv *macv = venetdev_to_macv(vdev);
+ skb->dev = macv->mdev.lowerdev;
+ skb->protocol = eth_type_trans(skb, macv->mdev.lowerdev);
+ skb_push(skb, ETH_HLEN);
+ return macv->macvlan_netdev_ops->ndo_start_xmit(skb, macv->mdev.dev);
+}
+
+static int
+venetmacv_netdev_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+
+ return venetmacv_out(&priv->dev, skb);
+}
+
+static struct net_device_stats *
+venetmacv_netdev_stats(struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+ return venetdev_get_stats(&priv->dev);
+}
+
+static int venetmacv_set_mac_address(struct net_device *dev, void *p)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+ int ret;
+
+ ret = priv->macvlan_netdev_ops->ndo_set_mac_address(dev, p);
+
+ if (!ret)
+ memcpy(priv->dev.cmac, p, ETH_ALEN);
+
+ return ret;
+}
+
+int venetmacv_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+
+ return priv->macvlan_netdev_ops->ndo_change_mtu(dev, new_mtu);
+}
+
+void venetmacv_change_rx_flags(struct net_device *dev, int change)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+
+ priv->macvlan_netdev_ops->ndo_change_rx_flags(dev, change);
+}
+
+void venetmacv_set_multicast_list(struct net_device *dev)
+{
+ struct venetmacv *priv = netdev_priv(dev);
+
+ priv->macvlan_netdev_ops->ndo_set_multicast_list(dev);
+}
+
+static struct net_device_ops venetmacv_netdev_ops = {
+ .ndo_open = venetmacv_netdev_open,
+ .ndo_stop = venetmacv_netdev_stop,
+ .ndo_set_config = venetdev_netdev_config,
+ .ndo_change_mtu = venetmacv_change_mtu,
+ .ndo_set_mac_address = venetmacv_set_mac_address,
+ .ndo_change_rx_flags = venetmacv_change_rx_flags,
+ .ndo_set_multicast_list = venetmacv_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_start_xmit = venetmacv_netdev_tx,
+ .ndo_do_ioctl = venetdev_netdev_ioctl,
+ .ndo_get_stats = venetmacv_netdev_stats,
+};
+
+
+/*
+ * This is called whenever the admin instantiates our devclass via
+ * "mkdir /config/vbus/devices/$(inst)/venet-tap"
+ */
+static int
+venetmacv_device_create(struct vbus_devclass *dc,
+ struct vbus_device **vdev)
+{
+ struct net_device *dev;
+ struct venetmacv *priv;
+ struct vbus_device *_vdev;
+
+ dev = alloc_netdev(sizeof(struct venetmacv), "macvenet%d",
+ macvlan_setup);
+
+ if (!dev)
+ return -ENOMEM;
+
+ priv = netdev_priv(dev);
+ memset(priv, 0, sizeof(*priv));
+
+ spin_lock_init(&priv->dev.lock);
+ random_ether_addr(priv->dev.cmac);
+ memcpy(priv->dev.hmac, priv->dev.cmac, ETH_ALEN);
+
+ /*
+ * vbus init
+ */
+ _vdev = &priv->dev.vbus.dev;
+
+ _vdev->type = VENETMACV_TYPE;
+ _vdev->ops = &venetmacv_device_ops;
+ _vdev->attrs = &venetmacv_attr_group;
+
+ venetdev_init(&priv->dev, dev);
+
+ priv->mdev.dev = dev;
+ priv->dev.netif.out = venetmacv_out;
+
+ priv->macvlan_netdev_ops = dev->netdev_ops;
+ dev->netdev_ops = &venetmacv_netdev_ops;
+
+ *vdev = _vdev;
+
+ return 0;
+}
+
+static struct vbus_devclass_ops venetmacv_devclass_ops = {
+ .create = venetmacv_device_create,
+};
+
+static struct vbus_devclass venetmacv_devclass = {
+ .name = VENETMACV_TYPE,
+ .ops = &venetmacv_devclass_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init venetmacv_init(void)
+{
+ return vbus_devclass_register(&venetmacv_devclass);
+}
+
+static void __exit venetmacv_cleanup(void)
+{
+ vbus_devclass_unregister(&venetmacv_devclass);
+}
+
+module_init(venetmacv_init);
+module_exit(venetmacv_cleanup);
+
diff --git a/kernel/vbus/devices/venet/venetdevice.h b/kernel/vbus/devices/venet/venetdevice.h
index 71c9f0f..1a74723 100644
--- a/kernel/vbus/devices/venet/venetdevice.h
+++ b/kernel/vbus/devices/venet/venetdevice.h
@@ -173,4 +173,11 @@ extern struct vbus_device_attribute attr_ifname;
extern struct vbus_device_attribute attr_txmitigation;
extern struct vbus_device_attribute attr_zcthresh;
+ssize_t cmac_store(struct vbus_device *dev,
+ struct vbus_device_attribute *attr,
+ const char *buf, size_t count);
+ssize_t client_mac_show(struct vbus_device *dev,
+ struct vbus_device_attribute *attr, char *buf);
+
+
#endif
^ permalink raw reply related
* [PATCH 3/4] venetdev: support common venet netdev routines
From: Patrick Mullaney @ 2009-11-10 22:28 UTC (permalink / raw)
To: alacrityvm-devel; +Cc: linux-kernel, kaber, arnd, bridge, evb, netdev
In-Reply-To: <20091110222632.24100.14884.stgit@mimic.site>
This patch breaks out common netdev routines that allow
a device to pass venetdev pointer as opposed to assuming
it is the priv member of the netdevice.
Signed-off-by: Patrick Mullaney <pmullaney@novell.com>
---
kernel/vbus/devices/venet/device.c | 43 ++++++++++++++++++++++++++-----
kernel/vbus/devices/venet/venetdevice.h | 5 ++++
2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/kernel/vbus/devices/venet/device.c b/kernel/vbus/devices/venet/device.c
index d49ba7f..9fd94ca 100644
--- a/kernel/vbus/devices/venet/device.c
+++ b/kernel/vbus/devices/venet/device.c
@@ -228,9 +228,8 @@ venetdev_txq_notify_dec(struct venetdev *priv)
*/
int
-venetdev_netdev_open(struct net_device *dev)
+venetdev_open(struct venetdev *priv)
{
- struct venetdev *priv = netdev_priv(dev);
unsigned long flags;
BUG_ON(priv->netif.link);
@@ -260,7 +259,7 @@ venetdev_netdev_open(struct net_device *dev)
priv->netif.link = true;
if (!priv->vbus.link)
- netif_carrier_off(dev);
+ netif_carrier_off(priv->netif.dev);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -268,9 +267,16 @@ venetdev_netdev_open(struct net_device *dev)
}
int
-venetdev_netdev_stop(struct net_device *dev)
+venetdev_netdev_open(struct net_device *dev)
{
struct venetdev *priv = netdev_priv(dev);
+
+ return venetdev_open(priv);
+}
+
+int
+venetdev_stop(struct venetdev *priv)
+{
unsigned long flags;
int needs_stop = false;
@@ -296,6 +302,14 @@ venetdev_netdev_stop(struct net_device *dev)
return 0;
}
+int
+venetdev_netdev_stop(struct net_device *dev)
+{
+ struct venetdev *priv = netdev_priv(dev);
+
+ return venetdev_stop(priv);
+}
+
/*
* Configuration changes (passed on by ifconfig)
*/
@@ -1541,10 +1555,10 @@ venetdev_apply_backpressure(struct venetdev *priv)
* the netif flow control is still managed by the actual consumer,
* thereby avoiding the creation of an extra servo-loop to the equation.
*/
+
int
-venetdev_netdev_tx(struct sk_buff *skb, struct net_device *dev)
+venetdev_xmit(struct sk_buff *skb, struct venetdev *priv)
{
- struct venetdev *priv = netdev_priv(dev);
struct ioq *ioq = NULL;
unsigned long flags;
@@ -1585,6 +1599,15 @@ flowcontrol:
return NETDEV_TX_BUSY;
}
+int
+venetdev_netdev_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct venetdev *priv = netdev_priv(dev);
+
+ return venetdev_xmit(skb, priv);
+}
+
+
/*
* Ioctl commands
*/
@@ -1599,10 +1622,16 @@ venetdev_netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* Return statistics to the caller
*/
struct net_device_stats *
+venetdev_get_stats(struct venetdev *priv)
+{
+ return &priv->netif.stats;
+}
+
+struct net_device_stats *
venetdev_netdev_stats(struct net_device *dev)
{
struct venetdev *priv = netdev_priv(dev);
- return &priv->netif.stats;
+ return venetdev_get_stats(priv);
}
/*
diff --git a/kernel/vbus/devices/venet/venetdevice.h b/kernel/vbus/devices/venet/venetdevice.h
index 9a60a2e..71c9f0f 100644
--- a/kernel/vbus/devices/venet/venetdevice.h
+++ b/kernel/vbus/devices/venet/venetdevice.h
@@ -142,6 +142,11 @@ int venetdev_netdev_ioctl(struct net_device *dev, struct ifreq *rq,
int cmd);
struct net_device_stats *venetdev_netdev_stats(struct net_device *dev);
+int venetdev_open(struct venetdev *dev);
+int venetdev_stop(struct venetdev *dev);
+int venetdev_xmit(struct sk_buff *skb, struct venetdev *dev);
+struct net_device_stats *venetdev_get_stats(struct venetdev *dev);
+
static inline void venetdev_netdev_unregister(struct venetdev *priv)
{
if (priv->netif.enabled) {
^ permalink raw reply related
* [PATCH 2/4] macvlan: allow in-kernel modules to create and manage macvlan devices
From: Patrick Mullaney @ 2009-11-10 22:27 UTC (permalink / raw)
To: alacrityvm-devel; +Cc: linux-kernel, kaber, arnd, bridge, evb, netdev
In-Reply-To: <20091110222632.24100.14884.stgit@mimic.site>
The macvlan driver didn't allow for creation/deletion of devices
by other in-kernel modules. This patch provides common routines
for both in-kernel and netlink based management. This patch
also enables macvlan device support for gro for lower level
devices that support gro.
Signed-off-by: Patrick Mullaney <pmullaney@novell.com>
---
drivers/net/macvlan.c | 72 +++++++++++++++++++++++++++++++----------------
include/linux/macvlan.h | 6 ++++
2 files changed, 53 insertions(+), 25 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 0a389b8..6b98b26 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -208,7 +208,7 @@ static const struct header_ops macvlan_hard_header_ops = {
.cache_update = eth_header_cache_update,
};
-static int macvlan_open(struct net_device *dev)
+int macvlan_open(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev;
@@ -235,7 +235,7 @@ out:
return err;
}
-static int macvlan_stop(struct net_device *dev)
+int macvlan_stop(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev;
@@ -316,7 +316,7 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
#define MACVLAN_FEATURES \
(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
- NETIF_F_TSO_ECN | NETIF_F_TSO6)
+ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO)
#define MACVLAN_STATE_MASK \
((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -440,7 +440,7 @@ static void macvlan_port_destroy(struct net_device *dev)
kfree(port);
}
-static void macvlan_transfer_operstate(struct net_device *dev)
+void macvlan_transfer_operstate(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
const struct net_device *lowerdev = vlan->lowerdev;
@@ -458,6 +458,7 @@ static void macvlan_transfer_operstate(struct net_device *dev)
netif_carrier_off(dev);
}
}
+EXPORT_SYMBOL_GPL(macvlan_transfer_operstate);
int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
{
@@ -471,11 +472,47 @@ int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
}
EXPORT_SYMBOL_GPL(macvlan_validate);
-int macvlan_newlink(struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+int macvlan_link_lowerdev(struct net_device *dev,
+ struct net_device *lowerdev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct macvlan_port *port;
+ int err = 0;
+
+ if (lowerdev->macvlan_port == NULL) {
+ err = macvlan_port_create(lowerdev);
+ if (err < 0)
+ return err;
+ }
+ port = lowerdev->macvlan_port;
+
+ vlan->lowerdev = lowerdev;
+ vlan->dev = dev;
+ vlan->port = port;
+ vlan->receive = netif_rx;
+
+ macvlan_init(dev);
+
+ list_add_tail(&vlan->list, &port->vlans);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(macvlan_link_lowerdev);
+
+void macvlan_unlink_lowerdev(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvlan_port *port = vlan->port;
+
+ list_del(&vlan->list);
+
+ if (list_empty(&port->vlans))
+ macvlan_port_destroy(port->dev);
+}
+EXPORT_SYMBOL_GPL(macvlan_unlink_lowerdev);
+
+int macvlan_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
struct net_device *lowerdev;
int err;
@@ -502,23 +539,14 @@ int macvlan_newlink(struct net_device *dev,
if (!tb[IFLA_ADDRESS])
random_ether_addr(dev->dev_addr);
- if (lowerdev->macvlan_port == NULL) {
- err = macvlan_port_create(lowerdev);
- if (err < 0)
- return err;
- }
- port = lowerdev->macvlan_port;
-
- vlan->lowerdev = lowerdev;
- vlan->dev = dev;
- vlan->port = port;
- vlan->receive = netif_rx;
+ err = macvlan_link_lowerdev(dev, lowerdev);
+ if (err < 0)
+ return err;
err = register_netdevice(dev);
if (err < 0)
return err;
- list_add_tail(&vlan->list, &port->vlans);
macvlan_transfer_operstate(dev);
return 0;
}
@@ -526,14 +554,8 @@ EXPORT_SYMBOL_GPL(macvlan_newlink);
void macvlan_dellink(struct net_device *dev)
{
- struct macvlan_dev *vlan = netdev_priv(dev);
- struct macvlan_port *port = vlan->port;
-
- list_del(&vlan->list);
+ macvlan_unlink_lowerdev(dev);
unregister_netdevice(dev);
-
- if (list_empty(&port->vlans))
- macvlan_port_destroy(port->dev);
}
EXPORT_SYMBOL_GPL(macvlan_dellink);
diff --git a/include/linux/macvlan.h b/include/linux/macvlan.h
index 3f3c6c3..cf8738a 100644
--- a/include/linux/macvlan.h
+++ b/include/linux/macvlan.h
@@ -24,6 +24,12 @@ struct macvlan_dev {
};
extern int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern int macvlan_link_lowerdev(struct net_device *dev,
+ struct net_device *lowerdev);
+
+extern void macvlan_unlink_lowerdev(struct net_device *dev);
+
+extern void macvlan_transfer_operstate(struct net_device *dev);
extern void macvlan_setup(struct net_device *dev);
^ permalink raw reply related
* [PATCH 1/4] macvlan: derived from Arnd Bergmann's patch for macvtap
From: Patrick Mullaney @ 2009-11-10 22:27 UTC (permalink / raw)
To: alacrityvm-devel; +Cc: linux-kernel, kaber, arnd, bridge, evb, netdev
In-Reply-To: <20091110222632.24100.14884.stgit@mimic.site>
This is in the series because this has not gone upstream yet and
the subsequent patches depend on it. This patch includes only the
basic framework for overriding the receive path and the macvlan header
was moved to allow modules outside of driver/net to use it.
Signed-off-by: Patrick Mullaney <pmullaney@novell.com>
---
drivers/net/macvlan.c | 39 +++++++++++++++------------------------
include/linux/macvlan.h | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 24 deletions(-)
create mode 100644 include/linux/macvlan.h
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 99eed9f..0a389b8 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -30,22 +30,7 @@
#include <linux/if_macvlan.h>
#include <net/rtnetlink.h>
-#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
-
-struct macvlan_port {
- struct net_device *dev;
- struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
- struct list_head vlans;
-};
-
-struct macvlan_dev {
- struct net_device *dev;
- struct list_head list;
- struct hlist_node hlist;
- struct macvlan_port *port;
- struct net_device *lowerdev;
-};
-
+#include <linux/macvlan.h>
static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
const unsigned char *addr)
@@ -135,7 +120,7 @@ static void macvlan_broadcast(struct sk_buff *skb,
else
nskb->pkt_type = PACKET_MULTICAST;
- netif_rx(nskb);
+ vlan->receive(nskb);
}
}
}
@@ -180,11 +165,11 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
- netif_rx(skb);
+ vlan->receive(skb);
return NULL;
}
-static int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev)
+int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
const struct macvlan_dev *vlan = netdev_priv(dev);
unsigned int len = skb->len;
@@ -202,6 +187,7 @@ static int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
return NETDEV_TX_OK;
}
+EXPORT_SYMBOL_GPL(macvlan_start_xmit);
static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
@@ -412,7 +398,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static void macvlan_setup(struct net_device *dev)
+void macvlan_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -423,6 +409,7 @@ static void macvlan_setup(struct net_device *dev)
dev->ethtool_ops = &macvlan_ethtool_ops;
dev->tx_queue_len = 0;
}
+EXPORT_SYMBOL_GPL(macvlan_setup);
static int macvlan_port_create(struct net_device *dev)
{
@@ -472,7 +459,7 @@ static void macvlan_transfer_operstate(struct net_device *dev)
}
}
-static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
+int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
{
if (tb[IFLA_ADDRESS]) {
if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
@@ -482,9 +469,10 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
}
return 0;
}
+EXPORT_SYMBOL_GPL(macvlan_validate);
-static int macvlan_newlink(struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+int macvlan_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct macvlan_port *port;
@@ -524,6 +512,7 @@ static int macvlan_newlink(struct net_device *dev,
vlan->lowerdev = lowerdev;
vlan->dev = dev;
vlan->port = port;
+ vlan->receive = netif_rx;
err = register_netdevice(dev);
if (err < 0)
@@ -533,8 +522,9 @@ static int macvlan_newlink(struct net_device *dev,
macvlan_transfer_operstate(dev);
return 0;
}
+EXPORT_SYMBOL_GPL(macvlan_newlink);
-static void macvlan_dellink(struct net_device *dev)
+void macvlan_dellink(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct macvlan_port *port = vlan->port;
@@ -545,6 +535,7 @@ static void macvlan_dellink(struct net_device *dev)
if (list_empty(&port->vlans))
macvlan_port_destroy(port->dev);
}
+EXPORT_SYMBOL_GPL(macvlan_dellink);
static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
.kind = "macvlan",
diff --git a/include/linux/macvlan.h b/include/linux/macvlan.h
new file mode 100644
index 0000000..3f3c6c3
--- /dev/null
+++ b/include/linux/macvlan.h
@@ -0,0 +1,37 @@
+#ifndef _MACVLAN_H
+#define _MACVLAN_H
+
+#include <linux/netdevice.h>
+#include <linux/netlink.h>
+#include <linux/list.h>
+
+#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
+
+struct macvlan_port {
+ struct net_device *dev;
+ struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
+ struct list_head vlans;
+};
+
+struct macvlan_dev {
+ struct net_device *dev;
+ struct list_head list;
+ struct hlist_node hlist;
+ struct macvlan_port *port;
+ struct net_device *lowerdev;
+
+ int (*receive)(struct sk_buff *skb);
+};
+
+extern int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev);
+
+extern void macvlan_setup(struct net_device *dev);
+
+extern int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]);
+
+extern int macvlan_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[]);
+
+extern void macvlan_dellink(struct net_device *dev);
+
+#endif /* _MACVLAN_H */
^ permalink raw reply related
* [PATCH 0/4] vbus: venet macvlan support
From: Patrick Mullaney @ 2009-11-10 22:27 UTC (permalink / raw)
To: alacrityvm-devel; +Cc: linux-kernel, kaber, arnd, bridge, evb, netdev
(Applies to alacrityvm.git/master:34534534)
This patchset implements a vbus venet device with a
macvlan backend.
These patches allow an alacrityvm guest to send and receive
directly over a macvlan, avoiding the bridge entirely.
This driver inherits all of the benefits of the work done
to date on vbus/venet driver(SAR offloading, zero-copy
in the guest->host path, configurable tx-complete mitigation,
interrupt coalescing at the vbus level). Some of the work to
re-factor and share the common code between venet-tap and
venet-macvlan was done prior because it should be generally
useful to anyone wanting to implement a venet type of device.
Once the driver is built and installed, you may use it
just like you would a venet-tap device. In order to
instantiate a venet-macvlan, there are just two differences
from the procedure to instantiating a venet-tap. In order
to create the venet-macvlan device, just:
echo venet-macvlan > /config/vbus/devices/<device-name>/type
and
echo "lower-devicename" > /sys/vbus/devices/<device-name>/ll_ifname
where lower-devicename is something like eth0, eth1, eth2 etc.
The second step associates the lower-devicename, usually
a physical device, with the venet-macvlan device being created.
This step must be perform prior to enabling the venet-macvlan
device.
After that, a guest can make use of the venet-macvlan in
exactly the same manner as a venet-tap. In fact, the guest
actually sees venet-tap and venet-macvlan as identical
types of the devices on the vbus.
Using the venet-macvlan driver will reduce some overhead by
eliminating the linux bridge from the send and receive
paths. For a lightly loaded network segment and system,
we have measured this to be aproximately 1-3 us per side
depending on what hardware is involved.
Since this driver layered over the macvlan driver, it will
have that same limitations as the macvlan driver. For example,
forwarding between macvlan devices on the same host is not
supported. This driver targeted toward VEPA environments as
described by the 'Edge Virtual Bridging' working group.
---
Patrick Mullaney (4):
venet-macvlan: add new driver to connect a venet to a macvlan netdevice
venetdev: support common venet netdev routines
macvlan: allow in-kernel modules to create and manage macvlan devices
macvlan: derived from Arnd Bergmann's patch for macvtap
drivers/net/macvlan.c | 105 +++--
drivers/net/vbus-enet.c | 8
include/linux/macvlan.h | 43 ++
include/linux/venet.h | 5
kernel/vbus/devices/venet/Kconfig | 11 +
kernel/vbus/devices/venet/Makefile | 10 -
kernel/vbus/devices/venet/device.c | 53 ++-
kernel/vbus/devices/venet/macvlan.c | 598 +++++++++++++++++++++++++++++++
kernel/vbus/devices/venet/venetdevice.h | 12 +
9 files changed, 785 insertions(+), 60 deletions(-)
create mode 100644 include/linux/macvlan.h
create mode 100644 kernel/vbus/devices/venet/macvlan.c
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Trond Myklebust @ 2009-11-10 22:14 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Chris Friesen, netdev, Linux kernel
In-Reply-To: <1257888720.2834.30.camel@achroite.uk.solarflarecom.com>
On Tue, 2009-11-10 at 21:32 +0000, Ben Hutchings wrote:
> On Tue, 2009-11-10 at 15:06 -0600, Chris Friesen wrote:
> > On 11/10/2009 02:26 PM, Trond Myklebust wrote:
> > > Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict the
> > > range used to a safer one. That's what it is for...
>
> Unless I'm much mistaken, that only affects in-kernel SunRPC users.
There shouldn't be that many non-kernel sunrpc users that require
privileged ports.
The exceptions I can think of are
* the 'mount' program, if you are using the legacy binary mount
interface. Use text mounts instead...
* rpc.statd might also use privileged ports when booting the
system when it needs to notify servers of the reboot. You can
set that port number using the '-o' option.
Others? Do any of the NIS services require it?
Trond
^ permalink raw reply
* Re: Possible bug: SO_TIMESTAMPING 2.6.30+
From: Christopher Zimmermann @ 2009-11-10 22:03 UTC (permalink / raw)
Cc: Marcus D. Leech, netdev
In-Reply-To: <20091110091252.1667d27d@pundit>
On Tue, 10 Nov 2009 09:12:52 +0100
Christopher Zimmermann <madroach@zakweb.de> wrote:
> On Mon, 09 Nov 2009 19:40:30 -0500
> "Marcus D. Leech" <mleech@ripnet.com> wrote:
>
>
> > I know that Patrick Ohly has essentially moved on from doing the
> > SO_TIMESTAMPING stuff, so
> > who's maintaining it now?
>
> I worked on it a month ago or so and have a patchset from Patick Ohly
> and some changes by me which fix software timestamping and make the
> ioctl interface to the hardware more flexible (keeping backwards
> compatibility). Patches are attached.
> Still I never tried IPv6 and don't think the patches do anything about
> it.
> It would be nice to know weather software tx timestamps work
> with/without the patches.
>
>
> Christopher
Have a look at commit 51f31cabe3ce5345b51e4a4f82138b38c4d5dc91.
It adds support for SO_TIMESTAMPING in the transport layer, but only
for the ipv4 variants.
Good news is, it does look like it was simple to do the same to
ipv6/udp.c. Have fun.
ip: support for TX timestamps on UDP and RAW sockets
Instructions for time stamping outgoing packets are take from the
socket layer and later copied into the new skb.
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
But only in ipv4/udp.c:
-------------------------------- net/ipv4/udp.c
-------------------------------- index c47c989..4bd178a 100644
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
*sk, struct msghdr *msg, return -EOPNOTSUPP;
ipc.opt = NULL;
+ ipc.shtx.flags = 0;
if (up->pending) {
/*
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
*sk, struct msghdr *msg, ipc.addr = inet->saddr;
ipc.oif = sk->sk_bound_dev_if;
+ err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+ if (err)
+ return err;
if (msg->msg_controllen) {
err = ip_cmsg_send(sock_net(sk), msg, &ipc);
if (err)
^ permalink raw reply
* [PATCH] add HAVE_UNREGISTER_NETDEV_QUEUE define for out-of-tree modules
From: Benjamin LaHaise @ 2009-11-10 22:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Hello,
I have an out of tree network driver (GPL'd) that would like to make use of
the unregister_netdevice_queue interface for bulk unregister of devices.
Add a #define HAVE_UNREGISTER_NETDEV_QUEUE to allow the source to detect
that the kernel supports this.
-ben
Signed-off-by: Benjamin LaHaise <bcrl@lhnet.ca
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 465add6..f9e8e0e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1117,6 +1117,7 @@ extern int dev_close(struct net_device *dev);
extern void dev_disable_lro(struct net_device *dev);
extern int dev_queue_xmit(struct sk_buff *skb);
extern int register_netdevice(struct net_device *dev);
+#define HAVE_UNREGISTER_NETDEV_QUEUE
extern void unregister_netdevice_queue(struct net_device *dev,
struct list_head *head);
extern void unregister_netdevice_many(struct list_head *head);
^ permalink raw reply related
* Re: sunrpc port allocation and IANA reserved list
From: Trond Myklebust @ 2009-11-10 21:58 UTC (permalink / raw)
To: Chris Friesen; +Cc: Ben Hutchings, netdev, Linux kernel
In-Reply-To: <1257887844.3044.24.camel@heimdal.trondhjem.org>
On Wed, 2009-11-11 at 06:17 +0900, Trond Myklebust wrote:
> The people who are trying to run absolutely all IANA registered services
> on a single Linux machine that is also trying to run as an NFS client
> may have a problem, but then again, how many setups do you know who are
> trying to do that?
BTW: Even these setups can be fixed. One way to extend the available
port ranges is to allocate more than one IP address; either through the
use of multiple NICs, or through address aliasing. You can set up the
services to listen on one interface, while setting up your routing
tables to ensure that any outgoing connections to your NFS servers go
through through a different interface.
You could also use virtualised machines to host the services, etc...
Trond
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Chris Friesen @ 2009-11-10 21:54 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Trond Myklebust, netdev, Linux kernel
In-Reply-To: <1257888720.2834.30.camel@achroite.uk.solarflarecom.com>
On 11/10/2009 03:32 PM, Ben Hutchings wrote:
> I'm sure we could afford 128 bytes for a blacklist of privileged ports.
> However, the problem is that there is no API for userland to request
> 'any free privileged port' - it has to just try binding to different
> ports until it finds one available. This means that the kernel can't
> tell whether a process is trying to allocate a specifically assigned
> port or whether the blacklist should be applied.
That's unfortunate. Maybe a bindresvport syscall would make sense, but
that's starting to get bloated. At least for userspace apps netstat
will show who the owner is and it might be possible to clean it up
without rebooting.
For the ports allocated in the kernel via xs_get_random_port() and
xprt_bindresvport() it would be fairly easy to check a blacklist.
Interestingly, the current kernel range starts at 665 because IPMI is
known to use 664. The current glibc range to be tried in bindresvport()
starts at 600, which seems to be a bug waiting to happen.
Chris
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Ben Hutchings @ 2009-11-10 21:42 UTC (permalink / raw)
To: Chuck Lever; +Cc: Chris Friesen, Trond Myklebust, netdev, Linux kernel
In-Reply-To: <212D08D7-AC22-4857-837A-E72B0A11E8DE@oracle.com>
On Tue, 2009-11-10 at 16:34 -0500, Chuck Lever wrote:
> On Nov 10, 2009, at 4:32 PM, Ben Hutchings wrote:
>
> > On Tue, 2009-11-10 at 15:06 -0600, Chris Friesen wrote:
> >> On 11/10/2009 02:26 PM, Trond Myklebust wrote:
[...]
> >>> Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict
> >>> the
> >>> range used to a safer one. That's what it is for...
> >
> > Unless I'm much mistaken, that only affects in-kernel SunRPC users.
> >
> >> What constitutes a "safer range"? IANA has ports assigned
> >> intermittently all the way through the default RPC range. The
> >> largest
> >> unassigned range is 922-988 (since 921 is used by lwresd). If
> >> someone
> >> needs more than 66 ports, how are they supposed to handle it?
> >
> > I'm sure we could afford 128 bytes for a blacklist of privileged
> > ports.
> > However, the problem is that there is no API for userland to request
> > 'any free privileged port' - it has to just try binding to different
> > ports until it finds one available.
>
> bindresvport(3) and bindresvport_sa(3t) ?
These are library calls; they are not an API between userland the
kernel.
> > This means that the kernel can't
> > tell whether a process is trying to allocate a specifically assigned
> > port or whether the blacklist should be applied.
>
> Such a blacklist would have to be managed by glibc or libtirpc.
Right.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [RFC PATCH] net: add dataref destructor to sk_buff
From: Evgeniy Polyakov @ 2009-11-10 21:40 UTC (permalink / raw)
To: Gregory Haskins
Cc: Michael S. Tsirkin, alacrityvm-devel, herbert.xu, linux-kernel,
netdev
In-Reply-To: <4AF9B2A7.3050802@novell.com>
On Tue, Nov 10, 2009 at 01:36:23PM -0500, Gregory Haskins (ghaskins@novell.com) wrote:
> What about things like sendfile()? There has to be *some* way to
> synchronize with the io-completion event, I would think. Whatever that
> is, I'd like to tap into it.
All skb manipulation functions properly maintain data reference
counters, so pages will not be freed until all data is consumed.
But there is no guarantee that data placed in given page will not be
overwritten while page is being held somewhere in the stack.
Putting shared info destructor will allow to get notification, that
given shared info processing is over, i.e. that network stack does not
use data placed in shared info for given skb, but if it was copied or
VFS hold those pages, they may or may not be freed.
--
Evgeniy Polyakov
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Chuck Lever @ 2009-11-10 21:34 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Chris Friesen, Trond Myklebust, netdev, Linux kernel
In-Reply-To: <1257888720.2834.30.camel@achroite.uk.solarflarecom.com>
On Nov 10, 2009, at 4:32 PM, Ben Hutchings wrote:
> On Tue, 2009-11-10 at 15:06 -0600, Chris Friesen wrote:
>> On 11/10/2009 02:26 PM, Trond Myklebust wrote:
>>> On Tue, 2009-11-10 at 12:37 -0600, Chris Friesen wrote:
>>>> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
>>>>> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
>>>>
>>>>>> Given that a userspace application can be stopped and restarted
>>>>>> at any
>>>>>> time, and a sunrpc registration can happen at any time, what is
>>>>>> the
>>>>>> expected mechanism to prevent the kernel from allocating a port
>>>>>> for use
>>>>>> by sunrpc that reserved or well-known?
>>>>>>
>>>>>> Apparently Redhat and Debian have distro-specific ways of
>>>>>> dealing with
>>>>>> this, but is there a standard solution? Should there be?
>>>>>>
>>>>>> The current setup seems suboptimal.
>>>>>
>>>>> I believe both RH and Debian are using the same implementation:
>>>>> <http://cyberelk.net/tim/software/portreserve/>.
>>>>
>>>> That helps with the startup case, but still leaves a possible
>>>> hole if an
>>>> app using a fixed port number is restarted at runtime. During the
>>>> window where nobody is bound to the port, the kernel could randomly
>>>> assign it to someone else.
>>>
>>> Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict
>>> the
>>> range used to a safer one. That's what it is for...
>
> Unless I'm much mistaken, that only affects in-kernel SunRPC users.
>
>> What constitutes a "safer range"? IANA has ports assigned
>> intermittently all the way through the default RPC range. The
>> largest
>> unassigned range is 922-988 (since 921 is used by lwresd). If
>> someone
>> needs more than 66 ports, how are they supposed to handle it?
>
> I'm sure we could afford 128 bytes for a blacklist of privileged
> ports.
> However, the problem is that there is no API for userland to request
> 'any free privileged port' - it has to just try binding to different
> ports until it finds one available.
bindresvport(3) and bindresvport_sa(3t) ?
> This means that the kernel can't
> tell whether a process is trying to allocate a specifically assigned
> port or whether the blacklist should be applied.
Such a blacklist would have to be managed by glibc or libtirpc.
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Ben Hutchings @ 2009-11-10 21:32 UTC (permalink / raw)
To: Chris Friesen; +Cc: Trond Myklebust, netdev, Linux kernel
In-Reply-To: <4AF9D5D1.9040501@nortel.com>
On Tue, 2009-11-10 at 15:06 -0600, Chris Friesen wrote:
> On 11/10/2009 02:26 PM, Trond Myklebust wrote:
> > On Tue, 2009-11-10 at 12:37 -0600, Chris Friesen wrote:
> >> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
> >>> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
> >>
> >>>> Given that a userspace application can be stopped and restarted at any
> >>>> time, and a sunrpc registration can happen at any time, what is the
> >>>> expected mechanism to prevent the kernel from allocating a port for use
> >>>> by sunrpc that reserved or well-known?
> >>>>
> >>>> Apparently Redhat and Debian have distro-specific ways of dealing with
> >>>> this, but is there a standard solution? Should there be?
> >>>>
> >>>> The current setup seems suboptimal.
> >>>
> >>> I believe both RH and Debian are using the same implementation:
> >>> <http://cyberelk.net/tim/software/portreserve/>.
> >>
> >> That helps with the startup case, but still leaves a possible hole if an
> >> app using a fixed port number is restarted at runtime. During the
> >> window where nobody is bound to the port, the kernel could randomly
> >> assign it to someone else.
> >
> > Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict the
> > range used to a safer one. That's what it is for...
Unless I'm much mistaken, that only affects in-kernel SunRPC users.
> What constitutes a "safer range"? IANA has ports assigned
> intermittently all the way through the default RPC range. The largest
> unassigned range is 922-988 (since 921 is used by lwresd). If someone
> needs more than 66 ports, how are they supposed to handle it?
I'm sure we could afford 128 bytes for a blacklist of privileged ports.
However, the problem is that there is no API for userland to request
'any free privileged port' - it has to just try binding to different
ports until it finds one available. This means that the kernel can't
tell whether a process is trying to allocate a specifically assigned
port or whether the blacklist should be applied.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH resent] Documentation: rw_lock lessons learned
From: Paul E. McKenney @ 2009-11-10 21:22 UTC (permalink / raw)
To: William Allen Simpson
Cc: Linux Kernel Developers, Linux Kernel Network Developers,
Eric Dumazet
In-Reply-To: <4AF9C540.5090403@gmail.com>
On Tue, Nov 10, 2009 at 02:55:44PM -0500, William Allen Simpson wrote:
> In recent weeks, two different network projects erroneously
> strayed down the rw_lock path. Update the Documentation
> based upon comments in those threads.
>
> Signed-off-by: William.Allen.Simpson@gmail.com
> ---
> Documentation/spinlocks.txt | 14 ++++++++++++++
> 1 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
> index 619699d..c112052 100644
> --- a/Documentation/spinlocks.txt
> +++ b/Documentation/spinlocks.txt
> @@ -233,4 +233,18 @@ indeed), while write-locks need to protect themselves against interrupts.
>
> Linus
As you might guess, works for me!!!
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> +----
> +
> +The implications of spin_locks on memory are further described in:
> +
> + Documentation/memory-barriers.txt
> + (5) LOCK operations.
> + (6) UNLOCK operations.
> +
> +----
> +
> +We are working hard to remove reader-writer spinlocks (rw_lock) from the
> +network stack, so please don't add a new one. Instead, see:
> +
> + Documentation/RCU/rcu.txt
>
> --
> 1.6.3.3
>
>
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Trond Myklebust @ 2009-11-10 21:17 UTC (permalink / raw)
To: Chris Friesen; +Cc: Ben Hutchings, netdev, Linux kernel
In-Reply-To: <4AF9D5D1.9040501@nortel.com>
On Tue, 2009-11-10 at 15:06 -0600, Chris Friesen wrote:
> On 11/10/2009 02:26 PM, Trond Myklebust wrote:
> > On Tue, 2009-11-10 at 12:37 -0600, Chris Friesen wrote:
> >> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
> >>> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
> >>
> >>>> Given that a userspace application can be stopped and restarted at any
> >>>> time, and a sunrpc registration can happen at any time, what is the
> >>>> expected mechanism to prevent the kernel from allocating a port for use
> >>>> by sunrpc that reserved or well-known?
> >>>>
> >>>> Apparently Redhat and Debian have distro-specific ways of dealing with
> >>>> this, but is there a standard solution? Should there be?
> >>>>
> >>>> The current setup seems suboptimal.
> >>>
> >>> I believe both RH and Debian are using the same implementation:
> >>> <http://cyberelk.net/tim/software/portreserve/>.
> >>
> >> That helps with the startup case, but still leaves a possible hole if an
> >> app using a fixed port number is restarted at runtime. During the
> >> window where nobody is bound to the port, the kernel could randomly
> >> assign it to someone else.
> >
> > Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict the
> > range used to a safer one. That's what it is for...
>
> What constitutes a "safer range"? IANA has ports assigned
> intermittently all the way through the default RPC range. The largest
> unassigned range is 922-988 (since 921 is used by lwresd). If someone
> needs more than 66 ports, how are they supposed to handle it?
Distributions can, and should, set the default to whatever range that
constitutes a broad percentile of their customers, and then leave
instructions on how to change that default for the people who run the
funky setups.
The people who are trying to run absolutely all IANA registered services
on a single Linux machine that is also trying to run as an NFS client
may have a problem, but then again, how many setups do you know who are
trying to do that?
Trond
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Chris Friesen @ 2009-11-10 21:06 UTC (permalink / raw)
To: Trond Myklebust; +Cc: Ben Hutchings, netdev, Linux kernel
In-Reply-To: <1257884799.3044.7.camel@heimdal.trondhjem.org>
On 11/10/2009 02:26 PM, Trond Myklebust wrote:
> On Tue, 2009-11-10 at 12:37 -0600, Chris Friesen wrote:
>> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
>>> On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
>>
>>>> Given that a userspace application can be stopped and restarted at any
>>>> time, and a sunrpc registration can happen at any time, what is the
>>>> expected mechanism to prevent the kernel from allocating a port for use
>>>> by sunrpc that reserved or well-known?
>>>>
>>>> Apparently Redhat and Debian have distro-specific ways of dealing with
>>>> this, but is there a standard solution? Should there be?
>>>>
>>>> The current setup seems suboptimal.
>>>
>>> I believe both RH and Debian are using the same implementation:
>>> <http://cyberelk.net/tim/software/portreserve/>.
>>
>> That helps with the startup case, but still leaves a possible hole if an
>> app using a fixed port number is restarted at runtime. During the
>> window where nobody is bound to the port, the kernel could randomly
>> assign it to someone else.
>
> Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict the
> range used to a safer one. That's what it is for...
What constitutes a "safer range"? IANA has ports assigned
intermittently all the way through the default RPC range. The largest
unassigned range is 922-988 (since 921 is used by lwresd). If someone
needs more than 66 ports, how are they supposed to handle it?
Chris
^ permalink raw reply
* Re: sunrpc port allocation and IANA reserved list
From: Trond Myklebust @ 2009-11-10 20:26 UTC (permalink / raw)
To: Chris Friesen; +Cc: Ben Hutchings, netdev, Linux kernel
In-Reply-To: <4AF9B2CF.6050305@nortel.com>
On Tue, 2009-11-10 at 12:37 -0600, Chris Friesen wrote:
> On 11/10/2009 11:53 AM, Ben Hutchings wrote:
> > On Tue, 2009-11-10 at 11:43 -0600, Chris Friesen wrote:
>
> >> Given that a userspace application can be stopped and restarted at any
> >> time, and a sunrpc registration can happen at any time, what is the
> >> expected mechanism to prevent the kernel from allocating a port for use
> >> by sunrpc that reserved or well-known?
> >>
> >> Apparently Redhat and Debian have distro-specific ways of dealing with
> >> this, but is there a standard solution? Should there be?
> >>
> >> The current setup seems suboptimal.
> >
> > I believe both RH and Debian are using the same implementation:
> > <http://cyberelk.net/tim/software/portreserve/>.
>
> That helps with the startup case, but still leaves a possible hole if an
> app using a fixed port number is restarted at runtime. During the
> window where nobody is bound to the port, the kernel could randomly
> assign it to someone else.
Just use /proc/sys/sunrpc/{max,min}_resvport interface to restrict the
range used to a safer one. That's what it is for...
Trond
^ permalink raw reply
* Re: [PATCH 04/10] AOE: use rcu to find network device
From: Ed Cashin @ 2009-11-10 20:01 UTC (permalink / raw)
To: shemminger, davem, ecashin, harvey.harrison, bzolnier, netdev
In-Reply-To: <20091110175647.409162953@vyatta.com>
On Tue Nov 10 13:07:37 EST 2009, shemminger@vyatta.com wrote:
> This gets rid of another use of read_lock(&dev_base_lock) by using
> RCU. Also, it only increments the reference count of the device actually
> used rather than holding and releasing every device
>
> Compile tested only.
This function runs once a minute when the aoe driver is loaded,
if you'd like to test it a bit more.
It looks like there's no dev_put corresponding to the dev_hold
after the changes.
--
Ed
^ permalink raw reply
* [PATCH resent] Documentation: rw_lock lessons learned
From: William Allen Simpson @ 2009-11-10 19:55 UTC (permalink / raw)
To: Linux Kernel Developers, Linux Kernel Network Developers
Cc: Eric Dumazet, Paul E. McKenney
[-- Attachment #1: Type: text/plain, Size: 314 bytes --]
In recent weeks, two different network projects erroneously
strayed down the rw_lock path. Update the Documentation
based upon comments in those threads.
Signed-off-by: William.Allen.Simpson@gmail.com
---
Documentation/spinlocks.txt | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
[-- Attachment #2: spinlocks.txt.patch --]
[-- Type: text/plain, Size: 639 bytes --]
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index 619699d..c112052 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -233,4 +233,18 @@ indeed), while write-locks need to protect themselves against interrupts.
Linus
+----
+
+The implications of spin_locks on memory are further described in:
+
+ Documentation/memory-barriers.txt
+ (5) LOCK operations.
+ (6) UNLOCK operations.
+
+----
+
+We are working hard to remove reader-writer spinlocks (rw_lock) from the
+network stack, so please don't add a new one. Instead, see:
+
+ Documentation/RCU/rcu.txt
--
1.6.3.3
^ permalink raw reply related
* [PATCH] net: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
From: William Allen Simpson @ 2009-11-10 19:51 UTC (permalink / raw)
To: Linux Kernel Network Developers
[-- Attachment #1: Type: text/plain, Size: 686 bytes --]
Define two symbols needed in both kernel and user space.
Remove old (somewhat incorrect) kernel variant that wasn't used in
most cases. Default should apply to both RMSS and SMSS (RFC2581).
Replace numeric constants with defined symbols.
Stand-alone patch, originally developed for TCPCT.
Signed-off-by: William.Allen.Simpson@gmail.com
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/tcp.h | 6 ++++++
include/net/tcp.h | 3 ---
net/ipv4/tcp_input.c | 4 ++--
net/ipv4/tcp_ipv4.c | 6 +++---
net/ipv4/tcp_minisocks.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
6 files changed, 13 insertions(+), 10 deletions(-)
[-- Attachment #2: TCP_MSSv1.patch --]
[-- Type: text/plain, Size: 4017 bytes --]
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index eeecb85..32d7d77 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -81,6 +81,12 @@ enum {
TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000)
};
+/*
+ * TCP general constants
+ */
+#define TCP_MSS_DEFAULT 536U /* IPv4 (RFC1122, RFC2581) */
+#define TCP_MSS_DESIRED 1220U /* IPv6 (tunneled), EDNS0 (RFC3226) */
+
/* TCP socket options */
#define TCP_NODELAY 1 /* Turn off Nagle's algorithm. */
#define TCP_MAXSEG 2 /* Limit MSS */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 25bf3ba..a413e9f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -62,9 +62,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
#define TCP_MIN_MSS 88U
-/* Minimal RCV_MSS. */
-#define TCP_MIN_RCVMSS 536U
-
/* The least MTU to use for probing */
#define TCP_BASE_MSS 512
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index be0c5bf..cc306ac 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -140,7 +140,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
* "len" is invariant segment length, including TCP header.
*/
len += skb->data - skb_transport_header(skb);
- if (len >= TCP_MIN_RCVMSS + sizeof(struct tcphdr) ||
+ if (len >= TCP_MSS_DEFAULT + sizeof(struct tcphdr) ||
/* If PSH is not set, packet should be
* full sized, provided peer TCP is not badly broken.
* This observation (if it is correct 8)) allows
@@ -411,7 +411,7 @@ void tcp_initialize_rcv_mss(struct sock *sk)
unsigned int hint = min_t(unsigned int, tp->advmss, tp->mss_cache);
hint = min(hint, tp->rcv_wnd / 2);
- hint = min(hint, TCP_MIN_RCVMSS);
+ hint = min(hint, TCP_MSS_DEFAULT);
hint = max(hint, TCP_MIN_MSS);
inet_csk(sk)->icsk_ack.rcv_mss = hint;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f83ac91..0718fde 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -217,7 +217,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (inet->opt)
inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
- tp->rx_opt.mss_clamp = 536;
+ tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT;
/* Socket identity is still unknown (sport may be zero).
* However we set state to SYN-SENT and not releasing socket
@@ -1270,7 +1270,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop_and_free;
tcp_clear_options(&tmp_opt);
- tmp_opt.mss_clamp = 536;
+ tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss;
tcp_parse_options(skb, &tmp_opt, 0, dst);
@@ -1818,7 +1818,7 @@ static int tcp_v4_init_sock(struct sock *sk)
*/
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
tp->snd_cwnd_clamp = ~0;
- tp->mss_cache = 536;
+ tp->mss_cache = TCP_MSS_DEFAULT;
tp->reordering = sysctl_tcp_reordering;
icsk->icsk_ca_ops = &tcp_init_congestion_ops;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index fb68bab..7a42990 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -476,7 +476,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
if (newtp->af_specific->md5_lookup(sk, newsk))
newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
#endif
- if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len)
+ if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len)
newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
newtp->rx_opt.mss_clamp = req->mss;
TCP_ECN_openreq_child(newtp, req);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6951827..b528f75 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1849,7 +1849,7 @@ static int tcp_v6_init_sock(struct sock *sk)
*/
tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
tp->snd_cwnd_clamp = ~0;
- tp->mss_cache = 536;
+ tp->mss_cache = TCP_MSS_DEFAULT;
tp->reordering = sysctl_tcp_reordering;
--
1.6.3.3
^ permalink raw reply related
* [PATCH] s2io: fixing a ethtool test that is broken
From: leitao @ 2009-11-10 19:44 UTC (permalink / raw)
To: netdev; +Cc: sreenivasa.honnur, Breno Leitao
Due commit 4b77b0a2ba27d64f58f16d8d4d48d8319dda36ff, it is not more
possible to pci_restore_state() more than once without calling
pci_save_state() in the middle.
Actually running a ethtool test on s2io makes the card inactive,
and it needs to unload/reload the module to fix.
This patch just save the state just after it restore in order to
keep the old behaviour
Signed-off-by: Breno Leitao <leitao@linux.vnet.ibm.com>
---
drivers/net/s2io.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index ddccf5f..0dd7839 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3494,6 +3494,7 @@ static void s2io_reset(struct s2io_nic *sp)
/* Restore the PCI state saved during initialization. */
pci_restore_state(sp->pdev);
+ pci_save_state(sp->pdev);
pci_read_config_word(sp->pdev, 0x2, &val16);
if (check_pci_device_id(val16) != (u16)PCI_ANY_ID)
break;
--
1.6.0.2
^ 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