Add FE Instruction to fix TCP/UDP Payload checksum using hardware offload engine
authorHanoh Haim <[email protected]>
Thu, 29 Sep 2016 10:59:46 +0000 (13:59 +0300)
committerHanoh Haim <[email protected]>
Thu, 29 Sep 2016 13:50:29 +0000 (16:50 +0300)
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
src/common/Network/Packet/IPHeader.h
src/common/Network/Packet/TcpHeader.h
src/common/Network/Packet/UdpHeader.h
src/pal/linux/mbuf.h
src/rpc-server/commands/trex_rpc_cmd_stream.cpp
src/rpc-server/commands/trex_rpc_cmds.h
src/stateless/cp/trex_stream_vm.cpp
src/stateless/cp/trex_stream_vm.h
src/stateless/dp/trex_stateless_dp_core.cpp

index 079a8d3..a868dbe 100755 (executable)
@@ -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):
index dd9f509..da9ba52 100755 (executable)
@@ -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                     ();
 
 
index 97575a6..3873299 100755 (executable)
@@ -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 ();
 
index 43d08fe..67942a1 100755 (executable)
@@ -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();
 
 ////////////////////////////////////////////////////////////////////////////////////////
index e781914..2996b51 100755 (executable)
@@ -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);
index f0eadef..9bb2d55 100644 (file)
@@ -211,6 +211,15 @@ TrexRpcCmdAddStream::parse_rate(const Json::Value &rate, std::unique_ptr<TrexStr
 
 }
 
+void 
+TrexRpcCmdAddStream::parse_vm_instr_checksum_hw(const Json::Value &inst, std::unique_ptr<TrexStream> &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<TrexStream> &stream, Json::Value &result) {
 
@@ -462,13 +471,17 @@ TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, std::unique_ptr<TrexStream>
     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);
 
index 506bd2c..a68796a 100644 (file)
@@ -104,6 +104,8 @@ std::unique_ptr<TrexStream> allocate_new_stream(const Json::Value &section, uint
 void validate_stream(const std::unique_ptr<TrexStream> &stream, Json::Value &result);
 void parse_vm(const Json::Value &vm, std::unique_ptr<TrexStream> &stream, Json::Value &result);
 void parse_vm_instr_checksum(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result);
+void parse_vm_instr_checksum_hw(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result);
+
 void parse_vm_instr_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result);
 void parse_vm_instr_flow_var_rand_limit(const Json::Value &inst, std::unique_ptr<TrexStream> &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);
index c157ab0..a993575 100644 (file)
@@ -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);
 }
index 4f500a4..c9f459d 100644 (file)
@@ -27,9 +27,16 @@ limitations under the License.
 #include <unordered_map>
 #include <assert.h>
 #include <common/Network/Packet/IPHeader.h>
+#include <common/Network/Packet/UdpHeader.h>
+#include <common/Network/Packet/TcpHeader.h>
 #include "pal_utl.h"
 #include "mbuf.h"
 
+#ifdef RTE_DPDK
+#      include <rte_ip.h>
+#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
  * 
index bea52d4..857ac8f 100644 (file)
@@ -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,