Ensure RT incremental update not applied early
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
diff --git a/CHANGES_CORE.txt b/CHANGES_CORE.txt
index 51c254c..cfa9ea3 100644
--- a/CHANGES_CORE.txt
+++ b/CHANGES_CORE.txt
@@ -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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a8220b4..a0d1b7f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -42,7 +42,7 @@
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" )
diff --git a/docs/rel-notes.rst b/docs/rel-notes.rst
index 7f29300..dadc465 100644
--- a/docs/rel-notes.rst
+++ b/docs/rel-notes.rst
@@ -22,6 +22,21 @@
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
----------------------------
diff --git a/src/rmr/common/include/rmr_agnostic.h b/src/rmr/common/include/rmr_agnostic.h
index 7e6fdda..0858fde 100644
--- a/src/rmr/common/include/rmr_agnostic.h
+++ b/src/rmr/common/include/rmr_agnostic.h
@@ -83,11 +83,11 @@
// 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.
diff --git a/src/rmr/common/src/rt_generic_static.c b/src/rmr/common/src/rt_generic_static.c
index 2e4b711..dcedb49 100644
--- a/src/rmr/common/src/rt_generic_static.c
+++ b/src/rmr/common/src/rt_generic_static.c
@@ -852,7 +852,7 @@
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 @@
}
if( snarf_fname == NULL ) {
+ rmr_vlog( RMR_VL_DEBUG, "cycle_snarf: no file to save in" );
return;
}
@@ -1018,6 +1019,7 @@
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 @@
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 @@
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)
diff --git a/src/rmr/common/src/rtc_static.c b/src/rmr/common/src/rtc_static.c
index 96f8330..10bc2a7 100644
--- a/src/rmr/common/src/rtc_static.c
+++ b/src/rmr/common/src/rtc_static.c
@@ -310,6 +310,7 @@
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)
diff --git a/src/rmr/si/include/rmr_si_private.h b/src/rmr/si/include/rmr_si_private.h
index ee71409..414c649 100644
--- a/src/rmr/si/include/rmr_si_private.h
+++ b/src/rmr/si/include/rmr_si_private.h
@@ -122,7 +122,7 @@
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 @@
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
diff --git a/src/rmr/si/src/rmr_si.c b/src/rmr/si/src/rmr_si.c
index b8bb2a0..8f88cf8 100644
--- a/src/rmr/si/src/rmr_si.c
+++ b/src/rmr/si/src/rmr_si.c
@@ -733,7 +733,7 @@
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 @@
return;
}
+ if( ctx->seed_rt_fname != NULL ) {
+ free( ctx->seed_rt_fname );
+ }
+
ctx->shutdown = 1;
SItp_stats( ctx->si_ctx ); // dump some interesting stats
diff --git a/test/rt_static_test.c b/test/rt_static_test.c
index 7a51bca..3bdd312 100644
--- a/test/rt_static_test.c
+++ b/test/rt_static_test.c
@@ -1,3 +1,4 @@
+
// : vi ts=4 sw=4 noet :
/*
==================================================================================
@@ -500,6 +501,10 @@
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 @@
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
diff --git a/test/test_ctx_support.c b/test/test_ctx_support.c
index d15239a..cd3f14e 100644
--- a/test/test_ctx_support.c
+++ b/test/test_ctx_support.c
@@ -45,6 +45,7 @@
}
memset( ctx, 0, sizeof( *ctx ) );
+ ctx->snarf_rt_fd = -1;
return ctx;
}
@@ -70,6 +71,7 @@
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 ) {
diff --git a/test/test_gen_rt.c b/test/test_gen_rt.c
index 79b413f..5748ca1 100644
--- a/test/test_gen_rt.c
+++ b/test/test_gen_rt.c
@@ -45,6 +45,7 @@
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" );