<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2654.45">
<TITLE>Patches for Opensm</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>Hi Hal,</FONT>
</P>

<P><FONT SIZE=2>I noticed that you've checked in a change to the osm trunk few days ago without</FONT>
<BR><FONT SIZE=2>sending a patch regarding it.</FONT>
<BR><FONT SIZE=2>Since I am the owner of the opensm tree under Windows, and I am trying to keep</FONT>
<BR><FONT SIZE=2>the Windows tree as similar as possible to the Linux tree - I want to know </FONT>
<BR><FONT SIZE=2>about checkins to the osm tree, so I can add the patches to the Windows tree as well.</FONT>
<BR><FONT SIZE=2>Please send an e-mail with a patch when you commit changes to the osm tree.</FONT>
</P>

<P><FONT SIZE=2>Thanks,</FONT>
<BR><FONT SIZE=2>Yael</FONT>
</P>
<BR>

<P><FONT SIZE=2>-----Original Message-----</FONT>
<BR><FONT SIZE=2>From: Yael Kalka [<A HREF="mailto:yael@mellanox.co.il">mailto:yael@mellanox.co.il</A>]</FONT>
<BR><FONT SIZE=2>Sent: Thursday, October 27, 2005 3:04 PM</FONT>
<BR><FONT SIZE=2>To: halr@voltaire.com</FONT>
<BR><FONT SIZE=2>Cc: openib-general@openib.org; eitan@mellanox.co.il; yael@mellanox.co.il</FONT>
<BR><FONT SIZE=2>Subject: [PATCH] Opensm - fix lmc algorithm</FONT>
</P>
<BR>

<P><FONT SIZE=2>Hi Hal,</FONT>
</P>

<P><FONT SIZE=2>We noticed a problem in the lmc assignment algorithm.</FONT>
<BR><FONT SIZE=2>In the current code - when trying to run opensm with lmc > 0, the</FONT>
<BR><FONT SIZE=2>opensm goes into infinite loop.</FONT>
<BR><FONT SIZE=2>Debugging the problem we noticed that there is a problem with the</FONT>
<BR><FONT SIZE=2>lid assignment, and we changed the algorithm. The change is in the</FONT>
<BR><FONT SIZE=2>osm_lid_mgr_init_sweep function.</FONT>
<BR><FONT SIZE=2>We have done some testing to the new code, and it seems that the lmc</FONT>
<BR><FONT SIZE=2>assignment is ok with the fix.</FONT>
</P>

<P><FONT SIZE=2>Thanks,</FONT>
<BR><FONT SIZE=2>Yael</FONT>
</P>

<P><FONT SIZE=2>Signed-off-by:  Yael Kalka <yael@mellanox.co.il></FONT>
</P>

<P><FONT SIZE=2>Index: opensm/osm_lid_mgr.c</FONT>
<BR><FONT SIZE=2>===================================================================</FONT>
<BR><FONT SIZE=2>--- opensm/osm_lid_mgr.c        (revision 3848)</FONT>
<BR><FONT SIZE=2>+++ opensm/osm_lid_mgr.c        (working copy)</FONT>
<BR><FONT SIZE=2>@@ -337,7 +337,7 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2>   uint16_t             max_defined_lid;</FONT>
<BR><FONT SIZE=2>   uint16_t             max_persistent_lid;</FONT>
<BR><FONT SIZE=2>   uint16_t             max_discovered_lid;</FONT>
<BR><FONT SIZE=2>-  uint16_t             lid, l;</FONT>
<BR><FONT SIZE=2>+  uint16_t             lid;</FONT>
<BR><FONT SIZE=2>   uint16_t             disc_min_lid;</FONT>
<BR><FONT SIZE=2>   uint16_t             disc_max_lid;</FONT>
<BR><FONT SIZE=2>   uint16_t             db_min_lid;</FONT>
<BR><FONT SIZE=2>@@ -349,16 +349,23 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2>   osm_port_t          *p_port;</FONT>
<BR><FONT SIZE=2>   cl_qmap_t           *p_port_guid_tbl;</FONT>
<BR><FONT SIZE=2>   uint8_t              lmc_num_lids = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);</FONT>
<BR><FONT SIZE=2>+  uint16_t             lmc_mask;</FONT>
<BR><FONT SIZE=2>+  uint16_t             req_lid, num_lids;</FONT>
<BR><FONT SIZE=2>   </FONT>
<BR><FONT SIZE=2>   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>+  if (p_mgr->p_subn->opt.lmc)</FONT>
<BR><FONT SIZE=2>+    lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);</FONT>
<BR><FONT SIZE=2>+  else</FONT>
<BR><FONT SIZE=2>+    lmc_mask = 0xffff;</FONT>
<BR><FONT SIZE=2>+</FONT>
<BR><FONT SIZE=2>   /* if we came out of standby we need to discard any previous guid 2 lid</FONT>
<BR><FONT SIZE=2>      info we might had */</FONT>
<BR><FONT SIZE=2>   if ( p_mgr->p_subn->coming_out_of_standby == TRUE )</FONT>
<BR><FONT SIZE=2>   {</FONT>
<BR><FONT SIZE=2>     osm_db_clear( p_mgr->p_g2l );</FONT>
<BR><FONT SIZE=2>     for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++)</FONT>
<BR><FONT SIZE=2>-      cl_ptr_vector_set(&p_mgr->used_lids, lid, NULL);</FONT>
<BR><FONT SIZE=2>+      cl_ptr_vector_set(p_persistent_vec, lid, NULL);</FONT>
<BR><FONT SIZE=2>   }</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>   /* we need to cleanup the empty ranges list */</FONT>
<BR><FONT SIZE=2>@@ -375,7 +382,7 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>   /* we if are on the first sweep and in re-assign lids mode </FONT>
<BR><FONT SIZE=2>      we should ignore all the available info and simply define one </FONT>
<BR><FONT SIZE=2>-     hufe empty range */</FONT>
<BR><FONT SIZE=2>+     huge empty range */</FONT>
<BR><FONT SIZE=2>   if ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&</FONT>
<BR><FONT SIZE=2>       (p_mgr->p_subn->opt.reassign_lids == TRUE ))</FONT>
<BR><FONT SIZE=2>   {</FONT>
<BR><FONT SIZE=2>@@ -398,6 +405,34 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2>     osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);</FONT>
<BR><FONT SIZE=2>     for (lid = disc_min_lid; lid <= disc_max_lid; lid++)</FONT>
<BR><FONT SIZE=2>       cl_ptr_vector_set(p_discovered_vec, lid, p_port );</FONT>
<BR><FONT SIZE=2>+    /* make sure the guid2lid entry is valid. If not - clean it. */</FONT>
<BR><FONT SIZE=2>+    if (!osm_db_guid2lid_get( p_mgr->p_g2l,</FONT>
<BR><FONT SIZE=2>+                              cl_ntoh64(osm_port_get_guid(p_port)),</FONT>
<BR><FONT SIZE=2>+                              &db_min_lid, &db_max_lid))</FONT>
<BR><FONT SIZE=2>+    {</FONT>
<BR><FONT SIZE=2>+      if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=</FONT>
<BR><FONT SIZE=2>+           IB_NODE_TYPE_SWITCH)</FONT>
<BR><FONT SIZE=2>+        num_lids = lmc_num_lids;</FONT>
<BR><FONT SIZE=2>+      else</FONT>
<BR><FONT SIZE=2>+        num_lids = 1;</FONT>
<BR><FONT SIZE=2>+</FONT>
<BR><FONT SIZE=2>+      if ((num_lids != 1) &&</FONT>
<BR><FONT SIZE=2>+          (((db_min_lid & lmc_mask) != db_min_lid) ||</FONT>
<BR><FONT SIZE=2>+           (db_max_lid - db_min_lid + 1 < num_lids)) )</FONT>
<BR><FONT SIZE=2>+      {</FONT>
<BR><FONT SIZE=2>+        /* Not alligned, or not wide enough - remove the entry */</FONT>
<BR><FONT SIZE=2>+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,</FONT>
<BR><FONT SIZE=2>+                 "__osm_lid_mgr_init_sweep: "</FONT>
<BR><FONT SIZE=2>+                 "Cleaning persistent entry for guid:0x%016" PRIx64</FONT>
<BR><FONT SIZE=2>+                 " illegal range:[0x%x:0x%x] \n",</FONT>
<BR><FONT SIZE=2>+                 cl_ntoh64(osm_port_get_guid(p_port)), db_min_lid,</FONT>
<BR><FONT SIZE=2>+                 db_max_lid );</FONT>
<BR><FONT SIZE=2>+        osm_db_guid2lid_delete( p_mgr->p_g2l,</FONT>
<BR><FONT SIZE=2>+                                cl_ntoh64(osm_port_get_guid(p_port)));</FONT>
<BR><FONT SIZE=2>+        for ( lid = db_min_lid ; lid <= db_max_lid ; lid++ )</FONT>
<BR><FONT SIZE=2>+          cl_ptr_vector_set(p_persistent_vec, lid, NULL);</FONT>
<BR><FONT SIZE=2>+      }</FONT>
<BR><FONT SIZE=2>+    }</FONT>
<BR><FONT SIZE=2>   }</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>   /* </FONT>
<BR><FONT SIZE=2>@@ -434,7 +469,7 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2>   {</FONT>
<BR><FONT SIZE=2>     is_free = TRUE;</FONT>
<BR><FONT SIZE=2>     /* first check to see if the lid is used by a persistent assignment */</FONT>
<BR><FONT SIZE=2>-    if ((lid < max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid))</FONT>
<BR><FONT SIZE=2>+    if ((lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid))</FONT>
<BR><FONT SIZE=2>     {</FONT>
<BR><FONT SIZE=2>       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,</FONT>
<BR><FONT SIZE=2>                "__osm_lid_mgr_init_sweep: "</FONT>
<BR><FONT SIZE=2>@@ -442,62 +477,86 @@ __osm_lid_mgr_init_sweep(</FONT>
<BR><FONT SIZE=2>                lid);</FONT>
<BR><FONT SIZE=2>       is_free = FALSE;</FONT>
<BR><FONT SIZE=2>     }</FONT>
<BR><FONT SIZE=2>-</FONT>
<BR><FONT SIZE=2>-    /* check the discovered port if there is one */</FONT>
<BR><FONT SIZE=2>-    if ((lid < max_discovered_lid) &&</FONT>
<BR><FONT SIZE=2>-        (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))</FONT>
<BR><FONT SIZE=2>+    else</FONT>
<BR><FONT SIZE=2>     {</FONT>
<BR><FONT SIZE=2>-      /* get the lid range of that port  - but we know how many lids we </FONT>
<BR><FONT SIZE=2>-         are about to assign to it */</FONT>
<BR><FONT SIZE=2>-      osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);</FONT>
<BR><FONT SIZE=2>-      if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=</FONT>
<BR><FONT SIZE=2>-           IB_NODE_TYPE_SWITCH)</FONT>
<BR><FONT SIZE=2>-        disc_max_lid = disc_min_lid + lmc_num_lids - 1;</FONT>
<BR><FONT SIZE=2>-</FONT>
<BR><FONT SIZE=2>+      /* check this is a discovered port */</FONT>
<BR><FONT SIZE=2>+      CL_ASSERT(lid <= max_discovered_lid);</FONT>
<BR><FONT SIZE=2>+      if ((p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))</FONT>
<BR><FONT SIZE=2>+      {</FONT>
<BR><FONT SIZE=2>+        /* we have a port. Now lets see if we can preserve its lid range. */</FONT>
<BR><FONT SIZE=2>+        /* For that - we need to make sure:</FONT>
<BR><FONT SIZE=2>+           1. The port has a (legal) persistancy entry. Then the local lid</FONT>
<BR><FONT SIZE=2>+              is free (we will use the persistancy value).</FONT>
<BR><FONT SIZE=2>+           2. Can the port keep its local assignment?</FONT>
<BR><FONT SIZE=2>+              a. Make sure the lid a alligned.</FONT>
<BR><FONT SIZE=2>+              b. Make sure all needed lids (for the lmc) are free according</FONT>
<BR><FONT SIZE=2>+                 to persistancy table.</FONT>
<BR><FONT SIZE=2>+        */</FONT>
<BR><FONT SIZE=2>       /* qualify the guid of the port is not persistently mapped to </FONT>
<BR><FONT SIZE=2>          another range */</FONT>
<BR><FONT SIZE=2>       if (!osm_db_guid2lid_get( p_mgr->p_g2l,</FONT>
<BR><FONT SIZE=2>                                 cl_ntoh64(osm_port_get_guid(p_port)),</FONT>
<BR><FONT SIZE=2>                                 &db_min_lid, &db_max_lid))</FONT>
<BR><FONT SIZE=2>       {</FONT>
<BR><FONT SIZE=2>-        /* ok there is an asignment - is it the same ? */</FONT>
<BR><FONT SIZE=2>-        if ((disc_min_lid == db_min_lid) && (disc_max_lid == db_max_lid))</FONT>
<BR><FONT SIZE=2>-        {</FONT>
<BR><FONT SIZE=2>           osm_log( p_mgr->p_log, OSM_LOG_DEBUG,</FONT>
<BR><FONT SIZE=2>                    "__osm_lid_mgr_init_sweep: "</FONT>
<BR><FONT SIZE=2>-                   "[0x%04x,0x%04x] is not free as it was discovered "</FONT>
<BR><FONT SIZE=2>-                   " and mapped by the persistent db.\n",</FONT>
<BR><FONT SIZE=2>-                   disc_min_lid, disc_max_lid);</FONT>
<BR><FONT SIZE=2>-          is_free = FALSE;</FONT>
<BR><FONT SIZE=2>+                   "0x%04x is free as it was discovered "</FONT>
<BR><FONT SIZE=2>+                   "but mapped by the persistent db to [0x%04x:0x%04x].\n",</FONT>
<BR><FONT SIZE=2>+                   lid, db_min_lid, db_max_lid);</FONT>
<BR><FONT SIZE=2>+        }</FONT>
<BR><FONT SIZE=2>+        else</FONT>
<BR><FONT SIZE=2>+        {</FONT>
<BR><FONT SIZE=2>+          /* can the port keep its assignment ? */</FONT>
<BR><FONT SIZE=2>+          /* get the lid range of that port, and the required number</FONT>
<BR><FONT SIZE=2>+             of lids we are about to assign to it */</FONT>
<BR><FONT SIZE=2>+          osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);</FONT>
<BR><FONT SIZE=2>+          if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=</FONT>
<BR><FONT SIZE=2>+               IB_NODE_TYPE_SWITCH)</FONT>
<BR><FONT SIZE=2>+          {</FONT>
<BR><FONT SIZE=2>+            disc_max_lid = disc_min_lid + lmc_num_lids - 1;</FONT>
<BR><FONT SIZE=2>+            num_lids = lmc_num_lids;</FONT>
<BR><FONT SIZE=2>         }</FONT>
<BR><FONT SIZE=2>         else</FONT>
<BR><FONT SIZE=2>         {</FONT>
<BR><FONT SIZE=2>+            num_lids = 1;</FONT>
<BR><FONT SIZE=2>+          }</FONT>
<BR><FONT SIZE=2>+          /* Make sure the lid is alligned */</FONT>
<BR><FONT SIZE=2>+          if ((num_lids != 1) && ((disc_min_lid & lmc_mask) != disc_min_lid))</FONT>
<BR><FONT SIZE=2>+          {</FONT>
<BR><FONT SIZE=2>+            /* The lid cannot be used */</FONT>
<BR><FONT SIZE=2>           osm_log( p_mgr->p_log, OSM_LOG_DEBUG,</FONT>
<BR><FONT SIZE=2>                    "__osm_lid_mgr_init_sweep: "</FONT>
<BR><FONT SIZE=2>-                   "[0x%04x,0x%04x] is free as it was discovered"</FONT>
<BR><FONT SIZE=2>-                   " but mapped to range: [0x%x:0x%x] by the persistent db.\n",</FONT>
<BR><FONT SIZE=2>-                   disc_min_lid, disc_max_lid, db_min_lid, db_max_lid);</FONT>
<BR><FONT SIZE=2>-          for (l = disc_min_lid; l <= disc_max_lid; l++)</FONT>
<BR><FONT SIZE=2>-            cl_ptr_vector_set(p_discovered_vec, l, NULL);</FONT>
<BR><FONT SIZE=2>-        }</FONT>
<BR><FONT SIZE=2>+                     "0x%04x is free as it was discovered "</FONT>
<BR><FONT SIZE=2>+                     "but not alligned. \n",</FONT>
<BR><FONT SIZE=2>+                     lid );</FONT>
<BR><FONT SIZE=2>       }</FONT>
<BR><FONT SIZE=2>       else</FONT>
<BR><FONT SIZE=2>       {</FONT>
<BR><FONT SIZE=2>+            /* check that all needed lids are not persistantly mapped */</FONT>
<BR><FONT SIZE=2>+            is_free = FALSE;</FONT>
<BR><FONT SIZE=2>+            for ( req_lid = disc_min_lid + 1 ; req_lid <= disc_max_lid ; req_lid++ )</FONT>
<BR><FONT SIZE=2>+            {</FONT>
<BR><FONT SIZE=2>+              if ((req_lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, req_lid))</FONT>
<BR><FONT SIZE=2>+              {</FONT>
<BR><FONT SIZE=2>         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,</FONT>
<BR><FONT SIZE=2>                  "__osm_lid_mgr_init_sweep: "</FONT>
<BR><FONT SIZE=2>-                 "0x%04x is not free as it was discovered"</FONT>
<BR><FONT SIZE=2>-                 " and there is no persistent db entry for it.\n",</FONT>
<BR><FONT SIZE=2>+                         "0x%04x is free as it was discovered "</FONT>
<BR><FONT SIZE=2>+                         "but mapped. \n",</FONT>
<BR><FONT SIZE=2>                  lid);</FONT>
<BR><FONT SIZE=2>-        is_free = FALSE;</FONT>
<BR><FONT SIZE=2>+                is_free = TRUE;</FONT>
<BR><FONT SIZE=2>+                break;</FONT>
<BR><FONT SIZE=2>+              }</FONT>
<BR><FONT SIZE=2>       }</FONT>
<BR><FONT SIZE=2>-</FONT>
<BR><FONT SIZE=2>-      /* if there is more then one lid on that port - and the discovered port</FONT>
<BR><FONT SIZE=2>-         is going to retain its lids advance to the max lid */</FONT>
<BR><FONT SIZE=2>       if (is_free == FALSE)</FONT>
<BR><FONT SIZE=2>       {</FONT>
<BR><FONT SIZE=2>+              /* This port will use its local lid, and consume the entire required lid range.</FONT>
<BR><FONT SIZE=2>+                 Thus we can skip that range. */</FONT>
<BR><FONT SIZE=2>         lid = disc_max_lid;</FONT>
<BR><FONT SIZE=2>       }</FONT>
<BR><FONT SIZE=2>     }</FONT>
<BR><FONT SIZE=2>+        }</FONT>
<BR><FONT SIZE=2>+      }</FONT>
<BR><FONT SIZE=2>+    }</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>     if (is_free)</FONT>
<BR><FONT SIZE=2>     {</FONT>
<BR><FONT SIZE=2>@@ -1300,7 +1359,6 @@ osm_lid_mgr_process_subnet(</FONT>
<BR><FONT SIZE=2>       /* the proc returns the fact it sent a set port info */</FONT>
<BR><FONT SIZE=2>       if (__osm_lid_mgr_set_physp_pi( p_mgr, p_physp, cl_hton16( min_lid_ho )))</FONT>
<BR><FONT SIZE=2>         p_mgr->send_set_reqs = TRUE;</FONT>
<BR><FONT SIZE=2>-        </FONT>
<BR><FONT SIZE=2>     }</FONT>
<BR><FONT SIZE=2>   } /* all ports */</FONT>
<BR><FONT SIZE=2> </FONT>
</P>

</BODY>
</HTML>