diff options
-rw-r--r-- | scripts/automation/trex_control_plane/client_utils/packet_builder.py | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/scripts/automation/trex_control_plane/client_utils/packet_builder.py b/scripts/automation/trex_control_plane/client_utils/packet_builder.py index 60f1d2f4..1dd8b309 100644 --- a/scripts/automation/trex_control_plane/client_utils/packet_builder.py +++ b/scripts/automation/trex_control_plane/client_utils/packet_builder.py @@ -10,6 +10,7 @@ import string import struct import re from abc import ABCMeta, abstractmethod +from collections import namedtuple class CTRexPktBuilder(object): @@ -238,13 +239,13 @@ class CTRexPktBuilder(object): return copy.copy(layer) if layer else None # VM access methods - def set_vm_ip_range(self, ip_start, ip_end, ip_type="ipv4"): + def set_vm_ip_range(self, ip_layer_name, ip_start, ip_end, ip_type="ipv4", add_checksum_inst=True): pass - def set_vm_range_type(self, ip_type): + def set_vm_eth_range(self, eth_layer_name, mac_start, mac_end): pass - def set_vm_core_mask(self, ip_type): + def set_vm_range_type(self, start_val, end_val): pass def get_vm_data(self): @@ -451,6 +452,8 @@ class CTRexPktBuilder(object): This class defines the TRex VM which represents how TRex will regenerate packets. The packets will be regenerated based on the built packet containing this class. """ + InstStore = namedtuple('InstStore', ['type', 'inst']) + def __init__(self): """ Instantiate a CTRexVM object @@ -460,7 +463,7 @@ class CTRexPktBuilder(object): """ super(CTRexPktBuilder.CTRexVM, self).__init__() self.vm_variables = {} - self.vm_inst_by_offset = {} + self._inst_by_offset = {} # this data structure holds only offset-related instructions, ordered in tuples # self.vm_inst_offsets = [] def set_vm_var_field(self, var_name, field_name, val): @@ -504,19 +507,38 @@ class CTRexPktBuilder(object): + Exceptions from :func:`CTRexPktBuilder.CTRexVM.CTRexVMVariable.set_field` method. Will rise when VM variables were misconfiguration. """ - if name not in self.vm_variables.keys(): + if name not in self.vm_variables: self.vm_variables[name] = self.CTRexVMFlowVariable(name) - # try configuring VM var attributes + # try configuring VM instruction attributes for (field, value) in kwargs.items(): self.vm_variables[name].set_field(field, value) else: raise CTRexPktBuilder.VMVarNameExistsError(name) - def add_checksum_inst(self, linked_ip_layer): + def add_fix_checksum_inst(self, linked_ipv4_obj, offset_to_obj=20, name=None): + # check if specified linked_ipv4_obj is indeed an ipv4 object + if not (isinstance(linked_ipv4_obj, dpkt.ip.IP) ): + raise ValueError("The provided layer object is not of IPv4.") + checksum_offset = offset_to_obj + 10 # IPv4 header places checksum field at the 10-12 Bytes + if not name: + name = "checksum_{off}".format(off = checksum_offset) # name will override previous checksum inst, OK + new_checksum_inst = self.CTRexVMChecksumInst(name, checksum_offset) + # store the checksum inst in the end of the IP header (20 Bytes long) + self._inst_by_offset[offset_to_obj + 20] = self.InstStore('checksum', new_checksum_inst) + + def add_write_flow_inst(self, name, pkt_offset, **kwargs): pass + if name not in self.vm_variables: + raise KeyError("Trying to add write_flow_var instruction to a not-exists VM flow variable ('{0}')". + format(name)) + else: + new_write_inst = self.CTRexVMWrtFlowVarInst(name, pkt_offset) + # try configuring VM instruction attributes + for (field, value) in kwargs.items(): + new_write_inst.set_field(field, value) + # add the instruction to the date-structure + self._inst_by_offset[pkt_offset] = self.InstStore('write', new_write_inst) - def add_write_flow_inst(self): - pass def load_flow_man(self, flow_obj): """ @@ -539,7 +561,7 @@ class CTRexPktBuilder(object): def dump(self): """ - dumps a VM variables (instructions) into an list data structure. + dumps a VM variables (instructions) into a list data structure. :parameters: None @@ -548,8 +570,13 @@ class CTRexPktBuilder(object): list holds variables data of VM """ - return [var.dump() - for key, var in self.vm_variables.items()] + # at first, dump all CTRexVMFlowVariable instructions + ret_val = [var.dump() + for key, var in self.vm_variables.items()] + # then, dump all the CTRexVMWrtFlowVarInst and CTRexVMChecksumInst instructions + ret_val += [self._inst_by_offset.get(key).inst.dump() + for key in sorted(self._inst_by_offset)] + return ret_val class CVMAbstractInstruction(object): __metaclass__ = ABCMeta @@ -660,7 +687,7 @@ class CTRexPktBuilder(object): class CTRexVMChecksumInst(CVMAbstractInstruction): - def __init__(self, name, offset=0): + def __init__(self, name, offset): """ Instantiate a CTRexVMChecksumInst object @@ -677,7 +704,7 @@ class CTRexPktBuilder(object): class CTRexVMWrtFlowVarInst(CVMAbstractInstruction): - def __init__(self, name): + def __init__(self, name, pkt_offset): """ Instantiate a CTRexVMWrtFlowVarInst object @@ -686,13 +713,15 @@ class CTRexPktBuilder(object): a string representing the name of the VM variable. """ super(CTRexPktBuilder.CTRexVM.CTRexVMWrtFlowVarInst, self).__init__(name) - self.pkt_offset = 0 + self.pkt_offset = int(pkt_offset) self.add_value = 0 self.is_big_endian = False def set_field(self, field_name, val): if not hasattr(self, field_name): raise CTRexPktBuilder.VMFieldNameError(field_name) + elif field_name == 'pkt_offset': + raise ValueError("pkt_offset value cannot be changed") cur_attr_type = getattr(self, field_name) if cur_attr_type == type(val): setattr(self, field_name, val) @@ -702,7 +731,7 @@ class CTRexPktBuilder(object): def dump(self): return {"type": "write_flow_var", "name": self.name, - "pkt_offset": int(self.pkt_offset), + "pkt_offset": self.pkt_offset, "add_value": int(self.add_value), "is_big_endian": bool(self.is_big_endian) } |