2 * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_gir_rcv_t.
39 * This object represents the GUIDInfoRecord Receiver object.
40 * This object is part of the opensm family of objects.
45 #endif /* HAVE_CONFIG_H */
48 #include <iba/ib_types.h>
49 #include <complib/cl_qmap.h>
50 #include <complib/cl_passivelock.h>
51 #include <complib/cl_debug.h>
52 #include <complib/cl_qlist.h>
53 #include <vendor/osm_vendor_api.h>
54 #include <opensm/osm_port.h>
55 #include <opensm/osm_node.h>
56 #include <opensm/osm_helper.h>
57 #include <opensm/osm_pkey.h>
58 #include <opensm/osm_sa.h>
60 typedef struct osm_gir_item {
61 cl_list_item_t list_item;
62 ib_guidinfo_record_t rec;
65 typedef struct osm_gir_search_ctxt {
66 const ib_guidinfo_record_t *p_rcvd_rec;
70 const osm_physp_t *p_req_physp;
71 } osm_gir_search_ctxt_t;
73 /**********************************************************************
74 **********************************************************************/
75 static ib_api_status_t
76 __osm_gir_rcv_new_gir(IN osm_sa_t * sa,
77 IN const osm_node_t * const p_node,
78 IN cl_qlist_t * const p_list,
79 IN ib_net64_t const match_port_guid,
80 IN ib_net16_t const match_lid,
81 IN const osm_physp_t * const p_req_physp,
82 IN uint8_t const block_num)
84 osm_gir_item_t *p_rec_item;
85 ib_api_status_t status = IB_SUCCESS;
87 OSM_LOG_ENTER(sa->p_log);
89 p_rec_item = malloc(sizeof(*p_rec_item));
90 if (p_rec_item == NULL) {
91 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5102: "
92 "rec_item alloc failed\n");
93 status = IB_INSUFFICIENT_RESOURCES;
97 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
98 "New GUIDInfoRecord: lid %u, block num %d\n",
99 cl_ntoh16(match_lid), block_num);
101 memset(p_rec_item, 0, sizeof(*p_rec_item));
103 p_rec_item->rec.lid = match_lid;
104 p_rec_item->rec.block_num = block_num;
106 p_rec_item->rec.guid_info.guid[0] =
107 osm_physp_get_port_guid(p_req_physp);
109 cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
112 OSM_LOG_EXIT(sa->p_log);
116 /**********************************************************************
117 **********************************************************************/
119 __osm_sa_gir_create_gir(IN osm_sa_t * sa,
120 IN osm_node_t * const p_node,
121 IN cl_qlist_t * const p_list,
122 IN ib_net64_t const match_port_guid,
123 IN ib_net16_t const match_lid,
124 IN const osm_physp_t * const p_req_physp,
125 IN uint8_t const match_block_num)
127 const osm_physp_t *p_physp;
130 uint16_t match_lid_ho;
131 ib_net16_t base_lid_ho;
132 ib_net16_t max_lid_ho;
134 ib_net64_t port_guid;
135 uint8_t block_num, start_block_num, end_block_num, num_blocks;
137 OSM_LOG_ENTER(sa->p_log);
139 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
140 "Looking for GUIDRecord with LID: %u GUID:0x%016"
141 PRIx64 "\n", cl_ntoh16(match_lid), cl_ntoh64(match_port_guid));
144 For switches, do not return the GUIDInfo record(s)
145 for each port on the switch, just for port 0.
147 if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
150 num_ports = osm_node_get_num_physp(p_node);
152 for (port_num = 0; port_num < num_ports; port_num++) {
153 p_physp = osm_node_get_physp_ptr(p_node, port_num);
157 /* Check to see if the found p_physp and the requester physp
158 share a pkey. If not, continue */
159 if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp))
162 port_guid = osm_physp_get_port_guid(p_physp);
164 if (match_port_guid && (port_guid != match_port_guid))
168 Note: the following check is a temporary workaround
169 Since 1. GUIDCap should never be 0 on ports where this applies
170 and 2. GUIDCap should not be used on ports where it doesn't apply
171 So this should really be a check for whether the port is a
172 switch external port or not!
174 if (p_physp->port_info.guid_cap == 0)
177 num_blocks = p_physp->port_info.guid_cap / 8;
178 if (p_physp->port_info.guid_cap % 8)
180 if (match_block_num == 255) {
182 end_block_num = num_blocks - 1;
184 if (match_block_num >= num_blocks)
186 end_block_num = start_block_num = match_block_num;
189 base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp));
190 match_lid_ho = cl_ntoh16(match_lid);
192 lmc = osm_physp_get_lmc(p_physp);
193 max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1);
196 We validate that the lid belongs to this node.
198 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
199 "Comparing LID: %u <= %u <= %u\n",
200 base_lid_ho, match_lid_ho, max_lid_ho);
202 if (match_lid_ho < base_lid_ho
203 || match_lid_ho > max_lid_ho)
207 for (block_num = start_block_num; block_num <= end_block_num;
209 __osm_gir_rcv_new_gir(sa, p_node, p_list, port_guid,
210 cl_ntoh16(base_lid_ho), p_physp,
215 OSM_LOG_EXIT(sa->p_log);
218 /**********************************************************************
219 **********************************************************************/
221 __osm_sa_gir_by_comp_mask_cb(IN cl_map_item_t * const p_map_item,
224 const osm_gir_search_ctxt_t *const p_ctxt =
225 (osm_gir_search_ctxt_t *) context;
226 osm_node_t *const p_node = (osm_node_t *) p_map_item;
227 const ib_guidinfo_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec;
228 const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
229 osm_sa_t *sa = p_ctxt->sa;
230 const ib_guid_info_t *p_comp_gi;
231 ib_net64_t const comp_mask = p_ctxt->comp_mask;
232 ib_net64_t match_port_guid = 0;
233 ib_net16_t match_lid = 0;
234 uint8_t match_block_num = 255;
236 OSM_LOG_ENTER(p_ctxt->sa->p_log);
238 if (comp_mask & IB_GIR_COMPMASK_LID)
239 match_lid = p_rcvd_rec->lid;
241 if (comp_mask & IB_GIR_COMPMASK_BLOCKNUM)
242 match_block_num = p_rcvd_rec->block_num;
244 p_comp_gi = &p_rcvd_rec->guid_info;
245 /* Different rule for block 0 v. other blocks */
246 if (comp_mask & IB_GIR_COMPMASK_GID0) {
247 if (!p_rcvd_rec->block_num)
248 match_port_guid = osm_physp_get_port_guid(p_req_physp);
249 if (p_comp_gi->guid[0] != match_port_guid)
253 if (comp_mask & IB_GIR_COMPMASK_GID1) {
254 if (p_comp_gi->guid[1] != 0)
258 if (comp_mask & IB_GIR_COMPMASK_GID2) {
259 if (p_comp_gi->guid[2] != 0)
263 if (comp_mask & IB_GIR_COMPMASK_GID3) {
264 if (p_comp_gi->guid[3] != 0)
268 if (comp_mask & IB_GIR_COMPMASK_GID4) {
269 if (p_comp_gi->guid[4] != 0)
273 if (comp_mask & IB_GIR_COMPMASK_GID5) {
274 if (p_comp_gi->guid[5] != 0)
278 if (comp_mask & IB_GIR_COMPMASK_GID6) {
279 if (p_comp_gi->guid[6] != 0)
283 if (comp_mask & IB_GIR_COMPMASK_GID7) {
284 if (p_comp_gi->guid[7] != 0)
288 __osm_sa_gir_create_gir(sa, p_node, p_ctxt->p_list,
289 match_port_guid, match_lid, p_req_physp,
293 OSM_LOG_EXIT(p_ctxt->sa->p_log);
296 /**********************************************************************
297 **********************************************************************/
298 void osm_gir_rcv_process(IN void *ctx, IN void *data)
301 osm_madw_t *p_madw = data;
302 const ib_sa_mad_t *p_rcvd_mad;
303 const ib_guidinfo_record_t *p_rcvd_rec;
305 osm_gir_search_ctxt_t context;
306 osm_physp_t *p_req_physp;
310 OSM_LOG_ENTER(sa->p_log);
314 p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
316 (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
318 CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_GUIDINFO_RECORD);
320 /* we only support SubnAdmGet and SubnAdmGetTable methods */
321 if (p_rcvd_mad->method != IB_MAD_METHOD_GET &&
322 p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) {
323 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5105: "
324 "Unsupported Method (%s)\n",
325 ib_get_sa_method_str(p_rcvd_mad->method));
326 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
330 /* update the requester physical port. */
331 p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
332 osm_madw_get_mad_addr_ptr
334 if (p_req_physp == NULL) {
335 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5104: "
336 "Cannot find requester physical port\n");
340 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
341 osm_dump_guidinfo_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG);
343 cl_qlist_init(&rec_list);
345 context.p_rcvd_rec = p_rcvd_rec;
346 context.p_list = &rec_list;
347 context.comp_mask = p_rcvd_mad->comp_mask;
349 context.p_req_physp = p_req_physp;
351 cl_plock_acquire(sa->p_lock);
353 cl_qmap_apply_func(&sa->p_subn->node_guid_tbl,
354 __osm_sa_gir_by_comp_mask_cb, &context);
356 cl_plock_release(sa->p_lock);
358 osm_sa_respond(sa, p_madw, sizeof(ib_guidinfo_record_t), &rec_list);
361 OSM_LOG_EXIT(sa->p_log);