diff options
author | Simon Horman <horms@verge.net.au> | 2014-01-29 12:05:55 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2014-01-29 12:42:54 +0900 |
commit | 5231ba3b3876fb6da01f6c63e3a9704a9c20103d (patch) | |
tree | 14a526c09ec2ede222c8f1bccfcb68753df815b6 | |
parent | ec18b3f0f102d0ec1c4c228a3f40f19996997bf8 (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.py | 123 |
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) |