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