diff options
Diffstat (limited to 'include/net/6lowpan.h')
-rw-r--r-- | include/net/6lowpan.h | 360 |
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 | 81 | static 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 */ | 86 | static 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 | ||
112 | struct lowpan_802154_cb { | ||
113 | u16 d_tag; | ||
114 | unsigned int d_size; | ||
115 | u8 d_offset; | ||
116 | }; | ||
117 | |||
118 | static inline | ||
119 | struct 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 */ |
223 | static inline void raw_dump_inline(const char *caller, char *msg, | 127 | static 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 | */ |
238 | static inline void raw_dump_table(const char *caller, char *msg, | 142 | static 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 |
247 | static inline void raw_dump_table(const char *caller, char *msg, | 151 | static inline void raw_dump_table(const char *caller, char *msg, |
248 | unsigned char *buf, int len) { } | 152 | const unsigned char *buf, int len) { } |
249 | static inline void raw_dump_inline(const char *caller, char *msg, | 153 | static 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 | ||
253 | static 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. | |
264 | static inline bool lowpan_fetch_skb(struct sk_buff *skb, | 168 | */ |
265 | void *data, const unsigned int len) | 169 | static 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 | ||
283 | static inline u8 lowpan_addr_mode_size(const u8 addr_mode) | 188 | void 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 | |||
294 | static 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 | */ |
330 | static inline u16 | 206 | int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, |
331 | lowpan_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 | |
396 | void 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. | |
398 | int | 217 | * |
399 | lowpan_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 |
404 | int 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); | 225 | int 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__ */ |