ofproto-dpif: Improve code clarity and comments on recirc changes to rule_dpif_lookup()
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index cc36a0f..983cad5 100644 (file)
@@ -362,6 +362,18 @@ ofproto_dpif_flow_mod(struct ofproto_dpif *ofproto,
     ofproto_flow_mod(&ofproto->up, fm);
 }
 
+/* Resets the modified time for 'rule' or an equivalent rule. If 'rule' is not
+ * in the classifier, but an equivalent rule is, unref 'rule' and ref the new
+ * rule. Otherwise if 'rule' is no longer installed in the classifier,
+ * reinstall it.
+ *
+ * Returns the rule whose modified time has been reset. */
+struct rule_dpif *
+ofproto_dpif_refresh_rule(struct rule_dpif *rule)
+{
+    return rule_dpif_cast(ofproto_refresh_rule(&rule->up));
+}
+
 /* Appends 'pin' to the queue of "packet ins" to be sent to the controller.
  * Takes ownership of 'pin' and pin->packet. */
 void
@@ -951,7 +963,7 @@ check_recirc(struct dpif_backer *backer)
     flow.dp_hash = 1;
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, &flow, 0);
+    odp_flow_key_from_flow(&key, &flow, NULL, 0);
 
     error = dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY,
                           ofpbuf_data(&key), ofpbuf_size(&key), NULL, 0, NULL,
@@ -1084,7 +1096,7 @@ check_max_mpls_depth(struct dpif_backer *backer)
         flow_set_mpls_bos(&flow, n, 1);
 
         ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-        odp_flow_key_from_flow(&key, &flow, 0);
+        odp_flow_key_from_flow(&key, &flow, NULL, 0);
 
         error = dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY,
                               ofpbuf_data(&key), ofpbuf_size(&key), NULL, 0, NULL, 0, NULL);
@@ -3171,13 +3183,40 @@ rule_dpif_get_actions(const struct rule_dpif *rule)
     return rule_get_actions(&rule->up);
 }
 
-static uint8_t
-rule_dpif_lookup__ (struct ofproto_dpif *ofproto, const struct flow *flow,
-                    struct flow_wildcards *wc, struct rule_dpif **rule)
+/* Lookup 'flow' in table 0 of 'ofproto''s classifier.
+ * If 'wc' is non-null, sets the fields that were relevant as part of
+ * the lookup. Returns the table_id where a match or miss occurred.
+ *
+ * The return value will be zero unless there was a miss and
+ * OFPTC11_TABLE_MISS_CONTINUE is in effect for the sequence of tables
+ * where misses occur. */
+uint8_t
+rule_dpif_lookup(struct ofproto_dpif *ofproto, struct flow *flow,
+                 struct flow_wildcards *wc, struct rule_dpif **rule)
 {
     enum rule_dpif_lookup_verdict verdict;
     enum ofputil_port_config config = 0;
-    uint8_t table_id = TBL_INTERNAL;
+    uint8_t table_id;
+
+    if (ofproto_dpif_get_enable_recirc(ofproto)) {
+        /* Always exactly match recirc_id since datapath supports
+         * recirculation.  */
+        if (wc) {
+            wc->masks.recirc_id = UINT32_MAX;
+        }
+
+        /* Start looking up from internal table for post recirculation flows
+         * or packets. We can also simply send all, including normal flows
+         * or packets to the internal table. They will not match any post
+         * recirculation rules except the 'catch all' rule that resubmit
+         * them to table 0.
+         *
+         * As an optimization, we send normal flows and packets to table 0
+         * directly, saving one table lookup.  */
+        table_id = flow->recirc_id ? TBL_INTERNAL : 0;
+    } else {
+        table_id = 0;
+    }
 
     verdict = rule_dpif_lookup_from_table(ofproto, flow, wc, true,
                                           &table_id, rule);
@@ -3213,23 +3252,6 @@ rule_dpif_lookup__ (struct ofproto_dpif *ofproto, const struct flow *flow,
     return table_id;
 }
 
-/* Lookup 'flow' in table 0 of 'ofproto''s classifier.
- * If 'wc' is non-null, sets the fields that were relevant as part of
- * the lookup. Returns the table_id where a match or miss occurred.
- *
- * The return value will be zero unless there was a miss and
- * O!-TC_TABLE_MISS_CONTINUE is in effect for the sequence of tables
- * where misses occur. */
-uint8_t
-rule_dpif_lookup(struct ofproto_dpif *ofproto, struct flow *flow,
-                 struct flow_wildcards *wc, struct rule_dpif **rule)
-{
-    /* Set metadata to the value of recirc_id to speed up internal
-     * rule lookup. */
-    flow->metadata = htonll(flow->recirc_id);
-    return rule_dpif_lookup__(ofproto, flow, wc, rule);
-}
-
 static struct rule_dpif *
 rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
                           const struct flow *flow, struct flow_wildcards *wc)
@@ -3293,6 +3315,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
  *    - RULE_OFPTC_TABLE_MISS_CONTROLLER if no rule was found and either:
  *      + 'honor_table_miss' is false
  *      + a table miss configuration specified that the packet should be
+ *        sent to the controller in this case.
  *
  *    - RULE_DPIF_LOOKUP_VERDICT_DROP if no rule was found, 'honor_table_miss'
  *      is true and a table miss configuration specified that the packet
@@ -3780,6 +3803,7 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
 struct trace_ctx {
     struct xlate_out xout;
     struct xlate_in xin;
+    const struct flow *key;
     struct flow flow;
     struct flow_wildcards wc;
     struct ds *result;
@@ -3820,7 +3844,9 @@ trace_format_flow(struct ds *result, int level, const char *title,
 {
     ds_put_char_multiple(result, '\t', level);
     ds_put_format(result, "%s: ", title);
-    if (flow_equal(&trace->xin.flow, &trace->flow)) {
+    /* Do not report unchanged flows for resubmits. */
+    if ((level > 0 && flow_equal(&trace->xin.flow, &trace->flow))
+        || (level == 0 && flow_equal(&trace->xin.flow, trace->key))) {
         ds_put_cstr(result, "unchanged");
     } else {
         flow_format(result, &trace->xin.flow);
@@ -3865,7 +3891,7 @@ trace_format_megaflow(struct ds *result, int level, const char *title,
     ds_put_char_multiple(result, '\t', level);
     ds_put_format(result, "%s: ", title);
     flow_wildcards_or(&trace->wc, &trace->xout.wc, &trace->wc);
-    match_init(&match, &trace->flow, &trace->wc);
+    match_init(&match, trace->key, &trace->wc);
     match_format(&match, result, OFP_DEFAULT_PRIORITY);
     ds_put_char(result, '\n');
 }
@@ -4187,7 +4213,8 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow,
 
     if (rule || ofpacts) {
         trace.result = ds;
-        trace.flow = *flow;
+        trace.key = flow; /* Original flow key, used for megaflow. */
+        trace.flow = *flow; /* May be modified by actions. */
         xlate_in_init(&trace.xin, ofproto, flow, rule, ntohs(flow->tcp_flags),
                       packet);
         if (ofpacts) {