* Re: [PATCH v2 -next] 6LoWPAN: fix skb_copy call
From: Daniel Baluta @ 2011-09-01 12:10 UTC (permalink / raw)
To: Alexander Smirnov
Cc: davem, dbaryshkov, slapin, linux-zigbee-devel, netdev,
eric.dumazet, kernel-janitors
In-Reply-To: <1314881653-1104-1-git-send-email-alex.bluesman.smirnov@gmail.com>
> + if (NULL == skb) {
> + stat = -ENOMEM;
> + break;
> + }
This can hurt our eyes :). I think the common convention
is to use: "if (skb == NULL) " or simply "if (!skb) "
thanks,
Daniel.
^ permalink raw reply
* [PATCH 1/1 -next] 6LoWPAN: fix skb_copy call
From: Alexander Smirnov @ 2011-09-01 12:21 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
This patch fixes 2 issues in lowpan_skb_deliver function:
1. Check for return status of skb_copy call;
2. Use skb_copy with proper GFP flag depending on context.
Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index cf304cc..cac1361 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -477,9 +477,15 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
struct sk_buff *new;
struct lowpan_dev_record *entry;
int stat = NET_RX_SUCCESS;
+ gfp_t mask;
- new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
- GFP_KERNEL);
+ if (in_interrupt())
+ mask = GFP_ATOMIC;
+ else
+ mask = GFP_KERNEL;
+
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr),
+ skb_tailroom(skb), mask);
kfree_skb(skb);
if (NULL == new)
@@ -495,7 +501,13 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
rcu_read_lock();
list_for_each_entry_rcu(entry, &lowpan_devices, list)
if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
- skb = skb_copy(new, GFP_KERNEL);
+ skb = skb_copy(new, mask);
+
+ if (NULL == skb) {
+ kfree_skb(new);
+ return -ENOMEM;
+ }
+
skb->dev = entry->ldev;
if (in_interrupt())
--
1.7.2.5
------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
^ permalink raw reply related
* Re: [PATCH 2/2] Add a netlink attribute INET_DIAG_SECCTX
From: Paul Moore @ 2011-09-01 12:28 UTC (permalink / raw)
To: Rongqing Li; +Cc: netdev, selinux, linux-security-module
In-Reply-To: <4E5F5153.6070708@windriver.com>
On Thursday, September 01, 2011 05:33:07 PM Rongqing Li wrote:
> On 09/01/2011 05:18 AM, Paul Moore wrote:
> > On Wednesday, August 31, 2011 04:36:17 PM rongqing.li@windriver.com wrote:
> >> From: Roy.Li<rongqing.li@windriver.com>
> >>
> >> Add a new netlink attribute INET_DIAG_SECCTX to dump the security
> >> context of TCP sockets.
> >
> > You'll have to forgive me, I'm not familiar with the netlink code used
> > by
> > netstat and friends, but is there anyway to report back the security
> > context of UDP sockets? Or does the code below handle that already?
> >
> > In general, AF_INET and AF_INET6 sockets, regardless of any upper level
> > protocols, have security contexts associated with them and it would be
> > nice to see them in netstat.
>
> Yes, this is real concern, If the dumping tcp security context can be
> accepted by netdev, I am planning to implement it for ipv4 udp socket, unix
> socket. then ipv6..
Great, I'm glad to hear you're planning on implementing this for more than
just TCP.
I understand your desire to have the basic idea accepted with only TCP
implemented - and that is fine with me - but I would like to see support for
all of the protocols merged at the same time. In other words, seeking the
basic ACKs for TCP from the davem, et al is okay but I'd like to defer merging
TCP support until you have everything implemented and ready to be merged.
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 -next] 6LoWPAN: fix skb_copy call
From: Alexander Smirnov @ 2011-09-01 12:34 UTC (permalink / raw)
To: Eric Dumazet
Cc: davem, dbaryshkov, slapin, linux-zigbee-devel, netdev,
kernel-janitors
In-Reply-To: <1314878443.2823.6.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Hi Eric,
hmm, I think you are right.
First 6LoWPAN implementation was developed as a part of MAC layer and
code was based on this layer approach. But now 6lowpan is
MAC-independent, it's just a netif_rx hook and looks like I missed
this moment during migration.
sorry for confusion.
With best regards,
Alexander
2011/9/1 Eric Dumazet <eric.dumazet@gmail.com>:
> Le jeudi 01 septembre 2011 à 16:54 +0400, Alexander Smirnov a écrit :
>> This patch fixes 2 issues in lowpan_skb_deliver function:
>> 1. Check for return status of skb_copy call;
>> 2. Use skb_copy with proper GFP flag depending on context.
>>
>> Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
>> ---
>> net/ieee802154/6lowpan.c | 18 +++++++++++++++---
>> 1 files changed, 15 insertions(+), 3 deletions(-)
>>
>> diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
>> index cf304cc..16100be 100644
>> --- a/net/ieee802154/6lowpan.c
>> +++ b/net/ieee802154/6lowpan.c
>> @@ -477,9 +477,15 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
>> struct sk_buff *new;
>> struct lowpan_dev_record *entry;
>> int stat = NET_RX_SUCCESS;
>> + gfp_t mask;
>>
>> - new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
>> - GFP_KERNEL);
>> + if (in_interrupt())
>> + mask = GFP_ATOMIC;
>> + else
>> + mask = GFP_KERNEL;
>
> I am not sure to understand if lowpan_skb_deliver() can be called in
> pure process context. I feel we are in softirq handler or we have
> disabled BH, so GFP_ATOMIC is the only choice.
>
> If you are unsure, you could use following helper :
>
> mask = gfp_any();
>
>> +
>> + new = skb_copy_expand(skb, sizeof(struct ipv6hdr),
>> + skb_tailroom(skb), mask);
>> kfree_skb(skb);
>>
>
>
^ permalink raw reply
* e1000e - BUG: sleeping function called from invalid context
From: Francois Romieu @ 2011-09-01 12:20 UTC (permalink / raw)
To: netdev
Cc: Jeff Kirsher, Jesse Brandeburg, Bruce Allan, Carolyn Wyborny,
Don Skidmore, Greg Rose, PJ Waskiewicz, Alex Duyck, John Ronciak
I got this one while running plain 'ip link show' with linus's post
3.1.0-rc3 (CONFIG_DEBUG_ATOMIC_SLEEP=y, 82544 LOM with Intel DP55KG
motherboard):
[18628.524980] BUG: sleeping function called from invalid context at /home/romieu/git/linux-2.6-ref/kernel/mutex.c:85
[18628.524987] in_atomic(): 1, irqs_disabled(): 0, pid: 1204, name: irqbalance
[18628.524993] Pid: 1204, comm: irqbalance Not tainted 3.1.0-rc3+ #4
[18628.524996] Call Trace:
[18628.525007] [<ffffffff810421a1>] __might_sleep+0xeb/0xf0
[18628.525032] [<ffffffff814a9dd8>] mutex_lock+0x24/0x4a
[18628.525040] [<ffffffff8124dc82>] ? vsnprintf+0x83/0x44c
[18628.525057] [<ffffffffa01e1697>] e1000_acquire_swflag_ich8lan+0x27/0x138 [e1000e]
[18628.525078] [<ffffffffa01f0bae>] e1000e_update_stats+0x158/0x750 [e1000e]
[18628.525098] [<ffffffffa01f11e8>] e1000e_get_stats64+0x42/0x143 [e1000e]
[18628.525105] [<ffffffff813f4986>] dev_get_stats+0x38/0x7a
[18628.525110] [<ffffffff813f49f0>] dev_seq_printf_stats+0x28/0xf8
[18628.525118] [<ffffffff813f33e2>] ? dev_seq_start+0x1f/0x70
[18628.525123] [<ffffffff813f4ae2>] dev_seq_show+0x22/0x26
The path looks the same in linus's (9e79e3e9dd9672b37ac9412e9a926714306551fe)
and in davem's net-next (3857e3ee2209b7289c434103e366f765ec82a22d) branches:
e1000e_get_stats64
-> spin_lock(&adapter->stats64_lock);
e1000e_update_stats
-> e1000e_update_phy_stats
-> e1000_acquire_swflag_ich8lan (through hw->phy.ops.acquire)
-> mutex_lock(&swflag_mutex);
Can you fix it ?
(either turn stats64_lock into a mutex or remove it - and swflag_mutex as
well ? - and use the rtnl sem in your work tasks from a quick glance at
the code)
Thanks.
--
Ueimor
^ permalink raw reply
* [PATCH v2 -next] 6LoWPAN: fix skb_copy call
From: Alexander Smirnov @ 2011-09-01 12:54 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1314879675-31989-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch fixes 2 issues in lowpan_skb_deliver function:
1. Check for return status of skb_copy call;
2. Use skb_copy with proper GFP flag depending on context.
Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index cf304cc..16100be 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -477,9 +477,15 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
struct sk_buff *new;
struct lowpan_dev_record *entry;
int stat = NET_RX_SUCCESS;
+ gfp_t mask;
- new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
- GFP_KERNEL);
+ if (in_interrupt())
+ mask = GFP_ATOMIC;
+ else
+ mask = GFP_KERNEL;
+
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr),
+ skb_tailroom(skb), mask);
kfree_skb(skb);
if (NULL == new)
@@ -495,7 +501,13 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
rcu_read_lock();
list_for_each_entry_rcu(entry, &lowpan_devices, list)
if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
- skb = skb_copy(new, GFP_KERNEL);
+ skb = skb_copy(new, mask);
+
+ if (NULL == skb) {
+ stat = -ENOMEM;
+ break;
+ }
+
skb->dev = entry->ldev;
if (in_interrupt())
--
1.7.2.5
------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
^ permalink raw reply related
* Re: slow performance on disk/network i/o full speed after drop_caches
From: Mel Gorman @ 2011-09-01 12:57 UTC (permalink / raw)
To: Wu Fengguang
Cc: Stefan Priebe - Profihost AG, Zhu Yanhai, Pekka Enberg, LKML,
linux-mm@kvack.org, Andrew Morton, Jens Axboe, Linux Netdev List,
KOSAKI Motohiro
In-Reply-To: <20110901041458.GA30123@localhost>
On Thu, Sep 01, 2011 at 12:14:58PM +0800, Wu Fengguang wrote:
> Hi Stefan,
>
> On Wed, Aug 31, 2011 at 03:11:02PM +0800, Stefan Priebe - Profihost AG wrote:
> > Hi Fengguang,
> > Hi Yanhai,
> >
> > > you're abssolutely corect zone_reclaim_mode is on - but why?
> > > There must be some linux software which switches it on.
> > >
> > > ~# grep 'zone_reclaim_mode' /etc/sysctl.* -r -i
> > > ~#
> > >
> > > also
> > > ~# grep 'zone_reclaim_mode' /etc/sysctl.* -r -i
> > > ~#
> > >
> > > tells us nothing.
> > >
> > > I've then read this:
> > >
> > > "zone_reclaim_mode is set during bootup to 1 if it is determined that
> > > pages from remote zones will cause a measurable performance reduction.
> > > The page allocator will then reclaim easily reusable pages (those page
> > > cache pages that are currently not used) before allocating off node pages."
> > >
> > > Why does the kernel do that here in our case on these machines.
> >
> > Can nobody help why the kernel in this case set it to 1?
>
> It's determined by RECLAIM_DISTANCE.
>
> build_zonelists():
>
> /*
> * If another node is sufficiently far away then it is better
> * to reclaim pages in a zone before going off node.
> */
> if (distance > RECLAIM_DISTANCE)
> zone_reclaim_mode = 1;
>
> Since Linux v3.0 RECLAIM_DISTANCE is increased from 20 to 30 by this commit.
> It may well help your case, too.
>
Even with that, it's known that zone_reclaim() can be a disaster when
it runs into problems. This should be fixed in 3.1 by the following
commits;
[cd38b115 mm: page allocator: initialise ZLC for first zone eligible for zone_reclaim]
[76d3fbf8 mm: page allocator: reconsider zones for allocation after direct reclaim]
The description in cd38b115 has the interesting details.
--
Mel Gorman
SUSE Labs
^ permalink raw reply
* [patch net-next-2.6] br: remove redundant check and init
From: Jiri Pirko @ 2011-09-01 13:29 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, shemminger, bridge
Since these checks and initialization are done in
dev_ethtool_get_settings called later on, remove this redundancy.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
net/bridge/br_if.c | 24 +++++++++++-------------
1 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 2cdf007..b365bba 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -33,20 +33,18 @@
*/
static int port_cost(struct net_device *dev)
{
- if (dev->ethtool_ops && dev->ethtool_ops->get_settings) {
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, };
-
- if (!dev_ethtool_get_settings(dev, &ecmd)) {
- switch (ethtool_cmd_speed(&ecmd)) {
- case SPEED_10000:
- return 2;
- case SPEED_1000:
- return 4;
- case SPEED_100:
- return 19;
- case SPEED_10:
- return 100;
- }
+ struct ethtool_cmd ecmd;
+
+ if (!dev_ethtool_get_settings(dev, &ecmd)) {
+ switch (ethtool_cmd_speed(&ecmd)) {
+ case SPEED_10000:
+ return 2;
+ case SPEED_1000:
+ return 4;
+ case SPEED_100:
+ return 19;
+ case SPEED_10:
+ return 100;
}
}
--
1.7.6
^ permalink raw reply related
* [PATCH v3 -next] 6LoWPAN: fix skb_copy call
From: Alexander Smirnov @ 2011-09-01 13:55 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1314879675-31989-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch fixes 2 issues in lowpan_skb_deliver function:
1. Check for return status of skb_copy call;
2. Use skb_copy with proper GFP flag, drop check for non-interrupt
context.
Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index cf304cc..deb2adf 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -479,10 +479,10 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
int stat = NET_RX_SUCCESS;
new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
- GFP_KERNEL);
+ GFP_ATOMIC);
kfree_skb(skb);
- if (NULL == new)
+ if (!new)
return -ENOMEM;
skb_push(new, sizeof(struct ipv6hdr));
@@ -495,13 +495,14 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
rcu_read_lock();
list_for_each_entry_rcu(entry, &lowpan_devices, list)
if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
- skb = skb_copy(new, GFP_KERNEL);
- skb->dev = entry->ldev;
+ skb = skb_copy(new, GFP_ATOMIC);
+ if (!skb) {
+ stat = -ENOMEM;
+ break;
+ }
- if (in_interrupt())
- stat = netif_rx(skb);
- else
- stat = netif_rx_ni(skb);
+ skb->dev = entry->ldev;
+ stat = netif_rx(skb);
}
rcu_read_unlock();
--
1.7.2.5
------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
^ permalink raw reply related
* Re: BQL crap and wireless
From: John W. Linville @ 2011-09-01 14:13 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Jim Gettys, Andrew McGregor, Adrian Chadd, Tom Herbert, Dave Taht,
linux-wireless, Matt Smith, Kevin Hayes, Derek Smithies,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAB=NE6Wj4BxSjZmTOg9EFMcJ+H0RBZE4q8+6DB3x8qP=r42yNQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, Aug 31, 2011 at 01:50:48PM -0700, Luis R. Rodriguez wrote:
> On Wed, Aug 31, 2011 at 6:28 AM, Jim Gettys <jg-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org> wrote:
> > such as wireless, or even possibly modern broadband with
> > PowerBoost, classic RED or similar algorithms that do not take the
> > buffer drain rate cannot possibly hack it properly.
>
> Understood, just curious if anyone has tried a Minstrel approach.
FWIW, eBDP and the related algorithms from Tianji Li's paper are
philosophically similar to minstrel. They depend on measuring recent
conditions and modifying the current queue length accordingly.
http://www.hamilton.ie/tianji_li/buffersizing.pdf
The hack I added in debloat-testing is based on my understanding
of eBDP. It timestamps the SKBs when they are handed to the driver
for Tx and then checks the timestamp when the SKB is orphaned. It is
a bit crude and is an abuse of the skb_orphan API. Also while it
accounts for the 802.11e queues separately, it doesn't account for
802.11n aggregation. Still, it seems to improve latency w/o hugely
impacting throughput in at least some environments -- YMMV!
John
--
John W. Linville Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org might be all we have. Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] net: Initialize entire flowi struct
From: Ward, David - 0663 - MITLL @ 2011-09-01 13:34 UTC (permalink / raw)
To: Julian Anastasov; +Cc: David Miller, netdev@vger.kernel.org
In-Reply-To: <alpine.LFD.2.00.1108312321400.1826@ja.ssi.bg>
[-- Attachment #1: Type: text/plain, Size: 2527 bytes --]
Hi Julian,
On 08/31/2011 04:51 PM, Julian Anastasov wrote:
> On Wed, 31 Aug 2011, David Ward wrote
>> The entire flowi struct needs to be initialized by afinfo->decode_session,
>> because flow_hash_code operates over the entire struct and may otherwise
>> return different hash values for what is intended to be the same key.
> Such change will cause problems for callers that
> use flowi4 in stack. Examples:
>
> ip_route_me_harder
> icmp_route_lookup
Thanks for pointing this out.
> Not sure if adding size as parameter to flow_hash_code
> is better approach. May be flow_cache_lookup needs to
> determine size from family that can be used for flow_hash_code,
> flow_key_compare and the memcpy(&fle->key, key, sizeof(*key))
> after fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC).
Makes sense to me. However should we just replace flow_key_compare with
memcmp then, since the assumptions about constant size and alignment
will no longer apply? Or should there be a separate flow_key_compare
function for each family, and have all of the flowi* structures become
__attribute__((__aligned__(BITS_PER_LONG/8))) ?
David
> The question is how to get size by family.
>
>> Signed-off-by: David Ward<david.ward@ll.mit.edu>
>> ---
>> net/ipv4/xfrm4_policy.c | 2 +-
>> net/ipv6/xfrm6_policy.c | 2 +-
>> 2 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
>> index fc5368a..afce24d 100644
>> --- a/net/ipv4/xfrm4_policy.c
>> +++ b/net/ipv4/xfrm4_policy.c
>> @@ -114,7 +114,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
>> u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
>> struct flowi4 *fl4 =&fl->u.ip4;
>>
>> - memset(fl4, 0, sizeof(struct flowi4));
>> + memset(fl, 0, sizeof(struct flowi));
>> fl4->flowi4_mark = skb->mark;
>>
>> if (!ip_is_fragment(iph)) {
>> diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
>> index d879f7e..9088d38 100644
>> --- a/net/ipv6/xfrm6_policy.c
>> +++ b/net/ipv6/xfrm6_policy.c
>> @@ -129,7 +129,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
>> const unsigned char *nh = skb_network_header(skb);
>> u8 nexthdr = nh[IP6CB(skb)->nhoff];
>>
>> - memset(fl6, 0, sizeof(struct flowi6));
>> + memset(fl, 0, sizeof(struct flowi));
>> fl6->flowi6_mark = skb->mark;
>>
>> ipv6_addr_copy(&fl6->daddr, reverse ?&hdr->saddr :&hdr->daddr);
>> --
>> 1.7.4.1
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4184 bytes --]
^ permalink raw reply
* [PATCH net-next] can-gw: add netlink based CAN routing
From: Oliver Hartkopp @ 2011-09-01 14:23 UTC (permalink / raw)
To: David Miller
Cc: Linux Netdev List, Michal Sojka, Pavel Píša,
Zdenek Hanzálek, Oliver Hartkopp
This patch adds a CAN Gateway/Router to route (and modify) CAN frames.
It is based on the PF_CAN core infrastructure for msg filtering and msg
sending and can optionally modify routed CAN frames on the fly.
CAN frames can *only* be routed between CAN network interfaces (one hop).
They can be modified with AND/OR/XOR/SET operations as configured by the
netlink configuration interface known e.g. from iptables. From the netlink
view this can-gw implements RTM_{NEW|DEL|GET}ROUTE for PF_CAN.
The CAN specific userspace tool to manage CAN routing entries can be found in
the CAN utils http://svn.berlios.de/wsvn/socketcan/trunk/can-utils/cangw.c
at the SocketCAN SVN on BerliOS.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
The in-kernel CAN frame routing has been implemented to due performance
issues and has turned out to be a valuable tool in multiple projects.
It relies on the networking stack and uses the efficient PF_CAN CAN filters.
It has been analyzed and checked against -rt kernels by University of Prague
(DCE), where a real good performace of this approach could be shown. Only
with heavy ethernet load the routing times increased - but that's networking.
See at http://rtime.felk.cvut.cz/can/benchmark/1/ and .../benchmark/2/
Special thanks for review, feedback, bug-reports & measurements to Michal
Sojka, Pavel Píša and Zdenek Hanzálek from department of control engineering.
include/linux/can/Kbuild | 1
include/linux/can/gw.h | 164 ++++++
net/can/Kconfig | 11
net/can/Makefile | 3
net/can/gw.c | 959 +++++++++++++++++++++++++++++++++++++
5 files changed, 1138 insertions(+)
diff -u -r -N a/include/linux/can/gw.h b/include/linux/can/gw.h
--- a/include/linux/can/gw.h 1970-01-01 01:00:00.000000000 +0100
+++ b/include/linux/can/gw.h 2011-09-01 11:33:47.966271223 +0200
@@ -0,0 +1,164 @@
+/*
+ * linux/can/gw.h
+ *
+ * Definitions for CAN frame Gateway/Router/Bridge
+ *
+ * Author: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+ * Copyright (c) 2011 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#ifndef CAN_GW_H
+#define CAN_GW_H
+
+#include <linux/types.h>
+#include <linux/can.h>
+
+struct rtcanmsg {
+ __u8 can_family;
+ __u8 gwtype;
+ __u16 flags;
+};
+
+/* CAN gateway types */
+enum {
+ CGW_TYPE_UNSPEC,
+ CGW_TYPE_CAN_CAN, /* CAN->CAN routing */
+ __CGW_TYPE_MAX
+};
+
+#define CGW_TYPE_MAX (__CGW_TYPE_MAX - 1)
+
+/* CAN rtnetlink attribute definitions */
+enum {
+ CGW_UNSPEC,
+ CGW_MOD_AND, /* CAN frame modification binary AND */
+ CGW_MOD_OR, /* CAN frame modification binary OR */
+ CGW_MOD_XOR, /* CAN frame modification binary XOR */
+ CGW_MOD_SET, /* CAN frame modification set alternate values */
+ CGW_CS_XOR, /* set data[] XOR checksum into data[index] */
+ CGW_CS_CRC8, /* set data[] CRC8 checksum into data[index] */
+ CGW_HANDLED, /* number of handled CAN frames */
+ CGW_DROPPED, /* number of dropped CAN frames */
+ CGW_SRC_IF, /* ifindex of source network interface */
+ CGW_DST_IF, /* ifindex of destination network interface */
+ CGW_FILTER, /* specify struct can_filter on source CAN device */
+ __CGW_MAX
+};
+
+#define CGW_MAX (__CGW_MAX - 1)
+
+#define CGW_FLAGS_CAN_ECHO 0x01
+#define CGW_FLAGS_CAN_SRC_TSTAMP 0x02
+
+#define CGW_MOD_FUNCS 4 /* AND OR XOR SET */
+
+/* CAN frame elements that are affected by curr. 3 CAN frame modifications */
+#define CGW_MOD_ID 0x01
+#define CGW_MOD_DLC 0x02
+#define CGW_MOD_DATA 0x04
+
+#define CGW_FRAME_MODS 3 /* ID DLC DATA */
+
+#define MAX_MODFUNCTIONS (CGW_MOD_FUNCS * CGW_FRAME_MODS)
+
+struct cgw_frame_mod {
+ struct can_frame cf;
+ __u8 modtype;
+} __attribute__((packed));
+
+#define CGW_MODATTR_LEN sizeof(struct cgw_frame_mod)
+
+struct cgw_csum_xor {
+ __s8 from_idx;
+ __s8 to_idx;
+ __s8 result_idx;
+ __u8 init_xor_val;
+} __attribute__((packed));
+
+struct cgw_csum_crc8 {
+ __s8 from_idx;
+ __s8 to_idx;
+ __s8 result_idx;
+ __u8 init_crc_val;
+ __u8 final_xor_val;
+ __u8 crctab[256];
+ __u8 profile;
+ __u8 profile_data[20];
+} __attribute__((packed));
+
+/* length of checksum operation parameters. idx = index in CAN frame data[] */
+#define CGW_CS_XOR_LEN sizeof(struct cgw_csum_xor)
+#define CGW_CS_CRC8_LEN sizeof(struct cgw_csum_crc8)
+
+/* CRC8 profiles (compute CRC for additional data elements - see below) */
+enum {
+ CGW_CRC8PRF_UNSPEC,
+ CGW_CRC8PRF_1U8, /* compute one additional u8 value */
+ CGW_CRC8PRF_16U8, /* u8 value table indexed by data[1] & 0xF */
+ CGW_CRC8PRF_SFFID_XOR, /* (can_id & 0xFF) ^ (can_id >> 8 & 0xFF) */
+ __CGW_CRC8PRF_MAX
+};
+
+#define CGW_CRC8PRF_MAX (__CGW_CRC8PRF_MAX - 1)
+
+/*
+ * CAN rtnetlink attribute contents in detail
+ *
+ * CGW_XXX_IF (length 4 bytes):
+ * Sets an interface index for source/destination network interfaces.
+ * For the CAN->CAN gwtype the indices of _two_ CAN interfaces are mandatory.
+ *
+ * CGW_FILTER (length 8 bytes):
+ * Sets a CAN receive filter for the gateway job specified by the
+ * struct can_filter described in include/linux/can.h
+ *
+ * CGW_MOD_XXX (length 17 bytes):
+ * Specifies a modification that's done to a received CAN frame before it is
+ * send out to the destination interface.
+ *
+ * <struct can_frame> data used as operator
+ * <u8> affected CAN frame elements
+ *
+ * CGW_CS_XOR (length 4 bytes):
+ * Set a simple XOR checksum starting with an initial value into
+ * data[result-idx] using data[start-idx] .. data[end-idx]
+ *
+ * The XOR checksum is calculated like this:
+ *
+ * xor = init_xor_val
+ *
+ * for (i = from_idx .. to_idx)
+ * xor ^= can_frame.data[i]
+ *
+ * can_frame.data[ result_idx ] = xor
+ *
+ * CGW_CS_CRC8 (length 282 bytes):
+ * Set a CRC8 value into data[result-idx] using a given 256 byte CRC8 table,
+ * a given initial value and a defined input data[start-idx] .. data[end-idx].
+ * Finally the result value is XOR'ed with the final_xor_val.
+ *
+ * The CRC8 checksum is calculated like this:
+ *
+ * crc = init_crc_val
+ *
+ * for (i = from_idx .. to_idx)
+ * crc = crctab[ crc ^ can_frame.data[i] ]
+ *
+ * can_frame.data[ result_idx ] = crc ^ final_xor_val
+ *
+ * The calculated CRC may contain additional source data elements that can be
+ * defined in the handling of 'checksum profiles' e.g. shown in AUTOSAR specs
+ * like http://www.autosar.org/download/R4.0/AUTOSAR_SWS_E2ELibrary.pdf
+ * E.g. the profile_data[] may contain additional u8 values (called DATA_IDs)
+ * that are used depending on counter values inside the CAN frame data[].
+ * So far only three profiles have been implemented for illustration.
+ *
+ * Remark: In general the attribute data is a linear buffer.
+ * Beware of sending unpacked or aligned structs!
+ */
+
+#endif
diff -u -r -N a/include/linux/can/Kbuild b/include/linux/can/Kbuild
--- a/include/linux/can/Kbuild 2011-08-31 21:28:47.515610142 +0200
+++ b/include/linux/can/Kbuild 2011-08-31 21:29:24.343608873 +0200
@@ -1,4 +1,5 @@
header-y += raw.h
header-y += bcm.h
+header-y += gw.h
header-y += error.h
header-y += netlink.h
diff -u -r -N a/net/can/gw.c b/net/can/gw.c
--- a/net/can/gw.c 1970-01-01 01:00:00.000000000 +0100
+++ b/net/can/gw.c 2011-09-01 11:26:56.898284721 +0200
@@ -0,0 +1,959 @@
+/*
+ * gw.c - CAN frame Gateway/Router/Bridge with netlink interface
+ *
+ * Copyright (c) 2011 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Volkswagen nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/rculist.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/skbuff.h>
+#include <linux/can.h>
+#include <linux/can/core.h>
+#include <linux/can/gw.h>
+#include <net/rtnetlink.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#define CAN_GW_VERSION "20101209"
+static __initdata const char banner[] =
+ KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
+
+MODULE_DESCRIPTION("PF_CAN netlink gateway");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+MODULE_ALIAS("can-gw");
+
+HLIST_HEAD(cgw_list);
+static struct notifier_block notifier;
+
+static struct kmem_cache *cgw_cache __read_mostly;
+
+/* structure that contains the (on-the-fly) CAN frame modifications */
+struct cf_mod {
+ struct {
+ struct can_frame and;
+ struct can_frame or;
+ struct can_frame xor;
+ struct can_frame set;
+ } modframe;
+ struct {
+ u8 and;
+ u8 or;
+ u8 xor;
+ u8 set;
+ } modtype;
+ void (*modfunc[MAX_MODFUNCTIONS])(struct can_frame *cf,
+ struct cf_mod *mod);
+
+ /* CAN frame checksum calculation after CAN frame modifications */
+ struct {
+ struct cgw_csum_xor xor;
+ struct cgw_csum_crc8 crc8;
+ } csum;
+ struct {
+ void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor);
+ void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8);
+ } csumfunc;
+};
+
+
+/*
+ * So far we just support CAN -> CAN routing and frame modifications.
+ *
+ * The internal can_can_gw structure contains data and attributes for
+ * a CAN -> CAN gateway job.
+ */
+struct can_can_gw {
+ struct can_filter filter;
+ int src_idx;
+ int dst_idx;
+};
+
+/* list entry for CAN gateways jobs */
+struct cgw_job {
+ struct hlist_node list;
+ struct rcu_head rcu;
+ u32 handled_frames;
+ u32 dropped_frames;
+ struct cf_mod mod;
+ union {
+ /* CAN frame data source */
+ struct net_device *dev;
+ } src;
+ union {
+ /* CAN frame data destination */
+ struct net_device *dev;
+ } dst;
+ union {
+ struct can_can_gw ccgw;
+ /* tbc */
+ };
+ u8 gwtype;
+ u16 flags;
+};
+
+/* modification functions that are invoked in the hot path in can_can_gw_rcv */
+
+#define MODFUNC(func, op) static void func(struct can_frame *cf, \
+ struct cf_mod *mod) { op ; }
+
+MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id)
+MODFUNC(mod_and_dlc, cf->can_dlc &= mod->modframe.and.can_dlc)
+MODFUNC(mod_and_data, *(u64 *)cf->data &= *(u64 *)mod->modframe.and.data)
+MODFUNC(mod_or_id, cf->can_id |= mod->modframe.or.can_id)
+MODFUNC(mod_or_dlc, cf->can_dlc |= mod->modframe.or.can_dlc)
+MODFUNC(mod_or_data, *(u64 *)cf->data |= *(u64 *)mod->modframe.or.data)
+MODFUNC(mod_xor_id, cf->can_id ^= mod->modframe.xor.can_id)
+MODFUNC(mod_xor_dlc, cf->can_dlc ^= mod->modframe.xor.can_dlc)
+MODFUNC(mod_xor_data, *(u64 *)cf->data ^= *(u64 *)mod->modframe.xor.data)
+MODFUNC(mod_set_id, cf->can_id = mod->modframe.set.can_id)
+MODFUNC(mod_set_dlc, cf->can_dlc = mod->modframe.set.can_dlc)
+MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data)
+
+static inline void canframecpy(struct can_frame *dst, struct can_frame *src)
+{
+ /*
+ * Copy the struct members separately to ensure that no uninitialized
+ * data are copied in the 3 bytes hole of the struct. This is needed
+ * to make easy compares of the data in the struct cf_mod.
+ */
+
+ dst->can_id = src->can_id;
+ dst->can_dlc = src->can_dlc;
+ *(u64 *)dst->data = *(u64 *)src->data;
+}
+
+static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re)
+{
+ /*
+ * absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0]
+ * relative to received dlc -1 .. -8 :
+ * e.g. for received dlc = 8
+ * -1 => index = 7 (data[7])
+ * -3 => index = 5 (data[5])
+ * -8 => index = 0 (data[0])
+ */
+
+ if (fr > -9 && fr < 8 &&
+ to > -9 && to < 8 &&
+ re > -9 && re < 8)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static inline int calc_idx(int idx, int rx_dlc)
+{
+ if (idx < 0)
+ return rx_dlc + idx;
+ else
+ return idx;
+}
+
+static void cgw_csum_xor_rel(struct can_frame *cf, struct cgw_csum_xor *xor)
+{
+ int from = calc_idx(xor->from_idx, cf->can_dlc);
+ int to = calc_idx(xor->to_idx, cf->can_dlc);
+ int res = calc_idx(xor->result_idx, cf->can_dlc);
+ u8 val = xor->init_xor_val;
+ int i;
+
+ if (from < 0 || to < 0 || res < 0)
+ return;
+
+ if (from <= to) {
+ for (i = from; i <= to; i++)
+ val ^= cf->data[i];
+ } else {
+ for (i = from; i >= to; i--)
+ val ^= cf->data[i];
+ }
+
+ cf->data[res] = val;
+}
+
+static void cgw_csum_xor_pos(struct can_frame *cf, struct cgw_csum_xor *xor)
+{
+ u8 val = xor->init_xor_val;
+ int i;
+
+ for (i = xor->from_idx; i <= xor->to_idx; i++)
+ val ^= cf->data[i];
+
+ cf->data[xor->result_idx] = val;
+}
+
+static void cgw_csum_xor_neg(struct can_frame *cf, struct cgw_csum_xor *xor)
+{
+ u8 val = xor->init_xor_val;
+ int i;
+
+ for (i = xor->from_idx; i >= xor->to_idx; i--)
+ val ^= cf->data[i];
+
+ cf->data[xor->result_idx] = val;
+}
+
+static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
+{
+ int from = calc_idx(crc8->from_idx, cf->can_dlc);
+ int to = calc_idx(crc8->to_idx, cf->can_dlc);
+ int res = calc_idx(crc8->result_idx, cf->can_dlc);
+ u8 crc = crc8->init_crc_val;
+ int i;
+
+ if (from < 0 || to < 0 || res < 0)
+ return;
+
+ if (from <= to) {
+ for (i = crc8->from_idx; i <= crc8->to_idx; i++)
+ crc = crc8->crctab[crc^cf->data[i]];
+ } else {
+ for (i = crc8->from_idx; i >= crc8->to_idx; i--)
+ crc = crc8->crctab[crc^cf->data[i]];
+ }
+
+ switch (crc8->profile) {
+
+ case CGW_CRC8PRF_1U8:
+ crc = crc8->crctab[crc^crc8->profile_data[0]];
+ break;
+
+ case CGW_CRC8PRF_16U8:
+ crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+ break;
+
+ case CGW_CRC8PRF_SFFID_XOR:
+ crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+ (cf->can_id >> 8 & 0xFF)];
+ break;
+
+ }
+
+ cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
+}
+
+static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
+{
+ u8 crc = crc8->init_crc_val;
+ int i;
+
+ for (i = crc8->from_idx; i <= crc8->to_idx; i++)
+ crc = crc8->crctab[crc^cf->data[i]];
+
+ switch (crc8->profile) {
+
+ case CGW_CRC8PRF_1U8:
+ crc = crc8->crctab[crc^crc8->profile_data[0]];
+ break;
+
+ case CGW_CRC8PRF_16U8:
+ crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+ break;
+
+ case CGW_CRC8PRF_SFFID_XOR:
+ crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+ (cf->can_id >> 8 & 0xFF)];
+ break;
+ }
+
+ cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
+}
+
+static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
+{
+ u8 crc = crc8->init_crc_val;
+ int i;
+
+ for (i = crc8->from_idx; i >= crc8->to_idx; i--)
+ crc = crc8->crctab[crc^cf->data[i]];
+
+ switch (crc8->profile) {
+
+ case CGW_CRC8PRF_1U8:
+ crc = crc8->crctab[crc^crc8->profile_data[0]];
+ break;
+
+ case CGW_CRC8PRF_16U8:
+ crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+ break;
+
+ case CGW_CRC8PRF_SFFID_XOR:
+ crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+ (cf->can_id >> 8 & 0xFF)];
+ break;
+ }
+
+ cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
+}
+
+/* the receive & process & send function */
+static void can_can_gw_rcv(struct sk_buff *skb, void *data)
+{
+ struct cgw_job *gwj = (struct cgw_job *)data;
+ struct can_frame *cf;
+ struct sk_buff *nskb;
+ int modidx = 0;
+
+ /* do not handle already routed frames - see comment below */
+ if (skb_mac_header_was_set(skb))
+ return;
+
+ if (!(gwj->dst.dev->flags & IFF_UP)) {
+ gwj->dropped_frames++;
+ return;
+ }
+
+ /*
+ * clone the given skb, which has not been done in can_rcv()
+ *
+ * When there is at least one modification function activated,
+ * we need to copy the skb as we want to modify skb->data.
+ */
+ if (gwj->mod.modfunc[0])
+ nskb = skb_copy(skb, GFP_ATOMIC);
+ else
+ nskb = skb_clone(skb, GFP_ATOMIC);
+
+ if (!nskb) {
+ gwj->dropped_frames++;
+ return;
+ }
+
+ /*
+ * Mark routed frames by setting some mac header length which is
+ * not relevant for the CAN frames located in the skb->data section.
+ *
+ * As dev->header_ops is not set in CAN netdevices no one is ever
+ * accessing the various header offsets in the CAN skbuffs anyway.
+ * E.g. using the packet socket to read CAN frames is still working.
+ */
+ skb_set_mac_header(nskb, 8);
+ nskb->dev = gwj->dst.dev;
+
+ /* pointer to modifiable CAN frame */
+ cf = (struct can_frame *)nskb->data;
+
+ /* perform preprocessed modification functions if there are any */
+ while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
+ (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
+
+ /* check for checksum updates when the CAN frame has been modified */
+ if (modidx) {
+ if (gwj->mod.csumfunc.crc8)
+ (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+
+ if (gwj->mod.csumfunc.xor)
+ (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
+ }
+
+ /* clear the skb timestamp if not configured the other way */
+ if (!(gwj->flags & CGW_FLAGS_CAN_SRC_TSTAMP))
+ nskb->tstamp.tv64 = 0;
+
+ /* send to netdevice */
+ if (can_send(nskb, gwj->flags & CGW_FLAGS_CAN_ECHO))
+ gwj->dropped_frames++;
+ else
+ gwj->handled_frames++;
+}
+
+static inline int cgw_register_filter(struct cgw_job *gwj)
+{
+ return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
+ gwj->ccgw.filter.can_mask, can_can_gw_rcv,
+ gwj, "gw");
+}
+
+static inline void cgw_unregister_filter(struct cgw_job *gwj)
+{
+ can_rx_unregister(gwj->src.dev, gwj->ccgw.filter.can_id,
+ gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj);
+}
+
+static int cgw_notifier(struct notifier_block *nb,
+ unsigned long msg, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+
+ if (!net_eq(dev_net(dev), &init_net))
+ return NOTIFY_DONE;
+ if (dev->type != ARPHRD_CAN)
+ return NOTIFY_DONE;
+
+ if (msg == NETDEV_UNREGISTER) {
+
+ struct cgw_job *gwj = NULL;
+ struct hlist_node *n, *nx;
+
+ ASSERT_RTNL();
+
+ hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
+
+ if (gwj->src.dev == dev || gwj->dst.dev == dev) {
+ hlist_del(&gwj->list);
+ cgw_unregister_filter(gwj);
+ kfree(gwj);
+ }
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj)
+{
+ struct cgw_frame_mod mb;
+ struct rtcanmsg *rtcan;
+ struct nlmsghdr *nlh = nlmsg_put(skb, 0, 0, 0, sizeof(*rtcan), 0);
+ if (!nlh)
+ return -EMSGSIZE;
+
+ rtcan = nlmsg_data(nlh);
+ rtcan->can_family = AF_CAN;
+ rtcan->gwtype = gwj->gwtype;
+ rtcan->flags = gwj->flags;
+
+ /* add statistics if available */
+
+ if (gwj->handled_frames) {
+ if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+ }
+
+ if (gwj->dropped_frames) {
+ if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+ }
+
+ /* check non default settings of attributes */
+
+ if (gwj->mod.modtype.and) {
+ memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf));
+ mb.modtype = gwj->mod.modtype.and;
+ if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+ }
+
+ if (gwj->mod.modtype.or) {
+ memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf));
+ mb.modtype = gwj->mod.modtype.or;
+ if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+ }
+
+ if (gwj->mod.modtype.xor) {
+ memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf));
+ mb.modtype = gwj->mod.modtype.xor;
+ if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+ }
+
+ if (gwj->mod.modtype.set) {
+ memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf));
+ mb.modtype = gwj->mod.modtype.set;
+ if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(mb));
+ }
+
+ if (gwj->mod.csumfunc.crc8) {
+ if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
+ &gwj->mod.csum.crc8) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + \
+ NLA_ALIGN(CGW_CS_CRC8_LEN);
+ }
+
+ if (gwj->mod.csumfunc.xor) {
+ if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN,
+ &gwj->mod.csum.xor) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + \
+ NLA_ALIGN(CGW_CS_XOR_LEN);
+ }
+
+ if (gwj->gwtype == CGW_TYPE_CAN_CAN) {
+
+ if (gwj->ccgw.filter.can_id || gwj->ccgw.filter.can_mask) {
+ if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter),
+ &gwj->ccgw.filter) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN +
+ NLA_ALIGN(sizeof(struct can_filter));
+ }
+
+ if (nla_put_u32(skb, CGW_SRC_IF, gwj->ccgw.src_idx) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+
+ if (nla_put_u32(skb, CGW_DST_IF, gwj->ccgw.dst_idx) < 0)
+ goto cancel;
+ else
+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(sizeof(u32));
+ }
+
+ return skb->len;
+
+cancel:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
+/* Dump information about all CAN gateway jobs, in response to RTM_GETROUTE */
+static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct cgw_job *gwj = NULL;
+ struct hlist_node *n;
+ int idx = 0;
+ int s_idx = cb->args[0];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(gwj, n, &cgw_list, list) {
+ if (idx < s_idx)
+ goto cont;
+
+ if (cgw_put_job(skb, gwj) < 0)
+ break;
+cont:
+ idx++;
+ }
+ rcu_read_unlock();
+
+ cb->args[0] = idx;
+
+ return skb->len;
+}
+
+/* check for common and gwtype specific attributes */
+static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
+ u8 gwtype, void *gwtypeattr)
+{
+ struct nlattr *tb[CGW_MAX+1];
+ struct cgw_frame_mod mb;
+ int modidx = 0;
+ int err = 0;
+
+ /* initialize modification & checksum data space */
+ memset(mod, 0, sizeof(*mod));
+
+ err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, NULL);
+ if (err < 0)
+ return err;
+
+ /* check for AND/OR/XOR/SET modifications */
+
+ if (tb[CGW_MOD_AND] &&
+ nla_len(tb[CGW_MOD_AND]) == CGW_MODATTR_LEN) {
+ nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN);
+
+ canframecpy(&mod->modframe.and, &mb.cf);
+ mod->modtype.and = mb.modtype;
+
+ if (mb.modtype & CGW_MOD_ID)
+ mod->modfunc[modidx++] = mod_and_id;
+
+ if (mb.modtype & CGW_MOD_DLC)
+ mod->modfunc[modidx++] = mod_and_dlc;
+
+ if (mb.modtype & CGW_MOD_DATA)
+ mod->modfunc[modidx++] = mod_and_data;
+ }
+
+ if (tb[CGW_MOD_OR] &&
+ nla_len(tb[CGW_MOD_OR]) == CGW_MODATTR_LEN) {
+ nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN);
+
+ canframecpy(&mod->modframe.or, &mb.cf);
+ mod->modtype.or = mb.modtype;
+
+ if (mb.modtype & CGW_MOD_ID)
+ mod->modfunc[modidx++] = mod_or_id;
+
+ if (mb.modtype & CGW_MOD_DLC)
+ mod->modfunc[modidx++] = mod_or_dlc;
+
+ if (mb.modtype & CGW_MOD_DATA)
+ mod->modfunc[modidx++] = mod_or_data;
+ }
+
+ if (tb[CGW_MOD_XOR] &&
+ nla_len(tb[CGW_MOD_XOR]) == CGW_MODATTR_LEN) {
+ nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN);
+
+ canframecpy(&mod->modframe.xor, &mb.cf);
+ mod->modtype.xor = mb.modtype;
+
+ if (mb.modtype & CGW_MOD_ID)
+ mod->modfunc[modidx++] = mod_xor_id;
+
+ if (mb.modtype & CGW_MOD_DLC)
+ mod->modfunc[modidx++] = mod_xor_dlc;
+
+ if (mb.modtype & CGW_MOD_DATA)
+ mod->modfunc[modidx++] = mod_xor_data;
+ }
+
+ if (tb[CGW_MOD_SET] &&
+ nla_len(tb[CGW_MOD_SET]) == CGW_MODATTR_LEN) {
+ nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN);
+
+ canframecpy(&mod->modframe.set, &mb.cf);
+ mod->modtype.set = mb.modtype;
+
+ if (mb.modtype & CGW_MOD_ID)
+ mod->modfunc[modidx++] = mod_set_id;
+
+ if (mb.modtype & CGW_MOD_DLC)
+ mod->modfunc[modidx++] = mod_set_dlc;
+
+ if (mb.modtype & CGW_MOD_DATA)
+ mod->modfunc[modidx++] = mod_set_data;
+ }
+
+ /* check for checksum operations after CAN frame modifications */
+ if (modidx) {
+
+ if (tb[CGW_CS_CRC8] &&
+ nla_len(tb[CGW_CS_CRC8]) == CGW_CS_CRC8_LEN) {
+
+ struct cgw_csum_crc8 *c = (struct cgw_csum_crc8 *)\
+ nla_data(tb[CGW_CS_CRC8]);
+
+ err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
+ c->result_idx);
+ if (err)
+ return err;
+
+ nla_memcpy(&mod->csum.crc8, tb[CGW_CS_CRC8],
+ CGW_CS_CRC8_LEN);
+
+ /*
+ * select dedicated processing function to reduce
+ * runtime operations in receive hot path.
+ */
+ if (c->from_idx < 0 || c->to_idx < 0 ||
+ c->result_idx < 0)
+ mod->csumfunc.crc8 = cgw_csum_crc8_rel;
+ else if (c->from_idx <= c->to_idx)
+ mod->csumfunc.crc8 = cgw_csum_crc8_pos;
+ else
+ mod->csumfunc.crc8 = cgw_csum_crc8_neg;
+ }
+
+ if (tb[CGW_CS_XOR] &&
+ nla_len(tb[CGW_CS_XOR]) == CGW_CS_XOR_LEN) {
+
+ struct cgw_csum_xor *c = (struct cgw_csum_xor *)\
+ nla_data(tb[CGW_CS_XOR]);
+
+ err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
+ c->result_idx);
+ if (err)
+ return err;
+
+ nla_memcpy(&mod->csum.xor, tb[CGW_CS_XOR],
+ CGW_CS_XOR_LEN);
+
+ /*
+ * select dedicated processing function to reduce
+ * runtime operations in receive hot path.
+ */
+ if (c->from_idx < 0 || c->to_idx < 0 ||
+ c->result_idx < 0)
+ mod->csumfunc.xor = cgw_csum_xor_rel;
+ else if (c->from_idx <= c->to_idx)
+ mod->csumfunc.xor = cgw_csum_xor_pos;
+ else
+ mod->csumfunc.xor = cgw_csum_xor_neg;
+ }
+ }
+
+ if (gwtype == CGW_TYPE_CAN_CAN) {
+
+ /* check CGW_TYPE_CAN_CAN specific attributes */
+
+ struct can_can_gw *ccgw = (struct can_can_gw *)gwtypeattr;
+ memset(ccgw, 0, sizeof(*ccgw));
+
+ /* check for can_filter in attributes */
+ if (tb[CGW_FILTER] &&
+ nla_len(tb[CGW_FILTER]) == sizeof(struct can_filter))
+ nla_memcpy(&ccgw->filter, tb[CGW_FILTER],
+ sizeof(struct can_filter));
+
+ err = -ENODEV;
+
+ /* specifying two interfaces is mandatory */
+ if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF])
+ return err;
+
+ if (nla_len(tb[CGW_SRC_IF]) == sizeof(u32))
+ nla_memcpy(&ccgw->src_idx, tb[CGW_SRC_IF],
+ sizeof(u32));
+
+ if (nla_len(tb[CGW_DST_IF]) == sizeof(u32))
+ nla_memcpy(&ccgw->dst_idx, tb[CGW_DST_IF],
+ sizeof(u32));
+
+ /* both indices set to 0 for flushing all routing entries */
+ if (!ccgw->src_idx && !ccgw->dst_idx)
+ return 0;
+
+ /* only one index set to 0 is an error */
+ if (!ccgw->src_idx || !ccgw->dst_idx)
+ return err;
+ }
+
+ /* add the checks for other gwtypes here */
+
+ return 0;
+}
+
+static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
+ void *arg)
+{
+ struct rtcanmsg *r;
+ struct cgw_job *gwj;
+ int err = 0;
+
+ if (nlmsg_len(nlh) < sizeof(*r))
+ return -EINVAL;
+
+ r = nlmsg_data(nlh);
+ if (r->can_family != AF_CAN)
+ return -EPFNOSUPPORT;
+
+ /* so far we only support CAN -> CAN routings */
+ if (r->gwtype != CGW_TYPE_CAN_CAN)
+ return -EINVAL;
+
+ gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL);
+ if (!gwj)
+ return -ENOMEM;
+
+ gwj->handled_frames = 0;
+ gwj->dropped_frames = 0;
+ gwj->flags = r->flags;
+ gwj->gwtype = r->gwtype;
+
+ err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw);
+ if (err < 0)
+ goto out;
+
+ err = -ENODEV;
+
+ /* ifindex == 0 is not allowed for job creation */
+ if (!gwj->ccgw.src_idx || !gwj->ccgw.dst_idx)
+ goto out;
+
+ gwj->src.dev = dev_get_by_index(&init_net, gwj->ccgw.src_idx);
+
+ if (!gwj->src.dev)
+ goto out;
+
+ /* check for CAN netdev not using header_ops - see gw_rcv() */
+ if (gwj->src.dev->type != ARPHRD_CAN || gwj->src.dev->header_ops)
+ goto put_src_out;
+
+ gwj->dst.dev = dev_get_by_index(&init_net, gwj->ccgw.dst_idx);
+
+ if (!gwj->dst.dev)
+ goto put_src_out;
+
+ /* check for CAN netdev not using header_ops - see gw_rcv() */
+ if (gwj->dst.dev->type != ARPHRD_CAN || gwj->dst.dev->header_ops)
+ goto put_src_dst_out;
+
+ ASSERT_RTNL();
+
+ err = cgw_register_filter(gwj);
+ if (!err)
+ hlist_add_head_rcu(&gwj->list, &cgw_list);
+
+put_src_dst_out:
+ dev_put(gwj->dst.dev);
+put_src_out:
+ dev_put(gwj->src.dev);
+out:
+ if (err)
+ kmem_cache_free(cgw_cache, gwj);
+
+ return err;
+}
+
+static void cgw_remove_all_jobs(void)
+{
+ struct cgw_job *gwj = NULL;
+ struct hlist_node *n, *nx;
+
+ ASSERT_RTNL();
+
+ hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
+ hlist_del(&gwj->list);
+ cgw_unregister_filter(gwj);
+ kfree(gwj);
+ }
+}
+
+static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct cgw_job *gwj = NULL;
+ struct hlist_node *n, *nx;
+ struct rtcanmsg *r;
+ struct cf_mod mod;
+ struct can_can_gw ccgw;
+ int err = 0;
+
+ if (nlmsg_len(nlh) < sizeof(*r))
+ return -EINVAL;
+
+ r = nlmsg_data(nlh);
+ if (r->can_family != AF_CAN)
+ return -EPFNOSUPPORT;
+
+ /* so far we only support CAN -> CAN routings */
+ if (r->gwtype != CGW_TYPE_CAN_CAN)
+ return -EINVAL;
+
+ err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw);
+ if (err < 0)
+ return err;
+
+ /* two interface indices both set to 0 => remove all entries */
+ if (!ccgw.src_idx && !ccgw.dst_idx) {
+ cgw_remove_all_jobs();
+ return 0;
+ }
+
+ err = -EINVAL;
+
+ ASSERT_RTNL();
+
+ /* remove only the first matching entry */
+ hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
+
+ if (gwj->flags != r->flags)
+ continue;
+
+ if (memcmp(&gwj->mod, &mod, sizeof(mod)))
+ continue;
+
+ /* if (r->gwtype == CGW_TYPE_CAN_CAN) - is made sure here */
+ if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))
+ continue;
+
+ hlist_del(&gwj->list);
+ cgw_unregister_filter(gwj);
+ kfree(gwj);
+ err = 0;
+ break;
+ }
+
+ return err;
+}
+
+static __init int cgw_module_init(void)
+{
+ printk(banner);
+
+ cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
+ 0, 0, NULL);
+
+ if (!cgw_cache)
+ return -ENOMEM;
+
+ /* set notifier */
+ notifier.notifier_call = cgw_notifier;
+ register_netdevice_notifier(¬ifier);
+
+ if (__rtnl_register(PF_CAN, RTM_GETROUTE, NULL, cgw_dump_jobs, NULL)) {
+ unregister_netdevice_notifier(¬ifier);
+ kmem_cache_destroy(cgw_cache);
+ return -ENOBUFS;
+ }
+
+ /* Only the first call to __rtnl_register can fail */
+ __rtnl_register(PF_CAN, RTM_NEWROUTE, cgw_create_job, NULL, NULL);
+ __rtnl_register(PF_CAN, RTM_DELROUTE, cgw_remove_job, NULL, NULL);
+
+ return 0;
+}
+
+static __exit void cgw_module_exit(void)
+{
+ rtnl_unregister_all(PF_CAN);
+
+ unregister_netdevice_notifier(¬ifier);
+
+ rtnl_lock();
+ cgw_remove_all_jobs();
+ rtnl_unlock();
+
+ rcu_barrier(); /* Wait for completion of call_rcu()'s */
+
+ kmem_cache_destroy(cgw_cache);
+}
+
+module_init(cgw_module_init);
+module_exit(cgw_module_exit);
diff -u -r -N a/net/can/Kconfig b/net/can/Kconfig
--- a/net/can/Kconfig 2011-08-31 21:10:58.399595821 +0200
+++ b/net/can/Kconfig 2011-08-31 21:09:29.939596430 +0200
@@ -40,5 +40,16 @@
CAN messages are used on the bus (e.g. in automotive environments).
To use the Broadcast Manager, use AF_CAN with protocol CAN_BCM.
+config CAN_GW
+ tristate "CAN Gateway/Router (with netlink configuration)"
+ depends on CAN
+ default N
+ ---help---
+ The CAN Gateway/Router is used to route (and modify) CAN frames.
+ It is based on the PF_CAN core infrastructure for msg filtering and
+ msg sending and can optionally modify routed CAN frames on the fly.
+ CAN frames can be routed between CAN network interfaces (one hop).
+ They can be modified with AND/OR/XOR/SET operations as configured
+ by the netlink configuration interface known e.g. from iptables.
source "drivers/net/can/Kconfig"
diff -u -r -N a/net/can/Makefile b/net/can/Makefile
--- a/net/can/Makefile 2011-08-31 21:10:53.355595713 +0200
+++ b/net/can/Makefile 2011-08-31 21:09:34.483599007 +0200
@@ -10,3 +10,6 @@
obj-$(CONFIG_CAN_BCM) += can-bcm.o
can-bcm-y := bcm.o
+
+obj-$(CONFIG_CAN_GW) += can-gw.o
+can-gw-y := gw.o
^ permalink raw reply
* commit 1faa4356 breaks IPv6 assignment on libvirtd
From: Ang Way Chuang @ 2011-09-01 14:42 UTC (permalink / raw)
To: netdev, Stephen Hemminger
Hi all,
Commit 1faa4356 break IPv6 assignment on libvirtd. The configuration for my VM bridge network is as such:
<network>
<name>default</name>
<forward mode='nat'/>
<bridge name='virbr0' stp='on' delay='0' />
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
</dhcp>
</ip>
<ip family='ipv6' address='2001:d30:113:504::1' prefix='64'>
</ip>
</network>
This configuration worked fine on kernel 2.6.38. Updating my distro kernel broke the setup. My colleague
and I traced the problem and found that libvirtd failed because there wasn't any carrier on virbr0 interface
due to the change introduced by that commit. How can this be fixed? Thanks in advance.
Regards,
Ang Way Chuang
^ permalink raw reply
* [PATCH] dev_ioctl should return -EINVAL for unknown ioctl instead of -ENOTTY
From: Wang Sheng-Hui @ 2011-09-01 14:52 UTC (permalink / raw)
To: davem, netdev, linux-kernel
The patch is against 3.1-rc3.
Signed-off-by: Wang Sheng-Hui <shhuiw@gmail.com>
---
net/core/dev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 17d67b5..de6033c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5092,7 +5092,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
/* Take care of Wireless Extensions */
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
return wext_handle_ioctl(net, &ifr, cmd, arg);
- return -ENOTTY;
+ return -EINVAL;
}
}
--
1.7.1
^ permalink raw reply related
* [PATCH ] dynamic_debug: call __netdev_printk only for CONFIG_NET
From: Arnd Bergmann @ 2011-09-01 14:57 UTC (permalink / raw)
To: Jason Baron
Cc: gregkh, joe, jim.cromie, bvanassche, linux-kernel, davem,
aloisio.almeida, netdev
In-Reply-To: <5514795fe63ccfd4b3a80283ed04a526abe3c59d.1313085588.git.jbaron@redhat.com>
__netdev_printk is only defined when CONFIG_NET is set. Since we only need
__dynamic_netdev_dbg for network drivers, we can make it conditional on the
same Kconfig symbol.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
On Thursday 11 August 2011, Jason Baron wrote:
>
> From: Jason Baron <jbaron@redhat.com>
>
> Previously, if dynamic debug was enabled netdev_dbg() was using
> dynamic_dev_dbg() to print out the underlying msg. Fix this by making
> sure netdev_dbg() uses __netdev_printk().
>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
> ---
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -504,6 +504,7 @@ int __dynamic_dev_dbg(struct _ddebug *descriptor,
}
EXPORT_SYMBOL(__dynamic_dev_dbg);
+#ifdef CONFIG_NET
int __dynamic_netdev_dbg(struct _ddebug *descriptor,
const struct net_device *dev, const char *fmt, ...)
{
@@ -527,6 +528,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,
return res;
}
EXPORT_SYMBOL(__dynamic_netdev_dbg);
+#endif
static __initdata char ddebug_setup_string[1024];
static __init int ddebug_setup_query(char *str)
^ permalink raw reply
* Re: [patch 1/3 -next] 6LoWPAN: use kfree_skb() instead of kfree()
From: Dan Carpenter @ 2011-09-01 15:04 UTC (permalink / raw)
To: Alexander Smirnov
Cc: Eric Dumazet, Dmitry Eremin-Solenikov, Sergey Lapin,
David S. Miller, open list:IEEE 802.15.4 SUB...,
open list:NETWORKING [GENERAL], kernel-janitors
In-Reply-To: <CAJmB2rBid27YYT4f6vMtBf9EMFWZQgT=xO85z4OBz326pUT+4A@mail.gmail.com>
On Thu, Sep 01, 2011 at 01:26:02PM +0400, Alexander Smirnov wrote:
> Hi Dan, Eric,
>
> thank you a lot for the finds, that were my faults.
>
So uh... You're going to send a patch to fix the things Eric
mentioned, right?
regards,
dan carpenter
^ permalink raw reply
* Re: BQL crap and wireless
From: Jim Gettys @ 2011-09-01 15:08 UTC (permalink / raw)
To: John W. Linville
Cc: Luis R. Rodriguez, Andrew McGregor, Adrian Chadd, Tom Herbert,
Dave Taht, linux-wireless, Matt Smith, Kevin Hayes,
Derek Smithies, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20110901141304.GA2580-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
On 09/01/2011 10:13 AM, John W. Linville wrote:
> On Wed, Aug 31, 2011 at 01:50:48PM -0700, Luis R. Rodriguez wrote:
>> On Wed, Aug 31, 2011 at 6:28 AM, Jim Gettys <jg-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org> wrote:
>> such as wireless, or even possibly modern broadband with
>> PowerBoost, classic RED or similar algorithms that do not take the
>> buffer drain rate cannot possibly hack it properly.
>> Understood, just curious if anyone has tried a Minstrel approach.
> FWIW, eBDP and the related algorithms from Tianji Li's paper are
> philosophically similar to minstrel. They depend on measuring recent
> conditions and modifying the current queue length accordingly.
>
> http://www.hamilton.ie/tianji_li/buffersizing.pdf
>
> The hack I added in debloat-testing is based on my understanding
> of eBDP. It timestamps the SKBs when they are handed to the driver
> for Tx and then checks the timestamp when the SKB is orphaned. It is
> a bit crude and is an abuse of the skb_orphan API. Also while it
> accounts for the 802.11e queues separately, it doesn't account for
> 802.11n aggregation. Still, it seems to improve latency w/o hugely
> impacting throughput in at least some environments -- YMMV!
>
Certainly eBDP *sort of* works for me; I see somewhat more variation
(jitter) than I'd like, but at least latencies are at least somewhat
controlled and I've not seen performance (throughput) problems. This is
on an Intel chipset.
Tanji Li's work and eBDP came to our attention after a conversation I
had with Van at the beginning of this year; Van send me a pointer to it
with the comments:
"As I said on the phone I think there's an easier, more robust way to accomplish the same
thing but they have running code and I don't."
But we've not had time to do any systematic testing on eBDP yet and the
implementation needs more work before it should go upstream.
About the time we were thinking of starting that testing, it became
clear that getting aggregation working better was pretty essential to
validating any results. I'm looking forward to trying eBDP with the
revised Ath9k driver as soon as they get put into a single pool. And if
Kathleen and Van can get a "RED Light" they are happy with, that will be
fun to try as well.
- Jim
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: comparison of the AF_ALG interface with the /dev/crypto
From: Herbert Xu @ 2011-09-01 15:08 UTC (permalink / raw)
To: Nikos Mavrogiannopoulos
Cc: Phil Sutter, cryptodev-linux-devel, linux-crypto, linux-kernel,
netdev
In-Reply-To: <CAJU7zaKnKYYLx6W_9WsZCcwhNd0KMM9R8fs2D0=Xd_6T_AE4=A@mail.gmail.com>
On Thu, Sep 01, 2011 at 05:06:06PM +0200, Nikos Mavrogiannopoulos wrote:
>
> Indeed but today that's what we have in some systems. User-space TLS
> implementations (GnuTLS and OpenSSL) and kernel-space crypto
> offloading. The purpose of the /dev/crypto and AF_ALG interfaces is to
> connect those together. It would be interesting to have a partial
> kernel-space TLS implementation but I don't know whether such a thing
> could ever make it to kernel.
Well we've talked about a kernel implementation of the data path
previously and I don't think there is any opposition to the idea.
The only thing missing is an implementation.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [patch 1/3 -next] 6LoWPAN: use kfree_skb() instead of kfree()
From: Dan Carpenter @ 2011-09-01 15:06 UTC (permalink / raw)
To: Alexander Smirnov
Cc: Eric Dumazet, Dmitry Eremin-Solenikov, Sergey Lapin,
David S. Miller, open list:IEEE 802.15.4 SUB...,
open list:NETWORKING [GENERAL], kernel-janitors
In-Reply-To: <20110901150425.GK3705@shale.localdomain>
On Thu, Sep 01, 2011 at 06:04:25PM +0300, Dan Carpenter wrote:
> On Thu, Sep 01, 2011 at 01:26:02PM +0400, Alexander Smirnov wrote:
> > Hi Dan, Eric,
> >
> > thank you a lot for the finds, that were my faults.
> >
>
> So uh... You're going to send a patch to fix the things Eric
> mentioned, right?
>
Ah. You did already. I see that now. Sorry for the noise.
regards,
dan carpenter
^ permalink raw reply
* linux-next 20110831 - netconsole startup issue
From: Valdis.Kletnieks @ 2011-09-01 15:14 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kernel
Chasing a kernel panic in linux-next, and hit an unrelated issue
starting up netconsole that's bogging me down.
On linux-next-20110823, I had this:
[ 7.078099] e1000e: Intel(R) PRO/1000 Network Driver - 1.5.1-k
[ 7.078102] e1000e: Copyright(c) 1999 - 2011 Intel Corporation.
[ 7.078158] e1000e 0000:00:19.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
[ 7.078171] e1000e 0000:00:19.0: setting latency timer to 64
[ 7.078354] e1000e 0000:00:19.0: irq 46 for MSI/MSI-X
[ 7.269439] e1000e 0000:00:19.0: eth0: (PCI Express:2.5GT/s:Width x1) 00:21:70:de:b6:fd
[ 7.269443] e1000e 0000:00:19.0: eth0: Intel(R) PRO/1000 Network Connection
[ 7.269469] e1000e 0000:00:19.0: eth0: MAC: 7, PHY: 8, PBA No: 4003FF-0FF
[ 7.293569] netconsole: network logging started
Bring up the ethernet, then the console. Works great,
However, on -20110831, I get this:
[ 0.983149] netconsole: local port 9909
[ 0.983254] netconsole: local IP 128.173.14.107
[ 0.983358] netconsole: interface 'eth0'
[ 0.983461] netconsole: remote port 9909
[ 0.983564] netconsole: remote IP 128.173.14.108
[ 0.983668] netconsole: remote ethernet address 00:14:22:5a:79:d3
[ 0.983776] netconsole: eth0 doesn't exist, aborting.
[ 0.983897] netconsole: cleaning up
[ 1.176429] e1000e 0000:00:19.0: eth0: (PCI Express:2.5GT/s:Width x1) 00:21:70:de:b6:fd
[ 1.176557] e1000e 0000:00:19.0: eth0: Intel(R) PRO/1000 Network Connection
[ 1.176688] e1000e 0000:00:19.0: eth0: MAC: 7, PHY: 8, PBA No: 4003FF-0FF
Whoops. No netconsole.
Even more annoying (and quite possibly related), the kernel is built with
CONFIG_NETCONSOLE_DYNAMIC. On -20110823, I have a /sys/kernel/config/netconsole
directory and can use it to configure netconsole on the fly. However, on
-20110831, /sys/kernel/config is empty - no netconsole subdirectory. So I
couldn't even boot to single-user, configure netconsole, and then continue to
multiuser and capture the crash.
^ permalink raw reply
* Re: [PATCH ] dynamic_debug: call __netdev_printk only for CONFIG_NET
From: Jason Baron @ 2011-09-01 15:18 UTC (permalink / raw)
To: Arnd Bergmann
Cc: gregkh, joe, jim.cromie, bvanassche, linux-kernel, davem,
aloisio.almeida, netdev
In-Reply-To: <201109011657.02407.arnd@arndb.de>
On Thu, Sep 01, 2011 at 04:57:02PM +0200, Arnd Bergmann wrote:
> __netdev_printk is only defined when CONFIG_NET is set. Since we only need
> __dynamic_netdev_dbg for network drivers, we can make it conditional on the
> same Kconfig symbol.
>
Hi,
Yes, I've posted a fix for this:
https://lkml.org/lkml/2011/8/30/297
Hopefully, it will be pulled in soon.
Thanks,
-Jason
^ permalink raw reply
* [RFC] igb: Add notifier mechanism in order to synch DMA Coalescing feature
From: Carolyn Wyborny @ 2011-09-01 15:21 UTC (permalink / raw)
To: netdev
DMA Coalescing feature runs on every port of quad i350 adapters. Having
more than one card in a system can cause the DMA Coalescing feature
to be offset enough on each port to eventually reduce the expected power
savings on the system overall. This feature is a way to synch the
DMA Coalescing instances in order to improve the power savings with multiple
cards in a system.
I'm sending this RFC to see if anyone has a better way of doing this.
The requirement is to have every driver instance attached to this
particular device write a single register bit on every rx interrrupt.
People using this feature would be more interested in power savings
than extreme performance. For purposes of this RFC, the DMAC feature isi
enabled. The feature is normally disabled by default
---
drivers/net/ethernet/intel/igb/igb.h | 1 +
drivers/net/ethernet/intel/igb/igb_main.c | 63 ++++++++++++++++++++++++++++-
2 files changed, 63 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 265e151..272ceb1 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -341,6 +341,7 @@ struct igb_adapter {
#define IGB_MIN_TXPBSIZE 20408
#define IGB_TX_BUF_4096 4096
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */
+#define IGB_DMACR_EXIT_DC 0x20000000 /* Exit DMAC Coalescing */
#define IGB_82576_TSYNC_SHIFT 19
#define IGB_82580_TSYNC_SHIFT 24
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 8016084..c6a4b88 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -173,6 +173,20 @@ static struct notifier_block dca_notifier = {
.priority = 0
};
#endif
+
+#define IGB_OPTIMIZE_DMAC 0x0001
+static ATOMIC_NOTIFIER_HEAD(igb_opt_dmac_notify_list);
+static int igb_register_opt_dmac_notifier (struct notifier_block *nb);
+static int igb_unregister_opt_dmac_notifier (struct notifier_block *nb);
+static void igb_call_opt_dmac_notify(unsigned long msg);
+static int igb_notify_opt_dmac(struct notifier_block *, unsigned long, void *);
+static int __igb_notify_opt_dmac(struct device *dev, void *data);
+static struct notifier_block igb_notifier_opt_dmac = {
+ .notifier_call = igb_notify_opt_dmac,
+ .next = NULL,
+ .priority = 0
+};
+
#ifdef CONFIG_NET_POLL_CONTROLLER
/* for netdump / net console */
static void igb_netpoll(struct net_device *);
@@ -599,6 +613,9 @@ static int __init igb_init_module(void)
dca_register_notify(&dca_notifier);
#endif
ret = pci_register_driver(&igb_driver);
+ if (ret >= 0) {
+ igb_register_opt_dmac_notifier(&igb_notifier_opt_dmac);
+ }
return ret;
}
@@ -615,6 +632,7 @@ static void __exit igb_exit_module(void)
#ifdef CONFIG_IGB_DCA
dca_unregister_notify(&dca_notifier);
#endif
+ igb_unregister_opt_dmac_notifier(&igb_notifier_opt_dmac);
pci_unregister_driver(&igb_driver);
}
@@ -2441,7 +2459,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
igb_irq_disable(adapter);
if (hw->mac.type == e1000_i350)
- adapter->flags &= ~IGB_FLAG_DMAC;
+ /* adapter->flags &= ~IGB_FLAG_DMAC; */
+ adapter->flags |= IGB_FLAG_DMAC;
set_bit(__IGB_DOWN, &adapter->state);
return 0;
@@ -5539,6 +5558,10 @@ static int igb_poll(struct napi_struct *napi, int budget)
if (q_vector->rx_ring)
igb_clean_rx_irq_adv(q_vector, &work_done, budget);
+ if ((q_vector->adapter->hw.mac.type = e1000_i350) &&
+ (q_vector->adapter->flags & IGB_FLAG_DMAC))
+ igb_call_opt_dmac_notify(IGB_OPTIMIZE_DMAC);
+
if (!tx_clean_complete)
work_done = budget;
@@ -6889,4 +6912,42 @@ static void igb_vmm_control(struct igb_adapter *adapter)
}
}
+static int igb_register_opt_dmac_notifier (struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&igb_opt_dmac_notify_list,
+ &igb_notifier_opt_dmac);
+}
+static int igb_unregister_opt_dmac_notifier (struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&igb_opt_dmac_notify_list,
+ &igb_notifier_opt_dmac);
+}
+static void igb_call_opt_dmac_notify(unsigned long msg)
+{
+ atomic_notifier_call_chain(&igb_opt_dmac_notify_list, msg,
+ NULL);
+}
+static int igb_notify_opt_dmac(struct notifier_block *nb, unsigned long event,
+ void *p)
+{
+ int ret_val;
+
+ ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event,
+ __igb_notify_opt_dmac);
+
+ return NOTIFY_DONE;
+}
+static int __igb_notify_opt_dmac(struct device *dev, void *data)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ unsigned long event = *(unsigned long *)data;
+
+ if (event == IGB_OPTIMIZE_DMAC) {
+ wr32(E1000_DMACR, IGB_DMACR_EXIT_DC);
+ }
+ return E1000_SUCCESS;
+}
+
/* igb_main.c */
--
1.7.4.4
^ permalink raw reply related
* Re: [PATCH v3 -next] 6LoWPAN: fix skb_copy call
From: Eric Dumazet @ 2011-09-01 15:31 UTC (permalink / raw)
To: Alexander Smirnov
Cc: davem, dbaryshkov, slapin, linux-zigbee-devel, netdev,
kernel-janitors
In-Reply-To: <1314885315-4033-1-git-send-email-alex.bluesman.smirnov@gmail.com>
Le jeudi 01 septembre 2011 à 17:55 +0400, Alexander Smirnov a écrit :
> This patch fixes 2 issues in lowpan_skb_deliver function:
> 1. Check for return status of skb_copy call;
> 2. Use skb_copy with proper GFP flag, drop check for non-interrupt
> context.
>
> Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> ---
> net/ieee802154/6lowpan.c | 17 +++++++++--------
> 1 files changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
> index cf304cc..deb2adf 100644
> --- a/net/ieee802154/6lowpan.c
> +++ b/net/ieee802154/6lowpan.c
> @@ -479,10 +479,10 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
> int stat = NET_RX_SUCCESS;
>
> new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
> - GFP_KERNEL);
> + GFP_ATOMIC);
> kfree_skb(skb);
>
> - if (NULL == new)
> + if (!new)
> return -ENOMEM;
>
> skb_push(new, sizeof(struct ipv6hdr));
> @@ -495,13 +495,14 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
> rcu_read_lock();
> list_for_each_entry_rcu(entry, &lowpan_devices, list)
> if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
> - skb = skb_copy(new, GFP_KERNEL);
> - skb->dev = entry->ldev;
> + skb = skb_copy(new, GFP_ATOMIC);
> + if (!skb) {
> + stat = -ENOMEM;
> + break;
> + }
>
> - if (in_interrupt())
> - stat = netif_rx(skb);
> - else
> - stat = netif_rx_ni(skb);
> + skb->dev = entry->ldev;
> + stat = netif_rx(skb);
> }
> rcu_read_unlock();
>
^ permalink raw reply
* Re: [PATCH] dev_ioctl should return -EINVAL for unknown ioctl instead of -ENOTTY
From: Ben Hutchings @ 2011-09-01 15:41 UTC (permalink / raw)
To: Wang Sheng-Hui; +Cc: davem, netdev, linux-kernel
In-Reply-To: <4E5F9C14.1040108@gmail.com>
On Thu, 2011-09-01 at 22:52 +0800, Wang Sheng-Hui wrote:
> The patch is against 3.1-rc3.
>
> Signed-off-by: Wang Sheng-Hui <shhuiw@gmail.com>
> ---
> net/core/dev.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 17d67b5..de6033c 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -5092,7 +5092,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
> /* Take care of Wireless Extensions */
> if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
> return wext_handle_ioctl(net, &ifr, cmd, arg);
> - return -ENOTTY;
> + return -EINVAL;
> }
> }
>
Whereas, Linus Torvalds wrote in
<BANLkTin=PTbTwBR2s+owMLy+GmKigeoYvg@mail.gmail.com>:
[...]
> The correct error code for "I don't understand this ioctl" is ENOTTY.
> The naming may be odd, but you should think of that error value as a
> "unrecognized ioctl number, you're feeding me random numbers that I
> don't understand and I assume for historical reasons that you tried to
> do some tty operation on me".
[...]
(Not that we are consistent about using ENOTTY in networking now.)
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: commit 1faa4356 breaks IPv6 assignment on libvirtd
From: Stephen Hemminger @ 2011-09-01 15:51 UTC (permalink / raw)
To: Ang Way Chuang; +Cc: netdev
In-Reply-To: <4E5F99E2.50301@sfc.wide.ad.jp>
On Thu, 01 Sep 2011 23:42:42 +0900
Ang Way Chuang <wcang@sfc.wide.ad.jp> wrote:
> Hi all,
>
> Commit 1faa4356 break IPv6 assignment on libvirtd. The configuration for my VM bridge network is as such:
>
> <network>
> <name>default</name>
> <forward mode='nat'/>
> <bridge name='virbr0' stp='on' delay='0' />
> <ip address='192.168.122.1' netmask='255.255.255.0'>
> <dhcp>
> <range start='192.168.122.2' end='192.168.122.254' />
> </dhcp>
> </ip>
> <ip family='ipv6' address='2001:d30:113:504::1' prefix='64'>
> </ip>
> </network>
>
> This configuration worked fine on kernel 2.6.38. Updating my distro kernel broke the setup. My colleague
> and I traced the problem and found that libvirtd failed because there wasn't any carrier on virbr0 interface
> due to the change introduced by that commit. How can this be fixed? Thanks in advance.
>
> Regards,
> Ang Way Chuang
The issue is that address is assigned to a bridge device with no ports.
IPv6 needs carrier to do duplicate address detection. Without any ports
the DAD will always succeed, and there is a possibility that when ports
are later added to the bridge the address actually is a duplicate.
A couple of possible options are:
1. Default to carrier on in bridge when there are no ports.
The downside with this is that IPv6 DAD is being fooled.
2. Change libvirt to allow turning off DAD. This is controlled
in kernel by writing 0 to /proc/sys/net/ipv6/conf/virbr0/accept_dad
^ 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