Exemplo n.º 1
0
    def setUpClass(cls):
        """Setup TestStruct."""
        reason = FlowRemovedReason.OFPRR_IDLE_TIMEOUT
        match = Match(in_port=80,
                      dl_vlan=1,
                      dl_vlan_pcp=1,
                      dl_type=1,
                      nw_tos=1,
                      nw_proto=1,
                      tp_src=80,
                      tp_dst=80,
                      dl_src=HWAddress('00:00:00:00:00:00'),
                      dl_dst=HWAddress('00:00:00:00:00:00'),
                      nw_src=IPAddress('192.168.0.1'),
                      nw_dst=IPAddress('192.168.0.2'))

        super().setUpClass()
        super().set_raw_dump_file('v0x01', 'ofpt_flow_removed')
        super().set_raw_dump_object(FlowRemoved,
                                    xid=12,
                                    match=match,
                                    cookie=0,
                                    priority=1,
                                    reason=reason,
                                    duration_sec=4,
                                    duration_nsec=23,
                                    idle_timeout=9,
                                    packet_count=10,
                                    byte_count=4)
        super().set_minimum_size(88)
Exemplo n.º 2
0
 def from_of_tlv(cls, tlv):
     """Return an instance from a pyof OXM TLV."""
     ip_address = IPAddress()
     ip_address.unpack(tlv.oxm_value)
     addr_str = str(ip_address)
     value = addr_str
     if tlv.oxm_hasmask:
         value = f'{addr_str}/{bytes_to_mask(tlv.oxm_value[4:], 32)}'
     return cls(value)
Exemplo n.º 3
0
 def as_of_tlv(self):
     """Return a pyof OXM TLV instance."""
     ip_addr = IPAddress(self.value)
     value_bytes = ip_addr.pack()
     if ip_addr.netmask < 32:
         value_bytes += mask_to_bytes(ip_addr.netmask, 32)
     return OxmTLV(oxm_field=self.oxm_field,
                   oxm_hasmask=ip_addr.netmask < 32,
                   oxm_value=value_bytes)
Exemplo n.º 4
0
 def __special_convert(self, table):
     convert = []
     IPTYPE = b'\x08\x00'
     for tr in table:
         priority = tr[0]
         match = {"eth_type": IPTYPE}
         tr1 = tr[1]
         sip = tr1.get("sip")
         if sip:
             match["ip_src"]=IPAddress(sip).pack()
         dip = tr1.get("dip")
         if dip:
             match["ip_dst"]=IPAddress(dip).pack()
         proto = tr1.get("proto")
         sport = tr1.get('sport')
         dport = tr1.get('dport')
         if proto=="udp":
             match["ip_proto"] = b'\x11'
             if sport:
                 match["udp_src"] = UBInt16(sport).pack()
             if dport:
                 match["udp_dst"] = UBInt16(dport).pack()
         if proto=="tcp":
             match["ip_proto"] = b'\x06'
             if sport:
                 match["tcp_src"] = UBInt16(sport).pack()
             if dport:
                 match["tcp_dst"] = UBInt16(dport).pack()
         tr2 = tr[2]
         seq = []
         fmap = {}
         for n,p in tr2:
             if n not in fmap:
                 fmap[n]={p}
                 seq.append(n)
             else:
                 fmap[n].add(p)
         path = [(n,fmap[n]) for n in seq]
         convert.append((priority, match, path))
     return convert
Exemplo n.º 5
0
    def __setattr__(self, name, value):

        # converts string ip_address to IPAddress
        if isinstance(getattr(Match, name), IPAddress) and \
                not isinstance(value, IPAddress):
            if isinstance(value, list):
                value = ".".join(str(x) for x in value)
            value = IPAddress(value)  # noqa
        # convertstring or list of hwaddress to HWAddress
        elif isinstance(getattr(Match, name), HWAddress) and \
                not isinstance(value, HWAddress):
            if isinstance(value, list):
                values = ["{0:0{1}x}".format(x, 2) for x in value]
                value = ":".join(values)
            value = HWAddress(value)

        super().__setattr__(name, value)
        self.fill_wildcards(name, value)
Exemplo n.º 6
0
 def _match_to_dict(self, flow_stats):
     match_dict = {}
     fields = (field for field in flow_stats.match.oxm_match_fields
               if field.oxm_field in self._match_values)
     for field in fields:
         match_field = self._match_values[field.oxm_field]
         if match_field == 'dl_vlan':
             data = int.from_bytes(field.oxm_value, 'big') & 4095
         elif match_field in ('dl_src', 'dl_dst'):
             addr = HWAddress()
             addr.unpack(field.oxm_value)
             data = str(addr)
         elif match_field in ('nw_src', 'nw_dst'):
             addr = IPAddress()
             addr.unpack(field.oxm_value)
             data = str(addr)
         else:
             data = int.from_bytes(field.oxm_value, 'big')
         match_dict[match_field] = data
     return match_dict
Exemplo n.º 7
0
 def _match_from_dict(self, dictionary):
     known_fields = ((field, data) for field, data in dictionary.items()
                     if field in self._match_names)
     for field_name, data in known_fields:
         tlv = OxmTLV()
         tlv.oxm_field = self._match_names[field_name]
         # set oxm_value
         if field_name in ('dl_vlan_pcp', 'nw_proto'):
             tlv.oxm_value = data.to_bytes(1, 'big')
         elif field_name == 'dl_vlan':
             vid = data | VlanId.OFPVID_PRESENT
             tlv.oxm_value = vid.to_bytes(2, 'big')
         elif field_name in ('dl_src', 'dl_dst'):
             tlv.oxm_value = HWAddress(data).pack()
         elif field_name in ('nw_src', 'nw_dst'):
             tlv.oxm_value = IPAddress(data).pack()
         elif field_name == 'in_port':
             tlv.oxm_value = data.to_bytes(4, 'big')
         else:
             tlv.oxm_value = data.to_bytes(2, 'big')
         yield tlv
Exemplo n.º 8
0
 def generate_flow_mod_message(self, xid, srcIpAddress):
     match = Match(dl_type=2048, nw_src=IPAddress(srcIpAddress))
     message = FlowMod(xid=xid,
                       match=match,
                       command=FlowModCommand.OFPFC_ADD)
     return message.pack()
Exemplo n.º 9
0
 def from_of_tlv(cls, tlv):
     """Return an instance from a pyof OXM TLV."""
     ip_address = IPAddress()
     ip_address.unpack(tlv.oxm_value)
     ip_str = str(ip_address)
     return cls(ip_str)
Exemplo n.º 10
0
 def as_of_tlv(self):
     """Return a pyof OXM TLV instance."""
     value_bytes = IPAddress(self.value).pack()
     return OxmTLV(oxm_field=self.oxm_field, oxm_value=value_bytes)
Exemplo n.º 11
0
class Match(GenericStruct):
    """Describes a flow entry. Fields to match against flows."""

    #: Wildcards fields.
    wildcards = UBInt32(value=FlowWildCards.OFPFW_ALL, enum_ref=FlowWildCards)
    #: Input switch port.
    in_port = UBInt16(0)
    #: Ethernet source address. (default: '00:00:00:00:00:00')
    dl_src = HWAddress()
    #: Ethernet destination address. (default: '00:00:00:00:00:00')
    dl_dst = HWAddress()
    #: Input VLAN id. (default: 0)
    dl_vlan = UBInt16(0)
    #: Input VLAN priority. (default: 0)
    dl_vlan_pcp = UBInt8(0)
    #: Align to 64-bits.
    pad1 = Pad(1)
    #: Ethernet frame type. (default: 0)
    dl_type = UBInt16(0)
    #: IP ToS (actually DSCP field, 6 bits). (default: 0)
    nw_tos = UBInt8(0)
    #: IP protocol or lower 8 bits of ARP opcode. (default: 0)
    nw_proto = UBInt8(0)
    #: Align to 64-bits.
    pad2 = Pad(2)
    #: IP source address. (default: '0.0.0.0/32')
    nw_src = IPAddress()
    #: IP destination address. (default: '0.0.0.0/32')
    nw_dst = IPAddress()
    #: TCP/UDP source port. (default: 0)
    tp_src = UBInt16(0)
    #: TCP/UDP destination port. (default: 0)
    tp_dst = UBInt16(0)

    def __init__(self, **kwargs):
        """All the constructor parameters below are optional.

        Args:
            wildcards (FlowWildCards): Wildcards fields. (Default: OFPFW_ALL)
            in_port (int): Input switch port. (default: 0)
            dl_src (HWAddress): Ethernet source address.
                (default: '00:00:00:00:00:00')
            dl_dst (HWAddress): Ethernet destination address.
                (default: '00:00:00:00:00:00')
            dl_vlan (int): Input VLAN id. (default: 0)
            dl_vlan_pcp (int): Input VLAN priority. (default: 0)
            dl_type (int): Ethernet frame type. (default: 0)
            nw_tos (int): IP ToS (actually DSCP field, 6 bits). (default: 0)
            nw_proto (int): IP protocol or lower 8 bits of ARP opcode.
                (default: 0)
            nw_src (IPAddress): IP source address. (default: '0.0.0.0/32')
            nw_dst (IPAddress): IP destination address. (default: '0.0.0.0/32')
            tp_src (int): TCP/UDP source port. (default: 0)
            tp_dst (int): TCP/UDP destination port. (default: 0)
        """
        super().__init__()
        [setattr(self, field, value) for field, value in kwargs.items()]

    def __setattr__(self, name, value):

        # converts string ip_address to IPAddress
        if isinstance(getattr(Match, name), IPAddress) and \
                not isinstance(value, IPAddress):
                    if isinstance(value, list):
                        value = ".".join(str(x) for x in value)
                    value = IPAddress(value)

        # convertstring or list of hwaddress to HWAddress
        if isinstance(getattr(Match, name), HWAddress) and \
                not isinstance(value, HWAddress):
                    if isinstance(value, list):
                        values = ["{0:0{1}x}".format(x, 2) for x in value]
                        value = ":".join(values)
                    value = HWAddress(value)

        super().__setattr__(name, value)
        self.fill_wildcards(name, value)

    def unpack(self, buff, offset=0):
        """Unpack *buff* into this object.

        Do nothing, since the _length is already defined and it is just a Pad.
        Keep buff and offset just for compability with other unpack methods.

        Args:
            buff: Buffer where data is located.
            offset (int): Where data stream begins.
        """
        super().unpack(buff, offset)
        self.wildcards = UBInt32(value=FlowWildCards.OFPFW_ALL,
                                 enum_ref=FlowWildCards)
        self.wildcards.unpack(buff, offset)

    def fill_wildcards(self, field=None, value=0):
        """Update wildcards attribute.

        This method update a wildcards considering the attributes of the
        current instance.

        Args:
            field (str): Name of the updated field.
            value (GenericType): New value used in the field.
        """
        if field in [None, 'wildcards'] or isinstance(value, Pad):
            return

        default_value = getattr(Match, field)
        if isinstance(default_value, IPAddress):
            if field is 'nw_dst':
                self.wildcards |= FlowWildCards.OFPFW_NW_DST_MASK
                shift = FlowWildCards.OFPFW_NW_DST_SHIFT
            else:
                self.wildcards |= FlowWildCards.OFPFW_NW_SRC_MASK
                shift = FlowWildCards.OFPFW_NW_SRC_SHIFT
            wildcard = (value.max_prefix - value.netmask) << shift
            self.wildcards -= wildcard
        else:
            wildcard_field = "OFPFW_{}".format(field.upper())
            wildcard = getattr(FlowWildCards, wildcard_field)

            if value == default_value and not (self.wildcards & wildcard) or \
               value != default_value and (self.wildcards & wildcard):
                self.wildcards ^= wildcard
Exemplo n.º 12
0
class ARP(GenericStruct):
    """ARP packet "struct".

    Contains fields for an ARP packet's header and data.
    Designed for Ethernet and IPv4 only: needs to have some attributes changed
    for other HTYPE and PTYPE implementations.
    Must be encapsulated inside an Ethernet frame.
    """

    htype = UBInt16()
    ptype = UBInt16()
    hlen = UBInt8()
    plen = UBInt8()
    oper = UBInt16()
    sha = HWAddress()
    spa = IPAddress()
    tha = HWAddress()
    tpa = IPAddress()

    def __init__(self,
                 htype=1,
                 ptype=EtherType.IPV4,
                 hlen=6,
                 plen=4,
                 oper=1,
                 sha='00:00:00:00:00:00',
                 spa='0.0.0.0',
                 tha="00:00:00:00:00:00",
                 tpa='0.0.0.0'):
        """Create an ARP with the parameters below.

        Args:
            htype (int): Hardware protocol type. Defaults to 1 for Ethernet.
            ptype (int): Network protocol type. Defaults to 0x800 for IPv4.
            hlen (int): Length of the hardware address. Defaults to 6 for MAC
                        addresses.
            plen (int): Length of the networking protocol address. Defaults to
                        4 for IPv4 addresses.
            oper (int): Determines the operation for this ARP packet. Must be 1
                        for ARP request or 2 for ARP reply. Defaults to 1.
            sha (str): Sender hardware address. Defaults to
                       '00:00:00:00:00:00'.
            spa (str): Sender protocol address. Defaults to '0.0.0.0'.
            tha (str): Target hardware address. Defaults to
                       '00:00:00:00:00:00'.
            tpa (str): Target protocol address. Defaults to '0.0.0.0'.
        """
        super().__init__()
        self.htype = htype
        self.ptype = ptype
        self.hlen = hlen
        self.plen = plen
        self.oper = oper
        self.sha = sha
        self.spa = spa
        self.tha = tha
        self.tpa = tpa

    def is_valid(self):
        """Assure the ARP contains Ethernet and IPv4 information."""
        return self.htype == 1 and self.ptype == EtherType.IPV4

    def unpack(self, buff, offset=0):
        """Unpack a binary struct into this object's attributes.

        Return the values instead of the lib's basic types.
        Check if the protocols involved are Ethernet and IPv4. Other protocols
        are currently not supported.

        Args:
            buff (bytes): Binary buffer.
            offset (int): Where to begin unpacking.

        Raises:
            :exc:`~.exceptions.UnpackException`: If unpack fails.

        """
        super().unpack(buff, offset)
        if not self.is_valid():
            raise UnpackException("Unsupported protocols in ARP packet")
Exemplo n.º 13
0
class IPv4(GenericStruct):
    """IPv4 packet "struct".

    Contains all fields of an IP version 4 packet header, plus the upper layer
    content as binary data.
    Some of the fields were merged together because of their size being
    inferior to 8 bits. They are represented as a single class attribute, but
    pack/unpack methods will take into account the values in individual
    instance attributes.
    """

    #: _version_ihl (:class:`UBInt8`): IP protocol version + Internet Header
    #: Length (words)
    _version_ihl = UBInt8()
    #: _dscp_ecn (:class:`UBInt8`): Differentiated Services Code Point
    #: (ToS - Type of Service) + Explicit Congestion Notification
    _dscp_ecn = UBInt8()
    #: length (:class:`UBInt16`): IP packet length (bytes)
    length = UBInt16()
    #: identification (:class:`UBInt16`): Packet ID - common to all fragments
    identification = UBInt16()
    #: _flags_offset (:class:`UBInt16`): Fragmentation flags + fragmentation
    #: offset
    _flags_offset = UBInt16()
    #: ttl (:class:`UBInt8`): Packet time-to-live
    ttl = UBInt8()
    #: protocol (:class:`UBInt8`): Upper layer protocol number
    protocol = UBInt8()
    #: checksum (:class:`UBInt16`): Header checksum
    checksum = UBInt16()
    #: source (:class:`IPAddress`): Source IPv4 address
    source = IPAddress()
    #: destination (:class:`IPAddress`): Destination IPv4 address
    destination = IPAddress()
    #: options (:class:`BinaryData`): IP Options - up to 320 bits, always
    #: padded to 32 bits
    options = BinaryData()
    #: data (:class:`BinaryData`): Packet data
    data = BinaryData()

    def __init__(self,
                 version=4,
                 ihl=5,
                 dscp=0,
                 ecn=0,
                 length=0,
                 identification=0,
                 flags=0,
                 offset=0,
                 ttl=255,
                 protocol=0,
                 checksum=0,
                 source="0.0.0.0",
                 destination="0.0.0.0",
                 options=b'',
                 data=b''):
        """Create an IPv4 with the parameters below.

        Args:
            version (int): IP protocol version. Defaults to 4.
            ihl (int): Internet Header Length. Default is 5.
            dscp (int): Differentiated Service Code Point. Defaults to 0.
            ecn (int): Explicit Congestion Notification. Defaults to 0.
            length (int): IP packet length in bytes. Defaults to 0.
            identification (int): Packet Id. Defaults to 0.
            flags (int): IPv4 Flags. Defults 0.
            offset (int): IPv4 offset. Defaults to 0.
            ttl (int): Packet time-to-live. Defaults to 255
            protocol (int): Upper layer protocol number. Defaults to 0.
            checksum (int): Header checksum. Defaults to 0.
            source (str): Source IPv4 address. Defaults to "0.0.0.0"
            destination (str): Destination IPv4 address. Defaults to "0.0.0.0"
            options (bytes): IP options. Defaults to empty bytes.
            data (bytes): Packet data. Defaults to empty bytes.
        """
        super().__init__()
        self.version = version
        self.ihl = ihl
        self.dscp = dscp
        self.ecn = ecn
        self.length = length
        self.identification = identification
        self.flags = flags
        self.offset = offset
        self.ttl = ttl
        self.protocol = protocol
        self.checksum = checksum
        self.source = source
        self.destination = destination
        self.options = options
        self.data = data

    def _update_checksum(self):
        """Update the packet checksum to enable integrity check."""
        source_list = [int(octet) for octet in self.source.split(".")]
        destination_list = [
            int(octet) for octet in self.destination.split(".")
        ]
        source_upper = (source_list[0] << 8) + source_list[1]
        source_lower = (source_list[2] << 8) + source_list[3]
        destination_upper = (destination_list[0] << 8) + destination_list[1]
        destination_lower = (destination_list[2] << 8) + destination_list[3]

        block_sum = ((self._version_ihl << 8 | self._dscp_ecn) + self.length +
                     self.identification + self._flags_offset +
                     (self.ttl << 8 | self.protocol) + source_upper +
                     source_lower + destination_upper + destination_lower)

        while block_sum > 65535:
            carry = block_sum >> 16
            block_sum = (block_sum & 65535) + carry

        self.checksum = ~block_sum & 65535

    def pack(self, value=None):
        """Pack the struct in a binary representation.

        Merge some fields to ensure correct packing.

        Returns:
            bytes: Binary representation of this instance.

        """
        # Set the correct IHL based on options size
        if self.options:
            self.ihl += int(len(self.options) / 4)

        # Set the correct packet length based on header length and data
        self.length = int(self.ihl * 4 + len(self.data))

        self._version_ihl = self.version << 4 | self.ihl
        self._dscp_ecn = self.dscp << 2 | self.ecn
        self._flags_offset = self.flags << 13 | self.offset

        # Set the checksum field before packing
        self._update_checksum()

        return super().pack()

    def unpack(self, buff, offset=0):
        """Unpack a binary struct into this object's attributes.

        Return the values instead of the lib's basic types.

        Args:
            buff (bytes): Binary buffer.
            offset (int): Where to begin unpacking.

        Raises:
            :exc:`~.exceptions.UnpackException`: If unpack fails.

        """
        super().unpack(buff, offset)

        self.version = self._version_ihl.value >> 4
        self.ihl = self._version_ihl.value & 15
        self.dscp = self._dscp_ecn.value >> 2
        self.ecn = self._dscp_ecn.value & 3
        self.length = self.length.value
        self.identification = self.identification.value
        self.flags = self._flags_offset.value >> 13
        self.offset = self._flags_offset.value & 8191
        self.ttl = self.ttl.value
        self.protocol = self.protocol.value
        self.checksum = self.checksum.value
        self.source = self.source.value
        self.destination = self.destination.value

        if self.ihl > 5:
            options_size = (self.ihl - 5) * 4
            self.data = self.options.value[options_size:]
            self.options = self.options.value[:options_size]
        else:
            self.data = self.options.value
            self.options = b''
    def setupPathList(self, path_table):
        self.__msg_queue.put(path_table)


if __name__ == "__main__":
    from pyof.foundation.basic_types import IPAddress

    logger.setLevel("DEBUG")
    plugin = ControllerPlugin()
    plugin.start()
    sw = [
        "", "00:00:00:00:00:00:00:01", "00:00:00:00:00:00:00:02",
        "00:00:00:00:00:00:00:03", "00:00:00:00:00:00:00:04"
    ]
    ip1 = IPAddress("10.0.0.1/32").pack()
    ip2 = IPAddress("10.0.0.2/32").pack()
    IPTYPE = b'\x08\x00'
    match1_2 = {"eth_type": IPTYPE, "ip_src": ip1, "ip_dst": ip2}
    match2_1 = {"eth_type": IPTYPE, "ip_src": ip2, "ip_dst": ip1}
    path1_2 = [[(sw[1], {1}), (sw[2], {1}), (sw[3], {3})],
               [(sw[1], {2}), (sw[4], {1}), (sw[3], {3})]]
    path2_1 = [[(sw[3], {1}), (sw[2], {2}), (sw[1], {3})],
               [(sw[3], {2}), (sw[4], {2}), (sw[1], {3})]]
    count = 1
    while True:
        import time

        a = input("wait input: ")
        plugin.setupPath(10, match1_2, path1_2[count % 2])
        plugin.setupPath(10, match2_1, path2_1[count % 2])
Exemplo n.º 15
0
class Match(GenericStruct):
    """Describes a flow entry. Fields to match against flows."""

    #: Wildcards fields.
    wildcards = UBInt32(value=FlowWildCards.OFPFW_ALL, enum_ref=FlowWildCards)
    #: Input switch port.
    in_port = UBInt16(0)
    #: Ethernet source address. (default: '00:00:00:00:00:00')
    dl_src = HWAddress()
    #: Ethernet destination address. (default: '00:00:00:00:00:00')
    dl_dst = HWAddress()
    #: Input VLAN id. (default: 0)
    dl_vlan = UBInt16(0)
    #: Input VLAN priority. (default: 0)
    dl_vlan_pcp = UBInt8(0)
    #: Align to 64-bits.
    pad1 = Pad(1)
    #: Ethernet frame type. (default: 0)
    dl_type = UBInt16(0)
    #: IP ToS (actually DSCP field, 6 bits). (default: 0)
    nw_tos = UBInt8(0)
    #: IP protocol or lower 8 bits of ARP opcode. (default: 0)
    nw_proto = UBInt8(0)
    #: Align to 64-bits.
    pad2 = Pad(2)
    #: IP source address. (default: '0.0.0.0/0')
    nw_src = IPAddress('0.0.0.0/0')
    #: IP destination address. (default: '0.0.0.0/0')
    nw_dst = IPAddress('0.0.0.0/0')
    #: TCP/UDP source port. (default: 0)
    tp_src = UBInt16(0)
    #: TCP/UDP destination port. (default: 0)
    tp_dst = UBInt16(0)

    def __init__(self, **kwargs):
        """All the constructor parameters below are optional.

        Args:
            wildcards (FlowWildCards): Wildcards fields. (Default: OFPFW_ALL)
            in_port (int): Input switch port. (default: 0)
            dl_src (HWAddress): Ethernet source address.
                (default: '00:00:00:00:00:00')
            dl_dst (HWAddress): Ethernet destination address.
                (default: '00:00:00:00:00:00')
            dl_vlan (int): Input VLAN id. (default: 0)
            dl_vlan_pcp (int): Input VLAN priority. (default: 0)
            dl_type (int): Ethernet frame type. (default: 0)
            nw_tos (int): IP ToS (actually DSCP field, 6 bits). (default: 0)
            nw_proto (int): IP protocol or lower 8 bits of ARP opcode.
                (default: 0)
            nw_src (IPAddress): IP source address. (default: '0.0.0.0/0')
            nw_dst (IPAddress): IP destination address. (default: '0.0.0.0/0')
            tp_src (int): TCP/UDP source port. (default: 0)
            tp_dst (int): TCP/UDP destination port. (default: 0)
        """
        super().__init__()
        for field, value in kwargs.items():
            setattr(self, field, value)

    def __setattr__(self, name, value):

        # converts string ip_address to IPAddress
        if isinstance(getattr(Match, name), IPAddress) and \
                not isinstance(value, IPAddress):
            if isinstance(value, list):
                value = ".".join(str(x) for x in value)
            value = IPAddress(value)  # noqa
        # convertstring or list of hwaddress to HWAddress
        elif isinstance(getattr(Match, name), HWAddress) and \
                not isinstance(value, HWAddress):
            if isinstance(value, list):
                values = ["{0:0{1}x}".format(x, 2) for x in value]
                value = ":".join(values)
            value = HWAddress(value)

        super().__setattr__(name, value)
        self.fill_wildcards(name, value)

    def unpack(self, buff, offset=0):
        """Unpack *buff* into this object.

        Do nothing, since the _length is already defined and it is just a Pad.
        Keep buff and offset just for compability with other unpack methods.

        Args:
            buff (bytes): Binary buffer.
            offset (int): Where to begin unpacking.

        Raises:
            :exc:`~.exceptions.UnpackException`: If unpack fails.

        """
        super().unpack(buff, offset)
        self.wildcards = UBInt32(value=FlowWildCards.OFPFW_ALL,
                                 enum_ref=FlowWildCards)
        self.wildcards.unpack(buff, offset)

    def fill_wildcards(self, field=None, value=0):
        """Update wildcards attribute.

        This method update a wildcards considering the attributes of the
        current instance.

        Args:
            field (str): Name of the updated field.
            value (GenericType): New value used in the field.
        """
        if field in [None, 'wildcards'] or isinstance(value, Pad):
            return

        default_value = getattr(Match, field)
        if isinstance(default_value, IPAddress):
            if field == 'nw_dst':
                shift = FlowWildCards.OFPFW_NW_DST_SHIFT
                base_mask = FlowWildCards.OFPFW_NW_DST_MASK
            else:
                shift = FlowWildCards.OFPFW_NW_SRC_SHIFT
                base_mask = FlowWildCards.OFPFW_NW_SRC_MASK

            # First we clear the nw_dst/nw_src mask related bits on the current
            # wildcard by setting 0 on all of them while we keep all other bits
            # as they are.
            self.wildcards &= FlowWildCards.OFPFW_ALL ^ base_mask

            # nw_dst and nw_src wildcard fields have 6 bits each.
            # "base_mask" is the 'all ones' for those 6 bits.
            # Once we know the netmask, we can calculate the these 6 bits
            # wildcard value and reverse them in order to insert them at the
            # correct position in self.wildcards
            wildcard = (value.max_prefix - value.netmask) << shift
            self.wildcards |= wildcard
        else:
            wildcard_field = "OFPFW_{}".format(field.upper())
            wildcard = getattr(FlowWildCards, wildcard_field)

            if value == default_value and not (self.wildcards & wildcard) or \
               value != default_value and (self.wildcards & wildcard):
                self.wildcards ^= wildcard