summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-09-12 17:29:33 +0300
committerHanoh Haim <hhaim@cisco.com>2016-09-13 19:37:29 +0300
commitc754842a0ec39e704bb92ffc21bb4624db576496 (patch)
tree20f29b88ebff3bb70b1c24bfba488607bfc51efe
parent138686f389fe48139ddc4a57ac5de363e71b38e7 (diff)
add rand limit instruction DP
-rw-r--r--scripts/exp/pcap_remote_dual-0.erfbin51000 -> 51000 bytes
-rw-r--r--src/gtest/trex_stateless_gtest.cpp11
-rw-r--r--src/stateless/cp/trex_stream_vm.cpp309
-rw-r--r--src/stateless/cp/trex_stream_vm.h193
4 files changed, 454 insertions, 59 deletions
diff --git a/scripts/exp/pcap_remote_dual-0.erf b/scripts/exp/pcap_remote_dual-0.erf
index e93e0e8b..c4dd69fb 100644
--- a/scripts/exp/pcap_remote_dual-0.erf
+++ b/scripts/exp/pcap_remote_dual-0.erf
Binary files differ
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 9e111b61..10bd0aac 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -179,6 +179,17 @@ TEST_F(basic_vm, pkt_size) {
}
+TEST_F(basic_vm, vm_rand_limit0) {
+
+ StreamVm vm;
+
+ vm.add_instruction( new StreamVmInstructionFlowRandLimit( "var1",1,100,0x1234) );
+
+ vm.Dump(stdout);
+}
+
+
+
/* start/stop/stop back to back */
TEST_F(basic_vm, vm0) {
diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp
index 9e4fbe1c..1f3f8ab4 100644
--- a/src/stateless/cp/trex_stream_vm.cpp
+++ b/src/stateless/cp/trex_stream_vm.cpp
@@ -132,6 +132,33 @@ void StreamVmInstructionFlowMan::sanity_check_valid_range(uint32_t ins_id,Stream
+uint8_t StreamVmInstructionFlowMan::bss_init_value(uint8_t *p){
+ uint8_t res;
+
+ switch (m_size_bytes) {
+ case 1:
+ *p=(uint8_t)get_bss_init_value();
+ res=1;
+ break;
+ case 2:
+ *((uint16_t*)p)=(uint16_t)get_bss_init_value();
+ res=2;
+ break;
+ case 4:
+ *((uint32_t*)p)=(uint32_t)get_bss_init_value();
+ res=4;
+ break;
+ case 8:
+ *((uint64_t*)p)=(uint64_t)get_bss_init_value();
+ res=8;
+ break;
+ default:
+ assert(0);
+ }
+ return(res);
+}
+
+
void StreamVmInstructionFlowMan::sanity_check(uint32_t ins_id,StreamVm *lp){
sanity_check_valid_size(ins_id,lp);
@@ -140,6 +167,89 @@ void StreamVmInstructionFlowMan::sanity_check(uint32_t ins_id,StreamVm *lp){
}
+
+void StreamVmInstructionFlowRandLimit::Dump(FILE *fd){
+ fprintf(fd," flow_var_rand_limit , %s ,%lu, ",m_var_name.c_str(),(ulong)m_size_bytes);
+ fprintf(fd," (%lu:%lu:%lu) \n",m_limit,(ulong)m_size_bytes,(ulong)m_seed);
+}
+
+void StreamVmInstructionFlowRandLimit::sanity_check(uint32_t ins_id,StreamVm *lp){
+ sanity_check_valid_size(ins_id,lp);
+}
+
+
+uint8_t StreamVmInstructionFlowRandLimit::bss_init_value(uint8_t *p){
+ uint8_t res;
+
+ typedef union ua_ {
+ RandMemBss8 *lpv8;
+ RandMemBss16 *lpv16;
+ RandMemBss32 *lpv32;
+ RandMemBss64 *lpv64;
+ } ua_t ;
+
+ ua_t u;
+
+
+ switch (m_size_bytes) {
+ case 1:
+ u.lpv8=(RandMemBss8 *)p;
+ u.lpv8->m_seed=m_seed;
+ res=sizeof(RandMemBss8);
+ break;
+ case 2:
+ u.lpv16=(RandMemBss16 *)p;
+ u.lpv16->m_seed=m_seed;
+ res=sizeof(RandMemBss16);
+ break;
+ case 4:
+ u.lpv32=(RandMemBss32 *)p;
+ u.lpv32->m_seed=m_seed;
+ res=sizeof(RandMemBss32);
+ break;
+ case 8:
+ u.lpv64=(RandMemBss64 *)p;
+ u.lpv64->m_seed=m_seed;
+ res=sizeof(RandMemBss64);
+ break;
+ default:
+ assert(0);
+ }
+ return (res);
+}
+
+
+void StreamVmInstructionFlowRandLimit::sanity_check_valid_size(uint32_t ins_id,StreamVm *lp){
+ uint8_t valid[]={1,2,4,8};
+ int i;
+ for (i=0; i<sizeof(valid)/sizeof(valid[0]); i++) {
+ if (valid[i]==m_size_bytes) {
+ uint64_t limit = (1ULL<<((i+1)*8))-1;
+ /* check limit */
+ if ( m_limit == 0) {
+ std::stringstream ss;
+ ss << "instruction id '" << ins_id << "' limit " << m_limit << " can't be zero " ;
+ lp->err(ss.str());
+ }
+
+ if ( m_limit > limit) {
+ std::stringstream ss;
+ ss << "instruction id '" << ins_id << "' limit " << m_limit << " is bigger than size " << m_size_bytes ;
+ lp->err(ss.str());
+ }
+ return;
+ }
+ }
+
+ std::stringstream ss;
+
+ ss << "instruction id '" << ins_id << "' has non valid length " << m_size_bytes ;
+
+ lp->err(ss.str());
+}
+
+
+
void StreamVmInstructionWriteMaskToPkt::Dump(FILE *fd){
fprintf(fd," flow_var:%s, offset:%lu, cast_size:%lu, mask:0x%lx, shift:%ld, add:%ld, is_big:%lu \n",m_flow_var_name.c_str(),(ulong)m_pkt_offset,(ulong)m_pkt_cast_size,(ulong)m_mask,(long)m_shift,(long)m_add_value,(ulong)(m_is_big_endian?1:0));
}
@@ -186,6 +296,31 @@ void StreamVmInstructionFlowClient::Dump(FILE *fd){
}
+uint8_t StreamVmInstructionFlowClient::bss_init_value(uint8_t *p){
+
+ if (m_client_min>0) {
+ *((uint32_t*)p)=(uint32_t)(m_client_min-1);
+ }else{
+ *((uint32_t*)p)=(uint32_t)m_client_min;
+ }
+
+ p+=4;
+
+ if (is_unlimited_flows() ) {
+ *((uint16_t*)p)=StreamDPOpClientsUnLimit::CLIENT_UNLIMITED_MIN_PORT;
+ }else{
+ *((uint16_t*)p)=(uint16_t)m_port_min;
+ }
+
+ p+=2;
+
+ *((uint32_t*)p)=0;
+ p+=4;
+
+ return (get_flow_var_size());
+}
+
+
/***************************
@@ -307,6 +442,30 @@ void StreamVm::build_flow_var_table() {
}
}
+ if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_RAND_LIMIT ){
+
+ StreamVmInstructionFlowRandLimit * ins_man=(StreamVmInstructionFlowRandLimit *)inst;
+
+ /* check that instruction is valid */
+ ins_man->sanity_check(ins_id,this);
+
+ VmFlowVarRec var;
+ /* if this is the first time */
+ if ( var_lookup( ins_man->m_var_name,var) == true){
+ std::stringstream ss;
+ ss << "instruction id '" << ins_id << "' flow variable name " << ins_man->m_var_name << " already exists";
+ err(ss.str());
+ }else{
+
+ var.m_offset=m_cur_var_offset;
+ var.m_ins.m_ins_flow_rand_limit = ins_man;
+ var.m_size_bytes = ins_man->m_size_bytes; /* used for write*/
+ var_add(ins_man->m_var_name,var);
+ m_cur_var_offset += ins_man->m_size_bytes*2 + sizeof(uint32_t) ; /* see RandMemBss8 types */
+ }
+ }
+
+
if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_CLIENT ){
StreamVmInstructionFlowClient * ins_man=(StreamVmInstructionFlowClient *)inst;
@@ -358,7 +517,7 @@ void StreamVm::build_flow_var_table() {
/* limit the flow var size */
if (m_cur_var_offset > StreamVm::svMAX_FLOW_VAR ) {
std::stringstream ss;
- ss << "too many flow varibles current size is :" << m_cur_var_offset << " maximum support is " << StreamVm::svMAX_FLOW_VAR;
+ ss << "too many flow variables current size is :" << m_cur_var_offset << " maximum support is " << StreamVm::svMAX_FLOW_VAR;
err(ss.str());
}
ins_id++;
@@ -378,16 +537,23 @@ void StreamVm::build_flow_var_table() {
if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet size with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ;
+ ss << "instruction id '" << ins_id << "' packet size with no valid flow variable name '" << lpPkt->m_flow_var_name << "'" ;
err(ss.str());
}
if ( var.m_size_bytes != 2 ) {
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet size change should point to a flow varible with size 2 ";
+ ss << "instruction id '" << ins_id << "' packet size change should point to a flow variable with size 2 ";
err(ss.str());
}
+ if ( var.m_ins.m_ins_flowv->get_instruction_type() != StreamVmInstruction::itFLOW_MAN ){
+ std::stringstream ss;
+ ss << "instruction id '" << ins_id << "' packet size change should point to a simple flow variable type (Random/Client) types are not supported ";
+ err(ss.str());
+
+ }
+
if ( var.m_ins.m_ins_flowv->m_max_value > m_pkt_size) {
var.m_ins.m_ins_flowv->m_max_value =m_pkt_size;
}
@@ -495,6 +661,46 @@ void StreamVm::build_program(){
m_instructions.add_command(&ipv_fix,sizeof(ipv_fix));
}
+ if (ins_type == StreamVmInstruction::itFLOW_RAND_LIMIT) {
+ StreamVmInstructionFlowRandLimit *lpMan =(StreamVmInstructionFlowRandLimit *)inst;
+ var_cnt++;
+
+ if (lpMan->m_size_bytes == 1 ){
+ StreamDPOpFlowRandLimit8 fv8;
+ fv8.m_op = StreamDPVmInstructions::ditRAND_LIMIT8 ;
+ fv8.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv8.m_limit = (uint8_t)lpMan->m_limit;
+ fv8.m_seed = (uint32_t)lpMan->m_seed;
+ m_instructions.add_command(&fv8,sizeof(fv8));
+ }
+
+ if (lpMan->m_size_bytes == 2 ){
+ StreamDPOpFlowRandLimit16 fv16;
+ fv16.m_op = StreamDPVmInstructions::ditRAND_LIMIT16 ;
+ fv16.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv16.m_limit = (uint16_t)lpMan->m_limit;
+ fv16.m_seed = (uint32_t)lpMan->m_seed;
+ m_instructions.add_command(&fv16,sizeof(fv16));
+ }
+
+ if (lpMan->m_size_bytes == 4 ){
+ StreamDPOpFlowRandLimit32 fv32;
+ fv32.m_op = StreamDPVmInstructions::ditRAND_LIMIT32 ;
+ fv32.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv32.m_limit = (uint32_t)lpMan->m_limit;
+ fv32.m_seed = (uint32_t)lpMan->m_seed;
+ m_instructions.add_command(&fv32,sizeof(fv32));
+ }
+
+ if (lpMan->m_size_bytes == 8 ){
+ StreamDPOpFlowRandLimit64 fv64;
+ fv64.m_op = StreamDPVmInstructions::ditRAND_LIMIT64 ;
+ fv64.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv64.m_limit = lpMan->m_limit;
+ fv64.m_seed = (uint32_t)lpMan->m_seed;
+ m_instructions.add_command(&fv64,sizeof(fv64));
+ }
+ }
/* flow man */
if (ins_type == StreamVmInstruction::itFLOW_MAN) {
@@ -693,7 +899,7 @@ void StreamVm::build_program(){
if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet write with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ;
+ ss << "instruction id '" << ins_id << "' packet write with no valid flow variable name '" << lpPkt->m_flow_var_name << "'" ;
err(ss.str());
}
@@ -769,7 +975,7 @@ void StreamVm::build_program(){
if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet write with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ;
+ ss << "instruction id '" << ins_id << "' packet write with no valid flow variable name '" << lpPkt->m_flow_var_name << "'" ;
err(ss.str());
}
@@ -788,7 +994,7 @@ void StreamVm::build_program(){
uint8_t flags = (is_big?StreamDPOpPktWrMask::MASK_PKT_WR_IS_BIG:0);
uint8_t flow_offset = get_var_offset(lpPkt->m_flow_var_name);
- /* read LSB in case of 64bit varible */
+ /* read LSB in case of 64bit variable */
if (op_size == 8) {
op_size = 4;
if ( is_big ) {
@@ -850,13 +1056,13 @@ void StreamVm::build_program(){
if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet size with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ;
+ ss << "instruction id '" << ins_id << "' packet size with no valid flow variable name '" << lpPkt->m_flow_var_name << "'" ;
err(ss.str());
}
if ( var.m_size_bytes != 2 ) {
std::stringstream ss;
- ss << "instruction id '" << ins_id << "' packet size change should point to a flow varible with size 2 ";
+ ss << "instruction id '" << ins_id << "' packet size change should point to a flow variable with size 2 ";
err(ss.str());
}
@@ -890,54 +1096,7 @@ void StreamVm::build_bss() {
}
for (auto inst : m_inst_list) {
-
- if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_MAN ){
-
- StreamVmInstructionFlowMan * ins_man=(StreamVmInstructionFlowMan *)inst;
-
- switch (ins_man->m_size_bytes) {
- case 1:
- *p=(uint8_t)ins_man->get_bss_init_value();
- p+=1;
- break;
- case 2:
- *((uint16_t*)p)=(uint16_t)ins_man->get_bss_init_value();
- p+=2;
- break;
- case 4:
- *((uint32_t*)p)=(uint32_t)ins_man->get_bss_init_value();
- p+=4;
- break;
- case 8:
- *((uint64_t*)p)=(uint64_t)ins_man->get_bss_init_value();
- p+=8;
- break;
- default:
- assert(0);
- }
- }
-
- if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_CLIENT ){
-
- StreamVmInstructionFlowClient * ins_man=(StreamVmInstructionFlowClient *)inst;
- if (ins_man->m_client_min>0) {
- *((uint32_t*)p)=(uint32_t)(ins_man->m_client_min-1);
- }else{
- *((uint32_t*)p)=(uint32_t)ins_man->m_client_min;
- }
- p+=4;
-
- if (ins_man->is_unlimited_flows() ) {
- *((uint16_t*)p)=StreamDPOpClientsUnLimit::CLIENT_UNLIMITED_MIN_PORT;
- }else{
- *((uint16_t*)p)=(uint16_t)ins_man->m_port_min;
- }
- p+=2;
-
- *((uint32_t*)p)=0;
- p+=4;
- }
-
+ p+=inst->bss_init_value(p);
}
}
@@ -1391,6 +1550,23 @@ void StreamDPOpPktSizeChange::dump(FILE *fd,std::string opt){
}
+void StreamDPOpFlowRandLimit8::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s, flow_offset: %lu limit :%lu seed:%x \n", opt.c_str(),(ulong)m_flow_offset,(ulong)m_limit,m_seed);
+}
+
+void StreamDPOpFlowRandLimit16::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s, flow_offset: %lu limit :%lu seed:%x \n", opt.c_str(),(ulong)m_flow_offset,(ulong)m_limit,m_seed);
+}
+
+void StreamDPOpFlowRandLimit32::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s, flow_offset: %lu limit :%lu seed:%x \n", opt.c_str(),(ulong)m_flow_offset,(ulong)m_limit,m_seed);
+}
+
+void StreamDPOpFlowRandLimit64::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s, flow_offset: %lu limit :%lu seed:%x \n", opt.c_str(),(ulong)m_flow_offset,(ulong)m_limit,m_seed);
+}
+
+
void StreamDPOpPktWrMask::wr(uint8_t * flow_var_base,
@@ -1530,6 +1706,27 @@ void StreamDPVmInstructionsRunner::slow_commands(uint8_t op_code,
p+=sizeof(StreamDPOpPktWrMask);
break;
+ case StreamDPVmInstructions::ditRAND_LIMIT8:
+ ua.lpv_rl8 =(StreamDPOpFlowRandLimit8 *)p;
+ ua.lpv_rl8->run(flow_var);
+ p+=sizeof(StreamDPOpFlowRandLimit8);
+ break;
+ case StreamDPVmInstructions::ditRAND_LIMIT16:
+ ua.lpv_rl16 =(StreamDPOpFlowRandLimit16 *)p;
+ ua.lpv_rl16->run(flow_var);
+ p+=sizeof(StreamDPOpFlowRandLimit16);
+ break;
+ case StreamDPVmInstructions::ditRAND_LIMIT32:
+ ua.lpv_rl32 =(StreamDPOpFlowRandLimit32 *)p;
+ ua.lpv_rl32->run(flow_var);
+ p+=sizeof(StreamDPOpFlowRandLimit32);
+ break;
+ case StreamDPVmInstructions::ditRAND_LIMIT64:
+ ua.lpv_rl64 =(StreamDPOpFlowRandLimit64 *)p;
+ ua.lpv_rl64->run(flow_var);
+ p+=sizeof(StreamDPOpFlowRandLimit64);
+ break;
+
default:
assert(0);
}
diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index f55d33c1..6a83c5ea 100644
--- a/src/stateless/cp/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
@@ -75,6 +75,111 @@ static inline uint64_t vm_rand64(uint32_t * per_thread_seed)
class StreamVm;
+/* memory struct of rand_limit instruction */
+/*******************************************************/
+
+struct RandMemBss8 {
+ uint8_t m_val;
+ uint8_t m_cnt;
+ uint32_t m_seed;
+} __attribute__((packed));
+
+struct RandMemBss16 {
+ uint16_t m_val;
+ uint16_t m_cnt;
+ uint32_t m_seed;
+} __attribute__((packed));
+
+struct RandMemBss32 {
+ uint32_t m_val;
+ uint32_t m_cnt;
+ uint32_t m_seed;
+} __attribute__((packed));
+
+struct RandMemBss64 {
+ uint64_t m_val;
+ uint64_t m_cnt;
+ uint32_t m_seed;
+} __attribute__((packed));
+
+struct StreamDPOpFlowRandLimit8 {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint8_t m_limit;
+ uint32_t m_seed;
+public:
+ void dump(FILE *fd,std::string opt);
+ inline void run(uint8_t * flow_var) {
+ RandMemBss8 *p = (RandMemBss8 *)(flow_var + m_flow_offset);
+ if (p->m_cnt == m_limit){
+ p->m_seed = m_seed;
+ p->m_cnt=0;
+ }
+ uint32_t val = vm_rand16(&p->m_seed);
+ p->m_val= (uint8_t)(val);
+ p->m_cnt++;
+ }
+};
+
+struct StreamDPOpFlowRandLimit16 {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint16_t m_limit;
+ uint32_t m_seed;
+public:
+ void dump(FILE *fd,std::string opt);
+ inline void run(uint8_t * flow_var) {
+ RandMemBss16 *p = (RandMemBss16 *)(flow_var + m_flow_offset);
+ if (p->m_cnt == m_limit){
+ p->m_seed = m_seed;
+ p->m_cnt=0;
+ }
+ uint32_t val = vm_rand16(&p->m_seed);
+ p->m_val= (uint16_t)(val);
+ p->m_cnt++;
+ }
+
+};
+
+struct StreamDPOpFlowRandLimit32 {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint32_t m_limit;
+ uint32_t m_seed;
+public:
+ void dump(FILE *fd,std::string opt);
+ inline void run(uint8_t * flow_var) {
+ RandMemBss32 *p = (RandMemBss32 *)(flow_var + m_flow_offset);
+ if (p->m_cnt == m_limit){
+ p->m_seed = m_seed;
+ p->m_cnt=0;
+ }
+ uint32_t val = vm_rand32(&p->m_seed);
+ p->m_val= val;
+ p->m_cnt++;
+ }
+};
+
+struct StreamDPOpFlowRandLimit64 {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint64_t m_limit;
+ uint32_t m_seed;
+public:
+ void dump(FILE *fd,std::string opt);
+ inline void run(uint8_t * flow_var) {
+ RandMemBss64 *p = (RandMemBss64 *)(flow_var + m_flow_offset);
+ if (p->m_cnt == m_limit){
+ p->m_seed = m_seed;
+ p->m_cnt=0;
+ }
+ uint64_t val = vm_rand64(&p->m_seed);
+ p->m_val= val;
+ p->m_cnt++;
+ }
+};
+
+/*******************************************************/
/* in memory program */
@@ -609,8 +714,12 @@ public:
ditDEC16_STEP ,
ditDEC32_STEP ,
ditDEC64_STEP ,
- itPKT_WR_MASK
+ itPKT_WR_MASK ,
+ ditRAND_LIMIT8 ,
+ ditRAND_LIMIT16 ,
+ ditRAND_LIMIT32 ,
+ ditRAND_LIMIT64 ,
};
@@ -677,6 +786,11 @@ typedef union ua_ {
StreamDPOpFlowVar64Step *lpv64s;
StreamDPOpPktWrMask *lpwr_mask;
+ StreamDPOpFlowRandLimit8 *lpv_rl8;
+ StreamDPOpFlowRandLimit16 *lpv_rl16;
+ StreamDPOpFlowRandLimit32 *lpv_rl32;
+ StreamDPOpFlowRandLimit64 *lpv_rl64;
+
} ua_t ;
@@ -833,7 +947,9 @@ public:
itPKT_WR = 6,
itFLOW_CLIENT = 7 ,
itPKT_SIZE_CHANGE = 8,
- itPKT_WR_MASK = 9
+ itPKT_WR_MASK = 9,
+ itFLOW_RAND_LIMIT = 10 /* random with limit & seed */
+
};
@@ -851,6 +967,10 @@ public:
virtual bool is_splitable() const {
return false;
}
+ /* nothing to init */
+ virtual uint8_t bss_init_value(uint8_t *p){
+ return (0);
+ }
private:
static const std::string m_name;
@@ -935,6 +1055,10 @@ public:
return (m_max_value - m_min_value + 1);
}
+
+ virtual uint8_t bss_init_value(uint8_t *p);
+
+
/**
* different types of operations on the object
*/
@@ -999,9 +1123,9 @@ public:
}
private:
- void sanity_check_valid_range(uint32_t ins_id,StreamVm *lp);
void sanity_check_valid_size(uint32_t ins_id,StreamVm *lp);
void sanity_check_valid_opt(uint32_t ins_id,StreamVm *lp);
+ void sanity_check_valid_range(uint32_t ins_id,StreamVm *lp);
public:
@@ -1021,6 +1145,64 @@ public:
/**
+ * flow var random with limit
+ *
+ * @author hhaim 9/2016
+ */
+class StreamVmInstructionFlowRandLimit : public StreamVmInstructionVar {
+
+public:
+
+ virtual instruction_type_t get_instruction_type() const {
+ return ( StreamVmInstruction::itFLOW_RAND_LIMIT);
+ }
+
+ virtual bool is_valid_for_split() const {
+ return (false);
+ }
+
+
+ virtual uint64_t get_splitable_range() const {
+ return (1);
+ }
+
+
+ StreamVmInstructionFlowRandLimit(const std::string &var_name,
+ uint8_t size,
+ uint64_t limit,
+ int seed
+ ) : StreamVmInstructionVar(var_name) {
+
+ m_size_bytes = size;
+ m_seed = seed;
+ m_limit = limit;
+ }
+
+ virtual void Dump(FILE *fd);
+
+ void sanity_check(uint32_t ins_id,StreamVm *lp);
+
+ virtual uint8_t bss_init_value(uint8_t *p);
+
+ virtual StreamVmInstruction * clone() {
+ return new StreamVmInstructionFlowRandLimit(m_var_name,
+ m_size_bytes,
+ m_limit,
+ m_seed);
+ }
+
+private:
+ void sanity_check_valid_size(uint32_t ins_id,StreamVm *lp);
+
+public:
+
+ uint64_t m_limit;
+ int m_seed;
+ uint8_t m_size_bytes;
+};
+
+
+/**
* write flow-write-mask to packet, hhaim
*
* uint32_t var_tmp=(uint32_t )(flow_var_t size )flow_var;
@@ -1142,6 +1324,10 @@ public:
return get_ip_range();
}
+
+ virtual uint8_t bss_init_value(uint8_t *p);
+
+
bool is_unlimited_flows(){
return ( (m_flags & StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS ) ==
StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS );
@@ -1175,6 +1361,7 @@ public:
union {
StreamVmInstructionFlowMan * m_ins_flowv;
StreamVmInstructionFlowClient * m_ins_flow_client;
+ StreamVmInstructionFlowRandLimit * m_ins_flow_rand_limit;
} m_ins;
uint8_t m_size_bytes;
};