]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/osmtest/osmt_slvl_vl_arb.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / osmtest / osmt_slvl_vl_arb.c
1 /*
2  * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35
36 /*
37  * Abstract:
38  *    Implementation of SLtoVL and VL Arbitration testing flow..
39  *    Top level is osmt_run_slvl_and_vlarb_records_flow:
40  *     osmt_query_all_ports_vl_arb
41  *     osmt_query_all_ports_slvl_map
42  *
43  */
44
45 #ifndef __WIN__
46 #include <unistd.h>
47 #endif
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <complib/cl_debug.h>
52 #include "osmtest.h"
53
54 /**********************************************************************
55  **********************************************************************/
56 static ib_api_status_t
57 osmtest_write_vl_arb_table(IN osmtest_t * const p_osmt,
58                            IN FILE * fh,
59                            IN const ib_vl_arb_table_record_t * const p_rec)
60 {
61         int result, i;
62         cl_status_t status = IB_SUCCESS;
63
64         OSM_LOG_ENTER(&p_osmt->log);
65
66         result = fprintf(fh,
67                          "VL_ARBITRATION_TABLE\n"
68                          "lid                     0x%X\n"
69                          "port_num                0x%X\n"
70                          "block                   0x%X\n",
71                          cl_ntoh16(p_rec->lid),
72                          p_rec->port_num, p_rec->block_num);
73
74         fprintf(fh, "       ");
75         for (i = 0; i < 32; i++)
76                 fprintf(fh, "| %-2u ", i);
77         fprintf(fh, "|\nVL:    ");
78
79         for (i = 0; i < 32; i++)
80                 fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].vl);
81         fprintf(fh, "|\nWEIGHT:");
82
83         for (i = 0; i < 32; i++)
84                 fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].weight);
85         fprintf(fh, "|\nEND\n\n");
86
87         /*  Exit: */
88         OSM_LOG_EXIT(&p_osmt->log);
89         return (status);
90 }
91
92 /**********************************************************************
93  * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
94  **********************************************************************/
95 ib_api_status_t
96 osmt_query_vl_arb(IN osmtest_t * const p_osmt,
97                   IN ib_net16_t const lid,
98                   IN uint8_t const port_num,
99                   IN uint8_t const block_num, IN FILE * fh)
100 {
101         osmtest_req_context_t context;
102         ib_api_status_t status = IB_SUCCESS;
103         osmv_user_query_t user;
104         osmv_query_req_t req;
105         ib_vl_arb_table_record_t record, *p_rec;
106
107         OSM_LOG_ENTER(&p_osmt->log);
108
109         OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
110                 "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n",
111                 cl_ntoh16(lid), port_num);
112
113         /*
114          * Do a blocking query for this record in the subnet.
115          * The result is returned in the result field of the caller's
116          * context structure.
117          *
118          * The query structures are locals.
119          */
120         memset(&req, 0, sizeof(req));
121         memset(&user, 0, sizeof(user));
122         memset(&context, 0, sizeof(context));
123
124         context.p_osmt = p_osmt;
125
126         record.lid = lid;
127         record.port_num = port_num;
128         record.block_num = block_num;
129         user.p_attr = &record;
130
131         req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK;
132         req.timeout_ms = p_osmt->opt.transaction_timeout;
133         req.retry_cnt = p_osmt->opt.retry_count;
134         req.flags = OSM_SA_FLAGS_SYNC;
135         req.query_context = &context;
136         req.pfn_query_cb = osmtest_query_res_cb;
137         req.p_query_input = &user;
138         req.sm_key = 0;
139
140         status = osmv_query_sa(p_osmt->h_bind, &req);
141
142         if (status != IB_SUCCESS) {
143                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0405: "
144                         "ib_query failed (%s)\n", ib_get_err_str(status));
145                 goto Exit;
146         }
147
148         status = context.result.status;
149
150         if (status != IB_SUCCESS) {
151                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0466: "
152                         "ib_query failed (%s)\n", ib_get_err_str(status));
153
154                 if (status == IB_REMOTE_ERROR) {
155                         OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
156                                 "Remote error = %s\n",
157                                 ib_get_mad_status_str(osm_madw_get_mad_ptr
158                                                       (context.result.
159                                                        p_result_madw)));
160                 }
161                 goto Exit;
162         }
163
164         /* ok it worked */
165         p_rec = osmv_get_query_result(context.result.p_result_madw, 0);
166         if (fh) {
167                 osmtest_write_vl_arb_table(p_osmt, fh, p_rec);
168         }
169
170 Exit:
171         /*
172          * Return the IB query MAD to the pool as necessary.
173          */
174         if (context.result.p_result_madw != NULL) {
175                 osm_mad_pool_put(&p_osmt->mad_pool,
176                                  context.result.p_result_madw);
177                 context.result.p_result_madw = NULL;
178         }
179
180         OSM_LOG_EXIT(&p_osmt->log);
181         return (status);
182 }
183
184 static ib_api_status_t
185 osmt_query_all_ports_vl_arb(IN osmtest_t * const p_osmt, IN FILE * fh)
186 {
187         cl_status_t status = CL_SUCCESS;
188         cl_qmap_t *p_tbl;
189         port_t *p_src_port;
190         uint8_t block, anyErr = 0;
191
192         OSM_LOG_ENTER(&p_osmt->log);
193
194         OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
195                 "Obtaining ALL Ports VL Arbitration Tables\n");
196
197         /*
198          * Go over all ports that exist in the subnet
199          * get the relevant VLarbs
200          */
201
202         p_tbl = &p_osmt->exp_subn.port_key_tbl;
203
204         p_src_port = (port_t *) cl_qmap_head(p_tbl);
205
206         while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) {
207
208                 /* HACK we use capability_mask to know diff a CA port from switch port */
209                 if (p_src_port->rec.port_info.capability_mask) {
210                         /* this is an hca port */
211                         for (block = 1; block <= 4; block++) {
212                                 /*  NOTE to comply we must set port number to 0 and the SA should figure it out */
213                                 /*  since it is a CA port */
214                                 status =
215                                     osmt_query_vl_arb(p_osmt,
216                                                       p_src_port->rec.lid, 0,
217                                                       block, fh);
218                                 if (status != IB_SUCCESS) {
219                                         OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
220                                                 "ERR 0467: "
221                                                 "Failed to get Lid:0x%X Port:0x%X (%s)\n",
222                                                 cl_ntoh16(p_src_port->rec.lid),
223                                                 0, ib_get_err_str(status));
224                                         anyErr = 1;
225                                 }
226                         }
227                 } else {
228                         /* this is a switch port */
229                         for (block = 1; block <= 4; block++) {
230                                 status =
231                                     osmt_query_vl_arb(p_osmt,
232                                                       p_src_port->rec.lid,
233                                                       p_src_port->rec.port_num,
234                                                       block, fh);
235                                 if (status != IB_SUCCESS) {
236                                         OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
237                                                 "ERR 0468: "
238                                                 "Failed to get Lid:0x%X Port:0x%X (%s)\n",
239                                                 cl_ntoh16(p_src_port->rec.lid),
240                                                 p_src_port->rec.port_num,
241                                                 ib_get_err_str(status));
242                                         anyErr = 1;
243                                 }
244                         }
245                 }
246
247                 p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item);
248         }
249
250         OSM_LOG_EXIT(&p_osmt->log);
251         if (anyErr) {
252                 status = IB_ERROR;
253         }
254         return (status);
255 }
256
257 /*******************************************************************************
258  SLtoVL
259 *******************************************************************************/
260 static ib_api_status_t
261 osmtest_write_slvl_map_table(IN osmtest_t * const p_osmt,
262                              IN FILE * fh,
263                              IN const ib_slvl_table_record_t * const p_rec)
264 {
265         int result, i;
266         cl_status_t status = IB_SUCCESS;
267
268         OSM_LOG_ENTER(&p_osmt->log);
269
270         result = fprintf(fh,
271                          "SLtoVL_MAP_TABLE\n"
272                          "lid                     0x%X\n"
273                          "in_port_num             0x%X\n"
274                          "out_port_num            0x%X\n",
275                          cl_ntoh16(p_rec->lid),
276                          p_rec->in_port_num, p_rec->out_port_num);
277
278         fprintf(fh, "SL:");
279         for (i = 0; i < 16; i++)
280                 fprintf(fh, "| %-2u  ", i);
281         fprintf(fh, "|\nVL:");
282
283         for (i = 0; i < 16; i++)
284                 fprintf(fh, "| 0x%01X ",
285                         ib_slvl_table_get(&p_rec->slvl_tbl, (uint8_t) i));
286         fprintf(fh, "|\nEND\n\n");
287
288         /*  Exit: */
289         OSM_LOG_EXIT(&p_osmt->log);
290         return (status);
291 }
292
293 /**********************************************************************
294  * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
295  **********************************************************************/
296 ib_api_status_t
297 osmt_query_slvl_map(IN osmtest_t * const p_osmt,
298                     IN ib_net16_t const lid,
299                     IN uint8_t const out_port_num,
300                     IN uint8_t const in_port_num, IN FILE * fh)
301 {
302         osmtest_req_context_t context;
303         ib_api_status_t status = IB_SUCCESS;
304         osmv_user_query_t user;
305         osmv_query_req_t req;
306         ib_slvl_table_record_t record, *p_rec;
307
308         OSM_LOG_ENTER(&p_osmt->log);
309
310         OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,
311                 "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n",
312                 cl_ntoh16(lid), out_port_num, in_port_num);
313
314         /*
315          * Do a blocking query for this record in the subnet.
316          * The result is returned in the result field of the caller's
317          * context structure.
318          *
319          * The query structures are locals.
320          */
321         memset(&req, 0, sizeof(req));
322         memset(&user, 0, sizeof(user));
323         memset(&context, 0, sizeof(context));
324
325         context.p_osmt = p_osmt;
326
327         record.lid = lid;
328         record.in_port_num = in_port_num;
329         record.out_port_num = out_port_num;
330         user.p_attr = &record;
331
332         req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS;
333         req.timeout_ms = p_osmt->opt.transaction_timeout;
334         req.retry_cnt = p_osmt->opt.retry_count;
335         req.flags = OSM_SA_FLAGS_SYNC;
336         req.query_context = &context;
337         req.pfn_query_cb = osmtest_query_res_cb;
338         req.p_query_input = &user;
339         req.sm_key = 0;
340
341         status = osmv_query_sa(p_osmt->h_bind, &req);
342
343         if (status != IB_SUCCESS) {
344                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0469: "
345                         "ib_query failed (%s)\n", ib_get_err_str(status));
346                 goto Exit;
347         }
348
349         status = context.result.status;
350
351         if (status != IB_SUCCESS) {
352                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0470: "
353                         "ib_query failed (%s)\n", ib_get_err_str(status));
354
355                 if (status == IB_REMOTE_ERROR) {
356                         OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
357                                 "Remote error = %s\n",
358                                 ib_get_mad_status_str(osm_madw_get_mad_ptr
359                                                       (context.result.
360                                                        p_result_madw)));
361                 }
362                 goto Exit;
363         }
364
365         /* ok it worked */
366         p_rec = osmv_get_query_result(context.result.p_result_madw, 0);
367         if (fh) {
368                 osmtest_write_slvl_map_table(p_osmt, fh, p_rec);
369         }
370
371 Exit:
372         /*
373          * Return the IB query MAD to the pool as necessary.
374          */
375         if (context.result.p_result_madw != NULL) {
376                 osm_mad_pool_put(&p_osmt->mad_pool,
377                                  context.result.p_result_madw);
378                 context.result.p_result_madw = NULL;
379         }
380
381         OSM_LOG_EXIT(&p_osmt->log);
382         return (status);
383 }
384
385 static ib_api_status_t
386 osmt_query_all_ports_slvl_map(IN osmtest_t * const p_osmt, IN FILE * fh)
387 {
388         cl_status_t status = CL_SUCCESS;
389         cl_qmap_t *p_tbl;
390         port_t *p_src_port;
391         uint8_t in_port, anyErr = 0, num_ports;
392         node_t *p_node;
393         const cl_qmap_t *p_node_tbl;
394
395         OSM_LOG_ENTER(&p_osmt->log);
396
397         /*
398          * Go over all ports that exist in the subnet
399          * get the relevant SLtoVLs
400          */
401
402         OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE,
403                 "Obtaining ALL Ports (to other ports) SLtoVL Maps\n");
404
405         p_tbl = &p_osmt->exp_subn.port_key_tbl;
406         p_node_tbl = &p_osmt->exp_subn.node_lid_tbl;
407
408         p_src_port = (port_t *) cl_qmap_head(p_tbl);
409
410         while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) {
411
412                 /* HACK we use capability_mask to know diff a CA port from switch port */
413                 if (p_src_port->rec.port_info.capability_mask) {
414                         /* this is an hca port */
415                         /*  NOTE to comply we must set port number to 0 and the SA should figure it out */
416                         /*  since it is a CA port */
417                         status =
418                             osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0,
419                                                 0, fh);
420                         if (status != IB_SUCCESS) {
421                                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0471: "
422                                         "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s)\n",
423                                         cl_ntoh16(p_src_port->rec.lid), 0, 0,
424                                         ib_get_err_str(status));
425                                 anyErr = 1;
426                         }
427                 } else {
428                         /* this is a switch port */
429                         /* get the node */
430                         p_node =
431                             (node_t *) cl_qmap_get(p_node_tbl,
432                                                    p_src_port->rec.lid);
433                         if (p_node == (node_t *) cl_qmap_end(p_node_tbl)) {
434                                 OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0472: "
435                                         "Failed to get Node by Lid:0x%X\n",
436                                         p_src_port->rec.lid);
437                                 goto Exit;
438                         }
439
440                         num_ports = p_node->rec.node_info.num_ports;
441
442                         for (in_port = 1; in_port <= num_ports; in_port++) {
443                                 status =
444                                     osmt_query_slvl_map(p_osmt,
445                                                         p_src_port->rec.lid,
446                                                         p_src_port->rec.
447                                                         port_num, in_port, fh);
448                                 if (status != IB_SUCCESS) {
449                                         OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
450                                                 "ERR 0473: "
451                                                 "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s)\n",
452                                                 cl_ntoh16(p_src_port->rec.lid),
453                                                 p_src_port->rec.port_num,
454                                                 in_port,
455                                                 ib_get_err_str(status));
456                                         anyErr = 1;
457                                 }
458                         }
459                 }
460
461                 p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item);
462         }
463
464 Exit:
465         OSM_LOG_EXIT(&p_osmt->log);
466         if (anyErr) {
467                 status = IB_ERROR;
468         }
469         return (status);
470 }
471
472 /*
473  * Run a vl arbitration queries and sl2vl maps queries flow:
474  * Good flow:
475  * - for each physical port on the network - obtain the VL Arb
476  * - for each CA physical port obtain its SLtoVL Map
477  * - for each SW physical port (out) obtain the SLtoVL Map to each other port
478  * BAD flow:
479  * - Try get with multiple results
480  * - Try gettable
481  * - Try providing non existing port
482  */
483 ib_api_status_t
484 osmt_run_slvl_and_vlarb_records_flow(IN osmtest_t * const p_osmt)
485 {
486         ib_api_status_t status;
487         FILE *fh;
488         ib_net16_t test_lid;
489         uint8_t lmc;
490
491         OSM_LOG_ENTER(&p_osmt->log);
492
493         fh = fopen("qos.txt", "w");
494
495         /* go over all ports in the subnet */
496         status = osmt_query_all_ports_vl_arb(p_osmt, fh);
497         if (status != IB_SUCCESS) {
498                 goto Exit;
499         }
500
501         status = osmt_query_all_ports_slvl_map(p_osmt, fh);
502         if (status != IB_SUCCESS) {
503                 goto Exit;
504         }
505
506         /* If LMC > 0, test non base LID SA QoS Record requests */
507         status =
508             osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc);
509         if (status != IB_SUCCESS)
510                 goto Exit;
511
512         if (lmc != 0) {
513                 test_lid = cl_ntoh16(p_osmt->local_port.lid + 1);
514
515                 status = osmt_query_vl_arb(p_osmt, test_lid, 0, 1, NULL);
516                 if (status != IB_SUCCESS)
517                         goto Exit;
518
519                 status = osmt_query_slvl_map(p_osmt, test_lid, 0, 0, NULL);
520                 if (status != IB_SUCCESS)
521                         goto Exit;
522         }
523
524 Exit:
525         fclose(fh);
526         OSM_LOG_EXIT(&p_osmt->log);
527         return status;
528 }