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 **********************************************************************/ 56static ib_api_status_t 57osmtest_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 **********************************************************************/ 95ib_api_status_t 96osmt_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 170Exit: 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 184static ib_api_status_t 185osmt_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*******************************************************************************/ 260static ib_api_status_t 261osmtest_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 **********************************************************************/ 296ib_api_status_t 297osmt_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 371Exit: 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 385static ib_api_status_t 386osmt_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 464Exit: 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 */ 483ib_api_status_t 484osmt_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 524Exit: 525 fclose(fh); 526 OSM_LOG_EXIT(&p_osmt->log); 527 return status; 528} 529