Software implementation of IEEE 802.15.4
Subsystems (3)
cover Software implementation of IEEE 802.15.4
Hi,
In this (small) patchset we'd like to present the grounds of our software IEEE 802.15.4 MAC implementation. Especially this patchset contains only packet dissection and data path (in generic parts) and virtual loopback driver (as an example user).
Please review.
Dmitry Eremin-Solenikov (2):
mac802154: add a software MAC 802.15.4 implementation
ieee802154: add virtual loopback driver
MAINTAINERS | 1 + drivers/ieee802154/Kconfig | 13 + drivers/ieee802154/Makefile | 1 + drivers/ieee802154/fakelb.c | 255 ++++++++++++ include/linux/mac802154.h | 35 ++ include/net/mac802154.h | 106 +++++ net/Kconfig | 1 + net/Makefile | 1 + net/mac802154/Kconfig | 17 + net/mac802154/Makefile | 4 + net/mac802154/dev.c | 924 +++++++++++++++++++++++++++++++++++++++++++ net/mac802154/mac802154.h | 85 ++++ net/mac802154/mac_cmd.c | 99 +++++ net/mac802154/mdev.c | 295 ++++++++++++++ net/mac802154/mib.h | 32 ++ net/mac802154/rx.c | 98 +++++ 16 files changed, 1967 insertions(+), 0 deletions(-) create mode 100644 drivers/ieee802154/fakelb.c create mode 100644 include/linux/mac802154.h create mode 100644 include/net/mac802154.h create mode 100644 net/mac802154/Kconfig create mode 100644 net/mac802154/Makefile create mode 100644 net/mac802154/dev.c create mode 100644 net/mac802154/mac802154.h create mode 100644 net/mac802154/mac_cmd.c create mode 100644 net/mac802154/mdev.c create mode 100644 net/mac802154/mib.h create mode 100644 net/mac802154/rx.c
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july
A message that is not in the archive (sent off-list or not yet received): 1249913800-10176-1-git-send-email-dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
PATCH 1/2 mac802154: add a software MAC 802.15.4 implementation
Some of available devices are just dump radios implementing IEEE 802.15.4 PHY layer. This commit adds a common library that acts like an intermediate layer between our socket family and drivers for those dumb devices.
Currently this is data-only part (no commands, no beacons). Control interfaces will follow up shortly.
Note this implementaion is neither certified, nor feature complete!
--- MAINTAINERS | 1 + include/linux/mac802154.h | 35 ++ include/net/mac802154.h | 106 ++++++ net/Kconfig | 1 + net/Makefile | 1 + net/mac802154/Kconfig | 17 + net/mac802154/Makefile | 4 + net/mac802154/dev.c | 924 +++++++++++++++++++++++++++++++++++++++++++++ net/mac802154/mac802154.h | 85 +++++ net/mac802154/mac_cmd.c | 99 +++++ net/mac802154/mdev.c | 295 +++++++++++++++ net/mac802154/mib.h | 32 ++ net/mac802154/rx.c | 98 +++++ 13 files changed, 1698 insertions(+), 0 deletions(-) create mode 100644 include/linux/mac802154.h create mode 100644 include/net/mac802154.h create mode 100644 net/mac802154/Kconfig create mode 100644 net/mac802154/Makefile create mode 100644 net/mac802154/dev.c create mode 100644 net/mac802154/mac802154.h create mode 100644 net/mac802154/mac_cmd.c create mode 100644 net/mac802154/mdev.c create mode 100644 net/mac802154/mib.h create mode 100644 net/mac802154/rx.c
MAINTAINERS +1 -0
@@ -2529,6 +2529,7 @@ W: http://apps.sourceforge.net/trac/linux-zigbee T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git S: Maintained F: net/ieee802154/ +F: net/mac802154/ F: drivers/ieee802154/ INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
include/linux/mac802154.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Copyright (C) 2007, 2008, 2009 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +*/ + +#ifndef LINUX_MAC802154_H +#define LINUX_MAC802154_H + +enum { +IFLA_WPAN_UNSPEC , +IFLA_WPAN_CHANNEL , +IFLA_WPAN_PAN_ID , +IFLA_WPAN_SHORT_ADDR , +IFLA_WPAN_COORD_SHORT_ADDR , +IFLA_WPAN_COORD_EXT_ADDR , + __IFLA_WPAN_MAX, +}; + +#define IFLA_WPAN_MAX (__IFLA_WPAN_MAX - 1) + +#endif +
include/net/mac802154.h new file +106 -0
106 lines not on this page · raw message
net/Kconfig +1 -0
@@ -180,6 +180,7 @@ source "net/econet/Kconfig" source "net/wanrouter/Kconfig" source "net/phonet/Kconfig" source "net/ieee802154/Kconfig" +source "net/mac802154/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig"
net/Makefile +1 -0
@@ -61,6 +61,7 @@ ifneq ($(CONFIG_DCB),) obj-y += dcb/ endif obj-y += ieee802154/ +obj-y += mac802154/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o
net/mac802154/Kconfig new file +17 -0
@@ -0,0 +1,17 @@ +config MAC802154 + tristate "Generic IEEE 802.15.4 Soft Networking Stack (mac802154)" + depends on IEEE802154 && EXPERIMENTAL + select CRC_CCITT + ---help--- + This option enables the hardware independent IEEE 802.15.4 + networking stack for SoftMAC devices (the ones implementing + only PHY level of IEEE 802.15.4 standard). + + Note: this implementation is neither certified, nor feature + complete! We do not garantee that it is compatible w/ other + implementations, etc. + + If you plan to use HardMAC IEEE 802.15.4 devices, you can + say N here. Alternatievly you can say M to compile it as + module. +
net/mac802154/Makefile new file +4 -0
@@ -0,0 +1,4 @@ +obj-$(CONFIG_MAC802154) += mac802154.o +mac802154-objs := rx.o mdev.o dev.o mac_cmd.o + +EXTRA_CFLAGS += -Wall -DDEBUG
net/mac802154/dev.c new file +924 -0
924 lines not on this page · raw message
net/mac802154/mac802154.h new file +85 -0
85 lines not on this page · raw message
net/mac802154/mac_cmd.c new file +99 -0
99 lines not on this page · raw message
net/mac802154/mdev.c new file +295 -0
295 lines not on this page · raw message
net/mac802154/mib.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Copyright 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +*/ + +#ifndef MIB802154_H +#define MIB802154_H + +/* FIXME: should be dropped in favour of generic MIB API */ +u8 ieee802154_dev_get_dsn (struct net_device *dev); +u8 ieee802154_dev_get_bsn (struct net_device *dev); +u16 ieee802154_dev_get_pan_id (struct net_device *dev); +u16 ieee802154_dev_get_short_addr (struct net_device *dev); +void ieee802154_dev_set_pan_id (struct net_device *dev,u16 val); +void ieee802154_dev_set_short_addr (struct net_device *dev,u16 val); +void ieee802154_dev_set_channel (struct net_device *dev,u8 chan); + + +#endif
net/mac802154/rx.c new file +98 -0
98 lines not on this page · raw message
Signature · 6 lines
1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 1249913800-10176-2-git-send-email-dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
PATCH 2/2 ieee802154: add virtual loopback driver
fakelb is a virtual loopback driver implementing one or several interconnected radios. Packets from the radio are either sent back to the node (if no other fake radio are registered) or to all other fake radio.
--- drivers/ieee802154/Kconfig | 13 ++ drivers/ieee802154/Makefile | 1 + drivers/ieee802154/fakelb.c | 255 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 0 deletions(-) create mode 100644 drivers/ieee802154/fakelb.c
drivers/ieee802154/Kconfig +13 -0
@@ -20,3 +20,16 @@ config IEEE802154_FAKEHARD This driver can also be built as a module. To do so say M here. The module will be called 'fakehard'. + +if IEEE802154_DRIVERS && MAC802154 +config IEEE802154_FAKELB + tristate "Fake LR-WPAN driver with several interconnected devices" + ---help--- + Say Y here to enable the fake driver that can emulate a net + of several interconnected radio devices. + + This driver can also be built as a module. To do so say M here. + The module will be called 'fakelb'. + +endif +
drivers/ieee802154/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o +obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
drivers/ieee802154/fakelb.c new file +255 -0
255 lines not on this page · raw message
Signature · 8 lines
1.6.3.3 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july
A message that is not in the archive (sent off-list or not yet received): 1249913800-10176-3-git-send-email-dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH 2/2] ieee802154: add virtual loopback driver
drivers/ieee802154/Kconfig config IEEE802154_FAKEHARD · line 25
Quoted 2 lines · Dmitry Eremin-Solenikov
drivers/ieee802154/Kconfig +2
-0+if IEEE802154_DRIVERS && MAC802154 +config IEEE802154_FAKELB
depends on
drivers/ieee802154/Kconfig config IEEE802154_FAKEHARD · line 32
Quoted 7 lines
drivers/ieee802154/Kconfig +7
-0+ tristate "Fake LR-WPAN driver with several interconnected devices" + ---help--- + Say Y here to enable the fake driver that can emulate a net + of several interconnected radio devices. + + This driver can also be built as a module. To do so say M here. + The module will be called 'fakelb'.
whitespace damage
johannes
Re: [PATCH 2/2] ieee802154: add virtual loopback driver
In reply to a message not in the archiveQuoted 7 lines · Dmitry Eremin-Solenikov
fakelb is a virtual loopback driver implementing one or several interconnected radios.
drivers/ieee802154/fakelb.c new file +4
-0+ +static int radios =3 ; +module_param (radios, int,0444 ); +MODULE_PARM_DESC (radios,"Number of simulated radios" );
drivers/ieee802154/fakelb.c line 201
Quoted 10 lines
drivers/ieee802154/fakelb.c new file +8
-0+ + +for (i =0 ; i < radios; i++) { + err =ieee802154fake_add_priv (&pdev->dev, priv); +if (err <0 ) + goto err_slave; + } +
Hi Dimtry,
creating software networking devices like this is IMO not state-of-the-art for
kernel inclusion.
Please use the NETLINK interface for creating the virtual loopback drivers, like e.g. the virtual CAN driver (drivers/net/can/vcan.c) does.
Regards,
Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
In reply to a message not in the archiveQuoted 1 line · Dmitry Eremin-Solenikov
Some of available devices are just dump radios implementing IEEE 802.15.4
dump -> dumb
Quoted 1 line
Note this implementaion is neither certified, nor feature complete!
implementation
Quoted 5 lines
+ * @tx: Handler that 802.15.4 module calls for each transmitted frame.
+ * skb cntains the buffer starting from the IEEE 802.15.4 header. + * The low-level driver should send the frame based on available + * configuration. + * This function should return zero or negative errno.
That return value is strange.
net/Makefile ifneq ($(CONFIG_DCB),) · line 64
Quoted 6 lines
+++ b/net/Makefile
net/Makefile +1
-0@@ -61,6 +61,7 @@ ifneq ($(CONFIG_DCB),) obj-y += dcb/ endif obj-y += ieee802154/ +obj-y += mac802154/
I think you should use obj-$(CONFIG_MAC802154) as there's no need to recurse into the dir unless that's selected.
But does it make sense to actually have this little code as a separate dir/module?
net/mac802154/Kconfig line 12
Quoted 3 lines
net/mac802154/Kconfig new file +3
-0+ Note: this implementation is neither certified, nor feature + complete! We do not garantee that it is compatible w/ other + implementations, etc.
guarantee
But generally, you don't have to write that anyway due to the license.
net/mac802154/Kconfig line 16
Quoted 3 lines
net/mac802154/Kconfig new file +3
-0+ If you plan to use HardMAC IEEE 802.15.4 devices, you can + say N here. Alternatievly you can say M to compile it as + module.
white space gone wrong
net/mac802154/mac802154.h line 39
Quoted 10 lines
net/mac802154/mac802154.h new file +10
-0+struct net_device *netdev;/* mwpanX device */ +int open_count; +/* As in mac80211 slaves list is modified: +* 1) under the RTNL +* 2) protected by slaves_mtx; +* 3) in an RCU manner +* +* So atomic readers can use any of this protection methods +*/ +struct list_head slaves;
heh.
net/mac802154/mdev.c line 83
Quoted 2 lines
net/mac802154/mdev.c new file +2
-0+static int ieee802154_master_open (struct net_device *dev) +{
We've had no end to trouble with the master netdev, I suggest you look into the current mac80211 code and see if you can get rid of it.
net/mac802154/mdev.c line 208
Quoted 5 lines
net/mac802154/mdev.c new file +4
-0+struct ieee802154_dev *ieee802154_alloc_device (size_t priv_size, +struct ieee802154_ops *ops) +{ +if (!try_module_get (ops->owner)) {
That isn't necessary since the module is just calling your function. In fact, doing this removes the ability to rmmod any module using this which is bogus.
johannes
A message that is not in the archive (sent off-list or not yet received): 1249914466.32614.13.camel-YfaajirXv2244ywRPIzf9A@public.gmane.org
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 8 lines · Johannes Berg
Quoted 5 lines · Dmitry Eremin-Solenikov
+ * @tx: Handler that 802.15.4 module calls for each transmitted frame.
+ * skb cntains the buffer starting from the IEEE 802.15.4 header. + * The low-level driver should send the frame based on available + * configuration. + * This function should return zero or negative errno.That return value is strange.
The idea is that tx function can return info about errors during transmit (busy channel, no ACK, etc).
Quoted 10 lines
net/Makefile ifneq ($(CONFIG_DCB),) · line 64
Quoted 7 lines
+++ b/net/Makefile
net/Makefile +1
-0@@ -61,6 +61,7 @@ ifneq ($(CONFIG_DCB),) obj-y += dcb/ endif obj-y += ieee802154/ +obj-y += mac802154/I think you should use obj-$(CONFIG_MAC802154) as there's no need to recurse into the dir unless that's selected.
fixed.
Quoted 3 lines
But does it make sense to actually have this little code as a separate dir/module?
The submitted patch is only a part of written MAC code. And we still aren't feature complete. Is there any sence in keeping mac80211 separate? IMHO yes. Same goes for mac802154.
Quoted 4 lines
Quoted 4 lines
net/mac802154/mac802154.h new file +4
-0+struct net_device *netdev;/* mwpanX device */ +int open_count; +/* As in mac80211 slaves list is modified: +* 1) under the RTNL
Quoted 8 lines
net/mac802154/mac802154.h line 39
Quoted 6 lines
net/mac802154/mac802154.h new file +6
-0+* 2) protected by slaves_mtx; +* 3) in an RCU manner +* +* So atomic readers can use any of this protection methods +*/ +struct list_head slaves;heh.
? C&p from mac80211 mostly :)
Quoted 6 lines
net/mac802154/mdev.c line 83
Quoted 3 lines
net/mac802154/mdev.c new file +2
-0+static int ieee802154_master_open (struct net_device *dev) +{We've had no end to trouble with the master netdev, I suggest you look into the current mac80211 code and see if you can get rid of it.
What troubles w/ master netdev did you have had? I do still see the master devices in mac80211. IIUC, it's planned to replace (from management point of view) the mdev with wiphy instance, isn't it?
Quoted 9 lines
net/mac802154/mdev.c line 208
Quoted 5 lines
net/mac802154/mdev.c new file +4
-0+struct ieee802154_dev *ieee802154_alloc_device (size_t priv_size, +struct ieee802154_ops *ops) +{ +if (!try_module_get (ops->owner)) {That isn't necessary since the module is just calling your function. In fact, doing this removes the ability to rmmod any module using this which is bogus.
Hmm. I thought that one may be able to rmmod the module w/ ops while the device is still hanging in the system. On the other hand, ops are provided by the driver, so if one rmmods the driver and the device is still there, it's a bug...
Removing now.
Signature · 7 lines
With best wishes Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 4 lines · Dmitry Eremin-Solenikov
Quoted 1 line
That return value is strange.
The idea is that tx function can return info about errors during transmit (busy channel, no ACK, etc).
Well, TX functions don't usually wait for anything so busy channel or no ack wouldn't be possible to return there but more like a TX status, and I think people are more used to NETDEV_TX_OK etc. return values. But it's your choice to make, obviously. If you want to return specific information like that though I would recommend making an enum so you get at least some type checking (and things like 'return -1' are more obviously wrong).
Quoted 6 lines
Quoted 2 lines
We've had no end to trouble with the master netdev, I suggest you look into the current mac80211 code and see if you can get rid of it.
What troubles w/ master netdev did you have had? I do still see the master devices in mac80211. IIUC, it's planned to replace (from management point of view) the mdev with wiphy instance, isn't it?
Mostly the userspace API was a mess, and you can't actually _do_ anything with the master netdev. It also doesn't see all the frames, only outgoing. It's very strange.
Yes, you still see it in the current tree, but it's gone in our -next tree.
The biggest problem is that it really clutters up the userspace API since you can't do any netdev things with it, it's just a placeholder.
In addition to that, you can't put anything into skb->cb, then push the frame to the master netdev, and expect things in skb->cb to still be there when the frame arrives at the master netdev. Not sure you do that (I hope not because that would be very buggy), but eventually you'll probably find that you do want that, etc.
IMHO it's just better practise to not use it in situations like this where it can't be really used as a netdev.
Quoted 4 lines
Hmm. I thought that one may be able to rmmod the module w/ ops while the device is still hanging in the system. On the other hand, ops are provided by the driver, so if one rmmods the driver and the device is still there, it's a bug...
Exactly. You _want_ to be able to rmmod the module and have it unregister itself.
johannes
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 7 lines · Johannes Berg
Quoted 4 lines · Dmitry Eremin-Solenikov
Quoted 1 line
That return value is strange.
The idea is that tx function can return info about errors during transmit (busy channel, no ACK, etc).
Quoted 7 lines
Well, TX functions don't usually wait for anything so busy channel or no ack wouldn't be possible to return there but more like a TX status, and I think people are more used to
NETDEV_TX_OKetc. return values. But it's your choice to make, obviously. If you want to return specific information like that though I would recommend making an enum so you get at least some type checking (and things like 'return -1' are more obviously wrong).
Currently we do all the work from special worker threads, so it's possible for this callback to sleep. The error isn't yet propagated to upper layers (there is a huge TODO there), anyway.
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines
We've had no end to trouble with the master netdev, I suggest you look into the current mac80211 code and see if you can get rid of it.
What troubles w/ master netdev did you have had? I do still see the master devices in mac80211. IIUC, it's planned to replace (from management point of view) the mdev with wiphy instance, isn't it?
Mostly the userspace API was a mess, and you can't actually _do_ anything with the master netdev. It also doesn't see all the frames, only outgoing. It's very strange.
We were using master netdevices for several purposes:
1) ip link add link mwpanX type wpan, so that we have out-of-box support for radio additions. That's really nice thing to have.
2) for SOCK_RAW implementation that can be used to send raw packets over-the-air/receive raw packets. I think we can use af_packet for this, but I'm still not sure about packet injection.
3) On the RX, we did send a clone of skb to the mdev and clones to slave interfaces, thus overcoming your last argument.
Quoted 8 lines
The biggest problem is that it really clutters up the userspace API since you can't do any netdev things with it, it's just a placeholder.
In addition to that, you can't put anything into
skb->cb, then push the frame to the master netdev, and expect things inskb->cbto still be there when the frame arrives at the master netdev. Not sure you do that (I hope not because that would be very buggy), but eventually you'll probably find that you do want that, etc.
Hmm. It works for us. Could you please tell me more about the problems with skb->cb ?
Quoted 2 lines
IMHO it's just better practise to not use it in situations like this where it can't be really used as a netdev.
We did use it as a netdev, however we can probably live without it. I'll rethink this interface.
Signature · 2 lines
With best wishes Dmitry
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 8 lines · Dmitry Eremin-Solenikov
Quoted 5 lines
In addition to that, you can't put anything into
skb->cb, then push the frame to the master netdev, and expect things inskb->cbto still be there when the frame arrives at the master netdev. Not sure you do that (I hope not because that would be very buggy), but eventually you'll probably find that you do want that, etc.Hmm. It works for us. Could you please tell me more about the problems with
skb->cb?
Uh, well, you don't own the skb->cb between dev_queue_xmit() and ndo_start_xmit(). In fact, your phy_cb data will be overwritten by the qdisc.
So your code is completely and utterly broken just like mac80211 was for a long time.
Also, looking into this a bit more, I see no reason to allocate a work struct every time you get a frame -- better just queue them up and stick everything else into skb->cb. In fact, you don't need a master netdev here anyway, just move all code from ieee802154_master_hard_start_xmit() into ieee802154_net_xmit().
johannes
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 8 lines · Johannes Berg
Quoted 6 lines · Dmitry Eremin-Solenikov
Quoted 5 lines
In addition to that, you can't put anything into
skb->cb, then push the frame to the master netdev, and expect things inskb->cbto still be there when the frame arrives at the master netdev. Not sure you do that (I hope not because that would be very buggy), but eventually you'll probably find that you do want that, etc.
Quoted 6 lines
Quoted 2 lines
Hmm. It works for us. Could you please tell me more about the problems with
skb->cb?Uh, well, you don't own the
skb->cbbetweendev_queue_xmit()andndo_start_xmit(). In fact, yourphy_cbdata will be overwritten by the qdisc.
Hmmm. Really weird. Then, if we want to pass data from socket layer to MAC layer, we should place data in skb->data and not in skb->cb (like radiotap header)?
Quoted 6 lines
Also, looking into this a bit more, I see no reason to allocate a work struct every time you get a frame -- better just queue them up and stick everything else into
skb->cb. In fact, you don't need a master netdev here anyway, just move all code fromieee802154_master_hard_start_xmit()intoieee802154_net_xmit().
Nice idea. Thanks a lot!
Signature · 2 lines
With best wishes Dmitry
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
In reply to a message not in the archiveQuoted 8 lines · Dmitry Eremin-Solenikov
Some of available devices are just dump radios implementing IEEE 802.15.4 PHY layer. This commit adds a common library that acts like an intermediate layer between our socket family and drivers for those dumb devices.
Currently this is data-only part (no commands, no beacons). Control interfaces will follow up shortly.
Note this implementaion is neither certified, nor feature complete!
One question below, otherwise looks plausible. (I am not entirely sure which lists are which...)
Thanx, Paul
Quoted 632 lines
Signed-off-by Dmitry Eremin-Solenikov <[email protected]>Signed-off-by Sergey Lapin <[email protected]>--- MAINTAINERS | 1 + include/linux/mac802154.h | 35 ++ include/net/mac802154.h | 106 ++++++ net/Kconfig | 1 + net/Makefile | 1 + net/mac802154/Kconfig | 17 + net/mac802154/Makefile | 4 + net/mac802154/dev.c | 924 +++++++++++++++++++++++++++++++++++++++++++++ net/mac802154/mac802154.h | 85 +++++ net/mac802154/mac_cmd.c | 99 +++++ net/mac802154/mdev.c | 295 +++++++++++++++ net/mac802154/mib.h | 32 ++ net/mac802154/rx.c | 98 +++++ 13 files changed, 1698 insertions(+), 0 deletions(-) create mode 100644 include/linux/mac802154.h create mode 100644 include/net/mac802154.h create mode 100644 net/mac802154/Kconfig create mode 100644 net/mac802154/Makefile create mode 100644 net/mac802154/dev.c create mode 100644 net/mac802154/mac802154.h create mode 100644 net/mac802154/mac_cmd.c create mode 100644 net/mac802154/mdev.c create mode 100644 net/mac802154/mib.h create mode 100644 net/mac802154/rx.cMAINTAINERS +1
-0@@ -2529,6 +2529,7 @@ W: http://apps.sourceforge.net/trac/linux-zigbee T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git S: Maintained F: net/ieee802154/ +F: net/mac802154/ F: drivers/ieee802154/ INTEGRITY MEASUREMENT ARCHITECTURE (IMA)include/linux/mac802154.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Copyright (C) 2007, 2008, 2009 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +*/ + +#ifndef LINUX_MAC802154_H +#define LINUX_MAC802154_H + +enum { +IFLA_WPAN_UNSPEC , +IFLA_WPAN_CHANNEL , +IFLA_WPAN_PAN_ID , +IFLA_WPAN_SHORT_ADDR , +IFLA_WPAN_COORD_SHORT_ADDR , +IFLA_WPAN_COORD_EXT_ADDR , + __IFLA_WPAN_MAX, +}; + +#define IFLA_WPAN_MAX (__IFLA_WPAN_MAX - 1) + +#endif +include/net/mac802154.h new file +106
-0@@ -0,0 +1,106 @@ +/* +* IEEE802.15.4-2003 specification +* +* Copyright (C) 2007, 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Written by: +*/ +#ifndef NET_MAC802154_H +#define NET_MAC802154_H + +struct ieee802154_dev { +int extra_tx_headroom;/* headroom to reserve for tx skb */ +void *priv;/* driver-specific data */ +u32 channel_mask; +u8 current_channel; +u32 flags;/* Flags for device to set */ +struct device *parent; +}; + +/* Checksum is in hardware and is omitted from packet */ +/** +* enum ieee802154_hw_flags - hardware flags +* +* These flags are used to indicate hardware capabilities to +* the stack. Generally, flags here should have their meaning +* done in a way that the simplest hardware doesn't need setting +* any particular flags. There are some exceptions to this rule, +* however, so you are advised to review these flags carefully. +* +* @IEEE802154_HW_OMIT_CKSUM: +* Indicates that receiver omits FCS and transmitter will add +* FCS on it's own. +* +* @IEEE802154_HW_AACK: +* Indicates that receiver will autorespond with ACK frames. +*/ +enum ieee802154_hw_flags { +IEEE802154_HW_OMIT_CKSUM =1 <<0 , +IEEE802154_HW_AACK =1 <<1 , +}; + +struct sk_buff ; + +/** +* struct ieee802154_ops - callbacks from mac802154 to the driver +* +* This structure contains various callbacks that the driver may +* handle or, in some cases, must handle, for example to transmit +* a frame. +* +* @start: Handler that 802.15.4 module calls for device initialisation. +* This function is called before the first interface is attached. +* +* @stop: Handler that 802.15.4 module calls for device cleanup +* This function is called after the last interface is removed. +* +* @tx: Handler that 802.15.4 module calls for each transmitted frame. +* skb cntains the buffer starting from the IEEE 802.15.4 header. +* The low-level driver should send the frame based on available +* configuration. +* This function should return zero or negative errno. +* +* @ed: Handler that 802.15.4 module calls for Energy Detection. +* This function should place the value for detected energy +* (usually device-dependant) in the level pointer and return +* either zero or negative errno. +* +* @set_channel: Set radio for listening on specific channel. +* Set the device for listening on specified channel. +* Returns either zero, or negative errno. +*/ +struct ieee802154_ops { +struct module *owner; +int (*start)(struct ieee802154_dev *dev); +void (*stop)(struct ieee802154_dev *dev); +int (*xmit)(struct ieee802154_dev *dev, +struct sk_buff *skb); +int (*ed)(struct ieee802154_dev *dev,u8 *level); +int (*set_channel)(struct ieee802154_dev *dev, +int channel); +}; + +struct ieee802154_dev *ieee802154_alloc_device (size_t priv_size, +struct ieee802154_ops *ops); +int ieee802154_register_device (struct ieee802154_dev *dev); +void ieee802154_unregister_device (struct ieee802154_dev *dev); +void ieee802154_free_device (struct ieee802154_dev *dev); + +void ieee802154_rx (struct ieee802154_dev *dev,struct sk_buff *skb,u8 lqi); +void ieee802154_rx_irqsafe (struct ieee802154_dev *dev,struct sk_buff *skb, +u8 lqi); +#endif +net/Kconfig +1
-0@@ -180,6 +180,7 @@ source "net/econet/Kconfig" source "net/wanrouter/Kconfig" source "net/phonet/Kconfig" source "net/ieee802154/Kconfig" +source "net/mac802154/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig"net/Makefile +1
-0@@ -61,6 +61,7 @@ ifneq ($(CONFIG_DCB),) obj-y += dcb/ endif obj-y += ieee802154/ +obj-y += mac802154/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.onet/mac802154/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config MAC802154 + tristate "Generic IEEE 802.15.4 Soft Networking Stack (mac802154)" + depends on IEEE802154 && EXPERIMENTAL + select CRC_CCITT + ---help--- + This option enables the hardware independent IEEE 802.15.4 + networking stack for SoftMAC devices (the ones implementing + only PHY level of IEEE 802.15.4 standard). + + Note: this implementation is neither certified, nor feature + complete! We do not garantee that it is compatible w/ other + implementations, etc. + + If you plan to use HardMAC IEEE 802.15.4 devices, you can + say N here. Alternatievly you can say M to compile it as + module. +net/mac802154/Makefile new file +4
-0@@ -0,0 +1,4 @@ +obj-$(CONFIG_MAC802154) += mac802154.o +mac802154-objs := rx.o mdev.o dev.o mac_cmd.o + +EXTRA_CFLAGS += -Wall -DDEBUGnet/mac802154/dev.c new file +376
-0@@ -0,0 +1,924 @@ +/* +* Copyright 2007, 2008, 2009 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Written by: +* Sergey Lapin <[email protected]> +* Maxim Gorbachyov <[email protected]> +*/ + +#include <linux/net.h> +#include <linux/capability.h> +#include <linux/module.h> +#include <linux/if_arp.h> +#include <linux/rculist.h> +#include <linux/random.h> +#include <linux/crc-ccitt.h> +#include <linux/mac802154.h> +#include <net/rtnetlink.h> + +#include <net/af_ieee802154.h> +#include <net/mac802154.h> +#include <net/ieee802154_netdev.h> +#include <net/ieee802154.h> + +#include "mac802154.h" +#include "mib.h" + +static int ieee802154_net_xmit (struct sk_buff *skb,struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv; + priv =netdev_priv (dev); + +if (!(priv->hw->hw.flags &IEEE802154_HW_OMIT_CKSUM )) { +u16 crc =crc_ccitt (0 , skb->data, skb->len); +u8 *data =skb_put (skb,2 ); + data[0 ] = crc &0xff ; + data[1 ] = crc >>8 ; + } + +read_lock (&priv->mib_lock); +phy_cb (skb)->chan = priv->chan; +read_unlock (&priv->mib_lock); + + skb->iif = dev->ifindex; + skb->dev = priv->hw->netdev; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + dev->trans_start = jiffies; +dev_queue_xmit (skb); + +return 0 ; +} + +static int ieee802154_slave_open (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +int res =0 ; + +if (priv->hw->open_count++ ==0 ) { + res =dev_open (priv->hw->netdev); +WARN_ON (res); +if (res) + goto err; + } + +netif_start_queue (dev); +return 0 ; +err: + priv->hw->open_count--; + +return res; +} + +static int ieee802154_slave_close (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + +netif_stop_queue (dev); + +if ((--priv->hw->open_count) ==0 ) { +if (netif_running (priv->hw->netdev)) +dev_close (priv->hw->netdev); + } + +return 0 ; +} + + +static int ieee802154_slave_ioctl (struct net_device *dev,struct ifreq *ifr, +int cmd) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +struct sockaddr_ieee802154 *sa = + (struct sockaddr_ieee802154 *)&ifr->ifr_addr; +int err = -ENOIOCTLCMD ; + +read_lock (&priv->mib_lock); + +switch (cmd) { +case SIOCGIFADDR : +if (priv->pan_id ==IEEE802154_PANID_BROADCAST || + priv->short_addr ==IEEE802154_ADDR_BROADCAST ) { + err = -EADDRNOTAVAIL ; +break ; + } + + sa->family =AF_IEEE802154 ; + sa->addr.addr_type =IEEE802154_ADDR_SHORT ; + sa->addr.pan_id = priv->pan_id; + sa->addr.short_addr = priv->short_addr; + + err =0 ; +break ; +case SIOCSIFADDR : +dev_warn (&dev->dev, +"Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n" ); +if (sa->family !=AF_IEEE802154 || + sa->addr.addr_type !=IEEE802154_ADDR_SHORT || + sa->addr.pan_id ==IEEE802154_PANID_BROADCAST || + sa->addr.short_addr ==IEEE802154_ADDR_BROADCAST || + sa->addr.short_addr ==IEEE802154_ADDR_UNDEF ) { + err = -EINVAL ; +break ; + } + + priv->pan_id = sa->addr.pan_id; + priv->short_addr = sa->addr.short_addr; + err =0 ; +break ; + } +read_unlock (&priv->mib_lock); +return err; +} + +static int ieee802154_slave_mac_addr (struct net_device *dev,void *p) +{ +struct sockaddr *addr = p; + +if (netif_running (dev)) +return -EBUSY ; +/* FIXME: validate addr */ +memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); +return 0 ; +} + +static void ieee802154_haddr_copy_swap (u8 *dest,const u8 *src) +{ +int i; +for (i =0 ; i <IEEE802154_ADDR_LEN ; i++) + dest[IEEE802154_ADDR_LEN - i -1 ] = src[i]; +} + +static int ieee802154_header_create (struct sk_buff *skb, +struct net_device *dev, +unsigned short type,const void *_daddr, +const void *_saddr,unsigned len) +{ +u8 head[24 ] = {}; +int pos =0 ; + +u16 fc; +const struct ieee802154_addr *saddr = _saddr; +const struct ieee802154_addr *daddr = _daddr; +struct ieee802154_addr dev_addr; +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + + fc =mac_cb_type (skb); +if (mac_cb_is_ackreq (skb)) + fc |=IEEE802154_FC_ACK_REQ ; + + pos =2 ; + + head[pos++] =mac_cb (skb)->seq;/* DSN/BSN */ + +if (!daddr) +return -EINVAL ; + +if (!saddr) { +read_lock (&priv->mib_lock); +if (priv->short_addr ==IEEE802154_ADDR_BROADCAST || + priv->short_addr ==IEEE802154_ADDR_UNDEF || + priv->pan_id ==IEEE802154_PANID_BROADCAST ) { + dev_addr.addr_type =IEEE802154_ADDR_LONG ; +memcpy (dev_addr.hwaddr, dev->dev_addr, +IEEE802154_ADDR_LEN ); + }else { + dev_addr.addr_type =IEEE802154_ADDR_SHORT ; + dev_addr.short_addr = priv->short_addr; + } + + dev_addr.pan_id = priv->pan_id; + saddr = &dev_addr; + +read_unlock (&priv->mib_lock); + } + +if (daddr->addr_type !=IEEE802154_ADDR_NONE ) { + fc |= (daddr->addr_type <<IEEE802154_FC_DAMODE_SHIFT ); + + head[pos++] = daddr->pan_id &0xff ; + head[pos++] = daddr->pan_id >>8 ; + +if (daddr->addr_type ==IEEE802154_ADDR_SHORT ) { + head[pos++] = daddr->short_addr &0xff ; + head[pos++] = daddr->short_addr >>8 ; + }else { +ieee802154_haddr_copy_swap (head + pos, daddr->hwaddr); + pos +=IEEE802154_ADDR_LEN ; + } + } + +if (saddr->addr_type !=IEEE802154_ADDR_NONE ) { + fc |= (saddr->addr_type <<IEEE802154_FC_SAMODE_SHIFT ); + +if ((saddr->pan_id == daddr->pan_id) && + (saddr->pan_id !=IEEE802154_PANID_BROADCAST )) +/* PANID compression/ intra PAN */ + fc |=IEEE802154_FC_INTRA_PAN ; +else { + head[pos++] = saddr->pan_id &0xff ; + head[pos++] = saddr->pan_id >>8 ; + } + +if (saddr->addr_type ==IEEE802154_ADDR_SHORT ) { + head[pos++] = saddr->short_addr &0xff ; + head[pos++] = saddr->short_addr >>8 ; + }else { +ieee802154_haddr_copy_swap (head + pos, saddr->hwaddr); + pos +=IEEE802154_ADDR_LEN ; + } + } + + head[0 ] = fc; + head[1 ] = fc >>8 ; + +memcpy (skb_push (skb, pos), head, pos); + +return pos; +} + +static int ieee802154_header_parse (const struct sk_buff *skb, +unsigned char *haddr) +{ +const u8 *hdr =skb_mac_header (skb), *tail =skb_tail_pointer (skb); +struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr; +u16 fc; +int da_type; + +if (hdr +3 > tail) + goto malformed; + + fc = hdr[0 ] | (hdr[1 ] <<8 ); + + hdr +=3 ; + + da_type =IEEE802154_FC_DAMODE (fc); + addr->addr_type =IEEE802154_FC_SAMODE (fc); + +switch (da_type) { +case IEEE802154_ADDR_NONE : +if (fc &IEEE802154_FC_INTRA_PAN ) + goto malformed; +break ; + +case IEEE802154_ADDR_LONG : +if (hdr +2 > tail) + goto malformed; +if (fc &IEEE802154_FC_INTRA_PAN ) { + addr->pan_id = hdr[0 ] | (hdr[1 ] <<8 ); + hdr +=2 ; + } + +if (hdr +IEEE802154_ADDR_LEN > tail) + goto malformed; + hdr +=IEEE802154_ADDR_LEN ; +break ; + +case IEEE802154_ADDR_SHORT : +if (hdr +2 > tail) + goto malformed; +if (fc &IEEE802154_FC_INTRA_PAN ) { + addr->pan_id = hdr[0 ] | (hdr[1 ] <<8 ); + hdr +=2 ; + } + +if (hdr +2 > tail) + goto malformed; + hdr +=2 ; +break ; + +default : + goto malformed; + + } + +switch (addr->addr_type) { +case IEEE802154_ADDR_NONE : +break ; + +case IEEE802154_ADDR_LONG : +if (hdr +2 > tail) + goto malformed; +if (!(fc &IEEE802154_FC_INTRA_PAN )) { + addr->pan_id = hdr[0 ] | (hdr[1 ] <<8 ); + hdr +=2 ; + } + +if (hdr +IEEE802154_ADDR_LEN > tail) + goto malformed; +memcpy (addr->hwaddr, hdr,IEEE802154_ADDR_LEN ); + hdr +=IEEE802154_ADDR_LEN ; +break ; + +case IEEE802154_ADDR_SHORT : +if (hdr +2 > tail) + goto malformed; +if (!(fc &IEEE802154_FC_INTRA_PAN )) { + addr->pan_id = hdr[0 ] | (hdr[1 ] <<8 ); + hdr +=2 ; + } + +if (hdr +2 > tail) + goto malformed; + addr->short_addr = hdr[0 ] | (hdr[1 ] <<8 ); + hdr +=2 ; +break ; + +default : + goto malformed; + + } + +return sizeof (struct ieee802154_addr ); + +malformed: +pr_debug ("malformed packet\n" ); +return 0 ; +} + +static struct header_ops ieee802154_header_ops = { + .create = ieee802154_header_create, + .parse = ieee802154_header_parse, +}; + +static const struct net_device_ops ieee802154_slave_ops = { + .ndo_open = ieee802154_slave_open, + .ndo_stop = ieee802154_slave_close, + .ndo_start_xmit = ieee802154_net_xmit, + .ndo_do_ioctl = ieee802154_slave_ioctl, + .ndo_set_mac_address = ieee802154_slave_mac_addr, +}; + +static void ieee802154_netdev_setup (struct net_device *dev) +{ + dev->addr_len =IEEE802154_ADDR_LEN ; +memset (dev->broadcast,0xff ,IEEE802154_ADDR_LEN ); + dev->features =NETIF_F_NO_CSUM ; + dev->hard_header_len =2 +1 +20 +14 ; + dev->header_ops = &ieee802154_header_ops; + dev->needed_tailroom =2 ;/* FCS */ + dev->mtu =127 ; + dev->tx_queue_len =10 ; + dev->type =ARPHRD_IEEE802154 ;
net/mac802154/dev.c line 386
Quoted 10 lines
net/mac802154/dev.c new file +10
-0+ dev->flags =IFF_NOARP |IFF_BROADCAST ; + dev->watchdog_timeo =0 ; + + dev->destructor = free_netdev; + dev->netdev_ops = &ieee802154_slave_ops; + dev->ml_priv = &mac802154_mlme; +} + +/* +* This is for hw unregistration only, as it doesn't do RCU locking
So this list is different than the RCU-protected one, and readers always hold locks when traversing it?
I am not familiar with this code, so might be missing something, but it looks to me like the same list that RCU readers traverse. If so, need list_del_rcu() and synchronize_rcu().
Quoted 1,184 lines
net/mac802154/dev.c new file +538
-0+*/ +void ieee802154_drop_slaves (struct ieee802154_dev *hw) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (hw); +struct ieee802154_sub_if_data *sdata, *next; + +ASSERT_RTNL (); + +list_for_each_entry_safe (sdata, next, &priv->slaves, list) { +mutex_lock (&sdata->hw->slaves_mtx); +list_del (&sdata->list); +mutex_unlock (&sdata->hw->slaves_mtx); + +dev_put (sdata->hw->netdev); + +unregister_netdevice (sdata->dev); + } +} + +static int ieee802154_netdev_validate (struct nlattr *tb[], +struct nlattr *data[]) +{ +if (tb[IFLA_ADDRESS ]) +if (nla_len (tb[IFLA_ADDRESS ]) !=IEEE802154_ADDR_LEN ) +return -EINVAL ; + +if (tb[IFLA_BROADCAST ]) +return -EINVAL ; + +return 0 ; +} + +static int ieee802154_netdev_newlink (struct net_device *dev, +struct nlattr *tb[], +struct nlattr *data[]) +{ +struct net_device *mdev; +struct ieee802154_sub_if_data *priv; +struct ieee802154_priv *ipriv; +int err; + +if (!tb[IFLA_LINK ]) +return -EOPNOTSUPP ; + + mdev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); +if (!mdev) +return -ENODEV ; + +if (mdev->type !=ARPHRD_IEEE802154_PHY ) +return -EINVAL ; + + ipriv =netdev_priv (mdev); + + priv =netdev_priv (dev); + priv->dev = dev; + priv->hw = ipriv; + +rwlock_init (&priv->mib_lock); + +get_random_bytes (&priv->bsn,1 ); +get_random_bytes (&priv->dsn,1 ); + + priv->pan_id =IEEE802154_PANID_BROADCAST ; + priv->short_addr =IEEE802154_ADDR_BROADCAST ; + +dev_hold (ipriv->netdev); + + dev->needed_headroom = ipriv->hw.extra_tx_headroom; + +SET_NETDEV_DEV (dev, &ipriv->netdev->dev); + + err =register_netdevice (dev); +if (err <0 ) +return err; + +mutex_lock (&ipriv->slaves_mtx); +list_add_tail_rcu (&priv->list, &ipriv->slaves); +mutex_unlock (&ipriv->slaves_mtx); + +return 0 ; +} + +static void ieee802154_netdev_dellink (struct net_device *dev) +{ +struct ieee802154_sub_if_data *sdata; +ASSERT_RTNL (); + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + + sdata =netdev_priv (dev); + +mutex_lock (&sdata->hw->slaves_mtx); +list_del_rcu (&sdata->list); +mutex_unlock (&sdata->hw->slaves_mtx); + +dev_put (sdata->hw->netdev); + +synchronize_rcu (); +unregister_netdevice (sdata->dev); +} + +static size_t ieee802154_netdev_get_size (const struct net_device *dev) +{ +return nla_total_size (2 ) +/* IFLA_WPAN_CHANNEL */ +nla_total_size (2 ) +/* IFLA_WPAN_PAN_ID */ +nla_total_size (2 ) +/* IFLA_WPAN_SHORT_ADDR */ +nla_total_size (2 ) +/* IFLA_WPAN_COORD_SHORT_ADDR */ +nla_total_size (8 );/* IFLA_WPAN_COORD_EXT_ADDR */ +} + +static int ieee802154_netdev_fill_info (struct sk_buff *skb, +const struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + +read_lock (&priv->mib_lock); + +NLA_PUT_U16 (skb,IFLA_WPAN_CHANNEL , priv->chan); +NLA_PUT_U16 (skb,IFLA_WPAN_PAN_ID , priv->pan_id); +NLA_PUT_U16 (skb,IFLA_WPAN_SHORT_ADDR , priv->short_addr); +/* TODO: IFLA_WPAN_COORD_SHORT_ADDR */ +/* TODO: IFLA_WPAN_COORD_EXT_ADDR */ + +read_unlock (&priv->mib_lock); + +return 0 ; + +nla_put_failure: +read_unlock (&priv->mib_lock); +return -EMSGSIZE ; +} + +static struct rtnl_link_ops wpan_link_ops__read_mostly = { + .kind ="wpan" , + .priv_size =sizeof (struct ieee802154_sub_if_data ), + .setup = ieee802154_netdev_setup, + .validate = ieee802154_netdev_validate, + .newlink = ieee802154_netdev_newlink, + .dellink = ieee802154_netdev_dellink, + .get_size = ieee802154_netdev_get_size, + .fill_info = ieee802154_netdev_fill_info, +}; + +static int ieee802154_process_beacon (struct net_device *dev, +struct sk_buff *skb) +{ +pr_warning ("ieee802154: beacon frames are not yet supported\n" ); +kfree_skb (skb); +return NET_RX_DROP ; +} + +static int ieee802154_process_ack (struct net_device *dev,struct sk_buff *skb) +{ +pr_debug ("got ACK for SEQ=%d\n" ,mac_cb (skb)->seq); + +kfree_skb (skb); +return NET_RX_SUCCESS ; +} + +static int ieee802154_process_data (struct net_device *dev,struct sk_buff *skb) +{ +return netif_rx (skb); +} + +static int ieee802154_subif_frame (struct ieee802154_sub_if_data *sdata, +struct sk_buff *skb) +{ +pr_debug ("%s Getting packet via slave interface %s\n" , + __func__, sdata->dev->name); + +read_lock (&sdata->mib_lock); + +switch (mac_cb (skb)->da.addr_type) { +case IEEE802154_ADDR_NONE : +if (mac_cb (skb)->sa.addr_type !=IEEE802154_ADDR_NONE ) +/* FIXME: check if we are PAN coordinator :) */ + skb->pkt_type =PACKET_OTHERHOST ; +else +/* ACK comes with both addresses empty */ + skb->pkt_type =PACKET_HOST ; +break ; +case IEEE802154_ADDR_LONG : +if (mac_cb (skb)->da.pan_id != sdata->pan_id && +mac_cb (skb)->da.pan_id !=IEEE802154_PANID_BROADCAST ) + skb->pkt_type =PACKET_OTHERHOST ; +else if (!memcmp (mac_cb (skb)->da.hwaddr, sdata->dev->dev_addr, +IEEE802154_ADDR_LEN )) + skb->pkt_type =PACKET_HOST ; +else + skb->pkt_type =PACKET_OTHERHOST ; +break ; +case IEEE802154_ADDR_SHORT : +if (mac_cb (skb)->da.pan_id != sdata->pan_id && +mac_cb (skb)->da.pan_id !=IEEE802154_PANID_BROADCAST ) + skb->pkt_type =PACKET_OTHERHOST ; +else if (mac_cb (skb)->da.short_addr == sdata->short_addr) + skb->pkt_type =PACKET_HOST ; +else if (mac_cb (skb)->da.short_addr == +IEEE802154_ADDR_BROADCAST ) + skb->pkt_type =PACKET_BROADCAST ; +else + skb->pkt_type =PACKET_OTHERHOST ; +break ; + } + +read_unlock (&sdata->mib_lock); + + skb->dev = sdata->dev; + +if (skb->pkt_type ==PACKET_HOST &&mac_cb_is_ackreq (skb) && + !(sdata->hw->hw.flags &IEEE802154_HW_AACK )) +dev_warn (&sdata->dev->dev, +"ACK requested, however AACK not supported.\n" ); + +switch (mac_cb_type (skb)) { +case IEEE802154_FC_TYPE_BEACON : +return ieee802154_process_beacon (sdata->dev, skb); +case IEEE802154_FC_TYPE_ACK : +return ieee802154_process_ack (sdata->dev, skb); +case IEEE802154_FC_TYPE_MAC_CMD : +return ieee802154_process_cmd (sdata->dev, skb); +case IEEE802154_FC_TYPE_DATA : +return ieee802154_process_data (sdata->dev, skb); +default : +pr_warning ("ieee802154: Bad frame received (type = %d)\n" , +mac_cb_type (skb)); +kfree_skb (skb); +return NET_RX_DROP ; + } +} + +static u8 fetch_skb_u8 (struct sk_buff *skb) +{ +u8 ret; + +BUG_ON (skb->len <1 ); + + ret = skb->data[0 ]; +skb_pull (skb,1 ); + +return ret; +} + +static u16 fetch_skb_u16 (struct sk_buff *skb) +{ +u16 ret; + +BUG_ON (skb->len <2 ); + + ret = skb->data[0 ] + (skb->data[1 ] *256 ); +skb_pull (skb,2 ); +return ret; +} + +static void fetch_skb_u64 (struct sk_buff *skb,void *data) +{ +BUG_ON (skb->len <IEEE802154_ADDR_LEN ); + +memcpy (data, skb->data,IEEE802154_ADDR_LEN ); +skb_pull (skb,IEEE802154_ADDR_LEN ); +} + +#define IEEE802154_FETCH_U8 (skb, var) \ + do { \ + if (skb->len < 1) \ + goto exit_error; \ + var = fetch_skb_u8(skb); \ + } while (0) + +#define IEEE802154_FETCH_U16 (skb, var) \ + do { \ + if (skb->len < 2) \ + goto exit_error; \ + var = fetch_skb_u16(skb); \ + } while (0) + +#define IEEE802154_FETCH_U64 (skb, var) \ + do { \ + if (skb->len < IEEE802154_ADDR_LEN) \ + goto exit_error; \ + fetch_skb_u64(skb, &var); \ + } while (0) + +static int parse_frame_start (struct sk_buff *skb) +{ +u8 *head = skb->data; +u16 fc; + +if (skb->len <3 ) { +pr_debug ("frame size %d bytes is too short\n" , skb->len); +return -EINVAL ; + } + +IEEE802154_FETCH_U16 (skb, fc); +IEEE802154_FETCH_U8 (skb,mac_cb (skb)->seq); + +pr_debug ("%s: %04x dsn%02x\n" , __func__, fc, head[2 ]); + +mac_cb (skb)->flags =IEEE802154_FC_TYPE (fc); + +if (fc &IEEE802154_FC_ACK_REQ ) { +pr_debug ("%s(): ACKNOWLEDGE required\n" , __func__); +mac_cb (skb)->flags |=MAC_CB_FLAG_ACKREQ ; + } + +if (fc &IEEE802154_FC_SECEN ) +mac_cb (skb)->flags |=MAC_CB_FLAG_SECEN ; + +if (fc &IEEE802154_FC_INTRA_PAN ) +mac_cb (skb)->flags |=MAC_CB_FLAG_INTRAPAN ; + +/* TODO */ +if (mac_cb_is_secen (skb)) { +pr_info ("security support is not implemented\n" ); +return -EINVAL ; + } + +mac_cb (skb)->sa.addr_type =IEEE802154_FC_SAMODE (fc); +if (mac_cb (skb)->sa.addr_type ==IEEE802154_ADDR_NONE ) +pr_debug ("%s(): src addr_type is NONE\n" , __func__); + +mac_cb (skb)->da.addr_type =IEEE802154_FC_DAMODE (fc); +if (mac_cb (skb)->da.addr_type ==IEEE802154_ADDR_NONE ) +pr_debug ("%s(): dst addr_type is NONE\n" , __func__); + +if (IEEE802154_FC_TYPE (fc) ==IEEE802154_FC_TYPE_ACK ) { +/* ACK can only have NONE-type addresses */ +if (mac_cb (skb)->sa.addr_type !=IEEE802154_ADDR_NONE || +mac_cb (skb)->da.addr_type !=IEEE802154_ADDR_NONE ) +return -EINVAL ; + } + +if (mac_cb (skb)->da.addr_type !=IEEE802154_ADDR_NONE ) { +IEEE802154_FETCH_U16 (skb,mac_cb (skb)->da.pan_id); + +if (mac_cb_is_intrapan (skb)) {/* ! panid compress */ +pr_debug ("%s(): src IEEE802154_FC_INTRA_PAN\n" , + __func__); +mac_cb (skb)->sa.pan_id =mac_cb (skb)->da.pan_id; +pr_debug ("%s(): src PAN address %04x\n" , + __func__,mac_cb (skb)->sa.pan_id); + } + +pr_debug ("%s(): dst PAN address %04x\n" , + __func__,mac_cb (skb)->da.pan_id); + +if (mac_cb (skb)->da.addr_type ==IEEE802154_ADDR_SHORT ) { +IEEE802154_FETCH_U16 (skb,mac_cb (skb)->da.short_addr); +pr_debug ("%s(): dst SHORT address %04x\n" , + __func__,mac_cb (skb)->da.short_addr); + + }else { +IEEE802154_FETCH_U64 (skb,mac_cb (skb)->da.hwaddr); +pr_debug ("%s(): dst hardware addr\n" , __func__); + } + } + +if (mac_cb (skb)->sa.addr_type !=IEEE802154_ADDR_NONE ) { +pr_debug ("%s(): got src non-NONE address\n" , __func__); +if (!(mac_cb_is_intrapan (skb))) {/* ! panid compress */ +IEEE802154_FETCH_U16 (skb,mac_cb (skb)->sa.pan_id); +pr_debug ("%s(): src IEEE802154_FC_INTRA_PAN\n" , + __func__); + } + +if (mac_cb (skb)->sa.addr_type ==IEEE802154_ADDR_SHORT ) { +IEEE802154_FETCH_U16 (skb,mac_cb (skb)->sa.short_addr); +pr_debug ("%s(): src IEEE802154_ADDR_SHORT\n" , + __func__); + }else { +IEEE802154_FETCH_U64 (skb,mac_cb (skb)->sa.hwaddr); +pr_debug ("%s(): src hardware addr\n" , __func__); + } + } + +return 0 ; + +exit_error: +return -EINVAL ; +} + +void ieee802154_subif_rx (struct ieee802154_dev *hw,struct sk_buff *skb) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (hw); +struct ieee802154_sub_if_data *sdata, *prev =NULL ; +int ret; + +BUILD_BUG_ON (sizeof (struct ieee802154_mac_cb ) >sizeof (skb->cb)); +pr_debug ("%s()\n" , __func__); + +if (!(priv->hw.flags &IEEE802154_HW_OMIT_CKSUM )) { +u16 crc; + +if (skb->len <2 ) { +pr_debug ("%s(): Got invalid frame\n" , __func__); + goto out; + } + crc =crc_ccitt (0 , skb->data, skb->len); +if (crc) { +pr_debug ("%s(): CRC mismatch\n" , __func__); + goto out; + } +skb_trim (skb, skb->len -2 );/* CRC */ + } + + ret =parse_frame_start (skb);/* 3 bytes pulled after this */ +if (ret) { +pr_debug ("%s(): Got invalid frame\n" , __func__); + goto out; + } + +pr_debug ("%s() frame %d\n" , __func__,mac_cb_type (skb)); + +rcu_read_lock (); +list_for_each_entry_rcu (sdata, &priv->slaves, list) + { +if (prev) { +struct sk_buff *skb2 =skb_clone (skb,GFP_ATOMIC ); +if (skb2) +ieee802154_subif_frame (prev, skb2); + } + + prev = sdata; + } + +if (prev) { +ieee802154_subif_frame (prev, skb); + skb =NULL ; + } + +rcu_read_unlock (); + +out: +dev_kfree_skb (skb); +return ; +} + +u16 ieee802154_dev_get_pan_id (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +u16 ret; + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +read_lock (&priv->mib_lock); + ret = priv->pan_id; +read_unlock (&priv->mib_lock); + +return ret; +} + +u16 ieee802154_dev_get_short_addr (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +u16 ret; + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +read_lock (&priv->mib_lock); + ret = priv->short_addr; +read_unlock (&priv->mib_lock); + +return ret; +} + +void ieee802154_dev_set_pan_id (struct net_device *dev,u16 val) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +write_lock (&priv->mib_lock); + priv->pan_id = val; +write_unlock (&priv->mib_lock); +} +void ieee802154_dev_set_short_addr (struct net_device *dev,u16 val) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +write_lock (&priv->mib_lock); + priv->short_addr = val; +write_unlock (&priv->mib_lock); +} +void ieee802154_dev_set_channel (struct net_device *dev,u8 val) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +write_lock (&priv->mib_lock); + priv->chan = val; +write_unlock (&priv->mib_lock); +} + +u8 ieee802154_dev_get_dsn (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +u16 ret; + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +write_lock (&priv->mib_lock); + ret = priv->dsn++; +write_unlock (&priv->mib_lock); + +return ret; +} + +u8 ieee802154_dev_get_bsn (struct net_device *dev) +{ +struct ieee802154_sub_if_data *priv =netdev_priv (dev); +u16 ret; + +BUG_ON (dev->type !=ARPHRD_IEEE802154 ); + +write_lock (&priv->mib_lock); + ret = priv->bsn++; +write_unlock (&priv->mib_lock); + +return ret; +} + +static int __init ieee802154_dev_init (void ) +{ +return rtnl_link_register (&wpan_link_ops); +} +module_init (ieee802154_dev_init); + +static void __exit ieee802154_dev_exit(void) +{ +rtnl_link_unregister (&wpan_link_ops); +} +module_exit (ieee802154_dev_exit); + +MODULE_ALIAS_RTNL_LINK ("wpan" ); +net/mac802154/mac802154.h new file +85
-0@@ -0,0 +1,85 @@ +/* +* Copyright (C) 2007, 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Written by: +* Pavel Smolenskiy <[email protected]> +* Maxim Gorbachyov <[email protected]> +* Dmitry Eremin-Solenikov <[email protected]> +*/ +#ifndef MAC802154_H +#define MAC802154_H + +#include <linux/spinlock.h> +struct ieee802154_priv { +struct ieee802154_dev hw; +struct ieee802154_ops *ops; + +struct net_device *netdev;/* mwpanX device */ +int open_count; +/* As in mac80211 slaves list is modified: +* 1) under the RTNL +* 2) protected by slaves_mtx; +* 3) in an RCU manner +* +* So atomic readers can use any of this protection methods +*/ +struct list_head slaves; +struct mutex slaves_mtx; +/* This one is used for scanning and other +* jobs not to be interfered with serial driver */ +struct workqueue_struct *dev_workqueue; +}; + +#define ieee802154_to_priv (_hw) container_of(_hw, struct ieee802154_priv, hw) + +struct ieee802154_sub_if_data { +struct list_head list;/* the ieee802154_priv->slaves list */ + +struct ieee802154_priv *hw; +struct net_device *dev; + +rwlock_t mib_lock; + +u16 pan_id; +u16 short_addr; + +u8 chan; + +/* MAC BSN field */ +u8 bsn; +/* MAC BSN field */ +u8 dsn; +}; + +void ieee802154_drop_slaves (struct ieee802154_dev *hw); + +void ieee802154_subif_rx (struct ieee802154_dev *hw,struct sk_buff *skb); + +struct ieee802154_phy_cb { +u8 lqi; +u8 chan; +}; + +static inline struct ieee802154_phy_cb *phy_cb (struct sk_buff *skb) +{ +return (struct ieee802154_phy_cb *)skb->cb; +} + +extern struct ieee802154_mlme_ops mac802154_mlme; + +int ieee802154_process_cmd (struct net_device *dev,struct sk_buff *skb); + +#endif net/mac802154/mac_cmd.c new file +99
-0@@ -0,0 +1,99 @@ +/* +* MAC commands interface +* +* Copyright 2007, 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Written by: +* Sergey Lapin <[email protected]> +* Dmitry Eremin-Solenikov <[email protected]> +*/ + +#include <linux/kernel.h> +#include <linux/skbuff.h> +#include <linux/if_arp.h> +#include <net/af_ieee802154.h> +#include <net/mac802154.h> +#include <net/ieee802154.h> +#include <net/ieee802154_netdev.h> +#include <net/nl802154.h> + +#include "mac802154.h" +#include "mib.h" + +int ieee802154_process_cmd (struct net_device *dev,struct sk_buff *skb) +{ +pr_warning ("ieee802154: command frames are not yet supported\n" ); +kfree_skb (skb); +return NET_RX_DROP ; +} + + +static int ieee802154_mlme_assoc_req (struct net_device *dev, +struct ieee802154_addr *addr,u8 channel,u8 cap) +{ +/* We simply emulate it here */ +return ieee802154_nl_assoc_confirm (dev, +ieee802154_dev_get_short_addr (dev), +IEEE802154_SUCCESS ); +} + +static int ieee802154_mlme_assoc_resp (struct net_device *dev, +struct ieee802154_addr *addr,u16 short_addr,u8 status) +{ +return 0 ; +} + +static int ieee802154_mlme_disassoc_req (struct net_device *dev, +struct ieee802154_addr *addr,u8 reason) +{ +return ieee802154_nl_disassoc_confirm (dev,IEEE802154_SUCCESS ); +} + +static int ieee802154_mlme_start_req (struct net_device *dev, +struct ieee802154_addr *addr, +u8 channel, +u8 bcn_ord,u8 sf_ord,u8 pan_coord,u8 blx, +u8 coord_realign) +{ +/* We don't emulate beacons here at all, so START should fail */ +ieee802154_nl_start_confirm (dev,IEEE802154_INVALID_PARAMETER ); +return 0 ; +} + +static int ieee802154_mlme_scan_req (struct net_device *dev,u8 type, +u32 channels, +u8 duration) +{ +u8 edl[27 ] = {}; +return ieee802154_nl_scan_confirm (dev,IEEE802154_SUCCESS , type, + channels, + type ==IEEE802154_MAC_SCAN_ED ? edl :NULL ); +} + + +struct ieee802154_mlme_ops mac802154_mlme = { + .assoc_req = ieee802154_mlme_assoc_req, + .assoc_resp = ieee802154_mlme_assoc_resp, + .disassoc_req = ieee802154_mlme_disassoc_req, + .start_req = ieee802154_mlme_start_req, + .scan_req = ieee802154_mlme_scan_req, + + .get_pan_id = ieee802154_dev_get_pan_id, + .get_short_addr = ieee802154_dev_get_short_addr, + .get_dsn = ieee802154_dev_get_dsn, + .get_bsn = ieee802154_dev_get_bsn, +}; +net/mac802154/mdev.c new file +295
-0@@ -0,0 +1,295 @@ +/* +* Copyright (C) 2007, 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +*/ + +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/if_arp.h> +#include <net/route.h> + +#include <net/af_ieee802154.h> +#include <net/mac802154.h> + +#include "mac802154.h" + +struct xmit_work { +struct sk_buff *skb; +struct work_struct work; +struct ieee802154_priv *priv; +}; + +static void ieee802154_xmit_worker (struct work_struct *work) +{ + struct xmit_work *xw = container_of(work, struct xmit_work, work); +int res; + +if (xw->priv->hw.current_channel !=phy_cb (xw->skb)->chan) { + res = xw->priv->ops->set_channel (&xw->priv->hw, +phy_cb (xw->skb)->chan); +if (res) { +pr_debug ("set_channel failed\n" ); + goto out; + } + } + + res = xw->priv->ops->xmit (&xw->priv->hw, xw->skb); + +out: +/* FIXME: result processing and/or requeue!!! */ +dev_kfree_skb (xw->skb); + +kfree (xw); +} + +static int ieee802154_master_hard_start_xmit (struct sk_buff *skb, +struct net_device *dev) +{ +struct ieee802154_priv *priv =netdev_priv (dev); +struct xmit_work *work; + +if (skb_cow_head (skb, priv->hw.extra_tx_headroom)) { +dev_kfree_skb (skb); +return NETDEV_TX_OK ; + } + + work =kzalloc (sizeof (struct xmit_work ),GFP_ATOMIC ); +if (!work) +return NETDEV_TX_BUSY ; + +INIT_WORK (&work->work, ieee802154_xmit_worker); + work->skb = skb; + work->priv = priv; + +queue_work (priv->dev_workqueue, &work->work); + +return NETDEV_TX_OK ; +} + +static int ieee802154_master_open (struct net_device *dev) +{ +int rc; +struct ieee802154_priv *priv =netdev_priv (dev); + +if (!priv) { +pr_debug ("%s:%s: unable to get master private data\n" , + __FILE__, __func__); +return -ENODEV ; + } + +if (!priv->open_count) +return -EOPNOTSUPP ; + + rc = priv->ops->start (&priv->hw); + +if (!rc) +netif_tx_start_all_queues (dev); + +return rc; +} + +static int ieee802154_master_close (struct net_device *dev) +{ +struct ieee802154_priv *priv =netdev_priv (dev); +struct ieee802154_sub_if_data *sdata; + +ASSERT_RTNL (); + +/* We are under RTNL, so it's fine to do this */ +list_for_each_entry (sdata, &priv->slaves, list) +if (netif_running (sdata->dev)) +dev_close (sdata->dev); + + priv->ops->stop (&priv->hw); + +return 0 ; +} + +static ssize_t ieee802154_netdev_show (const struct device *dev, +struct device_attribute *attr,char *buf, +ssize_t (*format)(const struct net_device *,char *)) +{ +struct net_device *netdev =to_net_dev (dev); +ssize_t ret = -EINVAL ; + +if (netdev->reg_state <=NETREG_REGISTERED ) + ret = (*format)(netdev, buf); + +return ret; +} +#define MASTER_SHOW (field, format_string) \ +static ssize_t format_##field(const struct net_device *dev, char *buf) \ +{ \ + struct ieee802154_priv *priv = netdev_priv(dev); \ + return sprintf(buf, format_string, priv->hw.field); \ +} \ +static ssize_t show_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + return ieee802154_netdev_show(dev, attr, buf, format_##field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) + +static const char fmt_long_hex[] ="%#lx\n" ; +static const char fmt_hex[] ="%#x\n" ; +static const char fmt_dec[] ="%d\n" ; + +MASTER_SHOW (current_channel, fmt_dec); +MASTER_SHOW (channel_mask, fmt_hex); + +static struct attribute *pmib_attrs[] = { + &dev_attr_current_channel.attr, + &dev_attr_channel_mask.attr, +NULL +}; + +static struct attribute_group pmib_group = { + .name ="pib" , + .attrs = pmib_attrs, +}; + +static const struct net_device_ops ieee802154_master_ops = { + .ndo_open = ieee802154_master_open, + .ndo_stop = ieee802154_master_close, + .ndo_start_xmit = ieee802154_master_hard_start_xmit, +}; + +static void ieee802154_netdev_setup_master (struct net_device *dev) +{ + dev->addr_len =0 ; + dev->features =NETIF_F_NO_CSUM ; + dev->hard_header_len =0 ; + dev->mtu =127 ; + dev->tx_queue_len =0 ; + dev->type =ARPHRD_IEEE802154_PHY ; + dev->flags =IFF_NOARP |IFF_BROADCAST ; + dev->watchdog_timeo =0 ; + + dev->netdev_ops = &ieee802154_master_ops; +} + +struct ieee802154_dev *ieee802154_alloc_device (size_t priv_size, +struct ieee802154_ops *ops) +{ +struct net_device *dev; +struct ieee802154_priv *priv; + + dev =alloc_netdev (ALIGN (sizeof (*priv),NETDEV_ALIGN ) + priv_size, +"mwpan%d" , ieee802154_netdev_setup_master); +if (!dev) { +printk (KERN_ERR +"Failure to initialize master IEEE802154 device\n" ); +return NULL ; + } + priv =netdev_priv (dev); + priv->netdev = dev; + priv->hw.priv = (char *)priv +ALIGN (sizeof (*priv),NETDEV_ALIGN ); + +BUG_ON (!dev); +BUG_ON (!ops); +BUG_ON (!ops->xmit); +BUG_ON (!ops->ed); +BUG_ON (!ops->start); +BUG_ON (!ops->stop); + +if (!try_module_get (ops->owner)) { +free_netdev (dev); +return NULL ; + } + + priv->ops = ops; + +INIT_LIST_HEAD (&priv->slaves); +mutex_init (&priv->slaves_mtx); + +return &priv->hw; +} +EXPORT_SYMBOL (ieee802154_alloc_device); + +void ieee802154_free_device (struct ieee802154_dev *hw) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (hw); + +BUG_ON (!list_empty (&priv->slaves)); +BUG_ON (!priv->netdev); + +module_put (priv->ops->owner); + +free_netdev (priv->netdev); +} +EXPORT_SYMBOL (ieee802154_free_device); + +int ieee802154_register_device (struct ieee802154_dev *dev) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (dev); +struct net_device *ndev = priv->netdev; + +int rc; + +rtnl_lock (); +if (strchr (ndev->name,'%' )) { + rc =dev_alloc_name (ndev, ndev->name); +if (rc <0 ) + goto out_unlock; + } + + priv->dev_workqueue = +create_singlethread_workqueue (ndev->name); +if (!priv->dev_workqueue) { + rc = -ENOMEM ; + goto out_unlock; + } + + ndev->needed_headroom = priv->hw.extra_tx_headroom; +SET_NETDEV_DEV (ndev, priv->hw.parent); + + ndev->sysfs_groups[1 ] = &pmib_group; + + rc =register_netdevice (ndev); +if (rc <0 ) + goto out_wq; + +rtnl_unlock (); + +return 0 ; + +out_wq: +destroy_workqueue (priv->dev_workqueue); +out_unlock: +rtnl_unlock (); +return rc; +} +EXPORT_SYMBOL (ieee802154_register_device); + +void ieee802154_unregister_device (struct ieee802154_dev *dev) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (dev); + +flush_workqueue (priv->dev_workqueue); +destroy_workqueue (priv->dev_workqueue); + +rtnl_lock (); + +ieee802154_drop_slaves (dev); +unregister_netdevice (priv->netdev); + +rtnl_unlock (); +} +EXPORT_SYMBOL (ieee802154_unregister_device); + +MODULE_DESCRIPTION ("IEEE 802.15.4 implementation" ); +MODULE_LICENSE ("GPL v2" ); +net/mac802154/mib.h new file +32
-0@@ -0,0 +1,32 @@ +/* +* Copyright 2008 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +*/ + +#ifndef MIB802154_H +#define MIB802154_H + +/* FIXME: should be dropped in favour of generic MIB API */ +u8 ieee802154_dev_get_dsn (struct net_device *dev); +u8 ieee802154_dev_get_bsn (struct net_device *dev); +u16 ieee802154_dev_get_pan_id (struct net_device *dev); +u16 ieee802154_dev_get_short_addr (struct net_device *dev); +void ieee802154_dev_set_pan_id (struct net_device *dev,u16 val); +void ieee802154_dev_set_short_addr (struct net_device *dev,u16 val); +void ieee802154_dev_set_channel (struct net_device *dev,u8 chan); + + +#endif net/mac802154/rx.c new file +98
-0@@ -0,0 +1,98 @@ +/* +* Copyright (C) 2007, 2008, 2009 Siemens AG +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Written by: +* Pavel Smolenskiy <[email protected]> +* Maxim Gorbachyov <[email protected]> +* Dmitry Eremin-Solenikov <[email protected]> +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/workqueue.h> +#include <linux/netdevice.h> + +#include <net/mac802154.h> + +#include "mac802154.h" + +static void __ieee802154_rx_prepare (struct ieee802154_dev *dev, +struct sk_buff *skb,u8 lqi) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (dev); + +BUG_ON (!skb); + +phy_cb (skb)->lqi = lqi; + + skb->dev = priv->netdev; + + skb->iif = skb->dev->ifindex; + + skb->protocol =htons (ETH_P_IEEE802154 ); + +skb_reset_mac_header (skb); +} + +void ieee802154_rx (struct ieee802154_dev *dev,struct sk_buff *skb,u8 lqi) +{ +struct sk_buff *skb2; + +__ieee802154_rx_prepare (dev, skb, lqi); + + skb2 =skb_clone (skb,GFP_KERNEL ); +netif_rx (skb2); + +ieee802154_subif_rx (dev, skb); +} +EXPORT_SYMBOL (ieee802154_rx); + +struct rx_work { +struct sk_buff *skb; +struct work_struct work; +struct ieee802154_dev *dev; +}; + +static void ieee802154_rx_worker (struct work_struct *work) +{ + struct rx_work *rw = container_of(work, struct rx_work, work); +struct sk_buff *skb = rw->skb; + +struct sk_buff *skb2 =skb_clone (skb,GFP_KERNEL ); +netif_rx (skb2); + +ieee802154_subif_rx (rw->dev, skb); +kfree (rw); +} + +void ieee802154_rx_irqsafe (struct ieee802154_dev *dev, +struct sk_buff *skb,u8 lqi) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (dev); +struct rx_work *work =kzalloc (sizeof (struct rx_work ),GFP_ATOMIC ); + +if (!work) +return ; + +__ieee802154_rx_prepare (dev, skb, lqi); + +INIT_WORK (&work->work, ieee802154_rx_worker); + work->skb = skb; + work->dev = dev; + +queue_work (priv->dev_workqueue, &work->work); +} +EXPORT_SYMBOL (ieee802154_rx_irqsafe);Signature · 6 lines
1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20090810172843.GD6791-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org
Re: [PATCH 1/2] mac802154: add a software MAC 802.15.4 implementation
Quoted 14 lines · Paul E. McKenney
Quoted 8 lines · Dmitry Eremin-Solenikov
Some of available devices are just dump radios implementing IEEE 802.15.4 PHY layer. This commit adds a common library that acts like an intermediate layer between our socket family and drivers for those dumb devices.
Currently this is data-only part (no commands, no beacons). Control interfaces will follow up shortly.
Note this implementaion is neither certified, nor feature complete!
One question below, otherwise looks plausible. (I am not entirely sure which lists are which...)
Thanx, Paul
[skipped]
Quoted 11 lines
net/mac802154/dev.c line 386
Quoted 4 lines
net/mac802154/dev.c new file +3
-0+ +/* +* This is for hw unregistration only, as it doesn't do RCU locking So this list is different than the RCU-protected one, and readers always hold locks when traversing it?
I am not familiar with this code, so might be missing something, but it looks to me like the same list that RCU readers traverse. If so, need
list_del_rcu()andsynchronize_rcu().
On the first glance, yes. On the second glance, list_del instead of list_del_rcu should be safe as there should be now other list traversals at the same time. I'll think about it however.
Quoted 19 lines
Quoted 19 lines
+ */
net/mac802154/dev.c new file +17
-0+void ieee802154_drop_slaves (struct ieee802154_dev *hw) +{ +struct ieee802154_priv *priv =ieee802154_to_priv (hw); +struct ieee802154_sub_if_data *sdata, *next; + +ASSERT_RTNL (); + +list_for_each_entry_safe (sdata, next, &priv->slaves, list) { +mutex_lock (&sdata->hw->slaves_mtx); +list_del (&sdata->list); +mutex_unlock (&sdata->hw->slaves_mtx); + +dev_put (sdata->hw->netdev); + +unregister_netdevice (sdata->dev); + } +}
Signature · 9 lines
With best wishes Dmitry ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july