summaryrefslogtreecommitdiffstats
path: root/src/stateless/cp/trex_stream_vm.h
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-12-24 16:16:49 +0200
committerHanoh Haim <hhaim@cisco.com>2015-12-24 16:16:49 +0200
commit9d1cd91825d48a97ca0ea21fa7bd34900f6c7450 (patch)
treebb3c8585e29f7c6787d0f298e2d2655b21277855 /src/stateless/cp/trex_stream_vm.h
parent32bdea5fd30ffc378a213e773634015a5d5f255f (diff)
parentba297ed1bfdfbf61bc99fe7f75deb800b570c58e (diff)
merge vm random support
Diffstat (limited to 'src/stateless/cp/trex_stream_vm.h')
-rw-r--r--src/stateless/cp/trex_stream_vm.h301
1 files changed, 228 insertions, 73 deletions
diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index 9023c6b7..891e5b51 100644
--- a/src/stateless/cp/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
@@ -87,18 +87,20 @@ public:
void dump(FILE *fd,std::string opt);
inline void run_inc(uint8_t * flow_var) {
- uint8_t * p=(flow_var+m_flow_offset);
- *p=*p+1;
- if (*p>m_max_val) {
- *p=m_min_val;
+ uint8_t *p = (flow_var + m_flow_offset);
+ if (*p == m_max_val) {
+ *p = m_min_val;
+ } else {
+ *p = *p + 1;
}
}
inline void run_dec(uint8_t * flow_var) {
- uint8_t * p=(flow_var+m_flow_offset);
- *p=*p-1;
- if (*p<m_min_val) {
- *p=m_max_val;
+ uint8_t *p = (flow_var + m_flow_offset);
+ if (*p == m_min_val) {
+ *p = m_max_val;
+ } else {
+ *p = *p - 1;
}
}
@@ -119,18 +121,20 @@ public:
void dump(FILE *fd,std::string opt);
inline void run_inc(uint8_t * flow_var) {
- uint16_t * p=(uint16_t *)(flow_var+m_flow_offset);
- *p=*p+1;
- if (*p>m_max_val) {
- *p=m_min_val;
+ uint16_t *p = (uint16_t *)(flow_var + m_flow_offset);
+ if (*p == m_max_val) {
+ *p = m_min_val;
+ } else {
+ *p = *p + 1;
}
}
inline void run_dec(uint8_t * flow_var) {
- uint16_t * p=(uint16_t *)(flow_var+m_flow_offset);
- *p=*p-1;
- if (*p<m_min_val) {
- *p=m_max_val;
+ uint16_t *p = (uint16_t *)(flow_var + m_flow_offset);
+ if (*p == m_min_val) {
+ *p = m_max_val;
+ } else {
+ *p = *p - 1;
}
}
@@ -152,18 +156,20 @@ public:
void dump(FILE *fd,std::string opt);
inline void run_inc(uint8_t * flow_var) {
- uint32_t * p=(uint32_t *)(flow_var+m_flow_offset);
- *p=*p+1;
- if (*p>m_max_val) {
- *p=m_min_val;
+ uint32_t *p = (uint32_t *)(flow_var + m_flow_offset);
+ if (*p == m_max_val) {
+ *p = m_min_val;
+ } else {
+ *p = *p + 1;
}
}
inline void run_dec(uint8_t * flow_var) {
- uint32_t * p=(uint32_t *)(flow_var+m_flow_offset);
- *p=*p-1;
- if (*p<m_min_val) {
- *p=m_max_val;
+ uint32_t *p = (uint32_t *)(flow_var + m_flow_offset);
+ if (*p == m_min_val) {
+ *p = m_max_val;
+ } else {
+ *p = *p - 1;
}
}
@@ -183,18 +189,20 @@ public:
void dump(FILE *fd,std::string opt);
inline void run_inc(uint8_t * flow_var) {
- uint64_t * p=(uint64_t *)(flow_var+m_flow_offset);
- *p=*p+1;
- if (*p>m_max_val) {
- *p=m_min_val;
+ uint64_t *p = (uint64_t *)(flow_var + m_flow_offset);
+ if (*p == m_max_val) {
+ *p = m_min_val;
+ } else {
+ *p = *p + 1;
}
}
inline void run_dec(uint8_t * flow_var) {
- uint64_t * p=(uint64_t *)(flow_var+m_flow_offset);
- *p=*p-1;
- if (*p<m_min_val) {
- *p=m_max_val;
+ uint64_t *p = (uint64_t *)(flow_var + m_flow_offset);
+ if (*p == m_min_val) {
+ *p = m_max_val;
+ } else {
+ *p = *p - 1;
}
}
@@ -392,7 +400,7 @@ public:
class StreamDPVmInstructions {
public:
enum INS_TYPE {
- ditINC8 ,
+ ditINC8 =7 ,
ditINC16 ,
ditINC32 ,
ditINC64 ,
@@ -605,18 +613,57 @@ public:
typedef uint8_t instruction_type_t ;
- virtual instruction_type_t get_instruction_type()=0;
+ virtual instruction_type_t get_instruction_type() const = 0;
virtual ~StreamVmInstruction();
virtual void Dump(FILE *fd)=0;
+ virtual StreamVmInstruction * clone() = 0;
+
+ /* by default an instruction is not splitable */
+ virtual bool is_splitable() const {
+ return false;
+ }
private:
static const std::string m_name;
};
/**
+ * abstract class that defines a flow var
+ *
+ * @author imarom (23-Dec-15)
+ */
+class StreamVmInstructionVar : public StreamVmInstruction {
+
+public:
+
+ StreamVmInstructionVar(const std::string &var_name) : m_var_name(var_name) {
+
+ }
+
+ const std::string & get_var_name() {
+ return m_var_name;
+ }
+
+ virtual bool is_splitable() const {
+ return true;
+ }
+
+ /**
+ * what is the split range for this var
+ *
+ */
+ virtual uint64_t get_splitable_range() const = 0;
+
+public:
+
+ /* flow var name */
+ const std::string m_var_name;
+};
+
+/**
* fix checksum for ipv4
*
*/
@@ -626,12 +673,16 @@ public:
}
- virtual instruction_type_t get_instruction_type(){
+ virtual instruction_type_t get_instruction_type() const {
return ( StreamVmInstruction::itFIX_IPV4_CS);
}
virtual void Dump(FILE *fd);
+ virtual StreamVmInstruction * clone() {
+ return new StreamVmInstructionFixChecksumIpv4(m_pkt_offset);
+ }
+
public:
uint16_t m_pkt_offset; /* the offset of IPv4 header from the start of the packet */
};
@@ -641,14 +692,18 @@ public:
*
* @author imarom (07-Sep-15)
*/
-class StreamVmInstructionFlowMan : public StreamVmInstruction {
+class StreamVmInstructionFlowMan : public StreamVmInstructionVar {
public:
- virtual instruction_type_t get_instruction_type(){
+ virtual instruction_type_t get_instruction_type() const {
return ( StreamVmInstruction::itFLOW_MAN);
}
+ virtual uint64_t get_splitable_range() const {
+ return (m_max_value - m_min_value + 1);
+ }
+
/**
* different types of operations on the object
*/
@@ -658,25 +713,56 @@ public:
FLOW_VAR_OP_RANDOM
};
+
+ /**
+ * for BSS we take one previous value
+ * because the VM will be executed before writing to pkt
+ * so the init value is one step's advanced
+ *
+ */
+ uint64_t get_bss_init_value() const {
+ uint64_t init = m_init_value;
+
+ switch (m_op) {
+ case FLOW_VAR_OP_INC:
+ return (init == m_min_value ? m_max_value : (init - 1));
+
+ case FLOW_VAR_OP_DEC:
+ return (init == m_max_value ? m_min_value : (init + 1));
+
+ default:
+ return init;
+ }
+
+ }
+
StreamVmInstructionFlowMan(const std::string &var_name,
uint8_t size,
flow_var_op_e op,
uint64_t init_value,
uint64_t min_value,
- uint64_t max_value) :
- m_var_name(var_name),
- m_size_bytes(size),
- m_op(op),
- m_init_value(init_value),
- m_min_value(min_value),
- m_max_value(max_value) {
+ uint64_t max_value) : StreamVmInstructionVar(var_name) {
+ m_op = op;
+ m_size_bytes = size;
+ m_init_value = init_value;
+ m_min_value = min_value;
+ m_max_value = max_value;
}
virtual void Dump(FILE *fd);
void sanity_check(uint32_t ins_id,StreamVm *lp);
+ virtual StreamVmInstruction * clone() {
+ return new StreamVmInstructionFlowMan(m_var_name,
+ m_size_bytes,
+ m_op,
+ m_init_value,
+ m_min_value,
+ m_max_value);
+ }
+
private:
void sanity_check_valid_range(uint32_t ins_id,StreamVm *lp);
void sanity_check_valid_size(uint32_t ins_id,StreamVm *lp);
@@ -684,10 +770,6 @@ private:
public:
-
- /* flow var name */
- std::string m_var_name;
-
/* flow var size */
uint8_t m_size_bytes;
@@ -699,7 +781,6 @@ public:
uint64_t m_min_value;
uint64_t m_max_value;
-
};
@@ -708,7 +789,7 @@ public:
*
* @author hhaim
*/
-class StreamVmInstructionFlowClient : public StreamVmInstruction {
+class StreamVmInstructionFlowClient : public StreamVmInstructionVar {
public:
enum client_flags_e {
@@ -716,7 +797,7 @@ public:
};
- virtual instruction_type_t get_instruction_type(){
+ virtual instruction_type_t get_instruction_type() const {
return ( StreamVmInstruction::itFLOW_CLIENT);
}
@@ -728,8 +809,8 @@ public:
uint16_t port_max,
uint32_t limit_num_flows, /* zero means don't limit */
uint16_t flags
- ) {
- m_var_name = var_name;
+ ) : StreamVmInstructionVar(var_name) {
+
m_client_min = client_min_value;
m_client_max = client_max_value;
@@ -746,15 +827,34 @@ public:
return (4+2+4);
}
+ uint32_t get_ip_range() const {
+ return (m_client_max - m_client_min + 1);
+ }
+
+ uint16_t get_port_range() const {
+ return (m_port_max - m_port_min + 1);
+ }
+
+ virtual uint64_t get_splitable_range() const {
+ return get_ip_range();
+ }
+
bool is_unlimited_flows(){
return ( (m_flags & StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS ) ==
StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS );
}
-public:
+ virtual StreamVmInstruction * clone() {
+ return new StreamVmInstructionFlowClient(m_var_name,
+ m_client_min,
+ m_client_max,
+ m_port_min,
+ m_port_max,
+ m_limit_num_flows,
+ m_flags);
+ }
- /* flow var name */
- std::string m_var_name;
+public:
uint32_t m_client_min; // min ip
uint32_t m_client_max; // max ip
@@ -796,12 +896,19 @@ public:
m_add_value(add_value),
m_is_big_endian(is_big_endian) {}
- virtual instruction_type_t get_instruction_type(){
+ virtual instruction_type_t get_instruction_type() const {
return ( StreamVmInstruction::itPKT_WR);
}
virtual void Dump(FILE *fd);
+ virtual StreamVmInstruction * clone() {
+ return new StreamVmInstructionWriteToPkt(m_flow_var_name,
+ m_pkt_offset,
+ m_add_value,
+ m_is_big_endian);
+ }
+
public:
/* flow var name to write */
@@ -831,13 +938,15 @@ public:
m_bss_size=0;
m_program_size=0;
m_max_pkt_offset_change=0;
+ m_prefix_size = 0;
}
StreamVmDp( uint8_t * bss,
uint16_t bss_size,
uint8_t * prog,
uint16_t prog_size,
- uint16_t max_pkt_offset
+ uint16_t max_pkt_offset,
+ uint16_t prefix_size
){
if (bss) {
@@ -860,7 +969,9 @@ public:
m_program_ptr = NULL;
m_program_size=0;
}
- m_max_pkt_offset_change =max_pkt_offset;
+
+ m_max_pkt_offset_change = max_pkt_offset;
+ m_prefix_size = prefix_size;
}
~StreamVmDp(){
@@ -877,12 +988,13 @@ public:
}
StreamVmDp * clone() const {
- StreamVmDp * lp= new StreamVmDp(m_bss_ptr,
- m_bss_size,
- m_program_ptr,
- m_program_size,
- m_max_pkt_offset_change
- );
+ StreamVmDp * lp = new StreamVmDp(m_bss_ptr,
+ m_bss_size,
+ m_program_ptr,
+ m_program_size,
+ m_max_pkt_offset_change,
+ m_prefix_size
+ );
assert(lp);
return (lp);
}
@@ -915,12 +1027,21 @@ public:
return (m_max_pkt_offset_change);
}
+ uint16_t get_prefix_size() {
+ return m_prefix_size;
+ }
+
+ void set_prefix_size(uint16_t prefix_size) {
+ m_prefix_size = prefix_size;
+ }
+
private:
uint8_t * m_bss_ptr; /* pointer to the data section */
uint8_t * m_program_ptr; /* pointer to the program */
uint16_t m_bss_size;
uint16_t m_program_size; /* program size*/
uint16_t m_max_pkt_offset_change;
+ uint16_t m_prefix_size;
};
@@ -940,36 +1061,52 @@ public:
StreamVm(){
+ m_prefix_size=0;
m_bss=0;
m_pkt_size=0;
m_cur_var_offset=0;
m_is_random_var=false;
+ m_split_instr=NULL;
+ m_is_compiled = false;
}
- /* set packet size */
- void set_packet_size(uint16_t pkt_size){
- m_pkt_size = pkt_size;
+ uint16_t get_packet_size() const {
+ return ( m_pkt_size);
}
- uint16_t get_packet_size(){
- return ( m_pkt_size);
+
+ void set_split_instruction(StreamVmInstructionVar *instr);
+
+ StreamVmInstructionVar * get_split_instruction() {
+ return m_split_instr;
}
+ StreamVmDp * generate_dp_object(){
- StreamVmDp * cloneAsVmDp(){
+ if (!m_is_compiled) {
+ return NULL;
+ }
StreamVmDp * lp= new StreamVmDp(get_bss_ptr(),
get_bss_size(),
get_dp_instruction_buffer()->get_program(),
get_dp_instruction_buffer()->get_program_size(),
- get_max_packet_update_offset()
+ get_max_packet_update_offset(),
+ get_prefix_size()
);
assert(lp);
return (lp);
}
+ /**
+ * clone VM instructions
+ *
+ */
+ void copy_instructions(StreamVm &other) const;
+
+
bool is_vm_empty() {
return (m_inst_list.size() == 0);
}
@@ -1001,14 +1138,20 @@ public:
return ( m_max_field_update );
}
+ uint16_t get_prefix_size() {
+ return m_prefix_size;
+ }
+ bool is_compiled() {
+ return m_is_compiled;
+ }
/**
* compile the VM
* return true of success, o.w false
*
*/
- void compile();
+ void compile(uint16_t pkt_len);
~StreamVm();
@@ -1017,6 +1160,14 @@ public:
/* raise exception */
void err(const std::string &err);
+
+ /**
+ * return a pointer to a flow var / client var
+ * by name if exists, otherwise NULL
+ *
+ */
+ StreamVmInstructionVar * lookup_var_by_name(const std::string &var_name);
+
private:
/* lookup for varible offset, */
@@ -1046,6 +1197,8 @@ private:
private:
bool m_is_random_var;
+ bool m_is_compiled;
+ uint16_t m_prefix_size;
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 */
@@ -1056,6 +1209,8 @@ private:
StreamDPVmInstructions m_instructions;
+ StreamVmInstructionVar *m_split_instr;
+
};
#endif /* __TREX_STREAM_VM_API_H__ */