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>
This commit is contained in:
Simon Horman 2012-03-13 09:06:17 +09:00 committed by FUJITA Tomonori
parent bb7d3e8dd2
commit 36a62fa2f1
3 changed files with 95 additions and 1 deletions

View File

@ -16,6 +16,8 @@
DONTCARE = '\x00' * 6
BROADCAST = '\xff' * 6
MULTICAST = '\xfe' + '\xff' * 5
UNICAST = '\x01' + '\x00' * 5
def is_multicast(addr):

View File

@ -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)
@ -125,6 +180,25 @@ class MFInPort(MFField):
return self._put(buf, offset, rule.flow.in_port)
@_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):
@ -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

View File

@ -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)