diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2012-11-22 16:33:22 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2012-11-23 11:38:05 +0900 |
commit | fad94da2d49618dc7bb009c763f28c3a34d27fc5 (patch) | |
tree | 2e85b4d197bf176d792ebef9b25b54d3adc78670 | |
parent | 4152e5d229b2c9265a0367e2549ff6ecba9c7440 (diff) |
of1.3: support OFPMatch
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/ofproto/ofproto_v1_3.py | 76 | ||||
-rw-r--r-- | ryu/ofproto/ofproto_v1_3_parser.py | 1191 |
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( |