1249259Sdim/* 2249259Sdim * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved. 3249259Sdim * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4249259Sdim * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5249259Sdim * 6249259Sdim * This software is available to you under a choice of one of two 7249259Sdim * licenses. You may choose to be licensed under the terms of the GNU 8249259Sdim * General Public License (GPL) Version 2, available from the file 9249259Sdim * COPYING in the main directory of this source tree, or the 10249259Sdim * OpenIB.org BSD license below: 11249259Sdim * 12249259Sdim * Redistribution and use in source and binary forms, with or 13249259Sdim * without modification, are permitted provided that the following 14249259Sdim * conditions are met: 15249259Sdim * 16249259Sdim * - Redistributions of source code must retain the above 17249259Sdim * copyright notice, this list of conditions and the following 18249259Sdim * disclaimer. 19249259Sdim * 20249259Sdim * - Redistributions in binary form must reproduce the above 21249259Sdim * copyright notice, this list of conditions and the following 22249259Sdim * disclaimer in the documentation and/or other materials 23249259Sdim * provided with the distribution. 24249259Sdim * 25249259Sdim * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26249259Sdim * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27249259Sdim * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28249259Sdim * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29249259Sdim * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30249259Sdim * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31249259Sdim * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32249259Sdim * SOFTWARE. 33249259Sdim * 34249259Sdim */ 35249259Sdim 36249259Sdim/* 37249259Sdim * Abstract: 38249259Sdim * Implementation of SLtoVL and VL Arbitration testing flow.. 39249259Sdim * Top level is osmt_run_slvl_and_vlarb_records_flow: 40249259Sdim * osmt_query_all_ports_vl_arb 41249259Sdim * osmt_query_all_ports_slvl_map 42249259Sdim * 43249259Sdim */ 44249259Sdim 45249259Sdim#ifndef __WIN__ 46249259Sdim#include <unistd.h> 47249259Sdim#endif 48249259Sdim#include <stdio.h> 49249259Sdim#include <stdlib.h> 50249259Sdim#include <string.h> 51249259Sdim#include <complib/cl_debug.h> 52249259Sdim#include "osmtest.h" 53249259Sdim 54249259Sdim/********************************************************************** 55249259Sdim **********************************************************************/ 56249259Sdimstatic ib_api_status_t 57249259Sdimosmtest_write_vl_arb_table(IN osmtest_t * const p_osmt, 58249259Sdim IN FILE * fh, 59249259Sdim IN const ib_vl_arb_table_record_t * const p_rec) 60249259Sdim{ 61249259Sdim int result, i; 62249259Sdim cl_status_t status = IB_SUCCESS; 63249259Sdim 64249259Sdim OSM_LOG_ENTER(&p_osmt->log); 65249259Sdim 66249259Sdim result = fprintf(fh, 67249259Sdim "VL_ARBITRATION_TABLE\n" 68249259Sdim "lid 0x%X\n" 69249259Sdim "port_num 0x%X\n" 70249259Sdim "block 0x%X\n", 71249259Sdim cl_ntoh16(p_rec->lid), 72249259Sdim p_rec->port_num, p_rec->block_num); 73249259Sdim 74249259Sdim fprintf(fh, " "); 75249259Sdim for (i = 0; i < 32; i++) 76249259Sdim fprintf(fh, "| %-2u ", i); 77249259Sdim fprintf(fh, "|\nVL: "); 78249259Sdim 79249259Sdim for (i = 0; i < 32; i++) 80249259Sdim fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].vl); 81249259Sdim fprintf(fh, "|\nWEIGHT:"); 82249259Sdim 83249259Sdim for (i = 0; i < 32; i++) 84249259Sdim fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].weight); 85249259Sdim fprintf(fh, "|\nEND\n\n"); 86249259Sdim 87249259Sdim /* Exit: */ 88249259Sdim OSM_LOG_EXIT(&p_osmt->log); 89249259Sdim return (status); 90249259Sdim} 91249259Sdim 92249259Sdim/********************************************************************** 93249259Sdim * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER 94249259Sdim **********************************************************************/ 95249259Sdimib_api_status_t 96249259Sdimosmt_query_vl_arb(IN osmtest_t * const p_osmt, 97249259Sdim IN ib_net16_t const lid, 98249259Sdim IN uint8_t const port_num, 99249259Sdim IN uint8_t const block_num, IN FILE * fh) 100249259Sdim{ 101249259Sdim osmtest_req_context_t context; 102249259Sdim ib_api_status_t status = IB_SUCCESS; 103249259Sdim osmv_user_query_t user; 104249259Sdim osmv_query_req_t req; 105249259Sdim ib_vl_arb_table_record_t record, *p_rec; 106249259Sdim 107249259Sdim OSM_LOG_ENTER(&p_osmt->log); 108249259Sdim 109249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, 110249259Sdim "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n", 111249259Sdim cl_ntoh16(lid), port_num); 112249259Sdim 113249259Sdim /* 114249259Sdim * Do a blocking query for this record in the subnet. 115249259Sdim * The result is returned in the result field of the caller's 116249259Sdim * context structure. 117249259Sdim * 118249259Sdim * The query structures are locals. 119249259Sdim */ 120249259Sdim memset(&req, 0, sizeof(req)); 121249259Sdim memset(&user, 0, sizeof(user)); 122249259Sdim memset(&context, 0, sizeof(context)); 123249259Sdim 124249259Sdim context.p_osmt = p_osmt; 125249259Sdim 126249259Sdim record.lid = lid; 127249259Sdim record.port_num = port_num; 128249259Sdim record.block_num = block_num; 129249259Sdim user.p_attr = &record; 130249259Sdim 131249259Sdim req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK; 132249259Sdim req.timeout_ms = p_osmt->opt.transaction_timeout; 133249259Sdim req.retry_cnt = p_osmt->opt.retry_count; 134249259Sdim req.flags = OSM_SA_FLAGS_SYNC; 135249259Sdim req.query_context = &context; 136249259Sdim req.pfn_query_cb = osmtest_query_res_cb; 137249259Sdim req.p_query_input = &user; 138249259Sdim req.sm_key = 0; 139249259Sdim 140249259Sdim status = osmv_query_sa(p_osmt->h_bind, &req); 141249259Sdim 142249259Sdim if (status != IB_SUCCESS) { 143249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0405: " 144249259Sdim "ib_query failed (%s)\n", ib_get_err_str(status)); 145249259Sdim goto Exit; 146249259Sdim } 147249259Sdim 148249259Sdim status = context.result.status; 149249259Sdim 150249259Sdim if (status != IB_SUCCESS) { 151249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0466: " 152249259Sdim "ib_query failed (%s)\n", ib_get_err_str(status)); 153249259Sdim 154249259Sdim if (status == IB_REMOTE_ERROR) { 155249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 156249259Sdim "Remote error = %s\n", 157249259Sdim ib_get_mad_status_str(osm_madw_get_mad_ptr 158249259Sdim (context.result. 159249259Sdim p_result_madw))); 160249259Sdim } 161249259Sdim goto Exit; 162249259Sdim } 163249259Sdim 164249259Sdim /* ok it worked */ 165249259Sdim p_rec = osmv_get_query_result(context.result.p_result_madw, 0); 166249259Sdim if (fh) { 167249259Sdim osmtest_write_vl_arb_table(p_osmt, fh, p_rec); 168249259Sdim } 169249259Sdim 170249259SdimExit: 171249259Sdim /* 172249259Sdim * Return the IB query MAD to the pool as necessary. 173249259Sdim */ 174249259Sdim if (context.result.p_result_madw != NULL) { 175249259Sdim osm_mad_pool_put(&p_osmt->mad_pool, 176249259Sdim context.result.p_result_madw); 177249259Sdim context.result.p_result_madw = NULL; 178249259Sdim } 179249259Sdim 180249259Sdim OSM_LOG_EXIT(&p_osmt->log); 181249259Sdim return (status); 182249259Sdim} 183249259Sdim 184249259Sdimstatic ib_api_status_t 185249259Sdimosmt_query_all_ports_vl_arb(IN osmtest_t * const p_osmt, IN FILE * fh) 186249259Sdim{ 187249259Sdim cl_status_t status = CL_SUCCESS; 188249259Sdim cl_qmap_t *p_tbl; 189249259Sdim port_t *p_src_port; 190249259Sdim uint8_t block, anyErr = 0; 191249259Sdim 192249259Sdim OSM_LOG_ENTER(&p_osmt->log); 193249259Sdim 194249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, 195249259Sdim "Obtaining ALL Ports VL Arbitration Tables\n"); 196249259Sdim 197249259Sdim /* 198249259Sdim * Go over all ports that exist in the subnet 199249259Sdim * get the relevant VLarbs 200249259Sdim */ 201249259Sdim 202249259Sdim p_tbl = &p_osmt->exp_subn.port_key_tbl; 203249259Sdim 204249259Sdim p_src_port = (port_t *) cl_qmap_head(p_tbl); 205249259Sdim 206249259Sdim while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) { 207249259Sdim 208249259Sdim /* HACK we use capability_mask to know diff a CA port from switch port */ 209249259Sdim if (p_src_port->rec.port_info.capability_mask) { 210249259Sdim /* this is an hca port */ 211249259Sdim for (block = 1; block <= 4; block++) { 212249259Sdim /* NOTE to comply we must set port number to 0 and the SA should figure it out */ 213249259Sdim /* since it is a CA port */ 214249259Sdim status = 215249259Sdim osmt_query_vl_arb(p_osmt, 216249259Sdim p_src_port->rec.lid, 0, 217249259Sdim block, fh); 218249259Sdim if (status != IB_SUCCESS) { 219249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 220249259Sdim "ERR 0467: " 221249259Sdim "Failed to get Lid:0x%X Port:0x%X (%s)\n", 222249259Sdim cl_ntoh16(p_src_port->rec.lid), 223249259Sdim 0, ib_get_err_str(status)); 224249259Sdim anyErr = 1; 225249259Sdim } 226249259Sdim } 227249259Sdim } else { 228249259Sdim /* this is a switch port */ 229249259Sdim for (block = 1; block <= 4; block++) { 230249259Sdim status = 231249259Sdim osmt_query_vl_arb(p_osmt, 232249259Sdim p_src_port->rec.lid, 233249259Sdim p_src_port->rec.port_num, 234249259Sdim block, fh); 235249259Sdim if (status != IB_SUCCESS) { 236249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, 237249259Sdim "ERR 0468: " 238249259Sdim "Failed to get Lid:0x%X Port:0x%X (%s)\n", 239249259Sdim cl_ntoh16(p_src_port->rec.lid), 240249259Sdim p_src_port->rec.port_num, 241249259Sdim ib_get_err_str(status)); 242249259Sdim anyErr = 1; 243249259Sdim } 244249259Sdim } 245249259Sdim } 246249259Sdim 247249259Sdim p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item); 248249259Sdim } 249249259Sdim 250249259Sdim OSM_LOG_EXIT(&p_osmt->log); 251249259Sdim if (anyErr) { 252249259Sdim status = IB_ERROR; 253249259Sdim } 254249259Sdim return (status); 255249259Sdim} 256249259Sdim 257249259Sdim/******************************************************************************* 258249259Sdim SLtoVL 259249259Sdim*******************************************************************************/ 260249259Sdimstatic ib_api_status_t 261249259Sdimosmtest_write_slvl_map_table(IN osmtest_t * const p_osmt, 262249259Sdim IN FILE * fh, 263249259Sdim IN const ib_slvl_table_record_t * const p_rec) 264249259Sdim{ 265249259Sdim int result, i; 266249259Sdim cl_status_t status = IB_SUCCESS; 267249259Sdim 268249259Sdim OSM_LOG_ENTER(&p_osmt->log); 269249259Sdim 270249259Sdim result = fprintf(fh, 271249259Sdim "SLtoVL_MAP_TABLE\n" 272249259Sdim "lid 0x%X\n" 273249259Sdim "in_port_num 0x%X\n" 274249259Sdim "out_port_num 0x%X\n", 275249259Sdim cl_ntoh16(p_rec->lid), 276249259Sdim p_rec->in_port_num, p_rec->out_port_num); 277249259Sdim 278249259Sdim fprintf(fh, "SL:"); 279249259Sdim for (i = 0; i < 16; i++) 280249259Sdim fprintf(fh, "| %-2u ", i); 281249259Sdim fprintf(fh, "|\nVL:"); 282249259Sdim 283249259Sdim for (i = 0; i < 16; i++) 284249259Sdim fprintf(fh, "| 0x%01X ", 285249259Sdim ib_slvl_table_get(&p_rec->slvl_tbl, (uint8_t) i)); 286249259Sdim fprintf(fh, "|\nEND\n\n"); 287249259Sdim 288249259Sdim /* Exit: */ 289249259Sdim OSM_LOG_EXIT(&p_osmt->log); 290249259Sdim return (status); 291249259Sdim} 292249259Sdim 293249259Sdim/********************************************************************** 294249259Sdim * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER 295249259Sdim **********************************************************************/ 296249259Sdimib_api_status_t 297249259Sdimosmt_query_slvl_map(IN osmtest_t * const p_osmt, 298249259Sdim IN ib_net16_t const lid, 299249259Sdim IN uint8_t const out_port_num, 300249259Sdim IN uint8_t const in_port_num, IN FILE * fh) 301249259Sdim{ 302249259Sdim osmtest_req_context_t context; 303249259Sdim ib_api_status_t status = IB_SUCCESS; 304249259Sdim osmv_user_query_t user; 305249259Sdim osmv_query_req_t req; 306249259Sdim ib_slvl_table_record_t record, *p_rec; 307249259Sdim 308249259Sdim OSM_LOG_ENTER(&p_osmt->log); 309249259Sdim 310249259Sdim OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, 311249259Sdim "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n", 312249259Sdim cl_ntoh16(lid), out_port_num, in_port_num); 313249259Sdim 314249259Sdim /* 315249259Sdim * 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