1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5d6b92ffaSHans Petter Selasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
6d6b92ffaSHans Petter Selasky *
7d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
8d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
9d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
10d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
11d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
12d6b92ffaSHans Petter Selasky *
13d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
14d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
15d6b92ffaSHans Petter Selasky * conditions are met:
16d6b92ffaSHans Petter Selasky *
17d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
18d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
19d6b92ffaSHans Petter Selasky * disclaimer.
20d6b92ffaSHans Petter Selasky *
21d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
22d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
23d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
24d6b92ffaSHans Petter Selasky * provided with the distribution.
25d6b92ffaSHans Petter Selasky *
26d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33d6b92ffaSHans Petter Selasky * SOFTWARE.
34d6b92ffaSHans Petter Selasky *
35d6b92ffaSHans Petter Selasky */
36d6b92ffaSHans Petter Selasky
37d6b92ffaSHans Petter Selasky /*
38d6b92ffaSHans Petter Selasky * Abstract:
39d6b92ffaSHans Petter Selasky * Implementation of osm_mcast_tbl_t.
40d6b92ffaSHans Petter Selasky * This object represents a multicast forwarding table.
41d6b92ffaSHans Petter Selasky * This object is part of the opensm family of objects.
42d6b92ffaSHans Petter Selasky */
43d6b92ffaSHans Petter Selasky
44d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
45d6b92ffaSHans Petter Selasky # include <config.h>
46d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
47d6b92ffaSHans Petter Selasky
48d6b92ffaSHans Petter Selasky #include <stdlib.h>
49d6b92ffaSHans Petter Selasky #include <string.h>
50d6b92ffaSHans Petter Selasky #include <complib/cl_math.h>
51d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
52d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
53d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_MCAST_TBL_C
54d6b92ffaSHans Petter Selasky #include <opensm/osm_mcast_tbl.h>
55d6b92ffaSHans Petter Selasky
osm_mcast_tbl_init(IN osm_mcast_tbl_t * p_tbl,IN uint8_t num_ports,IN uint16_t capacity)56d6b92ffaSHans Petter Selasky void osm_mcast_tbl_init(IN osm_mcast_tbl_t * p_tbl, IN uint8_t num_ports,
57d6b92ffaSHans Petter Selasky IN uint16_t capacity)
58d6b92ffaSHans Petter Selasky {
59d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
60d6b92ffaSHans Petter Selasky CL_ASSERT(num_ports);
61d6b92ffaSHans Petter Selasky
62d6b92ffaSHans Petter Selasky memset(p_tbl, 0, sizeof(*p_tbl));
63d6b92ffaSHans Petter Selasky
64d6b92ffaSHans Petter Selasky p_tbl->max_block_in_use = -1;
65d6b92ffaSHans Petter Selasky
66d6b92ffaSHans Petter Selasky if (capacity == 0) {
67d6b92ffaSHans Petter Selasky /*
68d6b92ffaSHans Petter Selasky This switch apparently doesn't support multicast.
69d6b92ffaSHans Petter Selasky Everything is initialized to zero already, so return.
70d6b92ffaSHans Petter Selasky */
71d6b92ffaSHans Petter Selasky return;
72d6b92ffaSHans Petter Selasky }
73d6b92ffaSHans Petter Selasky
74d6b92ffaSHans Petter Selasky p_tbl->num_entries = capacity;
75d6b92ffaSHans Petter Selasky p_tbl->num_ports = num_ports;
76d6b92ffaSHans Petter Selasky p_tbl->max_position =
77d6b92ffaSHans Petter Selasky (uint8_t) ((ROUNDUP(num_ports, IB_MCAST_MASK_SIZE) /
78d6b92ffaSHans Petter Selasky IB_MCAST_MASK_SIZE) - 1);
79d6b92ffaSHans Petter Selasky
80d6b92ffaSHans Petter Selasky p_tbl->max_block = (uint16_t) ((ROUNDUP(p_tbl->num_entries,
81d6b92ffaSHans Petter Selasky IB_MCAST_BLOCK_SIZE) /
82d6b92ffaSHans Petter Selasky IB_MCAST_BLOCK_SIZE) - 1);
83d6b92ffaSHans Petter Selasky }
84d6b92ffaSHans Petter Selasky
osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * p_tbl)85d6b92ffaSHans Petter Selasky void osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * p_tbl)
86d6b92ffaSHans Petter Selasky {
87d6b92ffaSHans Petter Selasky free(p_tbl->p_mask_tbl);
88d6b92ffaSHans Petter Selasky }
89d6b92ffaSHans Petter Selasky
osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl,IN uint16_t mlid_ho,IN uint8_t port)90d6b92ffaSHans Petter Selasky void osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho,
91d6b92ffaSHans Petter Selasky IN uint8_t port)
92d6b92ffaSHans Petter Selasky {
93d6b92ffaSHans Petter Selasky unsigned mlid_offset, mask_offset, bit_mask;
94d6b92ffaSHans Petter Selasky int16_t block_num;
95d6b92ffaSHans Petter Selasky
96d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl && p_tbl->p_mask_tbl);
97d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
98d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
99d6b92ffaSHans Petter Selasky
100d6b92ffaSHans Petter Selasky mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
101d6b92ffaSHans Petter Selasky mask_offset = port / IB_MCAST_MASK_SIZE;
102d6b92ffaSHans Petter Selasky bit_mask = cl_ntoh16((uint16_t) (1 << (port % IB_MCAST_MASK_SIZE)));
103d6b92ffaSHans Petter Selasky (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask;
104d6b92ffaSHans Petter Selasky
105d6b92ffaSHans Petter Selasky block_num = (int16_t) (mlid_offset / IB_MCAST_BLOCK_SIZE);
106d6b92ffaSHans Petter Selasky
107d6b92ffaSHans Petter Selasky if (block_num > p_tbl->max_block_in_use)
108d6b92ffaSHans Petter Selasky p_tbl->max_block_in_use = (uint16_t) block_num;
109d6b92ffaSHans Petter Selasky }
110d6b92ffaSHans Petter Selasky
osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl,IN unsigned mlid_offset)111d6b92ffaSHans Petter Selasky int osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl, IN unsigned mlid_offset)
112d6b92ffaSHans Petter Selasky {
113d6b92ffaSHans Petter Selasky size_t mft_depth, size;
114d6b92ffaSHans Petter Selasky uint16_t (*p_mask_tbl)[][IB_MCAST_POSITION_MAX + 1];
115d6b92ffaSHans Petter Selasky
116d6b92ffaSHans Petter Selasky if (mlid_offset < p_tbl->mft_depth)
117d6b92ffaSHans Petter Selasky goto done;
118d6b92ffaSHans Petter Selasky
119d6b92ffaSHans Petter Selasky /*
120d6b92ffaSHans Petter Selasky The number of bytes needed in the mask table is:
121d6b92ffaSHans Petter Selasky The (maximum bit mask 'position' + 1) times the
122d6b92ffaSHans Petter Selasky number of bytes in each bit mask times the
123d6b92ffaSHans Petter Selasky number of MLIDs supported by the table.
124d6b92ffaSHans Petter Selasky
125d6b92ffaSHans Petter Selasky We must always allocate the array with the maximum position
126d6b92ffaSHans Petter Selasky since it is (and must be) defined that way the table structure
127d6b92ffaSHans Petter Selasky in order to create a pointer to a two dimensional array.
128d6b92ffaSHans Petter Selasky */
129d6b92ffaSHans Petter Selasky mft_depth = (mlid_offset / IB_MCAST_BLOCK_SIZE + 1) * IB_MCAST_BLOCK_SIZE;
130d6b92ffaSHans Petter Selasky size = mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8;
131d6b92ffaSHans Petter Selasky p_mask_tbl = realloc(p_tbl->p_mask_tbl, size);
132d6b92ffaSHans Petter Selasky if (!p_mask_tbl)
133d6b92ffaSHans Petter Selasky return -1;
134d6b92ffaSHans Petter Selasky memset((uint8_t *)p_mask_tbl + p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8,
135d6b92ffaSHans Petter Selasky 0,
136d6b92ffaSHans Petter Selasky size - p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8);
137d6b92ffaSHans Petter Selasky p_tbl->p_mask_tbl = p_mask_tbl;
138d6b92ffaSHans Petter Selasky p_tbl->mft_depth = mft_depth;
139d6b92ffaSHans Petter Selasky done:
140d6b92ffaSHans Petter Selasky p_tbl->max_mlid_ho = mlid_offset + IB_LID_MCAST_START_HO;
141d6b92ffaSHans Petter Selasky return 0;
142d6b92ffaSHans Petter Selasky }
143d6b92ffaSHans Petter Selasky
osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * p_tbl,IN uint16_t mlid_ho,IN uint8_t port_num)144d6b92ffaSHans Petter Selasky boolean_t osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * p_tbl,
145d6b92ffaSHans Petter Selasky IN uint16_t mlid_ho, IN uint8_t port_num)
146d6b92ffaSHans Petter Selasky {
147d6b92ffaSHans Petter Selasky unsigned mlid_offset, mask_offset, bit_mask;
148d6b92ffaSHans Petter Selasky
149d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
150d6b92ffaSHans Petter Selasky
151d6b92ffaSHans Petter Selasky if (p_tbl->p_mask_tbl) {
152d6b92ffaSHans Petter Selasky CL_ASSERT(port_num <=
153d6b92ffaSHans Petter Selasky (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE);
154d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
155d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
156d6b92ffaSHans Petter Selasky
157d6b92ffaSHans Petter Selasky mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
158d6b92ffaSHans Petter Selasky mask_offset = port_num / IB_MCAST_MASK_SIZE;
159d6b92ffaSHans Petter Selasky bit_mask = cl_ntoh16((uint16_t)
160d6b92ffaSHans Petter Selasky (1 << (port_num % IB_MCAST_MASK_SIZE)));
161d6b92ffaSHans Petter Selasky return (((*p_tbl->
162d6b92ffaSHans Petter Selasky p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) ==
163d6b92ffaSHans Petter Selasky bit_mask);
164d6b92ffaSHans Petter Selasky }
165d6b92ffaSHans Petter Selasky
166d6b92ffaSHans Petter Selasky return FALSE;
167d6b92ffaSHans Petter Selasky }
168d6b92ffaSHans Petter Selasky
osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * p_tbl,IN uint16_t mlid_ho)169d6b92ffaSHans Petter Selasky boolean_t osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * p_tbl,
170d6b92ffaSHans Petter Selasky IN uint16_t mlid_ho)
171d6b92ffaSHans Petter Selasky {
172d6b92ffaSHans Petter Selasky unsigned mlid_offset;
173d6b92ffaSHans Petter Selasky uint8_t position;
174d6b92ffaSHans Petter Selasky uint16_t result = 0;
175d6b92ffaSHans Petter Selasky
176d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
177d6b92ffaSHans Petter Selasky
178d6b92ffaSHans Petter Selasky if (p_tbl->p_mask_tbl) {
179d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
180d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
181d6b92ffaSHans Petter Selasky
182d6b92ffaSHans Petter Selasky mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
183d6b92ffaSHans Petter Selasky
184d6b92ffaSHans Petter Selasky for (position = 0; position <= p_tbl->max_position; position++)
185d6b92ffaSHans Petter Selasky result |= (*p_tbl->p_mask_tbl)[mlid_offset][position];
186d6b92ffaSHans Petter Selasky }
187d6b92ffaSHans Petter Selasky
188d6b92ffaSHans Petter Selasky return (result != 0);
189d6b92ffaSHans Petter Selasky }
190d6b92ffaSHans Petter Selasky
osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl,IN const ib_net16_t * p_block,IN int16_t block_num,IN uint8_t position)191d6b92ffaSHans Petter Selasky ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl,
192d6b92ffaSHans Petter Selasky IN const ib_net16_t * p_block,
193d6b92ffaSHans Petter Selasky IN int16_t block_num,
194d6b92ffaSHans Petter Selasky IN uint8_t position)
195d6b92ffaSHans Petter Selasky {
196d6b92ffaSHans Petter Selasky uint32_t i;
197d6b92ffaSHans Petter Selasky uint16_t mlid_start_ho;
198d6b92ffaSHans Petter Selasky
199d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
200d6b92ffaSHans Petter Selasky CL_ASSERT(p_block);
201d6b92ffaSHans Petter Selasky
202d6b92ffaSHans Petter Selasky if (block_num > p_tbl->max_block)
203d6b92ffaSHans Petter Selasky return IB_INVALID_PARAMETER;
204d6b92ffaSHans Petter Selasky
205d6b92ffaSHans Petter Selasky if (position > p_tbl->max_position)
206d6b92ffaSHans Petter Selasky return IB_INVALID_PARAMETER;
207d6b92ffaSHans Petter Selasky
208d6b92ffaSHans Petter Selasky mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
209d6b92ffaSHans Petter Selasky
210d6b92ffaSHans Petter Selasky if (mlid_start_ho + IB_MCAST_BLOCK_SIZE - 1 > p_tbl->mft_depth)
211d6b92ffaSHans Petter Selasky return IB_INVALID_PARAMETER;
212d6b92ffaSHans Petter Selasky
213d6b92ffaSHans Petter Selasky for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
214d6b92ffaSHans Petter Selasky (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i];
215d6b92ffaSHans Petter Selasky
216d6b92ffaSHans Petter Selasky if (block_num > p_tbl->max_block_in_use)
217d6b92ffaSHans Petter Selasky p_tbl->max_block_in_use = (uint16_t) block_num;
218d6b92ffaSHans Petter Selasky
219d6b92ffaSHans Petter Selasky return IB_SUCCESS;
220d6b92ffaSHans Petter Selasky }
221d6b92ffaSHans Petter Selasky
osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * p_tbl,IN uint16_t mlid_ho)222d6b92ffaSHans Petter Selasky void osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho)
223d6b92ffaSHans Petter Selasky {
224d6b92ffaSHans Petter Selasky unsigned mlid_offset;
225d6b92ffaSHans Petter Selasky
226d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
227d6b92ffaSHans Petter Selasky CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
228d6b92ffaSHans Petter Selasky
229d6b92ffaSHans Petter Selasky mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
230d6b92ffaSHans Petter Selasky if (p_tbl->p_mask_tbl && mlid_offset < p_tbl->mft_depth)
231d6b92ffaSHans Petter Selasky memset((uint8_t *)p_tbl->p_mask_tbl + mlid_offset * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8,
232d6b92ffaSHans Petter Selasky 0,
233d6b92ffaSHans Petter Selasky (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8);
234d6b92ffaSHans Petter Selasky }
235d6b92ffaSHans Petter Selasky
osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * p_tbl,IN int16_t block_num,IN uint8_t position,OUT ib_net16_t * p_block)236d6b92ffaSHans Petter Selasky boolean_t osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * p_tbl,
237d6b92ffaSHans Petter Selasky IN int16_t block_num, IN uint8_t position,
238d6b92ffaSHans Petter Selasky OUT ib_net16_t * p_block)
239d6b92ffaSHans Petter Selasky {
240d6b92ffaSHans Petter Selasky uint32_t i;
241d6b92ffaSHans Petter Selasky uint16_t mlid_start_ho;
242d6b92ffaSHans Petter Selasky
243d6b92ffaSHans Petter Selasky CL_ASSERT(p_tbl);
244d6b92ffaSHans Petter Selasky CL_ASSERT(p_block);
245d6b92ffaSHans Petter Selasky
246d6b92ffaSHans Petter Selasky if (block_num > p_tbl->max_block_in_use)
247d6b92ffaSHans Petter Selasky return FALSE;
248d6b92ffaSHans Petter Selasky
249d6b92ffaSHans Petter Selasky if (position > p_tbl->max_position) {
250d6b92ffaSHans Petter Selasky /*
251d6b92ffaSHans Petter Selasky Caller shouldn't do this for efficiency's sake...
252d6b92ffaSHans Petter Selasky */
253d6b92ffaSHans Petter Selasky memset(p_block, 0, IB_SMP_DATA_SIZE);
254d6b92ffaSHans Petter Selasky return TRUE;
255d6b92ffaSHans Petter Selasky }
256d6b92ffaSHans Petter Selasky
257d6b92ffaSHans Petter Selasky CL_ASSERT(block_num * IB_MCAST_BLOCK_SIZE <= p_tbl->mft_depth);
258d6b92ffaSHans Petter Selasky
259d6b92ffaSHans Petter Selasky mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
260d6b92ffaSHans Petter Selasky
261d6b92ffaSHans Petter Selasky for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
262d6b92ffaSHans Petter Selasky p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
263d6b92ffaSHans Petter Selasky
264d6b92ffaSHans Petter Selasky return TRUE;
265d6b92ffaSHans Petter Selasky }
266