import OpenFlow 1.2 protocol module and basic test cases from CPqD/oftest12

For now these tests will live in a separate directory. The goal is to merge
them where possible but this has to wait for an OpenFlow protocol module that
supports all versions of OpenFlow.
diff --git a/src/python/of12/match.py b/src/python/of12/match.py
new file mode 100644
index 0000000..de285a2
--- /dev/null
+++ b/src/python/of12/match.py
@@ -0,0 +1,787 @@
+
+# Python OpenFlow instruction wrapper classes
+
+import ipaddr
+from cstruct import *
+
+
+class oxm_tlv:
+    def __init__(self, field, hasmask, length, value, mask=None, class_ = 0x8000):
+        self.class_ = class_
+        self.field = field
+        self.hasmask = hasmask
+        self.length = length
+        self.value = value
+        self.mask = mask
+    
+    def pack(self, assertstruct=True):
+        
+        packed = ""
+        packed += struct.pack("!I", ((self.class_ << 16) | (self.field << 9) | (self.hasmask << 8) | self.length))
+        if self.length == 1:
+            packed += struct.pack("B", self.value)
+            if self.hasmask:
+                packed += struct.pack("B", self.mask)
+        elif self.length == 2 or (self.length == 4 and self.hasmask == True):
+            packed += struct.pack("!H", self.value)
+            if self.hasmask:
+                packed += struct.pack("!H", self.mask)
+        elif self.length == 4 or (self.length == 8 and self.hasmask == True):
+            packed += struct.pack("!I", self.value)
+            if self.hasmask:
+                packed += struct.pack("!I", self.mask)
+        elif self.length == 6 or self.length == 12:
+            packed += struct.pack("!BBBBBB", self.value[0],self.value[1],self.value[2],self.value[3],self.value[4],self.value[5])
+            if self.hasmask:
+                packed += struct.pack("!BBBBBB", self.mask[0],self.mask[1],self.mask[2],self.mask[3],self.mask[4],self.mask[5])
+        elif self.length == 8 or (self.length == 16 and self.hasmask == True):
+            packed += struct.pack("!Q", self.value)
+            if self.hasmask:
+                packed += struct.pack("!Q", self.mask)
+        elif self.length == 16 or self.length == 32:
+            packed += self.value.packed
+            if self.hasmask:
+                packed += self.mask.packed
+        return packed
+    
+    def __len__(self):
+        return self.length + 4
+    
+    def show(self, prefix=''):
+        return "\n".join(
+#        ("oxm_tlv_class=" + hex(self.class_),
+        ("oxm_tlv_class=" + str(self.class_),
+        "oxm_tlv_field=" + hex(self.field),
+        "oxm_tlv_hasmask=" + str(bool(self.hasmask)),
+        "oxm_tlv_length: " + hex(self.length),
+        "value: " + str(self.value),))
+
+
+def roundup (x,y): 
+    return (((x) + ((y) - 1)) / (y) * (y))
+
+class in_port(oxm_tlv):
+    """
+    Wrapper class for in_port match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IN_PORT , hasmask, 4, value)
+    def show(self, prefix=''):
+        outstr = prefix + "in_port\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+
+class in_phy_port(oxm_tlv):
+    """
+    Wrapper class for in_phy_port match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self,OFPXMT_OFB_IN_PHY_PORT, hasmask, 4, value)
+    def show(self, prefix=''):
+        outstr = prefix + "in_phy_port\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+
+class metadata(oxm_tlv):
+    """
+    Wrapper class for metadata match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, mask = None):
+        if mask == None:
+            oxm_tlv.__init__(self, OFPXMT_OFB_METADATA, False, 8, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_METADATA, True, 16, value, mask)            
+    def show(self, prefix=''):
+        outstr = prefix + "metadata\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class eth_dst(oxm_tlv):
+    """
+    Wrapper class for eth_dst match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, mask = None):
+        if mask == None:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ETH_DST, False, 6, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ETH_DST, True, 12, value, mask)            
+    def show(self, prefix=''):
+        outstr = prefix + "eth_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+  
+class eth_src(oxm_tlv):
+    """
+    Wrapper class for eth_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ETH_SRC, hasmask, 6, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ETH_SRC, hasmask, 12, value, mask)            
+    def show(self, prefix=''):
+        outstr = prefix + "eth_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class eth_type(oxm_tlv):
+    """
+    Wrapper class for eth_type match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ETH_TYPE, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "eth_type\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class vlan_vid(oxm_tlv):
+    """
+    Wrapper class for vlan_vid match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_VLAN_VID, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "vlan_vid\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class vlan_pcp(oxm_tlv):
+    """
+    Wrapper class for vlan_pcp match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_VLAN_PCP, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "vlan_pcp\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class ip_dscp(oxm_tlv):
+    """
+    Wrapper class for ip_dscp match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IP_DSCP, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "ip_dscp\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class ip_ecn(oxm_tlv):
+    """
+    Wrapper class for ip_dscp match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IP_ECN, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "ip_ecn\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class ip_proto(oxm_tlv):
+    """
+    Wrapper class for ip_proto match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IP_PROTO, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "ip_proto\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class ipv4_src(oxm_tlv):
+    """
+    Wrapper class for ipv4_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV4_SRC, hasmask, 4, value)
+        else: 
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV4_SRC, hasmask, 4, value, mask)
+    def show(self, prefix=''):
+        outstr = prefix + "ipv4_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class ipv4_dst(oxm_tlv):
+    """
+    Wrapper class for ipv4_dst match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV4_DST, hasmask, 4, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV4_DST, hasmask, 4, value, mask)
+    def show(self, prefix=''):
+        outstr = prefix + "ipv4_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class tcp_src(oxm_tlv):
+    """
+    Wrapper class for tcp_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_TCP_SRC, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "tcp_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class tcp_dst(oxm_tlv):
+    """
+    Wrapper class for tcp_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_TCP_DST, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "tcp_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr      
+
+class udp_src(oxm_tlv):
+    """
+    Wrapper class for udp_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_UDP_SRC, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "udp_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr   
+        
+class udp_dst(oxm_tlv):
+    """
+    Wrapper class for udp_dst match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_UDP_DST, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "udp_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr 
+        
+class sctp_src(oxm_tlv):
+    """
+    Wrapper class for sctp_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_SCTP_SRC, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "sctp_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr  
+
+
+class sctp_dst(oxm_tlv):
+    """
+    Wrapper class for sctp_dst match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_SCTP_DST, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "sctp_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr         
+  
+class icmpv4_type(oxm_tlv):
+    """
+    Wrapper class for icmpv4_type match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ICMPV4_TYPE, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "icmpv4_type\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr          
+
+class icmpv4_code(oxm_tlv):
+    """
+    Wrapper class for icmpv4_code match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ICMPV4_CODE, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "icmpv4_code\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outs
+        
+class arp_op(oxm_tlv):
+    """
+    Wrapper class for arp_op match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ARP_OP, hasmask, 2, value)
+    def show(self, prefix=''):
+        outstr = prefix + "arp_op\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outs
+
+class arp_spa(oxm_tlv):
+    """
+    Wrapper class for arp_spa match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_SPA, hasmask, 4, value)
+        else: 
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_SPA, hasmask, 4, value, mask)
+    def show(self, prefix=''):
+        outstr = prefix + "arp_spa\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class arp_tpa(oxm_tlv):
+    """
+    Wrapper class for arp_tpa match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_TPA, hasmask, 4, value)
+        else: 
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_TPA, hasmask, 4, value, mask)
+    def show(self, prefix=''):
+        outstr = prefix + "arp_tpa\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+
+class arp_sha(oxm_tlv):
+    """
+    Wrapper class for arp_sha match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_SHA, hasmask, 6, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_SHA, hasmask, 12, value)            
+    def show(self, prefix=''):
+        outstr = prefix + "arp_sha\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+ 
+class arp_tha(oxm_tlv):
+    """
+    Wrapper class for arp_tha match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_THA, hasmask, 6, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_ARP_THA, hasmask, 12, value)            
+    def show(self, prefix=''):
+        outstr = prefix + "arp_tha\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class ipv6_src(oxm_tlv):
+    """
+    Wrapper class for ipv6_src match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_SRC, False, 16, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_SRC, True, 32, value)            
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_src\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class ipv6_dst(oxm_tlv):
+    """
+    Wrapper class for ipv6_dst match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_DST, False, 16, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_DST, True, 32, value)            
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_dst\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+ 
+class ipv6_flabel(oxm_tlv):
+    """
+    Wrapper class for ipv6_flabel match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        if not hasmask:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_FLABEL, hasmask, 4, value)
+        else:
+            oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_FLABEL, hasmask, 8, value)            
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_flabel\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class icmpv6_type(oxm_tlv):
+    """
+    Wrapper class for icmpv6_type match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ICMPV6_TYPE, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "icmpv6_type\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr          
+
+class icmpv6_code(oxm_tlv):
+    """
+    Wrapper class for icmpv6_code match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_ICMPV6_CODE, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "icmpv6_code\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outs
+
+class ipv6_nd_target(oxm_tlv):
+    """
+    Wrapper class for ipv6_nd_target match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_ND_TARGET, hasmask, 16, value)
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_nd_target\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class ipv6_nd_sll(oxm_tlv):
+    """
+    Wrapper class for ipv6_nd_sll match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_ND_SLL, hasmask, 6, value)
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_nd_sll\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class ipv6_nd_tll(oxm_tlv):
+    """
+    Wrapper class for ipv6_nd_tll match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_IPV6_ND_TLL, hasmask, 6, value)          
+    def show(self, prefix=''):
+        outstr = prefix + "ipv6_nd_tll\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+class mpls_label(oxm_tlv):
+    """
+    Wrapper class for mpls_label match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_MPLS_LABEL, hasmask, 4, value)
+    def show(self, prefix=''):
+        outstr = prefix + "mpls_label\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+        
+class mpls_tc(oxm_tlv):
+    """
+    Wrapper class for mpls_ltc match object
+
+    Data members inherited from oxm_tlv:
+    @arg class
+    @arg field
+    @arg hasmask
+    @arg body
+
+    """
+    def __init__(self, value, hasmask = False):
+        oxm_tlv.__init__(self, OFPXMT_OFB_MPLS_TC, hasmask, 1, value)
+    def show(self, prefix=''):
+        outstr = prefix + "mpls_tc\n"
+        outstr += oxm_tlv.show(self, prefix)
+        return outstr
+
+match_class_list = (
+    in_port,
+    in_phy_port,
+    metadata,
+    eth_dst,
+    eth_src,
+    eth_type,
+    vlan_vid,
+    vlan_pcp,
+    ip_dscp,
+    ip_ecn,
+    ip_proto,
+    ipv4_src,
+    ipv4_dst,
+    tcp_src,
+    tcp_dst,
+    udp_src,
+    udp_dst,
+    sctp_src,
+    sctp_dst,
+    icmpv4_type,
+    icmpv4_code,
+    arp_op,
+    arp_spa,
+    arp_tpa,
+    arp_sha,
+    arp_tha,
+    ipv6_src,
+    ipv6_dst,
+    ipv6_flabel,
+    icmpv6_type,
+    icmpv6_code,
+    ipv6_nd_target,
+    ipv6_nd_sll,
+    ipv6_nd_tll,
+    mpls_label,
+    mpls_tc)