@@ -76,7 +76,9 @@ typedef struct osm_mcast_fwdbl {
uint16_t num_entries;
uint16_t max_mlid_ho;
uint16_t mft_depth;
- uint16_t(*p_mask_tbl)[][IB_MCAST_POSITION_MAX + 1];
+ uint16_t(*p_new_mask_tbl)[][IB_MCAST_BLOCK_SIZE*(IB_MCAST_POSITION_MAX + 1)];
+ uint16_t(*p_mask_tbl)[][IB_MCAST_BLOCK_SIZE*(IB_MCAST_POSITION_MAX + 1)];
+ uint16_t is_first_block[IB_MCAST_MAX_BLOCK_ID];
} osm_mcast_tbl_t;
/*
* FIELDS
@@ -104,11 +106,20 @@ typedef struct osm_mcast_fwdbl {
* Number of MLIDs in the currently allocated multicast port mask
* table.
*
-* p_mask_tbl
-* Pointer to a two dimensional array of port_masks for this switch.
-* The first dimension is MLID offset, second dimension is mask position.
+* p_new_mask_tbl
+* Pointer to a two dimensional array of (IB_MCAST_POSITION_MAX + 1)
+* MFT blocks. The first dimensional is MFT block offset, second dimension
+* is (IB_MCAST_POSITION_MAX + 1) MFT blocks of the same mlid offset.
* This pointer is null for switches that do not support multicast.
*
+* p_mask_tbl
+* Pointer to a table, that is being filled when MFT table is recieved
+* after applying the tables to the switches.
+*
+* is_first_block
+* Table that for each block indicates whether it's being issued for
+* the first time.
+*
* SEE ALSO
*********/
@@ -482,5 +493,35 @@ osm_mcast_tbl_get_max_position(IN osm_mcast_tbl_t * p_tbl)
* SEE ALSO
*********/
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_diff
+* NAME
+* osm_mcast_cmpr_tbl_block
+*
+* DESCRIPTION
+* Compares between two multicast forwarding table blocks.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcast_tbl_diff(IN osm_mcast_tbl_t * p_tbl,
+ IN int16_t block_num, IN uint8_t position);
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to an osm_mcast_tbl_t object.
+*
+* p_block
+* [in] Pointer to the Forwarding Table block.
+*
+* block_num
+* [in] Block number of this block.
+*
+* RETURN VALUES
+* Returns TRUE if block is not idnetical in p_new_mask_tbl
+* and p_mask_tbl. FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
END_C_DECLS
#endif /* _OSM_MCAST_TBL_H_ */
@@ -263,7 +263,7 @@ static void dump_mcast_routes(cl_map_item_t * item, FILE * file, void *cxt)
while (position <= p_tbl->max_position) {
mask_entry =
cl_ntoh16((*p_tbl->
- p_mask_tbl)[mlid_ho][position]);
+ p_new_mask_tbl)[mlid_ho][position]);
if (mask_entry == 0) {
position++;
continue;
@@ -380,8 +380,20 @@ static int mcast_mgr_set_mft_block(osm_sm_t * sm, IN osm_switch_t * p_sw,
p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
+ /*
+ Send MFT block only if one of the following persists:
+ 1) There is a connectiviry change in the switch.
+ 2) This is the first time, the block is sent.
+ 3) New block is different than the previous time the
+ block was sent.
+ */
+
if (osm_mcast_tbl_get_block(p_tbl, (uint16_t) block_num,
- (uint8_t) position, block)) {
+ (uint8_t) position, block) &&
+ p_sw->need_update != 0 ||
+ p_tbl->is_first_block[block_num] ||
+ osm_mcast_tbl_diff(p_tbl,
+ uint16_t) block_num,(uint8_t) position))) {
block_id_ho = block_num + (position << 28);
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
@@ -1045,6 +1057,7 @@ static int mcast_mgr_set_mftables(osm_sm_t * sm)
p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
if (++p_sw->mft_position > p_tbl->max_position) {
p_sw->mft_position = 0;
+ p_tbl->is_first_block[block_num] = 0;
p_sw->mft_block_num++;
}
}
@@ -78,29 +78,30 @@ void osm_mcast_tbl_init(IN osm_mcast_tbl_t * p_tbl, IN uint8_t num_ports,
p_tbl->max_block = (uint16_t) ((ROUNDUP(p_tbl->num_entries,
IB_MCAST_BLOCK_SIZE) /
IB_MCAST_BLOCK_SIZE) - 1);
+
+ memset(p_tbl->is_first_block,1,sizeof(p_tbl->is_first_block));
}
void osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * p_tbl)
{
- free(p_tbl->p_mask_tbl);
+ free(p_tbl->p_new_mask_tbl);
}
void osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho,
IN uint8_t port)
{
unsigned mlid_offset, mask_offset, bit_mask;
- int16_t block_num;
+ uint16_t block_num;
- CL_ASSERT(p_tbl && p_tbl->p_mask_tbl);
+ CL_ASSERT(p_tbl && p_tbl->p_new_mask_tbl);
CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
- mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
- mask_offset = port / IB_MCAST_MASK_SIZE;
+ mlid_offset = (mlid_ho - IB_LID_MCAST_START_HO) % IB_MCAST_BLOCK_SIZE;
+ mask_offset = mlid_offset + ( port / IB_MCAST_MASK_SIZE ) * IB_MCAST_BLOCK_SIZE;
+ block_num = (uint16_t) ((mlid_ho - IB_LID_MCAST_START_HO) / IB_MCAST_BLOCK_SIZE);
bit_mask = cl_ntoh16((uint16_t) (1 << (port % IB_MCAST_MASK_SIZE)));
- (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask;
-
- block_num = (int16_t) (mlid_offset / IB_MCAST_BLOCK_SIZE);
+ (*p_tbl->p_new_mask_tbl)[block_num][mask_offset] |= bit_mask;
if (block_num > p_tbl->max_block_in_use)
p_tbl->max_block_in_use = (uint16_t) block_num;
@@ -108,8 +109,8 @@ void osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho,
int osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl, IN unsigned mlid_offset)
{
- size_t mft_depth, size;
- uint16_t (*p_mask_tbl)[][IB_MCAST_POSITION_MAX + 1];
+ size_t mft_depth, size, old_size;
+ uint16_t (*p_new_mask_tbl)[][IB_MCAST_BLOCK_SIZE*(IB_MCAST_POSITION_MAX + 1)];
if (mlid_offset < p_tbl->mft_depth)
goto done;
@@ -125,14 +126,22 @@ int osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl, IN unsigned mlid_offset)
in order to create a pointer to a two dimensional array.
*/
mft_depth = (mlid_offset / IB_MCAST_BLOCK_SIZE + 1) * IB_MCAST_BLOCK_SIZE;
- size = mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8;
- p_mask_tbl = realloc(p_tbl->p_mask_tbl, size);
- if (!p_mask_tbl)
+ size = mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_BLOCK_SIZE * IB_MCAST_MASK_SIZE / 8;
+ old_size = p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_BLOCK_SIZE * IB_MCAST_MASK_SIZE / 8;
+ p_new_mask_tbl = realloc(p_tbl->p_new_mask_tbl, size);
+ if (!p_new_mask_tbl)
+ return -1;
+ memset((uint8_t *)p_new_mask_tbl + old_size,
+ 0, size - old_size);
+ p_tbl->p_new_mask_tbl = p_new_mask_tbl;
+
+ p_new_mask_tbl = realloc(p_tbl->p_mask_tbl, size);
+ if (!p_new_mask_tbl)
return -1;
- memset((uint8_t *)p_mask_tbl + p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8,
- 0,
- size - p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8);
- p_tbl->p_mask_tbl = p_mask_tbl;
+ memset((uint8_t *)p_new_mask_tbl + old_size,
+ 0, size - old_size);
+ p_tbl->p_mask_tbl = p_new_mask_tbl;
+
p_tbl->mft_depth = mft_depth;
done:
p_tbl->max_mlid_ho = mlid_offset + IB_LID_MCAST_START_HO;
@@ -143,21 +152,23 @@ boolean_t osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * p_tbl,
IN uint16_t mlid_ho, IN uint8_t port_num)
{
unsigned mlid_offset, mask_offset, bit_mask;
+ uint16_t block_num;
CL_ASSERT(p_tbl);
- if (p_tbl->p_mask_tbl) {
+ if (p_tbl->p_new_mask_tbl) {
CL_ASSERT(port_num <=
(p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE);
CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
- mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
- mask_offset = port_num / IB_MCAST_MASK_SIZE;
+ mlid_offset = (mlid_ho - IB_LID_MCAST_START_HO) % IB_MCAST_BLOCK_SIZE;
+ mask_offset = mlid_offset + ( port_num / IB_MCAST_MASK_SIZE ) * IB_MCAST_BLOCK_SIZE;
+ block_num = (uint16_t) ((mlid_ho - IB_LID_MCAST_START_HO) / IB_MCAST_BLOCK_SIZE);
bit_mask = cl_ntoh16((uint16_t)
(1 << (port_num % IB_MCAST_MASK_SIZE)));
return (((*p_tbl->
- p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) ==
+ p_new_mask_tbl)[block_num][mask_offset] & bit_mask) ==
bit_mask);
}
@@ -170,17 +181,19 @@ boolean_t osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * p_tbl,
unsigned mlid_offset;
uint8_t position;
uint16_t result = 0;
+ uint16_t block_num;
CL_ASSERT(p_tbl);
- if (p_tbl->p_mask_tbl) {
+ if (p_tbl->p_new_mask_tbl) {
CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho);
- mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+ mlid_offset = (mlid_ho - IB_LID_MCAST_START_HO) % IB_MCAST_BLOCK_SIZE;
+ block_num = (uint16_t) (mlid_offset / IB_MCAST_BLOCK_SIZE);
for (position = 0; position <= p_tbl->max_position; position++)
- result |= (*p_tbl->p_mask_tbl)[mlid_offset][position];
+ result |= (*p_tbl->p_new_mask_tbl)[block_num][mlid_offset + position * IB_MCAST_BLOCK_SIZE];
}
return (result != 0);
@@ -191,7 +204,6 @@ ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl,
IN int16_t block_num,
IN uint8_t position)
{
- uint32_t i;
uint16_t mlid_start_ho;
CL_ASSERT(p_tbl);
@@ -208,9 +220,7 @@ ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl,
if (mlid_start_ho + IB_MCAST_BLOCK_SIZE - 1 > p_tbl->mft_depth)
return IB_INVALID_PARAMETER;
- for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
- (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i];
-
+ memcpy(&(*p_tbl->p_mask_tbl)[block_num][position * IB_MCAST_BLOCK_SIZE],p_block,IB_MCAST_BLOCK_SIZE * IB_MCAST_MASK_SIZE / 8);
if (block_num > p_tbl->max_block_in_use)
p_tbl->max_block_in_use = (uint16_t) block_num;
@@ -220,24 +230,41 @@ ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl,
void osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho)
{
unsigned mlid_offset;
+ uint16_t block_num;
+ uint32_t i;
CL_ASSERT(p_tbl);
CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO);
- mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
- if (p_tbl->p_mask_tbl && mlid_offset < p_tbl->mft_depth)
- memset((uint8_t *)p_tbl->p_mask_tbl + mlid_offset * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8,
- 0,
- (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8);
+ mlid_offset = (mlid_ho - IB_LID_MCAST_START_HO) % IB_MCAST_BLOCK_SIZE;
+ block_num = (uint16_t) ((mlid_ho - IB_LID_MCAST_START_HO) / IB_MCAST_BLOCK_SIZE);
+
+ if (p_tbl->p_new_mask_tbl && mlid_offset < p_tbl->mft_depth)
+ for (i=0;i<IB_MCAST_POSITION_MAX + 1; i++)
+ memset(&(*p_tbl->p_new_mask_tbl)[block_num][i * IB_MCAST_BLOCK_SIZE + mlid_offset],
+ 0, IB_MCAST_MASK_SIZE / 8);
+}
+
+boolean_t osm_mcast_tbl_diff(IN osm_mcast_tbl_t * p_tbl,
+ IN int16_t block_num, IN uint8_t position)
+{
+ CL_ASSERT(p_tbl);
+ CL_ASSERT(p_block);
+ CL_ASSERT(block_num * IB_MCAST_BLOCK_SIZE <= p_tbl->mft_depth);
+ if (position > p_tbl->max_position)
+ return TRUE;
+
+ if (memcmp(&(*p_tbl->p_new_mask_tbl)[block_num][position * IB_MCAST_BLOCK_SIZE],
+ &(*p_tbl->p_mask_tbl)[block_num][position * IB_MCAST_BLOCK_SIZE],IB_MCAST_BLOCK_SIZE * IB_MCAST_MASK_SIZE / 8))
+ return TRUE;
+
+ return FALSE;
}
boolean_t 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)
{
- uint32_t i;
- uint16_t mlid_start_ho;
-
CL_ASSERT(p_tbl);
CL_ASSERT(p_block);
CL_ASSERT(block_num * IB_MCAST_BLOCK_SIZE <= p_tbl->mft_depth);
@@ -253,10 +280,7 @@ boolean_t osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * p_tbl,
return TRUE;
}
- mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE);
-
- for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
- p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
+ memcpy(p_block,&(*p_tbl->p_new_mask_tbl)[block_num][position*IB_MCAST_BLOCK_SIZE],IB_MCAST_BLOCK_SIZE * IB_MCAST_MASK_SIZE / 8);
return TRUE;
}