[ovs-dev] [PATCH] ofctl: Initial attempt for multiple tables in replace-flows

Darren Shepherd darren at godaddy.com
Wed Jun 5 22:12:10 UTC 2013


---
 lib/ofp-util.c        |    1 +
 utilities/ovs-ofctl.c |  125 ++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 98 insertions(+), 28 deletions(-)

diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index cc2dc36..afc3ce4 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -591,6 +591,7 @@ enum ofputil_protocol ofputil_flow_dump_protocols[] = {
     OFPUTIL_P_OF12_OXM,
     OFPUTIL_P_OF10_NXM,
     OFPUTIL_P_OF10_STD,
+    OFPUTIL_P_OF10_STD_TID,
 };
 size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
 
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 48f0fbf..16e189e 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -1888,14 +1888,66 @@ fte_insert(struct classifier *cls, const struct match *match,
     }
 }
 
+/* Holds classifiers for a set of tables */
+struct table_classifiers {
+    struct hmap classifiers;
+};
+
+struct table_classifier_node {
+    struct hmap_node hmap_node;
+    struct classifier cls;
+    uint8_t table_id;
+};
+
+static void
+table_classifiers_init(struct table_classifiers *tcls)
+{
+    hmap_init(&tcls->classifiers);
+}
+
+static uint32_t
+table_id_hash(uint8_t table_id)
+{
+    return (uint32_t)table_id;
+}
+
+static struct classifier *
+table_classifiers_find_classifier(struct table_classifiers *tcls, 
+                                  uint8_t table_id)
+{
+    struct table_classifier_node *cls_node;
+
+    HMAP_FOR_EACH_IN_BUCKET(cls_node, hmap_node, table_id_hash(table_id), 
+                            &tcls->classifiers) {
+        if ( cls_node->table_id == table_id ) {
+            return &cls_node->cls;
+        }
+    }
+
+    if ( cls_node == NULL ) {
+        cls_node = xzalloc(sizeof(struct table_classifier_node));
+        cls_node->table_id = table_id;
+
+        classifier_init(&cls_node->cls);
+
+        hmap_insert(&tcls->classifiers, &cls_node->hmap_node, 
+                    table_id_hash(table_id));
+    }
+
+    return &cls_node->cls;
+}
+
+
+
 /* Reads the flows in 'filename' as flow table entries in 'cls' for the version
  * with the specified 'index'.  Returns the flow formats able to represent the
  * flows that were read. */
 static enum ofputil_protocol
-read_flows_from_file(const char *filename, struct classifier *cls, int index)
+read_flows_from_file(const char *filename, struct table_classifiers *tcls, int index)
 {
     enum ofputil_protocol usable_protocols;
     struct ds s;
+    struct classifier *cls;
     FILE *file;
 
     file = !strcmp(filename, "-") ? stdin : fopen(filename, "r");
@@ -1920,6 +1972,15 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
         version->ofpacts_len = fm.ofpacts_len;
 
         usable_protocols &= ofputil_usable_protocols(&fm.match);
+        if ( fm.table_id != 0xff ) {
+            usable_protocols &= OFPUTIL_P_TID;
+        }
+
+        if ( usable_protocols & OFPUTIL_P_TID && fm.table_id == 0xff ) {
+            fm.table_id = 0;
+        }
+
+        cls = table_classifiers_find_classifier(tcls, fm.table_id);
 
         fte_insert(cls, &fm.match, fm.priority, version, index);
     }
@@ -1991,13 +2052,14 @@ recv_flow_stats_reply(struct vconn *vconn, ovs_be32 send_xid,
 static void
 read_flows_from_switch(struct vconn *vconn,
                        enum ofputil_protocol protocol,
-                       struct classifier *cls, int index)
+                       struct table_classifiers *tcls, int index)
 {
     struct ofputil_flow_stats_request fsr;
     struct ofputil_flow_stats fs;
     struct ofpbuf *request;
     struct ofpbuf ofpacts;
     struct ofpbuf *reply;
+    struct classifier *cls;
     ovs_be32 send_xid;
 
     fsr.aggregate = false;
@@ -2022,6 +2084,7 @@ read_flows_from_switch(struct vconn *vconn,
         version->ofpacts_len = fs.ofpacts_len;
         version->ofpacts = xmemdup(fs.ofpacts, fs.ofpacts_len);
 
+        cls = table_classifiers_find_classifier(tcls, fs.table_id);
         fte_insert(cls, &fs.match, fs.priority, version, index);
     }
     ofpbuf_uninit(&ofpacts);
@@ -2029,7 +2092,8 @@ read_flows_from_switch(struct vconn *vconn,
 
 static void
 fte_make_flow_mod(const struct fte *fte, int index, uint16_t command,
-                  enum ofputil_protocol protocol, struct list *packets)
+                  enum ofputil_protocol protocol, struct list *packets, 
+                  uint8_t table_id)
 {
     const struct fte_version *version = fte->versions[index];
     struct ofputil_flow_mod fm;
@@ -2040,7 +2104,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command,
     fm.cookie = htonll(0);
     fm.cookie_mask = htonll(0);
     fm.new_cookie = version->cookie;
-    fm.table_id = 0xff;
+    fm.table_id = table_id;
     fm.command = command;
     fm.idle_timeout = version->idle_timeout;
     fm.hard_timeout = version->hard_timeout;
@@ -2066,49 +2130,54 @@ ofctl_replace_flows(int argc OVS_UNUSED, char *argv[])
     enum { FILE_IDX = 0, SWITCH_IDX = 1 };
     enum ofputil_protocol usable_protocols, protocol;
     struct cls_cursor cursor;
-    struct classifier cls;
+    struct table_classifiers tcls;
+    struct table_classifier_node *tcls_node;
     struct list requests;
     struct vconn *vconn;
     struct fte *fte;
 
-    classifier_init(&cls);
-    usable_protocols = read_flows_from_file(argv[2], &cls, FILE_IDX);
+    table_classifiers_init(&tcls);
+    usable_protocols = read_flows_from_file(argv[2], &tcls, FILE_IDX);
 
     protocol = open_vconn(argv[1], &vconn);
     protocol = set_protocol_for_flow_dump(vconn, protocol, usable_protocols);
 
-    read_flows_from_switch(vconn, protocol, &cls, SWITCH_IDX);
+    read_flows_from_switch(vconn, protocol, &tcls, SWITCH_IDX);
 
     list_init(&requests);
 
-    /* Delete flows that exist on the switch but not in the file. */
-    cls_cursor_init(&cursor, &cls, NULL);
-    CLS_CURSOR_FOR_EACH (fte, rule, &cursor) {
-        struct fte_version *file_ver = fte->versions[FILE_IDX];
-        struct fte_version *sw_ver = fte->versions[SWITCH_IDX];
+    HMAP_FOR_EACH(tcls_node, hmap_node, &tcls.classifiers) {
+        /* Delete flows that exist on the switch but not in the file. */
+        cls_cursor_init(&cursor, &tcls_node->cls, NULL);
+        CLS_CURSOR_FOR_EACH (fte, rule, &cursor) {
+                struct fte_version *file_ver = fte->versions[FILE_IDX];
+                struct fte_version *sw_ver = fte->versions[SWITCH_IDX];
 
-        if (sw_ver && !file_ver) {
-            fte_make_flow_mod(fte, SWITCH_IDX, OFPFC_DELETE_STRICT,
-                              protocol, &requests);
+                if (sw_ver && !file_ver) {
+                fte_make_flow_mod(fte, SWITCH_IDX, OFPFC_DELETE_STRICT,
+                                protocol, &requests, tcls_node->table_id);
+                }
         }
-    }
-
-    /* Add flows that exist in the file but not on the switch.
-     * Update flows that exist in both places but differ. */
-    cls_cursor_init(&cursor, &cls, NULL);
-    CLS_CURSOR_FOR_EACH (fte, rule, &cursor) {
-        struct fte_version *file_ver = fte->versions[FILE_IDX];
-        struct fte_version *sw_ver = fte->versions[SWITCH_IDX];
 
-        if (file_ver
-            && (readd || !sw_ver || !fte_version_equals(sw_ver, file_ver))) {
-            fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, protocol, &requests);
+        /* Add flows that exist in the file but not on the switch.
+        * Update flows that exist in both places but differ. */
+        cls_cursor_init(&cursor, &tcls_node->cls, NULL);
+        CLS_CURSOR_FOR_EACH (fte, rule, &cursor) {
+                struct fte_version *file_ver = fte->versions[FILE_IDX];
+                struct fte_version *sw_ver = fte->versions[SWITCH_IDX];
+
+                if (file_ver
+                && (readd || !sw_ver || !fte_version_equals(sw_ver, file_ver))) {
+                fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, protocol, &requests,
+                tcls_node->table_id);
+                }
         }
     }
+
     transact_multiple_noreply(vconn, &requests);
     vconn_close(vconn);
 
-    fte_free_all(&cls);
+    //TODO: free tlcs fte_free_all(&cls);
 }
 
 static void
-- 
1.7.9.5




More information about the dev mailing list