[OpenSM] - This change fixes the retrieval of the MCMember records according to
authoreitan <eitan@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 4 Apr 2006 08:55:14 +0000 (08:55 +0000)
committereitan <eitan@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 4 Apr 2006 08:55:14 +0000 (08:55 +0000)
Errata MGTWG3280.

Quoting from MGTWG3280:

SA can be queried for multicast groups by sending a SubnAdmGet() or a
SubnAdmGetTable() request to it using the SA query mechanism (see
15.4.4 Administration Query Subsystem on page 923).

What SA returns in response to a query of multicast groups depends
strongly on whether the request is or is not a trusted request; the
degree of trust affects both the data returned in each attribute and
the set of attributes that are returned. See <ref to C15-0.2.2>.

o15-0.2.5 is made obsolete.

So we need to implement the following descriptive text:
SA can be queried for multicast groups by sending a SubnAdmGet() or a
SubnAdmGetTable() request to it using the SA query mechanism (see
15.4.4 Administration Query Subsystem on page 923). SA will return one
MCMemberRecord per multicast group matching the query, except in
cases where trust is specified as indicated in 15.4.1.2 Access Restrictions
For Other Attributes on page 922; in that case all the MCMemberRecords
associated with the multicast group are returned. The MCMemberRecord
will be returned with the PortGID, ProxyJoin, and the JoinState components
set to 0, except where trust is specified as indicated above, in that
case the actual contents for the above components will be provided.

Signed-off-by: Ofer Gigi <oferg@mellanox.co.il>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@280 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/opensm/user/opensm/osm_sa_mcmember_record.c

index c079e06..7456999 100644 (file)
@@ -88,6 +88,7 @@ typedef  struct   osm_sa_mcmr_search_ctxt {
   cl_qlist_t      *p_list; /*  hold results */
   ib_net64_t      comp_mask;
   const osm_physp_t*    p_req_physp;
+  boolean_t       trusted_req;
 } osm_sa_mcmr_search_ctxt_t;
 
 /**********************************************************************
@@ -1213,6 +1214,24 @@ __mgrp_request_is_realizable(
   return TRUE;
 }
   
+/**********************************************************************
+ Call this function to find or create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net64_t comp_mask,
+  IN ib_member_rec_t* const p_recvd_mcmember_rec,
+  OUT osm_mgrp_t **pp_mgrp)
+{
+  ib_api_status_t status;
+  status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, pp_mgrp);
+  if (status == IB_SUCCESS)
+     return status;
+  return osm_mcmr_rcv_create_new_mgrp(p_rcv, comp_mask,
+                 p_recvd_mcmember_rec, NULL, pp_mgrp);
+}
+
 /**********************************************************************
  Call this function to create a new mgrp.
 **********************************************************************/
@@ -1897,6 +1916,9 @@ __osm_sa_mcm_by_comp_mask_cb(
   /* will be used for group or port info */
   uint8_t scope_state; 
   uint8_t scope_state_mask = 0;
+  cl_map_item_t *p_item;
+  ib_gid_t     port_gid;
+  boolean_t proxy_join;
 
   OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_mcm_by_comp_mask_cb );
 
@@ -1917,51 +1939,33 @@ __osm_sa_mcm_by_comp_mask_cb(
 
   /* first try to eliminate the group by MGID, MLID, or P_Key */
   if ((IB_MCR_COMPMASK_MGID & comp_mask) &&
-      cl_memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t))) {
+      cl_memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t)))
     goto Exit;
-  }
 
   if ((IB_MCR_COMPMASK_MLID & comp_mask) &&
-      cl_memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t))) {
-    goto Exit;
-  }
-
-  /* if the requester physical port doesn't have the pkey that is defined for the
-     group - exit. */
-  if (! osm_physp_has_pkey( p_rcv->p_log, p_mgrp->mcmember_rec.pkey, p_req_physp ))
+      cl_memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t)))
     goto Exit;
 
-  /* so did we get the PortGUID mask */
-  if (IB_MCR_COMPMASK_PORT_GID & comp_mask)
-  {
-    /* try to find this port */
-    if (osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port))
-    {
-      scope_state = p_mcm_port->scope_state;
-    }
-    else
-    {
-      /* port not in group */
+  /* if the requester physical port doesn't have the pkey that is defined for
+     the group - exit. */
+  if (! osm_physp_has_pkey( p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+                            p_req_physp ))
       goto Exit;
-    }
-  }
-  else
-  {
-    /* point to the group information */
-    scope_state = p_mgrp->mcmember_rec.scope_state;
-  }
 
   /* now do the rest of the match */
   if ((IB_MCR_COMPMASK_QKEY & comp_mask) &&
-      (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey)) goto Exit;
+      (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey))
+    goto Exit;
 
   if ((IB_MCR_COMPMASK_PKEY & comp_mask) &&
-      (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey)) goto Exit;
+      (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey))
+    goto Exit;
 
   if ((IB_MCR_COMPMASK_TCLASS & comp_mask) &&
-      (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass)) goto Exit;
+      (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass))
+    goto Exit;
  
-  /* check SL , Flow and Hop limit */
+  /* check SL, Flow, and Hop limit */
   {
     uint8_t mgrp_sl, query_sl;
     uint32_t mgrp_flow, query_flow;
@@ -1974,38 +1978,111 @@ __osm_sa_mcm_by_comp_mask_cb(
                               &mgrp_sl, &mgrp_flow, &mgrp_hop);
 
     if (IB_MCR_COMPMASK_SL & comp_mask )
-      if (query_sl != mgrp_sl) goto Exit;
+      if (query_sl != mgrp_sl)
+        goto Exit;
 
     if (IB_MCR_COMPMASK_FLOW & comp_mask)
-      if (query_flow != mgrp_flow) goto Exit;
+      if (query_flow != mgrp_flow)
+        goto Exit;
 
     if (IB_MCR_COMPMASK_HOP & comp_mask)
-      if (query_hop != mgrp_hop) goto Exit;
+      if (query_hop != mgrp_hop)
+        goto Exit;
   }
 
+  if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
+      (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join))
+    goto Exit;
+
   if (IB_MCR_COMPMASK_SCOPE & comp_mask)
     scope_state_mask = 0xF0;
 
   if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask)
     scope_state_mask = scope_state_mask | 0x0F;
 
-  if ((scope_state_mask & p_rcvd_rec->scope_state) !=
-      (scope_state_mask & scope_state)) goto Exit;
-
-  if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
-      (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join)) goto Exit;
-
   /* need to validate mtu, rate, and pkt_lifetime fields. */
   if (__validate_more_comp_fields( p_rcv->p_log,
                                    p_mgrp,
                                    p_rcvd_rec,
-                                   comp_mask ) == FALSE) goto Exit;
+                                   comp_mask ) == FALSE)
+    goto Exit;
+
+  /* Port specific fields */
+  /* so did we get the PortGUID mask */
+  if (IB_MCR_COMPMASK_PORT_GID & comp_mask)
+  {
+     /* try to find this port */
+     if (osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port))
+     {
+       scope_state = p_mcm_port->scope_state;
+       cl_memcpy(&port_gid, &(p_mcm_port->port_gid), sizeof(ib_gid_t));
+       proxy_join = p_mcm_port->proxy_join;
+     }
+     else
+     {
+       /* port not in group */
+       goto Exit;
+     }
+  }
+  else
+  {
+     /* point to the group information */
+     scope_state = p_mgrp->mcmember_rec.scope_state;
+  }
+
+  /* Many MC records returned */
+  if ( (p_ctxt->trusted_req == TRUE) && !(IB_MCR_COMPMASK_PORT_GID & comp_mask) )
+  {
+     osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_mcm_by_comp_mask_cb: "
+             "trusted req is TRUE and no specific port defined\n");
+
+     /* return all the ports that match in this MC group */
+     p_item = cl_qmap_head(&(p_mgrp->mcm_port_tbl));
+     while( p_item != cl_qmap_end(&(p_mgrp->mcm_port_tbl)) )
+     {
+        p_mcm_port=(osm_mcm_port_t *)p_item;
+
+        if ((scope_state_mask & p_rcvd_rec->scope_state) ==
+            (scope_state_mask & p_mcm_port->scope_state)) 
+       {
+           /* add to the list */
+           match_rec = p_mgrp->mcmember_rec;
+           match_rec.scope_state = p_mcm_port->scope_state;
+           cl_memcpy( &(match_rec.port_gid), &(p_mcm_port->port_gid),
+                      sizeof(ib_gid_t));
+           osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+                   "__osm_sa_mcm_by_comp_mask_cb: "
+                   "record of port_gid: 0x%016" PRIx64 "0x%016" PRIx64 
+                   " in multicast_lid: 0x%X is returned\n",
+                   cl_ntoh64(match_rec.port_gid.unicast.prefix),
+                   cl_ntoh64(match_rec.port_gid.unicast.interface_id),
+                   cl_ntoh16(p_mgrp->mlid)
+                   );
+
+           match_rec.proxy_join = (uint8_t)(p_mcm_port->proxy_join);
+
+           __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+         }
+         p_item = cl_qmap_next(p_item);
+      }
+  }
+  /* One MC record returned */
+  else
+  {
+    if ((scope_state_mask & p_rcvd_rec->scope_state) !=
+        (scope_state_mask & scope_state))
+      goto Exit;
 
   /* add to the list */
   match_rec = p_mgrp->mcmember_rec;
   match_rec.scope_state = scope_state;
+    cl_memcpy(&(match_rec.port_gid), &port_gid, sizeof(ib_gid_t));
+    match_rec.proxy_join = (uint8_t)proxy_join;
 
   __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+  }
+
  Exit:
   OSM_LOG_EXIT( p_rcv->p_log );
 }
@@ -2032,7 +2109,7 @@ osm_mcmr_query_mgrp(IN osm_mcmr_recv_t*  const p_rcv,
   ib_api_status_t       status;
   ib_net64_t               comp_mask;
   osm_physp_t*             p_req_physp;
-  boolean_t                trusted_req = TRUE;
+  boolean_t                trusted_req;
 
   CL_ASSERT( p_rcv );
 
@@ -2046,6 +2123,12 @@ osm_mcmr_query_mgrp(IN osm_mcmr_recv_t*  const p_rcv,
 
   CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD );
 
+  /*
+    if sm_key is not zero and does not match we never get here
+    see main SA receiver
+   */
+  trusted_req = (p_rcvd_mad->sm_key != 0);
+
   /* update the requester physical port. */
   p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
                                           p_rcv->p_subn,
@@ -2065,6 +2148,7 @@ osm_mcmr_query_mgrp(IN osm_mcmr_recv_t*  const p_rcv,
   context.comp_mask = p_rcvd_mad->comp_mask;
   context.p_rcv = p_rcv;
   context.p_req_physp = p_req_physp;
+  context.trusted_req = trusted_req;
 
   CL_PLOCK_ACQUIRE( p_rcv->p_lock );
 
@@ -2191,8 +2275,6 @@ osm_mcmr_query_mgrp(IN osm_mcmr_recv_t*  const p_rcv,
     the mad is valid. Meaning - is either zero or equal to the local
     sm_key.
   */
-  if (p_rcvd_mad->sm_key == 0)
-    trusted_req = FALSE;
 
   for ( i = 0; i < pre_trim_num_rec; i++ )
   {