A conjunctive flow consists of two or more multiple flows with
conjunction actions. When input to the ofproto/trace command
matches a conjunctive flow, it outputs flows of all dimensions.

Signed-off-by: Nobuhiro MIKI <[email protected]>
---
 lib/classifier.c             | 35 +++++++++++++++++++++++++++++++++++
 lib/classifier.h             |  2 ++
 lib/flow.h                   |  1 +
 ofproto/ofproto-dpif-xlate.c | 31 +++++++++++++++++++++++++++++++
 tests/classifier.at          | 11 +++++++++++
 5 files changed, 80 insertions(+)

diff --git a/lib/classifier.c b/lib/classifier.c
index 18dbfc83ad44..c580301318cc 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -169,6 +169,7 @@ cls_rule_init__(struct cls_rule *rule, unsigned int 
priority)
     rculist_init(&rule->node);
     *CONST_CAST(int *, &rule->priority) = priority;
     ovsrcu_init(&rule->cls_match, NULL);
+    ovs_list_init(CONST_CAST(struct ovs_list *, &rule->conj_flows));
 }
 
 /* Initializes 'rule' to match packets specified by 'match' at the given
@@ -218,6 +219,36 @@ cls_rule_move(struct cls_rule *dst, struct cls_rule *src)
                    CONST_CAST(struct minimatch *, &src->match));
 }
 
+static void
+cls_rule_free_conj_flows(const struct cls_rule *rule)
+{
+    struct miniflow *flow;
+
+    LIST_FOR_EACH_POP (flow, list_node,
+                       CONST_CAST(struct ovs_list *, &rule->conj_flows)) {
+        free(flow);
+    }
+}
+
+static void
+cls_rule_append_conj_flows(const struct cls_rule *rule,
+                           struct cls_conjunction_set **soft, size_t n_soft)
+{
+    const struct miniflow *src;
+    struct miniflow *dst;
+    size_t data_size;
+    int i;
+
+    for (i = 0; i < n_soft; i++) {
+        src = &soft[i]->match->flow;
+        data_size = miniflow_alloc(&dst, 1, src);
+        miniflow_clone(dst, src, data_size / sizeof(uint64_t));
+
+        ovs_list_push_back(CONST_CAST(struct ovs_list *, &rule->conj_flows),
+                           &dst->list_node);
+    }
+}
+
 /* Frees memory referenced by 'rule'.  Doesn't free 'rule' itself (it's
  * normally embedded into a larger structure).
  *
@@ -226,6 +257,8 @@ void
 cls_rule_destroy(struct cls_rule *rule)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
+    cls_rule_free_conj_flows(rule);
+
     /* Must not be in a classifier. */
     ovs_assert(!get_cls_match_protected(rule));
 
@@ -1101,6 +1134,8 @@ classifier_lookup__(const struct classifier *cls, 
ovs_version_t version,
                 flow->conj_id = saved_conj_id;
 
                 if (rule) {
+                    cls_rule_free_conj_flows(rule);
+                    cls_rule_append_conj_flows(rule, soft, n_soft);
                     free_conjunctive_matches(&matches,
                                              cm_stubs, ARRAY_SIZE(cm_stubs));
                     if (soft != soft_stub) {
diff --git a/lib/classifier.h b/lib/classifier.h
index f646a8f7429b..0ef0a520e207 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -299,6 +299,7 @@
  * parallel to the rule's removal. */
 
 #include "cmap.h"
+#include "openvswitch/list.h"
 #include "openvswitch/match.h"
 #include "openvswitch/meta-flow.h"
 #include "pvector.h"
@@ -357,6 +358,7 @@ struct cls_rule {
     OVSRCU_TYPE(struct cls_match *) cls_match;  /* NULL if not in a
                                                  * classifier. */
     const struct minimatch match; /* Matching rule. */
+    const struct ovs_list conj_flows;
 };
 
 /* Constructor/destructor.  Must run single-threaded. */
diff --git a/lib/flow.h b/lib/flow.h
index a9d026e1ce3b..d94ae95394fd 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -517,6 +517,7 @@ flowmap_next_index(struct flowmap_aux *aux, size_t *idx)
  * A miniflow is always dynamically allocated so that the maps are followed by
  * at least as many elements as there are 1-bits in maps. */
 struct miniflow {
+    struct ovs_list list_node;
     struct flowmap map;
     /* Followed by:
      *     uint64_t values[n];
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index be4bd6657688..0fa5dac2be90 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -866,6 +866,35 @@ xlate_report_action_set(const struct xlate_ctx *ctx, const 
char *verb)
     }
 }
 
+static void
+xlate_report_conj_matches(const struct xlate_ctx *ctx,
+                          const struct cls_rule *rule)
+{
+    struct miniflow *conj_flow;
+    struct match match;
+    struct flow f;
+    int count;
+    int i = 0;
+
+    count = ovs_list_size(&rule->conj_flows);
+
+    LIST_FOR_EACH (conj_flow, list_node, &rule->conj_flows) {
+        miniflow_expand(conj_flow, &f);
+
+        match_init(&match, &f, ctx->xin->wc);
+        match.wc.masks.conj_id = 0;
+        match.wc.masks.recirc_id = 0;
+        match.wc.masks.in_port.ofp_port = 0;
+
+        struct ds s = DS_EMPTY_INITIALIZER;
+
+        match_format(&match, NULL, &s, OFP_DEFAULT_PRIORITY);
+        xlate_report_debug(ctx, OFT_DETAIL, "conj(%d/%d). %s",
+                           ++i, count, ds_cstr(&s));
+
+        ds_destroy(&s);
+    }
+}
 
 /* If tracing is enabled in 'ctx', appends a node representing 'rule' (in
  * OpenFlow table 'table_id') to the trace and makes this node the parent for
@@ -918,6 +947,8 @@ xlate_report_table(const struct xlate_ctx *ctx, struct 
rule_dpif *rule,
     ctx->xin->trace = &oftrace_report(ctx->xin->trace, OFT_TABLE,
                                       ds_cstr(&s))->subs;
     ds_destroy(&s);
+
+    xlate_report_conj_matches(ctx, &rule->up.cr);
 }
 
 /* If tracing is enabled in 'ctx', adds an OFT_DETAIL trace node to 'ctx'
diff --git a/tests/classifier.at b/tests/classifier.at
index de2705653e00..8ce00c2b835e 100644
--- a/tests/classifier.at
+++ b/tests/classifier.at
@@ -278,6 +278,17 @@ for src in 0 1 2 3 4 5 6 7; do
 ])
     done
 done
+dnl Check detailed output for conjunctive match.
+AT_CHECK([ovs-appctl ofproto/trace br0 
"in_port=1,dl_type=0x0800,nw_src=10.0.0.7,nw_dst=10.0.0.5" | grep conj], [0], 
[dnl
+ 0. conj_id=1, priority 32768
+     -> conj(1/2). ip,nw_src=10.0.0.7,nw_dst=0.0.0.0,nw_frag=no
+     -> conj(2/2). ip,nw_src=0.0.0.0,nw_dst=10.0.0.5,nw_frag=no
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 
"in_port=1,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.5" | grep conj], [0], 
[dnl
+ 0. conj_id=1, priority 32768
+     -> conj(1/2). ip,nw_src=10.0.0.1,nw_dst=0.0.0.0,nw_frag=no
+     -> conj(2/2). ip,nw_src=0.0.0.0,nw_dst=10.0.0.5,nw_frag=no
+])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
-- 
2.31.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to