* [PATCH] vhost: error handling fix
From: Michael S. Tsirkin @ 2010-09-03 10:25 UTC (permalink / raw)
To: Michael S. Tsirkin, Tejun Heo, Eric Dumazet, Ingo Molnar, kvm,
virtualization@
vhost should set worker to NULL on cgroups attach failure,
so that we won't try to destroy the worker again on close.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, no need to bother with this one unless you really want to -
I'll put it on my tree.
This is a follow up to Eric's patch - fixes error handling in a similar way.
drivers/vhost/vhost.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 7c75dce..666aa36 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -298,6 +298,7 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
return 0;
err_cgroup:
kthread_stop(worker);
+ dev->worker = NULL;
err_worker:
if (dev->mm)
mmput(dev->mm);
--
1.7.2.rc0.14.g41c1c
^ permalink raw reply related
* [PATCH] vhost: fix attach to cgroups regression
From: Michael S. Tsirkin @ 2010-09-05 15:08 UTC (permalink / raw)
To: Michael S. Tsirkin, Tejun Heo, kvm, virtualization, netdev,
linux-kernel
Since 2.6.36-rc1, non-root users of vhost-net fail to attach
if they are in any cgroups. This is a regression, and libvirt
actually uses this functionality, as it runs qemu with reduced
priveledges.
The bug is that when qemu uses vhost, vhost wants to attach
its thread to all cgroups that qemu has. But we got the API backwards,
so a non-priveledged process (qemu) tried to control
the priveledged one (vhost), which fails.
Fix this using the new cgroup_attach_task_all,
and running it from the vhost thread.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, no need to bother with this one unless you really want to -
I'll put it on my tree.
drivers/vhost/vhost.c | 79 +++++++++++++++++++++++++++++++++++-------------
1 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 4b99117..7c75dce 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -60,22 +60,25 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
return 0;
}
+static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn)
+{
+ INIT_LIST_HEAD(&work->node);
+ work->fn = fn;
+ init_waitqueue_head(&work->done);
+ work->flushing = 0;
+ work->queue_seq = work->done_seq = 0;
+}
+
/* Init poll structure */
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
unsigned long mask, struct vhost_dev *dev)
{
- struct vhost_work *work = &poll->work;
-
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
init_poll_funcptr(&poll->table, vhost_poll_func);
poll->mask = mask;
poll->dev = dev;
- INIT_LIST_HEAD(&work->node);
- work->fn = fn;
- init_waitqueue_head(&work->done);
- work->flushing = 0;
- work->queue_seq = work->done_seq = 0;
+ vhost_work_init(&poll->work, fn);
}
/* Start polling a file. We add ourselves to file's wait queue. The caller must
@@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll)
remove_wait_queue(poll->wqh, &poll->wait);
}
-/* Flush any work that has been scheduled. When calling this, don't hold any
- * locks that are also used by the callback. */
-void vhost_poll_flush(struct vhost_poll *poll)
+void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work)
{
- struct vhost_work *work = &poll->work;
unsigned seq;
int left;
int flushing;
- spin_lock_irq(&poll->dev->work_lock);
+ spin_lock_irq(&dev->work_lock);
seq = work->queue_seq;
work->flushing++;
- spin_unlock_irq(&poll->dev->work_lock);
+ spin_unlock_irq(&dev->work_lock);
wait_event(work->done, ({
- spin_lock_irq(&poll->dev->work_lock);
+ spin_lock_irq(&dev->work_lock);
left = seq - work->done_seq <= 0;
- spin_unlock_irq(&poll->dev->work_lock);
+ spin_unlock_irq(&dev->work_lock);
left;
}));
- spin_lock_irq(&poll->dev->work_lock);
+ spin_lock_irq(&dev->work_lock);
flushing = --work->flushing;
- spin_unlock_irq(&poll->dev->work_lock);
+ spin_unlock_irq(&dev->work_lock);
BUG_ON(flushing < 0);
}
-void vhost_poll_queue(struct vhost_poll *poll)
+/* Flush any work that has been scheduled. When calling this, don't hold any
+ * locks that are also used by the callback. */
+void vhost_poll_flush(struct vhost_poll *poll)
+{
+ vhost_work_flush(poll->dev, &poll->work);
+}
+
+static inline void vhost_work_queue(struct vhost_dev *dev,
+ struct vhost_work *work)
{
- struct vhost_dev *dev = poll->dev;
- struct vhost_work *work = &poll->work;
unsigned long flags;
spin_lock_irqsave(&dev->work_lock, flags);
@@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll)
spin_unlock_irqrestore(&dev->work_lock, flags);
}
+void vhost_poll_queue(struct vhost_poll *poll)
+{
+ vhost_work_queue(poll->dev, &poll->work);
+}
+
static void vhost_vq_reset(struct vhost_dev *dev,
struct vhost_virtqueue *vq)
{
@@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
return dev->mm == current->mm ? 0 : -EPERM;
}
+struct vhost_attach_cgroups_struct {
+ struct vhost_work work;
+ struct task_struct *owner;
+ int ret;
+};
+
+static void vhost_attach_cgroups_work(struct vhost_work *work)
+{
+ struct vhost_attach_cgroups_struct *s;
+ s = container_of(work, struct vhost_attach_cgroups_struct, work);
+ s->ret = cgroup_attach_task_all(s->owner, current);
+}
+
+static int vhost_attach_cgroups(struct vhost_dev *dev)
+{
+ struct vhost_attach_cgroups_struct attach;
+ attach.owner = current;
+ vhost_work_init(&attach.work, vhost_attach_cgroups_work);
+ vhost_work_queue(dev, &attach.work);
+ vhost_work_flush(dev, &attach.work);
+ return attach.ret;
+}
+
/* Caller should have device mutex */
static long vhost_dev_set_owner(struct vhost_dev *dev)
{
@@ -255,10 +289,11 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
}
dev->worker = worker;
- err = cgroup_attach_task_current_cg(worker);
+ wake_up_process(worker); /* avoid contributing to loadavg */
+
+ err = vhost_attach_cgroups(dev);
if (err)
goto err_cgroup;
- wake_up_process(worker); /* avoid contributing to loadavg */
return 0;
err_cgroup:
--
1.7.2.rc0.14.g41c1c
^ permalink raw reply related
* Re: [PATCH 02/14] virtio: console: Remove control vq data only if using multiport support
From: Rusty Russell @ 2010-09-06 8:29 UTC (permalink / raw)
To: Amit Shah; +Cc: Virtualization List
In-Reply-To: <c7259c88e3dc036806629cd31f08e8b54fa1c345.1283430900.git.amit.shah@redhat.com>
On Thu, 2 Sep 2010 10:11:41 pm Amit Shah wrote:
> If a portdev isn't using multiport support, it won't have any control vq
> data to remove.
>
> Signed-off-by: Amit Shah <amit.shah@redhat.com>
So previously it would crash if it was ever removed? If so, it'd be
nice to see that in the patch description :)
Thanks,
Rusty.
^ permalink raw reply
* Re: [PATCH 3/3] virtio: console: Send SIGIO in case of port unplug
From: Rusty Russell @ 2010-09-06 9:21 UTC (permalink / raw)
To: Amit Shah; +Cc: Virtualization List
In-Reply-To: <04e7f90d7eed7f18c9f0cae4de96253d0a8dc532.1283433264.git.amit.shah@redhat.com>
On Thu, 2 Sep 2010 10:47:54 pm Amit Shah wrote:
> If a port has registered for SIGIO signals, let the application
> know that the port is getting unplugged.
>
> Signed-off-by: Amit Shah <amit.shah@redhat.com>
Thanks Amit, these patches were really well organized and nice to read.
Applied them all...
Rusty.
^ permalink raw reply
* Re: [PATCH 02/14] virtio: console: Remove control vq data only if using multiport support
From: Amit Shah @ 2010-09-06 10:22 UTC (permalink / raw)
To: Rusty Russell; +Cc: Virtualization List
In-Reply-To: <201009061759.40423.rusty@rustcorp.com.au>
On (Mon) Sep 06 2010 [17:59:39], Rusty Russell wrote:
> On Thu, 2 Sep 2010 10:11:41 pm Amit Shah wrote:
> > If a portdev isn't using multiport support, it won't have any control vq
> > data to remove.
> >
> > Signed-off-by: Amit Shah <amit.shah@redhat.com>
>
> So previously it would crash if it was ever removed? If so, it'd be
> nice to see that in the patch description :)
Well, yeah. If any module remove or port / device remove was performed
earlier, there would be crashes in multiple places (as noted in the
0/14) message. I didn't want to scare away people by repeating it for
each patch ;-)
You're right, though, I should've mentioned it. The 0/N message gets
lost and the commit history won't reflect that info.
Thanks for picking them up!
Amit
^ permalink raw reply
* Re: Using virtio as a physical (wire-level) transport
From: Michael S. Tsirkin @ 2010-09-06 11:19 UTC (permalink / raw)
To: Alexander Graf
Cc: netdev@vger.kernel.org, virtualization@lists.linux-foundation.org,
Zang Roy, Ira W. Snyder
In-Reply-To: <4C336074-FC8C-4BDF-B945-5295133CDB38@suse.de>
On Sat, Aug 14, 2010 at 07:34:19AM -0400, Alexander Graf wrote:
> I'd vote for defining virtio v2 that makes everything LE. Maybe we
> could even have an LE capability with a grace period of phasing out
> non-LE capable hosts and guests.
So there are multiple ideas floating for modifying the ring,
and together they might warrant virtio2.
This includes removing available ring, publishing consumer indexes,
possibly some interrupt mitigation ideas, and we can put
endian-ness there.
--
MST
^ permalink raw reply
* [GIT PULL net-2.6] vhost-net: 2.6.36 regression fixes
From: Michael S. Tsirkin @ 2010-09-06 11:36 UTC (permalink / raw)
To: David Miller; +Cc: kvm, virtualization, netdev, linux-kernel
David,
The following tree includes more regression fixes for vhost-net
in 2.6.36. It is on top of net-2.6.
Please merge it for 2.6.36.
Thanks!
The following changes since commit 0b5d404e349c0236b11466c0a4785520c0be6982:
pkt_sched: Fix lockdep warning on est_tree_lock in gen_estimator (2010-09-02 13:22:11 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost-net
Michael S. Tsirkin (3):
cgroups: fix API thinko
vhost: fix attach to cgroups regression
vhost: error handling fix
drivers/vhost/vhost.c | 80 ++++++++++++++++++++++++++++++++++-------------
include/linux/cgroup.h | 11 ++++++-
kernel/cgroup.c | 9 +++--
3 files changed, 73 insertions(+), 27 deletions(-)
--
MST
^ permalink raw reply
* [PATCH 1/1] staging: hv: Convert vmbus driver interface function pointer table to constant
From: Haiyang Zhang @ 2010-09-08 20:29 UTC (permalink / raw)
To: 'linux-kernel@vger.kernel.org',
'devel@driverdev.osuosl.org',
"'virtualization@lists.osdl.org'" <virtualiz>
From: Haiyang Zhang <haiyangz@microsoft.com>
Convert vmbus driver interface function pointer table to constant
The vmbus interface functions are assigned to a constant - vmbus_ops.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
---
drivers/staging/hv/TODO | 2 --
drivers/staging/hv/channel_interface.c | 29 +++++++++++++++--------------
drivers/staging/hv/channel_interface.h | 2 --
drivers/staging/hv/vmbus.c | 9 ---------
drivers/staging/hv/vmbus_api.h | 4 +++-
drivers/staging/hv/vmbus_drv.c | 4 +---
6 files changed, 19 insertions(+), 31 deletions(-)
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index 66a89c8..582fd4a 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -2,8 +2,6 @@ TODO:
- fix remaining checkpatch warnings and errors
- audit the vmbus to verify it is working properly with the
driver model
- - convert vmbus driver interface function pointer tables
- to constant, a.k.a vmbus_ops
- see if the vmbus can be merged with the other virtual busses
in the kernel
- audit the network driver
diff --git a/drivers/staging/hv/channel_interface.c b/drivers/staging/hv/channel_interface.c
index d9f51ac..3f6a1cb 100644
--- a/drivers/staging/hv/channel_interface.c
+++ b/drivers/staging/hv/channel_interface.c
@@ -97,20 +97,6 @@ static int IVmbusChannelTeardownGpadl(struct hv_device *device, u32 GpadlHandle)
}
-void GetChannelInterface(struct vmbus_channel_interface *iface)
-{
- iface->Open = IVmbusChannelOpen;
- iface->Close = IVmbusChannelClose;
- iface->SendPacket = IVmbusChannelSendPacket;
- iface->SendPacketPageBuffer = IVmbusChannelSendPacketPageBuffer;
- iface->SendPacketMultiPageBuffer =
- IVmbusChannelSendPacketMultiPageBuffer;
- iface->RecvPacket = IVmbusChannelRecvPacket;
- iface->RecvPacketRaw = IVmbusChannelRecvPacketRaw;
- iface->EstablishGpadl = IVmbusChannelEstablishGpadl;
- iface->TeardownGpadl = IVmbusChannelTeardownGpadl;
- iface->GetInfo = GetChannelInfo;
-}
void GetChannelInfo(struct hv_device *device, struct hv_device_info *info)
{
@@ -150,3 +136,18 @@ void GetChannelInfo(struct hv_device *device, struct hv_device_info *info)
info->Outbound.BytesAvailToRead = debugInfo.Outbound.BytesAvailToRead;
info->Outbound.BytesAvailToWrite = debugInfo.Outbound.BytesAvailToWrite;
}
+
+
+/* vmbus interface function pointer table */
+const struct vmbus_channel_interface vmbus_ops = {
+ .Open = IVmbusChannelOpen,
+ .Close = IVmbusChannelClose,
+ .SendPacket = IVmbusChannelSendPacket,
+ .SendPacketPageBuffer = IVmbusChannelSendPacketPageBuffer,
+ .SendPacketMultiPageBuffer = IVmbusChannelSendPacketMultiPageBuffer,
+ .RecvPacket = IVmbusChannelRecvPacket,
+ .RecvPacketRaw = IVmbusChannelRecvPacketRaw,
+ .EstablishGpadl = IVmbusChannelEstablishGpadl,
+ .TeardownGpadl = IVmbusChannelTeardownGpadl,
+ .GetInfo = GetChannelInfo,
+};
diff --git a/drivers/staging/hv/channel_interface.h b/drivers/staging/hv/channel_interface.h
index 6acaf6c..ec88219 100644
--- a/drivers/staging/hv/channel_interface.h
+++ b/drivers/staging/hv/channel_interface.h
@@ -27,8 +27,6 @@
#include "vmbus_api.h"
-void GetChannelInterface(struct vmbus_channel_interface *ChannelInterface);
-
void GetChannelInfo(struct hv_device *Device,
struct hv_device_info *DeviceInfo);
diff --git a/drivers/staging/hv/vmbus.c b/drivers/staging/hv/vmbus.c
index ca1e18a..db2afa3 100644
--- a/drivers/staging/hv/vmbus.c
+++ b/drivers/staging/hv/vmbus.c
@@ -61,14 +61,6 @@ static void VmbusGetChannelOffers(void)
}
/*
- * VmbusGetChannelInterface - Get the channel interface
- */
-static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
-{
- GetChannelInterface(Interface);
-}
-
-/*
* VmbusGetChannelInfo - Get the device info for the specified device object
*/
static void VmbusGetChannelInfo(struct hv_device *DeviceObject,
@@ -279,7 +271,6 @@ int VmbusInitialize(struct hv_driver *drv)
driver->OnMsgDpc = VmbusOnMsgDPC;
driver->OnEventDpc = VmbusOnEventDPC;
driver->GetChannelOffers = VmbusGetChannelOffers;
- driver->GetChannelInterface = VmbusGetChannelInterface;
driver->GetChannelInfo = VmbusGetChannelInfo;
/* Hypervisor initialization...setup hypercall page..etc */
diff --git a/drivers/staging/hv/vmbus_api.h b/drivers/staging/hv/vmbus_api.h
index 4275be3..7f3d7dc 100644
--- a/drivers/staging/hv/vmbus_api.h
+++ b/drivers/staging/hv/vmbus_api.h
@@ -129,6 +129,9 @@ struct vmbus_channel_interface {
void (*GetInfo)(struct hv_device *dev, struct hv_device_info *devinfo);
};
+extern const struct vmbus_channel_interface vmbus_ops;
+
+
/* Base driver object */
struct hv_driver {
const char *name;
@@ -183,7 +186,6 @@ struct vmbus_driver {
void (*OnEventDpc)(struct hv_driver *driver);
void (*GetChannelOffers)(void);
- void (*GetChannelInterface)(struct vmbus_channel_interface *i);
void (*GetChannelInfo)(struct hv_device *dev,
struct hv_device_info *devinfo);
};
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 092f02e..ad29887 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -458,9 +458,7 @@ EXPORT_SYMBOL(vmbus_child_driver_unregister);
*/
void vmbus_get_interface(struct vmbus_channel_interface *interface)
{
- struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-
- vmbus_drv_obj->GetChannelInterface(interface);
+ *interface = vmbus_ops;
}
EXPORT_SYMBOL(vmbus_get_interface);
--
1.6.3.2
^ permalink raw reply related
* Re: [PATCH 1/1] staging: hv: Convert vmbus driver interface function pointer table to constant
From: Greg KH @ 2010-09-08 22:44 UTC (permalink / raw)
To: Haiyang Zhang
Cc: 'linux-kernel@vger.kernel.org',
'devel@driverdev.osuosl.org',
'virtualization@lists.osdl.org', Hank Janssen
In-Reply-To: <1FB5E1D5CA062146B38059374562DF72854C92E8@TK5EX14MBXC130.redmond.corp.microsoft.com>
On Wed, Sep 08, 2010 at 08:29:45PM +0000, Haiyang Zhang wrote:
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> Convert vmbus driver interface function pointer table to constant
> The vmbus interface functions are assigned to a constant - vmbus_ops.
You also remove a function pointer in this patch, why? Please break up
the patch into logical parts, one patch, one thing.
This looks like it should be 2 patches, right?
thanks,
greg k-h
^ permalink raw reply
* RE: [PATCH 1/1] staging: hv: Convert vmbus driver interface function pointer table to constant
From: Haiyang Zhang @ 2010-09-09 14:53 UTC (permalink / raw)
To: Greg KH
Cc: 'linux-kernel@vger.kernel.org',
'devel@driverdev.osuosl.org',
'virtualization@lists.osdl.org', Hank Janssen
> From: Greg KH [mailto:gregkh@suse.de]
> Sent: Wednesday, September 08, 2010 6:44 PM
> > Convert vmbus driver interface function pointer table to constant
> > The vmbus interface functions are assigned to a constant - vmbus_ops.
>
> You also remove a function pointer in this patch, why? Please break up
> the patch into logical parts, one patch, one thing.
>
> This looks like it should be 2 patches, right?
Because the vmbus interface function pointer table is converted to a
constant variable -- vmbus_ops, the function GetChannelInterface(),
VmbusGetChannelInterface() and pointer GetChannelInterface are no longer
in use. The deprecated function's work is done by the initialization of
the newly added constant variable vmbus_ops.
I created the new constant variable vmbus_ops and removed the deprecated
function pointer GetChannelInterface in one patch.
Thanks,
- Haiyang
^ permalink raw reply
* Re: [GIT PULL net-2.6] vhost-net: 2.6.36 regression fixes
From: David Miller @ 2010-09-10 5:00 UTC (permalink / raw)
To: mst; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20100906113606.GA16143@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 6 Sep 2010 14:36:06 +0300
> The following tree includes more regression fixes for vhost-net
> in 2.6.36. It is on top of net-2.6.
> Please merge it for 2.6.36.
Pulled, thanks Michael.
^ permalink raw reply
* RE: Virtualization Digest, Vol 60, Issue 17
From: Arpit Patel @ 2010-09-10 17:08 UTC (permalink / raw)
To: virtualization@lists.linux-foundation.org
In-Reply-To: <mailman.124.1282750903.26161.virtualization@lists.linux-foundation.org>
Hi,
Can someone please point me to where I can find this early version of the IEEE802.1Qbg implementation? When I downloaded the 0.9.38 version of lldpad, it does not have the latest set of code mentioned below.
Thanks.
Arpit.
-----Original Message-----
From: virtualization-bounces@lists.linux-foundation.org [mailto:virtualization-bounces@lists.linux-foundation.org] On Behalf Of virtualization-request@lists.linux-foundation.org
Sent: Wednesday, August 25, 2010 8:42 AM
To: virtualization@lists.linux-foundation.org
Subject: Virtualization Digest, Vol 60, Issue 17
Send Virtualization mailing list submissions to
virtualization@lists.linux-foundation.org
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.linux-foundation.org/mailman/listinfo/virtualization
or, via email, send a message with subject or body 'help' to
virtualization-request@lists.linux-foundation.org
You can reach the person managing the list at
virtualization-owner@lists.linux-foundation.org
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Virtualization digest..."
Today's Topics:
1. [PATCH 01/10] consolidation of MIN and MAX macros in common.h
(Jens Osterkamp)
2. implementation of IEEE 802.1Qbg in lldpad (Jens Osterkamp)
3. [PATCH 02/10] implementation of IEEE 802.1Qbg in lldpad, part
1 (Jens Osterkamp)
----------------------------------------------------------------------
Message: 1
Date: Wed, 25 Aug 2010 14:27:33 +0200
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Subject: [PATCH 01/10] consolidation of MIN and MAX macros in common.h
To: e1000-eedc@lists.sourceforge.net,
virtualization@lists.linux-foundation.org, evb@yahoogroups.com
Cc: chrisw@redhat.com, Jens Osterkamp <jens@linux.vnet.ibm.com>
Message-ID:
<1282739262-14968-2-git-send-email-jens@linux.vnet.ibm.com>
This patch consolidates a modified version of the already existing MIN
macro in lldpad to include/common.h and add a MAX macro.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
---
include/common.h | 14 ++++++++++++++
include/dcb_protocol.h | 4 ----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/include/common.h b/include/common.h
index 01746ea..ab07dc2 100644
--- a/include/common.h
+++ b/include/common.h
@@ -387,4 +387,18 @@ typedef int socklen_t;
const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len);
+#define MIN(x,y) \
+ ({ \
+ typeof (x) __x = (x); \
+ typeof (y) __y = (y); \
+ __x < __y ? __x : __y; \
+ })
+
+#define MAX(x,y) \
+ ({ \
+ typeof (x) __x = (x); \
+ typeof (y) __y = (y); \
+ __x > __y ? __x : __y; \
+ })
+
#endif /* COMMON_H */
diff --git a/include/dcb_protocol.h b/include/dcb_protocol.h
index 63e2d3c..d7127f5 100644
--- a/include/dcb_protocol.h
+++ b/include/dcb_protocol.h
@@ -58,10 +58,6 @@ typedef enum {
#define DUP_DCBX_TLV_LLINK 0x0020
#define TOO_MANY_NGHBRS 0x0040
-//#ifndef min /*todo: change to min()
- #define MIN(x, y) ((x) < (y) ? x : y)
-//#endif
-
#define INIT_DCB_OUI {0x00,0x1b,0x21}
int add_adapter(char *device_name);
--
1.7.1
------------------------------
Message: 2
Date: Wed, 25 Aug 2010 14:27:32 +0200
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Subject: implementation of IEEE 802.1Qbg in lldpad
To: e1000-eedc@lists.sourceforge.net,
virtualization@lists.linux-foundation.org, evb@yahoogroups.com
Cc: chrisw@redhat.com
Message-ID:
<1282739262-14968-1-git-send-email-jens@linux.vnet.ibm.com>
Hi,
this set of patches contains the initial implementation of the IEEE 802.1Qbg
standard: code for the exchange of EVB TLVs in LLDP frames to negotiate VSI
capabalities as well as VDP VSI TLVs between a host with virtual machines
and an adjacent switch.
It supports setting the parameters of the TLV exchange from the command
line using lldptool.
VDP profiles consisting of mode,mgrid,typeid,typeidversion,instanceid,mac,vlan
can be given to lldpad with lldptool or sent to lldpad via netlink messages from
the kernel or another program, e.g. libvirt.
VDP profiles are processed through the VDP/VSI and ECP state machines and
sent out in ECP frames.
ACK frames are received and processed through ECP and VDP/VSI state machines.
It implements a VDP bridge role for a port together with a lldptool command to
switch a port to the bridge role.
The patches have been rebased to lldpad 0.9.38 and still contain code to log
low-level protocol activity more verbosely than necessary.
In comparison to the last posted series, several changes have been made:
- all EVB TLV patches have been folded into one
- ECP and VDP implementation now only consists of 3 patches: ECP, VDP and VDP
commandline interface
- the protocol specific ecp structure has been moved away from the general
port structure
- the non-standard ECP_TX_IDLE state has been removed from the ECP TX state
machine which causes ecp frames to be sent out immediately to allow sequence
synchronization
- VDP subtype has changed from 0 to 2
- some network byte order in the VSI tlv have been fixed
- vdp config variables are now saved in subsection "vdp" under the interface
in lldpad.conf
- some compiler warnings have been fixed
- many other small bug fixes
For more information about lldpad take a look at
http://sourceforge.net/projects/e1000/files/DCB%20Tools/lldpad/
Please review and comment.
Thanks !
Jens
------------------------------
Message: 3
Date: Wed, 25 Aug 2010 14:27:34 +0200
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Subject: [PATCH 02/10] implementation of IEEE 802.1Qbg in lldpad, part
1
To: e1000-eedc@lists.sourceforge.net,
virtualization@lists.linux-foundation.org, evb@yahoogroups.com
Cc: chrisw@redhat.com, Jens Osterkamp <jens@linux.vnet.ibm.com>
Message-ID:
<1282739262-14968-3-git-send-email-jens@linux.vnet.ibm.com>
This patch contains the first part of an initial implementation of the
IEEE 802.1Qbg standard: it implements code for the exchange of EVB
capabilities between a host with virtual machines and an adjacent switch.
For this it adds a new EVB TLV to LLDP.
Exchange of EVB TLV may be enabled or disabled on a per port basis.
Information about the information negotiated by the protocol can be
queried on the commandline with lldptool.
This patch adds support for querying and setting parameters used in
the exchange of EVB TLV messages.
The parameters that can be set are:
- forwarding mode
- host protocol capabilities (RTE, ECP, VDP)
- no. of supported VSIs
- retransmission timer exponent (RTE)
The parameters are implemented as a local policy: all frames received by
an adjacent switch are validated against this policy and taken over where
appropriate. Negotiated parameters are stored in lldpads config, picked up
again and used at the next start.
The patch applies to lldpad 0.9.38 and still contains code to log protocol
activity more verbosely than it would be necessary in the final version.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
---
Makefile.am | 10 +-
include/lldp.h | 19 ++
include/lldp_evb.h | 80 ++++++
include/lldp_evb_clif.h | 51 ++++
include/lldp_evb_cmds.h | 31 +++
include/lldp_tlv.h | 1 +
lldp_evb.c | 658 +++++++++++++++++++++++++++++++++++++++++++++++
lldp_evb_clif.c | 226 ++++++++++++++++
lldp_evb_cmds.c | 512 ++++++++++++++++++++++++++++++++++++
lldpad.c | 2 +
lldptool.c | 2 +
11 files changed, 1588 insertions(+), 4 deletions(-)
create mode 100644 include/lldp_evb.h
create mode 100644 include/lldp_evb_clif.h
create mode 100644 include/lldp_evb_cmds.h
create mode 100644 lldp_evb.c
create mode 100644 lldp_evb_clif.c
create mode 100644 lldp_evb_cmds.c
diff --git a/Makefile.am b/Makefile.am
index 743e16f..d59a6fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,7 +37,7 @@ lldpad_include_HEADERS = include/dcb_types.h include/dcbtool.h \
include/dcb_osdep.h include/clif.h include/lldp_dcbx_cmds.h include/common.h \
include/lldpad.h include/os.h include/includes.h include/lldp_mand_cmds.h \
include/clif_msgs.h include/lldp_basman_cmds.h include/lldp_8023_cmds.h \
-include/lldp_med_cmds.h include/lldp_dcbx_cfg.h
+include/lldp_med_cmds.h include/lldp_dcbx_cfg.h include/lldp_evb_cmds.h
noinst_HEADERS = include/config.h include/ctrl_iface.h \
include/dcb_driver_if_types.h include/dcb_driver_interface.h \
@@ -47,7 +47,7 @@ include/event_iface.h include/messages.h include/parse_cli.h include/version.h \
include/lldptool_cli.h include/list.h \
include/lldp_mand_clif.h include/lldp_basman_clif.h include/lldp_med_clif.h \
include/lldp_8023_clif.h include/lldp_dcbx_clif.h include/lldptool.h \
-include/lldp_rtnl.h
+include/lldp_rtnl.h include/lldp_evb_clif.h
lldpad_SOURCES = lldpad.c config.c drv_cfg.c ctrl_iface.c event_iface.c eloop.c \
common.c os_unix.c lldp_dcbx_cmds.c log.c lldpad_shm.c \
@@ -62,10 +62,12 @@ lldp_dcbx_cfg.c include/lldp_dcbx_cfg.h \
lldp_util.c include/lldp_util.h \
lldp_mand.c include/lldp_mand.h \
lldp_mand_cmds.c lldp_basman_cmds.c lldp_8023_cmds.c lldp_med_cmds.c \
+lldp_evb_cmds.c \
lldp_tlv.c include/lldp_tlv.h \
lldp_basman.c include/lldp_basman.h \
lldp_med.c include/lldp_med.h \
-lldp_8023.c include/lldp_8023.h
+lldp_8023.c include/lldp_8023.h \
+lldp_evb.c include/lldp_evb.h
@@ -74,7 +76,7 @@ $(lldpad_include_HEADERS) $(noinst_HEADERS)
lldptool_SOURCES = lldptool.c clif.c lldptool_cmds.c common.c os_unix.c \
lldp_mand_clif.c lldp_basman_clif.c lldp_med_clif.c lldp_8023_clif.c \
-lldp_dcbx_clif.c $(lldpad_include_HEADERS) $(noinst_HEADERS)
+lldp_dcbx_clif.c lldp_evb_clif.c $(lldpad_include_HEADERS) $(noinst_HEADERS)
nltest_SOURCES = nltest.c nltest.h
diff --git a/include/lldp.h b/include/lldp.h
index 66532bd..e00ba7a 100644
--- a/include/lldp.h
+++ b/include/lldp.h
@@ -45,6 +45,8 @@
/* Telecommunications Industry Association TR-41 Committee */
#define OUI_TIA_TR41 0x0012bb
+#define OUI_IEEE_8021Qbg 0x001b3f
+
/* IEEE 802.3AB Clause 9: TLV Types */
#define CHASSIS_ID_TLV 1
#define PORT_ID_TLV 2
@@ -186,5 +188,22 @@ enum {
#define LLDP_8023_LINKAGG_CAPABLE (1 << 0)
#define LLDP_8023_LINKAGG_ENABLED (1 << 1)
+/* IEEE 802.1Qbg subtype */
+#define LLDP_EVB_SUBTYPE 0
+
+/* forwarding mode */
+#define LLDP_EVB_CAPABILITY_FORWARD_STANDARD (1 << 7)
+#define LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY (1 << 6)
+
+/* EVB supported protocols */
+#define LLDP_EVB_CAPABILITY_PROTOCOL_RTE (1 << 2)
+#define LLDP_EVB_CAPABILITY_PROTOCOL_ECP (1 << 1)
+#define LLDP_EVB_CAPABILITY_PROTOCOL_VDP (1 << 0)
+
+/* EVB specific values */
+#define LLDP_EVB_DEFAULT_MAX_VSI 4096
+#define LLDP_EVB_DEFAULT_SVSI 3295
+#define LLDP_EVB_DEFAULT_RTE 15
+
void somethingChangedLocal(char *ifname);
#endif /* _LLDP_H */
diff --git a/include/lldp_evb.h b/include/lldp_evb.h
new file mode 100644
index 0000000..667f9ad
--- /dev/null
+++ b/include/lldp_evb.h
@@ -0,0 +1,80 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#ifndef _LLDP_EVB_H
+#define _LLDP_EVB_H
+
+#include "lldp_mod.h"
+
+#define LLDP_MOD_EVB OUI_IEEE_8021Qbg
+#define LLDP_OUI_SUBTYPE { 0x00, 0x1b, 0x3f, 0x00 }
+
+typedef enum {
+ EVB_OFFER_CAPABILITIES = 0,
+ EVB_CONFIGURE,
+ EVB_CONFIRMATION
+} evb_state;
+
+struct tlv_info_evb {
+ u8 oui[3];
+ u8 sub;
+ /* supported forwarding mode */
+ u8 smode;
+ /* supported capabilities */
+ u8 scap;
+ /* currently configured forwarding mode */
+ u8 cmode;
+ /* currently configured capabilities */
+ u8 ccap;
+ /* supported no. of vsi */
+ u16 svsi;
+ /* currently configured no. of vsi */
+ u16 cvsi;
+ /* retransmission exponent */
+ u8 rte;
+} __attribute__ ((__packed__));
+
+struct evb_data {
+ char ifname[IFNAMSIZ];
+ struct unpacked_tlv *evb;
+ struct tlv_info_evb *tie;
+ /* local policy */
+ struct tlv_info_evb *policy;
+ int state;
+ LIST_ENTRY(evb_data) entry;
+};
+
+struct evb_user_data {
+ LIST_HEAD(evb_head, evb_data) head;
+};
+
+struct lldp_module *evb_register(void);
+void evb_unregister(struct lldp_module *mod);
+struct packed_tlv *evb_gettlv(struct port *port);
+void evb_ifdown(char *);
+void evb_ifup(char *);
+struct evb_data *evb_data(char *ifname);
+
+#endif /* _LLDP_EVB_H */
diff --git a/include/lldp_evb_clif.h b/include/lldp_evb_clif.h
new file mode 100644
index 0000000..acaee5e
--- /dev/null
+++ b/include/lldp_evb_clif.h
@@ -0,0 +1,51 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#ifndef _LLDP_EVB_CLIF_H
+#define _LLDP_EVB_CLIF_H
+
+struct lldp_module *evb_cli_register(void);
+void evb_cli_unregister(struct lldp_module *);
+int evb_print_tlv(u32, u16, char *);
+
+#define EVB_BUF_SIZE 256
+
+#define ARG_EVB_FORWARDING_MODE "fmode"
+
+#define VAL_EVB_FMODE_BRIDGE "bridge"
+#define VAL_EVB_FMODE_REFLECTIVE_RELAY "reflectiverelay"
+
+#define ARG_EVB_CAPABILITIES "capabilities"
+
+#define VAL_EVB_CAPA_RTE "rte"
+#define VAL_EVB_CAPA_ECP "ecp"
+#define VAL_EVB_CAPA_VDP "vdp"
+#define VAL_EVB_CAPA_NONE "none"
+
+#define ARG_EVB_VSIS "vsis"
+
+#define ARG_EVB_RTE "rte"
+
+#endif
diff --git a/include/lldp_evb_cmds.h b/include/lldp_evb_cmds.h
new file mode 100644
index 0000000..1367e5d
--- /dev/null
+++ b/include/lldp_evb_cmds.h
@@ -0,0 +1,31 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#ifndef _LLDP_EVB_CMDS_H
+#define _LLDP_EVB_CMDS_H
+
+struct arg_handlers *evb_get_arg_handlers();
+
+#endif
diff --git a/include/lldp_tlv.h b/include/lldp_tlv.h
index a32cc71..fe3a75a 100644
--- a/include/lldp_tlv.h
+++ b/include/lldp_tlv.h
@@ -144,6 +144,7 @@ int tlv_ok(struct unpacked_tlv *tlv);
#define TLVID_8021(sub) TLVID(OUI_IEEE_8021, (sub))
#define TLVID_8023(sub) TLVID(OUI_IEEE_8023, (sub))
#define TLVID_MED(sub) TLVID(OUI_TIA_TR41, (sub))
+#define TLVID_8021Qbg(sub) TLVID(OUI_IEEE_8021Qbg, (sub))
/* the size in bytes needed for a packed tlv from unpacked tlv */
#define TLVSIZE(t) ((t) ? (2 + (t)->length) : 0)
diff --git a/lldp_evb.c b/lldp_evb.c
new file mode 100644
index 0000000..4213137
--- /dev/null
+++ b/lldp_evb.c
@@ -0,0 +1,658 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#include <net/if.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <linux/if_bridge.h>
+#include <string.h>
+#include "lldp.h"
+#include "lldp_evb.h"
+#include "messages.h"
+#include "config.h"
+#include "common.h"
+#include "lldp_mand_clif.h"
+#include "lldp_evb_clif.h"
+#include "lldp_evb_cmds.h"
+
+extern struct lldp_head lldp_head;
+
+struct evb_data *evb_data(char *ifname)
+{
+ struct evb_user_data *ud;
+ struct evb_data *ed = NULL;
+
+ ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_EVB);
+ if (ud) {
+ LIST_FOREACH(ed, &ud->head, entry) {
+ if (!strncmp(ifname, ed->ifname, IFNAMSIZ))
+ return ed;
+ }
+ }
+ return NULL;
+}
+
+static void evb_print_tlvinfo(struct tlv_info_evb *tie)
+{
+ printf("%s(%i): supported forwarding mode: %02x\n", __FILE__, __LINE__, tie->smode);
+ printf("%s(%i): configured forwarding mode: %02x\n", __FILE__, __LINE__, tie->cmode);
+ printf("%s(%i): supported capabilities: %02x\n", __FILE__, __LINE__, tie->scap);
+ printf("%s(%i): configured capabilities: %02x\n", __FILE__, __LINE__, tie->ccap);
+ printf("%s(%i): supported no. of vsis: %04i\n", __FILE__, __LINE__, tie->svsi);
+ printf("%s(%i): configured no. of vsis: %04i\n", __FILE__, __LINE__, tie->cvsi);
+ printf("%s(%i): rte: %02i\n\n", __FILE__, __LINE__, tie->rte);
+}
+
+/*
+ * evb_bld_cfg_tlv - build the EVB TLV
+ * @ed: the evb data struct
+ *
+ * Returns 0 on success
+ */
+static int evb_bld_cfg_tlv(struct evb_data *ed)
+{
+ int rc = 0;
+ int i;
+ struct unpacked_tlv *tlv = NULL;
+
+ /* free ed->evb if it exists */
+ FREE_UNPKD_TLV(ed, evb);
+
+ if (!is_tlv_txenabled(ed->ifname, TLVID_8021Qbg(LLDP_EVB_SUBTYPE))) {
+ fprintf(stderr, "%s:%s:EVB tx is currently disabled !\n",
+ __func__, ed->ifname);
+ rc = EINVAL;
+ goto out_err;
+ }
+
+ tlv = create_tlv();
+ if (!tlv)
+ goto out_err;
+
+ tlv->type = ORG_SPECIFIC_TLV;
+ tlv->length = sizeof(struct tlv_info_evb);
+ tlv->info = (u8 *)malloc(tlv->length);
+ if(!tlv->info) {
+ free(tlv);
+ tlv = NULL;
+ rc = ENOMEM;
+ goto out_err;
+ }
+ memcpy(tlv->info, ed->tie, tlv->length);
+
+ printf("### %s:type %i, length %i, info ", __func__, tlv->type, tlv->length);
+
+ for (i=0; i < tlv->length; i++) {
+ printf("%02x ", tlv->info[i]);
+ }
+
+ printf("\n");
+
+ ed->evb = tlv;
+out_err:
+ return rc;
+}
+
+static void evb_free_tlv(struct evb_data *ed)
+{
+ if (ed) {
+ FREE_UNPKD_TLV(ed, evb);
+ }
+}
+
+/* evb_init_cfg_tlv:
+ *
+ * fill up tlv_info_evb structure with reasonable info
+ */
+static int evb_init_cfg_tlv(struct evb_data *ed)
+{
+ char arg_path[EVB_BUF_SIZE];
+ char *param;
+
+ /* load policy from config */
+ ed->policy = (struct tlv_info_evb *) calloc(1, sizeof(struct tlv_info_evb));
+
+ if (!ed->policy)
+ return ENOMEM;
+
+ /* set defaults */
+ hton24(ed->policy->oui, LLDP_MOD_EVB);
+ ed->policy->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+ ed->policy->scap = 0;
+ ed->policy->cmode = 0;
+ ed->policy->ccap = 0;
+ ed->policy->svsi = 0 /*LLDP_EVB_DEFAULT_SVSI*/;
+ ed->policy->rte = 0 /*LLDP_EVB_DEFAULT_RTE*/;
+
+ /* pull forwarding mode into policy */
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.fmode",
+ TLVID_PREFIX, TLVID_8021Qbg(LLDP_EVB_SUBTYPE));
+
+ if (get_cfg(ed->ifname, arg_path, (void *) ¶m, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: loading EVB policy for forwarding mode failed, using default.\n",
+ __func__, ed->ifname);
+ } else {
+ if (strcasestr(param, VAL_EVB_FMODE_BRIDGE)) {
+ ed->policy->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+ }
+
+ if (strcasestr(param, VAL_EVB_FMODE_REFLECTIVE_RELAY)) {
+ ed->policy->smode = LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY;
+ }
+
+ printf("%s:%s: policy param fmode = %s.\n", __func__, ed->ifname, param);
+ printf("%s:%s: policy param smode = %x.\n", __func__, ed->ifname, ed->policy->smode);
+ }
+
+ /* pull capabilities into policy */
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.capabilities",
+ TLVID_PREFIX, TLVID_8021Qbg(LLDP_EVB_SUBTYPE));
+
+ if (get_cfg(ed->ifname, arg_path, (void *) ¶m, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: loading EVB policy for capabilities failed, using default.\n",
+ __func__, ed->ifname);
+ } else {
+ if (strcasestr(param, VAL_EVB_CAPA_RTE)) {
+ ed->policy->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+ }
+
+ if (strcasestr(param, VAL_EVB_CAPA_ECP)) {
+ ed->policy->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+ }
+
+ if (strcasestr(param, VAL_EVB_CAPA_VDP)) {
+ ed->policy->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ }
+
+ printf("%s:%s: policy param capabilities = %s.\n", __func__, ed->ifname, param);
+ printf("%s:%s: policy param scap = %x.\n", __func__, ed->ifname, ed->policy->scap);
+ }
+
+ /* pull rte into policy */
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.rte",
+ TLVID_PREFIX, TLVID_8021Qbg(LLDP_EVB_SUBTYPE));
+
+ if (get_cfg(ed->ifname, arg_path, (void *) ¶m, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: loading EVB policy for rte failed, using default.\n",
+ __func__, ed->ifname);
+ } else {
+ ed->policy->rte = atoi(param);
+
+ printf("%s:%s: policy param rte = %s.\n", __func__, ed->ifname, param);
+ printf("%s:%s: policy param rte = %i.\n", __func__, ed->ifname, ed->policy->rte);
+ }
+
+ /* pull vsis into policy */
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.vsis",
+ TLVID_PREFIX, TLVID_8021Qbg(LLDP_EVB_SUBTYPE));
+
+ if (get_cfg(ed->ifname, arg_path, (void *) ¶m, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: loading EVB policy for vsis failed, using default.\n",
+ __func__, ed->ifname);
+ } else {
+ ed->policy->svsi = atoi(param);
+
+ printf("%s:%s: policy param vsis = %s.\n", __func__, ed->ifname, param);
+ printf("%s:%s: policy param vsis = %i.\n", __func__, ed->ifname, ed->policy->svsi);
+ }
+
+ /* load last used EVB TLV ... */
+ ed->tie = (struct tlv_info_evb *) calloc(1, sizeof(struct tlv_info_evb));
+
+ if (!ed->tie)
+ return ENOMEM;
+
+ if (get_config_tlvinfo_bin(ed->ifname, TLVID_8021Qbg(LLDP_EVB_SUBTYPE),
+ (void *)ed->tie, sizeof(struct tlv_info_evb))) {
+ printf("%s:%s: loading last used EVB TLV failed, using default.\n",
+ __func__, ed->ifname);
+ hton24(ed->tie->oui, LLDP_MOD_EVB);
+ ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY | LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+ ed->tie->cmode = 0x0;
+ ed->tie->scap = LLDP_EVB_CAPABILITY_PROTOCOL_RTE | LLDP_EVB_CAPABILITY_PROTOCOL_ECP
+ | LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ ed->tie->ccap = 0x0;
+ ed->tie->svsi = LLDP_EVB_DEFAULT_SVSI;
+ ed->tie->cvsi = 0x0;
+ ed->tie->rte = LLDP_EVB_DEFAULT_RTE;
+ } else {
+ printf("%s(%i): loaded last used EVB TLV from file.\n", __FILE__, __LINE__);
+ }
+
+ return 0;
+}
+
+static int evb_bld_tlv(struct evb_data *ed)
+{
+ int rc = 0;
+
+ if (!port_find_by_name(ed->ifname)) {
+ rc = EEXIST;
+ goto out_err;
+ }
+
+ if (!init_cfg()) {
+ rc = ENOENT;
+ goto out_err;
+ }
+
+ if (evb_bld_cfg_tlv(ed)) {
+ fprintf(stderr, "### %s:%s:evb_bld_cfg_tlv() failed\n",
+ __func__, ed->ifname);
+ rc = EINVAL;
+ goto out_err_destroy;
+ }
+
+out_err_destroy:
+ destroy_cfg();
+
+out_err:
+ return rc;
+}
+
+static void evb_free_data(struct evb_user_data *ud)
+{
+ struct evb_data *ed;
+ if (ud) {
+ while (!LIST_EMPTY(&ud->head)) {
+ ed = LIST_FIRST(&ud->head);
+ LIST_REMOVE(ed, entry);
+ evb_free_tlv(ed);
+ free(ed);
+ }
+ }
+}
+
+struct packed_tlv *evb_gettlv(struct port *port)
+{
+ int size;
+ struct evb_data *ed;
+ struct packed_tlv *ptlv = NULL;
+
+ ed = evb_data(port->ifname);
+ if (!ed)
+ goto out_err;
+
+ evb_free_tlv(ed);
+
+ if (evb_bld_tlv(ed)) {
+ fprintf(stderr, "### %s:%s evb_bld_tlv failed\n",
+ __func__, port->ifname);
+ goto out_err;
+ }
+
+ size = TLVSIZE(ed->evb);
+
+ if (!size)
+ goto out_err;
+
+ ptlv = create_ptlv();
+ if (!ptlv)
+ goto out_err;
+
+ ptlv->tlv = malloc(size);
+ if (!ptlv->tlv)
+ goto out_free;
+
+ ptlv->size = 0;
+ PACK_TLV_AFTER(ed->evb, ptlv, size, out_free);
+ return ptlv;
+out_free:
+ /* FIXME: free function returns pointer ? */
+ ptlv = free_pkd_tlv(ptlv);
+out_err:
+ fprintf(stderr,"### %s:%s: failed\n", __func__, port->ifname);
+ return NULL;
+
+}
+
+/* evb_check_and_fill
+ *
+ * checks values received in TLV and takes over some values
+ */
+int evb_check_and_fill(struct evb_data *ed, struct tlv_info_evb *tie)
+{
+ /* sanity check of received data in tie */
+ if ((tie->smode & (LLDP_EVB_CAPABILITY_FORWARD_STANDARD |
+ LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY)) == 0)
+ return TLV_ERR;
+
+ if ((tie->svsi < 0) || (tie->svsi > LLDP_EVB_DEFAULT_MAX_VSI))
+ return TLV_ERR;
+
+ if ((tie->cvsi < 0) || (tie->cvsi > LLDP_EVB_DEFAULT_MAX_VSI))
+ return TLV_ERR;
+
+ /* check bridge capabilities against local policy*/
+ /* if bridge supports RR and we support it as well, request it
+ * by setting smode in tlv to be sent out (ed->tie->smode) */
+ if ( (tie->smode & ed->policy->smode) ==
+ LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY ) {
+ ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY;
+ } else {
+ ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+ }
+
+ /* If both sides support RTE, set it */
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_RTE)
+ ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+
+ /* If both sides support ECP, set it */
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_ECP)
+ ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+
+ /* If both sides support VDP, set it */
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
+ ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+
+ /* If supported caps include VDP take over min value of both */
+ if (ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
+ ed->tie->cvsi = MIN(ed->policy->svsi,tie->svsi);
+
+ /* If both sides support RTE and value offer is > 0, set it */
+ if ((ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) &&
+ (tie->rte > 0) && (ed->policy->rte > 0))
+ ed->tie->rte = MAX(ed->policy->rte,tie->rte);
+
+ if (set_config_tlvinfo_bin(ed->ifname, TLVID_8021Qbg(LLDP_EVB_SUBTYPE),
+ (void *)ed->tie, sizeof(struct tlv_info_evb))) {
+ printf("%s(%i): error saving tlv_info_evb !\n", __FILE__, __LINE__);
+ } else {
+ printf("%s(%i): saved tlv_info_evb to config !\n", __FILE__, __LINE__);
+ }
+
+ /* maybe switch has already set the mode based on the saved info sent
+ * out on ifup */
+
+ if (tie->cmode == ed->tie->smode) {
+ ed->tie->cmode = tie->cmode;
+ }
+
+ /* only look at the mode for now
+ if (tie->ccap == ed->tie->ccap) {
+ ed->tie->ccap = tie->ccap;
+ }
+
+ if (tie->cvsi == ed->tie->cvsi) {
+ ed->tie->cvsi = tie->cvsi;
+ }
+ */
+
+ return TLV_OK;
+}
+
+/* evb_compare
+ *
+ * compare our own and received tlv_info_evb
+ */
+static int evb_compare(struct evb_data *ed, struct tlv_info_evb *tie)
+{
+ printf("%s(%i): \n", __func__, __LINE__);
+
+ if ((ed->tie->cmode == tie->cmode) /* &&
+ (ed->tie->ccap == tie->ccap) &&
+ (ed->tie->cvsi == tie->cvsi)*/)
+ return 0;
+ else
+ return 1;
+}
+
+/* evb_statemachine:
+ *
+ * handle possible states during EVB capabilities exchange
+ *
+ * possible states: EVB_OFFER_CAPABILITIES
+ * EVB_CONFIGURE
+ * EVB_CONFIRMATION
+ */
+static void evb_statemachine(struct evb_data *ed, struct tlv_info_evb *tie)
+{
+ switch(ed->state) {
+ case EVB_OFFER_CAPABILITIES:
+ /* waiting for valid packets to pour in
+ * if valid packet was received,
+ * - check parameters with what we have offered for this if,
+ * - fill structure with data,
+ * - enable local tx
+ * - switch to EVB_CONFIGURE
+ */
+ printf("%s: state -> EVB_OFFER_CAPABILITIES\n", __func__);
+ if (evb_check_and_fill(ed, tie) != TLV_OK) {
+ fprintf(stderr, "Invalid contents of EVB Cfg TLV !\n");
+ return;
+ }
+ somethingChangedLocal(ed->ifname); /* trigger tx with new values */
+ ed->state = EVB_CONFIGURE;
+ break;
+ case EVB_CONFIGURE:
+ /* we received a valid packet, if contents is same with our local settings
+ * we can switch state to EVB_CONFIRMATION.*/
+ printf("%s: state -> EVB_CONFIGURE\n", __func__);
+ if (evb_compare(ed, tie)) {
+ ed->state= EVB_OFFER_CAPABILITIES;
+ } else {
+ printf("tlv_info_evb now equal !\n");
+ ed->state = EVB_CONFIRMATION;
+ }
+ somethingChangedLocal(ed->ifname);
+ break;
+ case EVB_CONFIRMATION:
+ /* we are already in confirmation and received a new packet with
+ * different parameters ? Check parameters. switch state back to
+ * EVB_CONFIGURE ? */
+ printf("%s: state -> EVB_CONFIRMATION\n", __func__);
+#if 0
+ if (ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP)
+ ecp_init(ed->ifname);
+#endif
+ break;
+ default:
+ fprintf(stderr, "EVB statemachine reached invalid state !\n");
+ break;
+ }
+}
+
+/*
+ * evb_rchange: process RX TLV LLDPDU
+ *
+ * TLV not consumed on error
+ */
+static int evb_rchange(struct port *port, struct unpacked_tlv *tlv)
+{
+ int i;
+ struct evb_data *ed;
+ struct tlv_info_evb *tie = (struct tlv_info_evb *) tlv->info;
+ u8 oui_subtype[OUI_SUB_SIZE] = LLDP_OUI_SUBTYPE;
+
+ if (!init_cfg()) {
+ return SUBTYPE_INVALID;
+ }
+
+ ed = evb_data(port->ifname);
+
+ if (!ed)
+ return SUBTYPE_INVALID;
+
+ if (tlv->type == TYPE_127) {
+ /* check for length */
+ if (tlv->length < (OUI_SUB_SIZE)) {
+ return TLV_ERR;
+ }
+
+ /* check for oui */
+ if (memcmp(tlv->info, &oui_subtype, OUI_SUB_SIZE)) {
+ return SUBTYPE_INVALID;
+ }
+
+ /* disable rx if tx has been disabled by administrator */
+ if (!is_tlv_txenabled(ed->ifname, TLVID_8021Qbg(LLDP_EVB_SUBTYPE))) {
+ fprintf(stderr, "### %s:%s:EVB Config disabled\n",
+ __func__, ed->ifname);
+ return TLV_OK;
+ }
+
+ fprintf(stderr, "%s:type %i, length %i, info ", __func__, tlv->type, tlv->length);
+
+ for (i=0; i < tlv->length; i++) {
+ fprintf(stderr, "%02x ", tlv->info[i]);
+ }
+
+ printf("\n");
+
+ evb_print_tlvinfo(tie);
+
+ /* change state */
+ evb_statemachine(ed, tie);
+
+ /* check which values have been taken over */
+ evb_print_tlvinfo(ed->tie);
+ }
+
+ return TLV_OK;
+}
+
+void evb_ifdown(char *ifname)
+{
+ struct evb_data *ed;
+
+ printf("%s called !\n", __func__);
+
+ ed = evb_data(ifname);
+ if (!ed)
+ goto out_err;
+
+ free(ed->tie);
+ LIST_REMOVE(ed, entry);
+ evb_free_tlv(ed);
+ free(ed);
+ fprintf(stderr, "### %s:port %s removed\n", __func__, ifname);
+ return;
+out_err:
+ fprintf(stderr, "### %s:port %s adding failed\n", __func__, ifname);
+
+ return;
+}
+
+void evb_ifup(char *ifname)
+{
+ struct evb_data *ed;
+ struct evb_user_data *ud;
+
+ ed = evb_data(ifname);
+ if (ed) {
+ fprintf(stderr, "### %s:%s exists\n", __func__, ifname);
+ goto out_err;
+ }
+
+ /* not found, alloc/init per-port tlv data */
+ ed = (struct evb_data *) calloc(1, sizeof(struct evb_data));
+ if (!ed) {
+ fprintf(stderr, "### %s:%s malloc %ld failed\n",
+ __func__, ifname, sizeof(*ed));
+ goto out_err;
+ }
+ strncpy(ed->ifname, ifname, IFNAMSIZ);
+
+ if (!init_cfg()) {
+ goto out_err;
+ }
+
+ if (evb_init_cfg_tlv(ed)) {
+ fprintf(stderr, "### %s:%s evb_init_cfg_tlv failed\n", __func__, ifname);
+ free(ed);
+ goto out_err;
+ }
+
+ ed->state = EVB_OFFER_CAPABILITIES;
+
+ if (evb_bld_tlv(ed)) {
+ fprintf(stderr, "### %s:%s evb_bld_tlv failed\n", __func__, ifname);
+ free(ed);
+ goto out_err;
+ }
+
+ ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_EVB);
+ LIST_INSERT_HEAD(&ud->head, ed, entry);
+ fprintf(stderr, "### %s:port %s added\n", __func__, ifname);
+ return;
+
+out_err:
+ fprintf(stderr, "### %s:port %s adding failed\n", __func__, ifname);
+ return;
+}
+
+static const struct lldp_mod_ops evb_ops = {
+ .lldp_mod_register = evb_register,
+ .lldp_mod_unregister = evb_unregister,
+ .lldp_mod_gettlv = evb_gettlv,
+ .lldp_mod_rchange = evb_rchange,
+ .lldp_mod_ifup = evb_ifup,
+ .lldp_mod_ifdown = evb_ifdown,
+ .get_arg_handler = evb_get_arg_handlers,
+};
+
+struct lldp_module *evb_register(void)
+{
+ struct lldp_module *mod;
+ struct evb_user_data *ud;
+
+ mod = malloc(sizeof(*mod));
+ if (!mod) {
+ fprintf(stderr, "failed to malloc module data\n");
+ log_message(MSG_ERR_SERVICE_START_FAILURE,
+ "%s", "failed to malloc module data");
+ goto out_err;
+ }
+ ud = malloc(sizeof(struct evb_user_data));
+ if (!ud) {
+ free(mod);
+ fprintf(stderr, "failed to malloc module user data\n");
+ log_message(MSG_ERR_SERVICE_START_FAILURE,
+ "%s", "failed to malloc module user data");
+ goto out_err;
+ }
+ LIST_INIT(&ud->head);
+ mod->id = LLDP_MOD_EVB;
+ mod->ops = &evb_ops;
+ mod->data = ud;
+ fprintf(stderr, "### %s:done\n", __func__);
+ return mod;
+
+out_err:
+ fprintf(stderr, "### %s:failed\n", __func__);
+ return NULL;
+}
+
+void evb_unregister(struct lldp_module *mod)
+{
+ if (mod->data) {
+ evb_free_data((struct evb_user_data *) mod->data);
+ free(mod->data);
+ }
+ free(mod);
+ fprintf(stderr, "### %s:done\n", __func__);
+}
diff --git a/lldp_evb_clif.c b/lldp_evb_clif.c
new file mode 100644
index 0000000..7479d74
--- /dev/null
+++ b/lldp_evb_clif.c
@@ -0,0 +1,226 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#include "includes.h"
+#include "common.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include "lldp_mod.h"
+#include "lldptool.h"
+#include "lldp.h"
+#include "lldp_evb.h"
+#include "lldp_evb_clif.h"
+
+void evb_print_cfg_tlv(u16, char *info);
+int evb_print_help();
+
+u32 evb_lookup_tlv_name(char *tlvid_str);
+
+static const struct lldp_mod_ops evb_ops_clif = {
+ .lldp_mod_register = evb_cli_register,
+ .lldp_mod_unregister = evb_cli_unregister,
+ .print_tlv = evb_print_tlv,
+ .lookup_tlv_name = evb_lookup_tlv_name,
+ .print_help = evb_print_help,
+};
+
+struct type_name_info evb_tlv_names[] = {
+ { (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE,
+ "EVB Configuration TLV",
+ "evbCfg", evb_print_cfg_tlv },
+ { INVALID_TLVID, NULL, NULL }
+};
+
+int evb_print_help()
+{
+ struct type_name_info *tn = &evb_tlv_names[0];
+
+ while (tn->type != INVALID_TLVID) {
+ if (tn->key && strlen(tn->key) && tn->name) {
+ printf(" %s", tn->key);
+ if (strlen(tn->key)+3 <= 8)
+ printf("\t");
+ printf("\t: %s\n", tn->name);
+ }
+ tn++;
+ }
+
+ return 0;
+}
+
+struct lldp_module *evb_cli_register(void)
+{
+ struct lldp_module *mod;
+
+ mod = malloc(sizeof(*mod));
+ if (!mod) {
+ fprintf(stderr, "failed to malloc module data\n");
+ return NULL;
+ }
+ mod->id = LLDP_MOD_EVB;
+ mod->ops = &evb_ops_clif;
+
+ return mod;
+}
+
+void evb_cli_unregister(struct lldp_module *mod)
+{
+ free(mod);
+}
+
+void evb_print_cfg_tlv(u16 len, char *info)
+{
+ u8 smode;
+ u8 scap;
+ u8 cmode;
+ u8 ccap;
+ u16 svsi;
+ u16 cvsi;
+ u8 rte;
+
+ if (len != 9) {
+ printf("Bad Cfg TLV: %s\n", info);
+ return;
+ }
+
+ if (!hexstr2bin(info, &smode, sizeof(smode))) {
+ printf("supported forwarding mode: (0x%02hhx)", smode);
+
+ if (smode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY)
+ printf(" reflective relay");
+
+ if (smode & LLDP_EVB_CAPABILITY_FORWARD_STANDARD)
+ printf(" standard 802.1Q");
+
+ printf("\n");
+ } else {
+ printf("Unable to decode smode !\n");
+ }
+
+ if (!hexstr2bin(info+2, &scap, sizeof(scap))) {
+ printf("\tsupported capabilities: (0x%02hhx)", scap);
+
+ if ( scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE)
+ printf(" RTE");
+
+ if ( scap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP)
+ printf(" ECP");
+
+ if ( scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
+ printf(" VDP");
+
+ printf("\n");
+ } else {
+ printf("Unable to decode scap !\n");
+ }
+
+ if (!hexstr2bin(info+4, &cmode, sizeof(cmode))) {
+ printf("\tconfigured forwarding mode: (0x%02hhx)", cmode);
+
+ if (cmode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY)
+ printf(" reflective relay");
+
+ if (cmode & LLDP_EVB_CAPABILITY_FORWARD_STANDARD)
+ printf(" standard 802.1Q");
+
+ printf("\n");
+ } else {
+ printf("Unable to decode cmode !\n");
+ }
+
+ if (!hexstr2bin(info+6, &ccap, sizeof(ccap))) {
+ printf("\tconfigured capabilities: (0x%02hhx)", ccap);
+
+ if ( ccap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE)
+ printf(" RTE");
+
+ if ( ccap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP)
+ printf(" ECP");
+
+ if ( ccap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
+ printf(" VDP");
+
+ printf("\n");
+ } else {
+ printf("Unable to decode ccap !\n");
+ }
+
+ if (!hexstr2bin(info+8, (u8 *)&svsi, sizeof(svsi))) {
+ printf("\tno. of supported VSIs: %04i\n",svsi);
+ } else {
+ printf("Unable to decode svsi !\n");
+ }
+
+ if (!hexstr2bin(info+12, (u8 *)&cvsi, sizeof(cvsi))) {
+ printf("\tno. of configured VSIs: %04i\n",cvsi);
+ } else {
+ printf("Unable to decode cvsi !\n");
+ }
+
+ if (!hexstr2bin(info+16, &rte, sizeof(rte))) {
+ printf("\tRTE: %i\n",rte);
+ } else {
+ printf("Unable to decode cvsi !\n");
+ }
+
+ printf("\n");
+}
+
+/* return 1: if it printed the TLV
+ * 0: if it did not
+ */
+int evb_print_tlv(u32 tlvid, u16 len, char *info)
+{
+ struct type_name_info *tn = &evb_tlv_names[0];
+
+ while (tn->type != INVALID_TLVID) {
+ if (tlvid == tn->type) {
+ printf("%s\n", tn->name);
+ if (tn->print_info) {
+ printf("\t");
+ tn->print_info(len-4, info);
+ }
+ return 1;
+ }
+ tn++;
+ }
+
+ return 0;
+}
+
+u32 evb_lookup_tlv_name(char *tlvid_str)
+{
+ struct type_name_info *tn = &evb_tlv_names[0];
+
+ while (tn->type != INVALID_TLVID) {
+ if (!strcasecmp(tn->key, tlvid_str))
+ return tn->type;
+ tn++;
+ }
+ return INVALID_TLVID;
+}
+
diff --git a/lldp_evb_cmds.c b/lldp_evb_cmds.c
new file mode 100644
index 0000000..095a32c
--- /dev/null
+++ b/lldp_evb_cmds.c
@@ -0,0 +1,512 @@
+/*******************************************************************************
+
+ implementation of EVB TLVs for LLDP
+ (c) Copyright IBM Corp. 2010
+
+ Author(s): Jens Osterkamp <jens@linux.vnet.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+*******************************************************************************/
+
+#include "includes.h"
+#include "common.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include "lldpad.h"
+#include "ctrl_iface.h"
+#include "lldp.h"
+#include "lldp_evb.h"
+#include "lldp_mand_clif.h"
+#include "lldp_evb_clif.h"
+#include "lldp/ports.h"
+#include "libconfig.h"
+#include "config.h"
+#include "clif_msgs.h"
+#include "lldp/states.h"
+
+static int get_arg_tlvtxenable(struct cmd *, char *, char *, char *);
+static int set_arg_tlvtxenable(struct cmd *, char *, char *, char *);
+
+static int get_arg_fmode(struct cmd *, char *, char *, char *);
+static int set_arg_fmode(struct cmd *, char *, char *, char *);
+
+static int get_arg_rte(struct cmd *, char *, char *, char *);
+static int set_arg_rte(struct cmd *, char *, char *, char *);
+
+static int get_arg_vsis(struct cmd *, char *, char *, char *);
+static int set_arg_vsis(struct cmd *, char *, char *, char *);
+
+static int get_arg_capabilities(struct cmd *, char *, char *, char *);
+static int set_arg_capabilities(struct cmd *, char *, char *, char *);
+
+static struct arg_handlers arg_handlers[] = {
+ { ARG_EVB_FORWARDING_MODE, get_arg_fmode, set_arg_fmode },
+ { ARG_EVB_CAPABILITIES, get_arg_capabilities, set_arg_capabilities },
+ { ARG_EVB_VSIS, get_arg_vsis, set_arg_vsis },
+ { ARG_EVB_RTE, get_arg_rte, set_arg_rte },
+ { ARG_TLVTXENABLE, get_arg_tlvtxenable, set_arg_tlvtxenable },
+ { NULL }
+};
+
+static int get_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ int value;
+ char *s;
+ char arg_path[EVB_BUF_SIZE];
+
+ if (cmd->cmd != cmd_gettlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s",
+ TLVID_PREFIX, cmd->tlvid, arg);
+
+ if (get_cfg(cmd->ifname, arg_path, (void *)&value,
+ CONFIG_TYPE_BOOL))
+ value = false;
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ if (value)
+ s = VAL_YES;
+ else
+ s = VAL_NO;
+
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen(s), s);
+
+ return cmd_success;
+}
+
+static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ int value;
+ char arg_path[EVB_BUF_SIZE];
+
+ if (cmd->cmd != cmd_settlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ if (!strcasecmp(argvalue, VAL_YES))
+ value = 1;
+ else if (!strcasecmp(argvalue, VAL_NO))
+ value = 0;
+ else
+ return cmd_invalid;
+
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s",
+ TLVID_PREFIX, cmd->tlvid, arg);
+
+ if (set_cfg(cmd->ifname, arg_path, (void *)&value, CONFIG_TYPE_BOOL))
+ return cmd_failed;
+
+ return cmd_success;
+}
+
+static int get_arg_fmode(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ char *s;
+ struct evb_data *ed;
+
+ if (cmd->cmd != cmd_gettlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+ if (!ed)
+ return cmd_invalid;
+ if (ed->policy->smode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY)
+ s = VAL_EVB_FMODE_BRIDGE;
+ else
+ s = VAL_EVB_FMODE_REFLECTIVE_RELAY;
+
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen(s), s);
+
+ return cmd_success;
+}
+
+static int set_arg_fmode(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ u8 smode;
+ char arg_path[EVB_BUF_SIZE];
+ struct evb_data *ed;
+
+ if (cmd->cmd != cmd_settlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+
+ if (!ed)
+ return cmd_invalid;
+
+ smode = 0;
+
+ if (!strcasecmp(argvalue, VAL_EVB_FMODE_BRIDGE)) {
+ smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+ }
+
+ if (!strcasecmp(argvalue, VAL_EVB_FMODE_REFLECTIVE_RELAY)) {
+ smode = LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY;
+ }
+
+ if (smode == 0) {
+ return cmd_invalid;
+ } else {
+ ed->policy->smode = smode;
+ }
+
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.fmode",
+ TLVID_PREFIX, cmd->tlvid);
+
+ if (set_cfg(ed->ifname, arg_path, (void *) &argvalue, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: saving EVB forwarding mode failed.\n",
+ __func__, ed->ifname);
+ return cmd_invalid;
+ }
+
+ return cmd_success;
+}
+
+static int get_arg_capabilities(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ int c;
+ char *s, *t;
+ struct evb_data *ed;
+
+ printf("%s(%i): arg %s, argvalue %s !\n", __func__, __LINE__, arg, argvalue);
+
+ s = t = malloc(EVB_BUF_SIZE);
+
+ if (!s)
+ return cmd_invalid;
+
+ memset(s, 0, EVB_BUF_SIZE);
+
+ if (cmd->cmd != cmd_gettlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+ if (!ed)
+ return cmd_invalid;
+
+ if (ed->policy->scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) {
+ c = sprintf(s, VAL_EVB_CAPA_RTE " ");
+ if (c <= 0)
+ return cmd_invalid;
+ s += c;
+ }
+
+ if (ed->policy->scap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP) {
+ c = sprintf(s, VAL_EVB_CAPA_ECP " ");
+ if (c <= 0)
+ return cmd_invalid;
+ s += c;
+ }
+
+ if (ed->policy->scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) {
+ c = sprintf(s, VAL_EVB_CAPA_VDP " ");
+ if (c <= 0)
+ return cmd_invalid;
+ s += c;
+ }
+
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen(t), t);
+
+ return cmd_success;
+}
+
+static int set_arg_capabilities(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ u8 scap = 0;
+ char arg_path[EVB_BUF_SIZE];
+ struct evb_data *ed;
+
+ if (cmd->cmd != cmd_settlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+
+ if (!ed)
+ return cmd_invalid;
+
+ if (strcasestr(argvalue, VAL_EVB_CAPA_RTE)) {
+ scap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+ }
+
+ if (strcasestr(argvalue, VAL_EVB_CAPA_ECP)) {
+ scap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+ }
+
+ if (strcasestr(argvalue, VAL_EVB_CAPA_VDP)) {
+ scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ }
+
+ ed->policy->scap = scap;
+
+ snprintf(arg_path, sizeof(arg_path), "%s%08x.capabilities",
+ TLVID_PREFIX, cmd->tlvid);
+
+ if (set_cfg(ed->ifname, arg_path, (void *) &argvalue, CONFIG_TYPE_STRING)) {
+ printf("%s:%s: saving EVB capabilities failed.\n",
+ __func__, ed->ifname);
+ return cmd_invalid;
+ }
+
+ return cmd_success;
+}
+
+static int get_arg_rte(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ char s[EVB_BUF_SIZE];
+ struct evb_data *ed;
+
+ if (cmd->cmd != cmd_gettlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+ if (!ed)
+ return cmd_invalid;
+
+ if (sprintf(s, "%i", ed->policy->rte) <= 0)
+ return cmd_invalid;
+
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen(s), s);
+
+ return cmd_success;
+}
+
+static int set_arg_rte(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ int value, err;
+ char arg_path[EVB_BUF_SIZE];
+ char svalue[10];
+ char *sv;
+ struct evb_data *ed = NULL;
+
+ if (cmd->cmd != cmd_settlv)
+ goto out_err;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ goto out_err;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+
+ if (!ed)
+ goto out_err;
+
+ value = atoi(argvalue);
+
+ if ((value < 0))
+ goto out_err;
+
+ ed->policy->rte = value;
+
+ err = snprintf(arg_path, sizeof(arg_path), "%s%08x.rte",
+ TLVID_PREFIX, cmd->tlvid);
+
+ if (err < 0)
+ goto out_err;
+
+ err = snprintf(svalue, sizeof(svalue), "%i", value);
+
+ if (err < 0)
+ goto out_err;
+
+ sv = &svalue[0];
+
+ if (set_cfg(ed->ifname, arg_path, (void *) &sv, CONFIG_TYPE_STRING)) {
+ goto out_err;
+ }
+
+ return cmd_success;
+
+out_err:
+ printf("%s:%s: saving EVB rte failed.\n", __func__, ed->ifname);
+ return cmd_invalid;
+}
+
+static int get_arg_vsis(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ char s[EVB_BUF_SIZE];
+ struct evb_data *ed;
+
+ if (cmd->cmd != cmd_gettlv)
+ return cmd_invalid;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ return cmd_invalid;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+ if (!ed)
+ return cmd_invalid;
+
+ if (sprintf(s, "%04i", ed->policy->svsi) <= 0)
+ return cmd_invalid;
+
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen(s), s);
+
+ return cmd_success;
+}
+
+static int set_arg_vsis(struct cmd *cmd, char *arg, char *argvalue,
+ char *obuf)
+{
+ int value, err;
+ char arg_path[EVB_BUF_SIZE];
+ char svalue[10];
+ char *sv;
+ struct evb_data *ed = NULL;
+
+ if (cmd->cmd != cmd_settlv)
+ goto out_err;
+
+ switch (cmd->tlvid) {
+ case (LLDP_MOD_EVB << 8) | LLDP_EVB_SUBTYPE:
+ break;
+ case INVALID_TLVID:
+ goto out_err;
+ default:
+ return cmd_not_applicable;
+ }
+
+ ed = evb_data((char *) &cmd->ifname);
+
+ if (!ed)
+ goto out_err;
+
+ value = atoi(argvalue);
+
+ if ((value < 0) || (value > LLDP_EVB_DEFAULT_MAX_VSI))
+ goto out_err;
+
+ ed->policy->svsi = value;
+
+ err = snprintf(arg_path, sizeof(arg_path), "%s%08x.vsis",
+ TLVID_PREFIX, cmd->tlvid);
+
+ if (err < 0)
+ goto out_err;
+
+ err = snprintf(svalue, sizeof(svalue), "%i", value);
+
+ if (err < 0)
+ goto out_err;
+
+ sv = &svalue[0];
+
+ if (set_cfg(ed->ifname, arg_path, (void *) &sv, CONFIG_TYPE_STRING)) {
+ goto out_err;
+ }
+
+ return cmd_success;
+
+out_err:
+ printf("%s:%s: saving EVB vsis failed.\n", __func__, ed->ifname);
+ return cmd_invalid;
+}
+
+struct arg_handlers *evb_get_arg_handlers()
+{
+ return &arg_handlers[0];
+}
diff --git a/lldpad.c b/lldpad.c
index a89b5a4..571da31 100644
--- a/lldpad.c
+++ b/lldpad.c
@@ -49,6 +49,7 @@
#include "lldp_dcbx.h"
#include "lldp_med.h"
#include "lldp_8023.h"
+#include "lldp_evb.h"
#include "config.h"
#include "lldpad_shm.h"
#include "clif.h"
@@ -63,6 +64,7 @@ struct lldp_module *(*register_tlv_table[])(void) = {
dcbx_register,
med_register,
ieee8023_register,
+ evb_register,
NULL,
};
diff --git a/lldptool.c b/lldptool.c
index 5cf2846..7e166fe 100644
--- a/lldptool.c
+++ b/lldptool.c
@@ -39,6 +39,7 @@
#include "lldp_med_clif.h"
#include "lldp_8023_clif.h"
#include "lldp_dcbx_clif.h"
+#include "lldp_evb_clif.h"
#include "lldptool.h"
#include "lldptool_cli.h"
#include "lldp_mod.h"
@@ -156,6 +157,7 @@ struct lldp_module *(*register_tlv_table[])(void) = {
ieee8023_cli_register,
med_cli_register,
dcbx_cli_register,
+ evb_cli_register,
NULL,
};
--
1.7.1
------------------------------
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization
End of Virtualization Digest, Vol 60, Issue 17
**********************************************
^ permalink raw reply related
* Re: [PATCH 2/3] S390: Add virtio hotplug add support
From: Alexander Graf @ 2010-09-12 0:42 UTC (permalink / raw)
To: Alexander Graf
Cc: linux-s390, KVM list, Christian Borntraeger, Carsten Otte,
virtualization, Christian Ehrhardt
In-Reply-To: <1282657732-20902-2-git-send-email-agraf@suse.de>
On 24.08.2010, at 15:48, Alexander Graf wrote:
> The one big missing feature in s390-virtio was hotplugging. This is no more.
> This patch implements hotplug add support, so you can on the fly add new devices
> in the guest.
>
> Keep in mind that this needs a patch for qemu to actually leverage the
> functionality.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
ping (on the patch set)?
Alex
^ permalink raw reply
* Re: [PATCH 2/3] S390: Add virtio hotplug add support
From: Avi Kivity @ 2010-09-12 9:00 UTC (permalink / raw)
To: Alexander Graf
Cc: linux-s390, KVM list, Christian Borntraeger, Carsten Otte,
virtualization, Christian Ehrhardt
In-Reply-To: <72A751CE-3F46-4D98-9FAF-BA1C1A95B6EE@suse.de>
On 09/12/2010 02:42 AM, Alexander Graf wrote:
> On 24.08.2010, at 15:48, Alexander Graf wrote:
>
>> The one big missing feature in s390-virtio was hotplugging. This is no more.
>> This patch implements hotplug add support, so you can on the fly add new devices
>> in the guest.
>>
>> Keep in mind that this needs a patch for qemu to actually leverage the
>> functionality.
>>
>> Signed-off-by: Alexander Graf<agraf@suse.de>
> ping (on the patch set)?
>
Actually Marcelo applied it. But the natural place for it is Rusty's
virtio tree. Rusty, if you want to take it, let me know and I'll drop
it from kvm.git.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply
* Re: [PATCH 2/3] S390: Add virtio hotplug add support
From: Rusty Russell @ 2010-09-13 3:35 UTC (permalink / raw)
To: Avi Kivity
Cc: linux-s390, KVM list, Christian Ehrhardt, Carsten Otte,
virtualization, Christian Borntraeger
In-Reply-To: <4C8C96BB.2010804@redhat.com>
On Sun, 12 Sep 2010 06:30:43 pm Avi Kivity wrote:
> On 09/12/2010 02:42 AM, Alexander Graf wrote:
> > On 24.08.2010, at 15:48, Alexander Graf wrote:
> >
> >> The one big missing feature in s390-virtio was hotplugging. This is no more.
> >> This patch implements hotplug add support, so you can on the fly add new devices
> >> in the guest.
> >>
> >> Keep in mind that this needs a patch for qemu to actually leverage the
> >> functionality.
> >>
> >> Signed-off-by: Alexander Graf<agraf@suse.de>
> > ping (on the patch set)?
> >
>
> Actually Marcelo applied it. But the natural place for it is Rusty's
> virtio tree. Rusty, if you want to take it, let me know and I'll drop
> it from kvm.git.
I thought it would be in the s390 tree, which is why I didn't take it...
But I'm *always* happy to let do the work!
Thanks,
Rusty.
^ permalink raw reply
* Re: [PATCH 2/3] S390: Add virtio hotplug add support
From: Martin Schwidefsky @ 2010-09-13 7:41 UTC (permalink / raw)
To: Rusty Russell
Cc: linux-s390, list, Christian Ehrhardt, Carsten Otte, KVM,
virtualization, Christian Borntraeger, Avi Kivity
In-Reply-To: <201009131305.58893.rusty@rustcorp.com.au>
On Mon, 13 Sep 2010 13:05:57 +0930
Rusty Russell <rusty@rustcorp.com.au> wrote:
> On Sun, 12 Sep 2010 06:30:43 pm Avi Kivity wrote:
> > On 09/12/2010 02:42 AM, Alexander Graf wrote:
> > > On 24.08.2010, at 15:48, Alexander Graf wrote:
> > >
> > >> The one big missing feature in s390-virtio was hotplugging. This is no more.
> > >> This patch implements hotplug add support, so you can on the fly add new devices
> > >> in the guest.
> > >>
> > >> Keep in mind that this needs a patch for qemu to actually leverage the
> > >> functionality.
> > >>
> > >> Signed-off-by: Alexander Graf<agraf@suse.de>
> > > ping (on the patch set)?
> > >
> >
> > Actually Marcelo applied it. But the natural place for it is Rusty's
> > virtio tree. Rusty, if you want to take it, let me know and I'll drop
> > it from kvm.git.
>
> I thought it would be in the s390 tree, which is why I didn't take it...
>
> But I'm *always* happy to let do the work!
I didn't pick them up after I saw that Marcelo took them. If others want
to do the work, be my guest..
--
blue skies,
Martin.
"Reality continues to ruin my life." - Calvin.
^ permalink raw reply
* Re: Fwd: RE: Virtualization Digest, Vol 60, Issue 17
From: Jens Osterkamp @ 2010-09-13 9:22 UTC (permalink / raw)
To: Arpit Patel; +Cc: Arnd Bergmann, virtualization
In-Reply-To: <201009131105.17870.arnd@arndb.de>
> ---------- Forwarded Message ----------
>
> Subject: RE: Virtualization Digest, Vol 60, Issue 17
> Date: Friday 10 September 2010
> From: Arpit Patel <Arpit.Patel@exar.com>
> To: "virtualization@lists.linux-foundation.org" <virtualization@lists.linux-foundation.org>
>
> Hi,
> Can someone please point me to where I can find this early version of the IEEE802.1Qbg implementation? When I downloaded the 0.9.38 version of lldpad, it does not have the latest set of code mentioned below.
Hi Arpit,
the 802.1Qbg are not included in lldpad. My patches apply against lldpad 0.9.38 to enable 802.1Qbg.
Jens
[Rest of Digest deleted]
--
IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH 2/3] S390: Add virtio hotplug add support
From: Avi Kivity @ 2010-09-13 9:41 UTC (permalink / raw)
To: Martin Schwidefsky
Cc: linux-s390, KVM list, Christian Ehrhardt, Carsten Otte,
virtualization, Christian Borntraeger
In-Reply-To: <20100913094113.3c0ee732@mschwide.boeblingen.de.ibm.com>
On 09/13/2010 09:41 AM, Martin Schwidefsky wrote:
>>> Actually Marcelo applied it. But the natural place for it is Rusty's
>>> virtio tree. Rusty, if you want to take it, let me know and I'll drop
>>> it from kvm.git.
>> I thought it would be in the s390 tree, which is why I didn't take it...
>>
>> But I'm *always* happy to let do the work!
> I didn't pick them up after I saw that Marcelo took them. If others want
> to do the work, be my guest..
>
I just hope that all this generosity doesn't lead to merge conflicts
later, or people basing their stuff on stale code. But it isn't like
this is a high churn area.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply
* [PATCH 1/4] x86: remove cast from void*
From: matt mooney @ 2010-09-14 5:18 UTC (permalink / raw)
To: Jeremy Fitzhardinge
Cc: Ian Campbell, matt mooney, x86, kernel-janitors, Chris Wright,
virtualization, Ingo Molnar, H. Peter Anvin, Tejun Heo,
Thomas Gleixner, xen-devel
Unnecessary cast from void* in assignment.
Signed-off-by: matt mooney <mfm@muteddisk.com>
---
arch/x86/xen/mmu.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 42086ac..7436283 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -737,7 +737,7 @@ pgd_t *xen_get_user_pgd(pgd_t *pgd)
if (offset < pgd_index(USER_LIMIT)) {
struct page *page = virt_to_page(pgd_page);
- user_ptr = (pgd_t *)page->private;
+ user_ptr = page->private;
if (user_ptr)
user_ptr += offset;
}
--
1.7.2.1
^ permalink raw reply related
* [PATCH] virtio: console: Prevent userspace from submitting NULL buffers
From: Amit Shah @ 2010-09-14 7:56 UTC (permalink / raw)
To: Rusty Russell; +Cc: Amit Shah, stable, Virtualization List
A userspace could submit a buffer with 0 length to be written to the
host. Prevent such a situation.
This was not needed previously, but recent changes in the way write()
works exposed this condition to trigger a virtqueue event to the host,
causing a NULL buffer to be sent across.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
CC: stable@kernel.org
---
drivers/char/virtio_console.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index f7adfd3..be67d6b 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -653,6 +653,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
ssize_t ret;
bool nonblock;
+ /* Userspace could be out to fool us */
+ if (!count)
+ return 0;
+
port = filp->private_data;
nonblock = filp->f_flags & O_NONBLOCK;
--
1.7.2.2
^ permalink raw reply related
* [PATCH] vhost-net: fix range checking in mrg bufs case
From: Michael S. Tsirkin @ 2010-09-14 13:15 UTC (permalink / raw)
To: Michael S. Tsirkin, kvm, virtualization, netdev, linux-kernel
In mergeable buffer case, we use headcount, log_num
and seg as indexes in same-size arrays, and
we know that headcount <= seg and
log_num equals either 0 or seg.
Therefore, the right thing to do is range-check seg,
not headcount as we do now: these will be different
if guest chains s/g descriptors (this does not
happen now, but we can not trust the guest).
Long term, we should add BUG_ON checks to verify
two other indexes are what we think they should be.
Reported-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, I'll queue this on my tree, no need to bother.
drivers/vhost/net.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 6400cd5..f095de6 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -245,7 +245,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
int r, nlogs = 0;
while (datalen > 0) {
- if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
+ if (unlikely(seg >= VHOST_NET_MAX_SG)) {
r = -ENOBUFS;
goto err;
}
--
1.7.3.rc1.5.ge5969
^ permalink raw reply related
* [PATCH] vhost: max s/g to match qemu
From: Jason Wang @ 2010-09-14 15:53 UTC (permalink / raw)
To: virtualization, netdev, linux-kernel, kvm, mst
Qemu supports up to UIO_MAXIOV s/g so we have to match that because guest
drivers may rely on this.
Allocate indirect and log arrays dynamically to avoid using too much contigious
memory and make the length of hdr array to match the header length since each
iovec entry has a least one byte.
Test with copying large files w/ and w/o migration in both linux and windows
guests.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/vhost/net.c | 2 +-
drivers/vhost/vhost.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
drivers/vhost/vhost.h | 18 ++++++++----------
3 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 29e850a..e828ef1 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -243,7 +243,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
int r, nlogs = 0;
while (datalen > 0) {
- if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
+ if (unlikely(headcount >= UIO_MAXIOV)) {
r = -ENOBUFS;
goto err;
}
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c579dcc..a45270e 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -212,6 +212,45 @@ static int vhost_worker(void *data)
}
}
+/* Helper to allocate iovec buffers for all vqs. */
+static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
+{
+ int i;
+ for (i = 0; i < dev->nvqs; ++i) {
+ dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
+ UIO_MAXIOV, GFP_KERNEL);
+ dev->vqs[i].log = kmalloc(sizeof *dev->vqs[i].log * UIO_MAXIOV,
+ GFP_KERNEL);
+ dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
+ UIO_MAXIOV, GFP_KERNEL);
+
+ if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
+ !dev->vqs[i].heads)
+ goto err_nomem;
+ }
+ return 0;
+err_nomem:
+ for (; i >= 0; --i) {
+ kfree(dev->vqs[i].indirect);
+ kfree(dev->vqs[i].log);
+ kfree(dev->vqs[i].heads);
+ }
+ return -ENOMEM;
+}
+
+static void vhost_dev_free_iovecs(struct vhost_dev *dev)
+{
+ int i;
+ for (i = 0; i < dev->nvqs; ++i) {
+ kfree(dev->vqs[i].indirect);
+ dev->vqs[i].indirect = NULL;
+ kfree(dev->vqs[i].log);
+ dev->vqs[i].log = NULL;
+ kfree(dev->vqs[i].heads);
+ dev->vqs[i].heads = NULL;
+ }
+}
+
long vhost_dev_init(struct vhost_dev *dev,
struct vhost_virtqueue *vqs, int nvqs)
{
@@ -229,6 +268,9 @@ long vhost_dev_init(struct vhost_dev *dev,
dev->worker = NULL;
for (i = 0; i < dev->nvqs; ++i) {
+ dev->vqs[i].log = NULL;
+ dev->vqs[i].indirect = NULL;
+ dev->vqs[i].heads = NULL;
dev->vqs[i].dev = dev;
mutex_init(&dev->vqs[i].mutex);
vhost_vq_reset(dev, dev->vqs + i);
@@ -295,6 +337,10 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
if (err)
goto err_cgroup;
+ err = vhost_dev_alloc_iovecs(dev);
+ if (err)
+ goto err_cgroup;
+
return 0;
err_cgroup:
kthread_stop(worker);
@@ -345,6 +391,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
fput(dev->vqs[i].call);
vhost_vq_reset(dev, dev->vqs + i);
}
+ vhost_dev_free_iovecs(dev);
if (dev->log_ctx)
eventfd_ctx_put(dev->log_ctx);
dev->log_ctx = NULL;
@@ -946,7 +993,7 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
}
ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
- ARRAY_SIZE(vq->indirect));
+ UIO_MAXIOV);
if (unlikely(ret < 0)) {
vq_err(vq, "Translation failure %d in indirect.\n", ret);
return ret;
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index afd7729..edc8929 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -15,11 +15,6 @@
struct vhost_device;
-enum {
- /* Enough place for all fragments, head, and virtio net header. */
- VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
-};
-
struct vhost_work;
typedef void (*vhost_work_fn_t)(struct vhost_work *work);
@@ -93,12 +88,15 @@ struct vhost_virtqueue {
bool log_used;
u64 log_addr;
- struct iovec indirect[VHOST_NET_MAX_SG];
- struct iovec iov[VHOST_NET_MAX_SG];
- struct iovec hdr[VHOST_NET_MAX_SG];
+ struct iovec iov[UIO_MAXIOV];
+ /* hdr is used to store the virtio header.
+ * Since each iovec has >= 1 byte length, we never need more than
+ * header length entries to store the header. */
+ struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)];
+ struct iovec *indirect;
size_t vhost_hlen;
size_t sock_hlen;
- struct vring_used_elem heads[VHOST_NET_MAX_SG];
+ struct vring_used_elem *heads;
/* We use a kind of RCU to access private pointer.
* All readers access it from worker, which makes it possible to
* flush the vhost_work instead of synchronize_rcu. Therefore readers do
@@ -109,7 +107,7 @@ struct vhost_virtqueue {
void *private_data;
/* Log write descriptors */
void __user *log_base;
- struct vhost_log log[VHOST_NET_MAX_SG];
+ struct vhost_log *log;
};
struct vhost_dev {
^ permalink raw reply related
* Re: [PATCH] vhost: max s/g to match qemu
From: Michael S. Tsirkin @ 2010-09-14 16:01 UTC (permalink / raw)
To: Jason Wang; +Cc: virtualization, netdev, linux-kernel, kvm
In-Reply-To: <20100914155305.3293.92519.stgit@dhcp-91-7.nay.redhat.com.englab.nay.redhat.com>
On Tue, Sep 14, 2010 at 11:53:05PM +0800, Jason Wang wrote:
> Qemu supports up to UIO_MAXIOV s/g so we have to match that because guest
> drivers may rely on this.
>
> Allocate indirect and log arrays dynamically to avoid using too much contigious
> memory and make the length of hdr array to match the header length since each
> iovec entry has a least one byte.
>
> Test with copying large files w/ and w/o migration in both linux and windows
> guests.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Looks good, I'll queue this up for 2.6.37.
Thanks!
> ---
> drivers/vhost/net.c | 2 +-
> drivers/vhost/vhost.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
> drivers/vhost/vhost.h | 18 ++++++++----------
> 3 files changed, 57 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 29e850a..e828ef1 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -243,7 +243,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
> int r, nlogs = 0;
>
> while (datalen > 0) {
> - if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
> + if (unlikely(headcount >= UIO_MAXIOV)) {
> r = -ENOBUFS;
> goto err;
> }
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index c579dcc..a45270e 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -212,6 +212,45 @@ static int vhost_worker(void *data)
> }
> }
>
> +/* Helper to allocate iovec buffers for all vqs. */
> +static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
> +{
> + int i;
> + for (i = 0; i < dev->nvqs; ++i) {
> + dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
> + UIO_MAXIOV, GFP_KERNEL);
> + dev->vqs[i].log = kmalloc(sizeof *dev->vqs[i].log * UIO_MAXIOV,
> + GFP_KERNEL);
> + dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
> + UIO_MAXIOV, GFP_KERNEL);
> +
> + if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
> + !dev->vqs[i].heads)
> + goto err_nomem;
> + }
> + return 0;
> +err_nomem:
> + for (; i >= 0; --i) {
> + kfree(dev->vqs[i].indirect);
> + kfree(dev->vqs[i].log);
> + kfree(dev->vqs[i].heads);
We probably want to assign NULL values here, same as below.
I have fixed this up in my tree.
> + }
> + return -ENOMEM;
> +}
> +
> +static void vhost_dev_free_iovecs(struct vhost_dev *dev)
> +{
> + int i;
> + for (i = 0; i < dev->nvqs; ++i) {
> + kfree(dev->vqs[i].indirect);
> + dev->vqs[i].indirect = NULL;
> + kfree(dev->vqs[i].log);
> + dev->vqs[i].log = NULL;
> + kfree(dev->vqs[i].heads);
> + dev->vqs[i].heads = NULL;
> + }
> +}
> +
> long vhost_dev_init(struct vhost_dev *dev,
> struct vhost_virtqueue *vqs, int nvqs)
> {
> @@ -229,6 +268,9 @@ long vhost_dev_init(struct vhost_dev *dev,
> dev->worker = NULL;
>
> for (i = 0; i < dev->nvqs; ++i) {
> + dev->vqs[i].log = NULL;
> + dev->vqs[i].indirect = NULL;
> + dev->vqs[i].heads = NULL;
> dev->vqs[i].dev = dev;
> mutex_init(&dev->vqs[i].mutex);
> vhost_vq_reset(dev, dev->vqs + i);
> @@ -295,6 +337,10 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
> if (err)
> goto err_cgroup;
>
> + err = vhost_dev_alloc_iovecs(dev);
> + if (err)
> + goto err_cgroup;
> +
> return 0;
> err_cgroup:
> kthread_stop(worker);
> @@ -345,6 +391,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
> fput(dev->vqs[i].call);
> vhost_vq_reset(dev, dev->vqs + i);
> }
> + vhost_dev_free_iovecs(dev);
> if (dev->log_ctx)
> eventfd_ctx_put(dev->log_ctx);
> dev->log_ctx = NULL;
> @@ -946,7 +993,7 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
> }
>
> ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
> - ARRAY_SIZE(vq->indirect));
> + UIO_MAXIOV);
> if (unlikely(ret < 0)) {
> vq_err(vq, "Translation failure %d in indirect.\n", ret);
> return ret;
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index afd7729..edc8929 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -15,11 +15,6 @@
>
> struct vhost_device;
>
> -enum {
> - /* Enough place for all fragments, head, and virtio net header. */
> - VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
> -};
> -
> struct vhost_work;
> typedef void (*vhost_work_fn_t)(struct vhost_work *work);
>
> @@ -93,12 +88,15 @@ struct vhost_virtqueue {
> bool log_used;
> u64 log_addr;
>
> - struct iovec indirect[VHOST_NET_MAX_SG];
> - struct iovec iov[VHOST_NET_MAX_SG];
> - struct iovec hdr[VHOST_NET_MAX_SG];
> + struct iovec iov[UIO_MAXIOV];
> + /* hdr is used to store the virtio header.
> + * Since each iovec has >= 1 byte length, we never need more than
> + * header length entries to store the header. */
> + struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)];
> + struct iovec *indirect;
> size_t vhost_hlen;
> size_t sock_hlen;
> - struct vring_used_elem heads[VHOST_NET_MAX_SG];
> + struct vring_used_elem *heads;
> /* We use a kind of RCU to access private pointer.
> * All readers access it from worker, which makes it possible to
> * flush the vhost_work instead of synchronize_rcu. Therefore readers do
> @@ -109,7 +107,7 @@ struct vhost_virtqueue {
> void *private_data;
> /* Log write descriptors */
> void __user *log_base;
> - struct vhost_log log[VHOST_NET_MAX_SG];
> + struct vhost_log *log;
> };
>
> struct vhost_dev {
^ permalink raw reply
* Re: [PATCH 1/4] x86: remove cast from void*
From: Jeremy Fitzhardinge @ 2010-09-14 17:49 UTC (permalink / raw)
To: matt mooney
Cc: xen-devel, Jeremy Fitzhardinge, x86, kernel-janitors,
Chris Wright, virtualization, Ingo Molnar, H. Peter Anvin,
Tejun Heo, Thomas Gleixner, Ian Campbell
In-Reply-To: <1284441511-11511-1-git-send-email-mfm@muteddisk.com>
On 09/13/2010 10:18 PM, matt mooney wrote:
> Unnecessary cast from void* in assignment.
Not very keen on this. The cast may not be strictly required, but it
does document what's going on there.
J
> Signed-off-by: matt mooney <mfm@muteddisk.com>
> ---
> arch/x86/xen/mmu.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
> index 42086ac..7436283 100644
> --- a/arch/x86/xen/mmu.c
> +++ b/arch/x86/xen/mmu.c
> @@ -737,7 +737,7 @@ pgd_t *xen_get_user_pgd(pgd_t *pgd)
>
> if (offset < pgd_index(USER_LIMIT)) {
> struct page *page = virt_to_page(pgd_page);
> - user_ptr = (pgd_t *)page->private;
> + user_ptr = page->private;
> if (user_ptr)
> user_ptr += offset;
> }
^ permalink raw reply
* Re: [PATCH 1/4] x86: remove cast from void*
From: H. Peter Anvin @ 2010-09-14 18:20 UTC (permalink / raw)
To: Jeremy Fitzhardinge
Cc: xen-devel, Jeremy Fitzhardinge, matt mooney, x86, kernel-janitors,
Chris Wright, virtualization, Ingo Molnar, Tejun Heo,
Thomas Gleixner, Ian Campbell
In-Reply-To: <4C8FB5C3.3050806@goop.org>
On 09/14/2010 10:49 AM, Jeremy Fitzhardinge wrote:
> On 09/13/2010 10:18 PM, matt mooney wrote:
>> Unnecessary cast from void* in assignment.
>
> Not very keen on this. The cast may not be strictly required, but it
> does document what's going on there.
>
But unnecessary casts are problematic in that if the type changes, they
can hide a real bug in the future.
-hpa
^ 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