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
__build_nodebyname_hash(osm_qos_policy_t * p_qos_policy)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
__is_num_in_range_arr(uint64_t ** range_arr,unsigned range_arr_len,uint64_t num)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
__free_single_element(void * p_element,void * context)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
osm_qos_policy_port_create(osm_physp_t * p_physp)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
osm_qos_policy_port_group_create()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
osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p)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
osm_qos_policy_vlarb_scope_create()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
osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p)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
osm_qos_policy_sl2vl_scope_create()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
osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p)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
osm_qos_policy_qos_level_create()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
osm_qos_policy_qos_level_destroy(osm_qos_level_t * p)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
osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level,IN ib_net16_t pkey)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
osm_qos_level_get_shared_pkey(IN const osm_qos_level_t * p_qos_level,IN const osm_physp_t * p_src_physp,IN const osm_physp_t * p_dest_physp,IN const boolean_t allow_both_pkeys)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
osm_qos_policy_match_rule_create()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
osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p)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
osm_qos_policy_create(osm_subn_t * p_subn)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
osm_qos_policy_destroy(osm_qos_policy_t * p_qos_policy)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
__qos_policy_is_port_in_group(osm_subn_t * p_subn,const osm_physp_t * p_physp,osm_qos_port_group_t * p_port_group)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
__qos_policy_is_port_in_group_list(const osm_qos_policy_t * p_qos_policy,const osm_physp_t * p_physp,cl_list_t * p_port_group_list)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
__qos_policy_get_match_rule_by_params(const osm_qos_policy_t * p_qos_policy,uint64_t service_id,uint16_t qos_class,uint16_t pkey,const osm_physp_t * p_src_physp,const osm_physp_t * p_dest_physp,ib_net64_t comp_mask)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
__qos_policy_get_qos_level_by_name(const osm_qos_policy_t * p_qos_policy,const char * name)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
__qos_policy_get_port_group_by_name(const osm_qos_policy_t * p_qos_policy,const char * const name)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
__qos_policy_validate_pkey(osm_qos_policy_t * p_qos_policy,osm_qos_match_rule_t * p_qos_match_rule,osm_prtn_t * p_prtn)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
osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,osm_log_t * p_log)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
__qos_policy_get_qos_level_by_params(IN const osm_qos_policy_t * p_qos_policy,IN const osm_physp_t * p_src_physp,IN const osm_physp_t * p_dest_physp,IN uint64_t service_id,IN uint16_t qos_class,IN uint16_t pkey,IN ib_net64_t comp_mask)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
osm_qos_policy_get_qos_level_by_pr(IN const osm_qos_policy_t * p_qos_policy,IN const ib_path_rec_t * p_pr,IN const osm_physp_t * p_src_physp,IN const osm_physp_t * p_dest_physp,IN ib_net64_t comp_mask)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
osm_qos_policy_get_qos_level_by_mpr(IN const osm_qos_policy_t * p_qos_policy,IN const ib_multipath_rec_t * p_mpr,IN const osm_physp_t * p_src_physp,IN const osm_physp_t * p_dest_physp,IN ib_net64_t comp_mask)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