From 4f91be3fe9e751b8f264efe989f367976f3349ad Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 29 Sep 2016 13:59:46 +0300 Subject: Add FE Instruction to fix TCP/UDP Payload checksum using hardware offload engine --- .../trex_stl_lib/trex_stl_packet_builder_scapy.py | 74 ++++++++++++++ src/common/Network/Packet/IPHeader.h | 9 ++ src/common/Network/Packet/TcpHeader.h | 4 + src/common/Network/Packet/UdpHeader.h | 7 ++ src/pal/linux/mbuf.h | 44 ++++++++ src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 15 ++- src/rpc-server/commands/trex_rpc_cmds.h | 2 + src/stateless/cp/trex_stream_vm.cpp | 111 +++++++++++++++++++++ src/stateless/cp/trex_stream_vm.h | 111 ++++++++++++++++++++- src/stateless/dp/trex_stateless_dp_core.cpp | 1 + 10 files changed, 374 insertions(+), 4 deletions(-) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py index 079a8d3c..a868dbe8 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py @@ -258,6 +258,20 @@ class CTRexVmInsFixIpv4(CTRexVmInsBase): self.pkt_offset = offset validate_type('offset', offset, int) +class CTRexVmInsFixHwCs(CTRexVmInsBase): + L4_TYPE_UDP = 11 + L4_TYPE_TCP = 13 + + def __init__(self, l2_len,l3_len,l4_type): + super(CTRexVmInsFixHwCs, self).__init__("fix_checksum_hw") + self.l2_len = l2_len + validate_type('l2_len', l2_len, int) + self.l3_len = l3_len + validate_type('l3_len', l3_len, int) + self.l4_type = l4_type + validate_type('l4_type', l4_type, int) + + class CTRexVmInsFlowVar(CTRexVmInsBase): #TBD add more validation tests @@ -764,6 +778,66 @@ class STLVmFlowVarRepetableRandom(CTRexVmDescBase): def get_var_name(self): return [self.name] +class STLVmFixChecksumHw(CTRexVmDescBase): + def __init__(self, l3_offset,l4_offset,l4_type): + """ + Fix Ipv4 header checksum and TCP/UDP checksum using hardware assist. + Use this if the packet header has changed or data payload has changed as it is necessary to change the checksum. + This instruction won't work on virtual interfaces only on Physical ports + + Support the following packets + + Ether()/(IPv4|IPv6)/(UDP|TCP) + Ether()/(IPv4|IPv6)/(UDP|TCP) + SomeTunnel()/(IPv4|IPv6)/(UDP|TCP) + SomeTunnel()/(IPv4|IPv6)/(UDP|TCP) + + + :parameters: + l3_offset : offset in bytes + **IPv4/IPv6 header** offset from packet start. It is **not** the offset of the checksum field itself. + in could be string in case of scapy packet. format IP[:[id]] + + l4_offset : offset in bytes to UDP/TCP header + + l4_type : CTRexVmInsFixHwCs.L4_TYPE_UDP or CTRexVmInsFixHwCs.L4_TYPE_TCP + + + .. code-block:: python + + # Example2 + + pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025) + + # by offset + STLVmFixChecksumHw(l3_offset=14,l4_offset=14+20,l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP) + + # in case of scapy packet can be defined by header name + STLVmFixChecksumHw(l3_offset="IP",l4_offset="UDP",l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP) + + # string for second "IP" header in the packet is IP:1 + STLVmFixChecksumHw(offset="IP:1") + + """ + + super(STLVmFixChecksumHw, self).__init__() + self.l3_offset = l3_offset; # could be a name of offset + self.l4_offset = l4_offset; # could be a name of offset + self.l4_type = l4_type + + + def get_obj (self): + return CTRexVmInsFixHwCs(self.l2_len,self.l3_len,self.l4_type); + + def compile(self,parent): + if type(self.l3_offset)==str: + self.l2_len = parent._pkt_layer_offset(self.l3_offset); + if type(self.l4_offset)==str: + self.l4_offset = parent._pkt_layer_offset(self.l4_offset); + + assert self.l4_offset >= self.l2_len+8, 'l4_offset should be higher than l3_offset offset' + self.l3_len = self.l4_offset - self.l2_len; + class STLVmFixIpv4(CTRexVmDescBase): def __init__(self, offset): diff --git a/src/common/Network/Packet/IPHeader.h b/src/common/Network/Packet/IPHeader.h index dd9f5096..da9ba52c 100755 --- a/src/common/Network/Packet/IPHeader.h +++ b/src/common/Network/Packet/IPHeader.h @@ -142,6 +142,15 @@ public: inline void updateCheckSum (); inline void updateCheckSum2(uint8_t* data1, uint16_t len1, uint8_t* data2 , uint16_t len2); + inline void ClearCheckSum(){ + myChecksum=0; + } + inline void SetCheckSumRaw(uint16_t Checksum){ + + myChecksum = Checksum; + } + + inline void swapSrcDest (); diff --git a/src/common/Network/Packet/TcpHeader.h b/src/common/Network/Packet/TcpHeader.h index 97575a60..38732998 100755 --- a/src/common/Network/Packet/TcpHeader.h +++ b/src/common/Network/Packet/TcpHeader.h @@ -92,6 +92,10 @@ public: void setChecksum (uint16_t); uint16_t getChecksum (); + inline void setChecksumRaw (uint16_t data){ + myChecksum = data; + } + void setUrgentOffset (uint16_t); uint16_t getUrgentOffset (); diff --git a/src/common/Network/Packet/UdpHeader.h b/src/common/Network/Packet/UdpHeader.h index 43d08fe1..67942a1c 100755 --- a/src/common/Network/Packet/UdpHeader.h +++ b/src/common/Network/Packet/UdpHeader.h @@ -20,6 +20,8 @@ limitations under the License. #include "PacketHeaderBase.h" #include "IPHeader.h" +#define UDP_HEADER_LEN 8 + class UDPHeader { @@ -56,6 +58,11 @@ public: inline bool isCheckSumOk(IPHeader *ipHeader); inline uint16_t calcCheckSum(IPHeader *ipHeader); + inline void setChecksumRaw (uint16_t data){ + myChecksum = data; + } + + inline void swapSrcDest(); //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/pal/linux/mbuf.h b/src/pal/linux/mbuf.h index e7819148..2996b514 100755 --- a/src/pal/linux/mbuf.h +++ b/src/pal/linux/mbuf.h @@ -63,6 +63,8 @@ struct rte_mbuf { uint32_t magic2; uint16_t refcnt_reserved; uint64_t ol_flags; /**< Offload features. */ + uint16_t l2_len; + uint16_t l3_len; } ; typedef struct rte_mempool rte_mempool_t; @@ -75,6 +77,48 @@ inline unsigned rte_mempool_count(rte_mempool_t *mp){ return (10); } +static inline uint16_t +rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr, uint64_t ol_flags){ + return (0); +} + +static inline uint16_t +rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr, uint64_t ol_flags){ + return(0); +} + + +#define PKT_TX_L4_NO_CKSUM (0ULL << 52) /**< Disable L4 cksum of TX pkt. */ +#define PKT_TX_TCP_CKSUM (1ULL << 52) /**< TCP cksum of TX pkt. computed by NIC. */ +#define PKT_TX_SCTP_CKSUM (2ULL << 52) /**< SCTP cksum of TX pkt. computed by NIC. */ +#define PKT_TX_UDP_CKSUM (3ULL << 52) /**< UDP cksum of TX pkt. computed by NIC. */ +#define PKT_TX_L4_MASK (3ULL << 52) /**< Mask for L4 cksum offload request. */ + +/** + * Offload the IP checksum in the hardware. The flag PKT_TX_IPV4 should + * also be set by the application, although a PMD will only check + * PKT_TX_IP_CKSUM. + * - set the IP checksum field in the packet to 0 + * - fill the mbuf offload information: l2_len, l3_len + */ +#define PKT_TX_IP_CKSUM (1ULL << 54) + +/** + * Packet is IPv4. This flag must be set when using any offload feature + * (TSO, L3 or L4 checksum) to tell the NIC that the packet is an IPv4 + * packet. If the packet is a tunneled packet, this flag is related to + * the inner headers. + */ +#define PKT_TX_IPV4 (1ULL << 55) + +/** + * Packet is IPv6. This flag must be set when using an offload feature + * (TSO or L4 checksum) to tell the NIC that the packet is an IPv6 + * packet. If the packet is a tunneled packet, this flag is related to + * the inner headers. + */ +#define PKT_TX_IPV6 (1ULL << 56) + void rte_pktmbuf_free(rte_mbuf_t *m); diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index f0eadef6..9bb2d552 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -211,6 +211,15 @@ TrexRpcCmdAddStream::parse_rate(const Json::Value &rate, std::unique_ptr &stream, Json::Value &result) { + uint16_t l2_len = parse_uint16(inst, "l2_len", result); + uint16_t l3_len = parse_uint16(inst, "l3_len", result); + uint16_t l4_type = parse_uint16(inst, "l4_type", result); + + stream->m_vm.add_instruction(new StreamVmInstructionFixHwChecksum(l2_len,l3_len,l4_type)); +} + void TrexRpcCmdAddStream::parse_vm_instr_checksum(const Json::Value &inst, std::unique_ptr &stream, Json::Value &result) { @@ -462,13 +471,17 @@ TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, std::unique_ptr for (int i = 0; i < instructions.size(); i++) { const Json::Value & inst = parse_object(instructions, i, result); - auto vm_types = {"fix_checksum_ipv4", "flow_var", "write_flow_var","tuple_flow_var","trim_pkt_size","write_mask_flow_var","flow_var_rand_limit"}; + auto vm_types = {"fix_checksum_hw", "fix_checksum_ipv4", "flow_var", "write_flow_var","tuple_flow_var","trim_pkt_size","write_mask_flow_var","flow_var_rand_limit"}; std::string vm_type = parse_choice(inst, "type", vm_types, result); // checksum instruction if (vm_type == "fix_checksum_ipv4") { parse_vm_instr_checksum(inst, stream, result); + } else if (vm_type == "fix_checksum_hw") { + + parse_vm_instr_checksum_hw(inst, stream, result); + } else if (vm_type == "flow_var") { parse_vm_instr_flow_var(inst, stream, result); diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 506bd2c9..a68796ae 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -104,6 +104,8 @@ std::unique_ptr allocate_new_stream(const Json::Value §ion, uint void validate_stream(const std::unique_ptr &stream, Json::Value &result); void parse_vm(const Json::Value &vm, std::unique_ptr &stream, Json::Value &result); void parse_vm_instr_checksum(const Json::Value &inst, std::unique_ptr &stream, Json::Value &result); +void parse_vm_instr_checksum_hw(const Json::Value &inst, std::unique_ptr &stream, Json::Value &result); + void parse_vm_instr_flow_var(const Json::Value &inst, std::unique_ptr &stream, Json::Value &result); void parse_vm_instr_flow_var_rand_limit(const Json::Value &inst, std::unique_ptr &stream, Json::Value &result); void check_min_max(uint8_t flow_var_size, uint64_t init_value,uint64_t step,uint64_t min_value,uint64_t max_value,Json::Value &result); diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp index c157ab06..a9935759 100644 --- a/src/stateless/cp/trex_stream_vm.cpp +++ b/src/stateless/cp/trex_stream_vm.cpp @@ -92,6 +92,9 @@ void StreamVmInstructionFixChecksumIpv4::Dump(FILE *fd){ fprintf(fd," fix_check_sum , %lu \n",(ulong)m_pkt_offset); } +void StreamVmInstructionFixHwChecksum::Dump(FILE *fd){ + fprintf(fd," fix_hw_cs %lu:%lu \n",(ulong)m_l2_len,(ulong)m_l3_len); +} void StreamVmInstructionFlowMan::sanity_check_valid_size(uint32_t ins_id,StreamVm *lp){ uint8_t valid[]={1,2,4,8}; @@ -633,6 +636,101 @@ void StreamVm::build_program(){ for (auto inst : m_inst_list) { StreamVmInstruction::instruction_type_t ins_type=inst->get_instruction_type(); + if (ins_type == StreamVmInstruction::itFIX_HW_CS) { + StreamVmInstructionFixHwChecksum *lpFix =(StreamVmInstructionFixHwChecksum *)inst; + if (lpFix->m_l2_len < 14 ) { + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw offset l2 " << lpFix->m_l2_len << " is lower than 14 "; + err(ss.str()); + } + + if (lpFix->m_l3_len < 8 ) { + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw offset l3 " << lpFix->m_l3_len << " is lower than 8 "; + err(ss.str()); + } + + uint16_t total_l4_offset = lpFix->m_l2_len + lpFix->m_l3_len; + uint16_t l4_header_size =0; + + + assert( m_pkt ); + + bool packet_is_ipv4=true; + IPHeader * ipv4= (IPHeader *)(m_pkt+lpFix->m_l2_len); + if (ipv4->getVersion() ==4 ) { + packet_is_ipv4=true; + if (ipv4->getSize() != lpFix->m_l3_len ) { + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw command IPv4 header size is not valid " << ipv4->getSize() ; + err(ss.str()); + } + if ( !((ipv4->getNextProtocol() == IPHeader::Protocol::TCP) || + (ipv4->getNextProtocol() == IPHeader::Protocol::UDP) ) ) { + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw command L4 should be TCP or UDP " << ipv4->getSize() ; + err(ss.str()); + } + }else{ + if (ipv4->getVersion() ==6) { + /* pass */ + }else{ + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw command should work on IPv4 or IPv6 " ; + err(ss.str()); + } + } + + StreamDPOpHwCsFix ipv_fix; + ipv_fix.m_l2_len = lpFix->m_l2_len; + ipv_fix.m_l3_len = lpFix->m_l3_len; + ipv_fix.m_op = StreamDPVmInstructions::ditFIX_HW_CS; + + if (packet_is_ipv4) { + if ( ipv4->getNextProtocol() == IPHeader::Protocol::TCP ){ + /* Ipv4 TCP */ + ipv_fix.m_ol_flags = (PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM); + l4_header_size = TCP_HEADER_LEN; + }else{ + assert( ipv4->getNextProtocol() == IPHeader::Protocol::UDP ); + /* Ipv4 UDP */ + ipv_fix.m_ol_flags = (PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM); + l4_header_size = UDP_HEADER_LEN; + } + }else{ + /* Ipv6*/ + /* in this case we need to scan the Ipv6 headers */ + /* TBD replace with parser of IPv6 function */ + if ( lpFix->m_l4_type==StreamVmInstructionFixHwChecksum::L4_TYPE_TCP ){ + ipv_fix.m_ol_flags = (PKT_TX_IPV6 | PKT_TX_TCP_CKSUM); + l4_header_size = TCP_HEADER_LEN; + }else{ + if ( lpFix->m_l4_type==StreamVmInstructionFixHwChecksum::L4_TYPE_UDP ){ + ipv_fix.m_ol_flags = (PKT_TX_IPV6 | PKT_TX_UDP_CKSUM); + l4_header_size = UDP_HEADER_LEN; + }else{ + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw command offsets should be TCP or UDP "; + err(ss.str()); + } + } + } + + if ( (total_l4_offset + l4_header_size) > m_pkt_size ) { + + std::stringstream ss; + ss << "instruction id '" << ins_id << "' fix hw command offsets " << (total_l4_offset + l4_header_size) << " is too high relative to packet size "<< m_pkt_size; + err(ss.str()); + } + + /* add the instruction*/ + m_instructions.add_command(&ipv_fix,sizeof(ipv_fix)); + + /* mark R/W of the packet */ + add_field_cnt(total_l4_offset + l4_header_size); + + } + /* itFIX_IPV4_CS */ if (ins_type == StreamVmInstruction::itFIX_IPV4_CS) { StreamVmInstructionFixChecksumIpv4 *lpFix =(StreamVmInstructionFixChecksumIpv4 *)inst; @@ -1233,6 +1331,8 @@ void StreamDPVmInstructions::Dump(FILE *fd){ StreamDPOpFlowVar32Step *lpv32s; StreamDPOpFlowVar64Step *lpv64s; + StreamDPOpHwCsFix *lpHwFix; + StreamDPOpIpv4Fix *lpIpv4Fix; StreamDPOpPktWr8 *lpw8; StreamDPOpPktWr16 *lpw16; @@ -1273,6 +1373,12 @@ void StreamDPVmInstructions::Dump(FILE *fd){ p+=sizeof(StreamDPOpFlowVar64Step); break; + case ditFIX_HW_CS : + lpHwFix =(StreamDPOpHwCsFix *)p; + lpHwFix->dump(fd,"HwFixCs"); + p+=sizeof(StreamDPOpHwCsFix); + break; + case ditFIX_IPV4_CS : lpIpv4Fix =(StreamDPOpIpv4Fix *)p; lpIpv4Fix->dump(fd,"Ipv4Fix"); @@ -1438,6 +1544,11 @@ void StreamDPOpPktWrMask::dump(FILE *fd,std::string opt){ } +void StreamDPOpHwCsFix::dump(FILE *fd,std::string opt){ + fprintf(fd," %10s op:%lu, lens: %lu,%lu \n", opt.c_str(),(ulong)m_op,(ulong)m_l2_len,(ulong)m_l3_len); + +} + void StreamDPOpIpv4Fix::dump(FILE *fd,std::string opt){ fprintf(fd," %10s op:%lu, offset: %lu \n", opt.c_str(),(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 4f500a44..c9f459d3 100644 --- a/src/stateless/cp/trex_stream_vm.h +++ b/src/stateless/cp/trex_stream_vm.h @@ -27,9 +27,16 @@ limitations under the License. #include #include #include +#include +#include #include "pal_utl.h" #include "mbuf.h" +#ifdef RTE_DPDK +# include +#endif /* RTE_DPDK */ + + class StreamVmInstructionFlowClient; /** @@ -535,6 +542,46 @@ public: } __attribute__((packed)); +/* fix checksum using hardware */ +struct StreamDPOpHwCsFix { + uint8_t m_op; + uint16_t m_l2_len; + uint16_t m_l3_len; + uint64_t m_ol_flags; + +public: + void dump(FILE *fd,std::string opt); + void run(uint8_t * pkt_base,rte_mbuf_t * m){ + IPHeader * ipv4 = (IPHeader *)(pkt_base+m_l2_len); + union { + TCPHeader * tcp; + UDPHeader * udp; + } u; + + u.tcp = (TCPHeader*)(pkt_base+m_l3_len); + /* set the mbuf info */ + m->l2_len = m_l2_len; + m->l3_len = m_l3_len; + m->ol_flags |= m_ol_flags; + if (m_ol_flags & PKT_TX_IPV4 ){ /* splitting to 4 instructions didn't improve performance .. */ + ipv4->ClearCheckSum(); + if (m_ol_flags & PKT_TX_TCP_CKSUM ){ + u.tcp->setChecksumRaw(rte_ipv4_phdr_cksum((struct ipv4_hdr *)ipv4,m_ol_flags)); + }else{ + u.udp->setChecksumRaw(rte_ipv4_phdr_cksum((struct ipv4_hdr *)ipv4,m_ol_flags)); + } + }else{ + if (m_ol_flags & PKT_TX_TCP_CKSUM ){ + u.tcp->setChecksumRaw(rte_ipv6_phdr_cksum((struct ipv6_hdr *)ipv4,m_ol_flags)); + }else{ + u.udp->setChecksumRaw(rte_ipv6_phdr_cksum((struct ipv6_hdr *)ipv4,m_ol_flags)); + } + } + } +} __attribute__((packed)); + + + /* flow varible of Client command */ struct StreamDPFlowClient { uint32_t cur_ip; @@ -654,6 +701,7 @@ public: ditRANDOM64 , ditFIX_IPV4_CS , + ditFIX_HW_CS , itPKT_WR8 , itPKT_WR16 , @@ -701,8 +749,8 @@ private: class StreamDPVmInstructionsRunner { public: StreamDPVmInstructionsRunner(){ - m_new_pkt_size=0;; - + m_new_pkt_size=0; + m_m=0; } void slow_commands(uint8_t op_code, @@ -719,12 +767,23 @@ public: inline uint16_t get_new_pkt_size(){ return (m_new_pkt_size); } + + inline void set_mbuf(rte_mbuf_t * mbuf){ + m_m=mbuf; + } + inline rte_mbuf_t * get_mbuf(){ + return (m_m); + } + + private: uint16_t m_new_pkt_size; + rte_mbuf_t * m_m; }; typedef union ua_ { + StreamDPOpHwCsFix * lpHwFix; StreamDPOpIpv4Fix *lpIpv4Fix; StreamDPOpPktWr8 *lpw8; StreamDPOpPktWr16 *lpw16; @@ -856,6 +915,12 @@ inline void StreamDPVmInstructionsRunner::run(uint32_t * per_thread_random, p+=sizeof(StreamDPOpIpv4Fix); break; + case StreamDPVmInstructions::ditFIX_HW_CS : + ua.lpHwFix =(StreamDPOpHwCsFix *)p; + ua.lpHwFix->run(pkt,m_m); + p+=sizeof(StreamDPOpHwCsFix); + break; + case StreamDPVmInstructions::itPKT_WR8 : ua.lpw8 =(StreamDPOpPktWr8 *)p; ua.lpw8->wr(flow_var,pkt); @@ -911,7 +976,8 @@ public: itFLOW_CLIENT = 7 , itPKT_SIZE_CHANGE = 8, itPKT_WR_MASK = 9, - itFLOW_RAND_LIMIT = 10 /* random with limit & seed */ + itFLOW_RAND_LIMIT = 10, /* random with limit & seed */ + itFIX_HW_CS =11 }; @@ -1001,6 +1067,44 @@ public: uint16_t m_pkt_offset; /* the offset of IPv4 header from the start of the packet */ }; +/** + * fix Ipv6/Ipv6 TCP/UDP L4 headers using HW ofload to fix only IPv6 header use software it would be faster + * + */ +class StreamVmInstructionFixHwChecksum : public StreamVmInstruction { +public: + + enum { + L4_TYPE_UDP = 11, + L4_TYPE_TCP = 13, + + }; /* for flags */ + + StreamVmInstructionFixHwChecksum(uint16_t l2_len, + uint16_t l3_len, + uint8_t l4_type) { + m_l2_len = l2_len; + m_l3_len = l3_len; + m_l4_type = l4_type; + } + + virtual instruction_type_t get_instruction_type() const { + return ( StreamVmInstruction::itFIX_HW_CS); + } + + virtual void Dump(FILE *fd); + + virtual StreamVmInstruction * clone() { + return new StreamVmInstructionFixHwChecksum(m_l2_len,m_l3_len,m_l4_type); + } + +public: + uint16_t m_l2_len; + uint16_t m_l3_len; + uint8_t m_l4_type; /* should be either TCP or UDP - TBD could be fixed and calculated by a scan function */ +}; + + /** * flow manipulation instruction * @@ -1214,6 +1318,7 @@ public: }; + /** * write flow-write-mask to packet, hhaim * diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index bea52d42..857ac8f9 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -345,6 +345,7 @@ rte_mbuf_t * CGenNodeStateless::alloc_node_with_vm(){ /* run the VM program */ StreamDPVmInstructionsRunner runner; + runner.set_mbuf(m); runner.run( (uint32_t*)m_vm_flow_var, m_vm_program_size, -- cgit 1.2.3-korg