2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
4 * Copyright (c) 2004 Topspin Corporation. All rights reserved.
5 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
39 #include <linux/errno.h>
40 #include <linux/string.h>
41 #include <linux/if_ether.h>
43 #include <rdma/ib_pack.h>
45 #include <machine/in_cksum.h>
47 #define STRUCT_FIELD(header, field) \
48 .struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \
49 .struct_size_bytes = sizeof ((struct ib_unpacked_ ## header *) 0)->field, \
50 .field_name = #header ":" #field
52 static const struct ib_field lrh_table[] = {
53 { STRUCT_FIELD(lrh, virtual_lane),
57 { STRUCT_FIELD(lrh, link_version),
61 { STRUCT_FIELD(lrh, service_level),
69 { STRUCT_FIELD(lrh, link_next_header),
73 { STRUCT_FIELD(lrh, destination_lid),
81 { STRUCT_FIELD(lrh, packet_length),
85 { STRUCT_FIELD(lrh, source_lid),
91 static const struct ib_field eth_table[] = {
92 { STRUCT_FIELD(eth, dmac_h),
96 { STRUCT_FIELD(eth, dmac_l),
100 { STRUCT_FIELD(eth, smac_h),
104 { STRUCT_FIELD(eth, smac_l),
108 { STRUCT_FIELD(eth, type),
114 static const struct ib_field vlan_table[] = {
115 { STRUCT_FIELD(vlan, tag),
119 { STRUCT_FIELD(vlan, type),
125 static const struct ib_field ip4_table[] = {
126 { STRUCT_FIELD(ip4, ver),
130 { STRUCT_FIELD(ip4, hdr_len),
134 { STRUCT_FIELD(ip4, tos),
138 { STRUCT_FIELD(ip4, tot_len),
142 { STRUCT_FIELD(ip4, id),
146 { STRUCT_FIELD(ip4, frag_off),
150 { STRUCT_FIELD(ip4, ttl),
154 { STRUCT_FIELD(ip4, protocol),
158 { STRUCT_FIELD(ip4, check),
162 { STRUCT_FIELD(ip4, saddr),
166 { STRUCT_FIELD(ip4, daddr),
172 static const struct ib_field udp_table[] = {
173 { STRUCT_FIELD(udp, sport),
177 { STRUCT_FIELD(udp, dport),
181 { STRUCT_FIELD(udp, length),
185 { STRUCT_FIELD(udp, csum),
191 static const struct ib_field grh_table[] = {
192 { STRUCT_FIELD(grh, ip_version),
196 { STRUCT_FIELD(grh, traffic_class),
200 { STRUCT_FIELD(grh, flow_label),
204 { STRUCT_FIELD(grh, payload_length),
208 { STRUCT_FIELD(grh, next_header),
212 { STRUCT_FIELD(grh, hop_limit),
216 { STRUCT_FIELD(grh, source_gid),
220 { STRUCT_FIELD(grh, destination_gid),
226 static const struct ib_field bth_table[] = {
227 { STRUCT_FIELD(bth, opcode),
231 { STRUCT_FIELD(bth, solicited_event),
235 { STRUCT_FIELD(bth, mig_req),
239 { STRUCT_FIELD(bth, pad_count),
243 { STRUCT_FIELD(bth, transport_header_version),
247 { STRUCT_FIELD(bth, pkey),
255 { STRUCT_FIELD(bth, destination_qpn),
259 { STRUCT_FIELD(bth, ack_req),
267 { STRUCT_FIELD(bth, psn),
273 static const struct ib_field deth_table[] = {
274 { STRUCT_FIELD(deth, qkey),
282 { STRUCT_FIELD(deth, source_qpn),
288 __sum16 ib_ud_ip4_csum(struct ib_ud_header *header)
290 #if defined(INET) || defined(INET6)
295 iph.ip_tos = header->ip4.tos;
296 iph.ip_len = header->ip4.tot_len;
297 iph.ip_id = header->ip4.id;
298 iph.ip_off = header->ip4.frag_off;
299 iph.ip_ttl = header->ip4.ttl;
300 iph.ip_p = header->ip4.protocol;
302 iph.ip_src.s_addr = header->ip4.saddr;
303 iph.ip_dst.s_addr = header->ip4.daddr;
305 return in_cksum_hdr(&iph);
310 EXPORT_SYMBOL(ib_ud_ip4_csum);
313 * ib_ud_header_init - Initialize UD header structure
314 * @payload_bytes:Length of packet payload
315 * @lrh_present: specify if LRH is present
316 * @eth_present: specify if Eth header is present
317 * @vlan_present: packet is tagged vlan
318 * @grh_present: GRH flag (if non-zero, GRH will be included)
319 * @ip_version: if non-zero, IP header, V4 or V6, will be included
320 * @udp_present :if non-zero, UDP header will be included
321 * @immediate_present: specify if immediate data is present
322 * @header:Structure to initialize
324 int ib_ud_header_init(int payload_bytes,
331 int immediate_present,
332 struct ib_ud_header *header)
334 size_t udp_bytes = udp_present ? IB_UDP_BYTES : 0;
336 grh_present = grh_present && !ip_version;
337 memset(header, 0, sizeof *header);
340 * UDP header without IP header doesn't make sense
342 if (udp_present && ip_version != 4 && ip_version != 6)
348 header->lrh.link_version = 0;
349 header->lrh.link_next_header =
350 grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
351 packet_length = (IB_LRH_BYTES +
354 (grh_present ? IB_GRH_BYTES : 0) +
357 3) / 4; /* round up */
358 header->lrh.packet_length = cpu_to_be16(packet_length);
362 header->eth.type = cpu_to_be16(ETH_P_8021Q);
364 if (ip_version == 6 || grh_present) {
365 header->grh.ip_version = 6;
366 header->grh.payload_length =
367 cpu_to_be16((udp_bytes +
372 3) & ~3); /* round up */
373 header->grh.next_header = udp_present ? IPPROTO_UDP : 0x1b;
376 if (ip_version == 4) {
377 header->ip4.ver = 4; /* version 4 */
378 header->ip4.hdr_len = 5; /* 5 words */
379 header->ip4.tot_len =
380 cpu_to_be16(IB_IP4_BYTES +
386 header->ip4.protocol = IPPROTO_UDP;
388 if (udp_present && ip_version)
390 cpu_to_be16(IB_UDP_BYTES +
396 if (immediate_present)
397 header->bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
399 header->bth.opcode = IB_OPCODE_UD_SEND_ONLY;
400 header->bth.pad_count = (4 - payload_bytes) & 3;
401 header->bth.transport_header_version = 0;
403 header->lrh_present = lrh_present;
404 header->eth_present = eth_present;
405 header->vlan_present = vlan_present;
406 header->grh_present = grh_present || (ip_version == 6);
407 header->ipv4_present = ip_version == 4;
408 header->udp_present = udp_present;
409 header->immediate_present = immediate_present;
412 EXPORT_SYMBOL(ib_ud_header_init);
415 * ib_ud_header_pack - Pack UD header struct into wire format
416 * @header:UD header struct
417 * @buf:Buffer to pack into
419 * ib_ud_header_pack() packs the UD header structure @header into wire
420 * format in the buffer @buf.
422 int ib_ud_header_pack(struct ib_ud_header *header,
427 if (header->lrh_present) {
428 ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
429 &header->lrh, (char *)buf + len);
432 if (header->eth_present) {
433 ib_pack(eth_table, ARRAY_SIZE(eth_table),
434 &header->eth, (char *)buf + len);
437 if (header->vlan_present) {
438 ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
439 &header->vlan, (char *)buf + len);
440 len += IB_VLAN_BYTES;
442 if (header->grh_present) {
443 ib_pack(grh_table, ARRAY_SIZE(grh_table),
444 &header->grh, (char *)buf + len);
447 if (header->ipv4_present) {
448 ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
449 &header->ip4, (char *)buf + len);
452 if (header->udp_present) {
453 ib_pack(udp_table, ARRAY_SIZE(udp_table),
454 &header->udp, (char *)buf + len);
458 ib_pack(bth_table, ARRAY_SIZE(bth_table),
459 &header->bth, (char *)buf + len);
462 ib_pack(deth_table, ARRAY_SIZE(deth_table),
463 &header->deth, (char *)buf + len);
464 len += IB_DETH_BYTES;
466 if (header->immediate_present) {
467 memcpy((char *)buf + len, &header->immediate_data, sizeof header->immediate_data);
468 len += sizeof header->immediate_data;
473 EXPORT_SYMBOL(ib_ud_header_pack);
476 * ib_ud_header_unpack - Unpack UD header struct from wire format
477 * @header:UD header struct
478 * @buf:Buffer to pack into
480 * ib_ud_header_pack() unpacks the UD header structure @header from wire
481 * format in the buffer @buf.
483 int ib_ud_header_unpack(void *buf,
484 struct ib_ud_header *header)
486 ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
488 buf = (char *)buf + IB_LRH_BYTES;
490 if (header->lrh.link_version != 0) {
491 pr_warn("Invalid LRH.link_version %d\n",
492 header->lrh.link_version);
496 switch (header->lrh.link_next_header) {
497 case IB_LNH_IBA_LOCAL:
498 header->grh_present = 0;
501 case IB_LNH_IBA_GLOBAL:
502 header->grh_present = 1;
503 ib_unpack(grh_table, ARRAY_SIZE(grh_table),
505 buf = (char *)buf + IB_GRH_BYTES;
507 if (header->grh.ip_version != 6) {
508 pr_warn("Invalid GRH.ip_version %d\n",
509 header->grh.ip_version);
512 if (header->grh.next_header != 0x1b) {
513 pr_warn("Invalid GRH.next_header 0x%02x\n",
514 header->grh.next_header);
520 pr_warn("Invalid LRH.link_next_header %d\n",
521 header->lrh.link_next_header);
525 ib_unpack(bth_table, ARRAY_SIZE(bth_table),
527 buf = (char *)buf + IB_BTH_BYTES;
529 switch (header->bth.opcode) {
530 case IB_OPCODE_UD_SEND_ONLY:
531 header->immediate_present = 0;
533 case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
534 header->immediate_present = 1;
537 pr_warn("Invalid BTH.opcode 0x%02x\n", header->bth.opcode);
541 if (header->bth.transport_header_version != 0) {
542 pr_warn("Invalid BTH.transport_header_version %d\n",
543 header->bth.transport_header_version);
547 ib_unpack(deth_table, ARRAY_SIZE(deth_table),
549 buf = (char *)buf + IB_DETH_BYTES;
551 if (header->immediate_present)
552 memcpy(&header->immediate_data, buf, sizeof header->immediate_data);
556 EXPORT_SYMBOL(ib_ud_header_unpack);