[ovs-dev] [threaded-learning v2 02/25] ofproto: Reduce number of "collect" functions taking lots of parameters.

Ben Pfaff blp at nicira.com
Thu Sep 12 07:39:14 UTC 2013


The long lists of parameters for all these "collect" functions was starting
to get to me.  This reduces the number of such functions to one.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 ofproto/ofproto.c |  205 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 130 insertions(+), 75 deletions(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 4ab6e1b..98a0752 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -190,6 +190,38 @@ static uint32_t rule_eviction_priority(struct rule *);
 static void eviction_group_add_rule(struct rule *);
 static void eviction_group_remove_rule(struct rule *);
 
+/* Criteria that flow_mod and other operations use for selecting rules on
+ * which to operate. */
+struct rule_criteria {
+    /* An OpenFlow table or 255 for all tables. */
+    uint8_t table_id;
+
+    /* OpenFlow matching criteria.  Interpreted different in "loose" way by
+     * collect_rules_loose() and "strict" way by collect_rules_strict(), as
+     * defined in the OpenFlow spec. */
+    struct cls_rule cr;
+
+    /* Matching criteria for the OpenFlow cookie.  Consider a bit B in a rule's
+     * cookie and the corresponding bits C in 'cookie' and M in 'cookie_mask'.
+     * The rule will not be selected if M is 1 and B != C.  */
+    ovs_be64 cookie;
+    ovs_be64 cookie_mask;
+
+    /* Selection based on actions within a rule:
+     *
+     * If out_port != OFPP_ANY, selects only rules that output to out_port.
+     * If out_group != OFPG_ALL, select only rules that output to out_group. */
+    ofp_port_t out_port;
+    uint32_t out_group;
+};
+
+static void rule_criteria_init(struct rule_criteria *, uint8_t table_id,
+                               const struct match *match,
+                               unsigned int priority,
+                               ovs_be64 cookie, ovs_be64 cookie_mask,
+                               ofp_port_t out_port, uint32_t out_group);
+static void rule_criteria_destroy(struct rule_criteria *);
+
 /* ofport. */
 static void ofport_destroy__(struct ofport *);
 static void ofport_destroy(struct ofport *);
@@ -2935,79 +2967,94 @@ next_matching_table(const struct ofproto *ofproto,
          (TABLE) != NULL;                                         \
          (TABLE) = next_matching_table(OFPROTO, TABLE, TABLE_ID))
 
+/* Initializes 'criteria' in a straightforward way based on the other
+ * parameters.
+ *
+ * For "loose" matching, the 'priority' parameter is unimportant and may be
+ * supplied as 0. */
+static void
+rule_criteria_init(struct rule_criteria *criteria, uint8_t table_id,
+                   const struct match *match, unsigned int priority,
+                   ovs_be64 cookie, ovs_be64 cookie_mask,
+                   ofp_port_t out_port, uint32_t out_group)
+{
+    criteria->table_id = table_id;
+    cls_rule_init(&criteria->cr, match, priority);
+    criteria->cookie = cookie;
+    criteria->cookie_mask = cookie_mask;
+    criteria->out_port = out_port;
+    criteria->out_group = out_group;
+}
+
+static void
+rule_criteria_destroy(struct rule_criteria *criteria)
+{
+    cls_rule_destroy(&criteria->cr);
+}
+
 static enum ofperr
-collect_rule(struct rule *rule, uint8_t table_id,
-             ovs_be64 cookie, ovs_be64 cookie_mask,
-             ofp_port_t out_port, uint32_t out_group, struct list *rules)
+collect_rule(struct rule *rule, const struct rule_criteria *c,
+             struct list *rules)
 {
     if (ofproto_rule_is_hidden(rule)) {
         return 0;
     } else if (rule->pending) {
         return OFPROTO_POSTPONE;
     } else {
-        if ((table_id == rule->table_id || table_id == 0xff)
-            && ofproto_rule_has_out_port(rule, out_port)
-            && ofproto_rule_has_out_group(rule, out_group)
-            && !((rule->flow_cookie ^ cookie) & cookie_mask)) {
+        if ((c->table_id == rule->table_id || c->table_id == 0xff)
+            && ofproto_rule_has_out_port(rule, c->out_port)
+            && ofproto_rule_has_out_group(rule, c->out_group)
+            && !((rule->flow_cookie ^ c->cookie) & c->cookie_mask)) {
             list_push_back(rules, &rule->ofproto_node);
         }
         return 0;
     }
 }
 
-/* Searches 'ofproto' for rules in table 'table_id' (or in all tables, if
- * 'table_id' is 0xff) that match 'match' in the "loose" way required for
- * OpenFlow OFPFC_MODIFY and OFPFC_DELETE requests and puts them on list
+/* Searches 'ofproto' for rules that match the criteria in 'criteria'.  Matches
+ * on classifiers rules are done in the "loose" way required for OpenFlow
+ * OFPFC_MODIFY and OFPFC_DELETE requests.  Puts the selected rules on list
  * 'rules'.
  *
- * If 'out_port' is anything other than OFPP_ANY, then only rules that output
- * to 'out_port' are included.
- *
  * Hidden rules are always omitted.
  *
  * Returns 0 on success, otherwise an OpenFlow error code. */
 static enum ofperr
-collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
-                    const struct match *match,
-                    ovs_be64 cookie, ovs_be64 cookie_mask,
-                    ofp_port_t out_port, uint32_t out_group,
-                    struct list *rules)
+collect_rules_loose(struct ofproto *ofproto,
+                    const struct rule_criteria *criteria, struct list *rules)
 {
     struct oftable *table;
-    struct cls_rule cr;
     enum ofperr error;
 
-    error = check_table_id(ofproto, table_id);
+    error = check_table_id(ofproto, criteria->table_id);
     if (error) {
         return error;
     }
 
     list_init(rules);
-    cls_rule_init(&cr, match, 0);
 
-    if (cookie_mask == htonll(UINT64_MAX)) {
+    if (criteria->cookie_mask == htonll(UINT64_MAX)) {
         struct rule *rule;
 
-        HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node, hash_cookie(cookie),
+        HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node,
+                                   hash_cookie(criteria->cookie),
                                    &ofproto->cookies) {
-            if (cls_rule_is_loose_match(&rule->cr, &cr.match)) {
-                error = collect_rule(rule, table_id, cookie, cookie_mask,
-                                     out_port, out_group, rules);
+            if (cls_rule_is_loose_match(&rule->cr, &criteria->cr.match)) {
+                error = collect_rule(rule, criteria, rules);
                 if (error) {
                     break;
                 }
             }
         }
     } else {
-        FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
+        FOR_EACH_MATCHING_TABLE (table, criteria->table_id, ofproto) {
             struct cls_cursor cursor;
             struct rule *rule;
 
             ovs_rwlock_rdlock(&table->cls.rwlock);
-            cls_cursor_init(&cursor, &table->cls, &cr);
+            cls_cursor_init(&cursor, &table->cls, &criteria->cr);
             CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
-                error = collect_rule(rule, table_id, cookie, cookie_mask,
-                                     out_port, out_group, rules);
+                error = collect_rule(rule, criteria, rules);
                 if (error) {
                     break;
                 }
@@ -3016,64 +3063,54 @@ collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
         }
     }
 
-    cls_rule_destroy(&cr);
     return error;
 }
 
-/* Searches 'ofproto' for rules in table 'table_id' (or in all tables, if
- * 'table_id' is 0xff) that match 'match' in the "strict" way required for
- * OpenFlow OFPFC_MODIFY_STRICT and OFPFC_DELETE_STRICT requests and puts them
- * on list 'rules'.
- *
- * If 'out_port' is anything other than OFPP_ANY, then only rules that output
- * to 'out_port' are included.
+/* Searches 'ofproto' for rules that match the criteria in 'criteria'.  Matches
+ * on classifiers rules are done in the "strict" way required for OpenFlow
+ * OFPFC_MODIFY_STRICT and OFPFC_DELETE_STRICT requests.  Puts the selected
+ * rules on list 'rules'.
  *
  * Hidden rules are always omitted.
  *
  * Returns 0 on success, otherwise an OpenFlow error code. */
 static enum ofperr
-collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
-                     const struct match *match, unsigned int priority,
-                     ovs_be64 cookie, ovs_be64 cookie_mask,
-                     ofp_port_t out_port, uint32_t out_group,
-                     struct list *rules)
+collect_rules_strict(struct ofproto *ofproto,
+                     const struct rule_criteria *criteria, struct list *rules)
 {
     struct oftable *table;
-    struct cls_rule cr;
     int error;
 
-    error = check_table_id(ofproto, table_id);
+    error = check_table_id(ofproto, criteria->table_id);
     if (error) {
         return error;
     }
 
     list_init(rules);
-    cls_rule_init(&cr, match, priority);
 
-    if (cookie_mask == htonll(UINT64_MAX)) {
+    if (criteria->cookie_mask == htonll(UINT64_MAX)) {
         struct rule *rule;
 
-        HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node, hash_cookie(cookie),
+        HINDEX_FOR_EACH_WITH_HASH (rule, cookie_node,
+                                   hash_cookie(criteria->cookie),
                                    &ofproto->cookies) {
-            if (cls_rule_equal(&rule->cr, &cr)) {
-                error = collect_rule(rule, table_id, cookie, cookie_mask,
-                                     out_port, out_group, rules);
+            if (cls_rule_equal(&rule->cr, &criteria->cr)) {
+                error = collect_rule(rule, criteria, rules);
                 if (error) {
                     break;
                 }
             }
         }
     } else {
-        FOR_EACH_MATCHING_TABLE (table, table_id, ofproto) {
+        FOR_EACH_MATCHING_TABLE (table, criteria->table_id, ofproto) {
             struct rule *rule;
 
             ovs_rwlock_rdlock(&table->cls.rwlock);
-            rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls,
-                                                                   &cr));
+            rule = rule_from_cls_rule(classifier_find_rule_exactly(
+                                          &table->cls, &criteria->cr));
             ovs_rwlock_unlock(&table->cls.rwlock);
             if (rule) {
-                error = collect_rule(rule, table_id, cookie, cookie_mask,
-                                     out_port, out_group, rules);
+                error = collect_rule(rule, criteria, rules);
                 if (error) {
                     break;
                 }
@@ -3081,7 +3118,6 @@ collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
         }
     }
 
-    cls_rule_destroy(&cr);
     return error;
 }
 
@@ -3101,6 +3137,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofputil_flow_stats_request fsr;
+    struct rule_criteria criteria;
     struct list replies;
     struct list rules;
     struct rule *rule;
@@ -3111,9 +3148,10 @@ handle_flow_stats_request(struct ofconn *ofconn,
         return error;
     }
 
-    error = collect_rules_loose(ofproto, fsr.table_id, &fsr.match,
-                                fsr.cookie, fsr.cookie_mask,
-                                fsr.out_port, fsr.out_group, &rules);
+    rule_criteria_init(&criteria, fsr.table_id, &fsr.match, 0, fsr.cookie,
+                       fsr.cookie_mask, fsr.out_port, fsr.out_group);
+    error = collect_rules_loose(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
     if (error) {
         return error;
     }
@@ -3224,6 +3262,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     struct ofputil_flow_stats_request request;
     struct ofputil_aggregate_stats stats;
     bool unknown_packets, unknown_bytes;
+    struct rule_criteria criteria;
     struct ofpbuf *reply;
     struct list rules;
     struct rule *rule;
@@ -3234,9 +3273,11 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
         return error;
     }
 
-    error = collect_rules_loose(ofproto, request.table_id, &request.match,
-                                request.cookie, request.cookie_mask,
-                                request.out_port, request.out_group, &rules);
+    rule_criteria_init(&criteria, request.table_id, &request.match, 0,
+                       request.cookie, request.cookie_mask,
+                       request.out_port, request.out_group);
+    error = collect_rules_loose(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
     if (error) {
         return error;
     }
@@ -3698,12 +3739,15 @@ modify_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
                    struct ofputil_flow_mod *fm,
                    const struct ofp_header *request)
 {
+    struct rule_criteria criteria;
     struct list rules;
     int error;
 
-    error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
-                                fm->cookie, fm->cookie_mask,
-                                OFPP_ANY, OFPG11_ANY, &rules);
+    rule_criteria_init(&criteria, fm->table_id, &fm->match, 0,
+                       fm->cookie, fm->cookie_mask, OFPP_ANY, OFPG11_ANY);
+    error = collect_rules_loose(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
+
     if (error) {
         return error;
     } else if (list_is_empty(&rules)) {
@@ -3723,12 +3767,15 @@ modify_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
                    struct ofputil_flow_mod *fm,
                    const struct ofp_header *request)
 {
+    struct rule_criteria criteria;
     struct list rules;
     int error;
 
-    error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
-                                 fm->priority, fm->cookie, fm->cookie_mask,
-                                 OFPP_ANY, OFPG11_ANY, &rules);
+    rule_criteria_init(&criteria, fm->table_id, &fm->match, fm->priority,
+                       fm->cookie, fm->cookie_mask, OFPP_ANY, OFPG11_ANY);
+    error = collect_rules_strict(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
+
     if (error) {
         return error;
     } else if (list_is_empty(&rules)) {
@@ -3782,12 +3829,16 @@ delete_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
                    const struct ofputil_flow_mod *fm,
                    const struct ofp_header *request)
 {
+    struct rule_criteria criteria;
     struct list rules;
     enum ofperr error;
 
-    error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
-                                fm->cookie, fm->cookie_mask,
-                                fm->out_port, fm->out_group, &rules);
+    rule_criteria_init(&criteria, fm->table_id, &fm->match, 0,
+                       fm->cookie, fm->cookie_mask,
+                       fm->out_port, fm->out_group);
+    error = collect_rules_loose(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
+
     return (error ? error
             : !list_is_empty(&rules) ? delete_flows__(ofproto, ofconn, request,
                                                       &rules, OFPRR_DELETE)
@@ -3800,12 +3851,16 @@ delete_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
                    const struct ofputil_flow_mod *fm,
                    const struct ofp_header *request)
 {
+    struct rule_criteria criteria;
     struct list rules;
     enum ofperr error;
 
-    error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
-                                 fm->priority, fm->cookie, fm->cookie_mask,
-                                 fm->out_port, fm->out_group, &rules);
+    rule_criteria_init(&criteria, fm->table_id, &fm->match, fm->priority,
+                       fm->cookie, fm->cookie_mask,
+                       fm->out_port, fm->out_group);
+    error = collect_rules_strict(ofproto, &criteria, &rules);
+    rule_criteria_destroy(&criteria);
+
     return (error ? error
             : list_is_singleton(&rules) ? delete_flows__(ofproto, ofconn,
                                                          request, &rules,
-- 
1.7.10.4




More information about the dev mailing list