1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License version 2
3 * as published by the Free Software Foundation.
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
11 #include <net/6lowpan.h>
12 #include <net/ndisc.h>
13 #include <net/ieee802154_netdev.h>
14 #include <net/mac802154.h>
16 #include "6lowpan_i.h"
18 #define LOWPAN_FRAG1_HEAD_SIZE 0x4
19 #define LOWPAN_FRAGN_HEAD_SIZE 0x5
21 struct lowpan_addr_info
{
22 struct ieee802154_addr daddr
;
23 struct ieee802154_addr saddr
;
27 lowpan_addr_info
*lowpan_skb_priv(const struct sk_buff
*skb
)
29 WARN_ON_ONCE(skb_headroom(skb
) < sizeof(struct lowpan_addr_info
));
30 return (struct lowpan_addr_info
*)(skb
->data
-
31 sizeof(struct lowpan_addr_info
));
34 /* This callback will be called from AF_PACKET and IPv6 stack, the AF_PACKET
35 * sockets gives an 8 byte array for addresses only!
37 * TODO I think AF_PACKET DGRAM (sending/receiving) RAW (sending) makes no
38 * sense here. We should disable it, the right use-case would be AF_INET6
41 int lowpan_header_create(struct sk_buff
*skb
, struct net_device
*ldev
,
42 unsigned short type
, const void *daddr
,
43 const void *saddr
, unsigned int len
)
45 struct wpan_dev
*wpan_dev
= lowpan_802154_dev(ldev
)->wdev
->ieee802154_ptr
;
46 struct lowpan_addr_info
*info
= lowpan_skb_priv(skb
);
47 struct lowpan_802154_neigh
*llneigh
= NULL
;
48 const struct ipv6hdr
*hdr
= ipv6_hdr(skb
);
55 * if this package isn't ipv6 one, where should it be routed?
57 if (type
!= ETH_P_IPV6
)
60 /* intra-pan communication */
61 info
->saddr
.pan_id
= wpan_dev
->pan_id
;
62 info
->daddr
.pan_id
= info
->saddr
.pan_id
;
64 if (!memcmp(daddr
, ldev
->broadcast
, EUI64_ADDR_LEN
)) {
65 info
->daddr
.short_addr
= cpu_to_le16(IEEE802154_ADDR_BROADCAST
);
66 info
->daddr
.mode
= IEEE802154_ADDR_SHORT
;
68 __le16 short_addr
= cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC
);
70 n
= neigh_lookup(&nd_tbl
, &hdr
->daddr
, ldev
);
72 llneigh
= lowpan_802154_neigh(neighbour_priv(n
));
73 read_lock_bh(&n
->lock
);
74 short_addr
= llneigh
->short_addr
;
75 read_unlock_bh(&n
->lock
);
79 lowpan_802154_is_valid_src_short_addr(short_addr
)) {
80 info
->daddr
.short_addr
= short_addr
;
81 info
->daddr
.mode
= IEEE802154_ADDR_SHORT
;
83 info
->daddr
.mode
= IEEE802154_ADDR_LONG
;
84 ieee802154_be64_to_le64(&info
->daddr
.extended_addr
,
93 if (lowpan_802154_is_valid_src_short_addr(wpan_dev
->short_addr
)) {
94 info
->saddr
.mode
= IEEE802154_ADDR_SHORT
;
95 info
->saddr
.short_addr
= wpan_dev
->short_addr
;
97 info
->saddr
.mode
= IEEE802154_ADDR_LONG
;
98 info
->saddr
.extended_addr
= wpan_dev
->extended_addr
;
101 info
->saddr
.mode
= IEEE802154_ADDR_LONG
;
102 ieee802154_be64_to_le64(&info
->saddr
.extended_addr
, saddr
);
108 static struct sk_buff
*
109 lowpan_alloc_frag(struct sk_buff
*skb
, int size
,
110 const struct ieee802154_hdr
*master_hdr
, bool frag1
)
112 struct net_device
*wdev
= lowpan_802154_dev(skb
->dev
)->wdev
;
113 struct sk_buff
*frag
;
116 frag
= alloc_skb(wdev
->needed_headroom
+ wdev
->needed_tailroom
+ size
,
121 frag
->priority
= skb
->priority
;
122 skb_reserve(frag
, wdev
->needed_headroom
);
123 skb_reset_network_header(frag
);
124 *mac_cb(frag
) = *mac_cb(skb
);
127 skb_put_data(frag
, skb_mac_header(skb
), skb
->mac_len
);
129 rc
= wpan_dev_hard_header(frag
, wdev
,
131 &master_hdr
->source
, size
);
138 frag
= ERR_PTR(-ENOMEM
);
145 lowpan_xmit_fragment(struct sk_buff
*skb
, const struct ieee802154_hdr
*wpan_hdr
,
146 u8
*frag_hdr
, int frag_hdrlen
,
147 int offset
, int len
, bool frag1
)
149 struct sk_buff
*frag
;
151 raw_dump_inline(__func__
, " fragment header", frag_hdr
, frag_hdrlen
);
153 frag
= lowpan_alloc_frag(skb
, frag_hdrlen
+ len
, wpan_hdr
, frag1
);
155 return PTR_ERR(frag
);
157 skb_put_data(frag
, frag_hdr
, frag_hdrlen
);
158 skb_put_data(frag
, skb_network_header(skb
) + offset
, len
);
160 raw_dump_table(__func__
, " fragment dump", frag
->data
, frag
->len
);
162 return dev_queue_xmit(frag
);
166 lowpan_xmit_fragmented(struct sk_buff
*skb
, struct net_device
*ldev
,
167 const struct ieee802154_hdr
*wpan_hdr
, u16 dgram_size
,
172 int frag_cap
, frag_len
, payload_cap
, rc
;
173 int skb_unprocessed
, skb_offset
;
175 frag_tag
= htons(lowpan_802154_dev(ldev
)->fragment_tag
);
176 lowpan_802154_dev(ldev
)->fragment_tag
++;
178 frag_hdr
[0] = LOWPAN_DISPATCH_FRAG1
| ((dgram_size
>> 8) & 0x07);
179 frag_hdr
[1] = dgram_size
& 0xff;
180 memcpy(frag_hdr
+ 2, &frag_tag
, sizeof(frag_tag
));
182 payload_cap
= ieee802154_max_payload(wpan_hdr
);
184 frag_len
= round_down(payload_cap
- LOWPAN_FRAG1_HEAD_SIZE
-
185 skb_network_header_len(skb
), 8);
187 skb_offset
= skb_network_header_len(skb
);
188 skb_unprocessed
= skb
->len
- skb
->mac_len
- skb_offset
;
190 rc
= lowpan_xmit_fragment(skb
, wpan_hdr
, frag_hdr
,
191 LOWPAN_FRAG1_HEAD_SIZE
, 0,
192 frag_len
+ skb_network_header_len(skb
),
195 pr_debug("%s unable to send FRAG1 packet (tag: %d)",
196 __func__
, ntohs(frag_tag
));
200 frag_hdr
[0] &= ~LOWPAN_DISPATCH_FRAG1
;
201 frag_hdr
[0] |= LOWPAN_DISPATCH_FRAGN
;
202 frag_cap
= round_down(payload_cap
- LOWPAN_FRAGN_HEAD_SIZE
, 8);
205 dgram_offset
+= frag_len
;
206 skb_offset
+= frag_len
;
207 skb_unprocessed
-= frag_len
;
208 frag_len
= min(frag_cap
, skb_unprocessed
);
210 frag_hdr
[4] = dgram_offset
>> 3;
212 rc
= lowpan_xmit_fragment(skb
, wpan_hdr
, frag_hdr
,
213 LOWPAN_FRAGN_HEAD_SIZE
, skb_offset
,
216 pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
217 __func__
, ntohs(frag_tag
), skb_offset
);
220 } while (skb_unprocessed
> frag_cap
);
222 ldev
->stats
.tx_packets
++;
223 ldev
->stats
.tx_bytes
+= dgram_size
;
225 return NET_XMIT_SUCCESS
;
232 static int lowpan_header(struct sk_buff
*skb
, struct net_device
*ldev
,
233 u16
*dgram_size
, u16
*dgram_offset
)
235 struct wpan_dev
*wpan_dev
= lowpan_802154_dev(ldev
)->wdev
->ieee802154_ptr
;
236 struct ieee802154_mac_cb
*cb
= mac_cb_init(skb
);
237 struct lowpan_addr_info info
;
239 memcpy(&info
, lowpan_skb_priv(skb
), sizeof(info
));
241 *dgram_size
= skb
->len
;
242 lowpan_header_compress(skb
, ldev
, &info
.daddr
, &info
.saddr
);
243 /* dgram_offset = (saved bytes after compression) + lowpan header len */
244 *dgram_offset
= (*dgram_size
- skb
->len
) + skb_network_header_len(skb
);
246 cb
->type
= IEEE802154_FC_TYPE_DATA
;
248 if (info
.daddr
.mode
== IEEE802154_ADDR_SHORT
&&
249 ieee802154_is_broadcast_short_addr(info
.daddr
.short_addr
))
252 cb
->ackreq
= wpan_dev
->ackreq
;
254 return wpan_dev_hard_header(skb
, lowpan_802154_dev(ldev
)->wdev
,
255 &info
.daddr
, &info
.saddr
, 0);
258 netdev_tx_t
lowpan_xmit(struct sk_buff
*skb
, struct net_device
*ldev
)
260 struct ieee802154_hdr wpan_hdr
;
262 u16 dgram_size
, dgram_offset
;
264 pr_debug("package xmit\n");
266 WARN_ON_ONCE(skb
->len
> IPV6_MIN_MTU
);
268 /* We must take a copy of the skb before we modify/replace the ipv6
269 * header as the header could be used elsewhere
271 if (unlikely(skb_headroom(skb
) < ldev
->needed_headroom
||
272 skb_tailroom(skb
) < ldev
->needed_tailroom
)) {
273 struct sk_buff
*nskb
;
275 nskb
= skb_copy_expand(skb
, ldev
->needed_headroom
,
276 ldev
->needed_tailroom
, GFP_ATOMIC
);
282 return NET_XMIT_DROP
;
285 skb
= skb_unshare(skb
, GFP_ATOMIC
);
287 return NET_XMIT_DROP
;
290 ret
= lowpan_header(skb
, ldev
, &dgram_size
, &dgram_offset
);
293 return NET_XMIT_DROP
;
296 if (ieee802154_hdr_peek(skb
, &wpan_hdr
) < 0) {
298 return NET_XMIT_DROP
;
301 max_single
= ieee802154_max_payload(&wpan_hdr
);
303 if (skb_tail_pointer(skb
) - skb_network_header(skb
) <= max_single
) {
304 skb
->dev
= lowpan_802154_dev(ldev
)->wdev
;
305 ldev
->stats
.tx_packets
++;
306 ldev
->stats
.tx_bytes
+= dgram_size
;
307 return dev_queue_xmit(skb
);
311 pr_debug("frame is too big, fragmentation is needed\n");
312 rc
= lowpan_xmit_fragmented(skb
, ldev
, &wpan_hdr
, dgram_size
,
315 return rc
< 0 ? NET_XMIT_DROP
: rc
;