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 size_t udp_bytes
= udp_present
? IB_UDP_BYTES
: 0;
327 grh_present
= grh_present
&& !ip_version
;
328 memset(header
, 0, sizeof *header
);
331 * UDP header without IP header doesn't make sense
333 if (udp_present
&& ip_version
!= 4 && ip_version
!= 6)
339 header
->lrh
.link_version
= 0;
340 header
->lrh
.link_next_header
=
341 grh_present
? IB_LNH_IBA_GLOBAL
: IB_LNH_IBA_LOCAL
;
342 packet_length
= (IB_LRH_BYTES
+
345 (grh_present
? IB_GRH_BYTES
: 0) +
348 3) / 4; /* round up */
349 header
->lrh
.packet_length
= cpu_to_be16(packet_length
);
353 header
->eth
.type
= cpu_to_be16(ETH_P_8021Q
);
355 if (ip_version
== 6 || grh_present
) {
356 header
->grh
.ip_version
= 6;
357 header
->grh
.payload_length
=
358 cpu_to_be16((udp_bytes
+
363 3) & ~3); /* round up */
364 header
->grh
.next_header
= udp_present
? IPPROTO_UDP
: 0x1b;
367 if (ip_version
== 4) {
368 header
->ip4
.ver
= 4; /* version 4 */
369 header
->ip4
.hdr_len
= 5; /* 5 words */
370 header
->ip4
.tot_len
=
371 cpu_to_be16(IB_IP4_BYTES
+
377 header
->ip4
.protocol
= IPPROTO_UDP
;
379 if (udp_present
&& ip_version
)
381 cpu_to_be16(IB_UDP_BYTES
+
387 if (immediate_present
)
388 header
->bth
.opcode
= IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE
;
390 header
->bth
.opcode
= IB_OPCODE_UD_SEND_ONLY
;
391 header
->bth
.pad_count
= (4 - payload_bytes
) & 3;
392 header
->bth
.transport_header_version
= 0;
394 header
->lrh_present
= lrh_present
;
395 header
->eth_present
= eth_present
;
396 header
->vlan_present
= vlan_present
;
397 header
->grh_present
= grh_present
|| (ip_version
== 6);
398 header
->ipv4_present
= ip_version
== 4;
399 header
->udp_present
= udp_present
;
400 header
->immediate_present
= immediate_present
;
403 EXPORT_SYMBOL(ib_ud_header_init
);
406 * ib_ud_header_pack - Pack UD header struct into wire format
407 * @header:UD header struct
408 * @buf:Buffer to pack into
410 * ib_ud_header_pack() packs the UD header structure @header into wire
411 * format in the buffer @buf.
413 int ib_ud_header_pack(struct ib_ud_header
*header
,
418 if (header
->lrh_present
) {
419 ib_pack(lrh_table
, ARRAY_SIZE(lrh_table
),
420 &header
->lrh
, buf
+ len
);
423 if (header
->eth_present
) {
424 ib_pack(eth_table
, ARRAY_SIZE(eth_table
),
425 &header
->eth
, buf
+ len
);
428 if (header
->vlan_present
) {
429 ib_pack(vlan_table
, ARRAY_SIZE(vlan_table
),
430 &header
->vlan
, buf
+ len
);
431 len
+= IB_VLAN_BYTES
;
433 if (header
->grh_present
) {
434 ib_pack(grh_table
, ARRAY_SIZE(grh_table
),
435 &header
->grh
, buf
+ len
);
438 if (header
->ipv4_present
) {
439 ib_pack(ip4_table
, ARRAY_SIZE(ip4_table
),
440 &header
->ip4
, buf
+ len
);
443 if (header
->udp_present
) {
444 ib_pack(udp_table
, ARRAY_SIZE(udp_table
),
445 &header
->udp
, buf
+ len
);
449 ib_pack(bth_table
, ARRAY_SIZE(bth_table
),
450 &header
->bth
, buf
+ len
);
453 ib_pack(deth_table
, ARRAY_SIZE(deth_table
),
454 &header
->deth
, buf
+ len
);
455 len
+= IB_DETH_BYTES
;
457 if (header
->immediate_present
) {
458 memcpy(buf
+ len
, &header
->immediate_data
, sizeof header
->immediate_data
);
459 len
+= sizeof header
->immediate_data
;
464 EXPORT_SYMBOL(ib_ud_header_pack
);
467 * ib_ud_header_unpack - Unpack UD header struct from wire format
468 * @header:UD header struct
469 * @buf:Buffer to pack into
471 * ib_ud_header_pack() unpacks the UD header structure @header from wire
472 * format in the buffer @buf.
474 int ib_ud_header_unpack(void *buf
,
475 struct ib_ud_header
*header
)
477 ib_unpack(lrh_table
, ARRAY_SIZE(lrh_table
),
481 if (header
->lrh
.link_version
!= 0) {
482 pr_warn("Invalid LRH.link_version %d\n",
483 header
->lrh
.link_version
);
487 switch (header
->lrh
.link_next_header
) {
488 case IB_LNH_IBA_LOCAL
:
489 header
->grh_present
= 0;
492 case IB_LNH_IBA_GLOBAL
:
493 header
->grh_present
= 1;
494 ib_unpack(grh_table
, ARRAY_SIZE(grh_table
),
498 if (header
->grh
.ip_version
!= 6) {
499 pr_warn("Invalid GRH.ip_version %d\n",
500 header
->grh
.ip_version
);
503 if (header
->grh
.next_header
!= 0x1b) {
504 pr_warn("Invalid GRH.next_header 0x%02x\n",
505 header
->grh
.next_header
);
511 pr_warn("Invalid LRH.link_next_header %d\n",
512 header
->lrh
.link_next_header
);
516 ib_unpack(bth_table
, ARRAY_SIZE(bth_table
),
520 switch (header
->bth
.opcode
) {
521 case IB_OPCODE_UD_SEND_ONLY
:
522 header
->immediate_present
= 0;
524 case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE
:
525 header
->immediate_present
= 1;
528 pr_warn("Invalid BTH.opcode 0x%02x\n", header
->bth
.opcode
);
532 if (header
->bth
.transport_header_version
!= 0) {
533 pr_warn("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
);