1/* 2 * Copyright (c) 2004-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 * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 */ 36 37/* 38 * Abstract: 39 * OSM QoS Policy functions. 40 * 41 * Author: 42 * Yevgeny Kliteynik, Mellanox 43 */ 44 45#include <stdio.h> 46#include <assert.h> 47#include <stdlib.h> 48#include <string.h> 49#include <ctype.h> 50#include <opensm/osm_log.h> 51#include <opensm/osm_node.h> 52#include <opensm/osm_port.h> 53#include <opensm/osm_partition.h> 54#include <opensm/osm_opensm.h> 55#include <opensm/osm_qos_policy.h> 56 57extern osm_qos_level_t __default_simple_qos_level; 58 59/*************************************************** 60 ***************************************************/ 61 62static void 63__build_nodebyname_hash(osm_qos_policy_t * p_qos_policy) 64{ 65 osm_node_t * p_node; 66 cl_qmap_t * p_node_guid_tbl = &p_qos_policy->p_subn->node_guid_tbl; 67 68 p_qos_policy->p_node_hash = st_init_strtable(); 69 CL_ASSERT(p_qos_policy->p_node_hash); 70 71 if (!p_node_guid_tbl || !cl_qmap_count(p_node_guid_tbl)) 72 return; 73 74 for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); 75 p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl); 76 p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) { 77 if (!st_lookup(p_qos_policy->p_node_hash, 78 (st_data_t)p_node->print_desc, NULL)) 79 st_insert(p_qos_policy->p_node_hash, 80 (st_data_t)p_node->print_desc, 81 (st_data_t)p_node); 82 } 83} 84 85/*************************************************** 86 ***************************************************/ 87 88static boolean_t 89__is_num_in_range_arr(uint64_t ** range_arr, 90 unsigned range_arr_len, uint64_t num) 91{ 92 unsigned ind_1 = 0; 93 unsigned ind_2 = range_arr_len - 1; 94 unsigned ind_mid; 95 96 if (!range_arr || !range_arr_len) 97 return FALSE; 98 99 while (ind_1 <= ind_2) { 100 if (num < range_arr[ind_1][0] || num > range_arr[ind_2][1]) 101 return FALSE; 102 else if (num <= range_arr[ind_1][1] || num >= range_arr[ind_2][0]) 103 return TRUE; 104 105 ind_mid = ind_1 + (ind_2 - ind_1 + 1)/2; 106 107 if (num < range_arr[ind_mid][0]) 108 ind_2 = ind_mid; 109 else if (num > range_arr[ind_mid][1]) 110 ind_1 = ind_mid; 111 else 112 return TRUE; 113 114 ind_1++; 115 ind_2--; 116 } 117 118 return FALSE; 119} 120 121/*************************************************** 122 ***************************************************/ 123 124static void __free_single_element(void *p_element, void *context) 125{ 126 if (p_element) 127 free(p_element); 128} 129 130/*************************************************** 131 ***************************************************/ 132 133osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t *p_physp) 134{ 135 osm_qos_port_t *p = 136 (osm_qos_port_t *) malloc(sizeof(osm_qos_port_t)); 137 if (!p) 138 return NULL; 139 memset(p, 0, sizeof(osm_qos_port_t)); 140 141 p->p_physp = p_physp; 142 return p; 143} 144 145/*************************************************** 146 ***************************************************/ 147 148osm_qos_port_group_t *osm_qos_policy_port_group_create() 149{ 150 osm_qos_port_group_t *p = 151 (osm_qos_port_group_t *) malloc(sizeof(osm_qos_port_group_t)); 152 if (!p) 153 return NULL; 154 155 memset(p, 0, sizeof(osm_qos_port_group_t)); 156 cl_qmap_init(&p->port_map); 157 158 return p; 159} 160 161/*************************************************** 162 ***************************************************/ 163 164void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p) 165{ 166 osm_qos_port_t * p_port; 167 osm_qos_port_t * p_old_port; 168 169 if (!p) 170 return; 171 172 if (p->name) 173 free(p->name); 174 if (p->use) 175 free(p->use); 176 177 p_port = (osm_qos_port_t *) cl_qmap_head(&p->port_map); 178 while (p_port != (osm_qos_port_t *) cl_qmap_end(&p->port_map)) 179 { 180 p_old_port = p_port; 181 p_port = (osm_qos_port_t *) cl_qmap_next(&p_port->map_item); 182 free(p_old_port); 183 } 184 cl_qmap_remove_all(&p->port_map); 185 186 free(p); 187} 188 189/*************************************************** 190 ***************************************************/ 191 192osm_qos_vlarb_scope_t *osm_qos_policy_vlarb_scope_create() 193{ 194 osm_qos_vlarb_scope_t *p = 195 (osm_qos_vlarb_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t)); 196 if (!p) 197 return NULL; 198 199 memset(p, 0, sizeof(osm_qos_vlarb_scope_t)); 200 201 cl_list_init(&p->group_list, 10); 202 cl_list_init(&p->across_list, 10); 203 cl_list_init(&p->vlarb_high_list, 10); 204 cl_list_init(&p->vlarb_low_list, 10); 205 206 return p; 207} 208 209/*************************************************** 210 ***************************************************/ 211 212void osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p) 213{ 214 if (!p) 215 return; 216 217 cl_list_apply_func(&p->group_list, __free_single_element, NULL); 218 cl_list_apply_func(&p->across_list, __free_single_element, NULL); 219 cl_list_apply_func(&p->vlarb_high_list, __free_single_element, NULL); 220 cl_list_apply_func(&p->vlarb_low_list, __free_single_element, NULL); 221 222 cl_list_remove_all(&p->group_list); 223 cl_list_remove_all(&p->across_list); 224 cl_list_remove_all(&p->vlarb_high_list); 225 cl_list_remove_all(&p->vlarb_low_list); 226 227 cl_list_destroy(&p->group_list); 228 cl_list_destroy(&p->across_list); 229 cl_list_destroy(&p->vlarb_high_list); 230 cl_list_destroy(&p->vlarb_low_list); 231 232 free(p); 233} 234 235/*************************************************** 236 ***************************************************/ 237 238osm_qos_sl2vl_scope_t *osm_qos_policy_sl2vl_scope_create() 239{ 240 osm_qos_sl2vl_scope_t *p = 241 (osm_qos_sl2vl_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t)); 242 if (!p) 243 return NULL; 244 245 memset(p, 0, sizeof(osm_qos_sl2vl_scope_t)); 246 247 cl_list_init(&p->group_list, 10); 248 cl_list_init(&p->across_from_list, 10); 249 cl_list_init(&p->across_to_list, 10); 250 251 return p; 252} 253 254/*************************************************** 255 ***************************************************/ 256 257void osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p) 258{ 259 if (!p) 260 return; 261 262 cl_list_apply_func(&p->group_list, __free_single_element, NULL); 263 cl_list_apply_func(&p->across_from_list, __free_single_element, NULL); 264 cl_list_apply_func(&p->across_to_list, __free_single_element, NULL); 265 266 cl_list_remove_all(&p->group_list); 267 cl_list_remove_all(&p->across_from_list); 268 cl_list_remove_all(&p->across_to_list); 269 270 cl_list_destroy(&p->group_list); 271 cl_list_destroy(&p->across_from_list); 272 cl_list_destroy(&p->across_to_list); 273 274 free(p); 275} 276 277/*************************************************** 278 ***************************************************/ 279 280osm_qos_level_t *osm_qos_policy_qos_level_create() 281{ 282 osm_qos_level_t *p = 283 (osm_qos_level_t *) malloc(sizeof(osm_qos_level_t)); 284 if (!p) 285 return NULL; 286 memset(p, 0, sizeof(osm_qos_level_t)); 287 return p; 288} 289 290/*************************************************** 291 ***************************************************/ 292 293void osm_qos_policy_qos_level_destroy(osm_qos_level_t * p) 294{ 295 unsigned i; 296 297 if (!p) 298 return; 299 300 if (p->name) 301 free(p->name); 302 if (p->use) 303 free(p->use); 304 305 for (i = 0; i < p->path_bits_range_len; i++) 306 free(p->path_bits_range_arr[i]); 307 if (p->path_bits_range_arr) 308 free(p->path_bits_range_arr); 309 310 free(p); 311} 312 313/*************************************************** 314 ***************************************************/ 315 316boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level, 317 IN ib_net16_t pkey) 318{ 319 if (!p_qos_level || !p_qos_level->pkey_range_len) 320 return FALSE; 321 return __is_num_in_range_arr(p_qos_level->pkey_range_arr, 322 p_qos_level->pkey_range_len, 323 cl_ntoh16(pkey)); 324} 325 326/*************************************************** 327 ***************************************************/ 328 329ib_net16_t osm_qos_level_get_shared_pkey(IN const osm_qos_level_t * p_qos_level, 330 IN const osm_physp_t * p_src_physp, 331 IN const osm_physp_t * p_dest_physp) 332{ 333 unsigned i; 334 uint16_t pkey_ho = 0; 335 336 if (!p_qos_level || !p_qos_level->pkey_range_len) 337 return 0; 338 339 /* 340 * ToDo: This approach is not optimal. 341 * Think how to find shared pkey that also exists 342 * in QoS level in less runtime. 343 */ 344 345 for (i = 0; i < p_qos_level->pkey_range_len; i++) { 346 for (pkey_ho = p_qos_level->pkey_range_arr[i][0]; 347 pkey_ho <= p_qos_level->pkey_range_arr[i][1]; pkey_ho++) { 348 if (osm_physp_share_this_pkey 349 (p_src_physp, p_dest_physp, cl_hton16(pkey_ho))) 350 return cl_hton16(pkey_ho); 351 } 352 } 353 354 return 0; 355} 356 357/*************************************************** 358 ***************************************************/ 359 360osm_qos_match_rule_t *osm_qos_policy_match_rule_create() 361{ 362 osm_qos_match_rule_t *p = 363 (osm_qos_match_rule_t *) malloc(sizeof(osm_qos_match_rule_t)); 364 if (!p) 365 return NULL; 366 367 memset(p, 0, sizeof(osm_qos_match_rule_t)); 368 369 cl_list_init(&p->source_list, 10); 370 cl_list_init(&p->source_group_list, 10); 371 cl_list_init(&p->destination_list, 10); 372 cl_list_init(&p->destination_group_list, 10); 373 374 return p; 375} 376 377/*************************************************** 378 ***************************************************/ 379 380void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p) 381{ 382 unsigned i; 383 384 if (!p) 385 return; 386 387 if (p->qos_level_name) 388 free(p->qos_level_name); 389 if (p->use) 390 free(p->use); 391 392 for (i = 0; i < p->service_id_range_len; i++) 393 free(p->service_id_range_arr[i]); 394 if (p->service_id_range_arr) 395 free(p->service_id_range_arr); 396 397 for (i = 0; i < p->qos_class_range_len; i++) 398 free(p->qos_class_range_arr[i]); 399 if (p->qos_class_range_arr) 400 free(p->qos_class_range_arr); 401 402 for (i = 0; i < p->pkey_range_len; i++) 403 free(p->pkey_range_arr[i]); 404 if (p->pkey_range_arr) 405 free(p->pkey_range_arr); 406 407 cl_list_apply_func(&p->source_list, __free_single_element, NULL); 408 cl_list_remove_all(&p->source_list); 409 cl_list_destroy(&p->source_list); 410 411 cl_list_remove_all(&p->source_group_list); 412 cl_list_destroy(&p->source_group_list); 413 414 cl_list_apply_func(&p->destination_list, __free_single_element, NULL); 415 cl_list_remove_all(&p->destination_list); 416 cl_list_destroy(&p->destination_list); 417 418 cl_list_remove_all(&p->destination_group_list); 419 cl_list_destroy(&p->destination_group_list); 420 421 free(p); 422} 423 424/*************************************************** 425 ***************************************************/ 426 427osm_qos_policy_t * osm_qos_policy_create(osm_subn_t * p_subn) 428{ 429 osm_qos_policy_t * p_qos_policy = (osm_qos_policy_t *)malloc(sizeof(osm_qos_policy_t)); 430 if (!p_qos_policy) 431 return NULL; 432 433 memset(p_qos_policy, 0, sizeof(osm_qos_policy_t)); 434 435 cl_list_construct(&p_qos_policy->port_groups); 436 cl_list_init(&p_qos_policy->port_groups, 10); 437 438 cl_list_construct(&p_qos_policy->vlarb_tables); 439 cl_list_init(&p_qos_policy->vlarb_tables, 10); 440 441 cl_list_construct(&p_qos_policy->sl2vl_tables); 442 cl_list_init(&p_qos_policy->sl2vl_tables, 10); 443 444 cl_list_construct(&p_qos_policy->qos_levels); 445 cl_list_init(&p_qos_policy->qos_levels, 10); 446 447 cl_list_construct(&p_qos_policy->qos_match_rules); 448 cl_list_init(&p_qos_policy->qos_match_rules, 10); 449 450 p_qos_policy->p_subn = p_subn; 451 __build_nodebyname_hash(p_qos_policy); 452 453 return p_qos_policy; 454} 455 456/*************************************************** 457 ***************************************************/ 458 459void osm_qos_policy_destroy(osm_qos_policy_t * p_qos_policy) 460{ 461 cl_list_iterator_t list_iterator; 462 osm_qos_port_group_t *p_port_group = NULL; 463 osm_qos_vlarb_scope_t *p_vlarb_scope = NULL; 464 osm_qos_sl2vl_scope_t *p_sl2vl_scope = NULL; 465 osm_qos_level_t *p_qos_level = NULL; 466 osm_qos_match_rule_t *p_qos_match_rule = NULL; 467 468 if (!p_qos_policy) 469 return; 470 471 list_iterator = cl_list_head(&p_qos_policy->port_groups); 472 while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { 473 p_port_group = 474 (osm_qos_port_group_t *) cl_list_obj(list_iterator); 475 if (p_port_group) 476 osm_qos_policy_port_group_destroy(p_port_group); 477 list_iterator = cl_list_next(list_iterator); 478 } 479 cl_list_remove_all(&p_qos_policy->port_groups); 480 cl_list_destroy(&p_qos_policy->port_groups); 481 482 list_iterator = cl_list_head(&p_qos_policy->vlarb_tables); 483 while (list_iterator != cl_list_end(&p_qos_policy->vlarb_tables)) { 484 p_vlarb_scope = 485 (osm_qos_vlarb_scope_t *) cl_list_obj(list_iterator); 486 if (p_vlarb_scope) 487 osm_qos_policy_vlarb_scope_destroy(p_vlarb_scope); 488 list_iterator = cl_list_next(list_iterator); 489 } 490 cl_list_remove_all(&p_qos_policy->vlarb_tables); 491 cl_list_destroy(&p_qos_policy->vlarb_tables); 492 493 list_iterator = cl_list_head(&p_qos_policy->sl2vl_tables); 494 while (list_iterator != cl_list_end(&p_qos_policy->sl2vl_tables)) { 495 p_sl2vl_scope = 496 (osm_qos_sl2vl_scope_t *) cl_list_obj(list_iterator); 497 if (p_sl2vl_scope) 498 osm_qos_policy_sl2vl_scope_destroy(p_sl2vl_scope); 499 list_iterator = cl_list_next(list_iterator); 500 } 501 cl_list_remove_all(&p_qos_policy->sl2vl_tables); 502 cl_list_destroy(&p_qos_policy->sl2vl_tables); 503 504 list_iterator = cl_list_head(&p_qos_policy->qos_levels); 505 while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { 506 p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); 507 if (p_qos_level) 508 osm_qos_policy_qos_level_destroy(p_qos_level); 509 list_iterator = cl_list_next(list_iterator); 510 } 511 cl_list_remove_all(&p_qos_policy->qos_levels); 512 cl_list_destroy(&p_qos_policy->qos_levels); 513 514 list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); 515 while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { 516 p_qos_match_rule = 517 (osm_qos_match_rule_t *) cl_list_obj(list_iterator); 518 if (p_qos_match_rule) 519 osm_qos_policy_match_rule_destroy(p_qos_match_rule); 520 list_iterator = cl_list_next(list_iterator); 521 } 522 cl_list_remove_all(&p_qos_policy->qos_match_rules); 523 cl_list_destroy(&p_qos_policy->qos_match_rules); 524 525 if (p_qos_policy->p_node_hash) 526 st_free_table(p_qos_policy->p_node_hash); 527 528 free(p_qos_policy); 529 530 p_qos_policy = NULL; 531} 532 533/*************************************************** 534 ***************************************************/ 535 536static boolean_t 537__qos_policy_is_port_in_group(osm_subn_t * p_subn, 538 const osm_physp_t * p_physp, 539 osm_qos_port_group_t * p_port_group) 540{ 541 osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); 542 ib_net64_t port_guid = osm_physp_get_port_guid(p_physp); 543 uint64_t port_guid_ho = cl_ntoh64(port_guid); 544 545 /* check whether this port's type matches any of group's types */ 546 547 if ( p_port_group->node_types & 548 (((uint8_t)1)<<osm_node_get_type(p_node)) ) 549 return TRUE; 550 551 /* check whether this port's guid is in group's port map */ 552 553 if (cl_qmap_get(&p_port_group->port_map, port_guid_ho) != 554 cl_qmap_end(&p_port_group->port_map)) 555 return TRUE; 556 557 return FALSE; 558} /* __qos_policy_is_port_in_group() */ 559 560/*************************************************** 561 ***************************************************/ 562 563static boolean_t 564__qos_policy_is_port_in_group_list(const osm_qos_policy_t * p_qos_policy, 565 const osm_physp_t * p_physp, 566 cl_list_t * p_port_group_list) 567{ 568 osm_qos_port_group_t *p_port_group; 569 cl_list_iterator_t list_iterator; 570 571 list_iterator = cl_list_head(p_port_group_list); 572 while (list_iterator != cl_list_end(p_port_group_list)) { 573 p_port_group = 574 (osm_qos_port_group_t *) cl_list_obj(list_iterator); 575 if (p_port_group) { 576 if (__qos_policy_is_port_in_group 577 (p_qos_policy->p_subn, p_physp, p_port_group)) 578 return TRUE; 579 } 580 list_iterator = cl_list_next(list_iterator); 581 } 582 return FALSE; 583} 584 585/*************************************************** 586 ***************************************************/ 587 588static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params( 589 const osm_qos_policy_t * p_qos_policy, 590 uint64_t service_id, 591 uint16_t qos_class, 592 uint16_t pkey, 593 const osm_physp_t * p_src_physp, 594 const osm_physp_t * p_dest_physp, 595 ib_net64_t comp_mask) 596{ 597 osm_qos_match_rule_t *p_qos_match_rule = NULL; 598 cl_list_iterator_t list_iterator; 599 osm_log_t * p_log = &p_qos_policy->p_subn->p_osm->log; 600 601 boolean_t matched_by_sguid = FALSE, 602 matched_by_dguid = FALSE, 603 matched_by_class = FALSE, 604 matched_by_sid = FALSE, 605 matched_by_pkey = FALSE; 606 607 if (!cl_list_count(&p_qos_policy->qos_match_rules)) 608 return NULL; 609 610 OSM_LOG_ENTER(p_log); 611 612 /* Go over all QoS match rules and find the one that matches the request */ 613 614 list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); 615 while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { 616 p_qos_match_rule = 617 (osm_qos_match_rule_t *) cl_list_obj(list_iterator); 618 if (!p_qos_match_rule) { 619 list_iterator = cl_list_next(list_iterator); 620 continue; 621 } 622 623 /* If a match rule has Source groups, PR request source has to be in this list */ 624 625 if (cl_list_count(&p_qos_match_rule->source_group_list)) { 626 if (!__qos_policy_is_port_in_group_list(p_qos_policy, 627 p_src_physp, 628 &p_qos_match_rule-> 629 source_group_list)) 630 { 631 list_iterator = cl_list_next(list_iterator); 632 continue; 633 } 634 matched_by_sguid = TRUE; 635 } 636 637 /* If a match rule has Destination groups, PR request dest. has to be in this list */ 638 639 if (cl_list_count(&p_qos_match_rule->destination_group_list)) { 640 if (!__qos_policy_is_port_in_group_list(p_qos_policy, 641 p_dest_physp, 642 &p_qos_match_rule-> 643 destination_group_list)) 644 { 645 list_iterator = cl_list_next(list_iterator); 646 continue; 647 } 648 matched_by_dguid = TRUE; 649 } 650 651 /* If a match rule has QoS classes, PR request HAS 652 to have a matching QoS class to match the rule */ 653 654 if (p_qos_match_rule->qos_class_range_len) { 655 if (!(comp_mask & IB_PR_COMPMASK_QOS_CLASS)) { 656 list_iterator = cl_list_next(list_iterator); 657 continue; 658 } 659 660 if (!__is_num_in_range_arr 661 (p_qos_match_rule->qos_class_range_arr, 662 p_qos_match_rule->qos_class_range_len, 663 qos_class)) { 664 list_iterator = cl_list_next(list_iterator); 665 continue; 666 } 667 matched_by_class = TRUE; 668 } 669 670 /* If a match rule has Service IDs, PR request HAS 671 to have a matching Service ID to match the rule */ 672 673 if (p_qos_match_rule->service_id_range_len) { 674 if (!(comp_mask & IB_PR_COMPMASK_SERVICEID_MSB) || 675 !(comp_mask & IB_PR_COMPMASK_SERVICEID_LSB)) { 676 list_iterator = cl_list_next(list_iterator); 677 continue; 678 } 679 680 if (!__is_num_in_range_arr 681 (p_qos_match_rule->service_id_range_arr, 682 p_qos_match_rule->service_id_range_len, 683 service_id)) { 684 list_iterator = cl_list_next(list_iterator); 685 continue; 686 } 687 matched_by_sid = TRUE; 688 } 689 690 /* If a match rule has PKeys, PR request HAS 691 to have a matching PKey to match the rule */ 692 693 if (p_qos_match_rule->pkey_range_len) { 694 if (!(comp_mask & IB_PR_COMPMASK_PKEY)) { 695 list_iterator = cl_list_next(list_iterator); 696 continue; 697 } 698 699 if (!__is_num_in_range_arr 700 (p_qos_match_rule->pkey_range_arr, 701 p_qos_match_rule->pkey_range_len, 702 pkey & 0x7FFF)) { 703 list_iterator = cl_list_next(list_iterator); 704 continue; 705 } 706 matched_by_pkey = TRUE; 707 } 708 709 /* if we got here, then this match-rule matched this PR request */ 710 break; 711 } 712 713 if (list_iterator == cl_list_end(&p_qos_policy->qos_match_rules)) 714 p_qos_match_rule = NULL; 715 716 if (p_qos_match_rule) 717 OSM_LOG(p_log, OSM_LOG_DEBUG, 718 "request matched rule (%s) by:%s%s%s%s%s\n", 719 (p_qos_match_rule->use) ? 720 p_qos_match_rule->use : "no description", 721 (matched_by_sguid) ? " SGUID" : "", 722 (matched_by_dguid) ? " DGUID" : "", 723 (matched_by_class) ? " QoS_Class" : "", 724 (matched_by_sid) ? " ServiceID" : "", 725 (matched_by_pkey) ? " PKey" : ""); 726 else 727 OSM_LOG(p_log, OSM_LOG_DEBUG, 728 "request not matched any rule\n"); 729 730 OSM_LOG_EXIT(p_log); 731 return p_qos_match_rule; 732} /* __qos_policy_get_match_rule_by_params() */ 733 734/*************************************************** 735 ***************************************************/ 736 737static osm_qos_level_t *__qos_policy_get_qos_level_by_name( 738 const osm_qos_policy_t * p_qos_policy, 739 char *name) 740{ 741 osm_qos_level_t *p_qos_level = NULL; 742 cl_list_iterator_t list_iterator; 743 744 list_iterator = cl_list_head(&p_qos_policy->qos_levels); 745 while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { 746 p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); 747 if (!p_qos_level) 748 continue; 749 750 /* names are case INsensitive */ 751 if (strcasecmp(name, p_qos_level->name) == 0) 752 return p_qos_level; 753 754 list_iterator = cl_list_next(list_iterator); 755 } 756 757 return NULL; 758} 759 760/*************************************************** 761 ***************************************************/ 762 763static osm_qos_port_group_t *__qos_policy_get_port_group_by_name( 764 const osm_qos_policy_t * p_qos_policy, 765 const char *const name) 766{ 767 osm_qos_port_group_t *p_port_group = NULL; 768 cl_list_iterator_t list_iterator; 769 770 list_iterator = cl_list_head(&p_qos_policy->port_groups); 771 while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { 772 p_port_group = 773 (osm_qos_port_group_t *) cl_list_obj(list_iterator); 774 if (!p_port_group) 775 continue; 776 777 /* names are case INsensitive */ 778 if (strcasecmp(name, p_port_group->name) == 0) 779 return p_port_group; 780 781 list_iterator = cl_list_next(list_iterator); 782 } 783 784 return NULL; 785} 786 787/*************************************************** 788 ***************************************************/ 789 790static void __qos_policy_validate_pkey( 791 osm_qos_policy_t * p_qos_policy, 792 osm_qos_match_rule_t * p_qos_match_rule, 793 osm_prtn_t * p_prtn) 794{ 795 uint8_t sl; 796 uint32_t flow; 797 uint8_t hop; 798 osm_mgrp_t * p_mgrp; 799 800 if (!p_qos_policy || !p_qos_match_rule || !p_prtn) 801 return; 802 803 if (!p_qos_match_rule->p_qos_level->sl_set || 804 p_prtn->sl == p_qos_match_rule->p_qos_level->sl) 805 return; 806 807 /* overriding partition's SL */ 808 OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR, 809 "ERR AC15: pkey 0x%04X in match rule - " 810 "overriding partition SL (%u) with QoS Level SL (%u)\n", 811 cl_ntoh16(p_prtn->pkey), p_prtn->sl, 812 p_qos_match_rule->p_qos_level->sl); 813 p_prtn->sl = p_qos_match_rule->p_qos_level->sl; 814 815 816 /* If this partition is an IPoIB partition, there should 817 be a matching MCast group. Fix this group's SL too */ 818 819 if (!p_prtn->mlid) 820 return; 821 822 p_mgrp = osm_get_mgrp_by_mlid(p_qos_policy->p_subn, p_prtn->mlid); 823 if (!p_mgrp) { 824 OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR, 825 "ERR AC16: MCast group for partition with " 826 "pkey 0x%04X not found\n", 827 cl_ntoh16(p_prtn->pkey)); 828 return; 829 } 830 831 CL_ASSERT((cl_ntoh16(p_mgrp->mcmember_rec.pkey) & 0x7fff) == 832 (cl_ntoh16(p_prtn->pkey) & 0x7fff)); 833 834 ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop, 835 &sl, &flow, &hop); 836 if (sl != p_prtn->sl) { 837 OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_DEBUG, 838 "Updating MCGroup (MLID 0x%04x) SL to " 839 "match partition SL (%u)\n", 840 cl_hton16(p_mgrp->mcmember_rec.mlid), 841 p_prtn->sl); 842 p_mgrp->mcmember_rec.sl_flow_hop = 843 ib_member_set_sl_flow_hop(p_prtn->sl, flow, hop); 844 } 845} 846 847/*************************************************** 848 ***************************************************/ 849 850int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy, 851 osm_log_t *p_log) 852{ 853 cl_list_iterator_t match_rules_list_iterator; 854 cl_list_iterator_t list_iterator; 855 osm_qos_port_group_t *p_port_group = NULL; 856 osm_qos_match_rule_t *p_qos_match_rule = NULL; 857 char *str; 858 unsigned i, j; 859 int res = 0; 860 uint64_t pkey_64; 861 ib_net16_t pkey; 862 osm_prtn_t * p_prtn; 863 864 OSM_LOG_ENTER(p_log); 865 866 /* set default qos level */ 867 868 p_qos_policy->p_default_qos_level = 869 __qos_policy_get_qos_level_by_name(p_qos_policy, OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); 870 if (!p_qos_policy->p_default_qos_level) { 871 /* There's no default QoS level in the usual qos-level section. 872 Check whether the 'simple' default QoS level that can be 873 defined in the qos-ulp section exists */ 874 if (__default_simple_qos_level.sl_set) { 875 p_qos_policy->p_default_qos_level = &__default_simple_qos_level; 876 } 877 else { 878 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC10: " 879 "Default qos-level (%s) not defined.\n", 880 OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); 881 res = 1; 882 goto Exit; 883 } 884 } 885 886 /* scan all the match rules, and fill the lists of pointers to 887 relevant qos levels and port groups to speed up PR matching */ 888 889 i = 1; 890 match_rules_list_iterator = 891 cl_list_head(&p_qos_policy->qos_match_rules); 892 while (match_rules_list_iterator != 893 cl_list_end(&p_qos_policy->qos_match_rules)) { 894 p_qos_match_rule = 895 (osm_qos_match_rule_t *) 896 cl_list_obj(match_rules_list_iterator); 897 CL_ASSERT(p_qos_match_rule); 898 899 /* find the matching qos-level for each match-rule */ 900 901 if (!p_qos_match_rule->p_qos_level) 902 p_qos_match_rule->p_qos_level = 903 __qos_policy_get_qos_level_by_name(p_qos_policy, 904 p_qos_match_rule->qos_level_name); 905 906 if (!p_qos_match_rule->p_qos_level) { 907 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC11: " 908 "qos-match-rule num %u: qos-level '%s' not found\n", 909 i, p_qos_match_rule->qos_level_name); 910 res = 1; 911 goto Exit; 912 } 913 914 /* find the matching port-group for element of source_list */ 915 916 if (cl_list_count(&p_qos_match_rule->source_list)) { 917 list_iterator = 918 cl_list_head(&p_qos_match_rule->source_list); 919 while (list_iterator != 920 cl_list_end(&p_qos_match_rule->source_list)) { 921 str = (char *)cl_list_obj(list_iterator); 922 CL_ASSERT(str); 923 924 p_port_group = 925 __qos_policy_get_port_group_by_name(p_qos_policy, str); 926 if (!p_port_group) { 927 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC12: " 928 "qos-match-rule num %u: source port-group '%s' not found\n", 929 i, str); 930 res = 1; 931 goto Exit; 932 } 933 934 cl_list_insert_tail(&p_qos_match_rule-> 935 source_group_list, 936 p_port_group); 937 938 list_iterator = cl_list_next(list_iterator); 939 } 940 } 941 942 /* find the matching port-group for element of destination_list */ 943 944 if (cl_list_count(&p_qos_match_rule->destination_list)) { 945 list_iterator = 946 cl_list_head(&p_qos_match_rule->destination_list); 947 while (list_iterator != 948 cl_list_end(&p_qos_match_rule-> 949 destination_list)) { 950 str = (char *)cl_list_obj(list_iterator); 951 CL_ASSERT(str); 952 953 p_port_group = 954 __qos_policy_get_port_group_by_name(p_qos_policy,str); 955 if (!p_port_group) { 956 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC13: " 957 "qos-match-rule num %u: destination port-group '%s' not found\n", 958 i, str); 959 res = 1; 960 goto Exit; 961 } 962 963 cl_list_insert_tail(&p_qos_match_rule-> 964 destination_group_list, 965 p_port_group); 966 967 list_iterator = cl_list_next(list_iterator); 968 } 969 } 970 971 /* 972 * Scan all the pkeys in matching rule, and if the 973 * partition for these pkeys exists, set the SL 974 * according to the QoS Level. 975 * Warn if there's mismatch between QoS level SL 976 * and Partition SL. 977 */ 978 979 for (j = 0; j < p_qos_match_rule->pkey_range_len; j++) { 980 for ( pkey_64 = p_qos_match_rule->pkey_range_arr[j][0]; 981 pkey_64 <= p_qos_match_rule->pkey_range_arr[j][1]; 982 pkey_64++) { 983 pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); 984 p_prtn = (osm_prtn_t *)cl_qmap_get( 985 &p_qos_policy->p_subn->prtn_pkey_tbl, pkey); 986 987 if (p_prtn == (osm_prtn_t *)cl_qmap_end( 988 &p_qos_policy->p_subn->prtn_pkey_tbl)) 989 /* partition for this pkey not found */ 990 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC14: " 991 "pkey 0x%04X in match rule - " 992 "partition doesn't exist\n", 993 cl_ntoh16(pkey)); 994 else 995 __qos_policy_validate_pkey(p_qos_policy, 996 p_qos_match_rule, 997 p_prtn); 998 } 999 } 1000 1001 /* done with the current match-rule */ 1002 1003 match_rules_list_iterator = 1004 cl_list_next(match_rules_list_iterator); 1005 i++; 1006 } 1007 1008Exit: 1009 OSM_LOG_EXIT(p_log); 1010 return res; 1011} /* osm_qos_policy_validate() */ 1012 1013/*************************************************** 1014 ***************************************************/ 1015 1016static osm_qos_level_t * __qos_policy_get_qos_level_by_params( 1017 IN const osm_qos_policy_t * p_qos_policy, 1018 IN const osm_physp_t * p_src_physp, 1019 IN const osm_physp_t * p_dest_physp, 1020 IN uint64_t service_id, 1021 IN uint16_t qos_class, 1022 IN uint16_t pkey, 1023 IN ib_net64_t comp_mask) 1024{ 1025 osm_qos_match_rule_t *p_qos_match_rule = NULL; 1026 1027 if (!p_qos_policy) 1028 return NULL; 1029 1030 p_qos_match_rule = __qos_policy_get_match_rule_by_params( 1031 p_qos_policy, service_id, qos_class, pkey, 1032 p_src_physp, p_dest_physp, comp_mask); 1033 1034 return p_qos_match_rule ? p_qos_match_rule->p_qos_level : 1035 p_qos_policy->p_default_qos_level; 1036} /* __qos_policy_get_qos_level_by_params() */ 1037 1038/*************************************************** 1039 ***************************************************/ 1040 1041osm_qos_level_t * osm_qos_policy_get_qos_level_by_pr( 1042 IN const osm_qos_policy_t * p_qos_policy, 1043 IN const ib_path_rec_t * p_pr, 1044 IN const osm_physp_t * p_src_physp, 1045 IN const osm_physp_t * p_dest_physp, 1046 IN ib_net64_t comp_mask) 1047{ 1048 return __qos_policy_get_qos_level_by_params( 1049 p_qos_policy, p_src_physp, p_dest_physp, 1050 cl_ntoh64(p_pr->service_id), ib_path_rec_qos_class(p_pr), 1051 cl_ntoh16(p_pr->pkey), comp_mask); 1052} 1053 1054/*************************************************** 1055 ***************************************************/ 1056 1057osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr( 1058 IN const osm_qos_policy_t * p_qos_policy, 1059 IN const ib_multipath_rec_t * p_mpr, 1060 IN const osm_physp_t * p_src_physp, 1061 IN const osm_physp_t * p_dest_physp, 1062 IN ib_net64_t comp_mask) 1063{ 1064 ib_net64_t pr_comp_mask = 0; 1065 1066 if (!p_qos_policy) 1067 return NULL; 1068 1069 /* 1070 * Converting MultiPathRecord compmask to the PathRecord 1071 * compmask. Note that only relevant bits are set. 1072 */ 1073 pr_comp_mask = 1074 ((comp_mask & IB_MPR_COMPMASK_QOS_CLASS) ? 1075 IB_PR_COMPMASK_QOS_CLASS : 0) | 1076 ((comp_mask & IB_MPR_COMPMASK_PKEY) ? 1077 IB_PR_COMPMASK_PKEY : 0) | 1078 ((comp_mask & IB_MPR_COMPMASK_SERVICEID_MSB) ? 1079 IB_PR_COMPMASK_SERVICEID_MSB : 0) | 1080 ((comp_mask & IB_MPR_COMPMASK_SERVICEID_LSB) ? 1081 IB_PR_COMPMASK_SERVICEID_LSB : 0); 1082 1083 return __qos_policy_get_qos_level_by_params( 1084 p_qos_policy, p_src_physp, p_dest_physp, 1085 cl_ntoh64(ib_multipath_rec_service_id(p_mpr)), 1086 ib_multipath_rec_qos_class(p_mpr), 1087 cl_ntoh16(p_mpr->pkey), pr_comp_mask); 1088} 1089 1090/*************************************************** 1091 ***************************************************/ 1092