The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ofed/drivers/infiniband/core/ib_ud_header.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
    5  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
    6  *
    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:
   12  *
   13  *     Redistribution and use in source and binary forms, with or
   14  *     without modification, are permitted provided that the following
   15  *     conditions are met:
   16  *
   17  *      - Redistributions of source code must retain the above
   18  *        copyright notice, this list of conditions and the following
   19  *        disclaimer.
   20  *
   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.
   25  *
   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
   33  * SOFTWARE.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include <linux/errno.h>
   40 #include <linux/string.h>
   41 #include <linux/if_ether.h>
   42 
   43 #include <rdma/ib_pack.h>
   44 
   45 #include <machine/in_cksum.h>
   46 
   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
   51 
   52 static const struct ib_field lrh_table[]  = {
   53         { STRUCT_FIELD(lrh, virtual_lane),
   54           .offset_words = 0,
   55           .offset_bits  = 0,
   56           .size_bits    = 4 },
   57         { STRUCT_FIELD(lrh, link_version),
   58           .offset_words = 0,
   59           .offset_bits  = 4,
   60           .size_bits    = 4 },
   61         { STRUCT_FIELD(lrh, service_level),
   62           .offset_words = 0,
   63           .offset_bits  = 8,
   64           .size_bits    = 4 },
   65         { RESERVED,
   66           .offset_words = 0,
   67           .offset_bits  = 12,
   68           .size_bits    = 2 },
   69         { STRUCT_FIELD(lrh, link_next_header),
   70           .offset_words = 0,
   71           .offset_bits  = 14,
   72           .size_bits    = 2 },
   73         { STRUCT_FIELD(lrh, destination_lid),
   74           .offset_words = 0,
   75           .offset_bits  = 16,
   76           .size_bits    = 16 },
   77         { RESERVED,
   78           .offset_words = 1,
   79           .offset_bits  = 0,
   80           .size_bits    = 5 },
   81         { STRUCT_FIELD(lrh, packet_length),
   82           .offset_words = 1,
   83           .offset_bits  = 5,
   84           .size_bits    = 11 },
   85         { STRUCT_FIELD(lrh, source_lid),
   86           .offset_words = 1,
   87           .offset_bits  = 16,
   88           .size_bits    = 16 }
   89 };
   90 
   91 static const struct ib_field eth_table[]  = {
   92         { STRUCT_FIELD(eth, dmac_h),
   93           .offset_words = 0,
   94           .offset_bits  = 0,
   95           .size_bits    = 32 },
   96         { STRUCT_FIELD(eth, dmac_l),
   97           .offset_words = 1,
   98           .offset_bits  = 0,
   99           .size_bits    = 16 },
  100         { STRUCT_FIELD(eth, smac_h),
  101           .offset_words = 1,
  102           .offset_bits  = 16,
  103           .size_bits    = 16 },
  104         { STRUCT_FIELD(eth, smac_l),
  105           .offset_words = 2,
  106           .offset_bits  = 0,
  107           .size_bits    = 32 },
  108         { STRUCT_FIELD(eth, type),
  109           .offset_words = 3,
  110           .offset_bits  = 0,
  111           .size_bits    = 16 }
  112 };
  113 
  114 static const struct ib_field vlan_table[]  = {
  115         { STRUCT_FIELD(vlan, tag),
  116           .offset_words = 0,
  117           .offset_bits  = 0,
  118           .size_bits    = 16 },
  119         { STRUCT_FIELD(vlan, type),
  120           .offset_words = 0,
  121           .offset_bits  = 16,
  122           .size_bits    = 16 }
  123 };
  124 
  125 static const struct ib_field ip4_table[]  = {
  126         { STRUCT_FIELD(ip4, ver),
  127           .offset_words = 0,
  128           .offset_bits  = 0,
  129           .size_bits    = 4 },
  130         { STRUCT_FIELD(ip4, hdr_len),
  131           .offset_words = 0,
  132           .offset_bits  = 4,
  133           .size_bits    = 4 },
  134         { STRUCT_FIELD(ip4, tos),
  135           .offset_words = 0,
  136           .offset_bits  = 8,
  137           .size_bits    = 8 },
  138         { STRUCT_FIELD(ip4, tot_len),
  139           .offset_words = 0,
  140           .offset_bits  = 16,
  141           .size_bits    = 16 },
  142         { STRUCT_FIELD(ip4, id),
  143           .offset_words = 1,
  144           .offset_bits  = 0,
  145           .size_bits    = 16 },
  146         { STRUCT_FIELD(ip4, frag_off),
  147           .offset_words = 1,
  148           .offset_bits  = 16,
  149           .size_bits    = 16 },
  150         { STRUCT_FIELD(ip4, ttl),
  151           .offset_words = 2,
  152           .offset_bits  = 0,
  153           .size_bits    = 8 },
  154         { STRUCT_FIELD(ip4, protocol),
  155           .offset_words = 2,
  156           .offset_bits  = 8,
  157           .size_bits    = 8 },
  158         { STRUCT_FIELD(ip4, check),
  159           .offset_words = 2,
  160           .offset_bits  = 16,
  161           .size_bits    = 16 },
  162         { STRUCT_FIELD(ip4, saddr),
  163           .offset_words = 3,
  164           .offset_bits  = 0,
  165           .size_bits    = 32 },
  166         { STRUCT_FIELD(ip4, daddr),
  167           .offset_words = 4,
  168           .offset_bits  = 0,
  169           .size_bits    = 32 }
  170 };
  171 
  172 static const struct ib_field udp_table[]  = {
  173         { STRUCT_FIELD(udp, sport),
  174           .offset_words = 0,
  175           .offset_bits  = 0,
  176           .size_bits    = 16 },
  177         { STRUCT_FIELD(udp, dport),
  178           .offset_words = 0,
  179           .offset_bits  = 16,
  180           .size_bits    = 16 },
  181         { STRUCT_FIELD(udp, length),
  182           .offset_words = 1,
  183           .offset_bits  = 0,
  184           .size_bits    = 16 },
  185         { STRUCT_FIELD(udp, csum),
  186           .offset_words = 1,
  187           .offset_bits  = 16,
  188           .size_bits    = 16 }
  189 };
  190 
  191 static const struct ib_field grh_table[]  = {
  192         { STRUCT_FIELD(grh, ip_version),
  193           .offset_words = 0,
  194           .offset_bits  = 0,
  195           .size_bits    = 4 },
  196         { STRUCT_FIELD(grh, traffic_class),
  197           .offset_words = 0,
  198           .offset_bits  = 4,
  199           .size_bits    = 8 },
  200         { STRUCT_FIELD(grh, flow_label),
  201           .offset_words = 0,
  202           .offset_bits  = 12,
  203           .size_bits    = 20 },
  204         { STRUCT_FIELD(grh, payload_length),
  205           .offset_words = 1,
  206           .offset_bits  = 0,
  207           .size_bits    = 16 },
  208         { STRUCT_FIELD(grh, next_header),
  209           .offset_words = 1,
  210           .offset_bits  = 16,
  211           .size_bits    = 8 },
  212         { STRUCT_FIELD(grh, hop_limit),
  213           .offset_words = 1,
  214           .offset_bits  = 24,
  215           .size_bits    = 8 },
  216         { STRUCT_FIELD(grh, source_gid),
  217           .offset_words = 2,
  218           .offset_bits  = 0,
  219           .size_bits    = 128 },
  220         { STRUCT_FIELD(grh, destination_gid),
  221           .offset_words = 6,
  222           .offset_bits  = 0,
  223           .size_bits    = 128 }
  224 };
  225 
  226 static const struct ib_field bth_table[]  = {
  227         { STRUCT_FIELD(bth, opcode),
  228           .offset_words = 0,
  229           .offset_bits  = 0,
  230           .size_bits    = 8 },
  231         { STRUCT_FIELD(bth, solicited_event),
  232           .offset_words = 0,
  233           .offset_bits  = 8,
  234           .size_bits    = 1 },
  235         { STRUCT_FIELD(bth, mig_req),
  236           .offset_words = 0,
  237           .offset_bits  = 9,
  238           .size_bits    = 1 },
  239         { STRUCT_FIELD(bth, pad_count),
  240           .offset_words = 0,
  241           .offset_bits  = 10,
  242           .size_bits    = 2 },
  243         { STRUCT_FIELD(bth, transport_header_version),
  244           .offset_words = 0,
  245           .offset_bits  = 12,
  246           .size_bits    = 4 },
  247         { STRUCT_FIELD(bth, pkey),
  248           .offset_words = 0,
  249           .offset_bits  = 16,
  250           .size_bits    = 16 },
  251         { RESERVED,
  252           .offset_words = 1,
  253           .offset_bits  = 0,
  254           .size_bits    = 8 },
  255         { STRUCT_FIELD(bth, destination_qpn),
  256           .offset_words = 1,
  257           .offset_bits  = 8,
  258           .size_bits    = 24 },
  259         { STRUCT_FIELD(bth, ack_req),
  260           .offset_words = 2,
  261           .offset_bits  = 0,
  262           .size_bits    = 1 },
  263         { RESERVED,
  264           .offset_words = 2,
  265           .offset_bits  = 1,
  266           .size_bits    = 7 },
  267         { STRUCT_FIELD(bth, psn),
  268           .offset_words = 2,
  269           .offset_bits  = 8,
  270           .size_bits    = 24 }
  271 };
  272 
  273 static const struct ib_field deth_table[] = {
  274         { STRUCT_FIELD(deth, qkey),
  275           .offset_words = 0,
  276           .offset_bits  = 0,
  277           .size_bits    = 32 },
  278         { RESERVED,
  279           .offset_words = 1,
  280           .offset_bits  = 0,
  281           .size_bits    = 8 },
  282         { STRUCT_FIELD(deth, source_qpn),
  283           .offset_words = 1,
  284           .offset_bits  = 8,
  285           .size_bits    = 24 }
  286 };
  287 
  288 __sum16 ib_ud_ip4_csum(struct ib_ud_header *header)
  289 {
  290 #if defined(INET) || defined(INET6)
  291         struct ip iph;
  292 
  293         iph.ip_hl       = 5;
  294         iph.ip_v        = 4;
  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;
  301         iph.ip_sum      = 0;
  302         iph.ip_src.s_addr = header->ip4.saddr;
  303         iph.ip_dst.s_addr = header->ip4.daddr;
  304 
  305         return in_cksum_hdr(&iph);
  306 #else
  307         return 0;
  308 #endif
  309 }
  310 EXPORT_SYMBOL(ib_ud_ip4_csum);
  311 
  312 /**
  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
  323  */
  324 int ib_ud_header_init(int     payload_bytes,
  325                       int    lrh_present,
  326                       int    eth_present,
  327                       int    vlan_present,
  328                       int    grh_present,
  329                       int    ip_version,
  330                       int    udp_present,
  331                       int    immediate_present,
  332                       struct ib_ud_header *header)
  333 {
  334         size_t udp_bytes = udp_present ? IB_UDP_BYTES : 0;
  335 
  336         grh_present = grh_present && !ip_version;
  337         memset(header, 0, sizeof *header);
  338 
  339         /*
  340          * UDP header without IP header doesn't make sense
  341          */
  342         if (udp_present && ip_version != 4 && ip_version != 6)
  343                 return -EINVAL;
  344 
  345         if (lrh_present) {
  346                 u16 packet_length;
  347 
  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   +
  352                                  IB_BTH_BYTES   +
  353                                  IB_DETH_BYTES  +
  354                                  (grh_present ? IB_GRH_BYTES : 0) +
  355                                  payload_bytes  +
  356                                  4              + /* ICRC     */
  357                                  3) / 4;          /* round up */
  358                 header->lrh.packet_length = cpu_to_be16(packet_length);
  359         }
  360 
  361         if (vlan_present)
  362                 header->eth.type = cpu_to_be16(ETH_P_8021Q);
  363 
  364         if (ip_version == 6 || grh_present) {
  365                 header->grh.ip_version      = 6;
  366                 header->grh.payload_length  =
  367                         cpu_to_be16((udp_bytes        +
  368                                      IB_BTH_BYTES     +
  369                                      IB_DETH_BYTES    +
  370                                      payload_bytes    +
  371                                      4                + /* ICRC     */
  372                                      3) & ~3);          /* round up */
  373                 header->grh.next_header     = udp_present ? IPPROTO_UDP : 0x1b;
  374         }
  375 
  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   +
  381                                      udp_bytes     +
  382                                      IB_BTH_BYTES  +
  383                                      IB_DETH_BYTES +
  384                                      payload_bytes +
  385                                      4);     /* ICRC     */
  386                 header->ip4.protocol = IPPROTO_UDP;
  387         }
  388         if (udp_present && ip_version)
  389                 header->udp.length =
  390                         cpu_to_be16(IB_UDP_BYTES   +
  391                                      IB_BTH_BYTES  +
  392                                      IB_DETH_BYTES +
  393                                      payload_bytes +
  394                                      4);     /* ICRC     */
  395 
  396         if (immediate_present)
  397                 header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
  398         else
  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;
  402 
  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;
  410         return 0;
  411 }
  412 EXPORT_SYMBOL(ib_ud_header_init);
  413 
  414 /**
  415  * ib_ud_header_pack - Pack UD header struct into wire format
  416  * @header:UD header struct
  417  * @buf:Buffer to pack into
  418  *
  419  * ib_ud_header_pack() packs the UD header structure @header into wire
  420  * format in the buffer @buf.
  421  */
  422 int ib_ud_header_pack(struct ib_ud_header *header,
  423                       void                *buf)
  424 {
  425         int len = 0;
  426 
  427         if (header->lrh_present) {
  428                 ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
  429                         &header->lrh, (char *)buf + len);
  430                 len += IB_LRH_BYTES;
  431         }
  432         if (header->eth_present) {
  433                 ib_pack(eth_table, ARRAY_SIZE(eth_table),
  434                         &header->eth, (char *)buf + len);
  435                 len += IB_ETH_BYTES;
  436         }
  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;
  441         }
  442         if (header->grh_present) {
  443                 ib_pack(grh_table, ARRAY_SIZE(grh_table),
  444                         &header->grh, (char *)buf + len);
  445                 len += IB_GRH_BYTES;
  446         }
  447         if (header->ipv4_present) {
  448                 ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
  449                         &header->ip4, (char *)buf + len);
  450                 len += IB_IP4_BYTES;
  451         }
  452         if (header->udp_present) {
  453                 ib_pack(udp_table, ARRAY_SIZE(udp_table),
  454                         &header->udp, (char *)buf + len);
  455                 len += IB_UDP_BYTES;
  456         }
  457 
  458         ib_pack(bth_table, ARRAY_SIZE(bth_table),
  459                 &header->bth, (char *)buf + len);
  460         len += IB_BTH_BYTES;
  461 
  462         ib_pack(deth_table, ARRAY_SIZE(deth_table),
  463                 &header->deth, (char *)buf + len);
  464         len += IB_DETH_BYTES;
  465 
  466         if (header->immediate_present) {
  467                 memcpy((char *)buf + len, &header->immediate_data, sizeof header->immediate_data);
  468                 len += sizeof header->immediate_data;
  469         }
  470 
  471         return len;
  472 }
  473 EXPORT_SYMBOL(ib_ud_header_pack);
  474 
  475 /**
  476  * ib_ud_header_unpack - Unpack UD header struct from wire format
  477  * @header:UD header struct
  478  * @buf:Buffer to pack into
  479  *
  480  * ib_ud_header_pack() unpacks the UD header structure @header from wire
  481  * format in the buffer @buf.
  482  */
  483 int ib_ud_header_unpack(void                *buf,
  484                         struct ib_ud_header *header)
  485 {
  486         ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
  487                   buf, &header->lrh);
  488         buf = (char *)buf + IB_LRH_BYTES;
  489 
  490         if (header->lrh.link_version != 0) {
  491                 pr_warn("Invalid LRH.link_version %d\n",
  492                         header->lrh.link_version);
  493                 return -EINVAL;
  494         }
  495 
  496         switch (header->lrh.link_next_header) {
  497         case IB_LNH_IBA_LOCAL:
  498                 header->grh_present = 0;
  499                 break;
  500 
  501         case IB_LNH_IBA_GLOBAL:
  502                 header->grh_present = 1;
  503                 ib_unpack(grh_table, ARRAY_SIZE(grh_table),
  504                           buf, &header->grh);
  505                 buf = (char *)buf + IB_GRH_BYTES;
  506 
  507                 if (header->grh.ip_version != 6) {
  508                         pr_warn("Invalid GRH.ip_version %d\n",
  509                                 header->grh.ip_version);
  510                         return -EINVAL;
  511                 }
  512                 if (header->grh.next_header != 0x1b) {
  513                         pr_warn("Invalid GRH.next_header 0x%02x\n",
  514                                 header->grh.next_header);
  515                         return -EINVAL;
  516                 }
  517                 break;
  518 
  519         default:
  520                 pr_warn("Invalid LRH.link_next_header %d\n",
  521                         header->lrh.link_next_header);
  522                 return -EINVAL;
  523         }
  524 
  525         ib_unpack(bth_table, ARRAY_SIZE(bth_table),
  526                   buf, &header->bth);
  527         buf = (char *)buf + IB_BTH_BYTES;
  528 
  529         switch (header->bth.opcode) {
  530         case IB_OPCODE_UD_SEND_ONLY:
  531                 header->immediate_present = 0;
  532                 break;
  533         case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
  534                 header->immediate_present = 1;
  535                 break;
  536         default:
  537                 pr_warn("Invalid BTH.opcode 0x%02x\n", header->bth.opcode);
  538                 return -EINVAL;
  539         }
  540 
  541         if (header->bth.transport_header_version != 0) {
  542                 pr_warn("Invalid BTH.transport_header_version %d\n",
  543                         header->bth.transport_header_version);
  544                 return -EINVAL;
  545         }
  546 
  547         ib_unpack(deth_table, ARRAY_SIZE(deth_table),
  548                   buf, &header->deth);
  549         buf = (char *)buf + IB_DETH_BYTES;
  550 
  551         if (header->immediate_present)
  552                 memcpy(&header->immediate_data, buf, sizeof header->immediate_data);
  553 
  554         return 0;
  555 }
  556 EXPORT_SYMBOL(ib_ud_header_unpack);

Cache object: 7f7e28b42de182015ec696e8568163b1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.