* Re: [RFC PATCH bridge 5/5] bridge: Add sysfs interface to display VLANS
From: Vlad Yasevich @ 2012-08-30 14:05 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev
In-Reply-To: <20120830122724.GC20228@redhat.com>
On 08/30/2012 08:27 AM, Michael S. Tsirkin wrote:
> On Thu, Aug 23, 2012 at 03:29:55PM -0400, Vlad Yasevich wrote:
>> Add a binary sysfs file that will dump out vlans currently configured on the
>> port.
>>
>> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
>
> So what's the format here? I could not tell.
> List of vlans? Why binary? Why not make it text in that case?
> This would also allow reporting "all" if filtering
> is disabled and "untagged" for untagged packets.
I decided to do binary because text may result in more then page worth
of data. The display tool will know how to display things properly.
-vlad
>
>> ---
>> include/linux/if_bridge.h | 1 +
>> net/bridge/br_if.c | 34 ++++++++++++++++++++++++++++++++++
>> net/bridge/br_private.h | 2 ++
>> net/bridge/br_sysfs_if.c | 28 ++++++++++++++++++++++++++++
>> 4 files changed, 65 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
>> index ab750dd..d0f869b 100644
>> --- a/include/linux/if_bridge.h
>> +++ b/include/linux/if_bridge.h
>> @@ -20,6 +20,7 @@
>> #define SYSFS_BRIDGE_PORT_SUBDIR "brif"
>> #define SYSFS_BRIDGE_PORT_ATTR "brport"
>> #define SYSFS_BRIDGE_PORT_LINK "bridge"
>> +#define SYSFS_BRIDGE_PORT_VLANS "vlans"
>>
>> #define BRCTL_VERSION 1
>>
>> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
>> index 90c1038..3963748 100644
>> --- a/net/bridge/br_if.c
>> +++ b/net/bridge/br_if.c
>> @@ -510,6 +510,40 @@ int br_del_port_vlan(struct net_bridge_port *p, unsigned long vlan)
>> return 0;
>> }
>>
>> +size_t br_port_fill_vlans(struct net_bridge_port *p, char* buf,
>> + unsigned long max, unsigned long skip)
>> +{
>> + unsigned long *map;
>> + unsigned short *vid = (unsigned short *)buf;
>> + unsigned short i;
>> + int num = 0;
>> +
>> + if (skip > (VLAN_N_VID+1))
>> + return -EINVAL;
>> +
>> + memset(buf, 0, max * sizeof(unsigned short));
>
> Isn't max is in bytes? why is this safe?
>
>> +
>> + rcu_read_lock();
>> + map = rcu_dereference(p->vlan_map);
>> + if (!map)
>> + goto out;
>> +
>> + for (i = skip + 1; i < VLAN_N_VID + 1; i++) {
>
> Isn't skip in bytes too? Why do you compare it to i which is
> in dwords?
>
>> + if (test_bit(i, map)) {
>> + if (num > max)
>> + goto out;
>> +
>> + *vid = i-1;
>> + vid++;
>> + num++;
>> + }
>> + }
>> +out:
>> + rcu_read_unlock();
>> +
>> + return num*sizeof(unsigned short);
>> +}
>> +
>> void __net_exit br_net_exit(struct net *net)
>> {
>> struct net_device *dev;
>> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
>> index 5639c1c..cf95cd7 100644
>> --- a/net/bridge/br_private.h
>> +++ b/net/bridge/br_private.h
>> @@ -404,6 +404,8 @@ extern netdev_features_t br_features_recompute(struct net_bridge *br,
>> netdev_features_t features);
>> extern int br_set_port_vlan(struct net_bridge_port *p, unsigned long vid);
>> extern int br_del_port_vlan(struct net_bridge_port *p, unsigned long vid);
>> +extern size_t br_port_fill_vlans(struct net_bridge_port *p, char *buf,
>> + unsigned long max, unsigned long skip);
>>
>> /* br_input.c */
>> extern int br_handle_frame_finish(struct sk_buff *skb);
>> diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
>> index 13b36bd..a81e2ef 100644
>> --- a/net/bridge/br_sysfs_if.c
>> +++ b/net/bridge/br_sysfs_if.c
>> @@ -234,6 +234,29 @@ const struct sysfs_ops brport_sysfs_ops = {
>> };
>>
>> /*
>> + * Export the vlan table for a given port as a binary file.
>> + * The records are unsgined shorts.
>> + *
>> + * Returns the number of bytes read.
>> + */
>> +static ssize_t brport_vlans_read(struct file *filp, struct kobject *kobj,
>> + struct bin_attribute *bin_attr,
>> + char *buf, loff_t off, size_t count)
>> +{
>> + struct net_bridge_port *p = to_brport(kobj);
>> +
>> + return br_port_fill_vlans(p, buf,
>> + count/sizeof(unsigned short),
>> + off/sizeof(unsigned short));
>> +}
>> +
>> +static struct bin_attribute port_vlans = {
>> + .attr = { .name = SYSFS_BRIDGE_PORT_VLANS,
>> + .mode = S_IRUGO, },
>> + .read = brport_vlans_read,
>> +};
>> +
>> +/*
>> * Add sysfs entries to ethernet device added to a bridge.
>> * Creates a brport subdirectory with bridge attributes.
>> * Puts symlink in bridge's brif subdirectory
>> @@ -255,6 +278,11 @@ int br_sysfs_addif(struct net_bridge_port *p)
>> return err;
>> }
>>
>> + err = sysfs_create_bin_file(&p->kobj, &port_vlans);
>> + if (err) {
>> + return err;
>> + }
>> +
>> strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
>> return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name);
>> }
>> --
>> 1.7.7.6
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH bridge 0/5] Add basic VLAN support to bridges
From: Vlad Yasevich @ 2012-08-30 13:37 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev
In-Reply-To: <20120830123724.GE20228@redhat.com>
On 08/30/2012 08:37 AM, Michael S. Tsirkin wrote:
> On Thu, Aug 23, 2012 at 03:29:50PM -0400, Vlad Yasevich wrote:
>> This series of patches provides an ability to add VLAN IDs to the bridge
>> ports. This is similar to what can be found in most switches. The bridge
>> port may have any number of VLANs added to it including vlan 0 for untagged
>> traffic. When vlans are added to the port, only traffic tagged with particular
>> vlan will forwarded over this port. Additionally, vlan ids are added to FDB
>> entries and become part of the lookup. This way we correctly identify the FDB
>> entry.
>>
>> There are still pieces missing. I don't yet support adding a static fdb entry
>> with a particular vlan. There is no netlink support for carrying a vlan id.
>>
>> I'd like to hear thoughts of whether this is usufull and something we should
>> persue.
>>
>> The default behavior ofthe bridge is unchanged if no vlans have been
>> configured.
>
> Overall the feature looks good, I can think of some uses
> for it - for example, it could become useful for VMs if
> we add support to tap essentially stripping tags in Xmit but maybe you
> could be more explicit about what you have in mind?
> Do you plan to add tap support as well?
Yes, this is something I've thought of. Not sure if it would be at tap
or bridge itself. Need to work out where best to do it.
> Also - what tool support do you plan?
the patchset includes brctl to configure, but that seems to be getting
deprecated. I am working on iproute2 to add capability to configure this.
>
> I also found some coding style issues and some bugs in
> the patchset. Sent on list.
Thanks
-vlad
>
> Hope this helps.
>
^ permalink raw reply
* Re: [PATCH 1/1] tcp: Wrong timeout for SYN segments
From: Eric Dumazet @ 2012-08-30 13:12 UTC (permalink / raw)
To: H.K. Jerry Chu; +Cc: Alexander Bergmann, David Miller, netdev, linux-kernel
In-Reply-To: <CAFbMe2PG90X7s6s970+XK3X0Jvzx4p6vhvM+JQCwtULPvs1QLw@mail.gmail.com>
On Wed, 2012-08-29 at 10:25 -0700, H.K. Jerry Chu wrote:
> But it probably matter slightly more for TCP Fast Open (the server
> side patch has
> been completed and will be posted soon, after I finish breaking it up
> into smaller
> pieces for ease of review purpose), when a full socket will be created with data
> passed to the app upon a valid SYN+data. Dropping a fully functioning socket
> won't be the same as dropping a request_sock unknown to the app and letting
> the other side retransmitting SYN (w/o data this time).
>
> >
> > Sure, RFC numbers are what they are, but in practice, I doubt someone
> > will really miss the extra SYNACK sent after ~32 seconds, since it would
> > matter only for the last SYN attempted.
>
> I'd slightly prefer 1 extra retry plus longer wait time just to make
> TCP Fast Open
> a little more robust (even though the app protocol is required to be
> idempotent).
> But this is not a showstopper.
Thats very good points indeed, thanks.
Maybe we can increase SYNACK max retrans only if the FastOpen SYN cookie
was validated.
This way, we increase reliability without amplifying the effect of wild
SYN packets.
^ permalink raw reply
* Re: [RFC PATCH bridge 3/5] bridge: Add vlan id to multicast groups
From: Eric Dumazet @ 2012-08-30 12:55 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-4-git-send-email-vyasevic@redhat.com>
On Thu, 2012-08-23 at 15:29 -0400, Vlad Yasevich wrote:
> Add vlan_id to multicasts groups so that we know which vlan each group belongs
> to and can correctly forward to appropriate vlan.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
> ---
> #if IS_ENABLED(CONFIG_IPV6)
> static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb,
> - const struct in6_addr *ip)
> + const struct in6_addr *ip,
> + __u16 vid)
> {
> - return jhash2((__force u32 *)ip->s6_addr32, 4, mdb->secret) & (mdb->max - 1);
> + u32 addr = *(__force u32 *)ip->s6_addr32;
> + return jhash_2words(addr, vid, mdb->secret) & (mdb->max - 1);
> }
> #endif
It seems to me this is wrong.
Hashing only the first 32bits of the IPv6 address is not enough.
We know have ipv6_addr_hash()
^ permalink raw reply
* Re: [Qemu-devel] macvlan/macvtap: guest/host cannot communicate when network cable is unplugged
From: Stefan Hajnoczi @ 2012-08-30 12:53 UTC (permalink / raw)
To: ching; +Cc: qemu-devel, kaber, Michael S. Tsirkin, netdev
In-Reply-To: <503F58D0.2010003@gmail.com>
On Thu, Aug 30, 2012 at 1:13 PM, ching <lsching17@gmail.com> wrote:
>
>> Can you try the same test with two macvlan interfaces on the host (no
>> macvtap)? You may need to use the ping -I <interface-address>
>> argument to force the ping source address to a specific macvlan
>> interface.
>>
>> If you see the same problem, it may just be the macvlan design - it is
>> stacked on top of eth0 and might not work when eth0 is down. CCing
>> macvlan/macvtap folks.
>>
>> Stefan
>>
>
> tested as below
>
> $ifconfig
>
> eth0 Link encap:Ethernet HWaddr f4:6d:xx:xx:xx:xx
> inet6 addr: fe80::xx:xx:xx:xx/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:86507 errors:0 dropped:0 overruns:0 frame:0
> TX packets:55940 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:126005746 (120.1 MiB) TX bytes:4394225 (4.1 MiB)
>
> macvtap0 Link encap:Ethernet HWaddr 52:54:xx:xx:xx:xx
> inet6 addr: fe80::xx:xx:xx:xx/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:70 errors:0 dropped:0 overruns:0 frame:0
> TX packets:84 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:500
> RX bytes:9036 (8.8 KiB) TX bytes:14734 (14.3 KiB)
>
> znet0 Link encap:Ethernet HWaddr 00:60:xx:xx:xx:92
> inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
> inet6 addr: 2002:xx:xx:xx:xx/64 Scope:Global
> inet6 addr: fe80:xx:xx:xx:xx/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:4463190 errors:0 dropped:0 overruns:0 frame:0
> TX packets:12527522 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:0
> RX bytes:3959213697 (3.6 GiB) TX bytes:18590336476 (17.3 GiB)
>
> znet1 Link encap:Ethernet HWaddr 00:60:xx:xx:xx:99
> inet addr:192.168.1.177 Bcast:192.168.1.255 Mask:255.255.255.0
> inet6 addr: 2002:xx:xx:xx:xx64 Scope:Global
> inet6 addr: fe80:xx:xx:xx:xx/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:8 errors:0 dropped:0 overruns:0 frame:0
> TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:0
> RX bytes:1399 (1.3 KiB) TX bytes:1522 (1.4 KiB)
>
> $ ip -d link show
>
> 10: znet0@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT
> link/ether 00:60:xx:xx:xx:92 brd ff:ff:ff:ff:ff:ff
> macvlan mode bridge
> 15: znet1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT
> link/ether 00:60:xx:xx:xx:99 brd ff:ff:ff:ff:ff:ff
> macvlan mode bridge
>
>
> the macvlan interface cannot ping each other no matter network cable is plugged or not
>
> $ ping -I 192.168.1.2 192.168.1.177
> PING 192.168.1.177 (192.168.1.177) from 192.168.1.2 : 56(84) bytes of data.
>
> --- 192.168.1.177 ping statistics ---
> 6 packets transmitted, 0 received, 100% packet loss, time 4999ms
In bridge mode I expected them to be able to communicate.
> I also perform an additional test: the guests (macvtap bridge mode) CAN communicate each other no matter network cable is plugged or not.
Strange. I thought the original problem was that the macvtap guests
cannot communicate with each other when the network cable is
unplugged?
Hopefully someone else can help you, I'm not familiar enough with
macvlan/macvtap.
Stefan
^ permalink raw reply
* Re: [RFC PATCH bridge 0/5] Add basic VLAN support to bridges
From: Michael S. Tsirkin @ 2012-08-30 12:37 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-1-git-send-email-vyasevic@redhat.com>
On Thu, Aug 23, 2012 at 03:29:50PM -0400, Vlad Yasevich wrote:
> This series of patches provides an ability to add VLAN IDs to the bridge
> ports. This is similar to what can be found in most switches. The bridge
> port may have any number of VLANs added to it including vlan 0 for untagged
> traffic. When vlans are added to the port, only traffic tagged with particular
> vlan will forwarded over this port. Additionally, vlan ids are added to FDB
> entries and become part of the lookup. This way we correctly identify the FDB
> entry.
>
> There are still pieces missing. I don't yet support adding a static fdb entry
> with a particular vlan. There is no netlink support for carrying a vlan id.
>
> I'd like to hear thoughts of whether this is usufull and something we should
> persue.
>
> The default behavior ofthe bridge is unchanged if no vlans have been
> configured.
Overall the feature looks good, I can think of some uses
for it - for example, it could become useful for VMs if
we add support to tap essentially stripping tags in Xmit but maybe you
could be more explicit about what you have in mind?
Do you plan to add tap support as well?
Also - what tool support do you plan?
I also found some coding style issues and some bugs in
the patchset. Sent on list.
Hope this helps.
--
MST
^ permalink raw reply
* Re: [RFC PATCH bridge 3/5] bridge: Add vlan id to multicast groups
From: Michael S. Tsirkin @ 2012-08-30 12:30 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-4-git-send-email-vyasevic@redhat.com>
On Thu, Aug 23, 2012 at 03:29:53PM -0400, Vlad Yasevich wrote:
> Add vlan_id to multicasts groups so that we know which vlan each group belongs
> to and can correctly forward to appropriate vlan.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
> ---
> net/bridge/br_multicast.c | 64 +++++++++++++++++++++++++++++++--------------
> net/bridge/br_private.h | 1 +
> 2 files changed, 45 insertions(+), 20 deletions(-)
>
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 2417434..2976a2b 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -51,6 +51,8 @@ static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
> {
> if (a->proto != b->proto)
> return 0;
> + if (a->vid != b->vid)
> + return 0;
> switch (a->proto) {
> case htons(ETH_P_IP):
> return a->u.ip4 == b->u.ip4;
> @@ -62,16 +64,19 @@ static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
> return 0;
> }
>
> -static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip)
> +static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip,
> + __u16 vid)
> {
> - return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1);
> + return jhash_2words((__force u32)ip, vid, mdb->secret) & (mdb->max - 1);
> }
>
> #if IS_ENABLED(CONFIG_IPV6)
> static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb,
> - const struct in6_addr *ip)
> + const struct in6_addr *ip,
> + __u16 vid)
> {
> - return jhash2((__force u32 *)ip->s6_addr32, 4, mdb->secret) & (mdb->max - 1);
> + u32 addr = *(__force u32 *)ip->s6_addr32;
> + return jhash_2words(addr, vid, mdb->secret) & (mdb->max - 1);
> }
> #endif
>
> @@ -80,10 +85,10 @@ static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb,
> {
> switch (ip->proto) {
> case htons(ETH_P_IP):
> - return __br_ip4_hash(mdb, ip->u.ip4);
> + return __br_ip4_hash(mdb, ip->u.ip4, ip->vid);
> #if IS_ENABLED(CONFIG_IPV6)
> case htons(ETH_P_IPV6):
> - return __br_ip6_hash(mdb, &ip->u.ip6);
> + return __br_ip6_hash(mdb, &ip->u.ip6, ip->vid);
> #endif
> }
> return 0;
> @@ -113,24 +118,27 @@ static struct net_bridge_mdb_entry *br_mdb_ip_get(
> }
>
> static struct net_bridge_mdb_entry *br_mdb_ip4_get(
> - struct net_bridge_mdb_htable *mdb, __be32 dst)
> + struct net_bridge_mdb_htable *mdb, __be32 dst, __u16 vlan_tci)
> {
> struct br_ip br_dst;
>
> br_dst.u.ip4 = dst;
> br_dst.proto = htons(ETH_P_IP);
> + br_dst.vid = (vlan_tci & VLAN_VID_MASK);
() around value not needed.
Same in all cases below, I am not repeating
this comment.
>
> return br_mdb_ip_get(mdb, &br_dst);
> }
>
> #if IS_ENABLED(CONFIG_IPV6)
> static struct net_bridge_mdb_entry *br_mdb_ip6_get(
> - struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst)
> + struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst,
> + __u16 vlan_tci)
> {
> struct br_ip br_dst;
>
> br_dst.u.ip6 = *dst;
> br_dst.proto = htons(ETH_P_IPV6);
> + br_dst.vid = vlan_tci & VLAN_VID_MASK;
>
> return br_mdb_ip_get(mdb, &br_dst);
> }
> @@ -692,7 +700,8 @@ err:
>
> static int br_ip4_multicast_add_group(struct net_bridge *br,
> struct net_bridge_port *port,
> - __be32 group)
> + __be32 group,
> + __u16 vlan_tci)
> {
> struct br_ip br_group;
>
> @@ -701,6 +710,7 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
>
> br_group.u.ip4 = group;
> br_group.proto = htons(ETH_P_IP);
> + br_group.vid = vlan_tci & VLAN_VID_MASK;
>
> return br_multicast_add_group(br, port, &br_group);
> }
> @@ -708,7 +718,8 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
> #if IS_ENABLED(CONFIG_IPV6)
> static int br_ip6_multicast_add_group(struct net_bridge *br,
> struct net_bridge_port *port,
> - const struct in6_addr *group)
> + const struct in6_addr *group,
> + __u16 vlan_tci)
> {
> struct br_ip br_group;
>
> @@ -717,6 +728,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
>
> br_group.u.ip6 = *group;
> br_group.proto = htons(ETH_P_IPV6);
> + br_group.vid = vlan_tci & VLAN_VID_MASK;
>
> return br_multicast_add_group(br, port, &br_group);
> }
> @@ -928,7 +940,8 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
> continue;
> }
>
> - err = br_ip4_multicast_add_group(br, port, group);
> + err = br_ip4_multicast_add_group(br, port, group,
> + skb->vlan_tci);
Pls align continuation line at (, same as other
code in this file. Same in all cases below, I am not repeating
this comment.
> if (err)
> break;
> }
> @@ -988,7 +1001,8 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
> continue;
> }
>
> - err = br_ip6_multicast_add_group(br, port, &grec->grec_mca);
> + err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
> + skb->vlan_tci);
> if (!err)
> break;
> }
> @@ -1106,7 +1120,8 @@ static int br_ip4_multicast_query(struct net_bridge *br,
> if (!group)
> goto out;
>
> - mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group);
> + mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group,
> + skb->vlan_tci);
> if (!mp)
> goto out;
>
> @@ -1178,7 +1193,8 @@ static int br_ip6_multicast_query(struct net_bridge *br,
> if (!group)
> goto out;
>
> - mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group);
> + mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group,
> + skb->vlan_tci);
> if (!mp)
> goto out;
>
> @@ -1262,7 +1278,8 @@ out:
>
> static void br_ip4_multicast_leave_group(struct net_bridge *br,
> struct net_bridge_port *port,
> - __be32 group)
> + __be32 group,
> + __u16 vlan_tci)
> {
> struct br_ip br_group;
>
> @@ -1271,6 +1288,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
>
> br_group.u.ip4 = group;
> br_group.proto = htons(ETH_P_IP);
> + br_group.vid = (vlan_tci & VLAN_VID_MASK);
>
> br_multicast_leave_group(br, port, &br_group);
> }
> @@ -1278,7 +1296,8 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
> #if IS_ENABLED(CONFIG_IPV6)
> static void br_ip6_multicast_leave_group(struct net_bridge *br,
> struct net_bridge_port *port,
> - const struct in6_addr *group)
> + const struct in6_addr *group,
> + __u16 vlan_tci)
> {
> struct br_ip br_group;
>
> @@ -1287,6 +1306,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
>
> br_group.u.ip6 = *group;
> br_group.proto = htons(ETH_P_IPV6);
> + br_group.vid = (vlan_tci & VLAN_VID_MASK);
>
> br_multicast_leave_group(br, port, &br_group);
> }
> @@ -1369,7 +1389,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
> case IGMP_HOST_MEMBERSHIP_REPORT:
> case IGMPV2_HOST_MEMBERSHIP_REPORT:
> BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
> - err = br_ip4_multicast_add_group(br, port, ih->group);
> + err = br_ip4_multicast_add_group(br, port, ih->group,
> + skb2->vlan_tci);
> break;
> case IGMPV3_HOST_MEMBERSHIP_REPORT:
> err = br_ip4_multicast_igmp3_report(br, port, skb2);
> @@ -1378,7 +1399,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
> err = br_ip4_multicast_query(br, port, skb2);
> break;
> case IGMP_HOST_LEAVE_MESSAGE:
> - br_ip4_multicast_leave_group(br, port, ih->group);
> + br_ip4_multicast_leave_group(br, port, ih->group,
> + skb2->vlan_tci);
> break;
> }
>
> @@ -1498,7 +1520,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
> }
> mld = (struct mld_msg *)skb_transport_header(skb2);
> BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
> - err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
> + err = br_ip6_multicast_add_group(br, port, &mld->mld_mca,
> + skb2->vlan_tci);
> break;
> }
> case ICMPV6_MLD2_REPORT:
> @@ -1515,7 +1538,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
> goto out;
> }
> mld = (struct mld_msg *)skb_transport_header(skb2);
> - br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
> + br_ip6_multicast_leave_group(br, port, &mld->mld_mca,
> + skb2->vlan_tci);
> }
> }
>
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 921b927..b6c56ab 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -61,6 +61,7 @@ struct br_ip
> #endif
> } u;
> __be16 proto;
> + __u16 vid;
> };
>
> struct net_bridge_fdb_entry
> --
> 1.7.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH bridge 5/5] bridge: Add sysfs interface to display VLANS
From: Michael S. Tsirkin @ 2012-08-30 12:27 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-6-git-send-email-vyasevic@redhat.com>
On Thu, Aug 23, 2012 at 03:29:55PM -0400, Vlad Yasevich wrote:
> Add a binary sysfs file that will dump out vlans currently configured on the
> port.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
So what's the format here? I could not tell.
List of vlans? Why binary? Why not make it text in that case?
This would also allow reporting "all" if filtering
is disabled and "untagged" for untagged packets.
> ---
> include/linux/if_bridge.h | 1 +
> net/bridge/br_if.c | 34 ++++++++++++++++++++++++++++++++++
> net/bridge/br_private.h | 2 ++
> net/bridge/br_sysfs_if.c | 28 ++++++++++++++++++++++++++++
> 4 files changed, 65 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index ab750dd..d0f869b 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -20,6 +20,7 @@
> #define SYSFS_BRIDGE_PORT_SUBDIR "brif"
> #define SYSFS_BRIDGE_PORT_ATTR "brport"
> #define SYSFS_BRIDGE_PORT_LINK "bridge"
> +#define SYSFS_BRIDGE_PORT_VLANS "vlans"
>
> #define BRCTL_VERSION 1
>
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index 90c1038..3963748 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -510,6 +510,40 @@ int br_del_port_vlan(struct net_bridge_port *p, unsigned long vlan)
> return 0;
> }
>
> +size_t br_port_fill_vlans(struct net_bridge_port *p, char* buf,
> + unsigned long max, unsigned long skip)
> +{
> + unsigned long *map;
> + unsigned short *vid = (unsigned short *)buf;
> + unsigned short i;
> + int num = 0;
> +
> + if (skip > (VLAN_N_VID+1))
> + return -EINVAL;
> +
> + memset(buf, 0, max * sizeof(unsigned short));
Isn't max is in bytes? why is this safe?
> +
> + rcu_read_lock();
> + map = rcu_dereference(p->vlan_map);
> + if (!map)
> + goto out;
> +
> + for (i = skip + 1; i < VLAN_N_VID + 1; i++) {
Isn't skip in bytes too? Why do you compare it to i which is
in dwords?
> + if (test_bit(i, map)) {
> + if (num > max)
> + goto out;
> +
> + *vid = i-1;
> + vid++;
> + num++;
> + }
> + }
> +out:
> + rcu_read_unlock();
> +
> + return num*sizeof(unsigned short);
> +}
> +
> void __net_exit br_net_exit(struct net *net)
> {
> struct net_device *dev;
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 5639c1c..cf95cd7 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -404,6 +404,8 @@ extern netdev_features_t br_features_recompute(struct net_bridge *br,
> netdev_features_t features);
> extern int br_set_port_vlan(struct net_bridge_port *p, unsigned long vid);
> extern int br_del_port_vlan(struct net_bridge_port *p, unsigned long vid);
> +extern size_t br_port_fill_vlans(struct net_bridge_port *p, char *buf,
> + unsigned long max, unsigned long skip);
>
> /* br_input.c */
> extern int br_handle_frame_finish(struct sk_buff *skb);
> diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
> index 13b36bd..a81e2ef 100644
> --- a/net/bridge/br_sysfs_if.c
> +++ b/net/bridge/br_sysfs_if.c
> @@ -234,6 +234,29 @@ const struct sysfs_ops brport_sysfs_ops = {
> };
>
> /*
> + * Export the vlan table for a given port as a binary file.
> + * The records are unsgined shorts.
> + *
> + * Returns the number of bytes read.
> + */
> +static ssize_t brport_vlans_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr,
> + char *buf, loff_t off, size_t count)
> +{
> + struct net_bridge_port *p = to_brport(kobj);
> +
> + return br_port_fill_vlans(p, buf,
> + count/sizeof(unsigned short),
> + off/sizeof(unsigned short));
> +}
> +
> +static struct bin_attribute port_vlans = {
> + .attr = { .name = SYSFS_BRIDGE_PORT_VLANS,
> + .mode = S_IRUGO, },
> + .read = brport_vlans_read,
> +};
> +
> +/*
> * Add sysfs entries to ethernet device added to a bridge.
> * Creates a brport subdirectory with bridge attributes.
> * Puts symlink in bridge's brif subdirectory
> @@ -255,6 +278,11 @@ int br_sysfs_addif(struct net_bridge_port *p)
> return err;
> }
>
> + err = sysfs_create_bin_file(&p->kobj, &port_vlans);
> + if (err) {
> + return err;
> + }
> +
> strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
> return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name);
> }
> --
> 1.7.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH bridge 1/5] bridge: Add vlan check to forwarding path
From: Michael S. Tsirkin @ 2012-08-30 12:19 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-2-git-send-email-vyasevic@redhat.com>
On Thu, Aug 23, 2012 at 03:29:51PM -0400, Vlad Yasevich wrote:
> When forwarding packets make sure vlan matches any configured vlan for
> the port.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
> ---
> net/bridge/br_forward.c | 17 ++++++++++++++++-
> net/bridge/br_input.c | 8 ++++++++
> net/bridge/br_private.h | 2 ++
> 3 files changed, 26 insertions(+), 1 deletions(-)
>
> diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
> index e9466d4..ab81954 100644
> --- a/net/bridge/br_forward.c
> +++ b/net/bridge/br_forward.c
> @@ -26,11 +26,26 @@ static int deliver_clone(const struct net_bridge_port *prev,
> void (*__packet_hook)(const struct net_bridge_port *p,
> struct sk_buff *skb));
>
> -/* Don't forward packets to originating port or forwarding diasabled */
> +/* check to see that the vlan is allowed to be forwarded on this interface */
> +static inline int vlan_match(const struct net_bridge_port *p,
> + const struct sk_buff *skb)
> +{
> + unsigned long *vlan_map = rcu_dereference(p->vlan_map);
> + unsigned short vid = vlan_tx_tag_get(skb) & VLAN_VID_MASK;
> +
> + /* The map keeps the vlans off by 1 so adjust for that */
> + return (vlan_map && vlan_tx_tag_present(skb) &&
> + test_bit(vid+1, vlan_map));
It looks better if you put spaces around +,* etc:
vid + 1 This applies to all patches and many places so I am not
noting it everywhere - could you fnd such instances and fix up?
Also, this off by 1 map logic is all over this patch,
one hopes we did not forget is somewhere.
Would be better to have a wrapper.
Also do not put return value in () please - it gets us nothing
at all. Again applies everywhere.
> +}
> +
> +/* Don't forward packets to originating port or forwarding diasabled.
> + */
> static inline int should_deliver(const struct net_bridge_port *p,
> const struct sk_buff *skb)
> {
> +
extra empty line - no needed here.
> return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
> + vlan_match(p, skb) &&
> p->state == BR_STATE_FORWARDING);
> }
>
> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> index 76f15fd..b7ca3b3 100644
> --- a/net/bridge/br_input.c
> +++ b/net/bridge/br_input.c
> @@ -53,10 +53,18 @@ int br_handle_frame_finish(struct sk_buff *skb)
> struct net_bridge_fdb_entry *dst;
> struct net_bridge_mdb_entry *mdst;
> struct sk_buff *skb2;
> + unsigned long *vlan_map;
>
> if (!p || p->state == BR_STATE_DISABLED)
> goto drop;
>
> + /* If VLAN filter is configured on the port, make sure we accept
> + * only traffic matching the VLAN filter.
> + */
> + vlan_map = rcu_dereference(p->vlan_map);
> + if (vlan_map && !test_bit((skb->vlan_tci & VLAN_VID_MASK), vlan_map))
() not needed here around parameters.
> + goto drop;
> +
> /* insert into forwarding database after filtering to avoid spoofing */
> br = p->br;
> br_fdb_update(br, p, eth_hdr(skb)->h_source);
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index a768b24..8da90e8 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -152,6 +152,8 @@ struct net_bridge_port
> #ifdef CONFIG_NET_POLL_CONTROLLER
> struct netpoll *np;
> #endif
> + unsigned long __rcu *vlan_map;
> +
Empty line not needed.
> };
>
> #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
> --
> 1.7.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH bridge 4/5] bridge: Add private ioctls to configure vlans on bridge ports
From: Michael S. Tsirkin @ 2012-08-30 12:17 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1345750195-31598-5-git-send-email-vyasevic@redhat.com>
On Thu, Aug 23, 2012 at 03:29:54PM -0400, Vlad Yasevich wrote:
> Add a private ioctl to add and remove vlan configuration on bridge port.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
> ---
> include/linux/if_bridge.h | 2 +
> net/bridge/br_if.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
> net/bridge/br_ioctl.c | 31 ++++++++++++++++++++
> net/bridge/br_private.h | 2 +
> 4 files changed, 104 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index 288ff10..ab750dd 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -42,6 +42,8 @@
> #define BRCTL_SET_PORT_PRIORITY 16
> #define BRCTL_SET_PATH_COST 17
> #define BRCTL_GET_FDB_ENTRIES 18
> +#define BRCTL_ADD_VLAN 19
> +#define BRCTL_DEL_VLAN 20
>
> #define BR_STATE_DISABLED 0
> #define BR_STATE_LISTENING 1
That's not a lot of documentation especially
considering tricks such as using vlan 0
to mean untagged (an internal convention in kernel).
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index e1144e1..90c1038 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -23,6 +23,7 @@
> #include <linux/if_ether.h>
> #include <linux/slab.h>
> #include <net/sock.h>
> +#include <linux/if_vlan.h>
>
> #include "br_private.h"
>
> @@ -441,6 +442,74 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
> return 0;
> }
>
> +/* Called with RTNL */
> +int br_set_port_vlan(struct net_bridge_port *p, unsigned long vlan)
> +{
> + unsigned long table_size = (VLAN_N_VID/sizeof(unsigned long)) + 1;
Use DECLARE_BITMAP[VLAN_N_VID + 1]?
> + unsigned long *vid_map = NULL;
> + __u16 vid = (__u16) vlan + 1;
Don't put space after cast: (__u16)vlan.
In fact, cast is not needed here at all.
Applies to other places in this patch that do this.
> +
> + /* We are under lock so we can check this without rcu.
> + * The vlan map is indexed by vid+1. This way we can store
> + * vid 0 (untagged) into the map as well.
> + */
Would be better to put this documentation in struct
definition where vid_map is defined.
> + if (!p->vlan_map) {
> + vid_map = kzalloc(table_size, GFP_KERNEL);
> + if (!vid_map)
> + return -ENOMEM;
> +
> + set_bit(vid, vid_map);
What prevents vid from being > table_size * BITS_PER_LONG?
> + rcu_assign_pointer(p->vlan_map, vid_map);
> +
> + } else {
> + /* Map is already allocated */
> + set_bit(vid, p->vlan_map);
This should call rcu_dereference_protected.
> + }
> +
> + return 0;
> +}
> +
> +
> +/* Called with RTNL */
> +int br_del_port_vlan(struct net_bridge_port *p, unsigned long vlan)
> +{
> + unsigned long first_bit;
> + unsigned long next_bit;
> + __u16 vid = (__u16) vlan+1;
> + unsigned long tbl_len = VLAN_N_VID+1;
Same as above.
> +
> + if (!p->vlan_map)
> + return -EINVAL;
> +
> + if (!test_bit(vlan, p->vlan_map))
> + return -EINVAL;
> +
> + /* Check to see if any other vlans are in this table. If this
> + * is the last vlan, delete the whole table. If this is not the
> + * last vlan, just clear the bit.
> + */
> + first_bit = find_first_bit(p->vlan_map, tbl_len);
> + next_bit = find_next_bit(p->vlan_map, tbl_len, (tbl_len - vid));
() not needed around arguments.
> +
> + if ((__u16)first_bit != vid || (__u16)next_bit < tbl_len) {
What are these type casts doing? How can you get a value > 0xffff?
> + /* There are other vlans still configured. We can simply
> + * clear our bit and be safe.
> + */
> + clear_bit(vid, p->vlan_map);
> + } else {
> + /* This is the last vlan we are removing. Replace the
> + * map with a NULL pointer and free the old map
> + */
> + unsigned long *map = rcu_dereference(p->vlan_map);
> +
> + rcu_assign_pointer(p->vlan_map, NULL);
> + synchronize_net();
> + kfree(map);
> + }
> +
> + return 0;
> +}
> +
> void __net_exit br_net_exit(struct net *net)
> {
> struct net_device *dev;
> diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
> index 7222fe1..3a5b1f9 100644
> --- a/net/bridge/br_ioctl.c
> +++ b/net/bridge/br_ioctl.c
> @@ -289,6 +289,37 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> case BRCTL_GET_FDB_ENTRIES:
> return get_fdb_entries(br, (void __user *)args[1],
> args[2], args[3]);
> + case BRCTL_ADD_VLAN:
> + {
> + struct net_bridge_port *p;
> +
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + rcu_read_lock();
> + if ((p = br_get_port(br, args[1])) == NULL) {
> + rcu_read_unlock();
> + return -EINVAL;
> + }
> + rcu_read_unlock();
> + return br_set_port_vlan(p, args[2]);
So this sets vlan but does not synchronize RCU.
This means if this is the 1st vlan we set,
we return to userspace and afterwards
interfaces get packets with a wrong vlan.
I am guessing all these ioctls should synchronize_net.
> + }
> +
> + case BRCTL_DEL_VLAN:
> + {
> + struct net_bridge_port *p;
> +
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + rcu_read_lock();
> + if ((p = br_get_port(br, args[1])) == NULL) {
> + rcu_read_unlock();
> + return -EINVAL;
> + }
> + rcu_read_unlock();
> + br_set_port_vlan(p, args[2]);
Same problem as above as synchronize_net is not
invoked always.
> + }
> }
>
> return -EOPNOTSUPP;
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index b6c56ab..5639c1c 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -402,6 +402,8 @@ extern int br_del_if(struct net_bridge *br,
> extern int br_min_mtu(const struct net_bridge *br);
> extern netdev_features_t br_features_recompute(struct net_bridge *br,
> netdev_features_t features);
> +extern int br_set_port_vlan(struct net_bridge_port *p, unsigned long vid);
> +extern int br_del_port_vlan(struct net_bridge_port *p, unsigned long vid);
>
> /* br_input.c */
> extern int br_handle_frame_finish(struct sk_buff *skb);
> --
> 1.7.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [Qemu-devel] macvlan/macvtap: guest/host cannot communicate when network cable is unplugged
From: ching @ 2012-08-30 12:13 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: qemu-devel, kaber, Michael S. Tsirkin, netdev
In-Reply-To: <CAJSP0QWV_RmEteRMUj4U2B9QRjGMkKL=AG3iyKyqEYiqGftFWg@mail.gmail.com>
> Can you try the same test with two macvlan interfaces on the host (no
> macvtap)? You may need to use the ping -I <interface-address>
> argument to force the ping source address to a specific macvlan
> interface.
>
> If you see the same problem, it may just be the macvlan design - it is
> stacked on top of eth0 and might not work when eth0 is down. CCing
> macvlan/macvtap folks.
>
> Stefan
>
tested as below
$ifconfig
eth0 Link encap:Ethernet HWaddr f4:6d:xx:xx:xx:xx
inet6 addr: fe80::xx:xx:xx:xx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:86507 errors:0 dropped:0 overruns:0 frame:0
TX packets:55940 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:126005746 (120.1 MiB) TX bytes:4394225 (4.1 MiB)
macvtap0 Link encap:Ethernet HWaddr 52:54:xx:xx:xx:xx
inet6 addr: fe80::xx:xx:xx:xx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:70 errors:0 dropped:0 overruns:0 frame:0
TX packets:84 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:9036 (8.8 KiB) TX bytes:14734 (14.3 KiB)
znet0 Link encap:Ethernet HWaddr 00:60:xx:xx:xx:92
inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: 2002:xx:xx:xx:xx/64 Scope:Global
inet6 addr: fe80:xx:xx:xx:xx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4463190 errors:0 dropped:0 overruns:0 frame:0
TX packets:12527522 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3959213697 (3.6 GiB) TX bytes:18590336476 (17.3 GiB)
znet1 Link encap:Ethernet HWaddr 00:60:xx:xx:xx:99
inet addr:192.168.1.177 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: 2002:xx:xx:xx:xx64 Scope:Global
inet6 addr: fe80:xx:xx:xx:xx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1399 (1.3 KiB) TX bytes:1522 (1.4 KiB)
$ ip -d link show
10: znet0@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT
link/ether 00:60:xx:xx:xx:92 brd ff:ff:ff:ff:ff:ff
macvlan mode bridge
15: znet1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT
link/ether 00:60:xx:xx:xx:99 brd ff:ff:ff:ff:ff:ff
macvlan mode bridge
the macvlan interface cannot ping each other no matter network cable is plugged or not
$ ping -I 192.168.1.2 192.168.1.177
PING 192.168.1.177 (192.168.1.177) from 192.168.1.2 : 56(84) bytes of data.
--- 192.168.1.177 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 4999ms
I also perform an additional test: the guests (macvtap bridge mode) CAN communicate each other no matter network cable is plugged or not.
^ permalink raw reply
* [PATCH] ipv6: remove some deadcode
From: Sorin Dumitru @ 2012-08-30 12:01 UTC (permalink / raw)
To: netdev; +Cc: davem, kuznet, jmorris, yoshfuji, kaber, Sorin Dumitru
__ipv6_regen_rndid no longer returns anything other than 0
so there's no point in verifying what it returns
Signed-off-by: Sorin Dumitru <sdumitru@ixiacom.com>
---
net/ipv6/addrconf.c | 29 +++++++----------------------
1 file changed, 7 insertions(+), 22 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6bc85f7..055627f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -127,8 +127,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
#endif
#ifdef CONFIG_IPV6_PRIVACY
-static int __ipv6_regen_rndid(struct inet6_dev *idev);
-static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
+static void __ipv6_regen_rndid(struct inet6_dev *idev);
+static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
static void ipv6_regen_rndid(unsigned long data);
#endif
@@ -852,16 +852,7 @@ retry:
}
in6_ifa_hold(ifp);
memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
- if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) {
- spin_unlock_bh(&ifp->lock);
- write_unlock(&idev->lock);
- pr_warn("%s: regeneration of randomized interface id failed\n",
- __func__);
- in6_ifa_put(ifp);
- in6_dev_put(idev);
- ret = -1;
- goto out;
- }
+ __ipv6_try_regen_rndid(idev, tmpaddr);
memcpy(&addr.s6_addr[8], idev->rndid, 8);
age = (now - ifp->tstamp) / HZ;
tmp_valid_lft = min_t(__u32,
@@ -1600,7 +1591,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
#ifdef CONFIG_IPV6_PRIVACY
/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
-static int __ipv6_regen_rndid(struct inet6_dev *idev)
+static void __ipv6_regen_rndid(struct inet6_dev *idev)
{
regen:
get_random_bytes(idev->rndid, sizeof(idev->rndid));
@@ -1627,8 +1618,6 @@ regen:
if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
goto regen;
}
-
- return 0;
}
static void ipv6_regen_rndid(unsigned long data)
@@ -1642,8 +1631,7 @@ static void ipv6_regen_rndid(unsigned long data)
if (idev->dead)
goto out;
- if (__ipv6_regen_rndid(idev) < 0)
- goto out;
+ __ipv6_regen_rndid(idev);
expires = jiffies +
idev->cnf.temp_prefered_lft * HZ -
@@ -1664,13 +1652,10 @@ out:
in6_dev_put(idev);
}
-static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
+static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
{
- int ret = 0;
-
if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
- ret = __ipv6_regen_rndid(idev);
- return ret;
+ __ipv6_regen_rndid(idev);
}
#endif
--
1.7.12
^ permalink raw reply related
* [RFC] Move in6_dev_hold under CONFIG_IPV6_PRIVACY
From: David Marchand @ 2012-08-30 9:42 UTC (permalink / raw)
To: netdev
Hello,
I am currently looking at a problem with in6 interface refcnt on a
really old kernel and I have just noticed something I find suspicious in
all kernels until now.
The comment at net/ipv6/addrconf.c:396 suggests that the call to
in6_dev_hold is only for ipv6_regen_rndid.
As a consequence, if CONFIG_IPV6_PRIVACY is not set, then this
in6_dev_hold will leak a refcnt.
Can someone look at this ?
I did not test this patch, yet it looks reasonable to me.
Thank you.
$ git diff
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6bc85f7..263fcf3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -393,11 +393,6 @@ static struct inet6_dev *ipv6_add_dev(struct
net_device *dev)
return NULL;
}
- /* One reference from device. We must do this before
- * we invoke __ipv6_regen_rndid().
- */
- in6_dev_hold(ndev);
-
if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
ndev->cnf.accept_dad = -1;
@@ -410,6 +405,12 @@ static struct inet6_dev *ipv6_add_dev(struct
net_device *dev)
#ifdef CONFIG_IPV6_PRIVACY
INIT_LIST_HEAD(&ndev->tempaddr_list);
+
+ /* One reference from device. We must do this before
+ * we invoke ipv6_regen_rndid().
+ */
+ in6_dev_hold(ndev);
+
setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned
long)ndev);
if ((dev->flags&IFF_LOOPBACK) ||
dev->type == ARPHRD_TUNNEL ||
--
David Marchand
This message has been scanned for viruses by BlackSpider MailControl. - www.blackspider.com
^ permalink raw reply related
* Re: Slow inbound traffic on macvtap interfaces
From: Richard Davies @ 2012-08-30 8:20 UTC (permalink / raw)
To: Chris Webb; +Cc: netdev, qemu-devel, Jason Wang, Arnd Bergmann, Michael Tsirkin
In-Reply-To: <20120829175256.GC3529@arachsys.com>
Chris Webb wrote:
> I found that on my laptop, the single change of host kernel config
>
> -CONFIG_INTEL_IDLE=y
> +# CONFIG_INTEL_IDLE is not set
>
> is sufficient to turn transfers into guests from slow to full wire speed
I am not deep enough in this code to write a patch, but I wonder if
macvtap_forward in macvtap.c is missing a call to kill_fasync, which I
understand is used to signal to interested processes when data arrives?
Here is the end of macvtap_forward:
skb_queue_tail(&q->sk.sk_receive_queue, skb);
wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
return NET_RX_SUCCESS;
Compared to this end of tun_net_xmit in tun.c:
/* Enqueue packet */
skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
/* Notify and wake up reader process */
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
POLLRDNORM | POLLRDBAND);
return NETDEV_TX_OK;
Richard.
^ permalink raw reply
* Business Proposal
From: Mrs. Helen Wong @ 2012-08-30 8:38 UTC (permalink / raw)
Greetings to you,
I am Mrs.Helen Wong, from Shanghai Banking Corporation Limited. (China)I
have a business proposal of USD$30,000,000 (Thirty Million United States
Dollars Only)for you to transact with me
Contact me via my email address: mrshelenwong001@yahoo.co.jp
Mrs. Helen Wong
^ permalink raw reply
* Re: Slow inbound traffic on macvtap interfaces
From: Michael S. Tsirkin @ 2012-08-30 8:44 UTC (permalink / raw)
To: Richard Davies; +Cc: Jason Wang, netdev, Chris Webb, qemu-devel, Arnd Bergmann
In-Reply-To: <20120830082057.GA18072@alpha.arachsys.com>
On Thu, Aug 30, 2012 at 09:20:57AM +0100, Richard Davies wrote:
> Chris Webb wrote:
> > I found that on my laptop, the single change of host kernel config
> >
> > -CONFIG_INTEL_IDLE=y
> > +# CONFIG_INTEL_IDLE is not set
> >
> > is sufficient to turn transfers into guests from slow to full wire speed
>
> I am not deep enough in this code to write a patch, but I wonder if
> macvtap_forward in macvtap.c is missing a call to kill_fasync, which I
> understand is used to signal to interested processes when data arrives?
>
No, only if TUN_FASYNC is set. qemu does not seem to set it.
> Here is the end of macvtap_forward:
>
> skb_queue_tail(&q->sk.sk_receive_queue, skb);
> wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
> return NET_RX_SUCCESS;
>
>
> Compared to this end of tun_net_xmit in tun.c:
>
> /* Enqueue packet */
> skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
>
> /* Notify and wake up reader process */
> if (tun->flags & TUN_FASYNC)
> kill_fasync(&tun->fasync, SIGIO, POLL_IN);
> wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
> POLLRDNORM | POLLRDBAND);
> return NETDEV_TX_OK;
>
>
> Richard.
^ permalink raw reply
* Re: [PATCH 03/19] netfilter: nf_conntrack_ipv6: improve fragmentation handling
From: Patrick McHardy @ 2012-08-30 6:54 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Jesper Dangaard Brouer, Netfilter Developers, netdev
In-Reply-To: <20120830030635.GA17583@1984>
On Thu, 30 Aug 2012, Pablo Neira Ayuso wrote:
> On Wed, Aug 29, 2012 at 02:27:00PM +0200, Patrick McHardy wrote:
>>>> + (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
>>>
>>> Eric Dumazet would probably nitpick and say, it can be reduced to:
>>> (IP6CB(skb)->frag_max_size > mtu)
>>> ;-)
>>
>> True. I'll fix that once Pablo has pulled in the patches.
>
> If you don't want to wait, you can send me a follow up patch, I'll
> apply it manually.
No hurry, I'll send it with a few other patches once its merged.
^ permalink raw reply
* Re: [PATCH net-next] r8169: add D-Link DGE-560T identifiers.
From: Ben Hutchings @ 2012-08-30 6:36 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, David S. Miller, Neyuki Inaya
In-Reply-To: <20120829194037.GB6389@electric-eye.fr.zoreil.com>
On Wed, 2012-08-29 at 21:40 +0200, Francois Romieu wrote:
> This one includes a 8168. Not to be confused with the sky2 driven
> one whose PCI vendor and device ID are the same.
>
> Reported-by: Neyuki Inaya <in@joblog.ru>
> Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
> ---
>
> The patch applies to Linus's branch as well.
>
> drivers/net/ethernet/realtek/r8169.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
> index b47d5b3..ab1cc56 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -288,6 +288,8 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
> { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
> + { PCI_VENDOR_ID_DLINK, 0x4300,
> + PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
This has no effect, as the preceding entry will match all the same
devices. I think you need to insert it before that.
Ben.
> { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
> { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
> { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
--
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
* [PATCH v6 1/1] ieee802154: MRF24J40 driver
From: Alan Ott @ 2012-08-30 4:16 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, Tony Cheneau
Cc: Alan Ott, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1335155673-30848-1-git-send-email-alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
Driver for the Microchip MRF24J40 802.15.4 WPAN module.
Signed-off-by: Alan Ott <alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
---
drivers/ieee802154/Kconfig | 11 +
drivers/ieee802154/Makefile | 1 +
drivers/ieee802154/mrf24j40.c | 767 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 779 insertions(+), 0 deletions(-)
create mode 100644 drivers/ieee802154/mrf24j40.c
diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig
index 1fc4eef..08ae465 100644
--- a/drivers/ieee802154/Kconfig
+++ b/drivers/ieee802154/Kconfig
@@ -34,3 +34,14 @@ config IEEE802154_AT86RF230
depends on IEEE802154_DRIVERS && MAC802154
tristate "AT86RF230/231 transceiver driver"
depends on SPI
+
+config IEEE802154_MRF24J40
+ tristate "Microchip MRF24J40 transceiver driver"
+ depends on IEEE802154_DRIVERS && MAC802154
+ depends on SPI
+ ---help---
+ Say Y here to enable the MRF24J20 SPI 802.15.4 wireless
+ controller.
+
+ This driver can also be built as a module. To do so, say M here.
+ the module will be called 'mrf24j40'.
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 4f4371d..abb0c08 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
+obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
diff --git a/drivers/ieee802154/mrf24j40.c b/drivers/ieee802154/mrf24j40.c
new file mode 100644
index 0000000..0e53d4f
--- /dev/null
+++ b/drivers/ieee802154/mrf24j40.c
@@ -0,0 +1,767 @@
+/*
+ * Driver for Microchip MRF24J40 802.15.4 Wireless-PAN Networking controller
+ *
+ * Copyright (C) 2012 Alan Ott <alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
+ * Signal 11 Software
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <net/wpan-phy.h>
+#include <net/mac802154.h>
+
+/* MRF24J40 Short Address Registers */
+#define REG_RXMCR 0x00 /* Receive MAC control */
+#define REG_PANIDL 0x01 /* PAN ID (low) */
+#define REG_PANIDH 0x02 /* PAN ID (high) */
+#define REG_SADRL 0x03 /* Short address (low) */
+#define REG_SADRH 0x04 /* Short address (high) */
+#define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */
+#define REG_TXMCR 0x11 /* Transmit MAC control */
+#define REG_PACON0 0x16 /* Power Amplifier Control */
+#define REG_PACON1 0x17 /* Power Amplifier Control */
+#define REG_PACON2 0x18 /* Power Amplifier Control */
+#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
+#define REG_TXSTAT 0x24 /* TX MAC Status Register */
+#define REG_SOFTRST 0x2A /* Soft Reset */
+#define REG_TXSTBL 0x2E /* TX Stabilization */
+#define REG_INTSTAT 0x31 /* Interrupt Status */
+#define REG_INTCON 0x32 /* Interrupt Control */
+#define REG_RFCTL 0x36 /* RF Control Mode Register */
+#define REG_BBREG1 0x39 /* Baseband Registers */
+#define REG_BBREG2 0x3A /* */
+#define REG_BBREG6 0x3E /* */
+#define REG_CCAEDTH 0x3F /* Energy Detection Threshold */
+
+/* MRF24J40 Long Address Registers */
+#define REG_RFCON0 0x200 /* RF Control Registers */
+#define REG_RFCON1 0x201
+#define REG_RFCON2 0x202
+#define REG_RFCON3 0x203
+#define REG_RFCON5 0x205
+#define REG_RFCON6 0x206
+#define REG_RFCON7 0x207
+#define REG_RFCON8 0x208
+#define REG_RSSI 0x210
+#define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */
+#define REG_SLPCON1 0x220
+#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
+#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
+#define REG_RX_FIFO 0x300 /* Receive FIFO */
+
+/* Device configuration: Only channels 11-26 on page 0 are supported. */
+#define MRF24J40_CHAN_MIN 11
+#define MRF24J40_CHAN_MAX 26
+#define CHANNEL_MASK (((u32)1 << (MRF24J40_CHAN_MAX + 1)) \
+ - ((u32)1 << MRF24J40_CHAN_MIN))
+
+#define TX_FIFO_SIZE 128 /* From datasheet */
+#define RX_FIFO_SIZE 144 /* From datasheet */
+#define SET_CHANNEL_DELAY_US 192 /* From datasheet */
+
+/* Device Private Data */
+struct mrf24j40 {
+ struct spi_device *spi;
+ struct ieee802154_dev *dev;
+
+ struct mutex buffer_mutex; /* only used to protect buf */
+ struct completion tx_complete;
+ struct work_struct irqwork;
+ u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
+};
+
+/* Read/Write SPI Commands for Short and Long Address registers. */
+#define MRF24J40_READSHORT(reg) ((reg) << 1)
+#define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1)
+#define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
+#define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
+
+/* Maximum speed to run the device at. TODO: Get the real max value from
+ * someone at Microchip since it isn't in the datasheet. */
+#define MAX_SPI_SPEED_HZ 1000000
+
+#define printdev(X) (&X->spi->dev)
+
+static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value)
+{
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = devrec->buf,
+ .rx_buf = devrec->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ mutex_lock(&devrec->buffer_mutex);
+ devrec->buf[0] = MRF24J40_WRITESHORT(reg);
+ devrec->buf[1] = value;
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret)
+ dev_err(printdev(devrec),
+ "SPI write Failed for short register 0x%hhx\n", reg);
+
+ mutex_unlock(&devrec->buffer_mutex);
+ return ret;
+}
+
+static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
+{
+ int ret = -1;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = devrec->buf,
+ .rx_buf = devrec->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ mutex_lock(&devrec->buffer_mutex);
+ devrec->buf[0] = MRF24J40_READSHORT(reg);
+ devrec->buf[1] = 0;
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret)
+ dev_err(printdev(devrec),
+ "SPI read Failed for short register 0x%hhx\n", reg);
+ else
+ *val = devrec->buf[1];
+
+ mutex_unlock(&devrec->buffer_mutex);
+ return ret;
+}
+
+static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
+{
+ int ret;
+ u16 cmd;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 3,
+ .tx_buf = devrec->buf,
+ .rx_buf = devrec->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ cmd = MRF24J40_READLONG(reg);
+ mutex_lock(&devrec->buffer_mutex);
+ devrec->buf[0] = cmd >> 8 & 0xff;
+ devrec->buf[1] = cmd & 0xff;
+ devrec->buf[2] = 0;
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret)
+ dev_err(printdev(devrec),
+ "SPI read Failed for long register 0x%hx\n", reg);
+ else
+ *value = devrec->buf[2];
+
+ mutex_unlock(&devrec->buffer_mutex);
+ return ret;
+}
+
+static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
+{
+ int ret;
+ u16 cmd;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 3,
+ .tx_buf = devrec->buf,
+ .rx_buf = devrec->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ cmd = MRF24J40_WRITELONG(reg);
+ mutex_lock(&devrec->buffer_mutex);
+ devrec->buf[0] = cmd >> 8 & 0xff;
+ devrec->buf[1] = cmd & 0xff;
+ devrec->buf[2] = val;
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret)
+ dev_err(printdev(devrec),
+ "SPI write Failed for long register 0x%hx\n", reg);
+
+ mutex_unlock(&devrec->buffer_mutex);
+ return ret;
+}
+
+/* This function relies on an undocumented write method. Once a write command
+ and address is set, as many bytes of data as desired can be clocked into
+ the device. The datasheet only shows setting one byte at a time. */
+static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
+ const u8 *data, size_t length)
+{
+ int ret;
+ u16 cmd;
+ u8 lengths[2];
+ struct spi_message msg;
+ struct spi_transfer addr_xfer = {
+ .len = 2,
+ .tx_buf = devrec->buf,
+ };
+ struct spi_transfer lengths_xfer = {
+ .len = 2,
+ .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */
+ };
+ struct spi_transfer data_xfer = {
+ .len = length,
+ .tx_buf = data,
+ };
+
+ /* Range check the length. 2 bytes are used for the length fields.*/
+ if (length > TX_FIFO_SIZE-2) {
+ dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n");
+ length = TX_FIFO_SIZE-2;
+ }
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&addr_xfer, &msg);
+ spi_message_add_tail(&lengths_xfer, &msg);
+ spi_message_add_tail(&data_xfer, &msg);
+
+ cmd = MRF24J40_WRITELONG(reg);
+ mutex_lock(&devrec->buffer_mutex);
+ devrec->buf[0] = cmd >> 8 & 0xff;
+ devrec->buf[1] = cmd & 0xff;
+ lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
+ lengths[1] = length; /* Total length */
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret)
+ dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
+
+ mutex_unlock(&devrec->buffer_mutex);
+ return ret;
+}
+
+static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
+ u8 *data, u8 *len, u8 *lqi)
+{
+ u8 rx_len;
+ u8 addr[2];
+ u8 lqi_rssi[2];
+ u16 cmd;
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer addr_xfer = {
+ .len = 2,
+ .tx_buf = &addr,
+ };
+ struct spi_transfer data_xfer = {
+ .len = 0x0, /* set below */
+ .rx_buf = data,
+ };
+ struct spi_transfer status_xfer = {
+ .len = 2,
+ .rx_buf = &lqi_rssi,
+ };
+
+ /* Get the length of the data in the RX FIFO. The length in this
+ * register exclues the 1-byte length field at the beginning. */
+ ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len);
+ if (ret)
+ goto out;
+
+ /* Range check the RX FIFO length, accounting for the one-byte
+ * length field at the begining. */
+ if (rx_len > RX_FIFO_SIZE-1) {
+ dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n");
+ rx_len = RX_FIFO_SIZE-1;
+ }
+
+ if (rx_len > *len) {
+ /* Passed in buffer wasn't big enough. Should never happen. */
+ dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n");
+ rx_len = *len;
+ }
+
+ /* Set up the commands to read the data. */
+ cmd = MRF24J40_READLONG(REG_RX_FIFO+1);
+ addr[0] = cmd >> 8 & 0xff;
+ addr[1] = cmd & 0xff;
+ data_xfer.len = rx_len;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&addr_xfer, &msg);
+ spi_message_add_tail(&data_xfer, &msg);
+ spi_message_add_tail(&status_xfer, &msg);
+
+ ret = spi_sync(devrec->spi, &msg);
+ if (ret) {
+ dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n");
+ goto out;
+ }
+
+ *lqi = lqi_rssi[0];
+ *len = rx_len;
+
+#ifdef DEBUG
+ print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
+ DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
+ printk(KERN_DEBUG "mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
+ lqi_rssi[0], lqi_rssi[1]);
+#endif
+
+out:
+ return ret;
+}
+
+static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+{
+ struct mrf24j40 *devrec = dev->priv;
+ u8 val;
+ int ret = 0;
+
+ dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
+
+ ret = write_tx_buf(devrec, 0x000, skb->data, skb->len);
+ if (ret)
+ goto err;
+
+ /* Set TXNTRIG bit of TXNCON to send packet */
+ ret = read_short_reg(devrec, REG_TXNCON, &val);
+ if (ret)
+ goto err;
+ val |= 0x1;
+ val &= ~0x4;
+ write_short_reg(devrec, REG_TXNCON, val);
+
+ INIT_COMPLETION(devrec->tx_complete);
+
+ /* Wait for the device to send the TX complete interrupt. */
+ ret = wait_for_completion_interruptible_timeout(
+ &devrec->tx_complete,
+ 5 * HZ);
+ if (ret == -ERESTARTSYS)
+ goto err;
+ if (ret == 0) {
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ /* Check for send error from the device. */
+ ret = read_short_reg(devrec, REG_TXSTAT, &val);
+ if (ret)
+ goto err;
+ if (val & 0x1) {
+ dev_err(printdev(devrec), "Error Sending. Retry count exceeded\n");
+ ret = -ECOMM; /* TODO: Better error code ? */
+ } else
+ dev_dbg(printdev(devrec), "Packet Sent\n");
+
+err:
+
+ return ret;
+}
+
+static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
+{
+ /* TODO: */
+ printk(KERN_WARNING "mrf24j40: ed not implemented\n");
+ *level = 0;
+ return 0;
+}
+
+static int mrf24j40_start(struct ieee802154_dev *dev)
+{
+ struct mrf24j40 *devrec = dev->priv;
+ u8 val;
+ int ret;
+
+ dev_dbg(printdev(devrec), "start\n");
+
+ ret = read_short_reg(devrec, REG_INTCON, &val);
+ if (ret)
+ return ret;
+ val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */
+ write_short_reg(devrec, REG_INTCON, val);
+
+ return 0;
+}
+
+static void mrf24j40_stop(struct ieee802154_dev *dev)
+{
+ struct mrf24j40 *devrec = dev->priv;
+ u8 val;
+ int ret;
+ dev_dbg(printdev(devrec), "stop\n");
+
+ ret = read_short_reg(devrec, REG_INTCON, &val);
+ if (ret)
+ return;
+ val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
+ write_short_reg(devrec, REG_INTCON, val);
+
+ return;
+}
+
+static int mrf24j40_set_channel(struct ieee802154_dev *dev,
+ int page, int channel)
+{
+ struct mrf24j40 *devrec = dev->priv;
+ u8 val;
+ int ret;
+
+ dev_dbg(printdev(devrec), "Set Channel %d\n", channel);
+
+ WARN_ON(page != 0);
+ WARN_ON(channel < MRF24J40_CHAN_MIN);
+ WARN_ON(channel > MRF24J40_CHAN_MAX);
+
+ /* Set Channel TODO */
+ val = (channel-11) << 4 | 0x03;
+ write_long_reg(devrec, REG_RFCON0, val);
+
+ /* RF Reset */
+ ret = read_short_reg(devrec, REG_RFCTL, &val);
+ if (ret)
+ return ret;
+ val |= 0x04;
+ write_short_reg(devrec, REG_RFCTL, val);
+ val &= ~0x04;
+ write_short_reg(devrec, REG_RFCTL, val);
+
+ udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
+
+ return 0;
+}
+
+static int mrf24j40_filter(struct ieee802154_dev *dev,
+ struct ieee802154_hw_addr_filt *filt,
+ unsigned long changed)
+{
+ struct mrf24j40 *devrec = dev->priv;
+
+ dev_dbg(printdev(devrec), "filter\n");
+
+ if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
+ /* Short Addr */
+ u8 addrh, addrl;
+ addrh = filt->short_addr >> 8 & 0xff;
+ addrl = filt->short_addr & 0xff;
+
+ write_short_reg(devrec, REG_SADRH, addrh);
+ write_short_reg(devrec, REG_SADRL, addrl);
+ dev_dbg(printdev(devrec),
+ "Set short addr to %04hx\n", filt->short_addr);
+ }
+
+ if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
+ /* Device Address */
+ int i;
+ for (i = 0; i < 8; i++)
+ write_short_reg(devrec, REG_EADR0+i,
+ filt->ieee_addr[i]);
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "Set long addr to: ");
+ for (i = 0; i < 8; i++)
+ printk("%02hhx ", filt->ieee_addr[i]);
+ printk(KERN_DEBUG "\n");
+#endif
+ }
+
+ if (changed & IEEE802515_AFILT_PANID_CHANGED) {
+ /* PAN ID */
+ u8 panidl, panidh;
+ panidh = filt->pan_id >> 8 & 0xff;
+ panidl = filt->pan_id & 0xff;
+ write_short_reg(devrec, REG_PANIDH, panidh);
+ write_short_reg(devrec, REG_PANIDL, panidl);
+
+ dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
+ }
+
+ if (changed & IEEE802515_AFILT_PANC_CHANGED) {
+ /* Pan Coordinator */
+ u8 val;
+ int ret;
+
+ ret = read_short_reg(devrec, REG_RXMCR, &val);
+ if (ret)
+ return ret;
+ if (filt->pan_coord)
+ val |= 0x8;
+ else
+ val &= ~0x8;
+ write_short_reg(devrec, REG_RXMCR, val);
+
+ /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
+ * REG_ORDER is maintained as default (no beacon/superframe).
+ */
+
+ dev_dbg(printdev(devrec), "Set Pan Coord to %s\n",
+ filt->pan_coord ? "on" : "off");
+ }
+
+ return 0;
+}
+
+static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
+{
+ u8 len = RX_FIFO_SIZE;
+ u8 lqi = 0;
+ u8 val;
+ int ret = 0;
+ struct sk_buff *skb;
+
+ /* Turn off reception of packets off the air. This prevents the
+ * device from overwriting the buffer while we're reading it. */
+ ret = read_short_reg(devrec, REG_BBREG1, &val);
+ if (ret)
+ goto out;
+ val |= 4; /* SET RXDECINV */
+ write_short_reg(devrec, REG_BBREG1, val);
+
+ skb = alloc_skb(len, GFP_KERNEL);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi);
+ if (ret < 0) {
+ dev_err(printdev(devrec), "Failure reading RX FIFO\n");
+ kfree_skb(skb);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Cut off the checksum */
+ skb_trim(skb, len-2);
+
+ /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
+ * also from a workqueue). I think irqsafe is not necessary here.
+ * Can someone confirm? */
+ ieee802154_rx_irqsafe(devrec->dev, skb, lqi);
+
+ dev_dbg(printdev(devrec), "RX Handled\n");
+
+out:
+ /* Turn back on reception of packets off the air. */
+ ret = read_short_reg(devrec, REG_BBREG1, &val);
+ if (ret)
+ return ret;
+ val &= ~0x4; /* Clear RXDECINV */
+ write_short_reg(devrec, REG_BBREG1, val);
+
+ return ret;
+}
+
+static struct ieee802154_ops mrf24j40_ops = {
+ .owner = THIS_MODULE,
+ .xmit = mrf24j40_tx,
+ .ed = mrf24j40_ed,
+ .start = mrf24j40_start,
+ .stop = mrf24j40_stop,
+ .set_channel = mrf24j40_set_channel,
+ .set_hw_addr_filt = mrf24j40_filter,
+};
+
+static irqreturn_t mrf24j40_isr(int irq, void *data)
+{
+ struct mrf24j40 *devrec = data;
+
+ disable_irq_nosync(irq);
+
+ schedule_work(&devrec->irqwork);
+
+ return IRQ_HANDLED;
+}
+
+static void mrf24j40_isrwork(struct work_struct *work)
+{
+ struct mrf24j40 *devrec = container_of(work, struct mrf24j40, irqwork);
+ u8 intstat;
+ int ret;
+
+ /* Read the interrupt status */
+ ret = read_short_reg(devrec, REG_INTSTAT, &intstat);
+ if (ret)
+ goto out;
+
+ /* Check for TX complete */
+ if (intstat & 0x1)
+ complete(&devrec->tx_complete);
+
+ /* Check for Rx */
+ if (intstat & 0x8)
+ mrf24j40_handle_rx(devrec);
+
+out:
+ enable_irq(devrec->spi->irq);
+}
+
+static int __devinit mrf24j40_probe(struct spi_device *spi)
+{
+ int ret = -ENOMEM;
+ u8 val;
+ struct mrf24j40 *devrec;
+
+ printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
+
+ devrec = kzalloc(sizeof(struct mrf24j40), GFP_KERNEL);
+ if (!devrec)
+ goto err_devrec;
+ devrec->buf = kzalloc(3, GFP_KERNEL);
+ if (!devrec->buf)
+ goto err_buf;
+
+ spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
+ if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
+ spi->max_speed_hz = MAX_SPI_SPEED_HZ;
+
+ mutex_init(&devrec->buffer_mutex);
+ init_completion(&devrec->tx_complete);
+ INIT_WORK(&devrec->irqwork, mrf24j40_isrwork);
+ devrec->spi = spi;
+ dev_set_drvdata(&spi->dev, devrec);
+
+ /* Register with the 802154 subsystem */
+
+ devrec->dev = ieee802154_alloc_device(0, &mrf24j40_ops);
+ if (!devrec->dev)
+ goto err_alloc_dev;
+
+ devrec->dev->priv = devrec;
+ devrec->dev->parent = &devrec->spi->dev;
+ devrec->dev->phy->channels_supported[0] = CHANNEL_MASK;
+ devrec->dev->flags = IEEE802154_HW_OMIT_CKSUM|IEEE802154_HW_AACK;
+
+ dev_dbg(printdev(devrec), "registered mrf24j40\n");
+ ret = ieee802154_register_device(devrec->dev);
+ if (ret)
+ goto err_register_device;
+
+ /* Initialize the device.
+ From datasheet section 3.2: Initialization. */
+ write_short_reg(devrec, REG_SOFTRST, 0x07);
+ write_short_reg(devrec, REG_PACON2, 0x98);
+ write_short_reg(devrec, REG_TXSTBL, 0x95);
+ write_long_reg(devrec, REG_RFCON0, 0x03);
+ write_long_reg(devrec, REG_RFCON1, 0x01);
+ write_long_reg(devrec, REG_RFCON2, 0x80);
+ write_long_reg(devrec, REG_RFCON6, 0x90);
+ write_long_reg(devrec, REG_RFCON7, 0x80);
+ write_long_reg(devrec, REG_RFCON8, 0x10);
+ write_long_reg(devrec, REG_SLPCON1, 0x21);
+ write_short_reg(devrec, REG_BBREG2, 0x80);
+ write_short_reg(devrec, REG_CCAEDTH, 0x60);
+ write_short_reg(devrec, REG_BBREG6, 0x40);
+ write_short_reg(devrec, REG_RFCTL, 0x04);
+ write_short_reg(devrec, REG_RFCTL, 0x0);
+ udelay(192);
+
+ /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
+ ret = read_short_reg(devrec, REG_RXMCR, &val);
+ if (ret)
+ goto err_read_reg;
+ val &= ~0x3; /* Clear RX mode (normal) */
+ write_short_reg(devrec, REG_RXMCR, val);
+
+ ret = request_irq(spi->irq,
+ mrf24j40_isr,
+ IRQF_TRIGGER_FALLING,
+ dev_name(&spi->dev),
+ devrec);
+
+ if (ret) {
+ dev_err(printdev(devrec), "Unable to get IRQ");
+ goto err_irq;
+ }
+
+ return 0;
+
+err_irq:
+err_read_reg:
+ ieee802154_unregister_device(devrec->dev);
+err_register_device:
+ ieee802154_free_device(devrec->dev);
+err_alloc_dev:
+ kfree(devrec->buf);
+err_buf:
+ kfree(devrec);
+err_devrec:
+ return ret;
+}
+
+static int __devexit mrf24j40_remove(struct spi_device *spi)
+{
+ struct mrf24j40 *devrec = dev_get_drvdata(&spi->dev);
+
+ dev_dbg(printdev(devrec), "remove\n");
+
+ free_irq(spi->irq, devrec);
+ flush_work_sync(&devrec->irqwork); /* TODO: Is this the right call? */
+ ieee802154_unregister_device(devrec->dev);
+ ieee802154_free_device(devrec->dev);
+ /* TODO: Will ieee802154_free_device() wait until ->xmit() is
+ * complete? */
+
+ /* Clean up the SPI stuff. */
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(devrec->buf);
+ kfree(devrec);
+ return 0;
+}
+
+static const struct spi_device_id mrf24j40_ids[] = {
+ { "mrf24j40", 0 },
+ { "mrf24j40ma", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
+
+static struct spi_driver mrf24j40_driver = {
+ .driver = {
+ .name = "mrf24j40",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .id_table = mrf24j40_ids,
+ .probe = mrf24j40_probe,
+ .remove = __devexit_p(mrf24j40_remove),
+};
+
+static int __init mrf24j40_init(void)
+{
+ return spi_register_driver(&mrf24j40_driver);
+}
+
+static void __exit mrf24j40_exit(void)
+{
+ spi_unregister_driver(&mrf24j40_driver);
+}
+
+module_init(mrf24j40_init);
+module_exit(mrf24j40_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alan Ott");
+MODULE_DESCRIPTION("MRF24J40 SPI 802.15.4 Controller Driver");
--
1.7.0.4
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply related
* [PATCH v6 0/1] Driver for Microchip MRF24J40
From: Alan Ott @ 2012-08-30 4:16 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, Tony Cheneau
Cc: linux-zigbee-devel, linux-kernel, netdev, Alan Ott
In-Reply-To: <1335155673-30848-1-git-send-email-alan@signal11.us>
This is a driver for the Microchip MRF24J40 802.15.4 transceiver.
Versions 1-5 and discussion can be found on the archives of the linux-zigbee
mailing list:
http://www.mail-archive.com/linux-zigbee-devel@lists.sourceforge.net/msg01014.html
Alan Ott (1):
ieee802154: MRF24J40 driver
drivers/ieee802154/Kconfig | 11 +
drivers/ieee802154/Makefile | 1 +
drivers/ieee802154/mrf24j40.c | 767 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 779 insertions(+), 0 deletions(-)
create mode 100644 drivers/ieee802154/mrf24j40.c
^ permalink raw reply
* Re: [PATCH 03/19] netfilter: nf_conntrack_ipv6: improve fragmentation handling
From: Pablo Neira Ayuso @ 2012-08-30 3:06 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jesper Dangaard Brouer, Netfilter Developers, netdev
In-Reply-To: <Pine.GSO.4.63.1208291424550.26100@stinky-local.trash.net>
On Wed, Aug 29, 2012 at 02:27:00PM +0200, Patrick McHardy wrote:
> On Wed, 29 Aug 2012, Jesper Dangaard Brouer wrote:
>
> >
> >Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> >
> >And some nitpicks below...
> >
> >>diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> >>index 5b2d63e..a4f6263 100644
> >>--- a/net/ipv6/ip6_output.c
> >>+++ b/net/ipv6/ip6_output.c
> >>@@ -493,7 +493,8 @@ int ip6_forward(struct sk_buff *skb)
> >> if (mtu < IPV6_MIN_MTU)
> >> mtu = IPV6_MIN_MTU;
> >>
> >>- if (skb->len > mtu && !skb_is_gso(skb)) {
> >>+ if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) ||
> >
> >You use (!skb->local_df) to invalidate the use of skb->len,
> >instead of (!IP6CB(skb)->frag_max_size), (which is okay, because
> >you set local_df later). Is there are reason this check is
> >better?
>
> Just that it's consistent with ip6_output and the regular local_df
> handling. It saves one extra condition in ip6_output.
>
> >>+ (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
> >
> >Eric Dumazet would probably nitpick and say, it can be reduced to:
> >(IP6CB(skb)->frag_max_size > mtu)
> >;-)
>
> True. I'll fix that once Pablo has pulled in the patches.
If you don't want to wait, you can send me a follow up patch, I'll
apply it manually.
^ permalink raw reply
* Re: BUG: soft lockup - CPU#6 stuck for 22s! [httpd2-event:15597]
From: Cristian Rodríguez @ 2012-08-30 3:05 UTC (permalink / raw)
To: Neal Cardwell; +Cc: Netdev, Yuchung Cheng, Eric Dumazet
In-Reply-To: <CADVnQy=bdHm2jcuReZaxr-qRMRWLDLnVP-jkzBTE-HPZ9FROmw@mail.gmail.com>
El mié 29 ago 2012 21:37:46 CLT, Neal Cardwell escribió:
Hi neal, thanks for taking a look at this..
> 1) Are you still seeing this problem in your workload? If so, would
> you have time to try another small patch to add instrumentation to
> track down the cause?
After Eric's patch I no longer see this backtrace or hang, however the
machine does
hang apparently for another reason that I have been unable to capture
no clue at all in the logs and the KVM-over-ip video does not respond
after hang, needing a reset,
that's strange though, as it is usually able to display kernel messages
after a crash.
> 2) Do you happen to run with the tcp_mtu_probing sysctl enabled?
No, sysctl returns : net.ipv4.tcp_mtu_probing = 0
^ permalink raw reply
* [PATCH v2 2/2] 6lowpan: handle NETDEV_UNREGISTER event
From: Alan Ott @ 2012-08-30 2:39 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, David S. Miller,
Tony Cheneau
Cc: Alan Ott, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1346294341-26808-1-git-send-email-alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
Before, it was impossible to remove a wpan device which had lowpan
attached to it.
Signed-off-by: Alan Ott <alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
---
net/ieee802154/6lowpan.c | 44 +++++++++++++++++++++++++++++++++++++-------
1 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index ce33b02..fb41e08 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1063,12 +1063,6 @@ out:
return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK);
}
-static void lowpan_dev_free(struct net_device *dev)
-{
- dev_put(lowpan_dev_info(dev)->real_dev);
- free_netdev(dev);
-}
-
static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
{
struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
@@ -1118,7 +1112,7 @@ static void lowpan_setup(struct net_device *dev)
dev->netdev_ops = &lowpan_netdev_ops;
dev->header_ops = &lowpan_header_ops;
dev->ml_priv = &lowpan_mlme;
- dev->destructor = lowpan_dev_free;
+ dev->destructor = free_netdev;
}
static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1244,6 +1238,34 @@ static inline void __init lowpan_netlink_fini(void)
rtnl_link_unregister(&lowpan_link_ops);
}
+static int lowpan_device_event(struct notifier_block *unused,
+ unsigned long event,
+ void *ptr)
+{
+ struct net_device *dev = ptr;
+ LIST_HEAD(del_list);
+ struct lowpan_dev_record *entry, *tmp;
+
+ if (dev->type != ARPHRD_IEEE802154)
+ goto out;
+
+ if (event == NETDEV_UNREGISTER) {
+ list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
+ if (lowpan_dev_info(entry->ldev)->real_dev == dev)
+ lowpan_dellink(entry->ldev, &del_list);
+ }
+
+ unregister_netdevice_many(&del_list);
+ };
+
+out:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block lowpan_dev_notifier = {
+ .notifier_call = lowpan_device_event,
+};
+
static struct packet_type lowpan_packet_type = {
.type = __constant_htons(ETH_P_IEEE802154),
.func = lowpan_rcv,
@@ -1258,6 +1280,12 @@ static int __init lowpan_init_module(void)
goto out;
dev_add_pack(&lowpan_packet_type);
+
+ err = register_netdevice_notifier(&lowpan_dev_notifier);
+ if (err < 0) {
+ dev_remove_pack(&lowpan_packet_type);
+ lowpan_netlink_fini();
+ }
out:
return err;
}
@@ -1270,6 +1298,8 @@ static void __exit lowpan_cleanup_module(void)
dev_remove_pack(&lowpan_packet_type);
+ unregister_netdevice_notifier(&lowpan_dev_notifier);
+
/* Now 6lowpan packet_type is removed, so no new fragments are
* expected on RX, therefore that's the time to clean incomplete
* fragments.
--
1.7.0.4
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply related
* [PATCH v2 1/2] 6lowpan: Make a copy of skb's delivered to 6lowpan
From: Alan Ott @ 2012-08-30 2:39 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, David S. Miller,
Tony Cheneau
Cc: Alan Ott, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1346294341-26808-1-git-send-email-alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
Since lowpan_process_data() modifies the skb (by calling skb_pull()), we
need our own copy so that it doesn't affect the data received by other
protcols (in this case, af_ieee802154).
Signed-off-by: Alan Ott <alan-yzvJWuRpmD1zbRFIqnYvSA@public.gmane.org>
---
net/ieee802154/6lowpan.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 6a09522..ce33b02 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1133,6 +1133,8 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
+ struct sk_buff *local_skb;
+
if (!netif_running(dev))
goto drop;
@@ -1144,7 +1146,12 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
- lowpan_process_data(skb);
+ local_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!local_skb)
+ goto drop;
+ lowpan_process_data(local_skb);
+
+ kfree_skb(skb);
break;
default:
break;
--
1.7.0.4
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply related
* [PATCH v2 0/2] 6lowpan fixes
From: Alan Ott @ 2012-08-30 2:38 UTC (permalink / raw)
To: Alexander Smirnov, Dmitry Eremin-Solenikov, David S. Miller,
Tony Cheneau
Cc: linux-zigbee-devel, netdev, linux-kernel, Alan Ott
Fixes for 6lowpan.
I'm sorry about the other two emails that just went out with the same
subject. One day I'm going to start getting these right on the first try.
Alan Ott (2):
6lowpan: Make a copy of skb's delivered to 6lowpan
6lowpan: handle NETDEV_UNREGISTER event
net/ieee802154/6lowpan.c | 53 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 45 insertions(+), 8 deletions(-)
^ 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