When building a route table entry (rte) with several groups, a given
group can be added contiguously to the rte even if it has no endpoint.
Endpoints that reference to any of "our" local "address:port" are not
added to the rte. Thus, in some cases, groups that only reference to
local endpoints (nil) are added contiguously to the rte, causing the
round-robin group selection mechanism to stop sending messages to the
next groups after finding a nil-one.
This might happen, for instance, when a multicast routing rule is required
in which only one endpoint is added to each group, and one of these groups
references to one of the local "address:port" being used. In this case, only
the endpoints in the groups prior the nil-one will receive a copy of the
multicast message.
This change fixes this issue by adding contiguously only groups that have at
least one endpoint that does not refer to a local "address:port".
Some extra bytes are wasted in the rte by referencing to a group that does not
have an endpoint, but this is minor compared to spending time on recreating a
new rte and adding only the groups that do have endpoints. Those nil groups
don't cause any harm since the function that does the round-robin selection
assumes that the groups are contiguous and stops selecting endpoints when a
nil group is found.
Issue-ID: RIC-695
Signed-off-by: Alexandre Huff <alexandrehuff@gmail.com>
Change-Id: I13c7576ce0de82b7814c81c1a0da24172371a897
int i;
int ngtoks; // number of tokens in the group list
int grp; // index into group list
int i;
int ngtoks; // number of tokens in the group list
int grp; // index into group list
+ int cgidx; // contiguous group index (prevents the addition of a contiguous group without ep)
+ int has_ep = FALSE; // indicates if an endpoint was added in a given round robin group
ts_field = clip( ts_field ); // ditch extra whitespace and trailing comments
rr_field = clip( rr_field );
ts_field = clip( ts_field ); // ditch extra whitespace and trailing comments
rr_field = clip( rr_field );
rte = uta_add_rte( ctx->new_rtable, key, ngtoks ); // get/create entry for this key
rte->mtype = atoi( ts_field ); // capture mtype for debugging
rte = uta_add_rte( ctx->new_rtable, key, ngtoks ); // get/create entry for this key
rte->mtype = atoi( ts_field ); // capture mtype for debugging
- for( grp = 0; grp < ngtoks; grp++ ) {
- if( (ntoks = uta_rmip_tokenise( gtokens[grp], ctx->ip_list, tokens, 64, ',' )) > 0 ) { // remove any referneces to our ip addrs
+ for( grp = 0, cgidx = 0; grp < ngtoks; grp++ ) {
+ if( (ntoks = uta_rmip_tokenise( gtokens[grp], ctx->ip_list, tokens, 64, ',' )) > 0 ) { // remove any references to our ip addrs
for( i = 0; i < ntoks; i++ ) {
if( strcmp( tokens[i], ctx->my_name ) != 0 ) { // don't add if it is us -- cannot send to ourself
if( DEBUG > 1 || (vlevel > 1)) rmr_vlog_force( RMR_VL_DEBUG, "add endpoint ts=%s %s\n", ts_field, tokens[i] );
for( i = 0; i < ntoks; i++ ) {
if( strcmp( tokens[i], ctx->my_name ) != 0 ) { // don't add if it is us -- cannot send to ourself
if( DEBUG > 1 || (vlevel > 1)) rmr_vlog_force( RMR_VL_DEBUG, "add endpoint ts=%s %s\n", ts_field, tokens[i] );
- uta_add_ep( ctx->new_rtable, rte, tokens[i], grp );
+ uta_add_ep( ctx->new_rtable, rte, tokens[i], cgidx );
+ has_ep = TRUE;
+ if( has_ep ) {
+ cgidx++; // only increment to the next contiguous group if the current one has at least one endpoint
+ has_ep = FALSE;
+ }