lib: Move vlog.h to <openvswitch/vlog.h>
[cascardo/ovs.git] / utilities / ovs-ofctl.c
index 5835a70..1e349ea 100644 (file)
@@ -60,7 +60,7 @@
 #include "unixctl.h"
 #include "util.h"
 #include "vconn.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
 #include "meta-flow.h"
 #include "sort.h"
 
@@ -106,7 +106,7 @@ static size_t n_criteria, allocated_criteria;
 
 static const struct command *get_all_commands(void);
 
-NO_RETURN static void usage(void);
+OVS_NO_RETURN static void usage(void);
 static void parse_options(int argc, char *argv[]);
 
 static bool recv_flow_stats_reply(struct vconn *, ovs_be32 send_xid,
@@ -342,6 +342,8 @@ usage(void)
            "  add-groups SWITCH FILE      add group from FILE\n"
            "  mod-group SWITCH GROUP      modify specific group\n"
            "  del-groups SWITCH [GROUP]   delete matching GROUPs\n"
+           "  insert-buckets SWITCH [GROUP] add buckets to GROUP\n"
+           "  remove-buckets SWITCH [GROUP] remove buckets from GROUP\n"
            "  dump-group-features SWITCH  print group features\n"
            "  dump-groups SWITCH [GROUP]  print group description\n"
            "  dump-group-stats SWITCH [GROUP]  print group statistics\n"
@@ -393,7 +395,7 @@ ofctl_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
 }
 
 static void run(int retval, const char *message, ...)
-    PRINTF_FORMAT(2, 3);
+    OVS_PRINTF_FORMAT(2, 3);
 
 static void
 run(int retval, const char *message, ...)
@@ -579,7 +581,7 @@ dump_trivial_stats_transaction(const char *vconn_name, enum ofpraw raw)
  *
  * Destroys all of the 'requests'. */
 static void
-transact_multiple_noreply(struct vconn *vconn, struct list *requests)
+transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests)
 {
     struct ofpbuf *request, *reply;
 
@@ -604,7 +606,7 @@ transact_multiple_noreply(struct vconn *vconn, struct list *requests)
 static void
 transact_noreply(struct vconn *vconn, struct ofpbuf *request)
 {
-    struct list requests;
+    struct ovs_list requests;
 
     list_init(&requests);
     list_push_back(&requests, &request->list_node);
@@ -2174,6 +2176,18 @@ ofctl_del_groups(int argc, char *argv[])
     ofctl_group_mod(argc, argv, OFPGC11_DELETE);
 }
 
+static void
+ofctl_insert_bucket(int argc, char *argv[])
+{
+    ofctl_group_mod(argc, argv, OFPGC15_INSERT_BUCKET);
+}
+
+static void
+ofctl_remove_bucket(int argc, char *argv[])
+{
+    ofctl_group_mod(argc, argv, OFPGC15_REMOVE_BUCKET);
+}
+
 static void
 ofctl_dump_group_stats(int argc, char *argv[])
 {
@@ -2267,6 +2281,7 @@ struct fte_version {
     ovs_be64 cookie;
     uint16_t idle_timeout;
     uint16_t hard_timeout;
+    uint16_t importance;
     uint16_t flags;
     struct ofpact *ofpacts;
     size_t ofpacts_len;
@@ -2292,6 +2307,7 @@ fte_version_equals(const struct fte_version *a, const struct fte_version *b)
     return (a->cookie == b->cookie
             && a->idle_timeout == b->idle_timeout
             && a->hard_timeout == b->hard_timeout
+            && a->importance == b->importance
             && ofpacts_equal(a->ofpacts, a->ofpacts_len,
                              b->ofpacts, b->ofpacts_len));
 }
@@ -2318,6 +2334,9 @@ fte_version_format(const struct fte *fte, int index, struct ds *s)
     if (version->hard_timeout != OFP_FLOW_PERMANENT) {
         ds_put_format(s, " hard_timeout=%"PRIu16, version->hard_timeout);
     }
+    if (version->importance != 0) {
+        ds_put_format(s, " importance=%"PRIu16, version->importance);
+    }
 
     ds_put_cstr(s, " actions=");
     ofpacts_format(version->ofpacts, version->ofpacts_len, s);
@@ -2349,9 +2368,10 @@ fte_free_all(struct classifier *cls)
 {
     struct fte *fte;
 
-    CLS_FOR_EACH_SAFE (fte, rule, cls) {
+    classifier_defer(cls);
+    CLS_FOR_EACH (fte, rule, cls) {
         classifier_remove(cls, &fte->rule);
-        fte_free(fte);
+        ovsrcu_postpone(fte_free, fte);
     }
     classifier_destroy(cls);
 }
@@ -2373,10 +2393,10 @@ fte_insert(struct classifier *cls, const struct match *match,
 
     old = fte_from_cls_rule(classifier_replace(cls, &fte->rule));
     if (old) {
-        fte_version_free(old->versions[index]);
         fte->versions[!index] = old->versions[!index];
-        cls_rule_destroy(&old->rule);
-        free(old);
+        old->versions[!index] = NULL;
+
+        ovsrcu_postpone(fte_free, old);
     }
 }
 
@@ -2399,6 +2419,7 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
     ds_init(&s);
     usable_protocols = OFPUTIL_P_ANY;
     line_number = 0;
+    classifier_defer(cls);
     while (!ds_get_preprocessed_line(&s, file, &line_number)) {
         struct fte_version *version;
         struct ofputil_flow_mod fm;
@@ -2415,6 +2436,7 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
         version->cookie = fm.new_cookie;
         version->idle_timeout = fm.idle_timeout;
         version->hard_timeout = fm.hard_timeout;
+        version->importance = fm.importance;
         version->flags = fm.flags & (OFPUTIL_FF_SEND_FLOW_REM
                                      | OFPUTIL_FF_EMERG);
         version->ofpacts = fm.ofpacts;
@@ -2422,6 +2444,7 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
 
         fte_insert(cls, &fm.match, fm.priority, version, index);
     }
+    classifier_publish(cls);
     ds_destroy(&s);
 
     if (file != stdin) {
@@ -2510,6 +2533,7 @@ read_flows_from_switch(struct vconn *vconn,
 
     reply = NULL;
     ofpbuf_init(&ofpacts, 0);
+    classifier_defer(cls);
     while (recv_flow_stats_reply(vconn, send_xid, &reply, &fs, &ofpacts)) {
         struct fte_version *version;
 
@@ -2517,18 +2541,20 @@ read_flows_from_switch(struct vconn *vconn,
         version->cookie = fs.cookie;
         version->idle_timeout = fs.idle_timeout;
         version->hard_timeout = fs.hard_timeout;
+        version->importance = fs.importance;
         version->flags = 0;
         version->ofpacts_len = fs.ofpacts_len;
         version->ofpacts = xmemdup(fs.ofpacts, fs.ofpacts_len);
 
         fte_insert(cls, &fs.match, fs.priority, version, index);
     }
+    classifier_publish(cls);
     ofpbuf_uninit(&ofpacts);
 }
 
 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 ovs_list *packets)
 {
     const struct fte_version *version = fte->versions[index];
     struct ofputil_flow_mod fm;
@@ -2544,6 +2570,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command,
     fm.command = command;
     fm.idle_timeout = version->idle_timeout;
     fm.hard_timeout = version->hard_timeout;
+    fm.importance = version->importance;
     fm.buffer_id = UINT32_MAX;
     fm.out_port = OFPP_ANY;
     fm.flags = version->flags;
@@ -2567,7 +2594,7 @@ ofctl_replace_flows(int argc OVS_UNUSED, char *argv[])
     enum { FILE_IDX = 0, SWITCH_IDX = 1 };
     enum ofputil_protocol usable_protocols, protocol;
     struct classifier cls;
-    struct list requests;
+    struct ovs_list requests;
     struct vconn *vconn;
     struct fte *fte;
 
@@ -3539,6 +3566,10 @@ static const struct command all_commands[] = {
       1, 2, ofctl_mod_group },
     { "del-groups", "switch [group]",
       1, 2, ofctl_del_groups },
+    { "insert-buckets", "switch [group]",
+      1, 2, ofctl_insert_bucket },
+    { "remove-buckets", "switch [group]",
+      1, 2, ofctl_remove_bucket },
     { "dump-groups", "switch [group]",
       1, 2, ofctl_dump_group_desc },
     { "dump-group-stats", "switch [group]",