root/drivers/infiniband/core/ud_header.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ib_ud_ip4_csum
  2. ib_ud_header_init
  3. ib_ud_header_pack
  4. ib_ud_header_unpack

   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         size_t udp_bytes = udp_present ? IB_UDP_BYTES : 0;
 326 
 327         grh_present = grh_present && !ip_version;
 328         memset(header, 0, sizeof *header);
 329 
 330         /*
 331          * UDP header without IP header doesn't make sense
 332          */
 333         if (udp_present && ip_version != 4 && ip_version != 6)
 334                 return -EINVAL;
 335 
 336         if (lrh_present) {
 337                 u16 packet_length;
 338 
 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   +
 343                                  IB_BTH_BYTES   +
 344                                  IB_DETH_BYTES  +
 345                                  (grh_present ? IB_GRH_BYTES : 0) +
 346                                  payload_bytes  +
 347                                  4              + /* ICRC     */
 348                                  3) / 4;          /* round up */
 349                 header->lrh.packet_length = cpu_to_be16(packet_length);
 350         }
 351 
 352         if (vlan_present)
 353                 header->eth.type = cpu_to_be16(ETH_P_8021Q);
 354 
 355         if (ip_version == 6 || grh_present) {
 356                 header->grh.ip_version      = 6;
 357                 header->grh.payload_length  =
 358                         cpu_to_be16((udp_bytes        +
 359                                      IB_BTH_BYTES     +
 360                                      IB_DETH_BYTES    +
 361                                      payload_bytes    +
 362                                      4                + /* ICRC     */
 363                                      3) & ~3);          /* round up */
 364                 header->grh.next_header     = udp_present ? IPPROTO_UDP : 0x1b;
 365         }
 366 
 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   +
 372                                      udp_bytes     +
 373                                      IB_BTH_BYTES  +
 374                                      IB_DETH_BYTES +
 375                                      payload_bytes +
 376                                      4);     /* ICRC     */
 377                 header->ip4.protocol = IPPROTO_UDP;
 378         }
 379         if (udp_present && ip_version)
 380                 header->udp.length =
 381                         cpu_to_be16(IB_UDP_BYTES   +
 382                                      IB_BTH_BYTES  +
 383                                      IB_DETH_BYTES +
 384                                      payload_bytes +
 385                                      4);     /* ICRC     */
 386 
 387         if (immediate_present)
 388                 header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
 389         else
 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;
 393 
 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;
 401         return 0;
 402 }
 403 EXPORT_SYMBOL(ib_ud_header_init);
 404 
 405 /**
 406  * ib_ud_header_pack - Pack UD header struct into wire format
 407  * @header:UD header struct
 408  * @buf:Buffer to pack into
 409  *
 410  * ib_ud_header_pack() packs the UD header structure @header into wire
 411  * format in the buffer @buf.
 412  */
 413 int ib_ud_header_pack(struct ib_ud_header *header,
 414                       void                *buf)
 415 {
 416         int len = 0;
 417 
 418         if (header->lrh_present) {
 419                 ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
 420                         &header->lrh, buf + len);
 421                 len += IB_LRH_BYTES;
 422         }
 423         if (header->eth_present) {
 424                 ib_pack(eth_table, ARRAY_SIZE(eth_table),
 425                         &header->eth, buf + len);
 426                 len += IB_ETH_BYTES;
 427         }
 428         if (header->vlan_present) {
 429                 ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
 430                         &header->vlan, buf + len);
 431                 len += IB_VLAN_BYTES;
 432         }
 433         if (header->grh_present) {
 434                 ib_pack(grh_table, ARRAY_SIZE(grh_table),
 435                         &header->grh, buf + len);
 436                 len += IB_GRH_BYTES;
 437         }
 438         if (header->ipv4_present) {
 439                 ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
 440                         &header->ip4, buf + len);
 441                 len += IB_IP4_BYTES;
 442         }
 443         if (header->udp_present) {
 444                 ib_pack(udp_table, ARRAY_SIZE(udp_table),
 445                         &header->udp, buf + len);
 446                 len += IB_UDP_BYTES;
 447         }
 448 
 449         ib_pack(bth_table, ARRAY_SIZE(bth_table),
 450                 &header->bth, buf + len);
 451         len += IB_BTH_BYTES;
 452 
 453         ib_pack(deth_table, ARRAY_SIZE(deth_table),
 454                 &header->deth, buf + len);
 455         len += IB_DETH_BYTES;
 456 
 457         if (header->immediate_present) {
 458                 memcpy(buf + len, &header->immediate_data, sizeof header->immediate_data);
 459                 len += sizeof header->immediate_data;
 460         }
 461 
 462         return len;
 463 }
 464 EXPORT_SYMBOL(ib_ud_header_pack);
 465 
 466 /**
 467  * ib_ud_header_unpack - Unpack UD header struct from wire format
 468  * @header:UD header struct
 469  * @buf:Buffer to pack into
 470  *
 471  * ib_ud_header_pack() unpacks the UD header structure @header from wire
 472  * format in the buffer @buf.
 473  */
 474 int ib_ud_header_unpack(void                *buf,
 475                         struct ib_ud_header *header)
 476 {
 477         ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
 478                   buf, &header->lrh);
 479         buf += IB_LRH_BYTES;
 480 
 481         if (header->lrh.link_version != 0) {
 482                 pr_warn("Invalid LRH.link_version %d\n",
 483                         header->lrh.link_version);
 484                 return -EINVAL;
 485         }
 486 
 487         switch (header->lrh.link_next_header) {
 488         case IB_LNH_IBA_LOCAL:
 489                 header->grh_present = 0;
 490                 break;
 491 
 492         case IB_LNH_IBA_GLOBAL:
 493                 header->grh_present = 1;
 494                 ib_unpack(grh_table, ARRAY_SIZE(grh_table),
 495                           buf, &header->grh);
 496                 buf += IB_GRH_BYTES;
 497 
 498                 if (header->grh.ip_version != 6) {
 499                         pr_warn("Invalid GRH.ip_version %d\n",
 500                                 header->grh.ip_version);
 501                         return -EINVAL;
 502                 }
 503                 if (header->grh.next_header != 0x1b) {
 504                         pr_warn("Invalid GRH.next_header 0x%02x\n",
 505                                 header->grh.next_header);
 506                         return -EINVAL;
 507                 }
 508                 break;
 509 
 510         default:
 511                 pr_warn("Invalid LRH.link_next_header %d\n",
 512                         header->lrh.link_next_header);
 513                 return -EINVAL;
 514         }
 515 
 516         ib_unpack(bth_table, ARRAY_SIZE(bth_table),
 517                   buf, &header->bth);
 518         buf += IB_BTH_BYTES;
 519 
 520         switch (header->bth.opcode) {
 521         case IB_OPCODE_UD_SEND_ONLY:
 522                 header->immediate_present = 0;
 523                 break;
 524         case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
 525                 header->immediate_present = 1;
 526                 break;
 527         default:
 528                 pr_warn("Invalid BTH.opcode 0x%02x\n", header->bth.opcode);
 529                 return -EINVAL;
 530         }
 531 
 532         if (header->bth.transport_header_version != 0) {
 533                 pr_warn("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);

/* [<][>][^][v][top][bottom][index][help] */