--- include/linux/if_arp.h | 1 include/linux/nl802154.h | 1 net/mac802154/Makefile | 2 - net/mac802154/mac802154.h | 3 + net/mac802154/main.c | 4 + net/mac802154/mib.c | 3 + net/mac802154/rx.c | 1 net/mac802154/smac.c | 127 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 net/mac802154/smac.c
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h index 9cf4974..47a57d8 100644 --- a/include/linux/if_arp.h +++ b/include/linux/if_arp.h @@ -88,6 +88,7 @@ #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ #define ARPHRD_IEEE802154 804 #define ARPHRD_IEEE802154_MONITOR 805 +#define ARPHRD_SMAC 806 /* Freescale Simple MAC */ #define ARPHRD_PHONET 820 /* PhoNet media type */ #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h index a367738..a379fc7 100644 --- a/include/linux/nl802154.h +++ b/include/linux/nl802154.h @@ -128,6 +128,7 @@ enum { enum { IEEE802154_DEV_WPAN, IEEE802154_DEV_MONITOR, + IEEE802154_DEV_SMAC, __IEEE802154_DEV_MAX, }; diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile index b0bc4f7..790b97f 100644 --- a/net/mac802154/Makefile +++ b/net/mac802154/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_MAC802154) += mac802154.o mac802154-objs := rx.o tx.o main.o monitor.o wpan.o mac_cmd.o scan.o mib.o \ - beacon.o beacon_hash.o + beacon.o beacon_hash.o smac.o EXTRA_CFLAGS += -Wall -DDEBUG diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h index e86c8ee..f35245d 100644 --- a/net/mac802154/mac802154.h +++ b/net/mac802154/mac802154.h @@ -112,6 +112,9 @@ struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev); void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb); void mac802154_monitor_setup(struct net_device *dev); +void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb); +void mac802154_smac_setup(struct net_device *dev); + void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb); void mac802154_wpan_setup(struct net_device *dev); diff --git a/net/mac802154/main.c b/net/mac802154/main.c index dfa314f..b108df0 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -141,6 +141,10 @@ static struct net_device *mac802154_add_iface(struct wpan_phy *phy, dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), name, mac802154_monitor_setup); break; + case IEEE802154_DEV_SMAC: + dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), + name, mac802154_smac_setup); + break; default: dev = NULL; err = -EINVAL; diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index ee8cfa0..23871df 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c @@ -242,7 +242,8 @@ struct wpan_phy *mac802154_get_phy(const struct net_device *dev) { struct mac802154_sub_if_data *priv = netdev_priv(dev); BUG_ON(dev->type != ARPHRD_IEEE802154 - && dev->type != ARPHRD_IEEE802154_MONITOR); + && dev->type != ARPHRD_IEEE802154_MONITOR + && dev->type != ARPHRD_SMAC); return to_phy(get_device(&priv->hw->phy->dev)); } diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index be05d6c..0e9d5d4 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c @@ -54,6 +54,7 @@ static void mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb) } mac802154_monitors_rx(priv, skb); + mac802154_smacs_rx(priv, skb); mac802154_wpans_rx(priv, skb); out: diff --git a/net/mac802154/smac.c b/net/mac802154/smac.c new file mode 100644 index 0000000..b11f0ec --- /dev/null +++ b/net/mac802154/smac.c @@ -0,0 +1,127 @@ +/* + * Copyright 2010 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: + * Dmitry Eremin-Solenikov <dbarysh...@gmail.com> + */ + +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/if_arp.h> +#include <linux/nl802154.h> + +#include <net/mac802154.h> +#include <net/wpan-phy.h> + +#include "mac802154.h" + +static const u8 smac_header[] = {0x7E, 0xFF}; + +static netdev_tx_t mac802154_smac_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct mac802154_sub_if_data *priv; + u8 chan, page; + + priv = netdev_priv(dev); + + /* FIXME: locking */ + chan = priv->hw->phy->current_channel; + page = priv->hw->phy->current_page; + + if (chan == (u8)-1) /* not init */ + return NETDEV_TX_OK; + + BUG_ON(page >= WPAN_NUM_PAGES); + BUG_ON(chan >= 27); + + memcpy(skb_push(skb, sizeof(smac_header)), smac_header, sizeof(smac_header)); + + skb->skb_iif = dev->ifindex; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + return mac802154_tx(priv->hw, skb, page, chan); +} + +void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb) +{ + struct mac802154_sub_if_data *sdata; + + if (skb->len < sizeof(smac_header)) + return; + + if (memcmp(skb->data, smac_header, sizeof(smac_header))) + return; + + /* + * Currently we are the owner of the skb. + * We can change it's data pointers, provided we change them + * back at the end. + */ + + skb_pull(skb, sizeof(smac_header)); + + list_for_each_entry_rcu(sdata, &priv->slaves, list) { + struct sk_buff *skb2; + + if (sdata->type != IEEE802154_DEV_SMAC) + continue; + + skb2 = skb_clone(skb, GFP_ATOMIC); + skb2->dev = sdata->dev; + skb2->pkt_type = PACKET_HOST; + + if (in_interrupt()) + netif_rx(skb2); + else + netif_rx_ni(skb2); + } + rcu_read_unlock(); + + skb_push(skb, sizeof(smac_header)); +} + +static const struct net_device_ops mac802154_smac_ops = { + .ndo_open = mac802154_slave_open, + .ndo_stop = mac802154_slave_close, + .ndo_start_xmit = mac802154_smac_xmit, +}; + +void mac802154_smac_setup(struct net_device *dev) +{ + struct mac802154_sub_if_data *priv; + + dev->addr_len = 0; + dev->features = NETIF_F_NO_CSUM; + dev->hard_header_len = 2; + dev->needed_tailroom = 2; /* FCS */ + dev->mtu = 123; /* 127 - 2 (FCS) - 2 (header) */ + dev->tx_queue_len = 10; + dev->type = ARPHRD_SMAC; + dev->flags = IFF_NOARP | IFF_BROADCAST; + dev->watchdog_timeo = 0; + + dev->destructor = free_netdev; + dev->netdev_ops = &mac802154_smac_ops; + dev->ml_priv = &mac802154_mlme_simple; + + priv = netdev_priv(dev); + priv->type = IEEE802154_DEV_SMAC; + + priv->chan = -1; /* not initialized */ + priv->page = 0; /* for compat */ +} + ------------------------------------------------------------------------------ Colocation vs. Managed Hosting A question and answer guide to determining the best fit for your organization - today and in the future. http://p.sf.net/sfu/internap-sfd2d _______________________________________________ Linux-zigbee-devel mailing list Linux-zigbee-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel