ud_header.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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. #include <linux/errno.h>
  34. #include <linux/string.h>
  35. #include <linux/export.h>
  36. #include <linux/if_ether.h>
  37. #include <linux/ip.h>
  38. #include <rdma/ib_pack.h>
  39. #define STRUCT_FIELD(header, field) \
  40. .struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \
  41. .struct_size_bytes = sizeof_field(struct ib_unpacked_ ## header, field), \
  42. .field_name = #header ":" #field
  43. static const struct ib_field lrh_table[] = {
  44. { STRUCT_FIELD(lrh, virtual_lane),
  45. .offset_words = 0,
  46. .offset_bits = 0,
  47. .size_bits = 4 },
  48. { STRUCT_FIELD(lrh, link_version),
  49. .offset_words = 0,
  50. .offset_bits = 4,
  51. .size_bits = 4 },
  52. { STRUCT_FIELD(lrh, service_level),
  53. .offset_words = 0,
  54. .offset_bits = 8,
  55. .size_bits = 4 },
  56. { RESERVED,
  57. .offset_words = 0,
  58. .offset_bits = 12,
  59. .size_bits = 2 },
  60. { STRUCT_FIELD(lrh, link_next_header),
  61. .offset_words = 0,
  62. .offset_bits = 14,
  63. .size_bits = 2 },
  64. { STRUCT_FIELD(lrh, destination_lid),
  65. .offset_words = 0,
  66. .offset_bits = 16,
  67. .size_bits = 16 },
  68. { RESERVED,
  69. .offset_words = 1,
  70. .offset_bits = 0,
  71. .size_bits = 5 },
  72. { STRUCT_FIELD(lrh, packet_length),
  73. .offset_words = 1,
  74. .offset_bits = 5,
  75. .size_bits = 11 },
  76. { STRUCT_FIELD(lrh, source_lid),
  77. .offset_words = 1,
  78. .offset_bits = 16,
  79. .size_bits = 16 }
  80. };
  81. static const struct ib_field eth_table[] = {
  82. { STRUCT_FIELD(eth, dmac_h),
  83. .offset_words = 0,
  84. .offset_bits = 0,
  85. .size_bits = 32 },
  86. { STRUCT_FIELD(eth, dmac_l),
  87. .offset_words = 1,
  88. .offset_bits = 0,
  89. .size_bits = 16 },
  90. { STRUCT_FIELD(eth, smac_h),
  91. .offset_words = 1,
  92. .offset_bits = 16,
  93. .size_bits = 16 },
  94. { STRUCT_FIELD(eth, smac_l),
  95. .offset_words = 2,
  96. .offset_bits = 0,
  97. .size_bits = 32 },
  98. { STRUCT_FIELD(eth, type),
  99. .offset_words = 3,
  100. .offset_bits = 0,
  101. .size_bits = 16 }
  102. };
  103. static const struct ib_field vlan_table[] = {
  104. { STRUCT_FIELD(vlan, tag),
  105. .offset_words = 0,
  106. .offset_bits = 0,
  107. .size_bits = 16 },
  108. { STRUCT_FIELD(vlan, type),
  109. .offset_words = 0,
  110. .offset_bits = 16,
  111. .size_bits = 16 }
  112. };
  113. static const struct ib_field ip4_table[] = {
  114. { STRUCT_FIELD(ip4, ver),
  115. .offset_words = 0,
  116. .offset_bits = 0,
  117. .size_bits = 4 },
  118. { STRUCT_FIELD(ip4, hdr_len),
  119. .offset_words = 0,
  120. .offset_bits = 4,
  121. .size_bits = 4 },
  122. { STRUCT_FIELD(ip4, tos),
  123. .offset_words = 0,
  124. .offset_bits = 8,
  125. .size_bits = 8 },
  126. { STRUCT_FIELD(ip4, tot_len),
  127. .offset_words = 0,
  128. .offset_bits = 16,
  129. .size_bits = 16 },
  130. { STRUCT_FIELD(ip4, id),
  131. .offset_words = 1,
  132. .offset_bits = 0,
  133. .size_bits = 16 },
  134. { STRUCT_FIELD(ip4, frag_off),
  135. .offset_words = 1,
  136. .offset_bits = 16,
  137. .size_bits = 16 },
  138. { STRUCT_FIELD(ip4, ttl),
  139. .offset_words = 2,
  140. .offset_bits = 0,
  141. .size_bits = 8 },
  142. { STRUCT_FIELD(ip4, protocol),
  143. .offset_words = 2,
  144. .offset_bits = 8,
  145. .size_bits = 8 },
  146. { STRUCT_FIELD(ip4, check),
  147. .offset_words = 2,
  148. .offset_bits = 16,
  149. .size_bits = 16 },
  150. { STRUCT_FIELD(ip4, saddr),
  151. .offset_words = 3,
  152. .offset_bits = 0,
  153. .size_bits = 32 },
  154. { STRUCT_FIELD(ip4, daddr),
  155. .offset_words = 4,
  156. .offset_bits = 0,
  157. .size_bits = 32 }
  158. };
  159. static const struct ib_field udp_table[] = {
  160. { STRUCT_FIELD(udp, sport),
  161. .offset_words = 0,
  162. .offset_bits = 0,
  163. .size_bits = 16 },
  164. { STRUCT_FIELD(udp, dport),
  165. .offset_words = 0,
  166. .offset_bits = 16,
  167. .size_bits = 16 },
  168. { STRUCT_FIELD(udp, length),
  169. .offset_words = 1,
  170. .offset_bits = 0,
  171. .size_bits = 16 },
  172. { STRUCT_FIELD(udp, csum),
  173. .offset_words = 1,
  174. .offset_bits = 16,
  175. .size_bits = 16 }
  176. };
  177. static const struct ib_field grh_table[] = {
  178. { STRUCT_FIELD(grh, ip_version),
  179. .offset_words = 0,
  180. .offset_bits = 0,
  181. .size_bits = 4 },
  182. { STRUCT_FIELD(grh, traffic_class),
  183. .offset_words = 0,
  184. .offset_bits = 4,
  185. .size_bits = 8 },
  186. { STRUCT_FIELD(grh, flow_label),
  187. .offset_words = 0,
  188. .offset_bits = 12,
  189. .size_bits = 20 },
  190. { STRUCT_FIELD(grh, payload_length),
  191. .offset_words = 1,
  192. .offset_bits = 0,
  193. .size_bits = 16 },
  194. { STRUCT_FIELD(grh, next_header),
  195. .offset_words = 1,
  196. .offset_bits = 16,
  197. .size_bits = 8 },
  198. { STRUCT_FIELD(grh, hop_limit),
  199. .offset_words = 1,
  200. .offset_bits = 24,
  201. .size_bits = 8 },
  202. { STRUCT_FIELD(grh, source_gid),
  203. .offset_words = 2,
  204. .offset_bits = 0,
  205. .size_bits = 128 },
  206. { STRUCT_FIELD(grh, destination_gid),
  207. .offset_words = 6,
  208. .offset_bits = 0,
  209. .size_bits = 128 }
  210. };
  211. static const struct ib_field bth_table[] = {
  212. { STRUCT_FIELD(bth, opcode),
  213. .offset_words = 0,
  214. .offset_bits = 0,
  215. .size_bits = 8 },
  216. { STRUCT_FIELD(bth, solicited_event),
  217. .offset_words = 0,
  218. .offset_bits = 8,
  219. .size_bits = 1 },
  220. { STRUCT_FIELD(bth, mig_req),
  221. .offset_words = 0,
  222. .offset_bits = 9,
  223. .size_bits = 1 },
  224. { STRUCT_FIELD(bth, pad_count),
  225. .offset_words = 0,
  226. .offset_bits = 10,
  227. .size_bits = 2 },
  228. { STRUCT_FIELD(bth, transport_header_version),
  229. .offset_words = 0,
  230. .offset_bits = 12,
  231. .size_bits = 4 },
  232. { STRUCT_FIELD(bth, pkey),
  233. .offset_words = 0,
  234. .offset_bits = 16,
  235. .size_bits = 16 },
  236. { RESERVED,
  237. .offset_words = 1,
  238. .offset_bits = 0,
  239. .size_bits = 8 },
  240. { STRUCT_FIELD(bth, destination_qpn),
  241. .offset_words = 1,
  242. .offset_bits = 8,
  243. .size_bits = 24 },
  244. { STRUCT_FIELD(bth, ack_req),
  245. .offset_words = 2,
  246. .offset_bits = 0,
  247. .size_bits = 1 },
  248. { RESERVED,
  249. .offset_words = 2,
  250. .offset_bits = 1,
  251. .size_bits = 7 },
  252. { STRUCT_FIELD(bth, psn),
  253. .offset_words = 2,
  254. .offset_bits = 8,
  255. .size_bits = 24 }
  256. };
  257. static const struct ib_field deth_table[] = {
  258. { STRUCT_FIELD(deth, qkey),
  259. .offset_words = 0,
  260. .offset_bits = 0,
  261. .size_bits = 32 },
  262. { RESERVED,
  263. .offset_words = 1,
  264. .offset_bits = 0,
  265. .size_bits = 8 },
  266. { STRUCT_FIELD(deth, source_qpn),
  267. .offset_words = 1,
  268. .offset_bits = 8,
  269. .size_bits = 24 }
  270. };
  271. __sum16 ib_ud_ip4_csum(struct ib_ud_header *header)
  272. {
  273. struct iphdr iph;
  274. iph.ihl = 5;
  275. iph.version = 4;
  276. iph.tos = header->ip4.tos;
  277. iph.tot_len = header->ip4.tot_len;
  278. iph.id = header->ip4.id;
  279. iph.frag_off = header->ip4.frag_off;
  280. iph.ttl = header->ip4.ttl;
  281. iph.protocol = header->ip4.protocol;
  282. iph.check = 0;
  283. iph.saddr = header->ip4.saddr;
  284. iph.daddr = header->ip4.daddr;
  285. return ip_fast_csum((u8 *)&iph, iph.ihl);
  286. }
  287. EXPORT_SYMBOL(ib_ud_ip4_csum);
  288. /**
  289. * ib_ud_header_init - Initialize UD header structure
  290. * @payload_bytes:Length of packet payload
  291. * @lrh_present: specify if LRH is present
  292. * @eth_present: specify if Eth header is present
  293. * @vlan_present: packet is tagged vlan
  294. * @grh_present: GRH flag (if non-zero, GRH will be included)
  295. * @ip_version: if non-zero, IP header, V4 or V6, will be included
  296. * @udp_present :if non-zero, UDP header will be included
  297. * @immediate_present: specify if immediate data is present
  298. * @header:Structure to initialize
  299. */
  300. int ib_ud_header_init(int payload_bytes,
  301. int lrh_present,
  302. int eth_present,
  303. int vlan_present,
  304. int grh_present,
  305. int ip_version,
  306. int udp_present,
  307. int immediate_present,
  308. struct ib_ud_header *header)
  309. {
  310. size_t udp_bytes = udp_present ? IB_UDP_BYTES : 0;
  311. grh_present = grh_present && !ip_version;
  312. memset(header, 0, sizeof *header);
  313. /*
  314. * UDP header without IP header doesn't make sense
  315. */
  316. if (udp_present && ip_version != 4 && ip_version != 6)
  317. return -EINVAL;
  318. if (lrh_present) {
  319. u16 packet_length;
  320. header->lrh.link_version = 0;
  321. header->lrh.link_next_header =
  322. grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
  323. packet_length = (IB_LRH_BYTES +
  324. IB_BTH_BYTES +
  325. IB_DETH_BYTES +
  326. (grh_present ? IB_GRH_BYTES : 0) +
  327. payload_bytes +
  328. 4 + /* ICRC */
  329. 3) / 4; /* round up */
  330. header->lrh.packet_length = cpu_to_be16(packet_length);
  331. }
  332. if (vlan_present)
  333. header->eth.type = cpu_to_be16(ETH_P_8021Q);
  334. if (ip_version == 6 || grh_present) {
  335. header->grh.ip_version = 6;
  336. header->grh.payload_length =
  337. cpu_to_be16((udp_bytes +
  338. IB_BTH_BYTES +
  339. IB_DETH_BYTES +
  340. payload_bytes +
  341. 4 + /* ICRC */
  342. 3) & ~3); /* round up */
  343. header->grh.next_header = udp_present ? IPPROTO_UDP : 0x1b;
  344. }
  345. if (ip_version == 4) {
  346. header->ip4.ver = 4; /* version 4 */
  347. header->ip4.hdr_len = 5; /* 5 words */
  348. header->ip4.tot_len =
  349. cpu_to_be16(IB_IP4_BYTES +
  350. udp_bytes +
  351. IB_BTH_BYTES +
  352. IB_DETH_BYTES +
  353. payload_bytes +
  354. 4); /* ICRC */
  355. header->ip4.protocol = IPPROTO_UDP;
  356. }
  357. if (udp_present && ip_version)
  358. header->udp.length =
  359. cpu_to_be16(IB_UDP_BYTES +
  360. IB_BTH_BYTES +
  361. IB_DETH_BYTES +
  362. payload_bytes +
  363. 4); /* ICRC */
  364. if (immediate_present)
  365. header->bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
  366. else
  367. header->bth.opcode = IB_OPCODE_UD_SEND_ONLY;
  368. header->bth.pad_count = (4 - payload_bytes) & 3;
  369. header->bth.transport_header_version = 0;
  370. header->lrh_present = lrh_present;
  371. header->eth_present = eth_present;
  372. header->vlan_present = vlan_present;
  373. header->grh_present = grh_present || (ip_version == 6);
  374. header->ipv4_present = ip_version == 4;
  375. header->udp_present = udp_present;
  376. header->immediate_present = immediate_present;
  377. return 0;
  378. }
  379. EXPORT_SYMBOL(ib_ud_header_init);
  380. /**
  381. * ib_ud_header_pack - Pack UD header struct into wire format
  382. * @header:UD header struct
  383. * @buf:Buffer to pack into
  384. *
  385. * ib_ud_header_pack() packs the UD header structure @header into wire
  386. * format in the buffer @buf.
  387. */
  388. int ib_ud_header_pack(struct ib_ud_header *header,
  389. void *buf)
  390. {
  391. int len = 0;
  392. if (header->lrh_present) {
  393. ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
  394. &header->lrh, buf + len);
  395. len += IB_LRH_BYTES;
  396. }
  397. if (header->eth_present) {
  398. ib_pack(eth_table, ARRAY_SIZE(eth_table),
  399. &header->eth, buf + len);
  400. len += IB_ETH_BYTES;
  401. }
  402. if (header->vlan_present) {
  403. ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
  404. &header->vlan, buf + len);
  405. len += IB_VLAN_BYTES;
  406. }
  407. if (header->grh_present) {
  408. ib_pack(grh_table, ARRAY_SIZE(grh_table),
  409. &header->grh, buf + len);
  410. len += IB_GRH_BYTES;
  411. }
  412. if (header->ipv4_present) {
  413. ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
  414. &header->ip4, buf + len);
  415. len += IB_IP4_BYTES;
  416. }
  417. if (header->udp_present) {
  418. ib_pack(udp_table, ARRAY_SIZE(udp_table),
  419. &header->udp, buf + len);
  420. len += IB_UDP_BYTES;
  421. }
  422. ib_pack(bth_table, ARRAY_SIZE(bth_table),
  423. &header->bth, buf + len);
  424. len += IB_BTH_BYTES;
  425. ib_pack(deth_table, ARRAY_SIZE(deth_table),
  426. &header->deth, buf + len);
  427. len += IB_DETH_BYTES;
  428. if (header->immediate_present) {
  429. memcpy(buf + len, &header->immediate_data, sizeof header->immediate_data);
  430. len += sizeof header->immediate_data;
  431. }
  432. return len;
  433. }
  434. EXPORT_SYMBOL(ib_ud_header_pack);
  435. /**
  436. * ib_ud_header_unpack - Unpack UD header struct from wire format
  437. * @header:UD header struct
  438. * @buf:Buffer to pack into
  439. *
  440. * ib_ud_header_pack() unpacks the UD header structure @header from wire
  441. * format in the buffer @buf.
  442. */
  443. int ib_ud_header_unpack(void *buf,
  444. struct ib_ud_header *header)
  445. {
  446. ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
  447. buf, &header->lrh);
  448. buf += IB_LRH_BYTES;
  449. if (header->lrh.link_version != 0) {
  450. pr_warn("Invalid LRH.link_version %d\n",
  451. header->lrh.link_version);
  452. return -EINVAL;
  453. }
  454. switch (header->lrh.link_next_header) {
  455. case IB_LNH_IBA_LOCAL:
  456. header->grh_present = 0;
  457. break;
  458. case IB_LNH_IBA_GLOBAL:
  459. header->grh_present = 1;
  460. ib_unpack(grh_table, ARRAY_SIZE(grh_table),
  461. buf, &header->grh);
  462. buf += IB_GRH_BYTES;
  463. if (header->grh.ip_version != 6) {
  464. pr_warn("Invalid GRH.ip_version %d\n",
  465. header->grh.ip_version);
  466. return -EINVAL;
  467. }
  468. if (header->grh.next_header != 0x1b) {
  469. pr_warn("Invalid GRH.next_header 0x%02x\n",
  470. header->grh.next_header);
  471. return -EINVAL;
  472. }
  473. break;
  474. default:
  475. pr_warn("Invalid LRH.link_next_header %d\n",
  476. header->lrh.link_next_header);
  477. return -EINVAL;
  478. }
  479. ib_unpack(bth_table, ARRAY_SIZE(bth_table),
  480. buf, &header->bth);
  481. buf += IB_BTH_BYTES;
  482. switch (header->bth.opcode) {
  483. case IB_OPCODE_UD_SEND_ONLY:
  484. header->immediate_present = 0;
  485. break;
  486. case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
  487. header->immediate_present = 1;
  488. break;
  489. default:
  490. pr_warn("Invalid BTH.opcode 0x%02x\n", header->bth.opcode);
  491. return -EINVAL;
  492. }
  493. if (header->bth.transport_header_version != 0) {
  494. pr_warn("Invalid BTH.transport_header_version %d\n",
  495. header->bth.transport_header_version);
  496. return -EINVAL;
  497. }
  498. ib_unpack(deth_table, ARRAY_SIZE(deth_table),
  499. buf, &header->deth);
  500. buf += IB_DETH_BYTES;
  501. if (header->immediate_present)
  502. memcpy(&header->immediate_data, buf, sizeof header->immediate_data);
  503. return 0;
  504. }
  505. EXPORT_SYMBOL(ib_ud_header_unpack);