When flow fields are sorted before dumping in ovs-ofctl, each
significant field is extracted for sorting. However, in the case of
tunnel metadata a mapping table is necessary to know where each
field begins and ends. This information is current stripped off before
fetching the field data and returned field is simply zeroed. This
makes sorting based on tunnel metadata non-deterministic.

We have the tunnel allocation stored in match metadata with each
flow, so we can simply extract the data from there rather than
trying to build and populate a global mapping table.

Signed-off-by: Jesse Gross <je...@kernel.org>
---
 tests/ovs-ofctl.at    | 18 +++++++++++++++++-
 utilities/ovs-ofctl.c | 24 ++++++++++++++++++++++--
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index d966fc2..8747a06 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -2639,10 +2639,14 @@ priority=6,in_port=1027 actions=output:64
 priority=2,in_port=1025 actions=output:47
 priority=8,tcp,tp_src=5 actions=drop
 priority=9,tcp,tp_src=6 actions=drop
+priority=10,tun_metadata0=0xab actions=drop
+priority=11,tun_metadata0=0xcd actions=drop
 ]])
 
+AT_CHECK([ovs-ofctl add-tlv-map br0 
"{class=0xffff,type=0,len=4}->tun_metadata0"])
 AT_CHECK([ovs-ofctl add-flows br0 allflows.txt
 ], [0], [ignore])
+
 AT_CHECK([ovs-ofctl --sort dump-flows br0 | ofctl_strip], [0], [dnl
  priority=1,in_port=1026 actions=output:45
  priority=2,in_port=1025 actions=output:47
@@ -2653,8 +2657,12 @@ AT_CHECK([ovs-ofctl --sort dump-flows br0 | 
ofctl_strip], [0], [dnl
  priority=7,in_port=1029 actions=output:43
  priority=8,tcp,tp_src=5 actions=drop
  priority=9,tcp,tp_src=6 actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
+ priority=11,tun_metadata0=0xcd actions=drop
 ])
 AT_CHECK([ovs-ofctl --rsort dump-flows br0 | ofctl_strip], [0], [dnl
+ priority=11,tun_metadata0=0xcd actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
  priority=9,tcp,tp_src=6 actions=drop
  priority=8,tcp,tp_src=5 actions=drop
  priority=7,in_port=1029 actions=output:43
@@ -2673,6 +2681,8 @@ AT_CHECK([ovs-ofctl --sort=in_port dump-flows br0 | 
ofctl_strip], [0], [dnl
  priority=7,in_port=1029 actions=output:43
  priority=5,in_port=1029 actions=output:43
  priority=4,in_port=23213 actions=output:42
+ priority=11,tun_metadata0=0xcd actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
  priority=9,tcp,tp_src=6 actions=drop
  priority=8,tcp,tp_src=5 actions=drop
 ])
@@ -2684,12 +2694,16 @@ AT_CHECK([ovs-ofctl --rsort=in_port dump-flows br0 | 
ofctl_strip], [0], [dnl
  priority=6,in_port=1027 actions=output:64
  priority=1,in_port=1026 actions=output:45
  priority=2,in_port=1025 actions=output:47
+ priority=11,tun_metadata0=0xcd actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
  priority=9,tcp,tp_src=6 actions=drop
  priority=8,tcp,tp_src=5 actions=drop
 ])
 AT_CHECK([ovs-ofctl --sort=tcp_src dump-flows br0 | ofctl_strip], [0], [dnl
  priority=8,tcp,tp_src=5 actions=drop
  priority=9,tcp,tp_src=6 actions=drop
+ priority=11,tun_metadata0=0xcd actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
  priority=7,in_port=1029 actions=output:43
  priority=6,in_port=1027 actions=output:64
  priority=5,in_port=1029 actions=output:43
@@ -2699,7 +2713,7 @@ AT_CHECK([ovs-ofctl --sort=tcp_src dump-flows br0 | 
ofctl_strip], [0], [dnl
  priority=1,in_port=1026 actions=output:45
 ])
 AT_CHECK(
-  [ovs-ofctl --sort=in_port --sort=tcp_src dump-flows br0 | ofctl_strip], [0],
+  [ovs-ofctl --sort=in_port --sort=tcp_src --sort=tun_metadata0 dump-flows br0 
| ofctl_strip], [0],
   [ priority=2,in_port=1025 actions=output:47
  priority=1,in_port=1026 actions=output:45
  priority=6,in_port=1027 actions=output:64
@@ -2709,6 +2723,8 @@ AT_CHECK(
  priority=4,in_port=23213 actions=output:42
  priority=8,tcp,tp_src=5 actions=drop
  priority=9,tcp,tp_src=6 actions=drop
+ priority=10,tun_metadata0=0xab actions=drop
+ priority=11,tun_metadata0=0xcd actions=drop
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index dbeeebf..cf27d26 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -1194,6 +1194,26 @@ ofctl_dump_flows__(int argc, char *argv[], bool 
aggregate)
     vconn_close(vconn);
 }
 
+static void
+get_match_field(const struct mf_field *field, const struct match *match,
+                union mf_value *value)
+{
+    if (!match->tun_md.valid || (field->id < MFF_TUN_METADATA0 ||
+                                 field->id >= MFF_TUN_METADATA0 +
+                                              TUN_METADATA_NUM_OPTS)) {
+        mf_get_value(field, &match->flow, value);
+    } else {
+        const struct tun_metadata_loc *loc = &match->tun_md.entry[field->id -
+                                                         
MFF_TUN_METADATA0].loc;
+
+        /* Since we don't have a tunnel mapping table, extract the value
+         * from the locally allocated location in the match. */
+        memset(value, 0, field->n_bytes - loc->len);
+        memcpy(value->tun_metadata + field->n_bytes - loc->len,
+               match->flow.tunnel.metadata.opts.u8 + loc->c.offset, loc->len);
+    }
+}
+
 static int
 compare_flows(const void *afs_, const void *bfs_)
 {
@@ -1226,8 +1246,8 @@ compare_flows(const void *afs_, const void *bfs_)
             } else {
                 union mf_value aval, bval;
 
-                mf_get_value(f, &a->flow, &aval);
-                mf_get_value(f, &b->flow, &bval);
+                get_match_field(f, a, &aval);
+                get_match_field(f, b, &bval);
                 ret = memcmp(&aval, &bval, f->n_bytes);
             }
         }
-- 
2.7.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to