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