summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-11-22 16:33:22 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-11-23 11:38:05 +0900
commitfad94da2d49618dc7bb009c763f28c3a34d27fc5 (patch)
tree2e85b4d197bf176d792ebef9b25b54d3adc78670
parent4152e5d229b2c9265a0367e2549ff6ecba9c7440 (diff)
of1.3: support OFPMatch
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/ofproto/ofproto_v1_3.py76
-rw-r--r--ryu/ofproto/ofproto_v1_3_parser.py1191
2 files changed, 1256 insertions, 11 deletions
diff --git a/ryu/ofproto/ofproto_v1_3.py b/ryu/ofproto/ofproto_v1_3.py
index dd56d603..ec54ef8c 100644
--- a/ryu/ofproto/ofproto_v1_3.py
+++ b/ryu/ofproto/ofproto_v1_3.py
@@ -206,7 +206,7 @@ OFPXMT_OFB_IPV6_ND_SLL = 32 # Source link-layer for ND.
OFPXMT_OFB_IPV6_ND_TLL = 33 # Target link-layer for ND.
OFPXMT_OFB_MPLS_LABEL = 34 # MPLS label.
OFPXMT_OFB_MPLS_TC = 35 # MPLS TC.
-OFPXMT_OFP_MPLS_BOS = 36 # MPLS BoS bit.
+OFPXMT_OFB_MPLS_BOS = 36 # MPLS BoS bit.
OFPXMT_OFB_PBB_ISID = 37 # PBB I-SID.
OFPXMT_OFB_TUNNEL_ID = 38 # Logical Port Metadata.
OFPXMT_OFB_IPV6_EXTHDR = 39 # IPv6 Extension Header pseudo-field
@@ -233,7 +233,7 @@ assert (calcsize(OFP_OXM_EXPERIMENTER_HEADER_PACK_STR) ==
OFP_OXM_EXPERIMENTER_HEADER_SIZE)
# enum ofp_instruction_type
-OFPID_GOTO_TABLE = 1 # Setup the next table in the lookup pipeline.
+OFPIT_GOTO_TABLE = 1 # Setup the next table in the lookup pipeline.
OFPIT_WRITE_METADATA = 2 # Setup the metadata field for use later in
# pipeline.
OFPIT_WRITE_ACTIONS = 3 # Write the action(s) onto the datapath
@@ -1006,6 +1006,78 @@ OFP_EXPERIMENTER_HEADER_SIZE = 16
assert (calcsize(OFP_EXPERIMENTER_HEADER_PACK_STR) + OFP_HEADER_SIZE
== OFP_EXPERIMENTER_HEADER_SIZE)
+# OXM
+
+
+def _oxm_tlv_header(class_, field, hasmask, length):
+ return (class_ << 16) | (field << 9) | (hasmask << 8) | length
+
+
+def oxm_tlv_header(field, length):
+ return _oxm_tlv_header(OFPXMC_OPENFLOW_BASIC, field, 0, length)
+
+
+def oxm_tlv_header_w(field, length):
+ return _oxm_tlv_header(OFPXMC_OPENFLOW_BASIC, field, 1, length * 2)
+
+
+OXM_OF_IN_PORT = oxm_tlv_header(OFPXMT_OFB_IN_PORT, 4)
+OXM_OF_IN_PHY_PORT = oxm_tlv_header(OFPXMT_OFB_IN_PHY_PORT, 4)
+OXM_OF_METADATA = oxm_tlv_header(OFPXMT_OFB_METADATA, 8)
+OXM_OF_METADATA_W = oxm_tlv_header_w(OFPXMT_OFB_METADATA, 8)
+OXM_OF_ETH_DST = oxm_tlv_header(OFPXMT_OFB_ETH_DST, 6)
+OXM_OF_ETH_DST_W = oxm_tlv_header_w(OFPXMT_OFB_ETH_DST, 6)
+OXM_OF_ETH_SRC = oxm_tlv_header(OFPXMT_OFB_ETH_SRC, 6)
+OXM_OF_ETH_SRC_W = oxm_tlv_header_w(OFPXMT_OFB_ETH_SRC, 6)
+OXM_OF_ETH_TYPE = oxm_tlv_header(OFPXMT_OFB_ETH_TYPE, 2)
+OXM_OF_VLAN_VID = oxm_tlv_header(OFPXMT_OFB_VLAN_VID, 2)
+OXM_OF_VLAN_VID_W = oxm_tlv_header_w(OFPXMT_OFB_VLAN_VID, 2)
+OXM_OF_VLAN_PCP = oxm_tlv_header(OFPXMT_OFB_VLAN_PCP, 1)
+OXM_OF_IP_DSCP = oxm_tlv_header(OFPXMT_OFB_IP_DSCP, 1)
+OXM_OF_IP_ECN = oxm_tlv_header(OFPXMT_OFB_IP_ECN, 1)
+OXM_OF_IP_PROTO = oxm_tlv_header(OFPXMT_OFB_IP_PROTO, 1)
+OXM_OF_IPV4_SRC = oxm_tlv_header(OFPXMT_OFB_IPV4_SRC, 4)
+OXM_OF_IPV4_SRC_W = oxm_tlv_header_w(OFPXMT_OFB_IPV4_SRC, 4)
+OXM_OF_IPV4_DST = oxm_tlv_header(OFPXMT_OFB_IPV4_DST, 4)
+OXM_OF_IPV4_DST_W = oxm_tlv_header_w(OFPXMT_OFB_IPV4_DST, 4)
+OXM_OF_TCP_SRC = oxm_tlv_header(OFPXMT_OFB_TCP_SRC, 2)
+OXM_OF_TCP_DST = oxm_tlv_header(OFPXMT_OFB_TCP_DST, 2)
+OXM_OF_UDP_SRC = oxm_tlv_header(OFPXMT_OFB_UDP_SRC, 2)
+OXM_OF_UDP_DST = oxm_tlv_header(OFPXMT_OFB_UDP_DST, 2)
+OXM_OF_SCTP_SRC = oxm_tlv_header(OFPXMT_OFB_SCTP_SRC, 2)
+OXM_OF_SCTP_DST = oxm_tlv_header(OFPXMT_OFB_SCTP_DST, 2)
+OXM_OF_ICMPV4_TYPE = oxm_tlv_header(OFPXMT_OFB_ICMPV4_TYPE, 1)
+OXM_OF_ICMPV4_CODE = oxm_tlv_header(OFPXMT_OFB_ICMPV4_CODE, 1)
+OXM_OF_ARP_OP = oxm_tlv_header(OFPXMT_OFB_ARP_OP, 2)
+OXM_OF_ARP_SPA = oxm_tlv_header(OFPXMT_OFB_ARP_SPA, 4)
+OXM_OF_ARP_SPA_W = oxm_tlv_header_w(OFPXMT_OFB_ARP_SPA, 4)
+OXM_OF_ARP_TPA = oxm_tlv_header(OFPXMT_OFB_ARP_TPA, 4)
+OXM_OF_ARP_TPA_W = oxm_tlv_header_w(OFPXMT_OFB_ARP_TPA, 4)
+OXM_OF_ARP_SHA = oxm_tlv_header(OFPXMT_OFB_ARP_SHA, 6)
+OXM_OF_ARP_SHA_W = oxm_tlv_header_w(OFPXMT_OFB_ARP_SHA, 6)
+OXM_OF_ARP_THA = oxm_tlv_header(OFPXMT_OFB_ARP_THA, 6)
+OXM_OF_ARP_THA_W = oxm_tlv_header_w(OFPXMT_OFB_ARP_THA, 6)
+OXM_OF_IPV6_SRC = oxm_tlv_header(OFPXMT_OFB_IPV6_SRC, 16)
+OXM_OF_IPV6_SRC_W = oxm_tlv_header_w(OFPXMT_OFB_IPV6_SRC, 16)
+OXM_OF_IPV6_DST = oxm_tlv_header(OFPXMT_OFB_IPV6_DST, 16)
+OXM_OF_IPV6_DST_W = oxm_tlv_header_w(OFPXMT_OFB_IPV6_DST, 16)
+OXM_OF_IPV6_FLABEL = oxm_tlv_header(OFPXMT_OFB_IPV6_FLABEL, 4)
+OXM_OF_IPV6_FLABEL_W = oxm_tlv_header_w(OFPXMT_OFB_IPV6_FLABEL, 4)
+OXM_OF_ICMPV6_TYPE = oxm_tlv_header(OFPXMT_OFB_ICMPV6_TYPE, 1)
+OXM_OF_ICMPV6_CODE = oxm_tlv_header(OFPXMT_OFB_ICMPV6_CODE, 1)
+OXM_OF_IPV6_ND_TARGET = oxm_tlv_header(OFPXMT_OFB_IPV6_ND_TARGET, 16)
+OXM_OF_IPV6_ND_SLL = oxm_tlv_header(OFPXMT_OFB_IPV6_ND_SLL, 6)
+OXM_OF_IPV6_ND_TLL = oxm_tlv_header(OFPXMT_OFB_IPV6_ND_TLL, 6)
+OXM_OF_MPLS_LABEL = oxm_tlv_header(OFPXMT_OFB_MPLS_LABEL, 4)
+OXM_OF_MPLS_TC = oxm_tlv_header(OFPXMT_OFB_MPLS_TC, 1)
+OXM_OF_MPLS_BOS = oxm_tlv_header(OFPXMT_OFB_MPLS_BOS, 1)
+OXM_OF_PBB_ISID = oxm_tlv_header(OFPXMT_OFB_PBB_ISID, 3)
+OXM_OF_PBB_ISID_W = oxm_tlv_header_w(OFPXMT_OFB_PBB_ISID, 3)
+OXM_OF_TUNNEL_ID = oxm_tlv_header(OFPXMT_OFB_TUNNEL_ID, 8)
+OXM_OF_TUNNEL_ID_W = oxm_tlv_header_w(OFPXMT_OFB_TUNNEL_ID, 8)
+OXM_OF_IPV6_EXTHDR = oxm_tlv_header(OFPXMT_OFB_IPV6_EXTHDR, 2)
+OXM_OF_IPV6_EXTHDR_W = oxm_tlv_header_w(OFPXMT_OFB_IPV6_EXTHDR, 2)
+
# define constants
OFP_VERSION = 0x04
OFP_TCP_PORT = 6633
diff --git a/ryu/ofproto/ofproto_v1_3_parser.py b/ryu/ofproto/ofproto_v1_3_parser.py
index e3fc5885..bce9dd85 100644
--- a/ryu/ofproto/ofproto_v1_3_parser.py
+++ b/ryu/ofproto/ofproto_v1_3_parser.py
@@ -17,6 +17,8 @@
import collections
import struct
+from ryu.lib import mac
+from ryu import utils
from ofproto_parser import MsgBase, msg_pack_into, msg_str_attr
from . import ofproto_parser
from . import ofproto_v1_3
@@ -207,13 +209,1066 @@ class OFPSetConfig(MsgBase):
self.flags, self.miss_send_len)
+class Flow(object):
+ def __init__(self):
+ self.in_port = 0
+ self.in_phy_port = 0
+ self.metadata = 0
+ self.dl_dst = mac.DONTCARE
+ self.dl_src = mac.DONTCARE
+ self.dl_type = 0
+ self.vlan_vid = 0
+ self.vlan_pcp = 0
+ self.ip_dscp = 0
+ self.ip_ecn = 0
+ self.ip_proto = 0
+ self.ipv4_src = 0
+ self.ipv4_dst = 0
+ self.tcp_src = 0
+ self.tcp_dst = 0
+ self.udp_src = 0
+ self.udp_dst = 0
+ self.sctp_src = 0
+ self.sctp_dst = 0
+ self.icmpv4_type = 0
+ self.icmpv4_code = 0
+ self.arp_op = 0
+ self.arp_spa = 0
+ self.arp_tpa = 0
+ self.arp_sha = 0
+ self.arp_tha = 0
+ self.ipv6_src = []
+ self.ipv6_dst = []
+ self.ipv6_flabel = 0
+ self.icmpv6_type = 0
+ self.icmpv6_code = 0
+ self.ipv6_nd_target = []
+ self.ipv6_nd_sll = 0
+ self.ipv6_nd_tll = 0
+ self.mpls_lable = 0
+ self.mpls_tc = 0
+ self.mpls_bos = 0
+ self.pbb_isid = 0
+ self.tunnel_id = 0
+ self.ipv6_exthdr = 0
+
+
+class FlowWildcards(object):
+ def __init__(self):
+ self.metadata_mask = 0
+ self.dl_dst_mask = 0
+ self.dl_src_mask = 0
+ self.vlan_vid_mask = 0
+ self.ipv4_src_mask = 0
+ self.ipv4_dst_mask = 0
+ self.arp_spa_mask = 0
+ self.arp_tpa_mask = 0
+ self.arp_sha_mask = 0
+ self.arp_tha_mask = 0
+ self.ipv6_src_mask = []
+ self.ipv6_dst_mask = []
+ self.ipv6_flabel_mask = 0
+ self.pbb_isid_mask = 0
+ self.tunnel_id_mask = 0
+ self.ipv6_exthdr_mask = 0
+ self.wildcards = (1 << 64) - 1
+
+ def ft_set(self, shift):
+ self.wildcards &= ~(1 << shift)
+
+ def ft_test(self, shift):
+ return not self.wildcards & (1 << shift)
+
+
class OFPMatch(object):
def __init__(self):
super(OFPMatch, self).__init__()
+ self.wc = FlowWildcards()
+ self.flow = Flow()
+ self.fields = []
+
+ def append_field(self, header, value, mask=None):
+ self.fields.append(OFPMatchField.make(header, value, mask))
+
+ def serialize(self, buf, offset):
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IN_PORT):
+ self.append_field(ofproto_v1_3.OXM_OF_IN_PORT,
+ self.flow.in_port)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IN_PHY_PORT):
+ self.append_field(ofproto_v1_3.OXM_OF_IN_PHY_PORT,
+ self.flow.in_phy_port)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_METADATA):
+ if self.wc.metadata_mask == UINT64_MAX:
+ header = ofproto_v1_3.OXM_OF_METADATA
+ else:
+ header = ofproto_v1_3.OXM_OF_METADATA_W
+ self.append_field(header, self.flow.metadata,
+ self.wc.metadata_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ETH_DST):
+ if self.wc.dl_dst_mask:
+ header = ofproto_v1_3.OXM_OF_ETH_DST_W
+ else:
+ header = ofproto_v1_3.OXM_OF_ETH_DST
+ self.append_field(header, self.flow.dl_dst, self.wc.dl_dst_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ETH_SRC):
+ if self.wc.dl_src_mask:
+ header = ofproto_v1_3.OXM_OF_ETH_SRC_W
+ else:
+ header = ofproto_v1_3.OXM_OF_ETH_SRC
+ self.append_field(header, self.flow.dl_src, self.wc.dl_src_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ETH_TYPE):
+ self.append_field(ofproto_v1_3.OXM_OF_ETH_TYPE, self.flow.dl_type)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_VLAN_VID):
+ if self.wc.vlan_vid_mask == UINT16_MAX:
+ header = ofproto_v1_3.OXM_OF_VLAN_VID
+ else:
+ header = ofproto_v1_3.OXM_OF_VLAN_VID_W
+ self.append_field(header, self.flow.vlan_vid,
+ self.wc.vlan_vid_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_VLAN_PCP):
+ self.append_field(ofproto_v1_3.OXM_OF_VLAN_PCP, self.flow.vlan_pcp)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IP_DSCP):
+ self.append_field(ofproto_v1_3.OXM_OF_IP_DSCP, self.flow.ip_dscp)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IP_ECN):
+ self.append_field(ofproto_v1_3.OXM_OF_IP_ECN, self.flow.ip_ecn)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IP_PROTO):
+ self.append_field(ofproto_v1_3.OXM_OF_IP_PROTO, self.flow.ip_proto)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV4_SRC):
+ if self.wc.ipv4_src_mask == UINT32_MAX:
+ header = ofproto_v1_3.OXM_OF_IPV4_SRC
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV4_SRC_W
+ self.append_field(header, self.flow.ipv4_src,
+ self.wc.ipv4_src_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV4_DST):
+ if self.wc.ipv4_dst_mask == UINT32_MAX:
+ header = ofproto_v1_3.OXM_OF_IPV4_DST
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV4_DST_W
+ self.append_field(header, self.flow.ipv4_dst,
+ self.wc.ipv4_dst_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_TCP_SRC):
+ self.append_field(ofproto_v1_3.OXM_OF_TCP_SRC, self.flow.tcp_src)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_TCP_DST):
+ self.append_field(ofproto_v1_3.OXM_OF_TCP_DST, self.flow.tcp_dst)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_UDP_SRC):
+ self.append_field(ofproto_v1_3.OXM_OF_UDP_SRC, self.flow.udp_src)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_UDP_DST):
+ self.append_field(ofproto_v1_3.OXM_OF_UDP_DST, self.flow.udp_dst)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_SCTP_SRC):
+ self.append_field(ofproto_v1_3.OXM_OF_SCTP_SRC, self.flow.sctp_src)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_SCTP_DST):
+ self.append_field(ofproto_v1_3.OXM_OF_SCTP_DST, self.flow.sctp_dst)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ICMPV4_TYPE):
+ self.append_field(ofproto_v1_3.OXM_OF_ICMPV4_TYPE,
+ self.flow.icmpv4_type)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ICMPV4_CODE):
+ self.append_field(ofproto_v1_3.OXM_OF_ICMPV4_CODE,
+ self.flow.icmpv4_code)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ARP_OP):
+ self.append_field(ofproto_v1_3.OXM_OF_ARP_OP, self.flow.arp_op)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ARP_SPA):
+ if self.wc.arp_spa_mask == UINT32_MAX:
+ header = ofproto_v1_3.OXM_OF_ARP_SPA
+ else:
+ header = ofproto_v1_3.OXM_OF_ARP_SPA_W
+ self.append_field(header, self.flow.arp_spa, self.wc.arp_spa_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ARP_TPA):
+ if self.wc.arp_tpa_mask == UINT32_MAX:
+ header = ofproto_v1_3.OXM_OF_ARP_TPA
+ else:
+ header = ofproto_v1_3.OXM_OF_ARP_TPA_W
+ self.append_field(header, self.flow.arp_tpa, self.wc.arp_tpa_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ARP_SHA):
+ if self.wc.arp_sha_mask:
+ header = ofproto_v1_3.OXM_OF_ARP_SHA_W
+ else:
+ header = ofproto_v1_3.OXM_OF_ARP_SHA
+ self.append_field(header, self.flow.arp_sha, self.wc.arp_sha_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ARP_THA):
+ if self.wc.arp_tha_mask:
+ header = ofproto_v1_3.OXM_OF_ARP_THA_W
+ else:
+ header = ofproto_v1_3.OXM_OF_ARP_THA
+ self.append_field(header, self.flow.arp_tha, self.wc.arp_tha_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_SRC):
+ if len(self.wc.ipv6_src_mask):
+ header = ofproto_v1_3.OXM_OF_IPV6_SRC_W
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV6_SRC
+ self.append_field(header, self.flow.ipv6_src,
+ self.wc.ipv6_src_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_DST):
+ if len(self.wc.ipv6_dst_mask):
+ header = ofproto_v1_3.OXM_OF_IPV6_DST_W
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV6_DST
+ self.append_field(header, self.flow.ipv6_dst,
+ self.wc.ipv6_dst_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_FLABEL):
+ if self.wc.ipv6_flabel_mask == UINT32_MAX:
+ header = ofproto_v1_3.OXM_OF_IPV6_FLABEL
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV6_FLABEL_W
+ self.append_field(header, self.flow.ipv6_flabel,
+ self.wc.ipv6_flabel_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ICMPV6_TYPE):
+ self.append_field(ofproto_v1_3.OXM_OF_ICMPV6_TYPE,
+ self.flow.icmpv6_type)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_ICMPV6_CODE):
+ self.append_field(ofproto_v1_3.OXM_OF_ICMPV6_CODE,
+ self.flow.icmpv6_code)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_TARGET):
+ self.append_field(ofproto_v1_3.OXM_OF_IPV6_ND_TARGET,
+ self.flow.ipv6_nd_target)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_SLL):
+ self.append_field(ofproto_v1_3.OXM_OF_IPV6_ND_SLL,
+ self.flow.ipv6_nd_sll)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_TLL):
+ self.append_field(ofproto_v1_3.OXM_OF_IPV6_ND_TLL,
+ self.flow.ipv6_nd_tll)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_MPLS_LABEL):
+ self.append_field(ofproto_v1_3.OXM_OF_MPLS_LABEL,
+ self.flow.mpls_label)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_MPLS_TC):
+ self.append_field(ofproto_v1_3.OXM_OF_MPLS_TC,
+ self.flow.mpls_tc)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_MPLS_BOS):
+ self.append_field(ofproto_v1_3.OXM_OF_MPLS_BOS,
+ self.flow.mpls_bos)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_PBB_ISID):
+ if self.wc.pbb_isid_mask:
+ header = ofproto_v1_3.OXM_OF_PBB_ISID_W
+ else:
+ header = ofproto_v1_3.OXM_OF_PBB_ISID
+ self.append_field(header, self.flow.pbb_isid,
+ self.wc.pbb_isid_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_TUNNEL_ID):
+ if self.wc.tunnel_id_mask:
+ header = ofproto_v1_3.OXM_OF_TUNNEL_ID_W
+ else:
+ header = ofproto_v1_3.OXM_OF_TUNNEL_ID
+ self.append_field(header, self.flow.tunnel_id,
+ self.wc.tunnel_id_mask)
+
+ if self.wc.ft_test(ofproto_v1_3.OFPXMT_OFB_IPV6_EXTHDR):
+ if self.wc.ipv6_exthdr_mask:
+ header = ofproto_v1_3.OXM_OF_IPV6_EXTHDR_W
+ else:
+ header = ofproto_v1_3.OXM_OF_IPV6_EXTHDR
+ self.append_field(header, self.flow.ipv6_exthdr,
+ self.wc.ipv6_exthdr_mask)
+
+ field_offset = offset + 4
+ for f in self.fields:
+ f.serialize(buf, field_offset)
+ field_offset += f.length
+
+ length = field_offset - offset
+ msg_pack_into('!HH', buf, offset, ofproto_v1_3.OFPMT_OXM, length)
+
+ pad_len = utils.round_up(length, 8) - length
+ ofproto_parser.msg_pack_into("%dx" % pad_len, buf, field_offset)
+
+ return length + pad_len
@classmethod
def parser(cls, buf, offset):
- pass
+ match = OFPMatch()
+ type_, length = struct.unpack_from('!HH', buf, offset)
+
+ match.type = type_
+ match.length = length
+
+ # ofp_match adjustment
+ offset += 4
+ length -= 4
+ while length > 0:
+ field = OFPMatchField.parser(buf, offset)
+ offset += field.length
+ length -= field.length
+ match.fields.append(field)
+
+ return match
+
+ def set_in_port(self, port):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IN_PORT)
+ self.flow.in_port = port
+
+ def set_in_phy_port(self, phy_port):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IN_PHY_PORT)
+ self.flow.in_phy_port = phy_port
+
+ def set_metadata(self, metadata):
+ self.set_metadata_masked(metadata, UINT64_MAX)
+
+ def set_metadata_masked(self, metadata, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_METADATA)
+ self.wc.metadata_mask = mask
+ self.flow.metadata = metadata & mask
+
+ def set_dl_dst(self, dl_dst):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ETH_DST)
+ self.flow.dl_dst = dl_dst
+
+ def set_dl_dst_masked(self, dl_dst, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ETH_DST)
+ self.wc.dl_dst_mask = mask
+ # bit-wise and of the corresponding elements of dl_dst and mask
+ self.flow.dl_dst = mac.haddr_bitand(dl_dst, mask)
+
+ def set_dl_src(self, dl_src):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ETH_SRC)
+ self.flow.dl_src = dl_src
+
+ def set_dl_src_masked(self, dl_src, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ETH_SRC)
+ self.wc.dl_src_mask = mask
+ self.flow.dl_src = mac.haddr_bitand(dl_src, mask)
+
+ def set_dl_type(self, dl_type):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ETH_TYPE)
+ self.flow.dl_type = dl_type
+
+ def set_vlan_vid(self, vid):
+ self.set_vlan_vid_masked(vid, UINT16_MAX)
+
+ def set_vlan_vid_masked(self, vid, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_VLAN_VID)
+ self.wc.vlan_vid_mask = mask
+ self.flow.vlan_vid = vid
+
+ def set_vlan_pcp(self, pcp):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_VLAN_PCP)
+ self.flow.vlan_pcp = pcp
+
+ def set_ip_dscp(self, ip_dscp):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IP_DSCP)
+ self.flow.ip_dscp = ip_dscp
+
+ def set_ip_ecn(self, ip_ecn):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IP_ECN)
+ self.flow.ip_ecn = ip_ecn
+
+ def set_ip_proto(self, ip_proto):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IP_PROTO)
+ self.flow.ip_proto = ip_proto
+
+ def set_ipv4_src(self, ipv4_src):
+ self.set_ipv4_src_masked(ipv4_src, UINT32_MAX)
+
+ def set_ipv4_src_masked(self, ipv4_src, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV4_SRC)
+ self.flow.ipv4_src = ipv4_src
+ self.wc.ipv4_src_mask = mask
+
+ def set_ipv4_dst(self, ipv4_dst):
+ self.set_ipv4_dst_masked(ipv4_dst, UINT32_MAX)
+
+ def set_ipv4_dst_masked(self, ipv4_dst, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV4_DST)
+ self.flow.ipv4_dst = ipv4_dst
+ self.wc.ipv4_dst_mask = mask
+
+ def set_tcp_src(self, tcp_src):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_TCP_SRC)
+ self.flow.tcp_src = tcp_src
+
+ def set_tcp_dst(self, tcp_dst):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_TCP_DST)
+ self.flow.tcp_dst = tcp_dst
+
+ def set_udp_src(self, udp_src):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_UDP_SRC)
+ self.flow.udp_src = udp_src
+
+ def set_udp_dst(self, udp_dst):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_UDP_DST)
+ self.flow.udp_dst = udp_dst
+
+ def set_sctp_src(self, sctp_src):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_SCTP_SRC)
+ self.flow.sctp_src = sctp_src
+
+ def set_sctp_dst(self, sctp_dst):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_SCTP_DST)
+ self.flow.sctp_dst = sctp_dst
+
+ def set_icmpv4_type(self, icmpv4_type):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ICMPV4_TYPE)
+ self.flow.icmpv4_type = icmpv4_type
+
+ def set_icmpv4_code(self, icmpv4_code):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ICMPV4_CODE)
+ self.flow.icmpv4_code = icmpv4_code
+
+ def set_arp_opcode(self, arp_op):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_OP)
+ self.flow.arp_op = arp_op
+
+ def set_arp_spa(self, arp_spa):
+ self.set_arp_spa_masked(arp_spa, UINT32_MAX)
+
+ def set_arp_spa_masked(self, arp_spa, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_SPA)
+ self.wc.arp_spa_mask = mask
+ self.flow.arp_spa = arp_spa
+
+ def set_arp_tpa(self, arp_tpa):
+ self.set_arp_tpa_masked(arp_tpa, UINT32_MAX)
+
+ def set_arp_tpa_masked(self, arp_tpa, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_TPA)
+ self.wc.arp_tpa_mask = mask
+ self.flow.arp_tpa = arp_tpa
+
+ def set_arp_sha(self, arp_sha):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_SHA)
+ self.flow.arp_sha = arp_sha
+
+ def set_arp_sha_masked(self, arp_sha, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_SHA)
+ self.wc.arp_sha_mask = mask
+ self.flow.arp_sha = mac.haddr_bitand(arp_sha, mask)
+
+ def set_arp_tha(self, arp_tha):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_THA)
+ self.flow.arp_tha = arp_tha
+
+ def set_arp_tha_masked(self, arp_tha, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ARP_THA)
+ self.wc.arp_tha_mask = mask
+ self.flow.arp_tha = mac.haddr_bitand(arp_tha, mask)
+
+ def set_ipv6_src(self, src):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_SRC)
+ self.flow.ipv6_src = src
+
+ def set_ipv6_src_masked(self, src, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_SRC)
+ self.wc.ipv6_src_mask = mask
+ self.flow.ipv6_src = [x & y for (x, y) in itertools.izip(src, mask)]
+
+ def set_ipv6_dst(self, dst):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_DST)
+ self.flow.ipv6_dst = dst
+
+ def set_ipv6_dst_masked(self, dst, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_DST)
+ self.wc.ipv6_dst_mask = mask
+ self.flow.ipv6_dst = [x & y for (x, y) in itertools.izip(dst, mask)]
+
+ def set_ipv6_flabel(self, flabel):
+ self.set_ipv6_flabel_masked(flabel, UINT32_MAX)
+
+ def set_ipv6_flabel_masked(self, flabel, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_FLABEL)
+ self.wc.ipv6_flabel_mask = mask
+ self.flow.ipv6_flabel = flabel
+
+ def set_icmpv6_type(self, icmpv6_type):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ICMPV6_TYPE)
+ self.flow.icmpv6_type = icmpv6_type
+
+ def set_icmpv6_code(self, icmpv6_code):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_ICMPV6_CODE)
+ self.flow.icmpv6_code = icmpv6_code
+
+ def set_ipv6_nd_target(self, target):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_TARGET)
+ self.flow.ipv6_nd_target = target
+
+ def set_ipv6_nd_sll(self, ipv6_nd_sll):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_SLL)
+ self.flow.ipv6_nd_sll = ipv6_nd_sll
+
+ def set_ipv6_nd_tll(self, ipv6_nd_tll):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_ND_TLL)
+ self.flow.ipv6_nd_tll = ipv6_nd_tll
+
+ def set_mpls_label(self, mpls_label):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_MPLS_LABEL)
+ self.flow.mpls_label = mpls_label
+
+ def set_mpls_tc(self, mpls_tc):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_MPLS_TC)
+ self.flow.mpls_tc = mpls_tc
+
+ def set_mpls_bos(self, bos):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_MPLS_BOS)
+ self.flow.mpls_bos = bos
+
+ def set_pbb_isid(self, isid):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_PBB_ISID)
+ self.flow.pbb_isid = isid
+
+ def set_pbb_isid_masked(self, isid, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_PBB_ISID)
+ self.wc.pbb_isid_mask = mask
+ self.flow.pbb_isid = isid
+
+ def set_tunnel_id(self, tunnel_id):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_TUNNEL_ID)
+ self.flow.tunnel_id = tunnel_id
+
+ def set_tunnel_id_masked(self, tunnel_id, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_TUNNEL_ID)
+ self.wc.tunnel_id_mask = mask
+ self.flow.tunnel_id = tunnel_id
+
+ def set_ipv6_exthdr(self, hdr):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_EXTHDR)
+ self.flow.ipv6_exthdr = hdr
+
+ def set_ipv6_exthdr_masked(self, hdr, mask):
+ self.wc.ft_set(ofproto_v1_3.OFPXMT_OFB_IPV6_EXTHDR)
+ self.wc.ipv6_exthdr_mask = mask
+ self.flow.ipv6_exthdr = hdr
+
+
+class OFPMatchField(object):
+ _FIELDS_HEADERS = {}
+
+ @staticmethod
+ def register_field_header(headers):
+ def _register_field_header(cls):
+ for header in headers:
+ OFPMatchField._FIELDS_HEADERS[header] = cls
+ return cls
+ return _register_field_header
+
+ def __init__(self, header):
+ self.header = header
+ hasmask = (header >> 8) & 1
+ if hasmask:
+ self.n_bytes = (header & 0xff) / 2
+ else:
+ self.n_bytes = header & 0xff
+ self.length = 0
+
+ @staticmethod
+ def make(header, value, mask=None):
+ cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
+ return cls_(header, value, mask)
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (header,) = struct.unpack_from('!I', buf, offset)
+ cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
+ if cls_:
+ field = cls_.field_parser(header, buf, offset)
+ else:
+ field = OFPMatchField(header)
+ field.length = (header & 0xff) + 4
+ return field
+
+ @classmethod
+ def field_parser(cls, header, buf, offset):
+ hasmask = (header >> 8) & 1
+ mask = None
+ if hasmask:
+ pack_str = '!' + cls.pack_str[1:] * 2
+ (value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
+ else:
+ (value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
+ return cls(header, value, mask)
+
+ def serialize(self, buf, offset):
+ hasmask = (self.header >> 8) & 1
+ if hasmask:
+ self.put_w(buf, offset, self.value, self.mask)
+ else:
+ self.put(buf, offset, self.value)
+
+ def _put_header(self, buf, offset):
+ ofproto_parser.msg_pack_into('!I', buf, offset, self.header)
+ self.length += 4
+
+ def _put(self, buf, offset, value):
+ ofproto_parser.msg_pack_into(self.pack_str, buf, offset, value)
+ self.length += self.n_bytes
+
+ def put_w(self, buf, offset, value, mask):
+ self._put_header(buf, offset)
+ self._put(buf, offset + self.length, value)
+ self._put(buf, offset + self.length, mask)
+
+ def put(self, buf, offset, value):
+ self._put_header(buf, offset)
+ self._put(buf, offset + self.length, value)
+
+ def _putv6(self, buf, offset, value):
+ ofproto_parser.msg_pack_into(self.pack_str, buf, offset,
+ *value)
+ self.length += self.n_bytes
+
+ def putv6(self, buf, offset, value, mask=None):
+ self._put_header(buf, offset)
+ self._putv6(buf, offset + self.length, value)
+ if mask and len(mask):
+ self._putv6(buf, offset + self.length, mask)
+
+ def oxm_len(self):
+ return self.header & 0xff
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IN_PORT])
+class MTInPort(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTInPort, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_METADATA,
+ ofproto_v1_3.OXM_OF_METADATA_W])
+class MTMetadata(OFPMatchField):
+ pack_str = '!Q'
+
+ def __init__(self, header, value, mask=None):
+ super(MTMetadata, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IN_PHY_PORT])
+class MTInPhyPort(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTInPhyPort, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ETH_DST,
+ ofproto_v1_3.OXM_OF_ETH_DST_W])
+class MTEthDst(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTEthDst, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ETH_SRC,
+ ofproto_v1_3.OXM_OF_ETH_SRC_W])
+class MTEthSrc(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTEthSrc, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ETH_TYPE])
+class MTEthType(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTEthType, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_VLAN_VID,
+ ofproto_v1_3.OXM_OF_VLAN_VID_W])
+class MTVlanVid(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTVlanVid, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+ @classmethod
+ def field_parser(cls, header, buf, offset):
+ m = super(MTVlanVid, cls).field_parser(header, buf, offset)
+ m.value &= ~ofproto_v1_3.OFPVID_PRESENT
+ return m
+
+ def serialize(self, buf, offset):
+ self.value |= ofproto_v1_3.OFPVID_PRESENT
+ super(MTVlanVid, self).serialize(buf, offset)
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_VLAN_PCP])
+class MTVlanPcp(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTVlanPcp, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IP_DSCP])
+class MTIPDscp(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPDscp, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IP_ECN])
+class MTIPECN(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPECN, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IP_PROTO])
+class MTIPProto(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPProto, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV4_SRC,
+ ofproto_v1_3.OXM_OF_IPV4_SRC_W])
+class MTIPV4Src(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPV4Src, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV4_DST,
+ ofproto_v1_3.OXM_OF_IPV4_DST_W])
+class MTIPV4Dst(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPV4Dst, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_TCP_SRC])
+class MTTCPSrc(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTTCPSrc, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_TCP_DST])
+class MTTCPDst(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTTCPDst, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_UDP_SRC])
+class MTUDPSrc(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTUDPSrc, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_UDP_DST])
+class MTUDPDst(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTUDPDst, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_SCTP_SRC])
+class MTSCTPSrc(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTSCTPSrc, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_SCTP_DST])
+class MTSCTPDst(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTSCTPDst, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ICMPV4_TYPE])
+class MTICMPV4Type(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTICMPV4Type, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ICMPV4_CODE])
+class MTICMPV4Code(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTICMPV4Code, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ARP_OP])
+class MTArpOp(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTArpOp, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ARP_SPA,
+ ofproto_v1_3.OXM_OF_ARP_SPA_W])
+class MTArpSpa(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTArpSpa, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ARP_TPA,
+ ofproto_v1_3.OXM_OF_ARP_TPA_W])
+class MTArpTpa(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTArpTpa, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ARP_SHA,
+ ofproto_v1_3.OXM_OF_ARP_SHA_W])
+class MTArpSha(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTArpSha, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ARP_THA,
+ ofproto_v1_3.OXM_OF_ARP_THA_W])
+class MTArpTha(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTArpTha, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+class MTIPv6(object):
+ @classmethod
+ def field_parser(cls, header, buf, offset):
+ hasmask = (header >> 8) & 1
+ if hasmask:
+ pack_str = '!' + cls.pack_str[1:] * 2
+ value = struct.unpack_from(pack_str, buf, offset + 4)
+ return cls(header, list(value[:8]), list(value[8:]))
+ else:
+ value = struct.unpack_from(cls.pack_str, buf, offset + 4)
+ return cls(header, list(value))
+
+ def serialize(self, buf, offset):
+ self.putv6(buf, offset, self.value, self.mask)
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_SRC,
+ ofproto_v1_3.OXM_OF_IPV6_SRC_W])
+class MTIPv6Src(MTIPv6, OFPMatchField):
+ pack_str = '!8H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6Src, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_DST,
+ ofproto_v1_3.OXM_OF_IPV6_DST_W])
+class MTIPv6Dst(MTIPv6, OFPMatchField):
+ pack_str = '!8H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6Dst, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_FLABEL,
+ ofproto_v1_3.OXM_OF_IPV6_FLABEL_W])
+class MTIPv6Flabel(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6Flabel, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_MPLS_LABEL])
+class MTMplsLabel(OFPMatchField):
+ pack_str = '!I'
+
+ def __init__(self, header, value, mask=None):
+ super(MTMplsLabel, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ICMPV6_TYPE])
+class MTICMPV6Type(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTICMPV6Type, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_ICMPV6_CODE])
+class MTICMPV6Code(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTICMPV6Code, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_ND_TARGET])
+class MTIPv6NdTarget(MTIPv6, OFPMatchField):
+ pack_str = '!8H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6NdTarget, self).__init__(header)
+ self.value = value
+
+ def serialize(self, buf, offset):
+ self.putv6(buf, offset, self.value)
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_ND_SLL])
+class MTIPv6NdSll(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6NdSll, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_ND_TLL])
+class MTIPv6NdTll(OFPMatchField):
+ pack_str = '!6s'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6NdTll, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_MPLS_TC])
+class MTMplsTc(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTMplsTc, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_MPLS_BOS])
+class MTMplsBos(OFPMatchField):
+ pack_str = '!B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTMplsBos, self).__init__(header)
+ self.value = value
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_PBB_ISID,
+ ofproto_v1_3.OXM_OF_PBB_ISID_W])
+class MTPbbIsid(OFPMatchField):
+ pack_str = '!3B'
+
+ def __init__(self, header, value, mask=None):
+ super(MTPbbIsid, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_TUNNEL_ID,
+ ofproto_v1_3.OXM_OF_TUNNEL_ID_W])
+class MTTunnelId(OFPMatchField):
+ pack_str = '!Q'
+
+ def __init__(self, header, value, mask=None):
+ super(MTTunnelId, self).__init__(header)
+ self.value = value
+ self.mask = mask
+
+
+@OFPMatchField.register_field_header([ofproto_v1_3.OXM_OF_IPV6_EXTHDR,
+ ofproto_v1_3.OXM_OF_IPV6_EXTHDR_W])
+class MTIPv6ExtHdr(OFPMatchField):
+ pack_str = '!H'
+
+ def __init__(self, header, value, mask=None):
+ super(MTIPv6ExtHdr, self).__init__(header)
+ self.value = value
+ self.mask = mask
@_register_parser
@@ -324,7 +1379,7 @@ class OFPPacketOut(MsgBase):
class OFPFlowMod(MsgBase):
def __init__(self, datapath, cookie, cookie_mask, table_id, command,
idle_timeout, hard_timeout, priority, buffer_id, out_port,
- out_group, flags, match):
+ out_group, flags, match, instructions):
super(OFPFlowMod, self).__init__(datapath)
self.cookie = cookie
self.cookie_mask = cookie_mask
@@ -338,6 +1393,7 @@ class OFPFlowMod(MsgBase):
self.out_group = out_group
self.flags = flags
self.match = match
+ self.instructions = instructions
def _serialize_body(self):
msg_pack_into(ofproto_v1_3.OFP_FLOW_MOD_PACK_STR0, self.buf,
@@ -347,9 +1403,119 @@ class OFPFlowMod(MsgBase):
self.priority, self.buffer_id, self.out_port,
self.out_group, self.flags)
- offset = (ofproto_v1_3.OFP_OFP_FLOW_MOD_SIZE -
- ofproto_v1_3.OFP_MATCH_SIZE - ofproto_v1_3.OFP_HEADER_SIZE)
- self.match.serialize(self.buf, offset)
+ offset = (ofproto_v1_3.OFP_FLOW_MOD_SIZE -
+ ofproto_v1_3.OFP_MATCH_SIZE)
+
+ match_len = self.match.serialize(self.buf, offset)
+ offset += match_len
+
+ for inst in self.instructions:
+ inst.serialize(self.buf, offset)
+ offset += inst.len
+
+
+class OFPInstruction(object):
+ _INSTRUCTION_TYPES = {}
+
+ @staticmethod
+ def register_instruction_type(types):
+ def _register_instruction_type(cls):
+ for type_ in types:
+ OFPInstruction._INSTRUCTION_TYPES[type_] = cls
+ return cls
+ return _register_instruction_type
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (type_, len_) = struct.unpack_from('!HH', buf, offset)
+ cls_ = cls._INSTRUCTION_TYPES.get(type_)
+ return cls_.parser(buf, offset)
+
+
+@OFPInstruction.register_instruction_type([ofproto_v1_3.OFPIT_GOTO_TABLE])
+class OFPInstructionGotoTable(object):
+ def __init__(self, table_id):
+ super(OFPInstructionGotoTable, self).__init__()
+ self.type = ofproto_v1_3.OFPIT_GOTO_TABLE
+ self.len = ofproto_v1_3.OFP_INSTRUCTION_GOTO_TABLE_SIZE
+ self.table_id = table_id
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (type_, len_, table_id) = struct.unpack_from(
+ ofproto_v1_3.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
+ buf, offset)
+ return cls(table_id)
+
+ def serialize(self, buf, offset):
+ msg_pack_into(ofproto_v1_3.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
+ buf, offset, self.type, self.len, self.table_id)
+
+
+@OFPInstruction.register_instruction_type([ofproto_v1_3.OFPIT_WRITE_METADATA])
+class OFPInstructionWriteMetadata(object):
+ def __init__(self, metadata, metadata_mask):
+ super(OFPInstructionWriteMetadata, self).__init__()
+ self.type = ofproto_v1_3.OFPIT_WRITE_METADATA
+ self.len = ofproto_v1_3.OFP_INSTRUCTION_WRITE_METADATA_SIZE
+ self.metadata = metadata
+ self.metadata_mask = metadata_mask
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (type_, len_, metadata, metadata_mask) = struct.unpack_from(
+ ofproto_v1_3.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
+ buf, offset)
+ return cls(metadata, metadata_mask)
+
+ def serialize(self, buf, offset):
+ msg_pack_into(ofproto_v1_3.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
+ buf, offset, self.type, self.len, self.metadata,
+ self.metadata_mask)
+
+
+@OFPInstruction.register_instruction_type([ofproto_v1_3.OFPIT_WRITE_ACTIONS,
+ ofproto_v1_3.OFPIT_APPLY_ACTIONS,
+ ofproto_v1_3.OFPIT_CLEAR_ACTIONS])
+class OFPInstructionActions(object):
+ def __init__(self, type_, actions=None):
+ super(OFPInstructionActions, self).__init__()
+ self.type = type_
+ self.actions = actions
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (type_, len_) = struct.unpack_from(
+ ofproto_v1_3.OFP_INSTRUCTION_ACTIONS_PACK_STR,
+ buf, offset)
+
+ offset += ofproto_v1_3.OFP_INSTRUCTION_ACTIONS_SIZE
+ actions = []
+ actions_len = len_ - ofproto_v1_3.OFP_INSTRUCTION_ACTIONS_SIZE
+ while actions_len > 0:
+ a = OFPAction.parser(buf, offset)
+ actions.append(a)
+ actions_len -= a.len
+ offset += a.len
+
+ inst = cls(type_, actions)
+ inst.len = len_
+ return inst
+
+ def serialize(self, buf, offset):
+ action_offset = offset + ofproto_v1_3.OFP_INSTRUCTION_ACTIONS_SIZE
+ if self.actions:
+ for a in self.actions:
+ a.serialize(buf, action_offset)
+ action_offset += a.len
+
+ self.len = action_offset - offset
+ pad_len = utils.round_up(self.len, 8) - self.len
+ ofproto_parser.msg_pack_into("%dx" % pad_len, buf, action_offset)
+ self.len += pad_len
+
+ msg_pack_into(ofproto_v1_3.OFP_INSTRUCTION_ACTIONS_PACK_STR,
+ buf, offset, self.type, self.len)
class OFPActionHeader(object):
@@ -598,13 +1764,20 @@ class OFPActionSetField(OFPAction):
def parser(cls, buf, offset):
(type_, len_) = struct.unpack_from(
ofproto_v1_3.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
- action = cls()
- # TODO: parse OXM
+ field = OFPMatchField.parser(buf, offset + 4)
+ action = cls(field)
+ action.len = len_
return action
def serialize(self, buf, offset):
- msg_pack_into(ofproto_v1_3.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
- # TODO: serialize OXM
+ len_ = ofproto_v1_3.OFP_ACTION_SET_FIELD_SIZE + self.field.oxm_len()
+ self.len = utils.round_up(len_, 8)
+ pad_len = self.len - len_
+
+ msg_pack_into('!HH', buf, offset, self.type, self.len)
+ self.field.serialize(buf, offset + 4)
+ offset += len_
+ ofproto_parser.msg_pack_into("%dx" % pad_len, buf, offset)
@OFPAction.register_action_type(