summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2012-03-13 09:06:17 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-03-13 21:41:31 -0700
commit36a62fa2f1e2a1718f3a58eb09d01619c859e91a (patch)
treed17b53942a4c84535b2e0abf30e55d717b2c70d9
parentbb7d3e8dd21c4494701101b1af112a58ba1ff87c (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.py2
-rw-r--r--ryu/ofproto/nx_match.py91
-rw-r--r--ryu/ofproto/ofproto_v1_0.py3
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)