[ofa-general] [PATCH] osm: QoS - adding simplified syntax for policy definition
Yevgeny Kliteynik
kliteyn at dev.mellanox.co.il
Sun Nov 18 04:49:28 PST 2007
Yevgeny Kliteynik wrote:
> This patch adds simplified syntax for QoS definition in QoS Policy file.
> Using this syntax the administrator is able to define QoS policy per
> ULP and/or per Service ID and/or per partition (pkey).
>
> Here's an example of the policy file with the new syntax, which is added
> in a new section called qos-policy:
Correction: it's called "qos-ulps"
-- Yevgeny
> qos-ulps
> sdp, port-num 30000 : 1 #SL for SDP when destination port is 30000
> sdp, port-num 10000-20000, 0xfffd : 2
> sdp : 0 #default SL for SDP
> srp, target-port-guid 0x1234-0x1235 : 2
> iser, port-num 0x3234-0x3235 : 4 #SL for iSER whith specific target ports
> iser : 5 #default SL for iSER
> rds, port-num 25000 : 2 #SL for RDS when destination port is 25000
> rds : 0 #default SL for RDS
> ipoib, pkey 0x0001 : 5 #SL for IPoIB on partition with pkey 0x0001
> ipoib : 6 #default IPoIB partition - pkey=0x7FFF
> any, pkey 0x0ABC : 3
> any, pkey 0x0ABD-0x0ABF,0x0BBD-0x0BBA : 4
> any, service-id 0x6234 : 2
> any, target-port-guid 0x2234-0xF235 : 2
> default : 0 #default SL
> end-qos-ulps
>
> Since any section of the policy file is optional as long as basic rules
> of the file are kept, the above example can serve as a complete QoS
> policy file - short and clear.
>
> I suspect that most of the administrators will use only this syntax, but
> if someone wishes to manage QoS in more detailed manner, there's always
> the rest of the policy file to do so.
>
> Signed-off-by: Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
> ---
> opensm/include/opensm/osm_qos_policy.h | 5 +
> opensm/opensm/osm_qos_parser.l | 46 +++
> opensm/opensm/osm_qos_parser.y | 637 +++++++++++++++++++++++++++++++-
> opensm/opensm/osm_qos_policy.c | 79 ++++-
> 4 files changed, 756 insertions(+), 11 deletions(-)
>
> diff --git a/opensm/include/opensm/osm_qos_policy.h b/opensm/include/opensm/osm_qos_policy.h
> index 61fc325..d61c269 100644
> --- a/opensm/include/opensm/osm_qos_policy.h
> +++ b/opensm/include/opensm/osm_qos_policy.h
> @@ -59,6 +59,11 @@
> #define OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH 128
> #define OSM_QOS_POLICY_DEFAULT_LEVEL_NAME "default"
>
> +#define OSM_QOS_POLICY_ULP_SDP_SERVICE_ID 0x0000000000010000ULL
> +#define OSM_QOS_POLICY_ULP_RDS_SERVICE_ID 0x0000000001060000ULL
> +#define OSM_QOS_POLICY_ULP_ISER_SERVICE_ID 0x0000000001060000ULL
> +#define OSM_QOS_POLICY_ULP_ISER_PORT 0x035C
> +
> #define OSM_QOS_POLICY_NODE_TYPE_CA (((uint8_t)1)<<IB_NODE_TYPE_CA)
> #define OSM_QOS_POLICY_NODE_TYPE_SWITCH (((uint8_t)1)<<IB_NODE_TYPE_SWITCH)
> #define OSM_QOS_POLICY_NODE_TYPE_ROUTER (((uint8_t)1)<<IB_NODE_TYPE_ROUTER)
> diff --git a/opensm/opensm/osm_qos_parser.l b/opensm/opensm/osm_qos_parser.l
> index bfc4637..41f8720 100644
> --- a/opensm/opensm/osm_qos_parser.l
> +++ b/opensm/opensm/osm_qos_parser.l
> @@ -105,19 +105,34 @@ static void reset_new_line_flags();
> #define START_RATE_LIMIT {in_single_number = TRUE;} /* single number */
> #define START_PACKET_LIFE {in_single_number = TRUE;} /* single number */
>
> +#define START_ULP_DEFAULT {in_single_number = TRUE;} /* single number */
> +#define START_ULP_ANY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
> +#define START_ULP_SDP_DEFAULT {in_single_number = TRUE;} /* single number */
> +#define START_ULP_SDP_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
> +#define START_ULP_RDS_DEFAULT {in_single_number = TRUE;} /* single number */
> +#define START_ULP_RDS_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
> +#define START_ULP_ISER_DEFAULT {in_single_number = TRUE;} /* single number */
> +#define START_ULP_ISER_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
> +#define START_ULP_SRP_GUID {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
> +#define START_ULP_IPOIB_DEFAULT {in_single_number = TRUE;} /* single number */
> +#define START_ULP_IPOIB_PKEY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */
>
>
> %}
>
> %option nounput
>
> +QOS_ULPS_START qos\-ulps
> +QOS_ULPS_END end\-qos\-ulps
> PORT_GROUPS_START port\-groups
> PORT_GROUPS_END end\-port\-groups
> PORT_GROUP_START port\-group
> PORT_GROUP_END end\-port\-group
> +PORT_NUM port\-num
> NAME name
> USE use
> PORT_GUID port\-guid
> +TARGET_PORT_GUID target\-port\-guid
> PORT_NAME port\-name
> PARTITION partition
> NODE_TYPE node\-type
> @@ -167,10 +182,19 @@ SWITCH [Ss][Ww][Ii][Tt][Cc][Hh]
> SELF [Ss][Ee][Ll][Ff]
> ALL [Aa][Ll][Ll]
>
> +ULP_SDP [Ss][Dd][Pp]
> +ULP_SRP [Ss][Rr][Pp]
> +ULP_RDS [Rr][Dd][Ss]
> +ULP_IPOIB [Ii][Pp][Oo][Ii][Bb]
> +ULP_ISER [Ii][Ss][Ee][Rr]
> +ULP_ANY [Aa][Nn][Yy]
> +ULP_DEFAULT [Dd][Ee][Ff][Aa][Uu][Ll][Tt]
> +
> WHITE [ \t]+
> NEW_LINE \n
> COMMENT \#.*\n
> WHITE_DOTDOT_WHITE [ \t]*:[ \t]*
> +WHITE_COMMA_WHITE [ \t]*,[ \t]*
> QUOTED_TEXT \"[^\"]*\"
>
> %%
> @@ -181,6 +205,9 @@ QUOTED_TEXT \"[^\"]*\"
> {WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; }
> {NEW_LINE} { SAVE_POS; RESET_NEW_LINE_FLAGS; }
>
> +{QOS_ULPS_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_START; }
> +{QOS_ULPS_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_END; }
> +
> {PORT_GROUPS_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_START; }
> {PORT_GROUPS_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_END; }
> {PORT_GROUP_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_START; }
> @@ -242,6 +269,25 @@ QUOTED_TEXT \"[^\"]*\"
> {SELF} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SELF; __qos_parser_lval = strdup(__qos_parser_text); return TK_TEXT; }
> {ALL} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ALL; __qos_parser_lval = strdup(__qos_parser_text); return TK_TEXT; }
>
> +{ULP_DEFAULT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_DEFAULT; return TK_ULP_DEFAULT; }
> +{ULP_ANY}{WHITE_COMMA_WHITE}{SERVICE_ID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SERVICE_ID; }
> +{ULP_ANY}{WHITE_COMMA_WHITE}{PKEY} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_PKEY; }
> +{ULP_ANY}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_TARGET_PORT_GUID; }
> +
> +{ULP_SDP}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_SDP_DEFAULT; }
> +{ULP_SDP}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_SDP_PORT; }
> +
> +{ULP_RDS}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_DEFAULT; return TK_ULP_RDS_DEFAULT; }
> +{ULP_RDS}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_PORT; return TK_ULP_RDS_PORT; }
> +
> +{ULP_ISER}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_ISER_DEFAULT; }
> +{ULP_ISER}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_ISER_PORT; }
> +
> +{ULP_SRP}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SRP_GUID; return TK_ULP_SRP_GUID; }
> +
> +{ULP_IPOIB}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_DEFAULT; return TK_ULP_IPOIB_DEFAULT; }
> +{ULP_IPOIB}{WHITE_COMMA_WHITE}{PKEY} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_PKEY; return TK_ULP_IPOIB_PKEY; }
> +
> 0[xX][0-9a-fA-F]+ {
> SAVE_POS;
> __qos_parser_lval = strdup(__qos_parser_text);
> diff --git a/opensm/opensm/osm_qos_parser.y b/opensm/opensm/osm_qos_parser.y
> index bf560aa..f136af4 100644
> --- a/opensm/opensm/osm_qos_parser.y
> +++ b/opensm/opensm/osm_qos_parser.y
> @@ -91,6 +91,9 @@ static int __parser_qos_level_end();
> static void __parser_match_rule_start();
> static int __parser_match_rule_end();
>
> +static void __parser_ulp_match_rule_start();
> +static int __parser_ulp_match_rule_end();
> +
> static void __rangelist2rangearr(
> cl_list_t * p_list,
> uint64_t ** * p_arr,
> @@ -126,6 +129,15 @@ static void __parser_add_map_to_port_map(
> cl_qmap_t * p_dmap,
> cl_map_t * p_smap);
>
> +static int __validate_pkeys(
> + uint64_t ** range_arr,
> + unsigned range_len,
> + boolean_t is_ipoib);
> +
> +static void __setup_simple_qos_levels();
> +static void __clear_simple_qos_levels();
> +static void __setup_ulp_match_rules();
> +static void __process_ulp_match_rules();
> static void __qos_parser_error(const char *format, ...);
>
> extern char * __qos_parser_text;
> @@ -148,6 +160,20 @@ osm_qos_level_t * p_current_qos_level = NULL;
> osm_qos_match_rule_t * p_current_qos_match_rule = NULL;
> osm_log_t * p_qos_parser_osm_log;
>
> +/* 16 Simple QoS Levels - one for each SL */
> +static osm_qos_level_t osm_qos_policy_simple_qos_levels[16];
> +
> +/* Default Simple QoS Level */
> +osm_qos_level_t __default_simple_qos_level;
> +
> +/*
> + * List of match rules that will be generated by the
> + * qos-ulp section. These rules are concatenated to
> + * the end of the usual matching rules list at the
> + * end of parsing.
> + */
> +static cl_list_t __ulp_match_rules;
> +
> /***************************************************/
>
> %}
> @@ -159,6 +185,9 @@ osm_log_t * p_qos_parser_osm_log;
> %token TK_ASTERISK
> %token TK_TEXT
>
> +%token TK_QOS_ULPS_START
> +%token TK_QOS_ULPS_END
> +
> %token TK_PORT_GROUPS_START
> %token TK_PORT_GROUPS_END
> %token TK_PORT_GROUP_START
> @@ -220,6 +249,19 @@ osm_log_t * p_qos_parser_osm_log;
> %token TK_NODE_TYPE_SELF
> %token TK_NODE_TYPE_ALL
>
> +%token TK_ULP_DEFAULT
> +%token TK_ULP_ANY_SERVICE_ID
> +%token TK_ULP_ANY_PKEY
> +%token TK_ULP_ANY_TARGET_PORT_GUID
> +%token TK_ULP_SDP_DEFAULT
> +%token TK_ULP_SDP_PORT
> +%token TK_ULP_RDS_DEFAULT
> +%token TK_ULP_RDS_PORT
> +%token TK_ULP_ISER_DEFAULT
> +%token TK_ULP_ISER_PORT
> +%token TK_ULP_SRP_GUID
> +%token TK_ULP_IPOIB_DEFAULT
> +%token TK_ULP_IPOIB_PKEY
>
> %start head
>
> @@ -232,13 +274,42 @@ qos_policy_entries: /* empty */
> | qos_policy_entries qos_policy_entry
> ;
>
> -qos_policy_entry: port_groups_section
> +qos_policy_entry: qos_ulps_section
> + | port_groups_section
> | qos_setup_section
> | qos_levels_section
> | qos_match_rules_section
> ;
>
> /*
> + * Parsing qos-ulps:
> + * -------------------
> + * qos-ulps
> + * default : 0 #default SL
> + * sdp, port-num 30000 : 1 #SL for SDP when destination port is 30000
> + * sdp, port-num 10000-20000 : 2
> + * sdp : 0 #default SL for SDP
> + * srp, target-port-guid 0x1234 : 2
> + * rds, port-num 25000 : 2 #SL for RDS when destination port is 25000
> + * rds, : 0 #default SL for RDS
> + * iser, port-num 900 : 5 #SL for iSER where target port is 900
> + * iser : 4 #default SL for iSER
> + * ipoib, pkey 0x0001 : 5 #SL for IPoIB on partition with pkey 0x0001
> + * ipoib : 6 #default IPoIB partition - pkey=0x7FFF
> + * any, service-id 0x6234 : 2
> + * any, pkey 0x0ABC : 3
> + * any, target-port-guid 0x0ABC-0xFFFFF : 6
> + * end-qos-ulps
> + */
> +
> +qos_ulps_section: TK_QOS_ULPS_START qos_ulps TK_QOS_ULPS_END
> + ;
> +
> +qos_ulps: qos_ulp
> + | qos_ulps qos_ulp
> + ;
> +
> + /*
> * Parsing port groups:
> * -------------------
> * port-groups
> @@ -536,6 +607,410 @@ qos_match_rule_entry: qos_match_rule_use
> | qos_match_rule_pkey
> ;
>
> +
> + /*
> + * Parsing qos-ulps:
> + * -----------------
> + * default
> + * sdp
> + * sdp with port-num
> + * rds
> + * rds with port-num
> + * srp with port-guid
> + * iser
> + * iser with port-num
> + * ipoib
> + * ipoib with pkey
> + * any with service-id
> + * any with pkey
> + * any with target-port-guid
> + */
> +
> +qos_ulp: TK_ULP_DEFAULT single_number {
> + /* parsing default ulp rule: "default: num" */
> + cl_list_iterator_t list_iterator;
> + uint64_t * p_tmp_num;
> +
> + list_iterator = cl_list_head(&tmp_parser_struct.num_list);
> + p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
> + if (*p_tmp_num > 15)
> + {
> + __qos_parser_error("illegal SL value");
> + return 1;
> + }
> + __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num);
> + __default_simple_qos_level.sl_set = TRUE;
> + free(p_tmp_num);
> + cl_list_remove_all(&tmp_parser_struct.num_list);
> + }
> +
> + | qos_ulp_type_any_service list_of_ranges TK_DOTDOT {
> + /* "any, service-id ... : sl" - one instance of list of ranges */
> + uint64_t ** range_arr;
> + unsigned range_len;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("ULP rule doesn't have service ids");
> + return 1;
> + }
> +
> + /* get all the service id ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = range_len;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_any_pkey list_of_ranges TK_DOTDOT {
> + /* "any, pkey ... : sl" - one instance of list of ranges */
> + uint64_t ** range_arr;
> + unsigned range_len;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("ULP rule doesn't have pkeys");
> + return 1;
> + }
> +
> + /* get all the pkey ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> +
> + p_current_qos_match_rule->pkey_range_arr = range_arr;
> + p_current_qos_match_rule->pkey_range_len = range_len;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_any_target_port_guid list_of_ranges TK_DOTDOT {
> + /* any, target-port-guid ... : sl */
> + uint64_t ** range_arr;
> + unsigned range_len;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("ULP rule doesn't have port guids");
> + return 1;
> + }
> +
> + /* create a new port group with these ports */
> + __parser_port_group_start();
> +
> + p_current_port_group->name = strdup("_ULP_Targets_");
> + p_current_port_group->use = strdup("Generated from ULP rules");
> +
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> +
> + __parser_add_guid_range_to_port_map(
> + &p_current_port_group->port_map,
> + range_arr,
> + range_len);
> +
> + /* add this port group to the destination
> + groups of the current match rule */
> + cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
> + p_current_port_group);
> +
> + __parser_port_group_end();
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_sdp_default {
> + /* "sdp : sl" - default SL for SDP */
> + uint64_t ** range_arr =
> + (uint64_t **)malloc(sizeof(uint64_t *));
> + range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
> + range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
> + range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF;
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = 1;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_sdp_port list_of_ranges TK_DOTDOT {
> + /* sdp with port numbers */
> + uint64_t ** range_arr;
> + unsigned range_len;
> + unsigned i;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("SDP ULP rule doesn't have port numbers");
> + return 1;
> + }
> +
> + /* get all the port ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> + /* now translate these port numbers into service ids */
> + for (i = 0; i < range_len; i++)
> + {
> + if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
> + {
> + __qos_parser_error("SDP port number out of range");
> + return 1;
> + }
> + range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
> + range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
> + }
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = range_len;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_rds_default {
> + /* "rds : sl" - default SL for RDS */
> + uint64_t ** range_arr =
> + (uint64_t **)malloc(sizeof(uint64_t *));
> + range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
> + range_arr[0][0] = OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
> + range_arr[0][1] = OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + 0xFFFF;
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = 1;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_rds_port list_of_ranges TK_DOTDOT {
> + /* rds with port numbers */
> + uint64_t ** range_arr;
> + unsigned range_len;
> + unsigned i;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("RDS ULP rule doesn't have port numbers");
> + return 1;
> + }
> +
> + /* get all the port ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> + /* now translate these port numbers into service ids */
> + for (i = 0; i < range_len; i++)
> + {
> + if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
> + {
> + __qos_parser_error("SDP port number out of range");
> + return 1;
> + }
> + range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
> + range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
> + }
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = range_len;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_iser_default {
> + /* "iSER : sl" - default SL for iSER */
> + uint64_t ** range_arr =
> + (uint64_t **)malloc(sizeof(uint64_t *));
> + range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
> + range_arr[0][0] = range_arr[0][1] =
> + OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT;
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = 1;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_iser_port list_of_ranges TK_DOTDOT {
> + /* iser with port numbers */
> + uint64_t ** range_arr;
> + unsigned range_len;
> + unsigned i;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("iSER ULP rule doesn't have port numbers");
> + return 1;
> + }
> +
> + /* get all the port ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> + /* now translate these port numbers into service ids */
> + for (i = 0; i < range_len; i++)
> + {
> + if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
> + {
> + __qos_parser_error("SDP port number out of range");
> + return 1;
> + }
> + range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
> + range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
> + }
> +
> + p_current_qos_match_rule->service_id_range_arr = range_arr;
> + p_current_qos_match_rule->service_id_range_len = range_len;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_srp_guid list_of_ranges TK_DOTDOT {
> + /* srp with target guids - this rule is similar
> + to writing 'any' ulp with target port guids */
> + uint64_t ** range_arr;
> + unsigned range_len;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("SRP ULP rule doesn't have port guids");
> + return 1;
> + }
> +
> + /* create a new port group with these ports */
> + __parser_port_group_start();
> +
> + p_current_port_group->name = strdup("_SRP_Targets_");
> + p_current_port_group->use = strdup("Generated from ULP rules");
> +
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> +
> + __parser_add_guid_range_to_port_map(
> + &p_current_port_group->port_map,
> + range_arr,
> + range_len);
> +
> + /* add this port group to the destination
> + groups of the current match rule */
> + cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
> + p_current_port_group);
> +
> + __parser_port_group_end();
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_ipoib_default {
> + /* ipoib w/o any pkeys (default pkey) */
> + uint64_t ** range_arr =
> + (uint64_t **)malloc(sizeof(uint64_t *));
> + range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
> + range_arr[0][0] = range_arr[0][1] = 0x7fff;
> +
> + /*
> + * Although we know that the default partition exists,
> + * we still need to validate it by checking that it has
> + * at least two full members. Otherwise IPoIB won't work.
> + */
> + if (__validate_pkeys(range_arr, 1, TRUE))
> + return 1;
> +
> + p_current_qos_match_rule->pkey_range_arr = range_arr;
> + p_current_qos_match_rule->pkey_range_len = 1;
> +
> + } qos_ulp_sl
> +
> + | qos_ulp_type_ipoib_pkey list_of_ranges TK_DOTDOT {
> + /* ipoib with pkeys */
> + uint64_t ** range_arr;
> + unsigned range_len;
> +
> + if (!cl_list_count(&tmp_parser_struct.num_pair_list))
> + {
> + __qos_parser_error("IPoIB ULP rule doesn't have pkeys");
> + return 1;
> + }
> +
> + /* get all the pkey ranges */
> + __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
> + &range_arr,
> + &range_len );
> +
> + /*
> + * Validate pkeys.
> + * For IPoIB pkeys the validation is strict.
> + * If some problem would be found, parsing will
> + * be aborted with a proper error messages.
> + */
> + if (__validate_pkeys(range_arr, range_len, TRUE))
> + return 1;
> +
> + p_current_qos_match_rule->pkey_range_arr = range_arr;
> + p_current_qos_match_rule->pkey_range_len = range_len;
> +
> + } qos_ulp_sl
> + ;
> +
> +qos_ulp_type_any_service: TK_ULP_ANY_SERVICE_ID
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_any_pkey: TK_ULP_ANY_PKEY
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_any_target_port_guid: TK_ULP_ANY_TARGET_PORT_GUID
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_sdp_default: TK_ULP_SDP_DEFAULT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_sdp_port: TK_ULP_SDP_PORT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_rds_default: TK_ULP_RDS_DEFAULT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_rds_port: TK_ULP_RDS_PORT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_iser_default: TK_ULP_ISER_DEFAULT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_iser_port: TK_ULP_ISER_PORT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_srp_guid: TK_ULP_SRP_GUID
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_ipoib_default: TK_ULP_IPOIB_DEFAULT
> + { __parser_ulp_match_rule_start(); };
> +
> +qos_ulp_type_ipoib_pkey: TK_ULP_IPOIB_PKEY
> + { __parser_ulp_match_rule_start(); };
> +
> +
> +qos_ulp_sl: single_number {
> + /* get the SL for ULP rules */
> + cl_list_iterator_t list_iterator;
> + uint64_t * p_tmp_num;
> + uint8_t sl;
> +
> + list_iterator = cl_list_head(&tmp_parser_struct.num_list);
> + p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
> + if (*p_tmp_num > 15)
> + {
> + __qos_parser_error("illegal SL value");
> + return 1;
> + }
> +
> + sl = (uint8_t)(*p_tmp_num);
> + free(p_tmp_num);
> + cl_list_remove_all(&tmp_parser_struct.num_list);
> +
> + p_current_qos_match_rule->p_qos_level =
> + &osm_qos_policy_simple_qos_levels[sl];
> + p_current_qos_match_rule->qos_level_name =
> + strdup(osm_qos_policy_simple_qos_levels[sl].name);
> +
> + if (__parser_ulp_match_rule_end())
> + return 1;
> + }
> + ;
> +
> /*
> * port_group_entry values:
> * port_group_name
> @@ -1814,10 +2289,19 @@ int osm_qos_parse_policy_file(IN osm_subn_t * const p_subn)
> if (first_time)
> {
> first_time = FALSE;
> + __setup_simple_qos_levels();
> + __setup_ulp_match_rules();
> osm_log(p_qos_parser_osm_log, OSM_LOG_INFO,
> "osm_qos_parse_policy_file: Loading QoS policy file (%s)\n",
> p_subn->opt.qos_policy_file);
> }
> + else
> + /*
> + * ULP match rules list was emptied at the end of
> + * previous parsing iteration.
> + * What's left is to clear simple QoS levels.
> + */
> + __clear_simple_qos_levels();
>
> column_num = 1;
> line_num = 1;
> @@ -1843,6 +2327,9 @@ int osm_qos_parse_policy_file(IN osm_subn_t * const p_subn)
> goto Exit;
> }
>
> + /* add generated ULP match rules to the usual match rules */
> + __process_ulp_match_rules();
> +
> if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log))
> {
> osm_log(p_qos_parser_osm_log, OSM_LOG_ERROR,
> @@ -2068,6 +2555,26 @@ static int __parser_match_rule_end()
> /***************************************************
> ***************************************************/
>
> +static void __parser_ulp_match_rule_start()
> +{
> + p_current_qos_match_rule = osm_qos_policy_match_rule_create();
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> +static int __parser_ulp_match_rule_end()
> +{
> + CL_ASSERT(p_current_qos_match_rule->p_qos_level);
> + cl_list_insert_tail(&__ulp_match_rules,
> + p_current_qos_match_rule);
> + p_current_qos_match_rule = NULL;
> + return 0;
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> static void __parser_tmp_struct_init()
> {
> tmp_parser_struct.str[0] = '\0';
> @@ -2110,6 +2617,73 @@ static void __parser_tmp_struct_destroy()
> /***************************************************
> ***************************************************/
>
> +#define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL"
> +#define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT"
> +
> +static void __setup_simple_qos_levels()
> +{
> + uint8_t i;
> + char tmp_buf[30];
> + memset(osm_qos_policy_simple_qos_levels, 0,
> + sizeof(osm_qos_policy_simple_qos_levels));
> + for (i = 0; i < 16; i++)
> + {
> + osm_qos_policy_simple_qos_levels[i].sl = i;
> + osm_qos_policy_simple_qos_levels[i].sl_set = TRUE;
> + sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i);
> + osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf);
> + }
> +
> + memset(&__default_simple_qos_level, 0,
> + sizeof(__default_simple_qos_level));
> + __default_simple_qos_level.name =
> + strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME);
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> +static void __clear_simple_qos_levels()
> +{
> + /*
> + * Simple QoS levels are static.
> + * What's left is to invalidate default simple QoS level.
> + */
> + __default_simple_qos_level.sl_set = FALSE;
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> +static void __setup_ulp_match_rules()
> +{
> + cl_list_construct(&__ulp_match_rules);
> + cl_list_init(&__ulp_match_rules, 10);
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> +static void __process_ulp_match_rules()
> +{
> + cl_list_iterator_t list_iterator;
> + osm_qos_match_rule_t *p_qos_match_rule = NULL;
> +
> + list_iterator = cl_list_head(&__ulp_match_rules);
> + while (list_iterator != cl_list_end(&__ulp_match_rules))
> + {
> + p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
> + if (p_qos_match_rule)
> + cl_list_insert_tail(&p_qos_policy->qos_match_rules,
> + p_qos_match_rule);
> + list_iterator = cl_list_next(list_iterator);
> + }
> + cl_list_remove_all(&__ulp_match_rules);
> +}
> +
> +/***************************************************
> + ***************************************************/
> +
> static int OSM_CDECL
> __cmp_num_range(
> const void * p1,
> @@ -2394,3 +2968,64 @@ static void __parser_add_map_to_port_map(
>
> /***************************************************
> ***************************************************/
> +
> +static int __validate_pkeys( uint64_t ** range_arr,
> + unsigned range_len,
> + boolean_t is_ipoib)
> +{
> + unsigned i;
> + uint64_t pkey_64;
> + ib_net16_t pkey;
> + osm_prtn_t * p_prtn;
> +
> + if (!range_arr || !range_len)
> + return 0;
> +
> + for (i = 0; i < range_len; i++) {
> + for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
> + pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
> + p_prtn = (osm_prtn_t *)
> + cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
> +
> + if (p_prtn == (osm_prtn_t *)cl_qmap_end(
> + &p_qos_policy->p_subn->prtn_pkey_tbl))
> + p_prtn = NULL;
> +
> + if (is_ipoib) {
> + /*
> + * Be very strict for IPoIB partition:
> + * - the partition for the pkey have to exist
> + * - it has to have at least 2 full members
> + */
> + if (!p_prtn) {
> + __qos_parser_error("IPoIB partition, pkey 0x%04X - "
> + "partition doesn't exist",
> + cl_ntoh16(pkey));
> + return 1;
> + }
> + else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) {
> + __qos_parser_error("IPoIB partition, pkey 0x%04X - "
> + "partition has less than two full members",
> + cl_ntoh16(pkey));
> + return 1;
> + }
> + }
> + else if (!p_prtn) {
> + /*
> + * For non-IPoIB pkey we just want to check that
> + * the relevant partition exists.
> + * And even if it doesn't, don't exit - just print
> + * error message and continue.
> + */
> + osm_log(p_qos_parser_osm_log, OSM_LOG_ERROR,
> + "__validate_pkeys: ERR AC02: pkey 0x%04X - "
> + "partition doesn't exist",
> + cl_ntoh16(pkey));
> + }
> + }
> + }
> + return 0;
> +}
> +
> +/***************************************************
> + ***************************************************/
> diff --git a/opensm/opensm/osm_qos_policy.c b/opensm/opensm/osm_qos_policy.c
> index 34f72b0..c0a7810 100644
> --- a/opensm/opensm/osm_qos_policy.c
> +++ b/opensm/opensm/osm_qos_policy.c
> @@ -56,6 +56,8 @@
> #include <opensm/osm_opensm.h>
> #include <opensm/osm_qos_policy.h>
>
> +extern osm_qos_level_t __default_simple_qos_level;
> +
> /***************************************************
> ***************************************************/
>
> @@ -780,8 +782,11 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
> osm_qos_port_group_t *p_port_group = NULL;
> osm_qos_match_rule_t *p_qos_match_rule = NULL;
> char *str;
> - unsigned i;
> + unsigned i, j;
> int res = 0;
> + uint64_t pkey_64;
> + ib_net16_t pkey;
> + osm_prtn_t * p_prtn;
>
> OSM_LOG_ENTER(p_log, osm_qos_policy_validate);
>
> @@ -790,12 +795,20 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
> p_qos_policy->p_default_qos_level =
> __qos_policy_get_qos_level_by_name(p_qos_policy, OSM_QOS_POLICY_DEFAULT_LEVEL_NAME);
> if (!p_qos_policy->p_default_qos_level) {
> - osm_log(p_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;
> + /* There's no default QoS level in the usual qos-level section.
> + Check whether the 'simple' default QoS level that can be
> + defined in the qos-ulp section exists */
> + if (__default_simple_qos_level.sl_set) {
> + p_qos_policy->p_default_qos_level = &__default_simple_qos_level;
> + }
> + else {
> + osm_log(p_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
> @@ -813,9 +826,10 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
>
> /* 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_policy,
> - p_qos_match_rule->qos_level_name);
> + if (!p_qos_match_rule->p_qos_level)
> + p_qos_match_rule->p_qos_level =
> + __qos_policy_get_qos_level_by_name(p_qos_policy,
> + p_qos_match_rule->qos_level_name);
>
> if (!p_qos_match_rule->p_qos_level) {
> osm_log(p_log, OSM_LOG_ERROR,
> @@ -887,6 +901,51 @@ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy,
> }
> }
>
> + /*
> + * Scan all the pkeys in matching rule, and if the
> + * partition for these pkeys exists, set the SL
> + * according to the QoS Level.
> + * Warn if there's mismatch between QoS level SL
> + * and Partition SL.
> + */
> +
> + for (j = 0; j < p_qos_match_rule->pkey_range_len; j++) {
> + for ( pkey_64 = p_qos_match_rule->pkey_range_arr[i][0];
> + pkey_64 <= p_qos_match_rule->pkey_range_arr[i][1];
> + pkey_64++) {
> + pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
> + p_prtn = (osm_prtn_t *)cl_qmap_get(
> + &p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
> +
> + if (p_prtn == (osm_prtn_t *)cl_qmap_end(
> + &p_qos_policy->p_subn->prtn_pkey_tbl)) {
> + /* partition for this pkey not found */
> + osm_log(p_log,
> + OSM_LOG_ERROR,
> + "osm_qos_policy_validate: ERR AC14: "
> + "pkey 0x%04X in match rule - "
> + "partition doesn't exist\n",
> + cl_ntoh16(pkey));
> + continue;
> + }
> +
> + if (p_qos_match_rule->p_qos_level->sl_set &&
> + p_prtn->sl != p_qos_match_rule->p_qos_level->sl) {
> + /* overriding partition's SL */
> + osm_log(p_log,
> + OSM_LOG_ERROR,
> + "osm_qos_policy_validate: ERR AC15: "
> + "pkey 0x%04X in match rule - "
> + "overriding partition SL (%u) "
> + "with QoS Level SL (%u)\n",
> + cl_ntoh16(pkey),
> + p_prtn->sl,
> + p_qos_match_rule->p_qos_level->sl);
> + p_prtn->sl = p_qos_match_rule->p_qos_level->sl;
> + }
> + }
> + }
> +
> /* done with the current match-rule */
>
> match_rules_list_iterator =
More information about the general
mailing list