---
 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/monitor.c   |  116 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac802154/rx.c        |    1 
 net/mac802154/tx.c        |    2 +
 9 files changed, 131 insertions(+), 2 deletions(-)
 create mode 100644 net/mac802154/monitor.c

diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 6d722f4..9cf4974 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -87,6 +87,7 @@
 #define ARPHRD_IEEE80211_PRISM 802     /* IEEE 802.11 + Prism2 header  */
 #define ARPHRD_IEEE80211_RADIOTAP 803  /* IEEE 802.11 + radiotap header */
 #define ARPHRD_IEEE802154        804
+#define ARPHRD_IEEE802154_MONITOR 805
 
 #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 9daea4a..a367738 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -127,6 +127,7 @@ enum {
 
 enum {
        IEEE802154_DEV_WPAN,
+       IEEE802154_DEV_MONITOR,
        __IEEE802154_DEV_MAX,
 };
 
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 28bd9e8..b0bc4f7 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 wpan.o mac_cmd.o scan.o mib.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
 
 EXTRA_CFLAGS += -Wall -DDEBUG
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index 2015ad7..e86c8ee 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -109,6 +109,9 @@ int mac802154_send_beacon_req(struct net_device *dev);
 
 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_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 76afb17..dfa314f 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -137,6 +137,10 @@ static struct net_device *mac802154_add_iface(struct 
wpan_phy *phy,
                dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
                                name, mac802154_wpan_setup);
                break;
+       case IEEE802154_DEV_MONITOR:
+               dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
+                               name, mac802154_monitor_setup);
+               break;
        default:
                dev = NULL;
                err = -EINVAL;
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index 7698c31..ee8cfa0 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -241,7 +241,8 @@ struct mac802154_priv *mac802154_slave_get_priv(struct 
net_device *dev)
 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);
+       BUG_ON(dev->type != ARPHRD_IEEE802154
+               && dev->type != ARPHRD_IEEE802154_MONITOR);
 
        return to_phy(get_device(&priv->hw->phy->dev));
 }
diff --git a/net/mac802154/monitor.c b/net/mac802154/monitor.c
new file mode 100644
index 0000000..3a24599
--- /dev/null
+++ b/net/mac802154/monitor.c
@@ -0,0 +1,116 @@
+/*
+ * 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:
+ * Dmitry Eremin-Solenikov <dbarysh...@gmail.com>
+ * Sergey Lapin <sla...@ossfans.org>
+ * Maxim Gorbachyov <maxim.gorbac...@siemens.com>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/nl802154.h>
+#include <linux/crc-ccitt.h>
+
+#include <net/mac802154.h>
+#include <net/wpan-phy.h>
+
+#include "mac802154.h"
+
+static netdev_tx_t mac802154_monitor_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);
+
+       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_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb)
+{
+       struct sk_buff *skb2;
+       struct mac802154_sub_if_data *sdata;
+       u16 crc = crc_ccitt(0, skb->data, skb->len);
+       u8 *data;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &priv->slaves, list) {
+               if (sdata->type != IEEE802154_DEV_MONITOR)
+                       continue;
+
+               skb2 = skb_clone(skb, GFP_ATOMIC);
+               skb2->dev = sdata->dev;
+               skb2->pkt_type = PACKET_HOST;
+               data = skb_put(skb2, 2);
+               data[0] = crc & 0xff;
+               data[1] = crc >> 8;
+
+               if (in_interrupt())
+                       netif_rx(skb2);
+               else
+                       netif_rx_ni(skb2);
+       }
+       rcu_read_unlock();
+}
+
+static const struct net_device_ops mac802154_monitor_ops = {
+       .ndo_open               = mac802154_slave_open,
+       .ndo_stop               = mac802154_slave_close,
+       .ndo_start_xmit         = mac802154_monitor_xmit,
+};
+
+void mac802154_monitor_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    = 0;
+       dev->needed_tailroom    = 2; /* FCS */
+       dev->mtu                = 127;
+       dev->tx_queue_len       = 10;
+       dev->type               = ARPHRD_IEEE802154_MONITOR;
+       dev->flags              = IFF_NOARP | IFF_BROADCAST;
+       dev->watchdog_timeo     = 0;
+
+       dev->destructor         = free_netdev;
+       dev->netdev_ops         = &mac802154_monitor_ops;
+       dev->ml_priv            = &mac802154_mlme_simple;
+
+       priv = netdev_priv(dev);
+       priv->type = IEEE802154_DEV_MONITOR;
+
+       priv->chan = -1; /* not initialized */
+       priv->page = 0; /* for compat */
+}
+
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index afb0f54..be05d6c 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -53,6 +53,7 @@ static void mac802154_subif_rx(struct ieee802154_dev *hw, 
struct sk_buff *skb)
                skb_trim(skb, skb->len - 2); /* CRC */
        }
 
+       mac802154_monitors_rx(priv, skb);
        mac802154_wpans_rx(priv, skb);
 
 out:
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 7f6a115..0703195 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -76,6 +76,8 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct 
sk_buff *skb,
                                        (1 << chan))))
                return NETDEV_TX_OK;
 
+       mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
+
        if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
                u16 crc = crc_ccitt(0, skb->data, skb->len);
                u8 *data = skb_put(skb, 2);


------------------------------------------------------------------------------
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

Reply via email to