2 * Copyright (c) 2004 Topspin Corporation. All rights reserved.
3 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
34 #include <linux/errno.h>
35 #include <linux/string.h>
36 #include <linux/export.h>
37 #include <linux/if_ether.h>
40 #include <rdma/ib_pack.h>
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
47 static const struct ib_field lrh_table
[] = {
48 { STRUCT_FIELD(lrh
, virtual_lane
),
52 { STRUCT_FIELD(lrh
, link_version
),
56 { STRUCT_FIELD(lrh
, service_level
),
64 { STRUCT_FIELD(lrh
, link_next_header
),
68 { STRUCT_FIELD(lrh
, destination_lid
),
76 { STRUCT_FIELD(lrh
, packet_length
),
80 { STRUCT_FIELD(lrh
, source_lid
),
86 static const struct ib_field eth_table
[] = {
87 { STRUCT_FIELD(eth
, dmac_h
),
91 { STRUCT_FIELD(eth
, dmac_l
),
95 { STRUCT_FIELD(eth
, smac_h
),
99 { STRUCT_FIELD(eth
, smac_l
),
103 { STRUCT_FIELD(eth
, type
),
109 static const struct ib_field vlan_table
[] = {
110 { STRUCT_FIELD(vlan
, tag
),
114 { STRUCT_FIELD(vlan
, type
),
120 static const struct ib_field ip4_table
[] = {
121 { STRUCT_FIELD(ip4
, ver
),
125 { STRUCT_FIELD(ip4
, hdr_len
),
129 { STRUCT_FIELD(ip4
, tos
),
133 { STRUCT_FIELD(ip4
, tot_len
),
137 { STRUCT_FIELD(ip4
, id
),
141 { STRUCT_FIELD(ip4
, frag_off
),
145 { STRUCT_FIELD(ip4
, ttl
),
149 { STRUCT_FIELD(ip4
, protocol
),
153 { STRUCT_FIELD(ip4
, check
),
157 { STRUCT_FIELD(ip4
, saddr
),
161 { STRUCT_FIELD(ip4
, daddr
),
167 static const struct ib_field udp_table
[] = {
168 { STRUCT_FIELD(udp
, sport
),
172 { STRUCT_FIELD(udp
, dport
),
176 { STRUCT_FIELD(udp
, length
),
180 { STRUCT_FIELD(udp
, csum
),
186 static const struct ib_field grh_table
[] = {
187 { STRUCT_FIELD(grh
, ip_version
),
191 { STRUCT_FIELD(grh
, traffic_class
),
195 { STRUCT_FIELD(grh
, flow_label
),
199 { STRUCT_FIELD(grh
, payload_length
),
203 { STRUCT_FIELD(grh
, next_header
),
207 { STRUCT_FIELD(grh
, hop_limit
),
211 { STRUCT_FIELD(grh
, source_gid
),
215 { STRUCT_FIELD(grh
, destination_gid
),
221 static const struct ib_field bth_table
[] = {
222 { STRUCT_FIELD(bth
, opcode
),
226 { STRUCT_FIELD(bth
, solicited_event
),
230 { STRUCT_FIELD(bth
, mig_req
),
234 { STRUCT_FIELD(bth
, pad_count
),
238 { STRUCT_FIELD(bth
, transport_header_version
),
242 { STRUCT_FIELD(bth
, pkey
),
250 { STRUCT_FIELD(bth
, destination_qpn
),
254 { STRUCT_FIELD(bth
, ack_req
),
262 { STRUCT_FIELD(bth
, psn
),
268 static const struct ib_field deth_table
[] = {
269 { STRUCT_FIELD(deth
, qkey
),
277 { STRUCT_FIELD(deth
, source_qpn
),
283 __sum16
ib_ud_ip4_csum(struct ib_ud_header
*header
)
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
;
296 iph
.saddr
= header
->ip4
.saddr
;
297 iph
.daddr
= header
->ip4
.daddr
;
299 return ip_fast_csum((u8
*)&iph
, iph
.ihl
);
301 EXPORT_SYMBOL(ib_ud_ip4_csum
);
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
315 int ib_ud_header_init(int payload_bytes
,
322 int immediate_present
,
323 struct ib_ud_header
*header
)
325 grh_present
= grh_present
&& !ip_version
;
326 memset(header
, 0, sizeof *header
);
329 * UDP header without IP header doesn't make sense
331 if (udp_present
&& ip_version
!= 4 && ip_version
!= 6)
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
+
343 (grh_present
? IB_GRH_BYTES
: 0) +
346 3) / 4; /* round up */
347 header
->lrh
.packet_length
= cpu_to_be16(packet_length
);
351 header
->eth
.type
= cpu_to_be16(ETH_P_8021Q
);
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
+
360 3) & ~3); /* round up */
361 header
->grh
.next_header
= udp_present
? IPPROTO_UDP
: 0x1b;
364 if (ip_version
== 4) {
365 int udp_bytes
= udp_present
? IB_UDP_BYTES
: 0;
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
+
376 header
->ip4
.protocol
= IPPROTO_UDP
;
378 if (udp_present
&& ip_version
)
380 cpu_to_be16(IB_UDP_BYTES
+
386 if (immediate_present
)
387 header
->bth
.opcode
= IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE
;
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;
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
;
402 EXPORT_SYMBOL(ib_ud_header_init
);
405 * ib_ud_header_pack - Pack UD header struct into wire format
406 * @header:UD header struct
407 * @buf:Buffer to pack into
409 * ib_ud_header_pack() packs the UD header structure @header into wire
410 * format in the buffer @buf.
412 int ib_ud_header_pack(struct ib_ud_header
*header
,
417 if (header
->lrh_present
) {
418 ib_pack(lrh_table
, ARRAY_SIZE(lrh_table
),
419 &header
->lrh
, buf
+ len
);
422 if (header
->eth_present
) {
423 ib_pack(eth_table
, ARRAY_SIZE(eth_table
),
424 &header
->eth
, buf
+ len
);
427 if (header
->vlan_present
) {
428 ib_pack(vlan_table
, ARRAY_SIZE(vlan_table
),
429 &header
->vlan
, buf
+ len
);
430 len
+= IB_VLAN_BYTES
;
432 if (header
->grh_present
) {
433 ib_pack(grh_table
, ARRAY_SIZE(grh_table
),
434 &header
->grh
, buf
+ len
);
437 if (header
->ipv4_present
) {
438 ib_pack(ip4_table
, ARRAY_SIZE(ip4_table
),
439 &header
->ip4
, buf
+ len
);
442 if (header
->udp_present
) {
443 ib_pack(udp_table
, ARRAY_SIZE(udp_table
),
444 &header
->udp
, buf
+ len
);
448 ib_pack(bth_table
, ARRAY_SIZE(bth_table
),
449 &header
->bth
, buf
+ len
);
452 ib_pack(deth_table
, ARRAY_SIZE(deth_table
),
453 &header
->deth
, buf
+ len
);
454 len
+= IB_DETH_BYTES
;
456 if (header
->immediate_present
) {
457 memcpy(buf
+ len
, &header
->immediate_data
, sizeof header
->immediate_data
);
458 len
+= sizeof header
->immediate_data
;
463 EXPORT_SYMBOL(ib_ud_header_pack
);
466 * ib_ud_header_unpack - Unpack UD header struct from wire format
467 * @header:UD header struct
468 * @buf:Buffer to pack into
470 * ib_ud_header_pack() unpacks the UD header structure @header from wire
471 * format in the buffer @buf.
473 int ib_ud_header_unpack(void *buf
,
474 struct ib_ud_header
*header
)
476 ib_unpack(lrh_table
, ARRAY_SIZE(lrh_table
),
480 if (header
->lrh
.link_version
!= 0) {
481 printk(KERN_WARNING
"Invalid LRH.link_version %d\n",
482 header
->lrh
.link_version
);
486 switch (header
->lrh
.link_next_header
) {
487 case IB_LNH_IBA_LOCAL
:
488 header
->grh_present
= 0;
491 case IB_LNH_IBA_GLOBAL
:
492 header
->grh_present
= 1;
493 ib_unpack(grh_table
, ARRAY_SIZE(grh_table
),
497 if (header
->grh
.ip_version
!= 6) {
498 printk(KERN_WARNING
"Invalid GRH.ip_version %d\n",
499 header
->grh
.ip_version
);
502 if (header
->grh
.next_header
!= 0x1b) {
503 printk(KERN_WARNING
"Invalid GRH.next_header 0x%02x\n",
504 header
->grh
.next_header
);
510 printk(KERN_WARNING
"Invalid LRH.link_next_header %d\n",
511 header
->lrh
.link_next_header
);
515 ib_unpack(bth_table
, ARRAY_SIZE(bth_table
),
519 switch (header
->bth
.opcode
) {
520 case IB_OPCODE_UD_SEND_ONLY
:
521 header
->immediate_present
= 0;
523 case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE
:
524 header
->immediate_present
= 1;
527 printk(KERN_WARNING
"Invalid BTH.opcode 0x%02x\n",
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
);
538 ib_unpack(deth_table
, ARRAY_SIZE(deth_table
),
540 buf
+= IB_DETH_BYTES
;
542 if (header
->immediate_present
)
543 memcpy(&header
->immediate_data
, buf
, sizeof header
->immediate_data
);
547 EXPORT_SYMBOL(ib_ud_header_unpack
);