[ofa-general] [PATCH 4/4] Many fixes on balanced minhop enhancements
Nicolas Morey Chaisemartin
nicolas.morey-chaisemartin at ext.bull.net
Tue Mar 10 07:00:14 PDT 2009
Fixed stupid order on 2nd lvl sort
Fixed bad init value for downgoing calls
Fixed bug in port counters
Fixed comments of bubble sort functions
Signed-off-by: Nicolas Morey-Chaisemartin <nicolas.morey-chaisemartin at ext.bull.net>
---
opensm/opensm/osm_ucast_ftree.c | 106 +++++++++++++++++++++++++++++----------
1 files changed, 80 insertions(+), 26 deletions(-)
diff --git a/opensm/opensm/osm_ucast_ftree.c b/opensm/opensm/osm_ucast_ftree.c
index bfefa0f..638504c 100644
--- a/opensm/opensm/osm_ucast_ftree.c
+++ b/opensm/opensm/osm_ucast_ftree.c
@@ -1901,6 +1901,13 @@ static void __osm_ftree_set_sw_fwd_table(IN cl_map_item_t * const p_map_item,
p_sw->p_osm_sw);
}
+/***************************************************
+ ***************************************************/
+
+/*
+ * Function: Finds the least loaded port group and stores its counter
+ * Given : A switch
+ */
static inline void
__osm_ftree_recalculate_min_counter_down(ftree_sw_t *p_sw){
uint32_t min= (1<<30);
@@ -1914,13 +1921,23 @@ __osm_ftree_recalculate_min_counter_down(ftree_sw_t *p_sw){
return;
}
+/*
+ * Function: Return the counter value of the least loaded down port group
+ * Given : A switch
+ */
static inline uint32_t
__osm_ftree_find_lowest_loaded_group_on_sw(ftree_sw_t *p_sw){
return p_sw->min_counter_down;
}
-/* This is for downgoing_by_going_up.
- * If load are equals, let's have a look at the remote switches and find the less loaded one */
+/*
+ * Function: Compare the load of two port groups and return which is the least loaded
+ * Given : Two port groups with remote switch
+ * When both port groups are equally loaded, it picks the one whom
+ * remote switch down ports are least loaded.
+ * This way, it prefers the switch from where it will be easier to go down (creating upward routes).
+ * If both are equal, it picks the bigger GUID to be deterministic.
+ */
static inline int
__osm_ftree_port_group_compare_load_down(const ftree_port_group_t *p1,const ftree_port_group_t *p2){
int temp = p1->counter_down -p2->counter_down ;
@@ -1936,63 +1953,100 @@ __osm_ftree_port_group_compare_load_down(const ftree_port_group_t *p1,const ftre
temp = load1-load2;
if(temp > 0)
return 1;
- return 0;
}while(0);
+ /* If they are both equal, choose the biggest GUID */
+ if(p1->remote_port_guid > p2->remote_port_guid)
+ return 1;
+
+ return -1;
}
+/*
+ * Function: Sorts an array of port group by up load order
+ * Given : A port group array and its length
+ * As the list is mostly sorted, we used a bubble sort instead of qsort
+ * as it is much faster.
+ *
+ * Important note:
+ * This function and __osm_ftree_bubble_sort_down must NOT be factorized.
+ * Although most of the code is the same and a function pointer could be used
+ * for the compareason function, it would prevent the compareason function to be inlined
+ * and cost a great deal to performances.
+ */
static inline void
__osm_ftree_bubble_sort_up(ftree_port_group_t **p_group_array, uint32_t nmemb)
{
- uint32_t i = 0; /* Indice de répétition du tri */
- uint32_t j = 0; /* Variable de boucle */
- ftree_port_group_t *tmp = p_group_array[0]; /* Variable de stockage temporaire et de fin de tri*/
+ uint32_t i = 0;
+ uint32_t j = 0;
+ ftree_port_group_t *tmp = p_group_array[0];
+
+ /* As this function is a great number of times, we only go into the loop
+ * if one of the port counters has changed, thus saving some tests */
if(tmp->hca_or_sw.p_sw->counter_up_changed == FALSE){
return;
}
- /* Boucle de répétition du tri et le test qui
- arrête le tri dès que le tableau est ordonné */
+ /* While we did modifications on the array order*/
+ /* i may grew above array length but next loop will fail and tmp will be null for the next time
+ * this way we save a test i < nmemb for each pass through the loop */
for(i = 0 ; tmp ; i++)
{
- /* Supposons le tableau ordonné */
+ /* Assume the array is orderd */
tmp = NULL;
- /* Vérification des éléments des places j et j-1 */
+ /* Comparing elements j and j-1 */
for(j = 1 ; j < (nmemb - i) ; j++)
{
- /* Si les 2 éléments sont mal triés */
+ /* If they are the wrong way around */
if( p_group_array[j]->counter_up < p_group_array[j-1]->counter_up)
{
- /* Inversion des 2 éléments */
+ /* We invert them */
tmp = p_group_array[j-1];
p_group_array[j-1] = p_group_array[j];
p_group_array[j] = tmp;
-
+ /* This sets tmp != NULL so the main loop will make another pass */
}
}
}
+
+ /* We have reordered the array so as long noone changes the counter
+ * it's not necessary to do it again */
p_group_array[0]->hca_or_sw.p_sw->counter_up_changed = FALSE;
}
+/*
+ * Function: Sorts an array of port group. Order is decide through
+ * __osm_ftree_port_group_compare_load_down ( up counters, least load remote switch, biggest GUID)
+ * Given : A port group array and its length. Each port group points to a remote switch (not a HCA)
+ * As the list is mostly sorted, we used a bubble sort instead of qsort
+ * as it is much faster.
+ *
+ * Important note:
+ * This function and __osm_ftree_bubble_sort_up must NOT be factorized.
+ * Although most of the code is the same and a function pointer could be used
+ * for the compareason function, it would prevent the compareason function to be inlined
+ * and cost a great deal to performances.
+ */
static inline void
__osm_ftree_bubble_sort_down(ftree_port_group_t **p_group_array, uint32_t nmemb)
{
- uint32_t i = 0; /* Indice de répétition du tri */
- uint32_t j = 0; /* Variable de boucle */
- ftree_port_group_t *tmp = p_group_array[0]; ; /* Variable de stockage temporaire et de fin de tri*/
+ uint32_t i = 0;
+ uint32_t j = 0;
+ ftree_port_group_t *tmp = p_group_array[0];
- /* Boucle de répétition du tri et le test qui
- arrête le tri dès que le tableau est ordonné */
+ /* While we did modifications on the array order*/
+ /* i may grew above array length but next loop will fail and tmp will be null for the next time
+ * this way we save a test i < nmemb for each pass through the loop */
for(i = 0 ; tmp ; i++)
{
- /* Supposons le tableau ordonné */
- tmp = NULL;
- /* Vérification des éléments des places j et j-1 */
+ /* Assume the array is orderd */
+ tmp = NULL;
+ /* Comparing elements j and j-1 */
for(j = 1 ; j < (nmemb - i) ; j++)
{
- /* Si les 2 éléments sont mal triés */
+ /* If they are the wrong way around */
if( __osm_ftree_port_group_compare_load_down(p_group_array[j],p_group_array[j-1]) < 0 )
{
- /* Inversion des 2 éléments */
+ /* We invert them */
tmp = p_group_array[j-1];
p_group_array[j-1] = p_group_array[j];
p_group_array[j] = tmp;
@@ -2187,12 +2241,12 @@ __osm_ftree_fabric_route_upgoing_by_going_down(IN ftree_fabric_t * p_ftree,
is_main_path, /* whether this is path to HCA that should by tracked by counters */
highest_rank_in_route, reverse_hops); /* highest visited point in the tree before going down */
created_route|=routed;
- if(routed)
+ if(routed){
p_min_port->counter_up++;
p_group->counter_up++;
p_group->hca_or_sw.p_sw->counter_up_changed = TRUE;
}
-
+ }
/* done scanning all the down-going port groups */
/* if the route was created, promote the index that
@@ -2449,7 +2503,7 @@ __osm_ftree_fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree,
* - go UP(TRUE,FALSE) to the remote switch
*/
- for (i = 1; i < p_sw->up_port_groups_num; i++) {
+ for (i = 0; i < p_sw->up_port_groups_num; i++) {
p_group = p_sw->up_port_groups[i];
p_remote_sw = p_group->remote_hca_or_sw.p_sw;
--
1.6.2-rc2.GIT
More information about the general
mailing list