[ofa-general] [PATCH] osm: QoS - adding simplified syntax for policy definition

Yevgeny Kliteynik kliteyn at dev.mellanox.co.il
Sun Nov 18 04:45:10 PST 2007


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:

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 =
-- 
1.5.1.4




More information about the general mailing list