Support metadata in FlowMod instructions and match.

Please specify mod_flow_entry IF parameter as follows.

 flow = {'match': {'metadata': '12345/fff'},
         'actions': [ {'type': 'WRITE_METADATA',
                       'metadata': '12345',
                       'metadata_mask': 'fff'}]}



Signed-off-by: WATANABE Fumitaka <[email protected]>
---
 ryu/lib/ofctl_v1_3.py |  140 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 91 insertions(+), 49 deletions(-)

diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py
index 752d518..c23ea81 100644
--- a/ryu/lib/ofctl_v1_3.py
+++ b/ryu/lib/ofctl_v1_3.py
@@ -29,7 +29,7 @@ LOG = logging.getLogger('ryu.lib.ofctl_v1_3')
 DEFAULT_TIMEOUT = 1.0


-def to_actions(dp, acts):
+def to_instructions(dp, acts):
     inst = []
     actions = []
     ofp = dp.ofproto
@@ -100,6 +100,13 @@ def to_actions(dp, acts):
         elif action_type == 'GOTO_TABLE':
             table_id = int(a.get('table_id'))
             inst.append(parser.OFPInstructionGotoTable(table_id))
+        elif action_type == 'WRITE_METADATA':
+            metadata = int(a.get('metadata'))
+            metadata_mask = (int(a['metadata_mask'], 16)
+                             if 'metadata_mask' in a
+                             else ofproto_v1_3_parser.UINT64_MAX)
+            inst.append(
+                parser.OFPInstructionWriteMetadata(metadata, metadata_mask))
         else:
             LOG.debug('Unknown action type: %s' % action_type)

@@ -108,53 +115,68 @@ def to_actions(dp, acts):
     return inst


-def actions_to_str(instructions):
-    actions = []
+def instructions_to_str(instructions):
+    inst = []

     for instruction in instructions:
-        if not isinstance(instruction,
-                          ofproto_v1_3_parser.OFPInstructionActions):
+        if isinstance(instruction,
+                       ofproto_v1_3_parser.OFPInstructionActions):
+            for a in instruction.actions:
+                action_type = a.cls_action_type
+
+                if action_type == ofproto_v1_3.OFPAT_OUTPUT:
+                    buf = 'OUTPUT:' + str(a.port)
+                elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_OUT:
+                    buf = 'COPY_TTL_OUT'
+                elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_IN:
+                    buf = 'COPY_TTL_IN'
+                elif action_type == ofproto_v1_3.OFPAT_SET_MPLS_TTL:
+                    buf = 'SET_MPLS_TTL:' + str(a.mpls_ttl)
+                elif action_type == ofproto_v1_3.OFPAT_DEC_MPLS_TTL:
+                    buf = 'DEC_MPLS_TTL'
+                elif action_type == ofproto_v1_3.OFPAT_PUSH_VLAN:
+                    buf = 'PUSH_VLAN:' + str(a.ethertype)
+                elif action_type == ofproto_v1_3.OFPAT_POP_VLAN:
+                    buf = 'POP_VLAN'
+                elif action_type == ofproto_v1_3.OFPAT_PUSH_MPLS:
+                    buf = 'PUSH_MPLS:' + str(a.ethertype)
+                elif action_type == ofproto_v1_3.OFPAT_POP_MPLS:
+                    buf = 'POP_MPLS'
+                elif action_type == ofproto_v1_3.OFPAT_OFPAT_SET_QUEUE:
+                    buf = 'SET_QUEUE:' + str(a.queue_id)
+                elif action_type == ofproto_v1_3.OFPAT_GROUP:
+                    pass
+                elif action_type == ofproto_v1_3.OFPAT_SET_NW_TTL:
+                    buf = 'SET_NW_TTL:' + str(a.nw_ttl)
+                elif action_type == ofproto_v1_3.OFPAT_DEC_NW_TTL:
+                    buf = 'DEC_NW_TTL'
+                elif action_type == ofproto_v1_3.OFPAT_SET_FIELD:
+                    buf = 'SET_FIELD: {%s:%s}' % (a.field, a.value)
+                elif action_type == ofproto_v1_3.OFPAT_PUSH_PBB:
+                    buf = 'PUSH_PBB:' + str(a.ethertype)
+                elif action_type == ofproto_v1_3.OFPAT_POP_PBB:
+                    buf = 'POP_PBB'
+                else:
+                    buf = 'UNKNOWN'
+                inst.append(buf)
+
+        elif isinstance(instruction,
+                          ofproto_v1_3_parser.OFPInstructionGotoTable):
+            buf = 'GOTO_TABLE:' + str(instruction.table_id)
+            inst.append(buf)
+
+        elif isinstance(instruction,
+                          ofproto_v1_3_parser.OFPInstructionWriteMetadata):
+            buf = ('WRITE_METADATA:%d/0x%x' % (instruction.metadata,
+                                             instruction.metadata_mask)
+                   if instruction.metadata_mask
+                   else 'WRITE_METADATA:%d' % instruction.metadata)
+            inst.append(buf)
+
+        else:
             continue
-        for a in instruction.actions:
-            action_type = a.cls_action_type
-
-            if action_type == ofproto_v1_3.OFPAT_OUTPUT:
-                buf = 'OUTPUT:' + str(a.port)
-            elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_OUT:
-                buf = 'COPY_TTL_OUT'
-            elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_IN:
-                buf = 'COPY_TTL_IN'
-            elif action_type == ofproto_v1_3.OFPAT_SET_MPLS_TTL:
-                buf = 'SET_MPLS_TTL:' + str(a.mpls_ttl)
-            elif action_type == ofproto_v1_3.OFPAT_DEC_MPLS_TTL:
-                buf = 'DEC_MPLS_TTL'
-            elif action_type == ofproto_v1_3.OFPAT_PUSH_VLAN:
-                buf = 'PUSH_VLAN:' + str(a.ethertype)
-            elif action_type == ofproto_v1_3.OFPAT_POP_VLAN:
-                buf = 'POP_VLAN'
-            elif action_type == ofproto_v1_3.OFPAT_PUSH_MPLS:
-                buf = 'PUSH_MPLS:' + str(a.ethertype)
-            elif action_type == ofproto_v1_3.OFPAT_POP_MPLS:
-                buf = 'POP_MPLS'
-            elif action_type == ofproto_v1_3.OFPAT_OFPAT_SET_QUEUE:
-                buf = 'SET_QUEUE:' + str(a.queue_id)
-            elif action_type == ofproto_v1_3.OFPAT_GROUP:
-                pass
-            elif action_type == ofproto_v1_3.OFPAT_SET_NW_TTL:
-                buf = 'SET_NW_TTL:' + str(a.nw_ttl)
-            elif action_type == ofproto_v1_3.OFPAT_DEC_NW_TTL:
-                buf = 'DEC_NW_TTL'
-            elif action_type == ofproto_v1_3.OFPAT_SET_FIELD:
-                buf = 'SET_FIELD: {%s:%s}' % (a.field, a.value)
-            elif action_type == ofproto_v1_3.OFPAT_PUSH_PBB:
-                buf = 'PUSH_PBB:' + str(a.ethertype)
-            elif action_type == ofproto_v1_3.OFPAT_POP_PBB:
-                buf = 'POP_PBB'
-            else:
-                buf = 'UNKNOWN'
-            actions.append(buf)

-    return actions
+    return inst


 def to_match(dp, attrs):
@@ -170,7 +192,8 @@ def to_match(dp, attrs):
                'nw_proto': int,
                'tp_src': int,
                'tp_dst': int,
-               'mpls_label': int}
+               'mpls_label': int,
+               'metadata': to_match_metadata}

     match_append = {'in_port': match.set_in_port,
                     'dl_src': match.set_dl_src,
@@ -182,7 +205,8 @@ def to_match(dp, attrs):
                     'nw_proto': match.set_ip_proto,
                     'tp_src': to_match_tpsrc,
                     'tp_dst': to_match_tpdst,
-                    'mpls_label': match.set_mpls_label}
+                    'mpls_label': match.set_mpls_label,
+                    'metadata': match.set_metadata_masked}

     for key, value in attrs.items():
         if key in convert:
@@ -196,6 +220,11 @@ def to_match(dp, attrs):
             elif key == 'tp_src' or key == 'tp_dst':
                 # tp_src/dst
                 match = match_append[key](value, match, attrs)
+            elif key == 'metadata':
+                # metadata
+                metadata = value[0]
+                metadata_mask = value[1]
+                match_append[key](metadata, metadata_mask)
             else:
                 # others
                 match_append[key](value)
@@ -239,6 +268,14 @@ def to_match_ip(value):
     return ipv4, netmask


+def to_match_metadata(value):
+    if '/'in value:
+        metadata = value.split('/')
+        return int(metadata[0]), int(metadata[1], 16)
+    else:
+        return int(value), ofproto_v1_3_parser.UINT64_MAX
+
+
 def match_to_str(ofmatch):
     keys = {ofproto_v1_3.OXM_OF_IN_PORT: 'in_port',
             ofproto_v1_3.OXM_OF_ETH_SRC: 'dl_src',
@@ -253,7 +290,9 @@ def match_to_str(ofmatch):
             ofproto_v1_3.OXM_OF_TCP_SRC: 'tp_src',
             ofproto_v1_3.OXM_OF_TCP_DST: 'tp_dst',
             ofproto_v1_3.OXM_OF_UDP_SRC: 'tp_src',
-            ofproto_v1_3.OXM_OF_UDP_DST: 'tp_dst'}
+            ofproto_v1_3.OXM_OF_UDP_DST: 'tp_dst',
+            ofproto_v1_3.OXM_OF_METADATA: 'metadata',
+            ofproto_v1_3.OXM_OF_METADATA_W: 'metadata'}

     match = {}
     for match_field in ofmatch.fields:
@@ -262,6 +301,9 @@ def match_to_str(ofmatch):
             value = mac.haddr_to_str(match_field.value)
         elif key == 'nw_src' or key == 'nw_dst':
             value = match_ip_to_str(match_field.value, match_field.mask)
+        elif key == 'metadata':
+            value = ('%d/0x%x' % (match_field.value, match_field.mask)
+                     if match_field.mask else '%d' % match_field.value)
         else:
             value = match_field.value
         match.setdefault(key, value)
@@ -329,7 +371,7 @@ def get_flow_stats(dp, waiters):
     flows = []
     for msg in msgs:
         for stats in msg.body:
-            actions = actions_to_str(stats.instructions)
+            actions = instructions_to_str(stats.instructions)
             match = match_to_str(stats.match)

             s = {'priority': stats.priority,
@@ -388,7 +430,7 @@ def mod_flow_entry(dp, flow, cmd):
     out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
     flags = int(flow.get('flags', 0))
     match = to_match(dp, flow.get('match', {}))
-    inst = to_actions(dp, flow.get('actions', []))
+    inst = to_instructions(dp, flow.get('actions', []))

     flow_mod = dp.ofproto_parser.OFPFlowMod(
         dp, cookie, cookie_mask, table_id, cmd, idle_timeout,
-- 1.7.10.4



------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to