ieee802154: 6lowpan: remove multiple lowpan per wpan support
We currently supports multiple lowpan interfaces per wpan interface. I never saw any use case into such functionality. We drop this feature now because it's much easier do deal with address changes inside the under laying wpan interface. This patch removes the multiple lowpan interface and adds a lowpan_dev netdev pointer into the wpan_dev, if this pointer isn't null the wpan interface belongs to the assigned lowpan interface. Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com> Tested-by: Stefan Schmidt <stefan@osg.samsung.com> Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Родитель
77e867b5f1
Коммит
51e0e5d812
|
@ -173,6 +173,9 @@ struct wpan_dev {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
|
|
||||||
|
/* lowpan interface, set when the wpan_dev belongs to one lowpan_dev */
|
||||||
|
struct net_device *lowpan_dev;
|
||||||
|
|
||||||
u32 identifier;
|
u32 identifier;
|
||||||
|
|
||||||
/* MAC PIB */
|
/* MAC PIB */
|
||||||
|
|
|
@ -37,15 +37,9 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct lowpan_dev_record {
|
|
||||||
struct net_device *ldev;
|
|
||||||
struct list_head list;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* private device info */
|
/* private device info */
|
||||||
struct lowpan_dev_info {
|
struct lowpan_dev_info {
|
||||||
struct net_device *real_dev; /* real WPAN device ptr */
|
struct net_device *real_dev; /* real WPAN device ptr */
|
||||||
struct mutex dev_list_mtx; /* mutex for list ops */
|
|
||||||
u16 fragment_tag;
|
u16 fragment_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,8 +49,6 @@ lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
|
||||||
return netdev_priv(dev);
|
return netdev_priv(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct list_head lowpan_devices;
|
|
||||||
|
|
||||||
int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type);
|
int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type);
|
||||||
void lowpan_net_frag_exit(void);
|
void lowpan_net_frag_exit(void);
|
||||||
int lowpan_net_frag_init(void);
|
int lowpan_net_frag_init(void);
|
||||||
|
|
|
@ -52,9 +52,6 @@
|
||||||
|
|
||||||
#include "6lowpan_i.h"
|
#include "6lowpan_i.h"
|
||||||
|
|
||||||
LIST_HEAD(lowpan_devices);
|
|
||||||
static int lowpan_open_count;
|
|
||||||
|
|
||||||
static struct header_ops lowpan_header_ops = {
|
static struct header_ops lowpan_header_ops = {
|
||||||
.create = lowpan_header_create,
|
.create = lowpan_header_create,
|
||||||
};
|
};
|
||||||
|
@ -114,7 +111,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
|
||||||
struct nlattr *tb[], struct nlattr *data[])
|
struct nlattr *tb[], struct nlattr *data[])
|
||||||
{
|
{
|
||||||
struct net_device *real_dev;
|
struct net_device *real_dev;
|
||||||
struct lowpan_dev_record *entry;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
@ -133,31 +129,19 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lowpan_dev_info(dev)->real_dev = real_dev;
|
if (real_dev->ieee802154_ptr->lowpan_dev) {
|
||||||
mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
|
|
||||||
|
|
||||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
|
||||||
if (!entry) {
|
|
||||||
dev_put(real_dev);
|
dev_put(real_dev);
|
||||||
lowpan_dev_info(dev)->real_dev = NULL;
|
return -EBUSY;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->ldev = dev;
|
lowpan_dev_info(dev)->real_dev = real_dev;
|
||||||
|
|
||||||
/* Set the lowpan hardware address to the wpan hardware address. */
|
/* Set the lowpan hardware address to the wpan hardware address. */
|
||||||
memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
|
memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
|
||||||
|
|
||||||
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
|
|
||||||
INIT_LIST_HEAD(&entry->list);
|
|
||||||
list_add_tail(&entry->list, &lowpan_devices);
|
|
||||||
mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
|
|
||||||
|
|
||||||
ret = register_netdevice(dev);
|
ret = register_netdevice(dev);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (!lowpan_open_count)
|
real_dev->ieee802154_ptr->lowpan_dev = dev;
|
||||||
lowpan_rx_init();
|
lowpan_rx_init();
|
||||||
lowpan_open_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -167,27 +151,12 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
|
||||||
{
|
{
|
||||||
struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
|
struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
|
||||||
struct net_device *real_dev = lowpan_dev->real_dev;
|
struct net_device *real_dev = lowpan_dev->real_dev;
|
||||||
struct lowpan_dev_record *entry, *tmp;
|
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
lowpan_open_count--;
|
|
||||||
if (!lowpan_open_count)
|
|
||||||
lowpan_rx_exit();
|
lowpan_rx_exit();
|
||||||
|
real_dev->ieee802154_ptr->lowpan_dev = NULL;
|
||||||
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
|
unregister_netdevice(dev);
|
||||||
list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
|
|
||||||
if (entry->ldev == dev) {
|
|
||||||
list_del(&entry->list);
|
|
||||||
kfree(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
|
|
||||||
|
|
||||||
mutex_destroy(&lowpan_dev_info(dev)->dev_list_mtx);
|
|
||||||
|
|
||||||
unregister_netdevice_queue(dev, head);
|
|
||||||
|
|
||||||
dev_put(real_dev);
|
dev_put(real_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,19 +183,21 @@ static int lowpan_device_event(struct notifier_block *unused,
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
{
|
{
|
||||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||||
LIST_HEAD(del_list);
|
|
||||||
struct lowpan_dev_record *entry, *tmp;
|
|
||||||
|
|
||||||
if (dev->type != ARPHRD_IEEE802154)
|
if (dev->type != ARPHRD_IEEE802154)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (event == NETDEV_UNREGISTER) {
|
switch (event) {
|
||||||
list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
|
case NETDEV_UNREGISTER:
|
||||||
if (lowpan_dev_info(entry->ldev)->real_dev == dev)
|
/* Check if wpan interface is unregistered that we
|
||||||
lowpan_dellink(entry->ldev, &del_list);
|
* also delete possible lowpan interfaces which belongs
|
||||||
}
|
* to the wpan interface.
|
||||||
|
*/
|
||||||
unregister_netdevice_many(&del_list);
|
if (dev->ieee802154_ptr && dev->ieee802154_ptr->lowpan_dev)
|
||||||
|
lowpan_dellink(dev->ieee802154_ptr->lowpan_dev, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -15,36 +15,14 @@
|
||||||
|
|
||||||
#include "6lowpan_i.h"
|
#include "6lowpan_i.h"
|
||||||
|
|
||||||
static int lowpan_give_skb_to_devices(struct sk_buff *skb,
|
static int lowpan_give_skb_to_device(struct sk_buff *skb,
|
||||||
struct net_device *dev)
|
struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct lowpan_dev_record *entry;
|
skb->dev = dev->ieee802154_ptr->lowpan_dev;
|
||||||
struct sk_buff *skb_cp;
|
|
||||||
int stat = NET_RX_SUCCESS;
|
|
||||||
|
|
||||||
skb->protocol = htons(ETH_P_IPV6);
|
skb->protocol = htons(ETH_P_IPV6);
|
||||||
skb->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
|
||||||
rcu_read_lock();
|
return netif_rx(skb);
|
||||||
list_for_each_entry_rcu(entry, &lowpan_devices, list)
|
|
||||||
if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
|
|
||||||
skb_cp = skb_copy(skb, GFP_ATOMIC);
|
|
||||||
if (!skb_cp) {
|
|
||||||
kfree_skb(skb);
|
|
||||||
rcu_read_unlock();
|
|
||||||
return NET_RX_DROP;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_cp->dev = entry->ldev;
|
|
||||||
stat = netif_rx(skb_cp);
|
|
||||||
if (stat == NET_RX_DROP)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
consume_skb(skb);
|
|
||||||
|
|
||||||
return stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -109,7 +87,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||||
if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
|
if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
|
||||||
/* Pull off the 1-byte of 6lowpan header. */
|
/* Pull off the 1-byte of 6lowpan header. */
|
||||||
skb_pull(skb, 1);
|
skb_pull(skb, 1);
|
||||||
return lowpan_give_skb_to_devices(skb, NULL);
|
return lowpan_give_skb_to_device(skb, dev);
|
||||||
} else {
|
} else {
|
||||||
switch (skb->data[0] & 0xe0) {
|
switch (skb->data[0] & 0xe0) {
|
||||||
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
|
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
|
||||||
|
@ -117,7 +95,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto drop_skb;
|
goto drop_skb;
|
||||||
|
|
||||||
return lowpan_give_skb_to_devices(skb, NULL);
|
return lowpan_give_skb_to_device(skb, dev);
|
||||||
case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
|
case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
|
||||||
ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
|
ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
|
@ -125,7 +103,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto drop_skb;
|
goto drop_skb;
|
||||||
|
|
||||||
return lowpan_give_skb_to_devices(skb, NULL);
|
return lowpan_give_skb_to_device(skb, dev);
|
||||||
} else if (ret == -1) {
|
} else if (ret == -1) {
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,7 +116,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto drop_skb;
|
goto drop_skb;
|
||||||
|
|
||||||
return lowpan_give_skb_to_devices(skb, NULL);
|
return lowpan_give_skb_to_device(skb, dev);
|
||||||
} else if (ret == -1) {
|
} else if (ret == -1) {
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
} else {
|
} else {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче