1 /*
2  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
3  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 #include <linux/errno.h>
35 #include <linux/string.h>
36 #include <linux/export.h>
37 #include <linux/if_ether.h>
38 #include <linux/ip.h>
39 
40 #include <rdma/ib_pack.h>
41 
42 #define STRUCT_FIELD(header, field) \
43 	.struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field),      \
44 	.struct_size_bytes   = sizeof ((struct ib_unpacked_ ## header *) 0)->field, \
45 	.field_name          = #header ":" #field
46 
47 static const struct ib_field lrh_table[]  = {
48 	{ STRUCT_FIELD(lrh, virtual_lane),
49 	  .offset_words = 0,
50 	  .offset_bits  = 0,
51 	  .size_bits    = 4 },
52 	{ STRUCT_FIELD(lrh, link_version),
53 	  .offset_words = 0,
54 	  .offset_bits  = 4,
55 	  .size_bits    = 4 },
56 	{ STRUCT_FIELD(lrh, service_level),
57 	  .offset_words = 0,
58 	  .offset_bits  = 8,
59 	  .size_bits    = 4 },
60 	{ RESERVED,
61 	  .offset_words = 0,
62 	  .offset_bits  = 12,
63 	  .size_bits    = 2 },
64 	{ STRUCT_FIELD(lrh, link_next_header),
65 	  .offset_words = 0,
66 	  .offset_bits  = 14,
67 	  .size_bits    = 2 },
68 	{ STRUCT_FIELD(lrh, destination_lid),
69 	  .offset_words = 0,
70 	  .offset_bits  = 16,
71 	  .size_bits    = 16 },
72 	{ RESERVED,
73 	  .offset_words = 1,
74 	  .offset_bits  = 0,
75 	  .size_bits    = 5 },
76 	{ STRUCT_FIELD(lrh, packet_length),
77 	  .offset_words = 1,
78 	  .offset_bits  = 5,
79 	  .size_bits    = 11 },
80 	{ STRUCT_FIELD(lrh, source_lid),
81 	  .offset_words = 1,
82 	  .offset_bits  = 16,
83 	  .size_bits    = 16 }
84 };
85 
86 static const struct ib_field eth_table[]  = {
87 	{ STRUCT_FIELD(eth, dmac_h),
88 	  .offset_words = 0,
89 	  .offset_bits  = 0,
90 	  .size_bits    = 32 },
91 	{ STRUCT_FIELD(eth, dmac_l),
92 	  .offset_words = 1,
93 	  .offset_bits  = 0,
94 	  .size_bits    = 16 },
95 	{ STRUCT_FIELD(eth, smac_h),
96 	  .offset_words = 1,
97 	  .offset_bits  = 16,
98 	  .size_bits    = 16 },
99 	{ STRUCT_FIELD(eth, smac_l),
100 	  .offset_words = 2,
101 	  .offset_bits  = 0,
102 	  .size_bits    = 32 },
103 	{ STRUCT_FIELD(eth, type),
104 	  .offset_words = 3,
105 	  .offset_bits  = 0,
106 	  .size_bits    = 16 }
107 };
108 
109 static const struct ib_field vlan_table[]  = {
110 	{ STRUCT_FIELD(vlan, tag),
111 	  .offset_words = 0,
112 	  .offset_bits  = 0,
113 	  .size_bits    = 16 },
114 	{ STRUCT_FIELD(vlan, type),
115 	  .offset_words = 0,
116 	  .offset_bits  = 16,
117 	  .size_bits    = 16 }
118 };
119 
120 static const struct ib_field ip4_table[]  = {
121 	{ STRUCT_FIELD(ip4, ver),
122 	  .offset_words = 0,
123 	  .offset_bits  = 0,
124 	  .size_bits    = 4 },
125 	{ STRUCT_FIELD(ip4, hdr_len),
126 	  .offset_words = 0,
127 	  .offset_bits  = 4,
128 	  .size_bits    = 4 },
129 	{ STRUCT_FIELD(ip4, tos),
130 	  .offset_words = 0,
131 	  .offset_bits  = 8,
132 	  .size_bits    = 8 },
133 	{ STRUCT_FIELD(ip4, tot_len),
134 	  .offset_words = 0,
135 	  .offset_bits  = 16,
136 	  .size_bits    = 16 },
137 	{ STRUCT_FIELD(ip4, id),
138 	  .offset_words = 1,
139 	  .offset_bits  = 0,
140 	  .size_bits    = 16 },
141 	{ STRUCT_FIELD(ip4, frag_off),
142 	  .offset_words = 1,
143 	  .offset_bits  = 16,
144 	  .size_bits    = 16 },
145 	{ STRUCT_FIELD(ip4, ttl),
146 	  .offset_words = 2,
147 	  .offset_bits  = 0,
148 	  .size_bits    = 8 },
149 	{ STRUCT_FIELD(ip4, protocol),
150 	  .offset_words = 2,
151 	  .offset_bits  = 8,
152 	  .size_bits    = 8 },
153 	{ STRUCT_FIELD(ip4, check),
154 	  .offset_words = 2,
155 	  .offset_bits  = 16,
156 	  .size_bits    = 16 },
157 	{ STRUCT_FIELD(ip4, saddr),
158 	  .offset_words = 3,
159 	  .offset_bits  = 0,
160 	  .size_bits    = 32 },
161 	{ STRUCT_FIELD(ip4, daddr),
162 	  .offset_words = 4,
163 	  .offset_bits  = 0,
164 	  .size_bits    = 32 }
165 };
166 
167 static const struct ib_field udp_table[]  = {
168 	{ STRUCT_FIELD(udp, sport),
169 	  .offset_words = 0,
170 	  .offset_bits  = 0,
171 	  .size_bits    = 16 },
172 	{ STRUCT_FIELD(udp, dport),
173 	  .offset_words = 0,
174 	  .offset_bits  = 16,
175 	  .size_bits    = 16 },
176 	{ STRUCT_FIELD(udp, length),
177 	  .offset_words = 1,
178 	  .offset_bits  = 0,
179 	  .size_bits    = 16 },
180 	{ STRUCT_FIELD(udp, csum),
181 	  .offset_words = 1,
182 	  .offset_bits  = 16,
183 	  .size_bits    = 16 }
184 };
185 
186 static const struct ib_field grh_table[]  = {
187 	{ STRUCT_FIELD(grh, ip_version),
188 	  .offset_words = 0,
189 	  .offset_bits  = 0,
190 	  .size_bits    = 4 },
191 	{ STRUCT_FIELD(grh, traffic_class),
192 	  .offset_words = 0,
193 	  .offset_bits  = 4,
194 	  .size_bits    = 8 },
195 	{ STRUCT_FIELD(grh, flow_label),
196 	  .offset_words = 0,
197 	  .offset_bits  = 12,
198 	  .size_bits    = 20 },
199 	{ STRUCT_FIELD(grh, payload_length),
200 	  .offset_words = 1,
201 	  .offset_bits  = 0,
202 	  .size_bits    = 16 },
203 	{ STRUCT_FIELD(grh, next_header),
204 	  .offset_words = 1,
205 	  .offset_bits  = 16,
206 	  .size_bits    = 8 },
207 	{ STRUCT_FIELD(grh, hop_limit),
208 	  .offset_words = 1,
209 	  .offset_bits  = 24,
210 	  .size_bits    = 8 },
211 	{ STRUCT_FIELD(grh, source_gid),
212 	  .offset_words = 2,
213 	  .offset_bits  = 0,
214 	  .size_bits    = 128 },
215 	{ STRUCT_FIELD(grh, destination_gid),
216 	  .offset_words = 6,
217 	  .offset_bits  = 0,
218 	  .size_bits    = 128 }
219 };
220 
221 static const struct ib_field bth_table[]  = {
222 	{ STRUCT_FIELD(bth, opcode),
223 	  .offset_words = 0,
224 	  .offset_bits  = 0,
225 	  .size_bits    = 8 },
226 	{ STRUCT_FIELD(bth, solicited_event),
227 	  .offset_words = 0,
228 	  .offset_bits  = 8,
229 	  .size_bits    = 1 },
230 	{ STRUCT_FIELD(bth, mig_req),
231 	  .offset_words = 0,
232 	  .offset_bits  = 9,
233 	  .size_bits    = 1 },
234 	{ STRUCT_FIELD(bth, pad_count),
235 	  .offset_words = 0,
236 	  .offset_bits  = 10,
237 	  .size_bits    = 2 },
238 	{ STRUCT_FIELD(bth, transport_header_version),
239 	  .offset_words = 0,
240 	  .offset_bits  = 12,
241 	  .size_bits    = 4 },
242 	{ STRUCT_FIELD(bth, pkey),
243 	  .offset_words = 0,
244 	  .offset_bits  = 16,
245 	  .size_bits    = 16 },
246 	{ RESERVED,
247 	  .offset_words = 1,
248 	  .offset_bits  = 0,
249 	  .size_bits    = 8 },
250 	{ STRUCT_FIELD(bth, destination_qpn),
251 	  .offset_words = 1,
252 	  .offset_bits  = 8,
253 	  .size_bits    = 24 },
254 	{ STRUCT_FIELD(bth, ack_req),
255 	  .offset_words = 2,
256 	  .offset_bits  = 0,
257 	  .size_bits    = 1 },
258 	{ RESERVED,
259 	  .offset_words = 2,
260 	  .offset_bits  = 1,
261 	  .size_bits    = 7 },
262 	{ STRUCT_FIELD(bth, psn),
263 	  .offset_words = 2,
264 	  .offset_bits  = 8,
265 	  .size_bits    = 24 }
266 };
267 
268 static const struct ib_field deth_table[] = {
269 	{ STRUCT_FIELD(deth, qkey),
270 	  .offset_words = 0,
271 	  .offset_bits  = 0,
272 	  .size_bits    = 32 },
273 	{ RESERVED,
274 	  .offset_words = 1,
275 	  .offset_bits  = 0,
276 	  .size_bits    = 8 },
277 	{ STRUCT_FIELD(deth, source_qpn),
278 	  .offset_words = 1,
279 	  .offset_bits  = 8,
280 	  .size_bits    = 24 }
281 };
282 
283 __sum16 ib_ud_ip4_csum(struct ib_ud_header *header)
284 {
285 	struct iphdr iph;
286 
287 	iph.ihl		= 5;
288 	iph.version	= 4;
289 	iph.tos		= header->ip4.tos;
290 	iph.tot_len	= header->ip4.tot_len;
291 	iph.id		= header->ip4.id;
292 	iph.frag_off	= header->ip4.frag_off;
293 	iph.ttl		= header->ip4.ttl;
294 	iph.protocol	= header->ip4.protocol;
295 	iph.check	= 0;
296 	iph.saddr	= header->ip4.saddr;
297 	iph.daddr	= header->ip4.daddr;
298 
299 	return ip_fast_csum((u8 *)&iph, iph.ihl);
300 }
301 EXPORT_SYMBOL(ib_ud_ip4_csum);
302 
303 /**
304  * ib_ud_header_init - Initialize UD header structure
305  * @payload_bytes:Length of packet payload
306  * @lrh_present: specify if LRH is present
307  * @eth_present: specify if Eth header is present
308  * @vlan_present: packet is tagged vlan
309  * @grh_present: GRH flag (if non-zero, GRH will be included)
310  * @ip_version: if non-zero, IP header, V4 or V6, will be included
311  * @udp_present :if non-zero, UDP header will be included
312  * @immediate_present: specify if immediate data is present
313  * @header:Structure to initialize
314  */
315 int ib_ud_header_init(int     payload_bytes,
316 		      int    lrh_present,
317 		      int    eth_present,
318 		      int    vlan_present,
319 		      int    grh_present,
320 		      int    ip_version,
321 		      int    udp_present,
322 		      int    immediate_present,
323 		      struct ib_ud_header *header)
324 {
325 	grh_present = grh_present && !ip_version;
326 	memset(header, 0, sizeof *header);
327 
328 	/*
329 	 * UDP header without IP header doesn't make sense
330 	 */
331 	if (udp_present && ip_version != 4 && ip_version != 6)
332 		return -EINVAL;
333 
334 	if (lrh_present) {
335 		u16 packet_length;
336 
337 		header->lrh.link_version     = 0;
338 		header->lrh.link_next_header =
339 			grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
340 		packet_length = (IB_LRH_BYTES	+
341 				 IB_BTH_BYTES	+
342 				 IB_DETH_BYTES	+
343 				 (grh_present ? IB_GRH_BYTES : 0) +
344 				 payload_bytes	+
345 				 4		+ /* ICRC     */
346 				 3) / 4;	  /* round up */
347 		header->lrh.packet_length = cpu_to_be16(packet_length);
348 	}
349 
350 	if (vlan_present)
351 		header->eth.type = cpu_to_be16(ETH_P_8021Q);
352 
353 	if (ip_version == 6 || grh_present) {
354 		header->grh.ip_version      = 6;
355 		header->grh.payload_length  =
356 			cpu_to_be16((IB_BTH_BYTES     +
357 				     IB_DETH_BYTES    +
358 				     payload_bytes    +
359 				     4                + /* ICRC     */
360 				     3) & ~3);          /* round up */
361 		header->grh.next_header     = udp_present ? IPPROTO_UDP : 0x1b;
362 	}
363 
364 	if (ip_version == 4) {
365 		int udp_bytes = udp_present ? IB_UDP_BYTES : 0;
366 
367 		header->ip4.ver = 4; /* version 4 */
368 		header->ip4.hdr_len = 5; /* 5 words */
369 		header->ip4.tot_len =
370 			cpu_to_be16(IB_IP4_BYTES   +
371 				     udp_bytes     +
372 				     IB_BTH_BYTES  +
373 				     IB_DETH_BYTES +
374 				     payload_bytes +
375 				     4);     /* ICRC     */
376 		header->ip4.protocol = IPPROTO_UDP;
377 	}
378 	if (udp_present && ip_version)
379 		header->udp.length =
380 			cpu_to_be16(IB_UDP_BYTES   +
381 				     IB_BTH_BYTES  +
382 				     IB_DETH_BYTES +
383 				     payload_bytes +
384 				     4);     /* ICRC     */
385 
386 	if (immediate_present)
387 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
388 	else
389 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY;
390 	header->bth.pad_count                = (4 - payload_bytes) & 3;
391 	header->bth.transport_header_version = 0;
392 
393 	header->lrh_present = lrh_present;
394 	header->eth_present = eth_present;
395 	header->vlan_present = vlan_present;
396 	header->grh_present = grh_present || (ip_version == 6);
397 	header->ipv4_present = ip_version == 4;
398 	header->udp_present = udp_present;
399 	header->immediate_present = immediate_present;
400 	return 0;
401 }
402 EXPORT_SYMBOL(ib_ud_header_init);
403 
404 /**
405  * ib_ud_header_pack - Pack UD header struct into wire format
406  * @header:UD header struct
407  * @buf:Buffer to pack into
408  *
409  * ib_ud_header_pack() packs the UD header structure @header into wire
410  * format in the buffer @buf.
411  */
412 int ib_ud_header_pack(struct ib_ud_header *header,
413 		      void                *buf)
414 {
415 	int len = 0;
416 
417 	if (header->lrh_present) {
418 		ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
419 			&header->lrh, buf + len);
420 		len += IB_LRH_BYTES;
421 	}
422 	if (header->eth_present) {
423 		ib_pack(eth_table, ARRAY_SIZE(eth_table),
424 			&header->eth, buf + len);
425 		len += IB_ETH_BYTES;
426 	}
427 	if (header->vlan_present) {
428 		ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
429 			&header->vlan, buf + len);
430 		len += IB_VLAN_BYTES;
431 	}
432 	if (header->grh_present) {
433 		ib_pack(grh_table, ARRAY_SIZE(grh_table),
434 			&header->grh, buf + len);
435 		len += IB_GRH_BYTES;
436 	}
437 	if (header->ipv4_present) {
438 		ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
439 			&header->ip4, buf + len);
440 		len += IB_IP4_BYTES;
441 	}
442 	if (header->udp_present) {
443 		ib_pack(udp_table, ARRAY_SIZE(udp_table),
444 			&header->udp, buf + len);
445 		len += IB_UDP_BYTES;
446 	}
447 
448 	ib_pack(bth_table, ARRAY_SIZE(bth_table),
449 		&header->bth, buf + len);
450 	len += IB_BTH_BYTES;
451 
452 	ib_pack(deth_table, ARRAY_SIZE(deth_table),
453 		&header->deth, buf + len);
454 	len += IB_DETH_BYTES;
455 
456 	if (header->immediate_present) {
457 		memcpy(buf + len, &header->immediate_data, sizeof header->immediate_data);
458 		len += sizeof header->immediate_data;
459 	}
460 
461 	return len;
462 }
463 EXPORT_SYMBOL(ib_ud_header_pack);
464 
465 /**
466  * ib_ud_header_unpack - Unpack UD header struct from wire format
467  * @header:UD header struct
468  * @buf:Buffer to pack into
469  *
470  * ib_ud_header_pack() unpacks the UD header structure @header from wire
471  * format in the buffer @buf.
472  */
473 int ib_ud_header_unpack(void                *buf,
474 			struct ib_ud_header *header)
475 {
476 	ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
477 		  buf, &header->lrh);
478 	buf += IB_LRH_BYTES;
479 
480 	if (header->lrh.link_version != 0) {
481 		printk(KERN_WARNING "Invalid LRH.link_version %d\n",
482 		       header->lrh.link_version);
483 		return -EINVAL;
484 	}
485 
486 	switch (header->lrh.link_next_header) {
487 	case IB_LNH_IBA_LOCAL:
488 		header->grh_present = 0;
489 		break;
490 
491 	case IB_LNH_IBA_GLOBAL:
492 		header->grh_present = 1;
493 		ib_unpack(grh_table, ARRAY_SIZE(grh_table),
494 			  buf, &header->grh);
495 		buf += IB_GRH_BYTES;
496 
497 		if (header->grh.ip_version != 6) {
498 			printk(KERN_WARNING "Invalid GRH.ip_version %d\n",
499 			       header->grh.ip_version);
500 			return -EINVAL;
501 		}
502 		if (header->grh.next_header != 0x1b) {
503 			printk(KERN_WARNING "Invalid GRH.next_header 0x%02x\n",
504 			       header->grh.next_header);
505 			return -EINVAL;
506 		}
507 		break;
508 
509 	default:
510 		printk(KERN_WARNING "Invalid LRH.link_next_header %d\n",
511 		       header->lrh.link_next_header);
512 		return -EINVAL;
513 	}
514 
515 	ib_unpack(bth_table, ARRAY_SIZE(bth_table),
516 		  buf, &header->bth);
517 	buf += IB_BTH_BYTES;
518 
519 	switch (header->bth.opcode) {
520 	case IB_OPCODE_UD_SEND_ONLY:
521 		header->immediate_present = 0;
522 		break;
523 	case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
524 		header->immediate_present = 1;
525 		break;
526 	default:
527 		printk(KERN_WARNING "Invalid BTH.opcode 0x%02x\n",
528 		       header->bth.opcode);
529 		return -EINVAL;
530 	}
531 
532 	if (header->bth.transport_header_version != 0) {
533 		printk(KERN_WARNING "Invalid BTH.transport_header_version %d\n",
534 		       header->bth.transport_header_version);
535 		return -EINVAL;
536 	}
537 
538 	ib_unpack(deth_table, ARRAY_SIZE(deth_table),
539 		  buf, &header->deth);
540 	buf += IB_DETH_BYTES;
541 
542 	if (header->immediate_present)
543 		memcpy(&header->immediate_data, buf, sizeof header->immediate_data);
544 
545 	return 0;
546 }
547 EXPORT_SYMBOL(ib_ud_header_unpack);
548