fba210938b0c2a280d73116819b7837763e09bfa
[mirror/winof/.git] / ulp / libibmad / src / mad.c
1 /*\r
2  * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenFabrics.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  */\r
29 \r
30 #if HAVE_CONFIG_H\r
31 #  include <config.h>\r
32 #endif /* HAVE_CONFIG_H */\r
33 \r
34 #include <stdio.h>\r
35 #include <stdlib.h>\r
36 \r
37 #if defined(_WIN32) || defined(_WIN64)\r
38 #include <windows.h>\r
39 #include <winsock2.h>\r
40 #include <time.h>\r
41 #define getpid GetCurrentProcessId\r
42 #else\r
43 #include <unistd.h>\r
44 #include <string.h>\r
45 #include <pthread.h>\r
46 #include <sys/time.h>\r
47 #endif\r
48 \r
49 #include <infiniband/umad.h>\r
50 #include <mad.h>\r
51 \r
52 #undef DEBUG\r
53 #define DEBUG   if (ibdebug)    IBWARN\r
54 \r
55 MAD_EXPORT uint32_t\r
56 mad_get_field(void *buf, int base_offs, int field)\r
57 {\r
58         return _get_field(buf, base_offs, ib_mad_f + field);\r
59 }\r
60 \r
61 MAD_EXPORT void\r
62 mad_set_field(void *buf, int base_offs, int field, uint32_t val)\r
63 {\r
64         _set_field(buf, base_offs, ib_mad_f + field, val);\r
65 }\r
66 \r
67 /* field must be byte aligned */\r
68 MAD_EXPORT uint64_t\r
69 mad_get_field64(void *buf, int base_offs, int field)\r
70 {\r
71         return _get_field64(buf, base_offs, ib_mad_f + field);\r
72 }\r
73 \r
74 MAD_EXPORT void\r
75 mad_set_field64(void *buf, int base_offs, int field, uint64_t val)\r
76 {\r
77         _set_field64(buf, base_offs, ib_mad_f + field, val);\r
78 }\r
79 \r
80 MAD_EXPORT void\r
81 mad_set_array(void *buf, int base_offs, int field, void *val)\r
82 {\r
83         _set_array(buf, base_offs, ib_mad_f + field, val);\r
84 }\r
85 \r
86 MAD_EXPORT void\r
87 mad_get_array(void *buf, int base_offs, int field, void *val)\r
88 {\r
89         _get_array(buf, base_offs, ib_mad_f + field, val);\r
90 }\r
91 \r
92 MAD_EXPORT void\r
93 mad_decode_field(uint8_t *buf, int field, void *val)\r
94 {\r
95         ib_field_t *f = ib_mad_f + field;\r
96 \r
97         if (!field) {\r
98                 *(int *)val = *(int *)buf;\r
99                 return;\r
100         }\r
101         if (f->bitlen <= 32) {\r
102                 *(uint32_t *)val = _get_field(buf, 0, f);\r
103                 return;\r
104         }\r
105         if (f->bitlen == 64) {\r
106                 *(uint64_t *)val = _get_field64(buf, 0, f);\r
107                 return;\r
108         }\r
109         _get_array(buf, 0, f, val);\r
110 }\r
111 \r
112 MAD_EXPORT void\r
113 mad_encode_field(uint8_t *buf, int field, void *val)\r
114 {\r
115         ib_field_t *f = ib_mad_f + field;\r
116 \r
117         if (!field) {\r
118                 *(int *)buf = *(int *)val;\r
119                 return;\r
120         }\r
121         if (f->bitlen <= 32) {\r
122                 _set_field(buf, 0, f, *(uint32_t *)val);\r
123                 return;\r
124         }\r
125         if (f->bitlen == 64) {\r
126                 _set_field64(buf, 0, f, *(uint64_t *)val);\r
127                 return;\r
128         }\r
129         _set_array(buf, 0, f, val);\r
130 }\r
131 \r
132 MAD_EXPORT uint64_t\r
133 mad_trid(void)\r
134 {\r
135         static uint64_t base;\r
136         static uint64_t trid;\r
137         uint64_t next;\r
138 \r
139         if (!base) {\r
140                 srand((int)time(0)*getpid());\r
141                 base = rand();\r
142                 trid = rand();\r
143         }\r
144         next = ++trid | (base << 32);\r
145         return next;\r
146 }\r
147 \r
148 MAD_EXPORT void *\r
149 mad_encode(void *buf, ib_rpc_t *rpc, ib_dr_path_t *drpath, void *data)\r
150 {\r
151         int is_resp = rpc->method & IB_MAD_RESPONSE;\r
152 \r
153         /* first word */\r
154         mad_set_field(buf, 0, IB_MAD_METHOD_F, rpc->method);\r
155         mad_set_field(buf, 0, IB_MAD_RESPONSE_F, is_resp ? 1 : 0);\r
156         mad_set_field(buf, 0, IB_MAD_CLASSVER_F, rpc->mgtclass == IB_SA_CLASS ? 2 : 1);\r
157         mad_set_field(buf, 0, IB_MAD_MGMTCLASS_F, rpc->mgtclass);\r
158         mad_set_field(buf, 0, IB_MAD_BASEVER_F, 1);\r
159 \r
160         /* second word */\r
161         if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) {\r
162                 if (!drpath) {\r
163                         IBWARN("encoding dr mad without drpath (null)");\r
164                         return 0;\r
165                 }\r
166                 mad_set_field(buf, 0, IB_DRSMP_HOPCNT_F, drpath->cnt);\r
167                 mad_set_field(buf, 0, IB_DRSMP_HOPPTR_F, is_resp ? drpath->cnt + 1 : 0x0);\r
168                 mad_set_field(buf, 0, IB_DRSMP_STATUS_F, rpc->rstatus);\r
169                 mad_set_field(buf, 0, IB_DRSMP_DIRECTION_F, is_resp ? 1 : 0);   /* out */\r
170         } else\r
171                 mad_set_field(buf, 0, IB_MAD_STATUS_F, rpc->rstatus);\r
172 \r
173         /* words 3,4,5,6 */\r
174         if (!rpc->trid)\r
175                 rpc->trid = mad_trid();\r
176 \r
177         mad_set_field64(buf, 0, IB_MAD_TRID_F, rpc->trid);\r
178         mad_set_field(buf, 0, IB_MAD_ATTRID_F, rpc->attr.id);\r
179         mad_set_field(buf, 0, IB_MAD_ATTRMOD_F, rpc->attr.mod);\r
180 \r
181         /* words 7,8 */\r
182         mad_set_field(buf, 0, IB_MAD_MKEY_F, (uint32_t)(rpc->mkey >> 32));\r
183         mad_set_field(buf, 4, IB_MAD_MKEY_F, (uint32_t)(rpc->mkey & 0xffffffff));\r
184 \r
185         if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) {\r
186                 /* word 9 */\r
187                 mad_set_field(buf, 0, IB_DRSMP_DRDLID_F, drpath->drdlid ? drpath->drdlid : 0xffff);\r
188                 mad_set_field(buf, 0, IB_DRSMP_DRSLID_F, drpath->drslid ? drpath->drslid : 0xffff);\r
189 \r
190                 /* bytes 128 - 256 - by default should be zero due to memset*/\r
191                 if (is_resp)\r
192                         mad_set_array(buf, 0, IB_DRSMP_RPATH_F, drpath->p);\r
193                 else\r
194                         mad_set_array(buf, 0, IB_DRSMP_PATH_F, drpath->p);\r
195         }\r
196 \r
197         if (rpc->mgtclass == IB_SA_CLASS)\r
198                 mad_set_field64(buf, 0, IB_SA_COMPMASK_F, rpc->mask);\r
199 \r
200         if (data)\r
201                 memcpy((char *)buf + rpc->dataoffs, data, rpc->datasz);\r
202 \r
203         /* vendor mads range 2 */\r
204         if (mad_is_vendor_range2(rpc->mgtclass))\r
205                 mad_set_field(buf, 0, IB_VEND2_OUI_F, rpc->oui);\r
206 \r
207         return (uint8_t *)buf + IB_MAD_SIZE;\r
208 }\r
209 \r
210 MAD_EXPORT int\r
211 mad_build_pkt(void *umad, ib_rpc_t *rpc, ib_portid_t *dport,\r
212               ib_rmpp_hdr_t *rmpp, void *data)\r
213 {\r
214         uint8_t *p, *mad;\r
215         int lid_routed = rpc->mgtclass != IB_SMI_DIRECT_CLASS;\r
216         int is_smi = (rpc->mgtclass == IB_SMI_CLASS ||\r
217                       rpc->mgtclass == IB_SMI_DIRECT_CLASS);\r
218         struct ib_mad_addr addr;\r
219 \r
220         if (!is_smi)\r
221                 umad_set_addr(umad, dport->lid, dport->qp, dport->sl, dport->qkey);\r
222         else if (lid_routed)\r
223                 umad_set_addr(umad, dport->lid, dport->qp, 0, 0);\r
224         else\r
225                 if ((dport->drpath.drslid != 0xffff) && (dport->lid > 0))\r
226                         umad_set_addr(umad, dport->lid, 0, 0, 0);\r
227                 else\r
228                         umad_set_addr(umad, 0xffff, 0, 0, 0);\r
229 \r
230         if (dport->grh_present && !is_smi) {\r
231                 addr.grh_present = 1;\r
232                 memcpy(addr.gid, dport->gid, 16);\r
233                 addr.hop_limit = 0xff;\r
234                 addr.traffic_class = 0;\r
235                 addr.flow_label = 0;\r
236                 umad_set_grh(umad, &addr);\r
237         } else\r
238                 umad_set_grh(umad, 0);\r
239         umad_set_pkey(umad, is_smi ? 0 : dport->pkey_idx);\r
240 \r
241         mad = umad_get_mad(umad);\r
242         p = mad_encode(mad, rpc, lid_routed ? 0 : &dport->drpath, data);\r
243 \r
244         if (!is_smi && rmpp) {\r
245                 mad_set_field(mad, 0, IB_SA_RMPP_VERS_F, 1);\r
246                 mad_set_field(mad, 0, IB_SA_RMPP_TYPE_F, rmpp->type);\r
247                 mad_set_field(mad, 0, IB_SA_RMPP_RESP_F, 0x3f);\r
248                 mad_set_field(mad, 0, IB_SA_RMPP_FLAGS_F, rmpp->flags);\r
249                 mad_set_field(mad, 0, IB_SA_RMPP_STATUS_F, rmpp->status);\r
250                 mad_set_field(mad, 0, IB_SA_RMPP_D1_F, rmpp->d1.u);\r
251                 mad_set_field(mad, 0, IB_SA_RMPP_D2_F, rmpp->d2.u);\r
252         }\r
253 \r
254         return ((int)(p - mad));\r
255 }\r