1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (c) 2004 Topspin Corporation. All rights reserved. 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun #ifndef IB_PACK_H 7*4882a593Smuzhiyun #define IB_PACK_H 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include <rdma/ib_verbs.h> 10*4882a593Smuzhiyun #include <uapi/linux/if_ether.h> 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun enum { 13*4882a593Smuzhiyun IB_LRH_BYTES = 8, 14*4882a593Smuzhiyun IB_ETH_BYTES = 14, 15*4882a593Smuzhiyun IB_VLAN_BYTES = 4, 16*4882a593Smuzhiyun IB_GRH_BYTES = 40, 17*4882a593Smuzhiyun IB_IP4_BYTES = 20, 18*4882a593Smuzhiyun IB_UDP_BYTES = 8, 19*4882a593Smuzhiyun IB_BTH_BYTES = 12, 20*4882a593Smuzhiyun IB_DETH_BYTES = 8, 21*4882a593Smuzhiyun IB_EXT_ATOMICETH_BYTES = 28, 22*4882a593Smuzhiyun IB_EXT_XRC_BYTES = 4, 23*4882a593Smuzhiyun IB_ICRC_BYTES = 4 24*4882a593Smuzhiyun }; 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun struct ib_field { 27*4882a593Smuzhiyun size_t struct_offset_bytes; 28*4882a593Smuzhiyun size_t struct_size_bytes; 29*4882a593Smuzhiyun int offset_words; 30*4882a593Smuzhiyun int offset_bits; 31*4882a593Smuzhiyun int size_bits; 32*4882a593Smuzhiyun char *field_name; 33*4882a593Smuzhiyun }; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun #define RESERVED \ 36*4882a593Smuzhiyun .field_name = "reserved" 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun /* 39*4882a593Smuzhiyun * This macro cleans up the definitions of constants for BTH opcodes. 40*4882a593Smuzhiyun * It is used to define constants such as IB_OPCODE_UD_SEND_ONLY, 41*4882a593Smuzhiyun * which becomes IB_OPCODE_UD + IB_OPCODE_SEND_ONLY, and this gives 42*4882a593Smuzhiyun * the correct value. 43*4882a593Smuzhiyun * 44*4882a593Smuzhiyun * In short, user code should use the constants defined using the 45*4882a593Smuzhiyun * macro rather than worrying about adding together other constants. 46*4882a593Smuzhiyun */ 47*4882a593Smuzhiyun #define IB_OPCODE(transport, op) \ 48*4882a593Smuzhiyun IB_OPCODE_ ## transport ## _ ## op = \ 49*4882a593Smuzhiyun IB_OPCODE_ ## transport + IB_OPCODE_ ## op 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun enum { 52*4882a593Smuzhiyun /* transport types -- just used to define real constants */ 53*4882a593Smuzhiyun IB_OPCODE_RC = 0x00, 54*4882a593Smuzhiyun IB_OPCODE_UC = 0x20, 55*4882a593Smuzhiyun IB_OPCODE_RD = 0x40, 56*4882a593Smuzhiyun IB_OPCODE_UD = 0x60, 57*4882a593Smuzhiyun /* per IBTA 1.3 vol 1 Table 38, A10.3.2 */ 58*4882a593Smuzhiyun IB_OPCODE_CNP = 0x80, 59*4882a593Smuzhiyun /* Manufacturer specific */ 60*4882a593Smuzhiyun IB_OPCODE_MSP = 0xe0, 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun /* operations -- just used to define real constants */ 63*4882a593Smuzhiyun IB_OPCODE_SEND_FIRST = 0x00, 64*4882a593Smuzhiyun IB_OPCODE_SEND_MIDDLE = 0x01, 65*4882a593Smuzhiyun IB_OPCODE_SEND_LAST = 0x02, 66*4882a593Smuzhiyun IB_OPCODE_SEND_LAST_WITH_IMMEDIATE = 0x03, 67*4882a593Smuzhiyun IB_OPCODE_SEND_ONLY = 0x04, 68*4882a593Smuzhiyun IB_OPCODE_SEND_ONLY_WITH_IMMEDIATE = 0x05, 69*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_FIRST = 0x06, 70*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_MIDDLE = 0x07, 71*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_LAST = 0x08, 72*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_LAST_WITH_IMMEDIATE = 0x09, 73*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_ONLY = 0x0a, 74*4882a593Smuzhiyun IB_OPCODE_RDMA_WRITE_ONLY_WITH_IMMEDIATE = 0x0b, 75*4882a593Smuzhiyun IB_OPCODE_RDMA_READ_REQUEST = 0x0c, 76*4882a593Smuzhiyun IB_OPCODE_RDMA_READ_RESPONSE_FIRST = 0x0d, 77*4882a593Smuzhiyun IB_OPCODE_RDMA_READ_RESPONSE_MIDDLE = 0x0e, 78*4882a593Smuzhiyun IB_OPCODE_RDMA_READ_RESPONSE_LAST = 0x0f, 79*4882a593Smuzhiyun IB_OPCODE_RDMA_READ_RESPONSE_ONLY = 0x10, 80*4882a593Smuzhiyun IB_OPCODE_ACKNOWLEDGE = 0x11, 81*4882a593Smuzhiyun IB_OPCODE_ATOMIC_ACKNOWLEDGE = 0x12, 82*4882a593Smuzhiyun IB_OPCODE_COMPARE_SWAP = 0x13, 83*4882a593Smuzhiyun IB_OPCODE_FETCH_ADD = 0x14, 84*4882a593Smuzhiyun /* opcode 0x15 is reserved */ 85*4882a593Smuzhiyun IB_OPCODE_SEND_LAST_WITH_INVALIDATE = 0x16, 86*4882a593Smuzhiyun IB_OPCODE_SEND_ONLY_WITH_INVALIDATE = 0x17, 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun /* real constants follow -- see comment about above IB_OPCODE() 89*4882a593Smuzhiyun macro for more details */ 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun /* RC */ 92*4882a593Smuzhiyun IB_OPCODE(RC, SEND_FIRST), 93*4882a593Smuzhiyun IB_OPCODE(RC, SEND_MIDDLE), 94*4882a593Smuzhiyun IB_OPCODE(RC, SEND_LAST), 95*4882a593Smuzhiyun IB_OPCODE(RC, SEND_LAST_WITH_IMMEDIATE), 96*4882a593Smuzhiyun IB_OPCODE(RC, SEND_ONLY), 97*4882a593Smuzhiyun IB_OPCODE(RC, SEND_ONLY_WITH_IMMEDIATE), 98*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_FIRST), 99*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_MIDDLE), 100*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_LAST), 101*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_LAST_WITH_IMMEDIATE), 102*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_ONLY), 103*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_WRITE_ONLY_WITH_IMMEDIATE), 104*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_READ_REQUEST), 105*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_READ_RESPONSE_FIRST), 106*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_READ_RESPONSE_MIDDLE), 107*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_READ_RESPONSE_LAST), 108*4882a593Smuzhiyun IB_OPCODE(RC, RDMA_READ_RESPONSE_ONLY), 109*4882a593Smuzhiyun IB_OPCODE(RC, ACKNOWLEDGE), 110*4882a593Smuzhiyun IB_OPCODE(RC, ATOMIC_ACKNOWLEDGE), 111*4882a593Smuzhiyun IB_OPCODE(RC, COMPARE_SWAP), 112*4882a593Smuzhiyun IB_OPCODE(RC, FETCH_ADD), 113*4882a593Smuzhiyun IB_OPCODE(RC, SEND_LAST_WITH_INVALIDATE), 114*4882a593Smuzhiyun IB_OPCODE(RC, SEND_ONLY_WITH_INVALIDATE), 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun /* UC */ 117*4882a593Smuzhiyun IB_OPCODE(UC, SEND_FIRST), 118*4882a593Smuzhiyun IB_OPCODE(UC, SEND_MIDDLE), 119*4882a593Smuzhiyun IB_OPCODE(UC, SEND_LAST), 120*4882a593Smuzhiyun IB_OPCODE(UC, SEND_LAST_WITH_IMMEDIATE), 121*4882a593Smuzhiyun IB_OPCODE(UC, SEND_ONLY), 122*4882a593Smuzhiyun IB_OPCODE(UC, SEND_ONLY_WITH_IMMEDIATE), 123*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_FIRST), 124*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_MIDDLE), 125*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_LAST), 126*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_LAST_WITH_IMMEDIATE), 127*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_ONLY), 128*4882a593Smuzhiyun IB_OPCODE(UC, RDMA_WRITE_ONLY_WITH_IMMEDIATE), 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun /* RD */ 131*4882a593Smuzhiyun IB_OPCODE(RD, SEND_FIRST), 132*4882a593Smuzhiyun IB_OPCODE(RD, SEND_MIDDLE), 133*4882a593Smuzhiyun IB_OPCODE(RD, SEND_LAST), 134*4882a593Smuzhiyun IB_OPCODE(RD, SEND_LAST_WITH_IMMEDIATE), 135*4882a593Smuzhiyun IB_OPCODE(RD, SEND_ONLY), 136*4882a593Smuzhiyun IB_OPCODE(RD, SEND_ONLY_WITH_IMMEDIATE), 137*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_FIRST), 138*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_MIDDLE), 139*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_LAST), 140*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_LAST_WITH_IMMEDIATE), 141*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_ONLY), 142*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_WRITE_ONLY_WITH_IMMEDIATE), 143*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_READ_REQUEST), 144*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_READ_RESPONSE_FIRST), 145*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_READ_RESPONSE_MIDDLE), 146*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_READ_RESPONSE_LAST), 147*4882a593Smuzhiyun IB_OPCODE(RD, RDMA_READ_RESPONSE_ONLY), 148*4882a593Smuzhiyun IB_OPCODE(RD, ACKNOWLEDGE), 149*4882a593Smuzhiyun IB_OPCODE(RD, ATOMIC_ACKNOWLEDGE), 150*4882a593Smuzhiyun IB_OPCODE(RD, COMPARE_SWAP), 151*4882a593Smuzhiyun IB_OPCODE(RD, FETCH_ADD), 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun /* UD */ 154*4882a593Smuzhiyun IB_OPCODE(UD, SEND_ONLY), 155*4882a593Smuzhiyun IB_OPCODE(UD, SEND_ONLY_WITH_IMMEDIATE) 156*4882a593Smuzhiyun }; 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun enum { 159*4882a593Smuzhiyun IB_LNH_RAW = 0, 160*4882a593Smuzhiyun IB_LNH_IP = 1, 161*4882a593Smuzhiyun IB_LNH_IBA_LOCAL = 2, 162*4882a593Smuzhiyun IB_LNH_IBA_GLOBAL = 3 163*4882a593Smuzhiyun }; 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun struct ib_unpacked_lrh { 166*4882a593Smuzhiyun u8 virtual_lane; 167*4882a593Smuzhiyun u8 link_version; 168*4882a593Smuzhiyun u8 service_level; 169*4882a593Smuzhiyun u8 link_next_header; 170*4882a593Smuzhiyun __be16 destination_lid; 171*4882a593Smuzhiyun __be16 packet_length; 172*4882a593Smuzhiyun __be16 source_lid; 173*4882a593Smuzhiyun }; 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun struct ib_unpacked_grh { 176*4882a593Smuzhiyun u8 ip_version; 177*4882a593Smuzhiyun u8 traffic_class; 178*4882a593Smuzhiyun __be32 flow_label; 179*4882a593Smuzhiyun __be16 payload_length; 180*4882a593Smuzhiyun u8 next_header; 181*4882a593Smuzhiyun u8 hop_limit; 182*4882a593Smuzhiyun union ib_gid source_gid; 183*4882a593Smuzhiyun union ib_gid destination_gid; 184*4882a593Smuzhiyun }; 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun struct ib_unpacked_bth { 187*4882a593Smuzhiyun u8 opcode; 188*4882a593Smuzhiyun u8 solicited_event; 189*4882a593Smuzhiyun u8 mig_req; 190*4882a593Smuzhiyun u8 pad_count; 191*4882a593Smuzhiyun u8 transport_header_version; 192*4882a593Smuzhiyun __be16 pkey; 193*4882a593Smuzhiyun __be32 destination_qpn; 194*4882a593Smuzhiyun u8 ack_req; 195*4882a593Smuzhiyun __be32 psn; 196*4882a593Smuzhiyun }; 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun struct ib_unpacked_deth { 199*4882a593Smuzhiyun __be32 qkey; 200*4882a593Smuzhiyun __be32 source_qpn; 201*4882a593Smuzhiyun }; 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun struct ib_unpacked_eth { 204*4882a593Smuzhiyun u8 dmac_h[4]; 205*4882a593Smuzhiyun u8 dmac_l[2]; 206*4882a593Smuzhiyun u8 smac_h[2]; 207*4882a593Smuzhiyun u8 smac_l[4]; 208*4882a593Smuzhiyun __be16 type; 209*4882a593Smuzhiyun }; 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun struct ib_unpacked_ip4 { 212*4882a593Smuzhiyun u8 ver; 213*4882a593Smuzhiyun u8 hdr_len; 214*4882a593Smuzhiyun u8 tos; 215*4882a593Smuzhiyun __be16 tot_len; 216*4882a593Smuzhiyun __be16 id; 217*4882a593Smuzhiyun __be16 frag_off; 218*4882a593Smuzhiyun u8 ttl; 219*4882a593Smuzhiyun u8 protocol; 220*4882a593Smuzhiyun __sum16 check; 221*4882a593Smuzhiyun __be32 saddr; 222*4882a593Smuzhiyun __be32 daddr; 223*4882a593Smuzhiyun }; 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun struct ib_unpacked_udp { 226*4882a593Smuzhiyun __be16 sport; 227*4882a593Smuzhiyun __be16 dport; 228*4882a593Smuzhiyun __be16 length; 229*4882a593Smuzhiyun __be16 csum; 230*4882a593Smuzhiyun }; 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun struct ib_unpacked_vlan { 233*4882a593Smuzhiyun __be16 tag; 234*4882a593Smuzhiyun __be16 type; 235*4882a593Smuzhiyun }; 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun struct ib_ud_header { 238*4882a593Smuzhiyun int lrh_present; 239*4882a593Smuzhiyun struct ib_unpacked_lrh lrh; 240*4882a593Smuzhiyun int eth_present; 241*4882a593Smuzhiyun struct ib_unpacked_eth eth; 242*4882a593Smuzhiyun int vlan_present; 243*4882a593Smuzhiyun struct ib_unpacked_vlan vlan; 244*4882a593Smuzhiyun int grh_present; 245*4882a593Smuzhiyun struct ib_unpacked_grh grh; 246*4882a593Smuzhiyun int ipv4_present; 247*4882a593Smuzhiyun struct ib_unpacked_ip4 ip4; 248*4882a593Smuzhiyun int udp_present; 249*4882a593Smuzhiyun struct ib_unpacked_udp udp; 250*4882a593Smuzhiyun struct ib_unpacked_bth bth; 251*4882a593Smuzhiyun struct ib_unpacked_deth deth; 252*4882a593Smuzhiyun int immediate_present; 253*4882a593Smuzhiyun __be32 immediate_data; 254*4882a593Smuzhiyun }; 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun void ib_pack(const struct ib_field *desc, 257*4882a593Smuzhiyun int desc_len, 258*4882a593Smuzhiyun void *structure, 259*4882a593Smuzhiyun void *buf); 260*4882a593Smuzhiyun 261*4882a593Smuzhiyun void ib_unpack(const struct ib_field *desc, 262*4882a593Smuzhiyun int desc_len, 263*4882a593Smuzhiyun void *buf, 264*4882a593Smuzhiyun void *structure); 265*4882a593Smuzhiyun 266*4882a593Smuzhiyun __sum16 ib_ud_ip4_csum(struct ib_ud_header *header); 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun int ib_ud_header_init(int payload_bytes, 269*4882a593Smuzhiyun int lrh_present, 270*4882a593Smuzhiyun int eth_present, 271*4882a593Smuzhiyun int vlan_present, 272*4882a593Smuzhiyun int grh_present, 273*4882a593Smuzhiyun int ip_version, 274*4882a593Smuzhiyun int udp_present, 275*4882a593Smuzhiyun int immediate_present, 276*4882a593Smuzhiyun struct ib_ud_header *header); 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun int ib_ud_header_pack(struct ib_ud_header *header, 279*4882a593Smuzhiyun void *buf); 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun int ib_ud_header_unpack(void *buf, 282*4882a593Smuzhiyun struct ib_ud_header *header); 283*4882a593Smuzhiyun 284*4882a593Smuzhiyun #endif /* IB_PACK_H */ 285