aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/6lowpan.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/6lowpan.h')
-rw-r--r--include/net/6lowpan.h360
1 files changed, 90 insertions, 270 deletions
diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index a2f59ec98d24..cf3bc564ac03 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -56,146 +56,37 @@
56#include <net/ipv6.h> 56#include <net/ipv6.h>
57#include <net/net_namespace.h> 57#include <net/net_namespace.h>
58 58
59#define UIP_802154_SHORTADDR_LEN 2 /* compressed ipv6 address length */ 59#define EUI64_ADDR_LEN 8
60#define UIP_IPH_LEN 40 /* ipv6 fixed header size */
61#define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */
62#define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */
63 60
64/* 61#define LOWPAN_NHC_MAX_ID_LEN 1
65 * ipv6 address based on mac 62/* Maximum next header compression length which we currently support inclusive
66 * second bit-flip (Universe/Local) is done according RFC2464 63 * possible inline data.
67 */ 64 */
68#define is_addr_mac_addr_based(a, m) \ 65#define LOWPAN_NHC_MAX_HDR_LEN (sizeof(struct udphdr))
69 ((((a)->s6_addr[8]) == (((m)[0]) ^ 0x02)) && \ 66/* Max IPHC Header len without IPv6 hdr specific inline data.
70 (((a)->s6_addr[9]) == (m)[1]) && \ 67 * Useful for getting the "extra" bytes we need at worst case compression.
71 (((a)->s6_addr[10]) == (m)[2]) && \ 68 *
72 (((a)->s6_addr[11]) == (m)[3]) && \ 69 * LOWPAN_IPHC + CID + LOWPAN_NHC_MAX_ID_LEN
73 (((a)->s6_addr[12]) == (m)[4]) && \
74 (((a)->s6_addr[13]) == (m)[5]) && \
75 (((a)->s6_addr[14]) == (m)[6]) && \
76 (((a)->s6_addr[15]) == (m)[7]))
77
78/*
79 * check whether we can compress the IID to 16 bits,
80 * it's possible for unicast adresses with first 49 bits are zero only.
81 */
82#define lowpan_is_iid_16_bit_compressable(a) \
83 ((((a)->s6_addr16[4]) == 0) && \
84 (((a)->s6_addr[10]) == 0) && \
85 (((a)->s6_addr[11]) == 0xff) && \
86 (((a)->s6_addr[12]) == 0xfe) && \
87 (((a)->s6_addr[13]) == 0))
88
89/* check whether the 112-bit gid of the multicast address is mappable to: */
90
91/* 48 bits, FFXX::00XX:XXXX:XXXX */
92#define lowpan_is_mcast_addr_compressable48(a) \
93 ((((a)->s6_addr16[1]) == 0) && \
94 (((a)->s6_addr16[2]) == 0) && \
95 (((a)->s6_addr16[3]) == 0) && \
96 (((a)->s6_addr16[4]) == 0) && \
97 (((a)->s6_addr[10]) == 0))
98
99/* 32 bits, FFXX::00XX:XXXX */
100#define lowpan_is_mcast_addr_compressable32(a) \
101 ((((a)->s6_addr16[1]) == 0) && \
102 (((a)->s6_addr16[2]) == 0) && \
103 (((a)->s6_addr16[3]) == 0) && \
104 (((a)->s6_addr16[4]) == 0) && \
105 (((a)->s6_addr16[5]) == 0) && \
106 (((a)->s6_addr[12]) == 0))
107
108/* 8 bits, FF02::00XX */
109#define lowpan_is_mcast_addr_compressable8(a) \
110 ((((a)->s6_addr[1]) == 2) && \
111 (((a)->s6_addr16[1]) == 0) && \
112 (((a)->s6_addr16[2]) == 0) && \
113 (((a)->s6_addr16[3]) == 0) && \
114 (((a)->s6_addr16[4]) == 0) && \
115 (((a)->s6_addr16[5]) == 0) && \
116 (((a)->s6_addr16[6]) == 0) && \
117 (((a)->s6_addr[14]) == 0))
118
119#define lowpan_is_addr_broadcast(a) \
120 ((((a)[0]) == 0xFF) && \
121 (((a)[1]) == 0xFF) && \
122 (((a)[2]) == 0xFF) && \
123 (((a)[3]) == 0xFF) && \
124 (((a)[4]) == 0xFF) && \
125 (((a)[5]) == 0xFF) && \
126 (((a)[6]) == 0xFF) && \
127 (((a)[7]) == 0xFF))
128
129#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
130#define LOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */
131#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
132#define LOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
133#define LOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
134
135#define LOWPAN_DISPATCH_MASK 0xf8 /* 11111000 */
136
137#define LOWPAN_FRAG_TIMEOUT (HZ * 60) /* time-out 60 sec */
138
139#define LOWPAN_FRAG1_HEAD_SIZE 0x4
140#define LOWPAN_FRAGN_HEAD_SIZE 0x5
141
142/*
143 * Values of fields within the IPHC encoding first byte
144 * (C stands for compressed and I for inline)
145 */ 70 */
146#define LOWPAN_IPHC_TF 0x18 71#define LOWPAN_IPHC_MAX_HEADER_LEN (2 + 1 + LOWPAN_NHC_MAX_ID_LEN)
147 72/* Maximum worst case IPHC header buffer size */
148#define LOWPAN_IPHC_FL_C 0x10 73#define LOWPAN_IPHC_MAX_HC_BUF_LEN (sizeof(struct ipv6hdr) + \
149#define LOWPAN_IPHC_TC_C 0x08 74 LOWPAN_IPHC_MAX_HEADER_LEN + \
150#define LOWPAN_IPHC_NH_C 0x04 75 LOWPAN_NHC_MAX_HDR_LEN)
151#define LOWPAN_IPHC_TTL_1 0x01
152#define LOWPAN_IPHC_TTL_64 0x02
153#define LOWPAN_IPHC_TTL_255 0x03
154#define LOWPAN_IPHC_TTL_I 0x00
155
156 76
157/* Values of fields within the IPHC encoding second byte */ 77#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
158#define LOWPAN_IPHC_CID 0x80 78#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
79#define LOWPAN_DISPATCH_IPHC_MASK 0xe0
159 80
160#define LOWPAN_IPHC_ADDR_00 0x00 81static inline bool lowpan_is_ipv6(u8 dispatch)
161#define LOWPAN_IPHC_ADDR_01 0x01 82{
162#define LOWPAN_IPHC_ADDR_02 0x02 83 return dispatch == LOWPAN_DISPATCH_IPV6;
163#define LOWPAN_IPHC_ADDR_03 0x03 84}
164
165#define LOWPAN_IPHC_SAC 0x40
166#define LOWPAN_IPHC_SAM 0x30
167
168#define LOWPAN_IPHC_SAM_BIT 4
169
170#define LOWPAN_IPHC_M 0x08
171#define LOWPAN_IPHC_DAC 0x04
172#define LOWPAN_IPHC_DAM_00 0x00
173#define LOWPAN_IPHC_DAM_01 0x01
174#define LOWPAN_IPHC_DAM_10 0x02
175#define LOWPAN_IPHC_DAM_11 0x03
176
177#define LOWPAN_IPHC_DAM_BIT 0
178/*
179 * LOWPAN_UDP encoding (works together with IPHC)
180 */
181#define LOWPAN_NHC_UDP_MASK 0xF8
182#define LOWPAN_NHC_UDP_ID 0xF0
183#define LOWPAN_NHC_UDP_CHECKSUMC 0x04
184#define LOWPAN_NHC_UDP_CHECKSUMI 0x00
185
186#define LOWPAN_NHC_UDP_4BIT_PORT 0xF0B0
187#define LOWPAN_NHC_UDP_4BIT_MASK 0xFFF0
188#define LOWPAN_NHC_UDP_8BIT_PORT 0xF000
189#define LOWPAN_NHC_UDP_8BIT_MASK 0xFF00
190 85
191/* values for port compression, _with checksum_ ie bit 5 set to 0 */ 86static inline bool lowpan_is_iphc(u8 dispatch)
192#define LOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */ 87{
193#define LOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline, 88 return (dispatch & LOWPAN_DISPATCH_IPHC_MASK) == LOWPAN_DISPATCH_IPHC;
194 dest = 0xF0 + 8 bit inline */ 89}
195#define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline,
196 dest = 16 bit inline */
197#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
198#define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */
199 90
200#define LOWPAN_PRIV_SIZE(llpriv_size) \ 91#define LOWPAN_PRIV_SIZE(llpriv_size) \
201 (sizeof(struct lowpan_priv) + llpriv_size) 92 (sizeof(struct lowpan_priv) + llpriv_size)
@@ -218,10 +109,23 @@ struct lowpan_priv *lowpan_priv(const struct net_device *dev)
218 return netdev_priv(dev); 109 return netdev_priv(dev);
219} 110}
220 111
112struct lowpan_802154_cb {
113 u16 d_tag;
114 unsigned int d_size;
115 u8 d_offset;
116};
117
118static inline
119struct lowpan_802154_cb *lowpan_802154_cb(const struct sk_buff *skb)
120{
121 BUILD_BUG_ON(sizeof(struct lowpan_802154_cb) > sizeof(skb->cb));
122 return (struct lowpan_802154_cb *)skb->cb;
123}
124
221#ifdef DEBUG 125#ifdef DEBUG
222/* print data in line */ 126/* print data in line */
223static inline void raw_dump_inline(const char *caller, char *msg, 127static inline void raw_dump_inline(const char *caller, char *msg,
224 unsigned char *buf, int len) 128 const unsigned char *buf, int len)
225{ 129{
226 if (msg) 130 if (msg)
227 pr_debug("%s():%s: ", caller, msg); 131 pr_debug("%s():%s: ", caller, msg);
@@ -236,7 +140,7 @@ static inline void raw_dump_inline(const char *caller, char *msg,
236 * ... 140 * ...
237 */ 141 */
238static inline void raw_dump_table(const char *caller, char *msg, 142static inline void raw_dump_table(const char *caller, char *msg,
239 unsigned char *buf, int len) 143 const unsigned char *buf, int len)
240{ 144{
241 if (msg) 145 if (msg)
242 pr_debug("%s():%s:\n", caller, msg); 146 pr_debug("%s():%s:\n", caller, msg);
@@ -245,24 +149,25 @@ static inline void raw_dump_table(const char *caller, char *msg,
245} 149}
246#else 150#else
247static inline void raw_dump_table(const char *caller, char *msg, 151static inline void raw_dump_table(const char *caller, char *msg,
248 unsigned char *buf, int len) { } 152 const unsigned char *buf, int len) { }
249static inline void raw_dump_inline(const char *caller, char *msg, 153static inline void raw_dump_inline(const char *caller, char *msg,
250 unsigned char *buf, int len) { } 154 const unsigned char *buf, int len) { }
251#endif 155#endif
252 156
253static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) 157/**
254{ 158 * lowpan_fetch_skb - getting inline data from 6LoWPAN header
255 if (unlikely(!pskb_may_pull(skb, 1))) 159 *
256 return -EINVAL; 160 * This function will pull data from sk buffer and put it into data to
257 161 * remove the 6LoWPAN inline data. This function returns true if the
258 *val = skb->data[0]; 162 * sk buffer is too small to pull the amount of data which is specified
259 skb_pull(skb, 1); 163 * by len.
260 164 *
261 return 0; 165 * @skb: the buffer where the inline data should be pulled from.
262} 166 * @data: destination buffer for the inline data.
263 167 * @len: amount of data which should be pulled in bytes.
264static inline bool lowpan_fetch_skb(struct sk_buff *skb, 168 */
265 void *data, const unsigned int len) 169static inline bool lowpan_fetch_skb(struct sk_buff *skb, void *data,
170 unsigned int len)
266{ 171{
267 if (unlikely(!pskb_may_pull(skb, len))) 172 if (unlikely(!pskb_may_pull(skb, len)))
268 return true; 173 return true;
@@ -280,129 +185,44 @@ static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
280 *hc_ptr += len; 185 *hc_ptr += len;
281} 186}
282 187
283static inline u8 lowpan_addr_mode_size(const u8 addr_mode) 188void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype);
284{
285 static const u8 addr_sizes[] = {
286 [LOWPAN_IPHC_ADDR_00] = 16,
287 [LOWPAN_IPHC_ADDR_01] = 8,
288 [LOWPAN_IPHC_ADDR_02] = 2,
289 [LOWPAN_IPHC_ADDR_03] = 0,
290 };
291 return addr_sizes[addr_mode];
292}
293
294static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header)
295{
296 u8 ret = 1;
297
298 if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
299 *uncomp_header += sizeof(struct udphdr);
300
301 switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
302 case LOWPAN_NHC_UDP_CS_P_00:
303 ret += 4;
304 break;
305 case LOWPAN_NHC_UDP_CS_P_01:
306 case LOWPAN_NHC_UDP_CS_P_10:
307 ret += 3;
308 break;
309 case LOWPAN_NHC_UDP_CS_P_11:
310 ret++;
311 break;
312 default:
313 break;
314 }
315
316 if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
317 ret += 2;
318 }
319
320 return ret;
321}
322 189
323/** 190/**
324 * lowpan_uncompress_size - returns skb->len size with uncompressed header 191 * lowpan_header_decompress - replace 6LoWPAN header with IPv6 header
325 * @skb: sk_buff with 6lowpan header inside
326 * @datagram_offset: optional to get the datagram_offset value
327 * 192 *
328 * Returns the skb->len with uncompressed header 193 * This function replaces the IPHC 6LoWPAN header which should be pointed at
194 * skb->data and skb_network_header, with the IPv6 header.
195 * It would be nice that the caller have the necessary headroom of IPv6 header
196 * and greatest Transport layer header, this would reduce the overhead for
197 * reallocate headroom.
198 *
199 * @skb: the buffer which should be manipulate.
200 * @dev: the lowpan net device pointer.
201 * @daddr: destination lladdr of mac header which is used for compression
202 * methods.
203 * @saddr: source lladdr of mac header which is used for compression
204 * methods.
329 */ 205 */
330static inline u16 206int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
331lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset) 207 const void *daddr, const void *saddr);
332{
333 u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
334 u8 iphc0, iphc1, h_enc;
335
336 iphc0 = skb_network_header(skb)[0];
337 iphc1 = skb_network_header(skb)[1];
338
339 switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
340 case 0:
341 ret += 4;
342 break;
343 case 1:
344 ret += 3;
345 break;
346 case 2:
347 ret++;
348 break;
349 default:
350 break;
351 }
352
353 if (!(iphc0 & LOWPAN_IPHC_NH_C))
354 ret++;
355
356 if (!(iphc0 & 0x03))
357 ret++;
358
359 ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
360 LOWPAN_IPHC_SAM_BIT);
361
362 if (iphc1 & LOWPAN_IPHC_M) {
363 switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
364 LOWPAN_IPHC_DAM_BIT) {
365 case LOWPAN_IPHC_DAM_00:
366 ret += 16;
367 break;
368 case LOWPAN_IPHC_DAM_01:
369 ret += 6;
370 break;
371 case LOWPAN_IPHC_DAM_10:
372 ret += 4;
373 break;
374 case LOWPAN_IPHC_DAM_11:
375 ret++;
376 break;
377 default:
378 break;
379 }
380 } else {
381 ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
382 LOWPAN_IPHC_DAM_BIT);
383 }
384
385 if (iphc0 & LOWPAN_IPHC_NH_C) {
386 h_enc = skb_network_header(skb)[ret];
387 ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
388 }
389 208
390 if (dgram_offset) 209/**
391 *dgram_offset = uncomp_header; 210 * lowpan_header_compress - replace IPv6 header with 6LoWPAN header
392 211 *
393 return skb->len + uncomp_header - ret; 212 * This function replaces the IPv6 header which should be pointed at
394} 213 * skb->data and skb_network_header, with the IPHC 6LoWPAN header.
395 214 * The caller need to be sure that the sk buffer is not shared and at have
396void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype); 215 * at least a headroom which is smaller or equal LOWPAN_IPHC_MAX_HEADER_LEN,
397 216 * which is the IPHC "more bytes than IPv6 header" at worst case.
398int 217 *
399lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, 218 * @skb: the buffer which should be manipulate.
400 const u8 *saddr, const u8 saddr_type, 219 * @dev: the lowpan net device pointer.
401 const u8 saddr_len, const u8 *daddr, 220 * @daddr: destination lladdr of mac header which is used for compression
402 const u8 daddr_type, const u8 daddr_len, 221 * methods.
403 u8 iphc0, u8 iphc1); 222 * @saddr: source lladdr of mac header which is used for compression
404int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 223 * methods.
405 unsigned short type, const void *_daddr, 224 */
406 const void *_saddr, unsigned int len); 225int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
226 const void *daddr, const void *saddr);
407 227
408#endif /* __6LOWPAN_H__ */ 228#endif /* __6LOWPAN_H__ */