Update field engine defs. Generation vm instrucions from updated model. 77/5177/1
authorVyacheslav Ogai <[email protected]>
Sat, 8 Oct 2016 17:59:07 +0000 (20:59 +0300)
committerHanoh Haim <[email protected]>
Mon, 19 Dec 2016 14:04:07 +0000 (16:04 +0200)
Signed-off-by: Vyacheslav Ogai <[email protected]>
scripts/automation/trex_control_plane/stl/services/scapy_server/field_engine.json
scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py
scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py

index 9214f4c..c978e42 100644 (file)
@@ -2,11 +2,11 @@
   "instructions": [
     {
       "id": "STLVmFlowVar",
-      "parameters": ["max_value","min_value","step","op"]
+      "parameters": ["name", "max_value","min_value","step", "size","op"]
     },
     {
       "id": "STLVmWrFlowVar",
-      "parameters": ["fv_name", "pkt_offset"]
+      "parameters": ["fv_name", "pkt_offset","offset_fixup","add_val","is_big"]
     },
     {
       "id": "STLVmFixIpv4",
   ],
 
   "instruction_params_meta": [
+    {
+      "id": "name",
+      "name": "Name",
+      "type": "STRING",
+      "required": true,
+      "defaultValue": "Not defined"
+    },
+    {
+      "id": "init_value",
+      "name": "Initial value",
+      "type": "STRING",
+      "defaultValue": "0"
+    },
     {
       "id": "max_value",
       "name": "Maximum value",
       "type": "STRING",
+      "required": true,
       "defaultValue": "0"
     },
     {
       "id": "min_value",
       "name": "Minimum value",
       "type": "STRING",
+      "required": true,
       "defaultValue": "0"
     },
     {
       "id": "step",
       "name": "Step",
       "type": "NUMBER",
+      "required": true,
       "defaultValue": "1"
     },
     {
         "dec": "Decrement",
         "inc": "Increment",
         "random": "Random"
+      },
+      "required": true
+    },
+    {
+      "id": "size",
+      "name": "Size",
+      "type": "ENUM",
+      "defaultValue": "1",
+      "dict": {
+        "1": "1",
+        "2": "2",
+        "4": "4",
+        "8": "8"
       }
     },
     {
       "id": "fv_name",
       "name": "Variable name",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": "Not Defined"
     },
     {
       "id": "pkt_offset",
       "name": "Offset",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": 0
+    },
+    {
+      "id": "offset_fixup",
+      "name": "offset_fixup",
+      "type": "NUMBER",
+      "defaultValue": 0
+    },
+    {
+      "id": "add_val",
+      "name": "add_val",
+      "type": "NUMBER",
+      "defaultValue": 0
+    },
+    {
+      "id": "is_big",
+      "name": "is_big",
+      "type": "ENUM",
+      "defaultValue": "true",
+      "dict": {
+        "true": "true",
+        "false": "false"
+      }
     },
     {
       "id": "offset",
       "name": "Offset",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": "Not defined"
     },
     {
       "id": "l3_offset",
       "name": "L3 offset",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": 0
     },
     {
       "id": "l4_offset",
       "name": "L4 offset",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": 0
     },
     {
       "id": "l4_type",
       "name": "L4 type",
-      "type": "STRING"
+      "type": "STRING",
+      "required": true,
+      "defaultValue": "Not defined"
     }
   ],
   "protocol_fields": {
index 93ca750..32b5efb 100755 (executable)
@@ -6,6 +6,7 @@ stl_pathname = os.path.abspath(os.path.join(os.pardir, os.pardir))
 sys.path.append(stl_pathname)
 
 from trex_stl_lib.api import *
+import trex_stl_lib.trex_stl_packet_builder_scapy
 import tempfile
 import hashlib
 import base64
@@ -401,6 +402,7 @@ class Scapy_service(Scapy_service_api):
         self.field_engine_instruction_expressions = []
         self._load_definitions_from_json()
         self._load_field_engine_meta_from_json()
+        self._vm_instructions = dict([m for m in inspect.getmembers(trex_stl_lib.trex_stl_packet_builder_scapy, inspect.isclass) if m[1].__module__ == 'trex_stl_lib.trex_stl_packet_builder_scapy'])
 
     def _load_definitions_from_json(self):
         # load protocol definitions from a json file
@@ -763,48 +765,14 @@ class Scapy_service(Scapy_service_api):
         return res
 
     def _generate_vm_instructions(self, pkt, field_engine_model_descriptor):
-        self.field_engine_instruction_expressions = [self._get_instruction_expressions_header()]
+        self.field_engine_instruction_expressions = []
         instructions = []
-        protocols_model = field_engine_model_descriptor['instructions']
-        for protocol in protocols_model:
-            protocol_id = protocol['id']
-            for field in protocol['fields']:
-                field_id = field['fieldId']
-                var_name = str(protocol_id + "_" + field_id)
-                parameters = field['parameters']
-                min_value = int(parameters['min_value']) if parameters['min_value'].isdigit() else str(parameters['min_value'])
-                max_value = int(parameters['max_value']) if parameters['max_value'].isdigit() else str(parameters['max_value'])
-                vm_flow_var = STLVmFlowVar(name=var_name, min_value=min_value, max_value=max_value,
-                                           step=int(parameters['step']), op=parameters['op'])
-                pkt_offset = self._get_pkt_offset_param(protocol_id, field_id)
-                vm_wr_flow_var = STLVmWrFlowVar(fv_name=var_name, pkt_offset=pkt_offset)
-                instructions.append(vm_flow_var)
-                instructions.append(vm_wr_flow_var)
-                self.field_engine_instruction_expressions += self._generate_vm_instruction_commands(protocol_id, field_id, parameters)
-
-        protocols = [(proto['id']) for proto in protocols_model]
-
-        if "IP" in protocols:
-            ip_v4_checksum_fixed = False
-            expression = {}
-
-            if "TCP" in protocols and protocols.index("TCP") - protocols.index("IP") == 1:
-                instructions.append(STLVmFixChecksumHw(l3_offset="IP",l4_offset="TCP",l4_type=CTRexVmInsFixHwCs.L4_TYPE_TCP))
-                expression['name'] = "STLVmFixChecksumHw"
-                expression['parameters'] = {"l3_offset": '"IP"',"l4_offset": '"TCP"',"l4_type": '"CTRexVmInsFixHwCs.L4_TYPE_TCP"'}
-                ip_v4_checksum_fixed = True
-            elif "UDP" in protocols and protocols.index("UDP") - protocols.index("IP") == 1:
-                instructions.append(STLVmFixChecksumHw(l3_offset="IP", l4_offset="UDP", l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP))
-                expression['name'] = "STLVmFixChecksumHw"
-                expression['parameters'] = {"l3_offset": '"IP"', "l4_offset": '"UDP"', "l4_type": '"CTRexVmInsFixHwCs.L4_TYPE_UDP"'}
-                ip_v4_checksum_fixed = True
-
-            if not ip_v4_checksum_fixed:
-                instructions.append(STLVmFixIpv4(offset="IP"))
-                expression['name'] = "STLVmFixIpv4"
-                expression['parameters'] = {"offset": '"IP"'}
-
-            self.field_engine_instruction_expressions.append(expression)
+        instructions_def = field_engine_model_descriptor['instructions']
+        for instruction_def in instructions_def:
+            instruction_id = instruction_def['id']
+            instruction_class = self._vm_instructions[instruction_id]
+            parameters = {k: self._sanitize_value(v) for (k, v) in instruction_def['parameters'].iteritems()}
+            instructions.append(instruction_class(**parameters))
 
         fe_parameters = field_engine_model_descriptor['global_parameters']
 
@@ -812,56 +780,17 @@ class Scapy_service(Scapy_service_api):
         if "cache_size" in fe_parameters:
             cache_size = int(fe_parameters['cache_size'])
 
-        self.field_engine_instruction_expressions += self._get_instruction_expressions_footer(cache_size)
-
         pkt_builder = STLPktBuilder(pkt=pkt, vm=STLScVmRaw(instructions, cache_size=cache_size))
         pkt_builder.compile()
         return pkt_builder.get_vm_data()
 
-    def _get_instruction_expressions_header(self):
-        return {'free_form': "vm = STLScVmRaw(["}
-
-    def _get_instruction_expressions_footer(self, cache_size):
-        instructions = []
-        footer = ']'
-
-        if cache_size != None and cache_size > 0:
-            footer += ',{0}={1}'.format("cache_size", cache_size)
-
-        footer += ')'
-        instructions.append({'free_form': footer})
-        return instructions
-
-    def _get_pkt_offset_param(self, protocol_id, field_id):
-        return str(protocol_id + "." + field_id) if protocol_id != "Ether" else 0
-
-    def _generate_vm_instruction_commands(self, protocol_id, field_id, parameters):
-        instructions = []
-        instruction = {}
-        instruction['name'] = "STLVmFlowVar"
-        var_name = '"'+str(protocol_id + "_" + field_id)+'"'
-        instruction['parameters'] = {}
-        instruction['parameters']["name"] = var_name
-        for param_id in parameters:
-            instruction['parameters'][param_id] = self._format_vm_instruction_param(param_id, parameters[param_id])
-        instructions.append(instruction)
-
-        instruction = {}
-        instruction['name'] = "STLVmWrFlowVar"
-        pkt_offset = self._get_pkt_offset_param(protocol_id, field_id)
-        pkt_offset_val = '"{0}"'.format(pkt_offset) if isinstance(pkt_offset, str) else pkt_offset
-        instruction['parameters'] = {}
-        instruction['parameters']["fv_name"] = var_name
-        instruction['parameters']["pkt_offset"] = pkt_offset_val
-        instructions.append(instruction)
-
-        return instructions
-
-    def _format_vm_instruction_param(self,param_id, value):
-        param_meta = self._get_instruction_parameter_meta(param_id)
-        if param_meta['type'] == "NUMBER" or self._is_int(value):
-            return value
-        return '"{0}"'.format(value)
+    def _sanitize_value(self, val):
+        if val == "true":
+            return True
+        elif val == "false":
+            return False
+        else:
+            return int(val) if val.isdigit() else str(val)
 
     def _get_instruction_parameter_meta(self, param_id):
         for meta in self.instruction_parameter_meta_definitions:
index af3bfb4..2f5dec9 100644 (file)
@@ -119,16 +119,22 @@ def test_get_definitions_all():
     assert("TCP" in def_classnames)
 
     fe_parameter_metas = defs['feInstructionParameters']
-    assert(fe_parameter_metas[0]['id'] == "max_value")
-    assert(fe_parameter_metas[1]['id'] == "min_value")
-    assert(fe_parameter_metas[2]['id'] == "step")
-    assert(fe_parameter_metas[3]['id'] == "op")
-    assert(fe_parameter_metas[4]['id'] == "fv_name")
-    assert(fe_parameter_metas[5]['id'] == "pkt_offset")
-    assert(fe_parameter_metas[6]['id'] == "offset")
-    assert(fe_parameter_metas[7]['id'] == "l3_offset")
-    assert(fe_parameter_metas[8]['id'] == "l4_offset")
-    assert(fe_parameter_metas[9]['id'] == "l4_type")
+    assert(fe_parameter_metas[0]['id'] == "name")
+    assert(fe_parameter_metas[1]['id'] == "init_value")
+    assert(fe_parameter_metas[2]['id'] == "max_value")
+    assert(fe_parameter_metas[3]['id'] == "min_value")
+    assert(fe_parameter_metas[4]['id'] == "step")
+    assert(fe_parameter_metas[5]['id'] == "op")
+    assert(fe_parameter_metas[6]['id'] == "size")
+    assert(fe_parameter_metas[7]['id'] == "fv_name")
+    assert(fe_parameter_metas[8]['id'] == "pkt_offset")
+    assert(fe_parameter_metas[9]['id'] == "offset_fixup")
+    assert(fe_parameter_metas[10]['id'] == "add_val")
+    assert(fe_parameter_metas[11]['id'] == "is_big")
+    assert(fe_parameter_metas[12]['id'] == "offset")
+    assert(fe_parameter_metas[13]['id'] == "l3_offset")
+    assert(fe_parameter_metas[14]['id'] == "l4_offset")
+    assert(fe_parameter_metas[15]['id'] == "l4_type")
 
     # All instructions should have a help description.
     fe_instructions = defs['feInstructions']
@@ -274,14 +280,29 @@ def test_generate_vm_instructions():
         layer_def("Ether"),
         layer_def("IP", src="16.0.0.1", dst="48.0.0.1")
     ]
-    ip_instructions_model = {"field_engine": {'global_parameters': {}, 'instructions': [{'id': "IP", 'fields': [
-        {"fieldId": "src", 'parameters': {'min_value': "0", 'max_value': "16.0.0.255", 'step': "1", 'op': "inc"}},
-        {"fieldId": "ttl", 'parameters': {'min_value': "1", 'max_value': "17", 'step': "1", 'op': "inc"}}]}]}}
+    ip_instructions_model = {"field_engine": {"instructions": [{"id": "STLVmFlowVar",
+                                                                "parameters": {"op": "inc", "min_value": "192.168.0.10",
+                                                                               "size": "1", "name": "ip_src",
+                                                                               "step": "1",
+                                                                               "max_value": "192.168.0.100"}},
+                                                               {"id": "STLVmWrFlowVar",
+                                                                "parameters": {"pkt_offset": "IP.src", "is_big": "true",
+                                                                               "add_val": "0", "offset_fixup": "0",
+                                                                               "fv_name": "ip_src"}},
+                                                               {"id": "STLVmFlowVar",
+                                                                "parameters": {"op": "dec", "min_value": "32",
+                                                                               "size": "1", "name": "ip_ttl",
+                                                                               "step": "4", "max_value": "64"}},
+                                                               {"id": "STLVmWrFlowVar",
+                                                                "parameters": {"pkt_offset": "IP.ttl", "is_big": "true",
+                                                                               "add_val": "0", "offset_fixup": "0",
+                                                                               "fv_name": "ip_ttl"}}],
+                                              "global_parameters": {}}}
     res = build_pkt_ex(ip_pkt_model, ip_instructions_model)
     src_instruction = res['vm_instructions']['instructions'][0]
-    assert(src_instruction['min_value'] == 0)
-    assert(src_instruction['max_value'] == 268435711)
+    assert(src_instruction['min_value'] == 3232235530)
+    assert(src_instruction['max_value'] == 3232235620)
 
     ttl_instruction = res['vm_instructions']['instructions'][2]
-    assert(ttl_instruction['min_value'] == 1)
-    assert(ttl_instruction['max_value'] == 17)
\ No newline at end of file
+    assert(ttl_instruction['min_value'] == 32)
+    assert(ttl_instruction['max_value'] == 64)