[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