Ensure RT incremental update not applied early 69/5869/1
authorE. Scott Daniels <daniels@att.com>
Fri, 9 Apr 2021 12:40:20 +0000 (08:40 -0400)
committerE. Scott Daniels <daniels@att.com>
Fri, 9 Apr 2021 13:24:23 +0000 (09:24 -0400)
This change ensures that a full table has been provided by the
route generator (route manager) prior to RMR accepting any
incremental updates.

The change also captures the initial value of the RMR_SEED
environment variable such that it cannot be changed once it has
been used.

Issue-ID: RIC-329

Signed-off-by: E. Scott Daniels <daniels@att.com>
Change-Id: I168cb42905e41641590130de724965e8dbca67e6

CHANGES_CORE.txt
CMakeLists.txt
docs/rel-notes.rst
src/rmr/common/include/rmr_agnostic.h
src/rmr/common/src/rt_generic_static.c
src/rmr/common/src/rtc_static.c
src/rmr/si/include/rmr_si_private.h
src/rmr/si/src/rmr_si.c
test/rt_static_test.c
test/test_ctx_support.c
test/test_gen_rt.c

index 51c254c..cfa9ea3 100644 (file)
@@ -5,6 +5,13 @@
 # API and build change  and fix summaries. Doc corrections
 # and/or changes are not mentioned here; see the commit messages.
 
+2021 April 9; version 4.7.2
+       Ensure that route table update received from route generator is not
+       applied before a full route table is received.
+
+2021 April 2; version 4.7.1
+       Correct issues found during static code analysis.
+
 2021 March 31; version 4.7.0
        The route table collector thread will capture the current "offering"
        from the Route Manager (table generator) if the RMR_SEED_RT environment
index a8220b4..a0d1b7f 100644 (file)
@@ -42,7 +42,7 @@ cmake_minimum_required( VERSION 3.5 )
 
 set( major_version "4" )               # should be automatically populated from git tag later, but until CI process sets a tag we use this
 set( minor_version "7" )
-set( patch_level "1" )
+set( patch_level "2" )
 
 set( install_root "${CMAKE_INSTALL_PREFIX}" )
 set( install_inc "include/rmr" )
index 7f29300..dadc465 100644 (file)
@@ -22,6 +22,21 @@ the need to leap frog versions ceased, and beginning with
 version 4.0.0, the RMR versions should no longer skip.
 
 
+2021 April 9; version 4.7.2
+---------------------------
+
+Ensure that route table update received from route generator
+is not applied before a full route table is received.
+
+
+
+2021 April 2; version 4.7.1
+---------------------------
+
+Correct issues found during static code analysis.
+
+
+
 2021 March 31; version 4.7.0
 ----------------------------
 
index 7e6fdda..0858fde 100644 (file)
@@ -83,11 +83,11 @@ typedef struct uta_ctx  uta_ctx_t;
                                                                        // internal flags, must be > than UFLAG_MASK
 //#define IFL_....
 
+                                                                       // context flags
 #define CFL_MTC_ENABLED        0x01            // multi-threaded call is enabled
 #define CFL_NO_RTACK   0x02            // no route table ack needed when end received
-
-                                                                       // context flags
-#define CTXFL_WARN             0x01            // ok to warn on stderr for some things that shouldn't happen
+#define CFL_WARN               0x04            // ok to warn on stderr for some things that shouldn't happen
+#define CFL_FULLRT             0x08            // set when we have received an initial full route table (prevent updates before one arrives)
 
                                                                        // msg buffer flags
 #define MFL_ZEROCOPY   0x01            // the message is an allocated zero copy message and can be sent.
index 2e4b711..dcedb49 100644 (file)
@@ -852,7 +852,7 @@ static void cycle_snarfed_rt( uta_ctx_t* ctx ) {
                return;
        }
 
-       if( (snarf_fname = getenv(  ENV_STASH_RT )) == NULL ) {                 // specific place to stash the rt not given
+       if( (snarf_fname = getenv(  ENV_STASH_RT )) == NULL ) {                         // specific place to stash the rt not given
                if( (seed_fname = getenv( ENV_SEED_RT )) != NULL ) {                    // no seed, we leave in the default file
                        memset( wfname, 0, sizeof( wfname ) );
                        snprintf( wfname, sizeof( wfname ) - 1, "%s.stash", seed_fname );
@@ -861,6 +861,7 @@ static void cycle_snarfed_rt( uta_ctx_t* ctx ) {
        }
 
        if( snarf_fname == NULL ) {
+               rmr_vlog( RMR_VL_DEBUG, "cycle_snarf: no file to save in" );
                return;
        }
 
@@ -1018,6 +1019,7 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
 
                                                send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL );
                                                ctx->rtable_ready = 1;                                                  // route based sends can now happen
+                                               ctx->flags |= CFL_FULLRT;                                               // indicate we have seen a complete route table
                                        } else {
                                                if( DEBUG > 1 ) rmr_vlog_force( RMR_VL_DEBUG, "end of route table noticed, but one was not started!\n" );
                                                ctx->new_rtable = NULL;
@@ -1079,6 +1081,11 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
                                break;
 
                        case 'u':                                                                                               // update current table, not a total replacement
+                               if( ! ctx->flags & CFL_FULLRT ) {                                       // we cannot update until we have a full table from route generator
+                                       rmr_vlog( RMR_VL_WARN, "route table update ignored: full table not previously recevied" );
+                                       break;
+                               }
+
                                tokens[1] = clip( tokens[1] );
                                if( strcmp( tokens[1], "end" ) == 0 ) {                         // wrap up the table we were building
                                        if( ctx->new_rtable == NULL ) {                                 // update table not in progress
@@ -1158,8 +1165,13 @@ static void read_static_rt( uta_ctx_t* ctx, int vlevel ) {
        char*   eor;                            // end of the record
        int             rcount = 0;                     // record count for debug
 
-       if( (fname = getenv( ENV_SEED_RT )) == NULL ) {
-               return;
+       if( (fname = ctx->seed_rt_fname) == NULL ) {
+               if( (fname = getenv( ENV_SEED_RT )) == NULL ) {
+                       return;
+               }
+
+               ctx->seed_rt_fname = strdup( fname );
+               fname = ctx->seed_rt_fname;
        }
 
        if( (fbuf = ensure_nlterm( uta_fib( fname ) ) ) == NULL ) {                     // read file into a single buffer (nil terminated string)
index 96f8330..10bc2a7 100644 (file)
@@ -310,6 +310,7 @@ static void* rtc( void* vctx ) {
        ctx->flags |= CFL_NO_RTACK;                             // don't ack when reading from a file
        read_static_rt( ctx, vlevel );                  // seed the route table if one provided
        ctx->flags &= ~CFL_NO_RTACK;
+       ctx->flags &= ~CFL_FULLRT;                              // even though rmr-ready goes true, the seed doesn't count as a full RT from route generator
 
 
        my_port = getenv( ENV_CTL_PORT );                               // default port to listen on (likely 4561)
index ee71409..414c649 100644 (file)
@@ -122,7 +122,7 @@ struct uta_ctx {
        int     shutdown;                               // thread notification if we need to tell them to stop
        int max_mlen;                           // max message length payload+header
        int     max_plen;                               // max payload length
-       int     flags;                                  // CTXFL_ constants
+       int     flags;                                  // CFL_ constants
        int nrtele;                                     // number of elements in the routing table
        int send_retries;                       // number of retries send_msg() should attempt if eagain/timeout indicated by nng
        int     trace_data_len;                 // number of bytes to allocate in header for trace data
@@ -132,6 +132,7 @@ struct uta_ctx {
        int rtable_ready;                       // set to true when rt is received or loaded
        int snarf_rt_fd;                        // the file des where we save the last rt from RM
        int dcount;                                     // drop counter when app is slow
+       char*   seed_rt_fname;          // the static/seed route table; name captured at start
        route_table_t* rtable;          // the active route table
        route_table_t* old_rtable;      // the previously used rt, sits here to allow for draining
        route_table_t* new_rtable;      // route table under construction
index b8bb2a0..8f88cf8 100644 (file)
@@ -733,7 +733,7 @@ static void* init( char* uproto_port, int def_msg_size, int flags ) {
 
        if( (tok = getenv( ENV_WARNINGS )) != NULL ) {
                if( *tok == '1' ) {
-                       ctx->flags |= CTXFL_WARN;                                       // turn on some warnings (not all, just ones that shouldn't impact performance)
+                       ctx->flags |= CFL_WARN;                                 // turn on some warnings (not all, just ones that shouldn't impact performance)
                }
        }
 
@@ -884,6 +884,10 @@ extern void rmr_close( void* vctx ) {
                return;
        }
 
+       if( ctx->seed_rt_fname != NULL ) {
+               free( ctx->seed_rt_fname );
+       }
+
        ctx->shutdown = 1;
 
        SItp_stats( ctx->si_ctx );                      // dump some interesting stats
index 7a51bca..3bdd312 100644 (file)
@@ -1,3 +1,4 @@
+
 // : vi ts=4 sw=4 noet :
 /*
 ==================================================================================
@@ -500,6 +501,10 @@ static int rt_test( ) {
                errors += fail_if_nil( ctx->rtable, "edge case route table didn't generate a pointer into the context" );
 
                unsetenv( "RMR_SEED_RT" );                      // remove for next read try
+               if( ctx && ctx->seed_rt_fname != NULL ) {
+                       free( ctx->seed_rt_fname );
+                       ctx->seed_rt_fname = NULL;
+               }
                read_static_rt( ctx, 0 );                       // drive for not there coverage
        }
 
@@ -571,6 +576,10 @@ static int rt_test( ) {
        ctx->rtable = NULL;
        ctx->my_name = strdup( "my_host_name" );                // set up to load a rtable
        ctx->my_ip = strdup( "192.168.1.30" );
+       if( ctx && ctx->seed_rt_fname != NULL ) {
+               free( ctx->seed_rt_fname );
+               ctx->seed_rt_fname = NULL;
+       }
        gen_rt( ctx );                                                                  // generate a route table with meid entries and hang off ctx
 
        mbuf = rmr_alloc_msg( ctx, 2048 );               //  buffer to play with
index d15239a..cd3f14e 100644 (file)
@@ -45,6 +45,7 @@ static inline uta_ctx_t *mk_dummy_ctx() {
        }
 
        memset( ctx, 0, sizeof( *ctx ) );
+       ctx->snarf_rt_fd = -1;
 
        return ctx;
 }
@@ -70,6 +71,7 @@ static inline uta_ctx_t *mk_dummy_ctx() {
        ctx->si_ctx = malloc( 1024 );
        ctx->my_name = strdup( "hostname1" );
        ctx->my_ip = strdup( "123.45.67.89" );
+       ctx->snarf_rt_fd = -1;
 
        ctx->rtgate = (pthread_mutex_t *) malloc( sizeof( *ctx->rtgate ) );
     if( ctx->rtgate != NULL ) {
index 79b413f..5748ca1 100644 (file)
@@ -45,6 +45,7 @@ static void gen_rt( uta_ctx_t* ctx ) {
        int             fd;
        char*   rt_stuff;               // strings for the route table
 
+ctx->flags |= 0x08;
        fd = open( "utesting.rt", O_WRONLY | O_CREAT, 0600 );
        if( fd < 0 ) {
                fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );