2 * Copyright (c) 2004-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_sir_rcv_t.
39 * This object represents the SwitchInfo 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_debug.h>
50 #include <complib/cl_qlist.h>
51 #include <vendor/osm_vendor_api.h>
52 #include <opensm/osm_node.h>
53 #include <opensm/osm_helper.h>
54 #include <opensm/osm_pkey.h>
55 #include <opensm/osm_sa.h>
57 typedef struct osm_sir_item {
58 cl_list_item_t list_item;
59 ib_switch_info_record_t rec;
62 typedef struct osm_sir_search_ctxt {
63 const ib_switch_info_record_t *p_rcvd_rec;
67 const osm_physp_t *p_req_physp;
68 } osm_sir_search_ctxt_t;
70 /**********************************************************************
71 **********************************************************************/
72 static ib_api_status_t
73 __osm_sir_rcv_new_sir(IN osm_sa_t * sa,
74 IN const osm_switch_t * const p_sw,
75 IN cl_qlist_t * const p_list, IN ib_net16_t const lid)
77 osm_sir_item_t *p_rec_item;
78 ib_api_status_t status = IB_SUCCESS;
80 OSM_LOG_ENTER(sa->p_log);
82 p_rec_item = malloc(sizeof(*p_rec_item));
83 if (p_rec_item == NULL) {
84 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5308: "
85 "rec_item alloc failed\n");
86 status = IB_INSUFFICIENT_RESOURCES;
90 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
91 "New SwitchInfoRecord: lid %u\n", cl_ntoh16(lid));
93 memset(p_rec_item, 0, sizeof(*p_rec_item));
95 p_rec_item->rec.lid = lid;
96 p_rec_item->rec.switch_info = p_sw->switch_info;
98 cl_qlist_insert_tail(p_list, &p_rec_item->list_item);
101 OSM_LOG_EXIT(sa->p_log);
105 /**********************************************************************
106 **********************************************************************/
108 __osm_sir_rcv_create_sir(IN osm_sa_t * sa,
109 IN const osm_switch_t * const p_sw,
110 IN cl_qlist_t * const p_list,
111 IN ib_net16_t const match_lid,
112 IN const osm_physp_t * const p_req_physp)
115 const osm_physp_t *p_physp;
116 uint16_t match_lid_ho;
117 ib_net16_t min_lid_ho;
118 ib_net16_t max_lid_ho;
120 OSM_LOG_ENTER(sa->p_log);
122 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
123 "Looking for SwitchInfoRecord with LID: %u\n",
124 cl_ntoh16(match_lid));
126 /* In switches, the port guid is the node guid. */
128 osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid);
130 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530A: "
131 "Failed to find Port by Node Guid:0x%016" PRIx64
132 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid));
136 /* check that the requester physp and the current physp are under
137 the same partition. */
138 p_physp = p_port->p_physp;
140 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530B: "
141 "Failed to find default physical Port by Node Guid:0x%016"
143 cl_ntoh64(p_sw->p_node->node_info.node_guid));
146 if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp))
149 /* get the port 0 of the switch */
150 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
152 match_lid_ho = cl_ntoh16(match_lid);
155 We validate that the lid belongs to this switch.
157 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
158 "Comparing LID: %u <= %u <= %u\n",
159 min_lid_ho, match_lid_ho, max_lid_ho);
161 if (match_lid_ho < min_lid_ho || match_lid_ho > max_lid_ho)
166 __osm_sir_rcv_new_sir(sa, p_sw, p_list, osm_port_get_base_lid(p_port));
169 OSM_LOG_EXIT(sa->p_log);
172 /**********************************************************************
173 **********************************************************************/
175 __osm_sir_rcv_by_comp_mask(IN cl_map_item_t * const p_map_item,
178 const osm_sir_search_ctxt_t *const p_ctxt =
179 (osm_sir_search_ctxt_t *) context;
180 const osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
181 const ib_switch_info_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec;
182 const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp;
183 osm_sa_t *sa = p_ctxt->sa;
184 ib_net64_t const comp_mask = p_ctxt->comp_mask;
185 ib_net16_t match_lid = 0;
187 OSM_LOG_ENTER(p_ctxt->sa->p_log);
189 osm_dump_switch_info(p_ctxt->sa->p_log,
190 &p_sw->switch_info, OSM_LOG_VERBOSE);
192 if (comp_mask & IB_SWIR_COMPMASK_LID) {
193 match_lid = p_rcvd_rec->lid;
198 __osm_sir_rcv_create_sir(sa, p_sw, p_ctxt->p_list,
199 match_lid, p_req_physp);
202 OSM_LOG_EXIT(p_ctxt->sa->p_log);
205 /**********************************************************************
206 **********************************************************************/
207 void osm_sir_rcv_process(IN void *ctx, IN void *data)
210 osm_madw_t *p_madw = data;
211 const ib_sa_mad_t *sad_mad;
212 const ib_switch_info_record_t *p_rcvd_rec;
214 osm_sir_search_ctxt_t context;
215 osm_physp_t *p_req_physp;
219 OSM_LOG_ENTER(sa->p_log);
223 sad_mad = osm_madw_get_sa_mad_ptr(p_madw);
225 (ib_switch_info_record_t *) ib_sa_mad_get_payload_ptr(sad_mad);
227 CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_RECORD);
229 /* we only support SubnAdmGet and SubnAdmGetTable methods */
230 if (sad_mad->method != IB_MAD_METHOD_GET &&
231 sad_mad->method != IB_MAD_METHOD_GETTABLE) {
232 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5305: "
233 "Unsupported Method (%s)\n",
234 ib_get_sa_method_str(sad_mad->method));
235 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
239 /* update the requester physical port. */
240 p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
241 osm_madw_get_mad_addr_ptr
243 if (p_req_physp == NULL) {
244 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5304: "
245 "Cannot find requester physical port\n");
249 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
250 osm_dump_switch_info_record(sa->p_log, p_rcvd_rec,
253 cl_qlist_init(&rec_list);
255 context.p_rcvd_rec = p_rcvd_rec;
256 context.p_list = &rec_list;
257 context.comp_mask = sad_mad->comp_mask;
259 context.p_req_physp = p_req_physp;
261 cl_plock_acquire(sa->p_lock);
263 /* Go over all switches */
264 cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl,
265 __osm_sir_rcv_by_comp_mask, &context);
267 cl_plock_release(sa->p_lock);
269 osm_sa_respond(sa, p_madw, sizeof(ib_switch_info_record_t), &rec_list);
272 OSM_LOG_EXIT(sa->p_log);