]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_node.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / opensm / osm_node.c
1 /*
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.
5  *
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:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
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.
24  *
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
32  * SOFTWARE.
33  *
34  */
35
36 /*
37  * Abstract:
38  *    Implementation of osm_node_t.
39  * This object represents an Infiniband Node.
40  * This object is part of the opensm family of objects.
41  */
42
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif                          /* HAVE_CONFIG_H */
46
47 #include <stdlib.h>
48 #include <iba/ib_types.h>
49 #include <opensm/osm_node.h>
50 #include <opensm/osm_madw.h>
51
52 /**********************************************************************
53  **********************************************************************/
54 void
55 osm_node_init_physp(IN osm_node_t * const p_node,
56                     IN const osm_madw_t * const p_madw)
57 {
58         ib_net64_t port_guid;
59         ib_smp_t *p_smp;
60         ib_node_info_t *p_ni;
61         uint8_t port_num;
62
63         p_smp = osm_madw_get_smp_ptr(p_madw);
64
65         p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
66         port_guid = p_ni->port_guid;
67         port_num = ib_node_info_get_local_port_num(p_ni);
68
69         CL_ASSERT(port_num < p_node->physp_tbl_size);
70
71         osm_physp_init(&p_node->physp_table[port_num],
72                        port_guid, port_num, p_node,
73                        osm_madw_get_bind_handle(p_madw),
74                        p_smp->hop_count, p_smp->initial_path);
75 }
76
77 /**********************************************************************
78  **********************************************************************/
79 static void node_init_physp0(IN osm_node_t * const p_node,
80                              IN const osm_madw_t * const p_madw)
81 {
82         ib_smp_t *p_smp;
83         ib_node_info_t *p_ni;
84
85         p_smp = osm_madw_get_smp_ptr(p_madw);
86         p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
87
88         osm_physp_init(&p_node->physp_table[0],
89                        p_ni->port_guid, 0, p_node,
90                        osm_madw_get_bind_handle(p_madw),
91                        p_smp->hop_count, p_smp->initial_path);
92 }
93
94 /**********************************************************************
95  **********************************************************************/
96 osm_node_t *osm_node_new(IN const osm_madw_t * const p_madw)
97 {
98         osm_node_t *p_node;
99         ib_smp_t *p_smp;
100         ib_node_info_t *p_ni;
101         uint8_t i;
102         uint32_t size;
103
104         p_smp = osm_madw_get_smp_ptr(p_madw);
105         p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
106
107         /*
108            The node object already contains one physical port object.
109            Therefore, subtract 1 from the number of physical ports
110            used by the switch.  This is not done for CA's since they
111            need to occupy 1 more physp than they physically have since
112            we still reserve room for a "port 0".
113          */
114         size = p_ni->num_ports;
115
116         p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
117         if (!p_node)
118                 return NULL;
119
120         memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
121         p_node->node_info = *p_ni;
122         p_node->physp_tbl_size = size + 1;
123
124         /*
125            Construct Physical Port objects owned by this Node.
126            Then, initialize the Physical Port through with we
127            discovered this port.
128            For switches, all ports have the same GUID.
129            For CAs and routers, each port has a different GUID, so we only
130            know the GUID for the port that responded to our
131            Get(NodeInfo).
132          */
133         for (i = 0; i < p_node->physp_tbl_size; i++)
134                 osm_physp_construct(&p_node->physp_table[i]);
135
136         osm_node_init_physp(p_node, p_madw);
137         if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
138                 node_init_physp0(p_node, p_madw);
139         p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
140
141         return (p_node);
142 }
143
144 /**********************************************************************
145  **********************************************************************/
146 static void osm_node_destroy(IN osm_node_t * p_node)
147 {
148         uint16_t i;
149
150         /*
151            Cleanup all physports
152          */
153         for (i = 0; i < p_node->physp_tbl_size; i++)
154                 osm_physp_destroy(&p_node->physp_table[i]);
155
156         /* cleanup printable node_desc field */
157         if (p_node->print_desc) {
158                 free(p_node->print_desc);
159         }
160 }
161
162 /**********************************************************************
163  **********************************************************************/
164 void osm_node_delete(IN OUT osm_node_t ** const p_node)
165 {
166         CL_ASSERT(p_node && *p_node);
167         osm_node_destroy(*p_node);
168         free(*p_node);
169         *p_node = NULL;
170 }
171
172 /**********************************************************************
173  **********************************************************************/
174 void
175 osm_node_link(IN osm_node_t * const p_node,
176               IN const uint8_t port_num,
177               IN osm_node_t * const p_remote_node,
178               IN const uint8_t remote_port_num)
179 {
180         osm_physp_t *p_physp;
181         osm_physp_t *p_remote_physp;
182
183         CL_ASSERT(port_num < p_node->physp_tbl_size);
184         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
185
186         p_physp = osm_node_get_physp_ptr(p_node, port_num);
187         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
188
189         if (p_physp->p_remote_physp)
190                 p_physp->p_remote_physp->p_remote_physp = NULL;
191         if (p_remote_physp->p_remote_physp)
192                 p_remote_physp->p_remote_physp->p_remote_physp = NULL;
193
194         osm_physp_link(p_physp, p_remote_physp);
195 }
196
197 /**********************************************************************
198  **********************************************************************/
199 void
200 osm_node_unlink(IN osm_node_t * const p_node,
201                 IN const uint8_t port_num,
202                 IN osm_node_t * const p_remote_node,
203                 IN const uint8_t remote_port_num)
204 {
205         osm_physp_t *p_physp;
206         osm_physp_t *p_remote_physp;
207
208         CL_ASSERT(port_num < p_node->physp_tbl_size);
209         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
210
211         if (osm_node_link_exists(p_node, port_num,
212                                  p_remote_node, remote_port_num)) {
213
214                 p_physp = osm_node_get_physp_ptr(p_node, port_num);
215                 p_remote_physp =
216                     osm_node_get_physp_ptr(p_remote_node, remote_port_num);
217
218                 osm_physp_unlink(p_physp, p_remote_physp);
219         }
220 }
221
222 /**********************************************************************
223  **********************************************************************/
224 boolean_t
225 osm_node_link_exists(IN osm_node_t * const p_node,
226                      IN const uint8_t port_num,
227                      IN osm_node_t * const p_remote_node,
228                      IN const uint8_t remote_port_num)
229 {
230         osm_physp_t *p_physp;
231         osm_physp_t *p_remote_physp;
232
233         CL_ASSERT(port_num < p_node->physp_tbl_size);
234         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
235
236         p_physp = osm_node_get_physp_ptr(p_node, port_num);
237         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
238
239         return (osm_physp_link_exists(p_physp, p_remote_physp));
240 }
241
242 /**********************************************************************
243  **********************************************************************/
244 boolean_t
245 osm_node_link_has_valid_ports(IN osm_node_t * const p_node,
246                               IN const uint8_t port_num,
247                               IN osm_node_t * const p_remote_node,
248                               IN const uint8_t remote_port_num)
249 {
250         osm_physp_t *p_physp;
251         osm_physp_t *p_remote_physp;
252
253         CL_ASSERT(port_num < p_node->physp_tbl_size);
254         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
255
256         p_physp = osm_node_get_physp_ptr(p_node, port_num);
257         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
258
259         return (p_physp && p_remote_physp);
260 }
261
262 /**********************************************************************
263  **********************************************************************/
264 boolean_t
265 osm_node_has_any_link(IN osm_node_t * const p_node, IN const uint8_t port_num)
266 {
267         osm_physp_t *p_physp;
268         CL_ASSERT(port_num < p_node->physp_tbl_size);
269         p_physp = osm_node_get_physp_ptr(p_node, port_num);
270         return (osm_physp_has_any_link(p_physp));
271 }
272
273 /**********************************************************************
274  **********************************************************************/
275 osm_node_t *osm_node_get_remote_node(IN osm_node_t * const p_node,
276                                      IN const uint8_t port_num,
277                                      OUT uint8_t * p_remote_port_num)
278 {
279         osm_physp_t *p_physp;
280         osm_physp_t *p_remote_physp;
281
282         p_physp = osm_node_get_physp_ptr(p_node, port_num);
283
284         if (!p_physp || !osm_physp_has_any_link(p_physp))
285                 return (NULL);
286
287         p_remote_physp = osm_physp_get_remote(p_physp);
288         if (p_remote_port_num)
289                 *p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
290
291         return (osm_physp_get_node_ptr(p_remote_physp));
292 }
293
294 /**********************************************************************
295  The lock must be held before calling this function.
296 **********************************************************************/
297 ib_net16_t
298 osm_node_get_remote_base_lid(IN osm_node_t * const p_node,
299                              IN const uint32_t port_num)
300 {
301         osm_physp_t *p_physp;
302         osm_physp_t *p_remote_physp;
303         CL_ASSERT(port_num < p_node->physp_tbl_size);
304
305         p_physp = osm_node_get_physp_ptr(p_node, port_num);
306         if (p_physp) {
307                 p_remote_physp = osm_physp_get_remote(p_physp);
308                 return (osm_physp_get_base_lid(p_remote_physp));
309         }
310
311         return (0);
312 }