Fixed bug on building RTE groups with no endpoint 01/5101/2
authorAlexandre Huff <alexandrehuff@gmail.com>
Tue, 17 Nov 2020 14:11:21 +0000 (11:11 -0300)
committerScott Daniels <daniels@research.att.com>
Tue, 17 Nov 2020 20:58:43 +0000 (20:58 +0000)
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

src/rmr/common/src/rt_generic_static.c

index 116b17f..1d8d9ca 100644 (file)
@@ -488,6 +488,8 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r
        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 );
@@ -507,14 +509,19 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r
                        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] );
-                                                       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;
+                                       }
                                }
                        }
                }