diff options
author | Simon Horman <horms@verge.net.au> | 2012-03-13 09:06:17 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2012-03-13 21:41:31 -0700 |
commit | 36a62fa2f1e2a1718f3a58eb09d01619c859e91a (patch) | |
tree | d17b53942a4c84535b2e0abf30e55d717b2c70d9 | |
parent | bb7d3e8dd21c4494701101b1af112a58ba1ff87c (diff) |
NXM: Add MFEthDst class
This is to handle ETH_DST NXM fields.
This will used when sending NXT_FLOW_MOD messages.
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/mac.py | 2 | ||||
-rw-r--r-- | ryu/ofproto/nx_match.py | 91 | ||||
-rw-r--r-- | ryu/ofproto/ofproto_v1_0.py | 3 |
3 files changed, 95 insertions, 1 deletions
diff --git a/ryu/lib/mac.py b/ryu/lib/mac.py index be4d7d60..8a7009cd 100644 --- a/ryu/lib/mac.py +++ b/ryu/lib/mac.py @@ -16,6 +16,8 @@ DONTCARE = '\x00' * 6 BROADCAST = '\xff' * 6 +MULTICAST = '\xfe' + '\xff' * 5 +UNICAST = '\x01' + '\x00' * 5 def is_multicast(addr): diff --git a/ryu/ofproto/nx_match.py b/ryu/ofproto/nx_match.py index 2b753bad..77abcb63 100644 --- a/ryu/ofproto/nx_match.py +++ b/ryu/ofproto/nx_match.py @@ -17,6 +17,7 @@ import struct from ryu import exception +from ryu.lib import mac from . import ofproto_parser from . import ofproto_v1_0 @@ -27,10 +28,15 @@ LOG = logging.getLogger('ryu.ofproto.nx_match') UINT64_MAX = (1 << 64) - 1 FWW_IN_PORT = 1 << 0 +FWW_DL_SRC = 1 << 2 +FWW_DL_DST = 1 << 3 +# No corresponding OFPFW_* bits +FWW_ETH_MCAST = 1 << 1 FWW_ALL = (1 << 13) - 1 MF_PACK_STRING_BE64 = '!Q' MF_PACK_STRING_BE16 = '!H' +MF_PACK_STRING_MAC = '!6s' _MF_FIELDS = {} @@ -44,6 +50,44 @@ class FlowWildcards(object): self.tun_id_mask = 0 self.wildcards = FWW_ALL + def set_dl_dst_mask(self, mask): + assert mask[0] in ['\x00', '\x01', '\xfe', '\xff'] + if mask[0] == '\x00': + self.wildcards |= FWW_DL_DST | FWW_ETH_MCAST + elif mask[0] == '\x01': + self.wildcards = (self.wildcards | FWW_DL_DST) & ~FWW_ETH_MCAST + elif mask[0] == '\xfe': + self.wildcards = (self.wildcards & ~FWW_DL_DST) | FWW_ETH_MCAST + elif mask[0] == '\xff': + self.wildcards &= ~(FWW_DL_DST | FWW_ETH_MCAST) + + def to_dl_dst_mask(self): + key = self.wildcards & (FWW_DL_DST | FWW_ETH_MCAST) + if key == 0: + return mac.BROADCAST + elif key == FWW_DL_DST: + return mac.UNICAST + elif key == FWW_ETH_MCAST: + return mac.MULTICAST + else: + return mac.DONTCARE + + +def flow_wildcards_is_dl_dst_mask_valid(cls, mask): + # 00:00:00:00:00:00, 01:00:00:00:00:00, fe:ff:ff:ff:ff:ff or + # ff:ff:ff:ff:ff:ff + # + # The trailing octects should all be the same + # so the set of those values should only have one element + # which can be compared with the desired value + s = set(mask[1:]) + if ((len(s) != 1) or + (mask[0] in ['\x00', '\x01']) and ('\x00' in s) or + (mask[0] in ['\xff', '\xfe']) and ('\xff' in s)): + return True + else: + return False + class ClsRule(object): def __init__(self): @@ -54,6 +98,17 @@ class ClsRule(object): self.wc.wildcards &= ~FWW_IN_PORT self.flow.in_port = port + def set_dl_dst(self, dl_dst): + self.wc.wildcards &= ~(FWW_DL_DST | FWW_ETH_MCAST) + self.flow.dl_dst = dl_dst + + def set_dl_dst_masked(self, dl_dst, mask): + self.wc.set_dl_dst_mask(mask) + # bit-wise and of the corresponding elements of dl_dst and mask + self.flow.dl_dst = reduce(lambda x, y: x + y, + map(lambda x: chr(ord(x[0]) & ord(x[1])), + zip(dl_dst, mask))) + def set_tun_id(self, tun_id): self.set_tun_id_masked(tun_id, UINT64_MAX) @@ -126,6 +181,25 @@ class MFInPort(MFField): @_register_make +@_set_nxm_headers([ofproto_v1_0.NXM_OF_ETH_DST, ofproto_v1_0.NXM_OF_ETH_DST_W]) +class MFEthDst(MFField): + @classmethod + def make(cls): + return cls(MF_PACK_STRING_MAC) + + def put(self, buf, offset, rule): + mask = FWW_DL_DST | FWW_ETH_MCAST + key = rule.wc.wildcards & mask + if key == mask: + return 0 + if key == 0: + return self._put(buf, offset, rule.flow.dl_dst) + else: + return self.putw(buf, offset, rule.flow.dl_dst, + rule.wc.to_dl_dst_mask()) + + +@_register_make @_set_nxm_headers([ofproto_v1_0.NXM_NX_TUN_ID, ofproto_v1_0.NXM_NX_TUN_ID_W]) class MFTunId(MFField): @classmethod @@ -142,7 +216,10 @@ def serialize_nxm_match(rule, buf, offset): if not rule.wc.wildcards & FWW_IN_PORT: offset += nxm_put(buf, offset, ofproto_v1_0.NXM_OF_IN_PORT, rule) - # XXX: Ethernet. + # Ethernet. + offset += nxm_put_eth_dst(buf, offset, rule) + # XXX: Ethernet Source and Type + # XXX: 802.1Q # XXX: L3 @@ -171,6 +248,18 @@ def nxm_put(buf, offset, header, rule): return len + mf.put(buf, offset + len, rule) +def nxm_put_eth_dst(buf, offset, rule): + mask = FWW_DL_DST | FWW_ETH_MCAST + key = rule.wc.wildcards & mask + if key == mask: + return 0 + elif key == 0: + header = ofproto_v1_0.NXM_OF_ETH_DST + else: + header = ofproto_v1_0.NXM_OF_ETH_DST_W + return nxm_put(buf, offset, header, rule) + + def round_up(length): return (length + 7) / 8 * 8 # Round up to a multiple of 8 diff --git a/ryu/ofproto/ofproto_v1_0.py b/ryu/ofproto/ofproto_v1_0.py index 0d6a36c9..b322d3e9 100644 --- a/ryu/ofproto/ofproto_v1_0.py +++ b/ryu/ofproto/ofproto_v1_0.py @@ -517,6 +517,9 @@ def nxm_header_w(vendor, field, length): NXM_OF_IN_PORT = nxm_header(0x0000, 0, 2) +NXM_OF_ETH_DST = nxm_header(0x0000, 1, 6) +NXM_OF_ETH_DST_W = nxm_header_w(0x0000, 1, 6) + NXM_NX_TUN_ID = nxm_header(0x0001, 16, 8) NXM_NX_TUN_ID_W = nxm_header_w(0x0001, 16, 8) |