This function checks for a rule in the classifier:
* If the rule exists, reset its modified time.
* If an equivalent rule exists, reset that rule's modified time.
* If no rule exists, re-install the rule and reset its modified time.
* Finally, return the rule that was modified.

This function will be used to ensure that hard timeouts for learnt rules
are refreshed if traffic consistently hits a rule with a learn action in
it. The first user will be the next commit.

Signed-off-by: Joe Stringer <joestrin...@nicira.com>
---
 ofproto/ofproto-dpif.c     |   12 +++++++++
 ofproto/ofproto-dpif.h     |    1 +
 ofproto/ofproto-provider.h |    2 ++
 ofproto/ofproto.c          |   62 +++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 97eb2b8..c7a3f98 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -351,6 +351,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
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index d09e285..f2820e3 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -118,6 +118,7 @@ void ofproto_dpif_send_packet_in(struct ofproto_dpif *,
                                  struct ofproto_packet_in *);
 int ofproto_dpif_send_packet(const struct ofport_dpif *, struct ofpbuf *);
 void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *);
+struct rule_dpif *ofproto_dpif_refresh_rule(struct rule_dpif *);
 
 struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t);
 
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 2c72fbc..ec54038 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -1720,6 +1720,8 @@ BUILD_ASSERT_DECL(OFPROTO_POSTPONE < OFPERR_OFS);
 
 int ofproto_flow_mod(struct ofproto *, struct ofputil_flow_mod *)
     OVS_EXCLUDED(ofproto_mutex);
+struct rule *ofproto_refresh_rule(struct rule *rule)
+    OVS_EXCLUDED(ofproto_mutex);
 void ofproto_add_flow(struct ofproto *, const struct match *,
                       unsigned int priority,
                       const struct ofpact *ofpacts, size_t ofpacts_len)
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 19e7091..948a472 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -266,6 +266,9 @@ static bool rule_is_modifiable(const struct rule *);
 static enum ofperr add_flow(struct ofproto *, struct ofconn *,
                             struct ofputil_flow_mod *,
                             const struct ofp_header *);
+static void do_add_flow(struct ofproto *, struct ofconn *,
+                        const struct ofp_header *request, uint32_t buffer_id,
+                        struct rule *);
 static enum ofperr modify_flows__(struct ofproto *, struct ofconn *,
                                   struct ofputil_flow_mod *,
                                   const struct ofp_header *,
@@ -1970,6 +1973,47 @@ ofproto_flow_mod(struct ofproto *ofproto, struct 
ofputil_flow_mod *fm)
     return handle_flow_mod__(ofproto, NULL, fm, NULL);
 }
 
+/* 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 *
+ofproto_refresh_rule(struct rule *rule)
+{
+    const struct oftable *table = &rule->ofproto->tables[rule->table_id];
+    const struct cls_rule *cr = &rule->cr;
+    struct rule *r;
+
+    /* do_add_flow() requires that the rule is not installed. We lock the
+     * ofproto_mutex here so that another thread cannot add the flow before
+     * we get a chance to add it.*/
+    ovs_mutex_lock(&ofproto_mutex);
+
+    fat_rwlock_rdlock(&table->cls.rwlock);
+    r = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls, cr));
+    if (r != rule) {
+        ofproto_rule_ref(r);
+    }
+    fat_rwlock_unlock(&table->cls.rwlock);
+
+    if (!r) {
+        do_add_flow(rule->ofproto, NULL, NULL, 0, rule);
+    } else if  (r != rule) {
+        ofproto_rule_unref(rule);
+        rule = r;
+    }
+    ovs_mutex_unlock(&ofproto_mutex);
+
+    /* Refresh the modified time for the rule. */
+    ovs_mutex_lock(&rule->mutex);
+    rule->modified = time_msec();
+    ovs_mutex_unlock(&rule->mutex);
+
+    return rule;
+}
+
 /* Searches for a rule with matching criteria exactly equal to 'target' in
  * ofproto's table 0 and, if it finds one, deletes it.
  *
@@ -3946,7 +3990,6 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
     OVS_REQUIRES(ofproto_mutex)
 {
     struct oftable *table;
-    struct ofopgroup *group;
     struct cls_rule cr;
     struct rule *rule;
     uint8_t table_id;
@@ -4075,14 +4118,25 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
     }
 
     /* Insert rule. */
+    do_add_flow(ofproto, ofconn, request, fm->buffer_id, rule);
+
+    return error;
+}
+
+static void
+do_add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
+            const struct ofp_header *request, uint32_t buffer_id,
+            struct rule *rule)
+    OVS_REQUIRES(ofproto_mutex)
+{
+    struct ofopgroup *group;
+
     oftable_insert_rule(rule);
 
-    group = ofopgroup_create(ofproto, ofconn, request, fm->buffer_id);
+    group = ofopgroup_create(ofproto, ofconn, request, buffer_id);
     ofoperation_create(group, rule, OFOPERATION_ADD, 0);
     ofproto->ofproto_class->rule_insert(rule);
     ofopgroup_submit(group);
-
-    return error;
 }
 
 /* OFPFC_MODIFY and OFPFC_MODIFY_STRICT. */
-- 
1.7.9.5

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

Reply via email to