2 * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * Implementation of osm_prtn_t.
37 * This object represents an IBA partition.
38 * This object is part of the opensm family of objects.
43 #endif /* HAVE_CONFIG_H */
49 #include <complib/cl_debug.h>
50 #include <iba/ib_types.h>
51 #include <opensm/osm_opensm.h>
52 #include <opensm/osm_partition.h>
53 #include <opensm/osm_node.h>
54 #include <opensm/osm_sa.h>
55 #include <opensm/osm_multicast.h>
57 extern int osm_prtn_config_parse_file(osm_log_t * const p_log,
58 osm_subn_t * const p_subn,
59 const char *file_name);
61 static uint16_t global_pkey_counter;
63 osm_prtn_t *osm_prtn_new(IN const char *name, IN const uint16_t pkey)
65 osm_prtn_t *p = malloc(sizeof(*p));
69 memset(p, 0, sizeof(*p));
71 p->sl = OSM_DEFAULT_SL;
72 cl_map_construct(&p->full_guid_tbl);
73 cl_map_init(&p->full_guid_tbl, 32);
74 cl_map_construct(&p->part_guid_tbl);
75 cl_map_init(&p->part_guid_tbl, 32);
78 strncpy(p->name, name, sizeof(p->name));
80 snprintf(p->name, sizeof(p->name), "%04x", cl_ntoh16(pkey));
85 void osm_prtn_delete(IN OUT osm_prtn_t ** const pp_prtn)
87 osm_prtn_t *p = *pp_prtn;
89 cl_map_remove_all(&p->full_guid_tbl);
90 cl_map_destroy(&p->full_guid_tbl);
91 cl_map_remove_all(&p->part_guid_tbl);
92 cl_map_destroy(&p->part_guid_tbl);
97 ib_api_status_t osm_prtn_add_port(osm_log_t * p_log, osm_subn_t * p_subn,
98 osm_prtn_t * p, ib_net64_t guid,
101 ib_api_status_t status = IB_SUCCESS;
104 osm_physp_t *p_physp;
106 p_port = osm_get_port_by_guid(p_subn, guid);
108 OSM_LOG(p_log, OSM_LOG_VERBOSE,
109 "port 0x%" PRIx64 " not found\n", cl_ntoh64(guid));
113 p_physp = p_port->p_physp;
115 OSM_LOG(p_log, OSM_LOG_VERBOSE,
116 "no physical for port 0x%" PRIx64 "\n",
121 if (cl_map_remove(&p->part_guid_tbl, guid) ||
122 cl_map_remove(&p->full_guid_tbl, guid)) {
123 OSM_LOG(p_log, OSM_LOG_VERBOSE,
124 "port 0x%" PRIx64 " already in "
125 "partition \'%s\' (0x%04x). Will overwrite\n",
126 cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey));
129 p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl;
131 if (cl_map_insert(p_tbl, guid, p_physp) == NULL)
132 return IB_INSUFFICIENT_MEMORY;
137 ib_api_status_t osm_prtn_add_all(osm_log_t * p_log, osm_subn_t * p_subn,
138 osm_prtn_t * p, boolean_t full)
140 cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
141 cl_map_item_t *p_item;
143 ib_api_status_t status = IB_SUCCESS;
145 p_item = cl_qmap_head(p_port_tbl);
146 while (p_item != cl_qmap_end(p_port_tbl)) {
147 p_port = (osm_port_t *) p_item;
148 p_item = cl_qmap_next(p_item);
149 status = osm_prtn_add_port(p_log, p_subn, p,
150 osm_port_get_guid(p_port), full);
151 if (status != IB_SUCCESS)
159 static const ib_gid_t osm_ipoib_mgid = {
161 0xff, /* multicast field */
162 0x12, /* non-permanent bit, link local scope */
163 0x40, 0x1b, /* IPv4 signature */
164 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
166 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */
171 * HACK: Until TS resolves their noncompliant join compmask,
172 * we have to pre-define the MGID
174 static const ib_gid_t osm_ts_ipoib_mgid = {
176 0xff, /* multicast field */
177 0x12, /* non-permanent bit, link local scope */
178 0x40, 0x1b, /* IPv4 signature */
179 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
181 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */
185 ib_api_status_t osm_prtn_add_mcgroup(osm_log_t * p_log,
186 osm_subn_t * p_subn, osm_prtn_t * p,
188 uint8_t mtu, uint8_t scope)
190 ib_member_rec_t mc_rec;
191 ib_net64_t comp_mask;
193 osm_mgrp_t *p_mgrp = NULL;
194 osm_sa_t *p_sa = &p_subn->p_osm->sa;
195 ib_api_status_t status = IB_SUCCESS;
198 pkey = p->pkey | cl_hton16(0x8000);
200 scope = OSM_DEFAULT_MGRP_SCOPE;
201 hop_limit = (scope == IB_MC_SCOPE_LINK_LOCAL) ? 0 : IB_HOPLIMIT_MAX;
203 memset(&mc_rec, 0, sizeof(mc_rec));
205 mc_rec.mgid = osm_ipoib_mgid; /* ipv4 broadcast group */
206 memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
208 mc_rec.qkey = CL_HTON32(0x0b1b);
209 mc_rec.mtu = (mtu ? mtu : OSM_DEFAULT_MGRP_MTU) | (2 << 6); /* 2048 Bytes */
212 mc_rec.rate = (rate ? rate : OSM_DEFAULT_MGRP_RATE) | (2 << 6); /* 10Gb/sec */
213 mc_rec.pkt_life = p_subn->opt.subnet_timeout;
214 mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p->sl, 0, hop_limit);
215 /* Scope in MCMemberRecord (if present) needs to be consistent with MGID */
216 mc_rec.scope_state = ib_member_set_scope_state(scope, IB_MC_REC_STATE_FULL_MEMBER);
217 ib_mgid_set_scope(&mc_rec.mgid, scope);
219 /* don't update rate, mtu */
220 comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL |
221 IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
222 status = osm_mcmr_rcv_find_or_create_new_mgrp(p_sa, comp_mask, &mc_rec,
224 if (!p_mgrp || status != IB_SUCCESS)
225 OSM_LOG(p_log, OSM_LOG_ERROR,
226 "Failed to create MC group with pkey 0x%04x\n",
229 p_mgrp->well_known = TRUE;
230 p->mlid = p_mgrp->mlid;
233 /* workaround for TS */
234 /* FIXME: remove this upon TS fixes */
235 mc_rec.mgid = osm_ts_ipoib_mgid;
236 memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
237 /* Scope in MCMemberRecord (if present) needs to be consistent with MGID */
238 mc_rec.scope_state = ib_member_set_scope_state(scope, IB_MC_REC_STATE_FULL_MEMBER);
239 ib_mgid_set_scope(&mc_rec.mgid, scope);
241 status = osm_mcmr_rcv_find_or_create_new_mgrp(p_sa, comp_mask, &mc_rec,
244 p_mgrp->well_known = TRUE;
246 p->mlid = p_mgrp->mlid;
252 static uint16_t __generate_pkey(osm_subn_t * p_subn)
256 cl_qmap_t *m = &p_subn->prtn_pkey_tbl;
257 while (global_pkey_counter < cl_ntoh16(IB_DEFAULT_PARTIAL_PKEY) - 1) {
258 pkey = ++global_pkey_counter;
259 pkey = cl_hton16(pkey);
260 if (cl_qmap_get(m, pkey) == cl_qmap_end(m))
266 osm_prtn_t *osm_prtn_find_by_name(osm_subn_t * p_subn, const char *name)
268 cl_map_item_t *p_next;
271 p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
272 while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
273 p = (osm_prtn_t *) p_next;
274 p_next = cl_qmap_next(&p->map_item);
275 if (!strncmp(p->name, name, sizeof(p->name)))
282 osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn,
283 const char *name, uint16_t pkey)
285 osm_prtn_t *p = NULL, *p_check;
287 pkey &= cl_hton16((uint16_t) ~ 0x8000);
290 if (name && (p = osm_prtn_find_by_name(p_subn, name)))
292 if (!(pkey = __generate_pkey(p_subn)))
296 p = osm_prtn_new(name, pkey);
298 OSM_LOG(p_log, OSM_LOG_ERROR, "Unable to create"
299 " partition \'%s\' (0x%04x)\n", name, cl_ntoh16(pkey));
303 p_check = (osm_prtn_t *) cl_qmap_insert(&p_subn->prtn_pkey_tbl,
304 p->pkey, &p->map_item);
306 OSM_LOG(p_log, OSM_LOG_VERBOSE, "Duplicated partition"
307 " definition: \'%s\' (0x%04x) prev name \'%s\'"
309 name, cl_ntoh16(pkey), p_check->name);
317 static ib_api_status_t osm_prtn_make_default(osm_log_t * const p_log,
318 osm_subn_t * const p_subn,
321 ib_api_status_t status = IB_UNKNOWN_ERROR;
324 p = osm_prtn_make_new(p_log, p_subn, "Default",
325 IB_DEFAULT_PARTIAL_PKEY);
328 status = osm_prtn_add_all(p_log, p_subn, p, no_config);
329 if (status != IB_SUCCESS)
331 cl_map_remove(&p->part_guid_tbl, p_subn->sm_port_guid);
333 osm_prtn_add_port(p_log, p_subn, p, p_subn->sm_port_guid, TRUE);
336 osm_prtn_add_mcgroup(p_log, p_subn, p, 0, 0, 0);
342 ib_api_status_t osm_prtn_make_partitions(osm_log_t * const p_log,
343 osm_subn_t * const p_subn)
346 const char *file_name;
347 boolean_t is_config = TRUE;
348 ib_api_status_t status = IB_SUCCESS;
349 cl_map_item_t *p_next;
352 file_name = p_subn->opt.partition_config_file ?
353 p_subn->opt.partition_config_file : OSM_DEFAULT_PARTITION_CONFIG_FILE;
354 if (stat(file_name, &statbuf))
357 /* clean up current port maps */
358 p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
359 while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
360 p = (osm_prtn_t *) p_next;
361 p_next = cl_qmap_next(&p->map_item);
362 cl_map_remove_all(&p->part_guid_tbl);
363 cl_map_remove_all(&p->full_guid_tbl);
366 global_pkey_counter = 0;
368 status = osm_prtn_make_default(p_log, p_subn, !is_config);
369 if (status != IB_SUCCESS)
372 if (is_config && osm_prtn_config_parse_file(p_log, p_subn, file_name)) {
373 OSM_LOG(p_log, OSM_LOG_VERBOSE, "Partition configuration "
374 "was not fully processed\n");
377 /* and now clean up empty partitions */
378 p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
379 while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
380 p = (osm_prtn_t *) p_next;
381 p_next = cl_qmap_next(&p->map_item);
382 if (cl_map_count(&p->part_guid_tbl) == 0 &&
383 cl_map_count(&p->full_guid_tbl) == 0) {
384 cl_qmap_remove_item(&p_subn->prtn_pkey_tbl,
385 (cl_map_item_t *) p);