diff options
-rw-r--r-- | src/gtest/trex_stateless_gtest.cpp | 11 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.cpp | 382 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.h | 81 |
3 files changed, 427 insertions, 47 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp index 1ad03c63..02e84c0f 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -55,30 +55,27 @@ TEST_F(basic_vm, vm0) { ); vm.Dump(stdout); - - } TEST_F(basic_vm, vm1) { StreamVm vm; - vm.set_packet_size(512); - - vm.add_instruction( new StreamVmInstructionFixChecksumIpv4(20) ); + vm.add_instruction( new StreamVmInstructionFixChecksumIpv4(14) ); vm.add_instruction( new StreamVmInstructionFlowMan( "var1",1, StreamVmInstructionFlowMan::FLOW_VAR_OP_INC,0,1,7 ) ); - vm.add_instruction( new StreamVmInstructionWriteToPkt( "var1",14, 0,true) + vm.add_instruction( new StreamVmInstructionWriteToPkt( "var1",26, 0,true) ); - vm.Dump(stdout); + vm.set_packet_size(128); vm.compile_next(); } + ////////////////////////////////////////////////////// diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp index 09a49111..82ba8bc5 100644 --- a/src/stateless/cp/trex_stream_vm.cpp +++ b/src/stateless/cp/trex_stream_vm.cpp @@ -24,6 +24,8 @@ limitations under the License. #include <assert.h> #include <iostream> #include <trex_stateless.h> +#include <common/Network/Packet/IPHeader.h> +#include <common/basic_utils.h> @@ -129,6 +131,12 @@ void StreamVm::add_instruction(StreamVmInstruction *inst) { m_inst_list.push_back(inst); } +const StreamDPVmInstructions & +StreamVm::get_dp_instruction_buffer(){ + return m_instructions; +} + + const std::vector<StreamVmInstruction *> & StreamVm::get_instruction_list() { return m_inst_list; @@ -144,6 +152,14 @@ bool StreamVm::var_add(const std::string &var_name,VmFlowVarRec & var){ } +uint16_t StreamVm::get_var_offset(const std::string &var_name){ + VmFlowVarRec var; + bool res=var_lookup(var_name,var); + assert(res); + return (var.m_offset); +} + + bool StreamVm::var_lookup(const std::string &var_name,VmFlowVarRec & var){ auto search = m_flow_var_offset.find(var_name); @@ -206,6 +222,18 @@ void StreamVm::alloc_bss(){ m_bss=(uint8_t *)malloc(m_cur_var_offset); } +void StreamVm::clean_max_field_cnt(){ + m_max_field_update=0; +} + +void StreamVm::add_field_cnt(uint16_t new_cnt){ + + if ( new_cnt > m_max_field_update) { + m_max_field_update = new_cnt; + } +} + + void StreamVm::free_bss(){ if (m_bss) { free(m_bss); @@ -216,6 +244,199 @@ void StreamVm::free_bss(){ void StreamVm::build_program(){ + /* build the commands into a buffer */ + m_instructions.clear(); + clean_max_field_cnt(); + uint32_t ins_id=0; + + for (auto inst : m_inst_list) { + StreamVmInstruction::instruction_type_t ins_type=inst->get_instruction_type(); + + /* itFIX_IPV4_CS */ + if (ins_type == StreamVmInstruction::itFIX_IPV4_CS) { + StreamVmInstructionFixChecksumIpv4 *lpFix =(StreamVmInstructionFixChecksumIpv4 *)inst; + + add_field_cnt(lpFix->m_pkt_offset +12); + + if ( (lpFix->m_pkt_offset + IPV4_HDR_LEN) > m_pkt_size ) { + + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix ipv4 command offset " << lpFix->m_pkt_offset << " is too high relative to packet size "<< m_pkt_size; + err(ss.str()); + } + + StreamDPOpIpv4Fix ipv_fix; + ipv_fix.m_offset = lpFix->m_pkt_offset; + ipv_fix.m_op = StreamDPVmInstructions::ditFIX_IPV4_CS; + m_instructions.add_command(&ipv_fix,sizeof(ipv_fix)); + } + + + /* flow man */ + if (ins_type == StreamVmInstruction::itFLOW_MAN) { + StreamVmInstructionFlowMan *lpMan =(StreamVmInstructionFlowMan *)inst; + + + if (lpMan->m_size_bytes == 1 ){ + + uint8_t op; + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ + op = StreamDPVmInstructions::ditINC8 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ + op = StreamDPVmInstructions::ditDEC8 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ + op = StreamDPVmInstructions::ditRANDOM8 ; + } + + StreamDPOpFlowVar8 fv8; + fv8.m_op = op; + fv8.m_flow_offset = get_var_offset(lpMan->m_var_name); + fv8.m_min_val = (uint8_t)lpMan->m_min_value; + fv8.m_max_val = (uint8_t)lpMan->m_max_value; + m_instructions.add_command(&fv8,sizeof(fv8)); + } + + if (lpMan->m_size_bytes == 2 ){ + uint8_t op; + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ + op = StreamDPVmInstructions::ditINC16 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ + op = StreamDPVmInstructions::ditDEC16 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ + op = StreamDPVmInstructions::ditRANDOM16 ; + } + + StreamDPOpFlowVar16 fv16; + fv16.m_op = op; + fv16.m_flow_offset = get_var_offset(lpMan->m_var_name); + fv16.m_min_val = (uint16_t)lpMan->m_min_value; + fv16.m_max_val = (uint16_t)lpMan->m_max_value; + m_instructions.add_command(&fv16,sizeof(fv16)); + } + + if (lpMan->m_size_bytes == 4 ){ + uint8_t op; + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ + op = StreamDPVmInstructions::ditINC32 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ + op = StreamDPVmInstructions::ditDEC32 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ + op = StreamDPVmInstructions::ditRANDOM32 ; + } + + StreamDPOpFlowVar32 fv32; + fv32.m_op = op; + fv32.m_flow_offset = get_var_offset(lpMan->m_var_name); + fv32.m_min_val = (uint32_t)lpMan->m_min_value; + fv32.m_max_val = (uint32_t)lpMan->m_max_value; + m_instructions.add_command(&fv32,sizeof(fv32)); + } + + if (lpMan->m_size_bytes == 8 ){ + uint8_t op; + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ + op = StreamDPVmInstructions::ditINC64 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ + op = StreamDPVmInstructions::ditDEC64 ; + } + + if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ + op = StreamDPVmInstructions::ditRANDOM64 ; + } + + StreamDPOpFlowVar32 fv64; + fv64.m_op = op; + fv64.m_flow_offset = get_var_offset(lpMan->m_var_name); + fv64.m_min_val = (uint64_t)lpMan->m_min_value; + fv64.m_max_val = (uint64_t)lpMan->m_max_value; + m_instructions.add_command(&fv64,sizeof(fv64)); + } + } + + if (ins_type == StreamVmInstruction::itPKT_WR) { + StreamVmInstructionWriteToPkt *lpPkt =(StreamVmInstructionWriteToPkt *)inst; + + VmFlowVarRec var; + 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 << "'" ; + err(ss.str()); + } + + if (lpPkt->m_pkt_offset + var.m_instruction->m_size_bytes > m_pkt_size ) { + std::stringstream ss; + ss << "instruction id '" << ins_id << "' packet write with packet_offset " << lpPkt->m_pkt_offset + var.m_instruction->m_size_bytes << " bigger than packet size "<< m_pkt_size; + err(ss.str()); + } + add_field_cnt(lpPkt->m_pkt_offset + var.m_instruction->m_size_bytes); + + + uint8_t op_size=var.m_instruction->m_size_bytes; + uint8_t flow_offset=get_var_offset(lpPkt->m_flow_var_name); + + if (op_size == 1) { + StreamDPOpPktWr8 pw8; + pw8.m_op = StreamDPVmInstructions::itPKT_WR8; + pw8.m_flags =0; + pw8.m_offset =flow_offset; + pw8.m_pkt_offset = lpPkt->m_pkt_offset; + pw8.m_val_offset = (int8_t)lpPkt->m_add_value; + m_instructions.add_command(&pw8,sizeof(pw8)); + } + + if (op_size == 2) { + StreamDPOpPktWr16 pw16; + pw16.m_op = StreamDPVmInstructions::itPKT_WR16; + pw16.m_flags =0; + pw16.m_offset =flow_offset; + pw16.m_pkt_offset = lpPkt->m_pkt_offset; + pw16.m_val_offset = (int16_t)lpPkt->m_add_value; + m_instructions.add_command(&pw16,sizeof(pw16)); + } + + if (op_size == 4) { + StreamDPOpPktWr32 pw32; + pw32.m_op = StreamDPVmInstructions::itPKT_WR32; + pw32.m_flags =0; + pw32.m_offset =flow_offset; + pw32.m_pkt_offset = lpPkt->m_pkt_offset; + pw32.m_val_offset = (int32_t)lpPkt->m_add_value; + m_instructions.add_command(&pw32,sizeof(pw32)); + } + + if (op_size == 8) { + StreamDPOpPktWr64 pw64; + pw64.m_op = StreamDPVmInstructions::itPKT_WR64; + pw64.m_flags =0; + pw64.m_offset =flow_offset; + pw64.m_pkt_offset = lpPkt->m_pkt_offset; + pw64.m_val_offset = (int64_t)lpPkt->m_add_value; + m_instructions.add_command(&pw64,sizeof(pw64)); + } + + } + + ins_id++; + } } @@ -265,14 +486,16 @@ void StreamVm::compile_next() { build_program(); - + if ( get_max_packet_update_offset() >svMAX_PACKET_OFFSET_CHANGE ){ + std::stringstream ss; + ss << "maximum offset is" << get_max_packet_update_offset() << " bigger than maximum " <<svMAX_PACKET_OFFSET_CHANGE; + err(ss.str()); + } } bool StreamVm::compile() { - //m_flow_var_offset - return (false); } @@ -285,12 +508,28 @@ StreamVm::~StreamVm() { void StreamVm::Dump(FILE *fd){ + fprintf(fd," instructions \n"); uint32_t cnt=0; for (auto inst : m_inst_list) { fprintf(fd," [%04lu] : ",(ulong)cnt); inst->Dump(fd); cnt++; } + + if ( get_bss_size() ) { + fprintf(fd," BSS \n"); + utl_DumpBuffer(fd,get_bss_ptr(),get_bss_size(),0); + } + + if ( m_instructions.get_program_size() > 0 ){ + fprintf(fd," RAW instructions \n"); + m_instructions.Dump(fd); + } +} + + +void StreamDPVmInstructions::clear(){ + m_inst_list.clear(); } @@ -314,46 +553,159 @@ uint32_t StreamDPVmInstructions::get_program_size(){ void StreamDPVmInstructions::Dump(FILE *fd){ - //uint8_t * p=get_program(); - - + uint8_t * p=get_program(); + + + uint32_t program_size = get_program_size(); + uint8_t * p_end=p+program_size; + + StreamDPOpFlowVar8 *lpv8; + StreamDPOpFlowVar16 *lpv16; + StreamDPOpFlowVar32 *lpv32; + StreamDPOpFlowVar64 *lpv64; + StreamDPOpIpv4Fix *lpIpv4Fix; + StreamDPOpPktWr8 *lpw8; + StreamDPOpPktWr16 *lpw16; + StreamDPOpPktWr32 *lpw32; + StreamDPOpPktWr64 *lpw64; + + while ( p < p_end) { + uint8_t op_code=*p; + switch (op_code) { + + case ditINC8 : + lpv8 =(StreamDPOpFlowVar8 *)p; + lpv8->dump(fd,"INC8"); + p+=sizeof(StreamDPOpFlowVar8); + break; + case ditINC16 : + lpv16 =(StreamDPOpFlowVar16 *)p; + lpv16->dump(fd,"INC16"); + p+=sizeof(StreamDPOpFlowVar16); + break; + case ditINC32 : + lpv32 =(StreamDPOpFlowVar32 *)p; + lpv32->dump(fd,"INC32"); + p+=sizeof(StreamDPOpFlowVar32); + break; + case ditINC64 : + lpv64 =(StreamDPOpFlowVar64 *)p; + lpv64->dump(fd,"INC64"); + p+=sizeof(StreamDPOpFlowVar64); + break; + + case ditDEC8 : + lpv8 =(StreamDPOpFlowVar8 *)p; + lpv8->dump(fd,"DEC8"); + p+=sizeof(StreamDPOpFlowVar8); + break; + case ditDEC16 : + lpv16 =(StreamDPOpFlowVar16 *)p; + lpv16->dump(fd,"DEC16"); + p+=sizeof(StreamDPOpFlowVar16); + break; + case ditDEC32 : + lpv32 =(StreamDPOpFlowVar32 *)p; + lpv32->dump(fd,"DEC32"); + p+=sizeof(StreamDPOpFlowVar32); + break; + case ditDEC64 : + lpv64 =(StreamDPOpFlowVar64 *)p; + lpv64->dump(fd,"DEC64"); + p+=sizeof(StreamDPOpFlowVar64); + break; + + case ditRANDOM8 : + lpv8 =(StreamDPOpFlowVar8 *)p; + lpv8->dump(fd,"RAND8"); + p+=sizeof(StreamDPOpFlowVar8); + break; + case ditRANDOM16 : + lpv16 =(StreamDPOpFlowVar16 *)p; + lpv16->dump(fd,"RAND16"); + p+=sizeof(StreamDPOpFlowVar16); + break; + case ditRANDOM32 : + lpv32 =(StreamDPOpFlowVar32 *)p; + lpv32->dump(fd,"RAND32"); + p+=sizeof(StreamDPOpFlowVar32); + break; + case ditRANDOM64 : + lpv64 =(StreamDPOpFlowVar64 *)p; + lpv64->dump(fd,"RAND64"); + p+=sizeof(StreamDPOpFlowVar64); + break; + + case ditFIX_IPV4_CS : + lpIpv4Fix =(StreamDPOpIpv4Fix *)p; + lpIpv4Fix->dump(fd,"Ipv4Fix"); + p+=sizeof(StreamDPOpIpv4Fix); + break; + + case itPKT_WR8 : + lpw8 =(StreamDPOpPktWr8 *)p; + lpw8->dump(fd,"Wr8"); + p+=sizeof(StreamDPOpPktWr8); + break; + + case itPKT_WR16 : + lpw16 =(StreamDPOpPktWr16 *)p; + lpw16->dump(fd,"Wr16"); + p+=sizeof(StreamDPOpPktWr16); + break; + + case itPKT_WR32 : + lpw32 =(StreamDPOpPktWr32 *)p; + lpw32->dump(fd,"Wr32"); + p+=sizeof(StreamDPOpPktWr32); + break; + + case itPKT_WR64 : + lpw64 =(StreamDPOpPktWr64 *)p; + lpw64->dump(fd,"Wr64"); + p+=sizeof(StreamDPOpPktWr64); + break; + default: + assert(0); + } + }; } -void StreamDPOpFlowVar8::dump(FILE *fd){ +void StreamDPOpFlowVar8::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val); } -void StreamDPOpFlowVar16::dump(FILE *fd){ +void StreamDPOpFlowVar16::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val); } -void StreamDPOpFlowVar32::dump(FILE *fd){ +void StreamDPOpFlowVar32::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val); } -void StreamDPOpFlowVar64::dump(FILE *fd){ +void StreamDPOpFlowVar64::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val); } -void StreamDPOpPktWr8::dump(FILE *fd){ +void StreamDPOpPktWr8::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flags,(ulong)m_pkt_offset,(ulong)m_offset); } -void StreamDPOpPktWr16::dump(FILE *fd){ +void StreamDPOpPktWr16::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flags,(ulong)m_pkt_offset,(ulong)m_offset); } -void StreamDPOpPktWr32::dump(FILE *fd){ +void StreamDPOpPktWr32::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flags,(ulong)m_pkt_offset,(ulong)m_offset); } -void StreamDPOpPktWr64::dump(FILE *fd){ +void StreamDPOpPktWr64::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu, %lu , %lu \n", (ulong)m_op,(ulong)m_flags,(ulong)m_pkt_offset,(ulong)m_offset); } -void StreamDPOpIpv4Fix::dump(FILE *fd){ +void StreamDPOpIpv4Fix::dump(FILE *fd,std::string opt){ fprintf(fd," %lu, %lu \n", (ulong)m_op,(ulong)m_offset); } diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h index ed0e2087..795f5aa1 100644 --- a/src/stateless/cp/trex_stream_vm.h +++ b/src/stateless/cp/trex_stream_vm.h @@ -39,7 +39,7 @@ struct StreamDPOpFlowVar8 { uint8_t m_min_val; uint8_t m_max_val; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)) ; @@ -49,7 +49,7 @@ struct StreamDPOpFlowVar16 { uint16_t m_min_val; uint16_t m_max_val; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)) ; @@ -59,7 +59,7 @@ struct StreamDPOpFlowVar32 { uint32_t m_min_val; uint32_t m_max_val; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)) ; @@ -69,49 +69,50 @@ struct StreamDPOpFlowVar64 { uint64_t m_min_val; uint64_t m_max_val; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)) ; -struct StreamDPOpPktWr8 { +struct StreamDPOpPktWrBase { uint8_t m_op; uint8_t m_flags; - uint8_t m_offset; + uint8_t m_offset; +} __attribute__((packed)) ; + + +struct StreamDPOpPktWr8 : public StreamDPOpPktWrBase { + int8_t m_val_offset; uint16_t m_pkt_offset; + public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)) ; -struct StreamDPOpPktWr16 { - uint8_t m_op; - uint8_t m_flags; +struct StreamDPOpPktWr16 : public StreamDPOpPktWrBase { uint16_t m_pkt_offset; - uint16_t m_offset; + int16_t m_val_offset; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)); -struct StreamDPOpPktWr32 { - uint8_t m_op; - uint8_t m_flags; +struct StreamDPOpPktWr32 : public StreamDPOpPktWrBase { uint16_t m_pkt_offset; - uint32_t m_offset; + int32_t m_val_offset; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)); -struct StreamDPOpPktWr64 { - uint8_t m_op; - uint8_t m_flags; +struct StreamDPOpPktWr64 : public StreamDPOpPktWrBase { uint16_t m_pkt_offset; - uint32_t m_offset; + int64_t m_val_offset; + public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)); @@ -119,7 +120,7 @@ struct StreamDPOpIpv4Fix { uint8_t m_op; uint32_t m_offset; public: - void dump(FILE *fd); + void dump(FILE *fd,std::string opt); } __attribute__((packed)); @@ -153,6 +154,7 @@ public: public: + void clear(); void add_command(void *buffer,uint16_t size); uint8_t * get_program(); uint32_t get_program_size(); @@ -211,7 +213,7 @@ public: virtual void Dump(FILE *fd); public: - uint16_t m_pkt_offset; + uint16_t m_pkt_offset; /* the offset of IPv4 header from the start of the packet */ }; /** @@ -335,7 +337,8 @@ public: class StreamVm { public: enum STREAM_VM { - svMAX_FLOW_VAR = 64 /* maximum flow varible */ + svMAX_FLOW_VAR = 64, /* maximum flow varible */ + svMAX_PACKET_OFFSET_CHANGE = 512 }; @@ -370,6 +373,23 @@ public: */ const std::vector<StreamVmInstruction *> & get_instruction_list(); + const StreamDPVmInstructions & get_dp_instruction_buffer(); + + uint16_t get_bss_size(){ + return (m_cur_var_offset ); + } + + uint8_t * get_bss_ptr(){ + return (m_bss ); + } + + + uint16_t get_max_packet_update_offset(){ + return ( m_max_field_update ); + } + + + /** * compile the VM * return true of success, o.w false @@ -396,6 +416,8 @@ private: void var_clear_table(); bool var_add(const std::string &var_name,VmFlowVarRec & var); + + uint16_t get_var_offset(const std::string &var_name); void build_flow_var_table() ; @@ -407,13 +429,22 @@ private: void free_bss(); +private: + + void clean_max_field_cnt(); + + void add_field_cnt(uint16_t new_cnt); private: uint16_t m_pkt_size; uint16_t m_cur_var_offset; + uint16_t m_max_field_update; /* the location of the last byte that is going to be changed in the packet */ + std::vector<StreamVmInstruction *> m_inst_list; std::unordered_map<std::string, VmFlowVarRec> m_flow_var_offset; uint8_t * m_bss; + + StreamDPVmInstructions m_instructions; }; |