On Wed, Jul 10, 2013 at 12:52:36PM +0900, YAMAMOTO Takashi wrote:
> a new api to compose matches. it looks like:
>
> match = OFPMatch(in_port=1,
> eth_type=0x86dd,
> ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee',
> 'ffff:ffff:ffff:ffff::'),
> ipv6_dst = '2001:db8:bd05:1d2:288a:1fc0:1:10ee')
How about allowing mask like CIDR notation?
e.g.. '2001:db8:bd05:1d2:288a:1fc0:1:10ee/64'
> the old match.set_foo and match.append_field methods are kept for now
> but will be removed later.
>
> Signed-off-by: YAMAMOTO Takashi <[email protected]>
> ---
> ryu/ofproto/ofproto_v1_3_parser.py | 56 +++++++++++++++++++++++++++++++++-
> ryu/ofproto/oxm_fields.py | 62
> ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 117 insertions(+), 1 deletion(-)
>
> diff --git a/ryu/ofproto/ofproto_v1_3_parser.py
> b/ryu/ofproto/ofproto_v1_3_parser.py
> index 77af01f..2a4e472 100644
> --- a/ryu/ofproto/ofproto_v1_3_parser.py
> +++ b/ryu/ofproto/ofproto_v1_3_parser.py
> @@ -22,6 +22,7 @@ from ryu import utils
> from ofproto_parser import StringifyMixin, MsgBase, msg_pack_into,
> msg_str_attr
> from . import ofproto_parser
> from . import ofproto_v1_3
> +from . import oxm_fields
>
> import logging
> LOG = logging.getLogger('ryu.ofproto.ofproto_v1_3_parser')
> @@ -349,7 +350,7 @@ class FlowWildcards(object):
>
>
> class OFPMatch(StringifyMixin):
> - def __init__(self, fields=[], type_=None):
> + def __init__(self, fields=[], type_=None, **kwargs):
> super(OFPMatch, self).__init__()
> self._wc = FlowWildcards()
> self._flow = Flow()
> @@ -379,10 +380,63 @@ class OFPMatch(StringifyMixin):
> f = cls(header, value, mask)
> self.fields.append(f)
>
> + # eg.
> + # OFPMatch(eth_src=('ff:ff:ff:00:00:00'), eth_type=0x800,
> + # ipv4_src='10.0.0.1')
> + fields2 = {}
> + for k, uv in kwargs.iteritems():
> + (n, v, m) = oxm_fields.from_user(k, uv)
> + # apply mask
> + if not m is None:
> + v = ''.join(chr(ord(x) & ord(y)) for (x, y)
> + in itertools.izip(v, m))
> + k2, uv2 = oxm_fields.to_user(n, v, m)
How about putting this kind of normalization into oxm_fields.py?
> + assert k2 == k
> + fields2[k2] = uv2
> + self._fields2 = fields2
> +
> def append_field(self, header, value, mask=None):
> self.fields.append(OFPMatchField.make(header, value, mask))
>
> def serialize(self, buf, offset):
> + # XXX compat
> + if self.fields or self._wc.__dict__ != FlowWildcards().__dict__:
> + return self.serialize_old(buf, offset)
> +
> + fields = []
> + for k, v in self._fields2.iteritems():
> + fields.append(oxm_fields.from_user(k, v))
fields = [oxm_fields.from_user(k, v) for k, v in self._fields2.iteritems()]
Probably it's matter of taste, though.
> +
> + # assumption: sorting by OXM type values makes fields
> + # meet ordering requirements (eg. eth_type before ipv4_src)
> + fields.sort()
> +
> + hdr_pack_str = '!HH'
> + field_offset = offset + struct.calcsize(hdr_pack_str)
> + for (n, value, mask) in fields:
> + if mask:
> + assert len(value) == len(mask)
> + pack_str = "!I%ds%ds" % (len(value), len(mask))
> + msg_pack_into(pack_str, buf, field_offset,
> + ofproto_v1_3.oxm_tlv_header_w(n, len(value)),
> + value, mask)
> + else:
> + pack_str = "!I%ds" % (len(value),)
> + msg_pack_into(pack_str, buf, field_offset,
> + ofproto_v1_3.oxm_tlv_header(n, len(value)),
> + value)
> + field_offset += struct.calcsize(pack_str)
> +
> + length = field_offset - offset
> + msg_pack_into(hdr_pack_str, 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
> +
> + def serialize_old(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)
> diff --git a/ryu/ofproto/oxm_fields.py b/ryu/ofproto/oxm_fields.py
> index a7c319d..e44962c 100644
> --- a/ryu/ofproto/oxm_fields.py
> +++ b/ryu/ofproto/oxm_fields.py
> @@ -16,6 +16,8 @@
> # See the License for the specific language governing permissions and
> # limitations under the License.
>
> +from ryu.lib import addrconv
> +
>
> class TypeDescr(object):
> pass
> @@ -25,6 +27,21 @@ class IntDescr(TypeDescr):
> def __init__(self, size):
> self.size = size
>
> + def to_user(self, bin):
> + i = 0
> + for x in xrange(self.size):
> + c = bin[:1]
> + i = i * 256 + ord(c)
> + bin = bin[1:]
> + return i
> +
> + def from_user(self, i):
> + bin = ''
> + for x in xrange(self.size):
> + bin = chr(i & 255) + bin
> + i /= 256
> + return bin
> +
> Int1 = IntDescr(1)
> Int2 = IntDescr(2)
> Int3 = IntDescr(3)
> @@ -34,14 +51,20 @@ Int8 = IntDescr(8)
>
> class MacAddr(TypeDescr):
> size = 6
> + to_user = addrconv.mac.bin_to_text
> + from_user = addrconv.mac.text_to_bin
>
>
> class IPv4Addr(TypeDescr):
> size = 4
> + to_user = addrconv.ipv4.bin_to_text
> + from_user = addrconv.ipv4.text_to_bin
>
>
> class IPv6Addr(TypeDescr):
> size = 16
> + to_user = addrconv.ipv6.bin_to_text
> + from_user = addrconv.ipv6.text_to_bin
>
>
> class D(object):
> @@ -111,3 +134,42 @@ def generate_constants(modname):
> add_attr('OFPXMT_OFB_' + uk, ofpxmt)
> add_attr('OXM_OF_' + uk, mod.oxm_tlv_header(ofpxmt, td.size))
> add_attr('OXM_OF_' + uk + '_W', mod.oxm_tlv_header_w(ofpxmt,
> td.size))
> +
> +
> +def find_field_by_name(name):
> + for t in oxm_types:
> + if t.name == name:
> + return t
> + raise KeyError
Can dict be used?
NAME_TO_FILED = dict((t.name, t) for t in oxm_types)
> +
> +
> +def from_user(name, user_value):
> + f = find_field_by_name(name)
> + t = f.type
> + if isinstance(user_value, tuple):
> + (value, mask) = user_value
> + else:
> + value = user_value
> + mask = None
> + value = t.from_user(value)
> + if not mask is None:
> + mask = t.from_user(mask)
> + return f.num, value, mask
> +
> +
> +def find_field_by_num(n):
> + for t in oxm_types:
> + if t.num == n:
> + return t
> + raise KeyError
Can dict be used?
NUM_TO_FIELD = dict((t.num, t) for t in oxm_types)
> +
> +
> +def to_user(n, v, m):
> + f = find_field_by_num(n)
> + t = f.type
> + value = t.to_user(v)
> + if m is None:
> + user_value = value
> + else:
> + user_value = (value, t.to_user(m))
> + return f.name, user_value
> --
> 1.8.1.5
>
>
> ------------------------------------------------------------------------------
> See everything from the browser to the database with AppDynamics
> Get end-to-end visibility with application monitoring from AppDynamics
> Isolate bottlenecks and diagnose root cause in seconds.
> Start your free trial of AppDynamics Pro today!
> http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel
>
--
yamahata
------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel