]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_mcast_tbl.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_mcast_tbl.c
1 /*
2  * Copyright (c) 2004-2006 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_mcast_tbl_t.
39  * This object represents an multicast forwarding table.
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 <string.h>
49 #include <complib/cl_math.h>
50 #include <iba/ib_types.h>
51 #include <opensm/osm_mcast_tbl.h>
52
53 /**********************************************************************
54  **********************************************************************/
55 ib_api_status_t
56 osm_mcast_tbl_init(IN osm_mcast_tbl_t * const p_tbl,
57                    IN uint8_t const num_ports, IN uint16_t const capacity)
58 {
59         CL_ASSERT(p_tbl);
60         CL_ASSERT(num_ports);
61
62         memset(p_tbl, 0, sizeof(*p_tbl));
63
64         p_tbl->max_block_in_use = -1;
65
66         if (capacity == 0) {
67                 /*
68                    This switch apparently doesn't support multicast.
69                    Everything is initialized to zero already, so return.
70                  */
71                 return (IB_SUCCESS);
72         }
73
74         p_tbl->num_entries = capacity;
75         p_tbl->num_ports = num_ports;
76         p_tbl->max_position =
77             (uint8_t) ((ROUNDUP(num_ports, IB_MCAST_MASK_SIZE) /
78                         IB_MCAST_MASK_SIZE) - 1);
79
80         p_tbl->max_block = (uint16_t) ((ROUNDUP(p_tbl->num_entries,
81                                                 IB_MCAST_BLOCK_SIZE) /
82                                         IB_MCAST_BLOCK_SIZE) - 1);
83
84         p_tbl->max_mlid_ho = (uint16_t) (IB_LID_MCAST_START_HO + capacity - 1);
85
86         /*
87            The number of bytes needed in the mask table is:
88            The (maximum bit mask 'position' + 1) times the
89            number of bytes in each bit mask times the
90            number of MLIDs supported by the table.
91
92            We must always allocate the array with the maximum position
93            since it is (and must be) defined that way the table structure
94            in order to create a pointer to a two dimensional array.
95          */
96         p_tbl->p_mask_tbl = malloc(p_tbl->num_entries *
97                                    (IB_MCAST_POSITION_MAX +
98                                     1) * IB_MCAST_MASK_SIZE / 8);
99
100         if (p_tbl->p_mask_tbl == NULL)
101                 return (IB_INSUFFICIENT_MEMORY);
102
103         memset(p_tbl->p_mask_tbl, 0,
104                p_tbl->num_entries * (IB_MCAST_POSITION_MAX +
105                                      1) * IB_MCAST_MASK_SIZE / 8);
106         return (IB_SUCCESS);
107 }
108
109 /**********************************************************************
110  **********************************************************************/
111 void osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * const p_tbl)
112 {
113         free(p_tbl->p_mask_tbl);
114 }
115
116 /**********************************************************************
117  **********************************************************************/
118 void
119 osm_mcast_tbl_set(IN osm_mcast_tbl_t * const p_tbl,
120                   IN const uint16_t mlid_ho, IN const uint8_t port)
121 {
122         uintn_t mlid_offset;
123         uintn_t mask_offset;
124         uintn_t bit_mask;
125         int16_t block_num;
126
127         CL_ASSERT(p_tbl);
128         CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
129         CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
130         CL_ASSERT(p_tbl->p_mask_tbl);
131
132         mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
133         mask_offset = port / IB_MCAST_MASK_SIZE;
134         bit_mask = cl_ntoh16((uint16_t) (1 << (port % IB_MCAST_MASK_SIZE)));
135         (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask;
136
137         block_num = (int16_t) (mlid_offset / IB_MCAST_BLOCK_SIZE);
138
139         if (block_num > p_tbl->max_block_in_use)
140                 p_tbl->max_block_in_use = (uint16_t) block_num;
141 }
142
143 /**********************************************************************
144  **********************************************************************/
145 boolean_t
146 osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * const p_tbl,
147                       IN const uint16_t mlid_ho, IN const uint8_t port_num)
148 {
149         uintn_t mlid_offset;
150         uintn_t mask_offset;
151         uintn_t bit_mask;
152
153         CL_ASSERT(p_tbl);
154
155         if (p_tbl->p_mask_tbl) {
156                 CL_ASSERT(port_num <=
157                           (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE);
158                 CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
159                 CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
160
161                 mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
162                 mask_offset = port_num / IB_MCAST_MASK_SIZE;
163                 bit_mask = cl_ntoh16((uint16_t)
164                                      (1 << (port_num % IB_MCAST_MASK_SIZE)));
165                 return (((*p_tbl->
166                           p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) ==
167                         bit_mask);
168         }
169
170         return (FALSE);
171 }
172
173 /**********************************************************************
174  **********************************************************************/
175 boolean_t
176 osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * const p_tbl,
177                           IN const uint16_t mlid_ho)
178 {
179         uintn_t mlid_offset;
180         uint8_t position;
181         uint16_t result = 0;
182
183         CL_ASSERT(p_tbl);
184
185         if (p_tbl->p_mask_tbl) {
186                 CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
187                 CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
188
189                 mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
190
191                 for (position = 0; position <= p_tbl->max_position; position++)
192                         result |= (*p_tbl->p_mask_tbl)[mlid_offset][position];
193         }
194
195         return (result != 0);
196 }
197
198 /**********************************************************************
199  **********************************************************************/
200 ib_api_status_t
201 osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * const p_tbl,
202                         IN const ib_net16_t * const p_block,
203                         IN const int16_t block_num, IN const uint8_t position)
204 {
205         uint32_t i;
206         uint16_t mlid_start_ho;
207
208         CL_ASSERT(p_tbl);
209         CL_ASSERT(p_block);
210
211         if (block_num > p_tbl->max_block)
212                 return (IB_INVALID_PARAMETER);
213
214         if (position > p_tbl->max_position)
215                 return (IB_INVALID_PARAMETER);
216
217         mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
218
219         if (mlid_start_ho + IB_MCAST_BLOCK_SIZE - 1 > p_tbl->max_mlid_ho)
220                 return (IB_INVALID_PARAMETER);
221
222         for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
223                 (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i];
224
225         if (block_num > p_tbl->max_block_in_use)
226                 p_tbl->max_block_in_use = (uint16_t) block_num;
227
228         return (IB_SUCCESS);
229 }
230
231 /**********************************************************************
232  **********************************************************************/
233 void
234 osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * const p_tbl,
235                          IN const uint16_t mlid_ho)
236 {
237         uint8_t i;
238         uintn_t mlid_offset;
239
240         CL_ASSERT(p_tbl);
241         CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
242
243         if (p_tbl->p_mask_tbl && (mlid_ho <= p_tbl->max_mlid_ho)) {
244                 mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
245                 for (i = 0; i <= p_tbl->max_position; i++)
246                         (*p_tbl->p_mask_tbl)[mlid_offset][i] = 0;
247         }
248 }
249
250 /**********************************************************************
251  **********************************************************************/
252 boolean_t
253 osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * const p_tbl,
254                         IN int16_t const block_num,
255                         IN uint8_t const position,
256                         OUT ib_net16_t * const p_block)
257 {
258         uint32_t i;
259         uint16_t mlid_start_ho;
260
261         CL_ASSERT(p_tbl);
262         CL_ASSERT(p_block);
263
264         if (block_num > p_tbl->max_block_in_use)
265                 return (FALSE);
266
267         if (position > p_tbl->max_position) {
268                 /*
269                    Caller shouldn't do this for efficiency's sake...
270                  */
271                 memset(p_block, 0, IB_SMP_DATA_SIZE);
272                 return (TRUE);
273         }
274
275         mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
276
277         if (mlid_start_ho + IB_MCAST_BLOCK_SIZE - 1 > p_tbl->max_mlid_ho)
278                 return (IB_INVALID_PARAMETER);
279
280         for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
281                 p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
282
283         return (TRUE);
284 }