]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/opensm/osm_node.c
MFV r340865:
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / opensm / osm_node.c
1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2015 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_file_ids.h>
50 #define FILE_ID OSM_FILE_NODE_C
51 #include <opensm/osm_node.h>
52 #include <opensm/osm_madw.h>
53
54 void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num,
55                          IN const osm_madw_t * p_madw)
56 {
57         ib_net64_t port_guid;
58         ib_smp_t *p_smp;
59         ib_node_info_t *p_ni;
60
61         p_smp = osm_madw_get_smp_ptr(p_madw);
62
63         p_ni = ib_smp_get_payload_ptr(p_smp);
64         port_guid = p_ni->port_guid;
65
66         CL_ASSERT(port_num < p_node->physp_tbl_size);
67
68         osm_physp_init(&p_node->physp_table[port_num],
69                        port_guid, port_num, p_node,
70                        osm_madw_get_bind_handle(p_madw),
71                        p_smp->hop_count, p_smp->initial_path);
72 }
73
74 osm_node_t *osm_node_new(IN const osm_madw_t * p_madw)
75 {
76         osm_node_t *p_node;
77         ib_smp_t *p_smp;
78         ib_node_info_t *p_ni;
79         uint8_t i;
80         uint32_t size;
81
82         p_smp = osm_madw_get_smp_ptr(p_madw);
83         p_ni = ib_smp_get_payload_ptr(p_smp);
84
85         /*
86            The node object already contains one physical port object.
87            Therefore, subtract 1 from the number of physical ports
88            used by the switch.  This is not done for CA's since they
89            need to occupy 1 more physp than they physically have since
90            we still reserve room for a "port 0".
91          */
92         size = p_ni->num_ports;
93
94         p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
95         if (!p_node)
96                 return NULL;
97
98         memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
99         p_node->node_info = *p_ni;
100         p_node->physp_tbl_size = size + 1;
101
102         p_node->physp_discovered = malloc(sizeof(uint8_t) * p_node->physp_tbl_size);
103         if (!p_node->physp_discovered) {
104                 free(p_node);
105                 return NULL;
106         }
107         memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size);
108         /*
109            Construct Physical Port objects owned by this Node.
110            Then, initialize the Physical Port through with we
111            discovered this port.
112            For switches, all ports have the same GUID.
113            For CAs and routers, each port has a different GUID, so we only
114            know the GUID for the port that responded to our
115            Get(NodeInfo).
116          */
117         for (i = 0; i < p_node->physp_tbl_size; i++)
118                 osm_physp_construct(&p_node->physp_table[i]);
119
120         if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
121                 for (i = 0; i <= p_ni->num_ports; i++)
122                         osm_node_init_physp(p_node, i, p_madw);
123         else
124                 osm_node_init_physp(p_node,
125                                     ib_node_info_get_local_port_num(p_ni),
126                                     p_madw);
127         p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
128
129         return p_node;
130 }
131
132 static void node_destroy(IN osm_node_t * p_node)
133 {
134         uint16_t i;
135
136         /*
137            Cleanup all physports
138          */
139         for (i = 0; i < p_node->physp_tbl_size; i++)
140                 osm_physp_destroy(&p_node->physp_table[i]);
141
142         /* cleanup printable node_desc field */
143         if (p_node->print_desc)
144                 free(p_node->print_desc);
145
146         /* cleanup physp_discovered array */
147         free(p_node->physp_discovered);
148 }
149
150 void osm_node_delete(IN OUT osm_node_t ** p_node)
151 {
152         CL_ASSERT(p_node && *p_node);
153         node_destroy(*p_node);
154         free(*p_node);
155         *p_node = NULL;
156 }
157
158 void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num,
159                    IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
160 {
161         osm_physp_t *p_physp;
162         osm_physp_t *p_remote_physp;
163
164         p_physp = osm_node_get_physp_ptr(p_node, port_num);
165         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
166
167         if (p_physp->p_remote_physp)
168                 p_physp->p_remote_physp->p_remote_physp = NULL;
169         if (p_remote_physp->p_remote_physp)
170                 p_remote_physp->p_remote_physp->p_remote_physp = NULL;
171
172         osm_physp_link(p_physp, p_remote_physp);
173 }
174
175 void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num,
176                      IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
177 {
178         osm_physp_t *p_physp;
179         osm_physp_t *p_remote_physp;
180
181         CL_ASSERT(port_num < p_node->physp_tbl_size);
182         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
183
184         if (osm_node_link_exists(p_node, port_num,
185                                  p_remote_node, remote_port_num)) {
186
187                 p_physp = osm_node_get_physp_ptr(p_node, port_num);
188                 p_remote_physp =
189                     osm_node_get_physp_ptr(p_remote_node, remote_port_num);
190
191                 osm_physp_unlink(p_physp, p_remote_physp);
192         }
193 }
194
195 boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num,
196                                IN osm_node_t * p_remote_node,
197                                IN uint8_t remote_port_num)
198 {
199         osm_physp_t *p_physp;
200         osm_physp_t *p_remote_physp;
201
202         CL_ASSERT(port_num < p_node->physp_tbl_size);
203         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
204
205         p_physp = osm_node_get_physp_ptr(p_node, port_num);
206         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
207
208         return osm_physp_link_exists(p_physp, p_remote_physp);
209 }
210
211 boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node,
212                                         IN uint8_t port_num,
213                                         IN osm_node_t * p_remote_node,
214                                         IN uint8_t remote_port_num)
215 {
216         osm_physp_t *p_physp;
217         osm_physp_t *p_remote_physp;
218
219         CL_ASSERT(port_num < p_node->physp_tbl_size);
220         CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
221
222         p_physp = osm_node_get_physp_ptr(p_node, port_num);
223         p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
224
225         return (p_physp && p_remote_physp);
226 }
227
228 boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num)
229 {
230         osm_physp_t *p_physp;
231         CL_ASSERT(port_num < p_node->physp_tbl_size);
232         p_physp = osm_node_get_physp_ptr(p_node, port_num);
233         return osm_physp_has_any_link(p_physp);
234 }
235
236 osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node,
237                                      IN uint8_t port_num,
238                                      OUT uint8_t * p_remote_port_num)
239 {
240         osm_physp_t *p_physp;
241         osm_physp_t *p_remote_physp;
242
243         p_physp = osm_node_get_physp_ptr(p_node, port_num);
244
245         if (!p_physp || !osm_physp_has_any_link(p_physp))
246                 return NULL;
247
248         p_remote_physp = osm_physp_get_remote(p_physp);
249         if (p_remote_port_num)
250                 *p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
251
252         return osm_physp_get_node_ptr(p_remote_physp);
253 }
254
255 /**********************************************************************
256  The lock must be held before calling this function.
257 **********************************************************************/
258 ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node,
259                                         IN uint32_t port_num)
260 {
261         osm_physp_t *p_physp;
262         osm_physp_t *p_remote_physp;
263         CL_ASSERT(port_num < p_node->physp_tbl_size);
264
265         p_physp = osm_node_get_physp_ptr(p_node, port_num);
266         if (p_physp) {
267                 p_remote_physp = osm_physp_get_remote(p_physp);
268                 return osm_physp_get_base_lid(p_remote_physp);
269         }
270
271         return 0;
272 }