aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2015-08-10 15:15:53 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-08-10 14:43:06 -0400
commit51e0e5d8124ece158927a4c2288c0929d3b53aa3 (patch)
treea10d123f0f82fbeaa2c0f4e2c139377b9dd2d40b /net/ieee802154
parent77e867b5f133f6bb3debcfcc75ce4536d644e62e (diff)
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>
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/6lowpan/6lowpan_i.h8
-rw-r--r--net/ieee802154/6lowpan/core.c67
-rw-r--r--net/ieee802154/6lowpan/rx.c38
3 files changed, 27 insertions, 86 deletions
diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
index e50f69da78eb..923b680adb61 100644
--- a/net/ieee802154/6lowpan/6lowpan_i.h
+++ b/net/ieee802154/6lowpan/6lowpan_i.h
@@ -37,15 +37,9 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
37 } 37 }
38} 38}
39 39
40struct lowpan_dev_record {
41 struct net_device *ldev;
42 struct list_head list;
43};
44
45/* private device info */ 40/* private device info */
46struct lowpan_dev_info { 41struct lowpan_dev_info {
47 struct net_device *real_dev; /* real WPAN device ptr */ 42 struct net_device *real_dev; /* real WPAN device ptr */
48 struct mutex dev_list_mtx; /* mutex for list ops */
49 u16 fragment_tag; 43 u16 fragment_tag;
50}; 44};
51 45
@@ -55,8 +49,6 @@ lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
55 return netdev_priv(dev); 49 return netdev_priv(dev);
56} 50}
57 51
58extern struct list_head lowpan_devices;
59
60int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); 52int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type);
61void lowpan_net_frag_exit(void); 53void lowpan_net_frag_exit(void);
62int lowpan_net_frag_init(void); 54int lowpan_net_frag_init(void);
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index f20a387a1011..a4edee8fdc79 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -52,9 +52,6 @@
52 52
53#include "6lowpan_i.h" 53#include "6lowpan_i.h"
54 54
55LIST_HEAD(lowpan_devices);
56static int lowpan_open_count;
57
58static struct header_ops lowpan_header_ops = { 55static struct header_ops lowpan_header_ops = {
59 .create = lowpan_header_create, 56 .create = lowpan_header_create,
60}; 57};
@@ -114,7 +111,6 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
114 struct nlattr *tb[], struct nlattr *data[]) 111 struct nlattr *tb[], struct nlattr *data[])
115{ 112{
116 struct net_device *real_dev; 113 struct net_device *real_dev;
117 struct lowpan_dev_record *entry;
118 int ret; 114 int ret;
119 115
120 ASSERT_RTNL(); 116 ASSERT_RTNL();
@@ -133,31 +129,19 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
133 return -EINVAL; 129 return -EINVAL;
134 } 130 }
135 131
136 lowpan_dev_info(dev)->real_dev = real_dev; 132 if (real_dev->ieee802154_ptr->lowpan_dev) {
137 mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
138
139 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
140 if (!entry) {
141 dev_put(real_dev); 133 dev_put(real_dev);
142 lowpan_dev_info(dev)->real_dev = NULL; 134 return -EBUSY;
143 return -ENOMEM;
144 } 135 }
145 136
146 entry->ldev = dev; 137 lowpan_dev_info(dev)->real_dev = real_dev;
147
148 /* Set the lowpan hardware address to the wpan hardware address. */ 138 /* Set the lowpan hardware address to the wpan hardware address. */
149 memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN); 139 memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
150 140
151 mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
152 INIT_LIST_HEAD(&entry->list);
153 list_add_tail(&entry->list, &lowpan_devices);
154 mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
155
156 ret = register_netdevice(dev); 141 ret = register_netdevice(dev);
157 if (ret >= 0) { 142 if (ret >= 0) {
158 if (!lowpan_open_count) 143 real_dev->ieee802154_ptr->lowpan_dev = dev;
159 lowpan_rx_init(); 144 lowpan_rx_init();
160 lowpan_open_count++;
161 } 145 }
162 146
163 return ret; 147 return ret;
@@ -167,27 +151,12 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
167{ 151{
168 struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev); 152 struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
169 struct net_device *real_dev = lowpan_dev->real_dev; 153 struct net_device *real_dev = lowpan_dev->real_dev;
170 struct lowpan_dev_record *entry, *tmp;
171 154
172 ASSERT_RTNL(); 155 ASSERT_RTNL();
173 156
174 lowpan_open_count--; 157 lowpan_rx_exit();
175 if (!lowpan_open_count) 158 real_dev->ieee802154_ptr->lowpan_dev = NULL;
176 lowpan_rx_exit(); 159 unregister_netdevice(dev);
177
178 mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
179 list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
180 if (entry->ldev == dev) {
181 list_del(&entry->list);
182 kfree(entry);
183 }
184 }
185 mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
186
187 mutex_destroy(&lowpan_dev_info(dev)->dev_list_mtx);
188
189 unregister_netdevice_queue(dev, head);
190
191 dev_put(real_dev); 160 dev_put(real_dev);
192} 161}
193 162
@@ -214,19 +183,21 @@ static int lowpan_device_event(struct notifier_block *unused,
214 unsigned long event, void *ptr) 183 unsigned long event, void *ptr)
215{ 184{
216 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 185 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
217 LIST_HEAD(del_list);
218 struct lowpan_dev_record *entry, *tmp;
219 186
220 if (dev->type != ARPHRD_IEEE802154) 187 if (dev->type != ARPHRD_IEEE802154)
221 goto out; 188 goto out;
222 189
223 if (event == NETDEV_UNREGISTER) { 190 switch (event) {
224 list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) { 191 case NETDEV_UNREGISTER:
225 if (lowpan_dev_info(entry->ldev)->real_dev == dev) 192 /* Check if wpan interface is unregistered that we
226 lowpan_dellink(entry->ldev, &del_list); 193 * also delete possible lowpan interfaces which belongs
227 } 194 * to the wpan interface.
228 195 */
229 unregister_netdevice_many(&del_list); 196 if (dev->ieee802154_ptr && dev->ieee802154_ptr->lowpan_dev)
197 lowpan_dellink(dev->ieee802154_ptr->lowpan_dev, NULL);
198 break;
199 default:
200 break;
230 } 201 }
231 202
232out: 203out:
diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c
index 4be1d289ab2d..d6f5e8ee6fda 100644
--- a/net/ieee802154/6lowpan/rx.c
+++ b/net/ieee802154/6lowpan/rx.c
@@ -15,36 +15,14 @@
15 15
16#include "6lowpan_i.h" 16#include "6lowpan_i.h"
17 17
18static int lowpan_give_skb_to_devices(struct sk_buff *skb, 18static int lowpan_give_skb_to_device(struct sk_buff *skb,
19 struct net_device *dev) 19 struct net_device *dev)
20{ 20{
21 struct lowpan_dev_record *entry; 21 skb->dev = dev->ieee802154_ptr->lowpan_dev;
22 struct sk_buff *skb_cp;
23 int stat = NET_RX_SUCCESS;
24
25 skb->protocol = htons(ETH_P_IPV6); 22 skb->protocol = htons(ETH_P_IPV6);
26 skb->pkt_type = PACKET_HOST; 23 skb->pkt_type = PACKET_HOST;
27 24
28 rcu_read_lock(); 25 return netif_rx(skb);
29 list_for_each_entry_rcu(entry, &lowpan_devices, list)
30 if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
31 skb_cp = skb_copy(skb, GFP_ATOMIC);
32 if (!skb_cp) {
33 kfree_skb(skb);
34 rcu_read_unlock();
35 return NET_RX_DROP;
36 }
37
38 skb_cp->dev = entry->ldev;
39 stat = netif_rx(skb_cp);
40 if (stat == NET_RX_DROP)
41 break;
42 }
43 rcu_read_unlock();
44
45 consume_skb(skb);
46
47 return stat;
48} 26}
49 27
50static int 28static int
@@ -109,7 +87,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
109 if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { 87 if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
110 /* Pull off the 1-byte of 6lowpan header. */ 88 /* Pull off the 1-byte of 6lowpan header. */
111 skb_pull(skb, 1); 89 skb_pull(skb, 1);
112 return lowpan_give_skb_to_devices(skb, NULL); 90 return lowpan_give_skb_to_device(skb, dev);
113 } else { 91 } else {
114 switch (skb->data[0] & 0xe0) { 92 switch (skb->data[0] & 0xe0) {
115 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ 93 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
@@ -117,7 +95,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
117 if (ret < 0) 95 if (ret < 0)
118 goto drop_skb; 96 goto drop_skb;
119 97
120 return lowpan_give_skb_to_devices(skb, NULL); 98 return lowpan_give_skb_to_device(skb, dev);
121 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ 99 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
122 ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1); 100 ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
123 if (ret == 1) { 101 if (ret == 1) {
@@ -125,7 +103,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
125 if (ret < 0) 103 if (ret < 0)
126 goto drop_skb; 104 goto drop_skb;
127 105
128 return lowpan_give_skb_to_devices(skb, NULL); 106 return lowpan_give_skb_to_device(skb, dev);
129 } else if (ret == -1) { 107 } else if (ret == -1) {
130 return NET_RX_DROP; 108 return NET_RX_DROP;
131 } else { 109 } else {
@@ -138,7 +116,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
138 if (ret < 0) 116 if (ret < 0)
139 goto drop_skb; 117 goto drop_skb;
140 118
141 return lowpan_give_skb_to_devices(skb, NULL); 119 return lowpan_give_skb_to_device(skb, dev);
142 } else if (ret == -1) { 120 } else if (ret == -1) {
143 return NET_RX_DROP; 121 return NET_RX_DROP;
144 } else { 122 } else {