aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 17:54:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 17:54:29 -0400
commitcc998ff8811530be521f6b316f37ab7676a07938 (patch)
treea054b3bf4b2ef406bf756a6cfc9be2f9115f17ae /net/ieee802154
parent57d730924d5cc2c3e280af16a9306587c3a511db (diff)
parent0d40f75bdab241868c0eb6f97aef9f8b3a66f7b3 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: "Noteworthy changes this time around: 1) Multicast rejoin support for team driver, from Jiri Pirko. 2) Centralize and simplify TCP RTT measurement handling in order to reduce the impact of bad RTO seeding from SYN/ACKs. Also, when both timestamps and local RTT measurements are available prefer the later because there are broken middleware devices which scramble the timestamp. From Yuchung Cheng. 3) Add TCP_NOTSENT_LOWAT socket option to limit the amount of kernel memory consumed to queue up unsend user data. From Eric Dumazet. 4) Add a "physical port ID" abstraction for network devices, from Jiri Pirko. 5) Add a "suppress" operation to influence fib_rules lookups, from Stefan Tomanek. 6) Add a networking development FAQ, from Paul Gortmaker. 7) Extend the information provided by tcp_probe and add ipv6 support, from Daniel Borkmann. 8) Use RCU locking more extensively in openvswitch data paths, from Pravin B Shelar. 9) Add SCTP support to openvswitch, from Joe Stringer. 10) Add EF10 chip support to SFC driver, from Ben Hutchings. 11) Add new SYNPROXY netfilter target, from Patrick McHardy. 12) Compute a rate approximation for sending in TCP sockets, and use this to more intelligently coalesce TSO frames. Furthermore, add a new packet scheduler which takes advantage of this estimate when available. From Eric Dumazet. 13) Allow AF_PACKET fanouts with random selection, from Daniel Borkmann. 14) Add ipv6 support to vxlan driver, from Cong Wang" Resolved conflicts as per discussion. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1218 commits) openvswitch: Fix alignment of struct sw_flow_key. netfilter: Fix build errors with xt_socket.c tcp: Add missing braces to do_tcp_setsockopt caif: Add missing braces to multiline if in cfctrl_linkup_request bnx2x: Add missing braces in bnx2x:bnx2x_link_initialize vxlan: Fix kernel panic on device delete. net: mvneta: implement ->ndo_do_ioctl() to support PHY ioctls net: mvneta: properly disable HW PHY polling and ensure adjust_link() works icplus: Use netif_running to determine device state ethernet/arc/arc_emac: Fix huge delays in large file copies tuntap: orphan frags before trying to set tx timestamp tuntap: purge socket error queue on detach qlcnic: use standard NAPI weights ipv6:introduce function to find route for redirect bnx2x: VF RSS support - VF side bnx2x: VF RSS support - PF side vxlan: Notify drivers for listening UDP port changes net: usbnet: update addr_assign_type if appropriate driver/net: enic: update enic maintainers and driver driver/net: enic: Exposing symbols for Cisco's low latency driver ...
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/6lowpan.c286
-rw-r--r--net/ieee802154/6lowpan.h20
2 files changed, 204 insertions, 102 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 3b9d5f20bd1c..c85e71e0c7ff 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -67,39 +67,6 @@ static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
67 67
68static LIST_HEAD(lowpan_devices); 68static LIST_HEAD(lowpan_devices);
69 69
70/*
71 * Uncompression of linklocal:
72 * 0 -> 16 bytes from packet
73 * 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet
74 * 2 -> 2 bytes from prefix - zeroes + 2 from packet
75 * 3 -> 2 bytes from prefix - infer 8 bytes from lladdr
76 *
77 * NOTE: => the uncompress function does change 0xf to 0x10
78 * NOTE: 0x00 => no-autoconfig => unspecified
79 */
80static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
81
82/*
83 * Uncompression of ctx-based:
84 * 0 -> 0 bits from packet [unspecified / reserved]
85 * 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet
86 * 2 -> 8 bytes from prefix - zeroes + 2 from packet
87 * 3 -> 8 bytes from prefix - infer 8 bytes from lladdr
88 */
89static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
90
91/*
92 * Uncompression of ctx-base
93 * 0 -> 0 bits from packet
94 * 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
95 * 2 -> 2 bytes from prefix - zeroes + 3 from packet
96 * 3 -> 2 bytes from prefix - infer 1 bytes from lladdr
97 */
98static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
99
100/* Link local prefix */
101static const u8 lowpan_llprefix[] = {0xfe, 0x80};
102
103/* private device info */ 70/* private device info */
104struct lowpan_dev_info { 71struct lowpan_dev_info {
105 struct net_device *real_dev; /* real WPAN device ptr */ 72 struct net_device *real_dev; /* real WPAN device ptr */
@@ -191,55 +158,177 @@ lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
191 return rol8(val, shift); 158 return rol8(val, shift);
192} 159}
193 160
194static void 161/*
195lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr) 162 * Uncompress address function for source and
163 * destination address(non-multicast).
164 *
165 * address_mode is sam value or dam value.
166 */
167static int
168lowpan_uncompress_addr(struct sk_buff *skb,
169 struct in6_addr *ipaddr,
170 const u8 address_mode,
171 const struct ieee802154_addr *lladdr)
196{ 172{
197 memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ADDR_LEN); 173 bool fail;
198 /* second bit-flip (Universe/Local) is done according RFC2464 */ 174
199 ipaddr->s6_addr[8] ^= 0x02; 175 switch (address_mode) {
176 case LOWPAN_IPHC_ADDR_00:
177 /* for global link addresses */
178 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
179 break;
180 case LOWPAN_IPHC_ADDR_01:
181 /* fe:80::XXXX:XXXX:XXXX:XXXX */
182 ipaddr->s6_addr[0] = 0xFE;
183 ipaddr->s6_addr[1] = 0x80;
184 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
185 break;
186 case LOWPAN_IPHC_ADDR_02:
187 /* fe:80::ff:fe00:XXXX */
188 ipaddr->s6_addr[0] = 0xFE;
189 ipaddr->s6_addr[1] = 0x80;
190 ipaddr->s6_addr[11] = 0xFF;
191 ipaddr->s6_addr[12] = 0xFE;
192 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
193 break;
194 case LOWPAN_IPHC_ADDR_03:
195 fail = false;
196 switch (lladdr->addr_type) {
197 case IEEE802154_ADDR_LONG:
198 /* fe:80::XXXX:XXXX:XXXX:XXXX
199 * \_________________/
200 * hwaddr
201 */
202 ipaddr->s6_addr[0] = 0xFE;
203 ipaddr->s6_addr[1] = 0x80;
204 memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr,
205 IEEE802154_ADDR_LEN);
206 /* second bit-flip (Universe/Local)
207 * is done according RFC2464
208 */
209 ipaddr->s6_addr[8] ^= 0x02;
210 break;
211 case IEEE802154_ADDR_SHORT:
212 /* fe:80::ff:fe00:XXXX
213 * \__/
214 * short_addr
215 *
216 * Universe/Local bit is zero.
217 */
218 ipaddr->s6_addr[0] = 0xFE;
219 ipaddr->s6_addr[1] = 0x80;
220 ipaddr->s6_addr[11] = 0xFF;
221 ipaddr->s6_addr[12] = 0xFE;
222 ipaddr->s6_addr16[7] = htons(lladdr->short_addr);
223 break;
224 default:
225 pr_debug("Invalid addr_type set\n");
226 return -EINVAL;
227 }
228 break;
229 default:
230 pr_debug("Invalid address mode value: 0x%x\n", address_mode);
231 return -EINVAL;
232 }
233
234 if (fail) {
235 pr_debug("Failed to fetch skb data\n");
236 return -EIO;
237 }
238
239 lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n",
240 ipaddr->s6_addr, 16);
241
242 return 0;
200} 243}
201 244
202/* 245/* Uncompress address function for source context
203 * Uncompress addresses based on a prefix and a postfix with zeroes in 246 * based address(non-multicast).
204 * between. If the postfix is zero in length it will use the link address
205 * to configure the IP address (autoconf style).
206 * pref_post_count takes a byte where the first nibble specify prefix count
207 * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
208 */ 247 */
209static int 248static int
210lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr, 249lowpan_uncompress_context_based_src_addr(struct sk_buff *skb,
211 u8 const *prefix, u8 pref_post_count, unsigned char *lladdr) 250 struct in6_addr *ipaddr,
251 const u8 sam)
212{ 252{
213 u8 prefcount = pref_post_count >> 4; 253 switch (sam) {
214 u8 postcount = pref_post_count & 0x0f; 254 case LOWPAN_IPHC_ADDR_00:
215 255 /* unspec address ::
216 /* full nibble 15 => 16 */ 256 * Do nothing, address is already ::
217 prefcount = (prefcount == 15 ? 16 : prefcount); 257 */
218 postcount = (postcount == 15 ? 16 : postcount); 258 break;
219 259 case LOWPAN_IPHC_ADDR_01:
220 if (lladdr) 260 /* TODO */
221 lowpan_raw_dump_inline(__func__, "linklocal address", 261 case LOWPAN_IPHC_ADDR_02:
222 lladdr, IEEE802154_ADDR_LEN); 262 /* TODO */
223 if (prefcount > 0) 263 case LOWPAN_IPHC_ADDR_03:
224 memcpy(ipaddr, prefix, prefcount); 264 /* TODO */
225 265 netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
226 if (prefcount + postcount < 16) 266 return -EINVAL;
227 memset(&ipaddr->s6_addr[prefcount], 0, 267 default:
228 16 - (prefcount + postcount)); 268 pr_debug("Invalid sam value: 0x%x\n", sam);
229 269 return -EINVAL;
230 if (postcount > 0) { 270 }
231 memcpy(&ipaddr->s6_addr[16 - postcount], skb->data, postcount); 271
232 skb_pull(skb, postcount); 272 lowpan_raw_dump_inline(NULL,
233 } else if (prefcount > 0) { 273 "Reconstructed context based ipv6 src addr is:\n",
234 if (lladdr == NULL) 274 ipaddr->s6_addr, 16);
235 return -EINVAL; 275
276 return 0;
277}
236 278
237 /* no IID based configuration if no prefix and no data */ 279/* Uncompress function for multicast destination address,
238 lowpan_uip_ds6_set_addr_iid(ipaddr, lladdr); 280 * when M bit is set.
281 */
282static int
283lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
284 struct in6_addr *ipaddr,
285 const u8 dam)
286{
287 bool fail;
288
289 switch (dam) {
290 case LOWPAN_IPHC_DAM_00:
291 /* 00: 128 bits. The full address
292 * is carried in-line.
293 */
294 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
295 break;
296 case LOWPAN_IPHC_DAM_01:
297 /* 01: 48 bits. The address takes
298 * the form ffXX::00XX:XXXX:XXXX.
299 */
300 ipaddr->s6_addr[0] = 0xFF;
301 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
302 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
303 break;
304 case LOWPAN_IPHC_DAM_10:
305 /* 10: 32 bits. The address takes
306 * the form ffXX::00XX:XXXX.
307 */
308 ipaddr->s6_addr[0] = 0xFF;
309 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
310 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
311 break;
312 case LOWPAN_IPHC_DAM_11:
313 /* 11: 8 bits. The address takes
314 * the form ff02::00XX.
315 */
316 ipaddr->s6_addr[0] = 0xFF;
317 ipaddr->s6_addr[1] = 0x02;
318 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
319 break;
320 default:
321 pr_debug("DAM value has a wrong value: 0x%x\n", dam);
322 return -EINVAL;
323 }
324
325 if (fail) {
326 pr_debug("Failed to fetch skb data\n");
327 return -EIO;
239 } 328 }
240 329
241 pr_debug("uncompressing %d + %d => ", prefcount, postcount); 330 lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n",
242 lowpan_raw_dump_inline(NULL, NULL, ipaddr->s6_addr, 16); 331 ipaddr->s6_addr, 16);
243 332
244 return 0; 333 return 0;
245} 334}
@@ -702,6 +791,12 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
702 skb_reserve(frame->skb, sizeof(struct ipv6hdr)); 791 skb_reserve(frame->skb, sizeof(struct ipv6hdr));
703 skb_put(frame->skb, frame->length); 792 skb_put(frame->skb, frame->length);
704 793
794 /* copy the first control block to keep a
795 * trace of the link-layer addresses in case
796 * of a link-local compressed address
797 */
798 memcpy(frame->skb->cb, skb->cb, sizeof(skb->cb));
799
705 init_timer(&frame->timer); 800 init_timer(&frame->timer);
706 /* time out is the same as for ipv6 - 60 sec */ 801 /* time out is the same as for ipv6 - 60 sec */
707 frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT; 802 frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
@@ -723,9 +818,9 @@ frame_err:
723static int 818static int
724lowpan_process_data(struct sk_buff *skb) 819lowpan_process_data(struct sk_buff *skb)
725{ 820{
726 struct ipv6hdr hdr; 821 struct ipv6hdr hdr = {};
727 u8 tmp, iphc0, iphc1, num_context = 0; 822 u8 tmp, iphc0, iphc1, num_context = 0;
728 u8 *_saddr, *_daddr; 823 const struct ieee802154_addr *_saddr, *_daddr;
729 int err; 824 int err;
730 825
731 lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data, 826 lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
@@ -828,8 +923,8 @@ lowpan_process_data(struct sk_buff *skb)
828 if (lowpan_fetch_skb_u8(skb, &iphc1)) 923 if (lowpan_fetch_skb_u8(skb, &iphc1))
829 goto drop; 924 goto drop;
830 925
831 _saddr = mac_cb(skb)->sa.hwaddr; 926 _saddr = &mac_cb(skb)->sa;
832 _daddr = mac_cb(skb)->da.hwaddr; 927 _daddr = &mac_cb(skb)->da;
833 928
834 pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1); 929 pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1);
835 930
@@ -868,8 +963,6 @@ lowpan_process_data(struct sk_buff *skb)
868 963
869 hdr.priority = ((tmp >> 2) & 0x0f); 964 hdr.priority = ((tmp >> 2) & 0x0f);
870 hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 965 hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
871 hdr.flow_lbl[1] = 0;
872 hdr.flow_lbl[2] = 0;
873 break; 966 break;
874 /* 967 /*
875 * Flow Label carried in-line 968 * Flow Label carried in-line
@@ -885,10 +978,6 @@ lowpan_process_data(struct sk_buff *skb)
885 break; 978 break;
886 /* Traffic Class and Flow Label are elided */ 979 /* Traffic Class and Flow Label are elided */
887 case 3: /* 11b */ 980 case 3: /* 11b */
888 hdr.priority = 0;
889 hdr.flow_lbl[0] = 0;
890 hdr.flow_lbl[1] = 0;
891 hdr.flow_lbl[2] = 0;
892 break; 981 break;
893 default: 982 default:
894 break; 983 break;
@@ -915,10 +1004,18 @@ lowpan_process_data(struct sk_buff *skb)
915 /* Extract SAM to the tmp variable */ 1004 /* Extract SAM to the tmp variable */
916 tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 1005 tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
917 1006
918 /* Source address uncompression */ 1007 if (iphc1 & LOWPAN_IPHC_SAC) {
919 pr_debug("source address stateless compression\n"); 1008 /* Source address context based uncompression */
920 err = lowpan_uncompress_addr(skb, &hdr.saddr, lowpan_llprefix, 1009 pr_debug("SAC bit is set. Handle context based source address.\n");
921 lowpan_unc_llconf[tmp], skb->data); 1010 err = lowpan_uncompress_context_based_src_addr(
1011 skb, &hdr.saddr, tmp);
1012 } else {
1013 /* Source address uncompression */
1014 pr_debug("source address stateless compression\n");
1015 err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
1016 }
1017
1018 /* Check on error of previous branch */
922 if (err) 1019 if (err)
923 goto drop; 1020 goto drop;
924 1021
@@ -931,23 +1028,14 @@ lowpan_process_data(struct sk_buff *skb)
931 pr_debug("dest: context-based mcast compression\n"); 1028 pr_debug("dest: context-based mcast compression\n");
932 /* TODO: implement this */ 1029 /* TODO: implement this */
933 } else { 1030 } else {
934 u8 prefix[] = {0xff, 0x02}; 1031 err = lowpan_uncompress_multicast_daddr(
935 1032 skb, &hdr.daddr, tmp);
936 pr_debug("dest: non context-based mcast compression\n");
937 if (0 < tmp && tmp < 3) {
938 if (lowpan_fetch_skb_u8(skb, &prefix[1]))
939 goto drop;
940 }
941
942 err = lowpan_uncompress_addr(skb, &hdr.daddr, prefix,
943 lowpan_unc_mxconf[tmp], NULL);
944 if (err) 1033 if (err)
945 goto drop; 1034 goto drop;
946 } 1035 }
947 } else { 1036 } else {
948 pr_debug("dest: stateless compression\n"); 1037 pr_debug("dest: stateless compression\n");
949 err = lowpan_uncompress_addr(skb, &hdr.daddr, lowpan_llprefix, 1038 err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
950 lowpan_unc_llconf[tmp], skb->data);
951 if (err) 1039 if (err)
952 goto drop; 1040 goto drop;
953 } 1041 }
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index 4b8f917658b5..2869c0526dad 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -193,10 +193,12 @@
193/* Values of fields within the IPHC encoding second byte */ 193/* Values of fields within the IPHC encoding second byte */
194#define LOWPAN_IPHC_CID 0x80 194#define LOWPAN_IPHC_CID 0x80
195 195
196#define LOWPAN_IPHC_ADDR_00 0x00
197#define LOWPAN_IPHC_ADDR_01 0x01
198#define LOWPAN_IPHC_ADDR_02 0x02
199#define LOWPAN_IPHC_ADDR_03 0x03
200
196#define LOWPAN_IPHC_SAC 0x40 201#define LOWPAN_IPHC_SAC 0x40
197#define LOWPAN_IPHC_SAM_00 0x00
198#define LOWPAN_IPHC_SAM_01 0x10
199#define LOWPAN_IPHC_SAM_10 0x20
200#define LOWPAN_IPHC_SAM 0x30 202#define LOWPAN_IPHC_SAM 0x30
201 203
202#define LOWPAN_IPHC_SAM_BIT 4 204#define LOWPAN_IPHC_SAM_BIT 4
@@ -230,4 +232,16 @@
230 dest = 16 bit inline */ 232 dest = 16 bit inline */
231#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ 233#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
232 234
235static inline bool lowpan_fetch_skb(struct sk_buff *skb,
236 void *data, const unsigned int len)
237{
238 if (unlikely(!pskb_may_pull(skb, len)))
239 return true;
240
241 skb_copy_from_linear_data(skb, data, len);
242 skb_pull(skb, len);
243
244 return false;
245}
246
233#endif /* __6LOWPAN_H__ */ 247#endif /* __6LOWPAN_H__ */