[ofa-general] [PATCH 3/7] osm: QoS policy C & H files

Yevgeny Kliteynik kliteyn at dev.mellanox.co.il
Mon Aug 20 05:06:19 PDT 2007


QoS policy data structures and functions

Signed-off-by: Yevgeny Kliteynik <kliteyn at dev.mellanox.co.il>
---
 opensm/include/opensm/osm_qos_policy.h |  193 +++++++
 opensm/opensm/osm_qos_policy.c         |  916 ++++++++++++++++++++++++++++++++
 2 files changed, 1109 insertions(+), 0 deletions(-)
 create mode 100644 opensm/include/opensm/osm_qos_policy.h
 create mode 100644 opensm/opensm/osm_qos_policy.c

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





More information about the general mailing list