diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gtest/trex_stateless_gtest.cpp | 32 | ||||
-rwxr-xr-x | src/main_dpdk.cpp | 1 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.cpp | 309 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.h | 253 |
4 files changed, 592 insertions, 3 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp index ce97fbcb..9e15cb46 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -31,6 +31,38 @@ limitations under the License. #include <trex_rpc_server_api.h> #include <iostream> + +class basic_vm : public testing::Test { + protected: + virtual void SetUp() { + } + virtual void TearDown() { + } + public: +}; + + +/* start/stop/stop back to back */ +TEST_F(basic_vm, vm0) { + + StreamVm vm; + + vm.add_instruction( new StreamVmInstructionFixChecksumIpv4(20) ); + 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.Dump(stdout); + + +} + + +////////////////////////////////////////////////////// + + #define EXPECT_EQ_UINT32(a,b) EXPECT_EQ((uint32_t)(a),(uint32_t)(b)) diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index c17f32f3..f4acb344 100755 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -2299,6 +2299,7 @@ int CCoreEthIF::send_node(CGenNode * node){ int CCoreEthIF::update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ assert(p); assert(dir<2); + CCorePerPort * lp_port=&m_ports[dir]; uint8_t p_id=lp_port->m_port->get_port_id(); memcpy(p,CGlobalInfo::m_options.get_dst_src_mac_addr(p_id),12); diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp index 2e760ae9..d8d0dd2e 100644 --- a/src/stateless/cp/trex_stream_vm.cpp +++ b/src/stateless/cp/trex_stream_vm.cpp @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -19,6 +20,98 @@ See the License for the specific language governing permissions and limitations under the License. */ #include <trex_stream_vm.h> +#include <sstream> +#include <assert.h> +#include <iostream> +#include <trex_stateless.h> + + + + +void StreamVmInstructionFixChecksumIpv4::Dump(FILE *fd){ + fprintf(fd," fix_check_sum , %lu \n",(ulong)m_pkt_offset); +} + + +void StreamVmInstructionFlowMan::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) { + return; + } + } + + std::stringstream ss; + + ss << "instruction id '" << ins_id << "' has non valid length " << m_size_bytes ; + + lp->err(ss.str()); +} + +void StreamVmInstructionFlowMan::sanity_check_valid_opt(uint32_t ins_id,StreamVm *lp){ + uint8_t valid[]={FLOW_VAR_OP_INC, + FLOW_VAR_OP_DEC, + FLOW_VAR_OP_RANDOM}; + int i; + for (i=0; i<sizeof(valid)/sizeof(valid[0]); i++) { + if (valid[i]==m_op) { + return; + } + } + + std::stringstream ss; + + ss << "instruction id '" << ins_id << "' has non valid op " << (int)m_op ; + + lp->err(ss.str()); +} + +void StreamVmInstructionFlowMan::sanity_check_valid_range(uint32_t ins_id,StreamVm *lp){ + //TBD check that init,min,max in valid range +} + + + +void StreamVmInstructionFlowMan::sanity_check(uint32_t ins_id,StreamVm *lp){ + + sanity_check_valid_size(ins_id,lp); + sanity_check_valid_opt(ins_id,lp); + sanity_check_valid_range(ins_id,lp); +} + + +void StreamVmInstructionFlowMan::Dump(FILE *fd){ + fprintf(fd," flow_var , %s ,%lu, ",m_var_name.c_str(),(ulong)m_size_bytes); + + switch (m_op) { + + case FLOW_VAR_OP_INC : + fprintf(fd," INC ,"); + break; + case FLOW_VAR_OP_DEC : + fprintf(fd," DEC ,"); + break; + case FLOW_VAR_OP_RANDOM : + fprintf(fd," RANDOM ,"); + break; + default: + fprintf(fd," UNKNOWN,"); + break; + }; + + fprintf(fd," (%lu:%lu:%lu) \n",m_init_value,m_min_value,m_max_value); +} + + +void StreamVmInstructionWriteToPkt::Dump(FILE *fd){ + + fprintf(fd," write_pkt , %s ,%lu, add, %ld, big, %lu",m_flow_var_name.c_str(),(ulong)m_pkt_offset,(long)m_add_value,(ulong)(m_is_big_endian?1:0)); +} + + + + /*************************** * StreamVmInstruction @@ -41,8 +134,145 @@ StreamVm::get_instruction_list() { return m_inst_list; } +void StreamVm::var_clear_table(){ + m_flow_var_offset.clear(); +} + +bool StreamVm::var_add(const std::string &var_name,VmFlowVarRec & var){ + m_flow_var_offset[var_name] = var; + return (true); +} + + +bool StreamVm::var_lookup(const std::string &var_name,VmFlowVarRec & var){ + auto search = m_flow_var_offset.find(var_name); + + if (search != m_flow_var_offset.end()) { + var = search->second; + return true; + } else { + return false; + } +} + + + +void StreamVm::err(const std::string &err){ + throw TrexException("*** error: " + err); +} + + +void StreamVm::build_flow_var_table() { + + var_clear_table(); + m_cur_var_offset=0; + uint32_t ins_id=0; + /* scan all flow var instruction and build */ + for (auto inst : m_inst_list) { + if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_MAN ){ + + StreamVmInstructionFlowMan * ins_man=(StreamVmInstructionFlowMan *)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_instruction = ins_man; + var_add(ins_man->m_var_name,var); + m_cur_var_offset += ins_man->m_size_bytes; + + /* 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; + err(ss.str()); + } + } + } + ins_id++; + } + +} + +void StreamVm::alloc_bss(){ + free_bss(); + m_bss=(uint8_t *)malloc(m_cur_var_offset); +} + +void StreamVm::free_bss(){ + if (m_bss) { + free(m_bss); + m_bss=0; + } +} + + +void StreamVm::build_program(){ + +} + + +void StreamVm::build_bss() { + alloc_bss(); + uint8_t * p=(uint8_t *)m_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->m_init_value; + p+=1; + break; + case 2: + *((uint16_t*)p)=(uint16_t)ins_man->m_init_value; + p+=2; + break; + case 4: + *((uint32_t*)p)=(uint32_t)ins_man->m_init_value; + p+=4; + break; + case 8: + *((uint64_t*)p)=(uint64_t)ins_man->m_init_value; + p+=8; + break; + default: + assert(0); + } + } + } +} + + + +void StreamVm::compile_next() { + + /* build flow var offset table */ + build_flow_var_table() ; + + /* build init flow var memory */ + build_bss(); + + build_program(); + + +} + + bool StreamVm::compile() { - /* implement me */ + + //m_flow_var_offset + return (false); } @@ -52,3 +282,80 @@ StreamVm::~StreamVm() { } } + +void StreamVm::Dump(FILE *fd){ + uint32_t cnt=0; + for (auto inst : m_inst_list) { + fprintf(fd," [%04lu] : ",(ulong)cnt); + inst->Dump(fd); + cnt++; + } +} + + +void StreamDPVmInstructions::add_command(void *buffer,uint16_t size){ + int i; + uint8_t *p= (uint8_t *)buffer; + /* push byte by byte */ + for (i=0; i<size; i++) { + m_inst_list.push_back(*p); + p++; + } +} + +uint8_t * StreamDPVmInstructions::get_program(){ + return (&m_inst_list[0]); +} + +uint32_t StreamDPVmInstructions::get_program_size(){ + return (m_inst_list.size()); +} + +void StreamDPVmInstructions::Dump(FILE *fd){ + + //uint8_t * p=get_program(); + + +} + + +void StreamDPOpFlowVar8::dump(FILE *fd){ + 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){ + 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){ + 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){ + 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){ + 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){ + 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){ + 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){ + 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){ + 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 56edbcaf..ed0e2087 100644 --- a/src/stateless/cp/trex_stream_vm.h +++ b/src/stateless/cp/trex_stream_vm.h @@ -24,6 +24,148 @@ limitations under the License. #include <string> #include <stdint.h> #include <vector> +#include <unordered_map> + + + +class StreamVm; + + +/* in memory program */ + +struct StreamDPOpFlowVar8 { + uint8_t m_op; + uint8_t m_flow_offset; + uint8_t m_min_val; + uint8_t m_max_val; +public: + void dump(FILE *fd); + +} __attribute__((packed)) ; + +struct StreamDPOpFlowVar16 { + uint8_t m_op; + uint8_t m_flow_offset; + uint16_t m_min_val; + uint16_t m_max_val; +public: + void dump(FILE *fd); + +} __attribute__((packed)) ; + +struct StreamDPOpFlowVar32 { + uint8_t m_op; + uint8_t m_flow_offset; + uint32_t m_min_val; + uint32_t m_max_val; +public: + void dump(FILE *fd); + +} __attribute__((packed)) ; + +struct StreamDPOpFlowVar64 { + uint8_t m_op; + uint8_t m_flow_offset; + uint64_t m_min_val; + uint64_t m_max_val; +public: + void dump(FILE *fd); + +} __attribute__((packed)) ; + + +struct StreamDPOpPktWr8 { + uint8_t m_op; + uint8_t m_flags; + uint8_t m_offset; + uint16_t m_pkt_offset; +public: + void dump(FILE *fd); + +} __attribute__((packed)) ; + + +struct StreamDPOpPktWr16 { + uint8_t m_op; + uint8_t m_flags; + uint16_t m_pkt_offset; + uint16_t m_offset; +public: + void dump(FILE *fd); + +} __attribute__((packed)); + +struct StreamDPOpPktWr32 { + uint8_t m_op; + uint8_t m_flags; + uint16_t m_pkt_offset; + uint32_t m_offset; +public: + void dump(FILE *fd); + +} __attribute__((packed)); + +struct StreamDPOpPktWr64 { + uint8_t m_op; + uint8_t m_flags; + uint16_t m_pkt_offset; + uint32_t m_offset; +public: + void dump(FILE *fd); + +} __attribute__((packed)); + +struct StreamDPOpIpv4Fix { + uint8_t m_op; + uint32_t m_offset; +public: + void dump(FILE *fd); + +} __attribute__((packed)); + + +/* datapath instructions */ +class StreamDPVmInstructions { +public: + enum INS_TYPE { + ditINC8 , + ditINC16 , + ditINC32 , + ditINC64 , + + ditDEC8 , + ditDEC16 , + ditDEC32 , + ditDEC64 , + + ditRANDOM8 , + ditRANDOM16 , + ditRANDOM32 , + ditRANDOM64 , + + ditFIX_IPV4_CS , + + itPKT_WR8 , + itPKT_WR16 , + itPKT_WR32 , + itPKT_WR64 + }; + + +public: + void add_command(void *buffer,uint16_t size); + uint8_t * get_program(); + uint32_t get_program_size(); + + + void Dump(FILE *fd); + + +private: + std::vector<uint8_t> m_inst_list; +}; + + /** * interface for stream VM instruction @@ -32,8 +174,22 @@ limitations under the License. class StreamVmInstruction { public: + enum INS_TYPE { + itNONE = 0, + itFIX_IPV4_CS = 4, + itFLOW_MAN = 5, + itPKT_WR = 6 + }; + + typedef uint8_t instruction_type_t ; + + virtual instruction_type_t get_instruction_type()=0; + virtual ~StreamVmInstruction(); + virtual void Dump(FILE *fd)=0; + + private: static const std::string m_name; }; @@ -48,7 +204,13 @@ public: } -private: + virtual instruction_type_t get_instruction_type(){ + return ( StreamVmInstruction::itFIX_IPV4_CS); + } + + virtual void Dump(FILE *fd); + +public: uint16_t m_pkt_offset; }; @@ -61,6 +223,10 @@ class StreamVmInstructionFlowMan : public StreamVmInstruction { public: + virtual instruction_type_t get_instruction_type(){ + return ( StreamVmInstruction::itFLOW_MAN); + } + /** * different types of operations on the object */ @@ -85,7 +251,16 @@ public: } + virtual void Dump(FILE *fd); + + void sanity_check(uint32_t ins_id,StreamVm *lp); + 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); + +public: /* flow var name */ @@ -105,6 +280,16 @@ private: }; + +class VmFlowVarRec { +public: + uint32_t m_offset; + StreamVmInstructionFlowMan * m_instruction; +}; + + + + /** * write flow var to packet * @@ -121,7 +306,14 @@ public: m_pkt_offset(pkt_offset), m_add_value(add_value), m_is_big_endian(is_big_endian) {} -private: + + virtual instruction_type_t get_instruction_type(){ + return ( StreamVmInstruction::itPKT_WR); + } + + virtual void Dump(FILE *fd); + +public: /* flow var name to write */ std::string m_flow_var_name; @@ -142,6 +334,29 @@ private: */ class StreamVm { public: + enum STREAM_VM { + svMAX_FLOW_VAR = 64 /* maximum flow varible */ + }; + + + + StreamVm(){ + m_bss=0; + m_pkt_size=0; + m_cur_var_offset=0; + } + + + /* set packet size */ + void set_packet_size(uint16_t pkt_size){ + m_pkt_size = pkt_size; + } + + uint16_t get_packet_size(){ + return ( m_pkt_size); + } + + /** * add new instruction to the VM @@ -162,10 +377,44 @@ public: */ bool compile(); + + void compile_next(); + + ~StreamVm(); + void Dump(FILE *fd); + + /* raise exception */ + void err(const std::string &err); + +private: + + /* lookup for varible offset, */ + bool var_lookup(const std::string &var_name,VmFlowVarRec & var); + + void var_clear_table(); + + bool var_add(const std::string &var_name,VmFlowVarRec & var); + + void build_flow_var_table() ; + + void build_bss(); + + void build_program(); + + void alloc_bss(); + + void free_bss(); + + private: + uint16_t m_pkt_size; + uint16_t m_cur_var_offset; std::vector<StreamVmInstruction *> m_inst_list; + std::unordered_map<std::string, VmFlowVarRec> m_flow_var_offset; + uint8_t * m_bss; + }; #endif /* __TREX_STREAM_VM_API_H__ */ |