QoS policy data structures and functions Signed-off-by: Yevgeny Kliteynik <[EMAIL PROTECTED]> --- opensm/include/opensm/osm_qos_policy.h | 188 +++++++ opensm/opensm/osm_qos_policy.c | 901 ++++++++++++++++++++++++++++++++ 2 files changed, 1089 insertions(+), 0 deletions(-) create mode 100644 opensm/include/opensm/osm_qos_policy.h create mode 100644 opensm/opensm/osm_qos_policy.c
diff --git a/opensm/include/opensm/osm_qos_policy.h b/opensm/include/opensm/osm_qos_policy.h new file mode 100644 index 0000000..05b8dc9 --- /dev/null +++ b/opensm/include/opensm/osm_qos_policy.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* + * Abstract: + * Declaration of OSM QoS Policy data types and functions. + * + * Environment: + * Linux User Mode + * + * Author: + * Yevgeny Kliteynik, Mellanox + */ + +#ifndef OSM_QOS_POLICY_H +#define OSM_QOS_POLICY_H + +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <iba/ib_types.h> +#include <opensm/osm_log.h> +#include <opensm/osm_opensm.h> + +#define YYSTYPE char * +#define OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH 128 +#define OSM_QOS_POLICY_DEFAULT_LEVEL_NAME "default" + +/***************************************************/ + +typedef struct osm_qos_port_group_t_ { + char *name; /* single string (this port group name) */ + char *use; /* single string (description) */ + cl_list_t port_name_list; /* list of port names (.../.../...) */ + uint64_t **guid_range_arr; /* array of guid ranges (pair of 64-bit guids) */ + unsigned guid_range_len; /* num of guid ranges in the array */ + cl_list_t partition_list; /* list of partition names */ + boolean_t node_type_ca; + boolean_t node_type_switch; + boolean_t node_type_router; + boolean_t node_type_self; +} osm_qos_port_group_t; + +osm_qos_port_group_t *osm_qos_policy_port_group_create(); +void osm_qos_policy_port_group_destroy(); + +/***************************************************/ + +typedef struct osm_qos_vlarb_scope_t_ { + cl_list_t group_list; /* list of group names (strings) */ + cl_list_t across_list; /* list of 'across' group names (strings) */ + cl_list_t vlarb_high_list; /* list of num pairs (n:m,...), 32-bit values */ + cl_list_t vlarb_low_list; /* list of num pairs (n:m,...), 32-bit values */ + uint32_t vl_high_limit; /* single integer */ + boolean_t vl_high_limit_set; +} osm_qos_vlarb_scope_t; + +osm_qos_vlarb_scope_t *osm_qos_policy_vlarb_scope_create(); +void osm_qos_policy_vlarb_scope_destroy(); + +/***************************************************/ + +typedef struct osm_qos_sl2vl_scope_t_ { + cl_list_t group_list; /* list of strings (port group names) */ + boolean_t from[OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH]; + boolean_t to[OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH]; + cl_list_t across_from_list; /* list of strings (port group names) */ + cl_list_t across_to_list; /* list of strings (port group names) */ + uint8_t sl2vl_table[16]; /* array of sl2vl values */ + boolean_t sl2vl_table_set; +} osm_qos_sl2vl_scope_t; + +osm_qos_sl2vl_scope_t *osm_qos_policy_sl2vl_scope_create(); +void osm_qos_policy_sl2vl_scope_destroy(); + +/***************************************************/ + +typedef struct osm_qos_level_t_ { + char *use; + char *name; + uint8_t sl; + boolean_t sl_set; + uint8_t mtu_limit; + boolean_t mtu_limit_set; + uint8_t rate_limit; + boolean_t rate_limit_set; + uint8_t pkt_life; + boolean_t pkt_life_set; + uint64_t **path_bits_range_arr; /* array of bit ranges (real values are 32bits) */ + unsigned path_bits_range_len; /* num of bit ranges in the array */ + uint64_t **pkey_range_arr; /* array of PKey ranges (real values are 16bits) */ + unsigned pkey_range_len; +} osm_qos_level_t; + +osm_qos_level_t *osm_qos_policy_qos_level_create(); +void osm_qos_policy_qos_level_destroy(); + +boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level, + IN ib_net16_t pkey); + +ib_net16_t 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); + +/***************************************************/ + +typedef struct osm_qos_match_rule_t_ { + char *use; + cl_list_t source_list; /* list of strings */ + cl_list_t source_group_list; /* list of pointers to relevant port-group */ + cl_list_t destination_list; /* list of strings */ + cl_list_t destination_group_list; /* list of pointers to relevant port-group */ + char *qos_level_name; + osm_qos_level_t *p_qos_level; + uint64_t **service_id_range_arr; /* array of SID ranges (64-bit values) */ + unsigned service_id_range_len; + uint64_t **qos_class_range_arr; /* array of QoS Class ranges (real values are 16bits) */ + unsigned qos_class_range_len; + uint64_t **pkey_range_arr; /* array of PKey ranges (real values are 16bits) */ + unsigned pkey_range_len; +} osm_qos_match_rule_t; + +osm_qos_match_rule_t *osm_qos_policy_match_rule_create(); +void osm_qos_policy_match_rule_destroy(); + +/***************************************************/ + +typedef struct osm_qos_policy_t_ { + cl_list_t port_groups; /* list of osm_qos_port_group_t */ + cl_list_t sl2vl_tables; /* list of osm_qos_sl2vl_scope_t */ + cl_list_t vlarb_tables; /* list of osm_qos_vlarb_scope_t */ + cl_list_t qos_levels; /* list of osm_qos_level_t */ + cl_list_t qos_match_rules; /* list of osm_qos_match_rule_t */ + osm_qos_level_t *p_default_qos_level; /* default QoS level */ +} osm_qos_policy_t; + +void osm_qos_policy_create(); +void osm_qos_policy_destroy(); +int osm_qos_policy_validate(); + +void osm_qos_policy_get_qos_level_by_pr(IN const osm_pr_rcv_t * p_rcv, + 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, + OUT osm_qos_level_t ** pp_qos_level); + +/***************************************************/ + +int osm_qos_parse_policy_file(IN osm_log_t * p_log, IN const char *policy_file); + +/***************************************************/ + +#endif /* ifndef OSM_QOS_POLICY_H */ diff --git a/opensm/opensm/osm_qos_policy.c b/opensm/opensm/osm_qos_policy.c new file mode 100644 index 0000000..bc2aa68 --- /dev/null +++ b/opensm/opensm/osm_qos_policy.c @@ -0,0 +1,901 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* + * Abstract: + * OSM QoS Policy functions. + * + * Environment: + * Linux User Mode + * + * Author: + * Yevgeny Kliteynik, Mellanox + */ + +#include <opensm/osm_qos_policy.h> +#include <opensm/osm_qos_parser_y.h> +#include <opensm/osm_partition.h> + +extern void yyerror(char *s); +osm_log_t *p_qos_parser_osm_log = NULL; +osm_qos_policy_t *p_qos_policy = NULL; + +/*************************************************** + ***************************************************/ + +static boolean_t +__is_num_in_range_arr(uint64_t ** range_arr, + unsigned range_arr_len, uint64_t num) +{ + unsigned i; + + /* + * TODO: although this array should be rather short, + * I should implement a binary search here + */ + + if (num < range_arr[0][0] || num > range_arr[range_arr_len - 1][1]) + return FALSE; + + for (i = 0; i < range_arr_len; i++) { + if (num >= range_arr[i][0] && num <= range_arr[i][1]) + return TRUE; + if (num < range_arr[i][0]) + return FALSE; + } + return FALSE; +} + +/*************************************************** + ***************************************************/ + +static void __free_single_element(void *p_element, void *context) +{ + if (p_element) + free(p_element); +} + +/*************************************************** + ***************************************************/ + +osm_qos_port_group_t *osm_qos_policy_port_group_create() +{ + osm_qos_port_group_t *p = + (osm_qos_port_group_t *) malloc(sizeof(osm_qos_port_group_t)); + if (!p) + return NULL; + + memset(p, 0, sizeof(osm_qos_port_group_t)); + + cl_list_init(&p->port_name_list, 10); + cl_list_init(&p->partition_list, 10); + + return p; +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p) +{ + unsigned i; + + if (!p) + return; + + if (p->name) + free(p->name); + if (p->use) + free(p->use); + + for (i = 0; i < p->guid_range_len; i++) + free(p->guid_range_arr[i]); + if (p->guid_range_arr) + free(p->guid_range_arr); + + cl_list_apply_func(&p->port_name_list, __free_single_element, NULL); + cl_list_remove_all(&p->port_name_list); + cl_list_destroy(&p->port_name_list); + + cl_list_apply_func(&p->partition_list, __free_single_element, NULL); + cl_list_remove_all(&p->partition_list); + cl_list_destroy(&p->partition_list); + + free(p); +} + +/*************************************************** + ***************************************************/ + +osm_qos_vlarb_scope_t *osm_qos_policy_vlarb_scope_create() +{ + osm_qos_vlarb_scope_t *p = + (osm_qos_vlarb_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t)); + if (!p) + return NULL; + + memset(p, 0, sizeof(osm_qos_vlarb_scope_t)); + + cl_list_init(&p->group_list, 10); + cl_list_init(&p->across_list, 10); + cl_list_init(&p->vlarb_high_list, 10); + cl_list_init(&p->vlarb_low_list, 10); + + return p; +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p) +{ + if (!p) + return; + + cl_list_apply_func(&p->group_list, __free_single_element, NULL); + cl_list_apply_func(&p->across_list, __free_single_element, NULL); + cl_list_apply_func(&p->vlarb_high_list, __free_single_element, NULL); + cl_list_apply_func(&p->vlarb_low_list, __free_single_element, NULL); + + cl_list_remove_all(&p->group_list); + cl_list_remove_all(&p->across_list); + cl_list_remove_all(&p->vlarb_high_list); + cl_list_remove_all(&p->vlarb_low_list); + + cl_list_destroy(&p->group_list); + cl_list_destroy(&p->across_list); + cl_list_destroy(&p->vlarb_high_list); + cl_list_destroy(&p->vlarb_low_list); + + free(p); +} + +/*************************************************** + ***************************************************/ + +osm_qos_sl2vl_scope_t *osm_qos_policy_sl2vl_scope_create() +{ + osm_qos_sl2vl_scope_t *p = + (osm_qos_sl2vl_scope_t *) malloc(sizeof(osm_qos_sl2vl_scope_t)); + if (!p) + return NULL; + + memset(p, 0, sizeof(osm_qos_vlarb_scope_t)); + + cl_list_init(&p->group_list, 10); + cl_list_init(&p->across_from_list, 10); + cl_list_init(&p->across_to_list, 10); + + return p; +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p) +{ + if (!p) + return; + + cl_list_apply_func(&p->group_list, __free_single_element, NULL); + cl_list_apply_func(&p->across_from_list, __free_single_element, NULL); + cl_list_apply_func(&p->across_to_list, __free_single_element, NULL); + + cl_list_remove_all(&p->group_list); + cl_list_remove_all(&p->across_from_list); + cl_list_remove_all(&p->across_to_list); + + cl_list_destroy(&p->group_list); + cl_list_destroy(&p->across_from_list); + cl_list_destroy(&p->across_to_list); + + free(p); +} + +/*************************************************** + ***************************************************/ + +osm_qos_level_t *osm_qos_policy_qos_level_create() +{ + osm_qos_level_t *p = + (osm_qos_level_t *) malloc(sizeof(osm_qos_level_t)); + if (!p) + return NULL; + memset(p, 0, sizeof(osm_qos_level_t)); + return p; +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_qos_level_destroy(osm_qos_level_t * p) +{ + unsigned i; + + if (!p) + return; + + if (p->use) + free(p->use); + + for (i = 0; i < p->path_bits_range_len; i++) + free(p->path_bits_range_arr[i]); + if (p->path_bits_range_arr) + free(p->path_bits_range_arr); + + free(p); +} + +/*************************************************** + ***************************************************/ + +boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level, + IN ib_net16_t pkey) +{ + if (!p_qos_level || !p_qos_level->pkey_range_len) + return FALSE; + return __is_num_in_range_arr(p_qos_level->pkey_range_arr, + p_qos_level->pkey_range_len, + cl_ntoh16(pkey)); +} + +/*************************************************** + ***************************************************/ + +ib_net16_t 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) +{ + unsigned i; + uint16_t pkey_ho = 0; + + if (!p_qos_level || !p_qos_level->pkey_range_len) + return 0; + + /* + * ToDo: This approach is not optimal. + * Think how to find shared pkey that also exists + * in QoS level in less runtime. + */ + + for (i = 0; i < p_qos_level->pkey_range_len; i++) { + for (pkey_ho = p_qos_level->pkey_range_arr[i][0]; + pkey_ho <= p_qos_level->pkey_range_arr[i][1]; pkey_ho++) { + if (osm_physp_share_this_pkey + (p_src_physp, p_dest_physp, cl_hton16(pkey_ho))) + return cl_hton16(pkey_ho); + } + } + + return 0; +} + +/*************************************************** + ***************************************************/ + +osm_qos_match_rule_t *osm_qos_policy_match_rule_create() +{ + osm_qos_match_rule_t *p = + (osm_qos_match_rule_t *) malloc(sizeof(osm_qos_match_rule_t)); + if (!p) + return NULL; + + memset(p, 0, sizeof(osm_qos_match_rule_t)); + + cl_list_init(&p->source_list, 10); + cl_list_init(&p->source_group_list, 10); + cl_list_init(&p->destination_list, 10); + cl_list_init(&p->destination_group_list, 10); + + return p; +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p) +{ + unsigned i; + + if (!p) + return; + + if (p->qos_level_name) + free(p->qos_level_name); + if (p->use) + free(p->use); + + for (i = 0; i < p->service_id_range_len; i++) + free(p->service_id_range_arr[i]); + if (p->service_id_range_arr) + free(p->service_id_range_arr); + + for (i = 0; i < p->qos_class_range_len; i++) + free(p->qos_class_range_arr[i]); + if (p->qos_class_range_arr) + free(p->qos_class_range_arr); + + cl_list_apply_func(&p->source_list, __free_single_element, NULL); + cl_list_remove_all(&p->source_list); + cl_list_destroy(&p->source_list); + + cl_list_remove_all(&p->source_group_list); + cl_list_destroy(&p->source_group_list); + + cl_list_apply_func(&p->destination_list, __free_single_element, NULL); + cl_list_remove_all(&p->destination_list); + cl_list_destroy(&p->destination_list); + + cl_list_remove_all(&p->destination_group_list); + cl_list_destroy(&p->destination_group_list); + + free(p); +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_create() +{ + if (p_qos_policy) + osm_qos_policy_destroy(); + + p_qos_policy = (osm_qos_policy_t *) malloc(sizeof(osm_qos_policy_t)); + CL_ASSERT(p_qos_policy); + + memset(p_qos_policy, 0, sizeof(osm_qos_policy_t)); + + cl_list_construct(&p_qos_policy->port_groups); + cl_list_init(&p_qos_policy->port_groups, 10); + + cl_list_construct(&p_qos_policy->vlarb_tables); + cl_list_init(&p_qos_policy->vlarb_tables, 10); + + cl_list_construct(&p_qos_policy->sl2vl_tables); + cl_list_init(&p_qos_policy->sl2vl_tables, 10); + + cl_list_construct(&p_qos_policy->qos_levels); + cl_list_init(&p_qos_policy->qos_levels, 10); + + cl_list_construct(&p_qos_policy->qos_match_rules); + cl_list_init(&p_qos_policy->qos_match_rules, 10); +} + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_destroy() +{ + cl_list_iterator_t list_iterator; + osm_qos_port_group_t *p_port_group = NULL; + osm_qos_vlarb_scope_t *p_vlarb_scope = NULL; + osm_qos_sl2vl_scope_t *p_sl2vl_scope = NULL; + osm_qos_level_t *p_qos_level = NULL; + osm_qos_match_rule_t *p_qos_match_rule = NULL; + + list_iterator = cl_list_head(&p_qos_policy->port_groups); + while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { + p_port_group = + (osm_qos_port_group_t *) cl_list_obj(list_iterator); + if (p_port_group) + osm_qos_policy_port_group_destroy(p_port_group); + list_iterator = cl_list_next(list_iterator); + } + cl_list_remove_all(&p_qos_policy->port_groups); + cl_list_destroy(&p_qos_policy->port_groups); + + list_iterator = cl_list_head(&p_qos_policy->vlarb_tables); + while (list_iterator != cl_list_end(&p_qos_policy->vlarb_tables)) { + p_vlarb_scope = + (osm_qos_vlarb_scope_t *) cl_list_obj(list_iterator); + if (p_vlarb_scope) + osm_qos_policy_vlarb_scope_destroy(p_vlarb_scope); + list_iterator = cl_list_next(list_iterator); + } + cl_list_remove_all(&p_qos_policy->vlarb_tables); + cl_list_destroy(&p_qos_policy->vlarb_tables); + + list_iterator = cl_list_head(&p_qos_policy->sl2vl_tables); + while (list_iterator != cl_list_end(&p_qos_policy->sl2vl_tables)) { + p_sl2vl_scope = + (osm_qos_sl2vl_scope_t *) cl_list_obj(list_iterator); + if (p_sl2vl_scope) + osm_qos_policy_sl2vl_scope_destroy(p_sl2vl_scope); + list_iterator = cl_list_next(list_iterator); + } + cl_list_remove_all(&p_qos_policy->sl2vl_tables); + cl_list_destroy(&p_qos_policy->sl2vl_tables); + + list_iterator = cl_list_head(&p_qos_policy->qos_levels); + while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { + p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); + if (p_qos_level) + osm_qos_policy_qos_level_destroy(p_qos_level); + list_iterator = cl_list_next(list_iterator); + } + cl_list_remove_all(&p_qos_policy->qos_levels); + cl_list_destroy(&p_qos_policy->qos_levels); + + list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); + while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { + p_qos_match_rule = + (osm_qos_match_rule_t *) cl_list_obj(list_iterator); + if (p_qos_match_rule) + osm_qos_policy_match_rule_destroy(p_qos_match_rule); + list_iterator = cl_list_next(list_iterator); + } + cl_list_remove_all(&p_qos_policy->qos_match_rules); + cl_list_destroy(&p_qos_policy->qos_match_rules); + + free(p_qos_policy); + + p_qos_policy = NULL; +} + +/*************************************************** + ***************************************************/ + +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) +{ + osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); + osm_prtn_t *p_prtn = NULL; + ib_net64_t port_guid = osm_physp_get_port_guid(p_physp); + uint64_t port_guid_ho = cl_ntoh64(port_guid); + uint8_t node_type = osm_node_get_type(p_node); + cl_list_iterator_t list_iterator; + char *partition_name; + + /* check whether this port's type matches any of group's types */ + + if ((node_type == IB_NODE_TYPE_CA && p_port_group->node_type_ca) || + (node_type == IB_NODE_TYPE_SWITCH && p_port_group->node_type_switch) + || (node_type == IB_NODE_TYPE_ROUTER + && p_port_group->node_type_router)) + return TRUE; + + /* check whether this port's guid is in range of this group's guids */ + + if (__is_num_in_range_arr(p_port_group->guid_range_arr, + p_port_group->guid_range_len, port_guid_ho)) + return TRUE; + + /* check whether this port is member of this group's partitions */ + + list_iterator = cl_list_head(&p_port_group->partition_list); + while (list_iterator != cl_list_end(&p_port_group->partition_list)) { + partition_name = (char *)cl_list_obj(list_iterator); + if (partition_name && strlen(partition_name)) { + p_prtn = osm_prtn_find_by_name(p_subn, partition_name); + if (p_prtn) { + if (osm_prtn_is_guid(p_prtn, port_guid)) + return TRUE; + } + } + list_iterator = cl_list_next(list_iterator); + } + + /* check whether this port's name matches any of group's names */ + + /* + * TODO: check port names + * + * char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + * memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE); + * desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + */ + + return FALSE; +} /* __qos_policy_is_port_in_group() */ + +/*************************************************** + ***************************************************/ + +static boolean_t +__qos_policy_is_port_in_group_list(const osm_pr_rcv_t * p_rcv, + const osm_physp_t * p_physp, + cl_list_t * p_port_group_list) +{ + osm_qos_port_group_t *p_port_group; + cl_list_iterator_t list_iterator; + + list_iterator = cl_list_head(p_port_group_list); + while (list_iterator != cl_list_end(p_port_group_list)) { + p_port_group = + (osm_qos_port_group_t *) cl_list_obj(list_iterator); + if (p_port_group) { + if (__qos_policy_is_port_in_group + (p_rcv->p_subn, p_physp, p_port_group)) + return TRUE; + } + list_iterator = cl_list_next(list_iterator); + } + return FALSE; +} + +/*************************************************** + ***************************************************/ + +static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_pr( + const osm_pr_rcv_t * p_rcv, + const ib_path_rec_t * p_pr, + const osm_physp_t * p_src_physp, + const osm_physp_t * p_dest_physp, + ib_net64_t comp_mask) +{ + osm_qos_match_rule_t *p_qos_match_rule = NULL; + cl_list_iterator_t list_iterator; + + if (!cl_list_count(&p_qos_policy->qos_match_rules)) + return NULL; + + /* Go over all QoS match rules and find the one that matches the request */ + + list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); + while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { + p_qos_match_rule = + (osm_qos_match_rule_t *) cl_list_obj(list_iterator); + if (!p_qos_match_rule) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + /* If a match rule has Source groups, PR request source has to be in this list */ + + if (cl_list_count(&p_qos_match_rule->source_group_list)) { + if (!__qos_policy_is_port_in_group_list(p_rcv, + p_src_physp, + &p_qos_match_rule-> + source_group_list)) + { + list_iterator = cl_list_next(list_iterator); + continue; + } + } + + /* If a match rule has Destination groups, PR request dest. has to be in this list */ + + if (cl_list_count(&p_qos_match_rule->destination_group_list)) { + if (!__qos_policy_is_port_in_group_list(p_rcv, + p_dest_physp, + &p_qos_match_rule-> + destination_group_list)) + { + list_iterator = cl_list_next(list_iterator); + continue; + } + } + + /* If a match rule has QoS classes, PR request HAS + to have a matching QoS class to match the rule */ + + if (p_qos_match_rule->qos_class_range_len) { + if (!(comp_mask & IB_PR_COMPMASK_QOS_CLASS)) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + if (!__is_num_in_range_arr + (p_qos_match_rule->qos_class_range_arr, + p_qos_match_rule->qos_class_range_len, + ib_path_rec_qos_class(p_pr))) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + } + + /* If a match rule has Service IDs, PR request HAS + to have a matching Service ID to match the rule */ + + if (p_qos_match_rule->service_id_range_len) { + if (!(comp_mask & IB_PR_COMPMASK_SERVICEID)) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + if (!__is_num_in_range_arr + (p_qos_match_rule->service_id_range_arr, + p_qos_match_rule->service_id_range_len, + p_pr->service_id)) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + } + + /* If a match rule has PKeys, PR request HAS + to have a matching PKey to match the rule */ + + if (p_qos_match_rule->pkey_range_len) { + if (!(comp_mask & IB_PR_COMPMASK_PKEY)) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + if (!__is_num_in_range_arr + (p_qos_match_rule->pkey_range_arr, + p_qos_match_rule->pkey_range_len, + ib_path_rec_qos_class(p_pr))) { + list_iterator = cl_list_next(list_iterator); + continue; + } + + } + + /* if we got here, then this match-rule matched this PR request */ + break; + } + + if (list_iterator == cl_list_end(&p_qos_policy->qos_match_rules)) + return NULL; + + return p_qos_match_rule; +} /* __qos_policy_get_match_rule_by_pr() */ + +/*************************************************** + ***************************************************/ + +static osm_qos_level_t *__qos_policy_get_qos_level_by_name(char *name) +{ + osm_qos_level_t *p_qos_level = NULL; + cl_list_iterator_t list_iterator; + + list_iterator = cl_list_head(&p_qos_policy->qos_levels); + while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { + p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); + if (!p_qos_level) + continue; + + /* names are case INsensitive */ + if (strcasecmp(name, p_qos_level->name) == 0) + return p_qos_level; + + list_iterator = cl_list_next(list_iterator); + } + + return NULL; +} + +/*************************************************** + ***************************************************/ + +static osm_qos_port_group_t *__qos_policy_get_port_group_by_name(const char + *const name) +{ + osm_qos_port_group_t *p_port_group = NULL; + cl_list_iterator_t list_iterator; + + list_iterator = cl_list_head(&p_qos_policy->port_groups); + while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { + p_port_group = + (osm_qos_port_group_t *) cl_list_obj(list_iterator); + if (!p_port_group) + continue; + + /* names are case INsensitive */ + if (strcasecmp(name, p_port_group->name) == 0) + return p_port_group; + + list_iterator = cl_list_next(list_iterator); + } + + return NULL; +} + +/*************************************************** + ***************************************************/ + +int osm_qos_policy_validate() +{ + cl_list_iterator_t match_rules_list_iterator; + cl_list_iterator_t list_iterator; + osm_qos_port_group_t *p_port_group = NULL; + osm_qos_match_rule_t *p_qos_match_rule = NULL; + char *str; + unsigned i; + int res = 0; + + OSM_LOG_ENTER(p_qos_parser_osm_log, osm_qos_policy_validate); + + /* set default qos level */ + + p_qos_policy->p_default_qos_level = + __qos_policy_get_qos_level_by_name + (OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); + if (!p_qos_policy->p_default_qos_level) { + osm_log(p_qos_parser_osm_log, OSM_LOG_ERROR, + "osm_qos_policy_validate: ERR AC10: " + "Default qos-level (%s) not defined.\n", + OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); + res = 1; + goto Exit; + } + + /* scan all the match rules, and fill the lists of pointers to + relevant qos levels and port groups to speed up PR matching */ + + i = 1; + match_rules_list_iterator = + cl_list_head(&p_qos_policy->qos_match_rules); + while (match_rules_list_iterator != + cl_list_end(&p_qos_policy->qos_match_rules)) { + p_qos_match_rule = + (osm_qos_match_rule_t *) + cl_list_obj(match_rules_list_iterator); + CL_ASSERT(p_qos_match_rule); + + /* find the matching qos-level for each match-rule */ + + p_qos_match_rule->p_qos_level = + __qos_policy_get_qos_level_by_name(p_qos_match_rule-> + qos_level_name); + + if (!p_qos_match_rule->p_qos_level) { + osm_log(p_qos_parser_osm_log, OSM_LOG_ERROR, + "osm_qos_policy_validate: ERR AC11: " + "qos-match-rule num %u: qos-level '%s' not found\n", + i, p_qos_match_rule->qos_level_name); + res = 1; + goto Exit; + } + + /* find the matching port-group for element of source_list */ + + if (cl_list_count(&p_qos_match_rule->source_list)) { + list_iterator = + cl_list_head(&p_qos_match_rule->source_list); + while (list_iterator != + cl_list_end(&p_qos_match_rule->source_list)) { + str = (char *)cl_list_obj(list_iterator); + CL_ASSERT(str); + + p_port_group = + __qos_policy_get_port_group_by_name(str); + if (!p_port_group) { + osm_log(p_qos_parser_osm_log, + OSM_LOG_ERROR, + "osm_qos_policy_validate: ERR AC12: " + "qos-match-rule num %u: source port-group '%s' not found\n", + i, str); + res = 1; + goto Exit; + } + + cl_list_insert_tail(&p_qos_match_rule-> + source_group_list, + p_port_group); + + list_iterator = cl_list_next(list_iterator); + } + } + + /* find the matching port-group for element of destination_list */ + + if (cl_list_count(&p_qos_match_rule->destination_list)) { + list_iterator = + cl_list_head(&p_qos_match_rule->destination_list); + while (list_iterator != + cl_list_end(&p_qos_match_rule-> + destination_list)) { + str = (char *)cl_list_obj(list_iterator); + CL_ASSERT(str); + + p_port_group = + __qos_policy_get_port_group_by_name(str); + if (!p_port_group) { + osm_log(p_qos_parser_osm_log, + OSM_LOG_ERROR, + "osm_qos_policy_validate: ERR AC13: " + "qos-match-rule num %u: destination port-group '%s' not found\n", + i, str); + res = 1; + goto Exit; + } + + cl_list_insert_tail(&p_qos_match_rule-> + destination_group_list, + p_port_group); + + list_iterator = cl_list_next(list_iterator); + } + } + + /* done with the current match-rule */ + + match_rules_list_iterator = + cl_list_next(match_rules_list_iterator); + i++; + } + + Exit: + OSM_LOG_EXIT(p_qos_parser_osm_log); + return res; +} /* osm_qos_policy_validate() */ + +/*************************************************** + ***************************************************/ + +void osm_qos_policy_get_qos_level_by_pr(IN const osm_pr_rcv_t * p_rcv, + 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, + OUT osm_qos_level_t ** pp_qos_level) +{ + osm_qos_match_rule_t *p_qos_match_rule = NULL; + osm_qos_level_t *p_qos_level = NULL; + + OSM_LOG_ENTER(p_rcv->p_log, osm_qos_policy_get_qos_level_by_pr); + + *pp_qos_level = NULL; + + if (!p_qos_policy) + goto Exit; + + p_qos_match_rule = __qos_policy_get_match_rule_by_pr(p_rcv, + p_pr, + p_src_physp, + p_dest_physp, + comp_mask); + + if (p_qos_match_rule) + p_qos_level = p_qos_match_rule->p_qos_level; + else + p_qos_level = p_qos_policy->p_default_qos_level; + + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "osm_qos_policy_get_qos_level_by_pr: " + "PathRecord request:" + "Src port 0x%016" PRIx64 ", " + "Dst port 0x%016" PRIx64 "\n", + cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), + cl_ntoh64(osm_physp_get_port_guid(p_dest_physp))); + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "osm_qos_policy_get_qos_level_by_pr: " + "Applying QoS Level %s (%s)\n", + p_qos_level->name, + (p_qos_level->use) ? p_qos_level->use : "no description"); + + *pp_qos_level = p_qos_level; + + Exit: + OSM_LOG_EXIT(p_rcv->p_log); +} /* osm_qos_policy_get_qos_level_by_pr() */ + +/*************************************************** + ***************************************************/ -- 1.5.1.4 _______________________________________________ general mailing list general@lists.openfabrics.org http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general