summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2014-01-29 12:05:55 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2014-01-29 12:42:54 +0900
commit5231ba3b3876fb6da01f6c63e3a9704a9c20103d (patch)
tree14a526c09ec2ede222c8f1bccfcb68753df815b6
parentec18b3f0f102d0ec1c4c228a3f40f19996997bf8 (diff)
Add OF1.4 SetField action support
Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/ofproto/ofproto_v1_4_parser.py123
1 files changed, 123 insertions, 0 deletions
diff --git a/ryu/ofproto/ofproto_v1_4_parser.py b/ryu/ofproto/ofproto_v1_4_parser.py
index 0c790c9f..8b4ee60d 100644
--- a/ryu/ofproto/ofproto_v1_4_parser.py
+++ b/ryu/ofproto/ofproto_v1_4_parser.py
@@ -2322,3 +2322,126 @@ class OFPActionSetQueue(OFPAction):
def serialize(self, buf, offset):
msg_pack_into(ofproto.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
offset, self.type, self.len, self.queue_id)
+
+
+@OFPAction.register_action_type(ofproto.OFPAT_SET_FIELD,
+ ofproto.OFP_ACTION_SET_FIELD_SIZE)
+class OFPActionSetField(OFPAction):
+ """
+ Set field action
+
+ This action modifies a header field in the packet.
+
+ ================ ======================================================
+ Attribute Description
+ ================ ======================================================
+ field Instance of ``OFPMatchField``
+ ================ ======================================================
+ """
+ def __init__(self, field=None, **kwargs):
+ # old api
+ # OFPActionSetField(field)
+ # new api
+ # OFPActionSetField(eth_src="00:00:00:00:00")
+ super(OFPActionSetField, self).__init__()
+ if isinstance(field, OFPMatchField):
+ # old api compat
+ assert len(kwargs) == 0
+ self.field = field
+ else:
+ # new api
+ assert len(kwargs) == 1
+ key = kwargs.keys()[0]
+ value = kwargs[key]
+ assert isinstance(key, (str, unicode))
+ assert not isinstance(value, tuple) # no mask
+ self.key = key
+ self.value = value
+
+ @classmethod
+ def parser(cls, buf, offset):
+ (type_, len_) = struct.unpack_from(
+ ofproto.OFP_ACTION_SET_FIELD_PACK_STR, buf, offset)
+ (n, value, mask, _len) = ofproto.oxm_parse(buf, offset + 4)
+ k, uv = ofproto.oxm_to_user(n, value, mask)
+ action = cls(**{k: uv})
+ action.len = len_
+
+ # old api compat
+ action.field = OFPMatchField.parser(buf, offset + 4)
+
+ return action
+
+ def serialize(self, buf, offset):
+ # old api compat
+ if self._composed_with_old_api():
+ return self.serialize_old(buf, offset)
+
+ n, value, mask = ofproto.oxm_from_user(self.key, self.value)
+ len_ = ofproto.oxm_serialize(n, value, mask, buf, offset + 4)
+ self.len = utils.round_up(4 + len_, 8)
+ msg_pack_into('!HH', buf, offset, self.type, self.len)
+ pad_len = self.len - (4 + len_)
+ ofproto_parser.msg_pack_into("%dx" % pad_len, buf, offset + 4 + len_)
+
+ # XXX old api compat
+ def serialize_old(self, buf, offset):
+ len_ = ofproto.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)
+
+ # XXX old api compat
+ def _composed_with_old_api(self):
+ return not hasattr(self, 'value')
+
+ def to_jsondict(self):
+ # XXX old api compat
+ if self._composed_with_old_api():
+ # copy object first because serialize_old is destructive
+ o2 = OFPActionSetField(self.field)
+ # serialize and parse to fill new fields
+ buf = bytearray()
+ o2.serialize(buf, 0)
+ o = OFPActionSetField.parser(str(buf), 0)
+ else:
+ o = self
+ return {
+ self.__class__.__name__: {
+ 'field': ofproto.oxm_to_jsondict(self.key, self.value)
+ }
+ }
+
+ @classmethod
+ def from_jsondict(cls, dict_):
+ k, v = ofproto.oxm_from_jsondict(dict_['field'])
+ o = OFPActionSetField(**{k: v})
+
+ # XXX old api compat
+ # serialize and parse to fill old attributes
+ buf = bytearray()
+ o.serialize(buf, 0)
+ return OFPActionSetField.parser(str(buf), 0)
+
+ # XXX old api compat
+ def __str__(self):
+ # XXX old api compat
+ if self._composed_with_old_api():
+ # copy object first because serialize_old is destructive
+ o2 = OFPActionSetField(self.field)
+ # serialize and parse to fill new fields
+ buf = bytearray()
+ o2.serialize(buf, 0)
+ o = OFPActionSetField.parser(str(buf), 0)
+ else:
+ o = self
+ return super(OFPActionSetField, o).__str__()
+
+ __repr__ = __str__
+
+ def stringify_attrs(self):
+ yield (self.key, self.value)