lib: Move vconn.h to <openvswitch/vconn.h>
[cascardo/ovs.git] / lib / ofp-parse.c
index 35ca316..2ae1edb 100644 (file)
@@ -38,7 +38,7 @@
 #include "packets.h"
 #include "simap.h"
 #include "socket-util.h"
-#include "vconn.h"
+#include "openvswitch/vconn.h"
 
 /* Parses 'str' as an 8-bit unsigned integer into '*valuep'.
  *
@@ -46,7 +46,7 @@
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_u8(const char *str, const char *name, uint8_t *valuep)
 {
     int value;
@@ -64,7 +64,7 @@ str_to_u8(const char *str, const char *name, uint8_t *valuep)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_u16(const char *str, const char *name, uint16_t *valuep)
 {
     int value;
@@ -80,7 +80,7 @@ str_to_u16(const char *str, const char *name, uint16_t *valuep)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_u32(const char *str, uint32_t *valuep)
 {
     char *tail;
@@ -103,7 +103,7 @@ str_to_u32(const char *str, uint32_t *valuep)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_u64(const char *str, uint64_t *valuep)
 {
     char *tail;
@@ -127,7 +127,7 @@ str_to_u64(const char *str, uint64_t *valuep)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_be64(const char *str, ovs_be64 *valuep)
 {
     uint64_t value = 0;
@@ -144,7 +144,7 @@ str_to_be64(const char *str, ovs_be64 *valuep)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_mac(const char *str, uint8_t mac[ETH_ADDR_LEN])
 {
     if (!ovs_scan(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
@@ -157,7 +157,7 @@ str_to_mac(const char *str, uint8_t mac[ETH_ADDR_LEN])
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 str_to_ip(const char *str, ovs_be32 *ip)
 {
     struct in_addr in_addr;
@@ -213,7 +213,7 @@ parse_protocol(const char *name, const struct protocol **p_out)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_field(const struct mf_field *mf, const char *s, struct match *match,
             enum ofputil_protocol *usable_protocols)
 {
@@ -241,13 +241,14 @@ extract_actions(char *s)
 }
 
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
                 enum ofputil_protocol *usable_protocols)
 {
     enum {
         F_OUT_PORT = 1 << 0,
         F_ACTIONS = 1 << 1,
+        F_IMPORTANCE = 1 << 2,
         F_TIMEOUT = 1 << 3,
         F_PRIORITY = 1 << 4,
         F_FLAGS = 1 << 5,
@@ -264,7 +265,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
         break;
 
     case OFPFC_ADD:
-        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
+        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS | F_IMPORTANCE;
         break;
 
     case OFPFC_DELETE:
@@ -305,6 +306,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
     fm->buffer_id = UINT32_MAX;
     fm->out_port = OFPP_ANY;
     fm->flags = 0;
+    fm->importance = 0;
     fm->out_group = OFPG11_ANY;
     fm->delete_reason = OFPRR_DELETE;
     if (fields & F_ACTIONS) {
@@ -366,6 +368,8 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
                 error = str_to_u16(value, name, &fm->idle_timeout);
             } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
                 error = str_to_u16(value, name, &fm->hard_timeout);
+            } else if (fields & F_IMPORTANCE && !strcmp(name, "importance")) {
+                error = str_to_u16(value, name, &fm->importance);
             } else if (!strcmp(name, "cookie")) {
                 char *mask = strchr(value, '/');
 
@@ -485,7 +489,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
               enum ofputil_protocol *usable_protocols)
 {
@@ -502,7 +506,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     return error;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
                           struct ofpbuf *bands, int command,
                           enum ofputil_protocol *usable_protocols)
@@ -706,7 +710,7 @@ parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_,
                         int command, enum ofputil_protocol *usable_protocols)
 {
@@ -726,7 +730,7 @@ parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_,
     return error;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
                              const char *str_, char *string,
                              enum ofputil_protocol *usable_protocols)
@@ -800,7 +804,7 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
                            const char *str_,
                            enum ofputil_protocol *usable_protocols)
@@ -817,7 +821,7 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
                        uint16_t command,
                        enum ofputil_protocol *usable_protocols)
@@ -840,7 +844,7 @@ parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
                     const char *flow_miss_handling,
                     enum ofputil_protocol *usable_protocols)
@@ -882,7 +886,7 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
                         struct ofputil_flow_mod **fms, size_t *n_fms,
                         enum ofputil_protocol *usable_protocols)
@@ -943,7 +947,7 @@ parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
     return NULL;
 }
 
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
                                  bool aggregate, const char *string,
                                  enum ofputil_protocol *usable_protocols)
@@ -1083,7 +1087,7 @@ exit:
     return error;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
                   enum ofputil_protocol *usable_protocols)
 {
@@ -1093,6 +1097,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
     char *error;
 
     bucket->weight = 1;
+    bucket->bucket_id = OFPG15_BUCKET_ALL;
     bucket->watch_port = OFPP_ANY;
     bucket->watch_group = OFPG11_ANY;
 
@@ -1115,6 +1120,13 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
                 error = xasprintf("invalid watch_group id %"PRIu32,
                                   bucket->watch_group);
             }
+        } else if (!strcasecmp(key, "bucket_id")) {
+            error = str_to_u32(value, &bucket->bucket_id);
+            if (!error && bucket->bucket_id > OFPG15_BUCKET_MAX) {
+                error = xasprintf("invalid bucket_id id %"PRIu32,
+                                  bucket->bucket_id);
+            }
+            *usable_protocols &= OFPUTIL_P_OF15_UP;
         } else if (!strcasecmp(key, "action") || !strcasecmp(key, "actions")) {
             ds_put_format(&actions, "%s,", value);
         } else {
@@ -1146,17 +1158,20 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
     return NULL;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
                           char *string,
                           enum ofputil_protocol *usable_protocols)
 {
     enum {
-        F_GROUP_TYPE  = 1 << 0,
-        F_BUCKETS     = 1 << 1,
+        F_GROUP_TYPE            = 1 << 0,
+        F_BUCKETS               = 1 << 1,
+        F_COMMAND_BUCKET_ID     = 1 << 2,
+        F_COMMAND_BUCKET_ID_ALL = 1 << 3,
     } fields;
     char *save_ptr = NULL;
     bool had_type = false;
+    bool had_command_bucket_id = false;
     char *name;
     struct ofputil_bucket *bucket;
     char *error = NULL;
@@ -1176,6 +1191,16 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
         fields = F_GROUP_TYPE | F_BUCKETS;
         break;
 
+    case OFPGC15_INSERT_BUCKET:
+        fields = F_BUCKETS | F_COMMAND_BUCKET_ID;
+        *usable_protocols &= OFPUTIL_P_OF15_UP;
+        break;
+
+    case OFPGC15_REMOVE_BUCKET:
+        fields = F_COMMAND_BUCKET_ID | F_COMMAND_BUCKET_ID_ALL;
+        *usable_protocols &= OFPUTIL_P_OF15_UP;
+        break;
+
     default:
         OVS_NOT_REACHED();
     }
@@ -1183,6 +1208,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
     memset(gm, 0, sizeof *gm);
     gm->command = command;
     gm->group_id = OFPG_ANY;
+    gm->command_bucket_id = OFPG15_BUCKET_ALL;
     list_init(&gm->buckets);
     if (command == OFPGC11_DELETE && string[0] == '\0') {
         gm->group_id = OFPG_ALL;
@@ -1192,7 +1218,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
     *usable_protocols = OFPUTIL_P_OF11_UP;
 
     if (fields & F_BUCKETS) {
-        char *bkt_str = strstr(string, "bucket");
+        char *bkt_str = strstr(string, "bucket=");
 
         if (bkt_str) {
             *bkt_str = '\0';
@@ -1208,7 +1234,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
             }
             bkt_str++;
 
-            next_bkt_str = strstr(bkt_str, "bucket");
+            next_bkt_str = strstr(bkt_str, "bucket=");
             if (next_bkt_str) {
                 *next_bkt_str = '\0';
             }
@@ -1235,7 +1261,38 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
             goto out;
         }
 
-        if (!strcmp(name, "group_id")) {
+        if (!strcmp(name, "command_bucket_id")) {
+            if (!(fields & F_COMMAND_BUCKET_ID)) {
+                error = xstrdup("command bucket id is not needed");
+                goto out;
+            }
+            if (!strcmp(value, "all")) {
+                gm->command_bucket_id = OFPG15_BUCKET_ALL;
+            } else if (!strcmp(value, "first")) {
+                gm->command_bucket_id = OFPG15_BUCKET_FIRST;
+            } else if (!strcmp(value, "last")) {
+                gm->command_bucket_id = OFPG15_BUCKET_LAST;
+            } else {
+                char *error = str_to_u32(value, &gm->command_bucket_id);
+                if (error) {
+                    goto out;
+                }
+                if (gm->command_bucket_id > OFPG15_BUCKET_MAX
+                    && (gm->command_bucket_id != OFPG15_BUCKET_FIRST
+                        && gm->command_bucket_id != OFPG15_BUCKET_LAST
+                        && gm->command_bucket_id != OFPG15_BUCKET_ALL)) {
+                    error = xasprintf("invalid command bucket id %"PRIu32,
+                                      gm->command_bucket_id);
+                    goto out;
+                }
+            }
+            if (gm->command_bucket_id == OFPG15_BUCKET_ALL
+                && !(fields & F_COMMAND_BUCKET_ID_ALL)) {
+                error = xstrdup("command_bucket_id=all is not permitted");
+                goto out;
+            }
+            had_command_bucket_id = true;
+        } else if (!strcmp(name, "group_id")) {
             if(!strcmp(value, "all")) {
                 gm->group_id = OFPG_ALL;
             } else {
@@ -1285,6 +1342,16 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
         goto out;
     }
 
+    if (fields & F_COMMAND_BUCKET_ID) {
+        if (!(fields & F_COMMAND_BUCKET_ID_ALL || had_command_bucket_id)) {
+            error = xstrdup("must specify a command bucket id");
+            goto out;
+        }
+    } else if (had_command_bucket_id) {
+        error = xstrdup("command bucket id is not needed");
+        goto out;
+    }
+
     /* Validate buckets. */
     LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
         if (bucket->weight != 1 && gm->type != OFPGT11_SELECT) {
@@ -1303,7 +1370,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
     return error;
 }
 
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_group_mod_str(struct ofputil_group_mod *gm, uint16_t command,
                         const char *str_,
                         enum ofputil_protocol *usable_protocols)
@@ -1319,7 +1386,7 @@ parse_ofp_group_mod_str(struct ofputil_group_mod *gm, uint16_t command,
     return error;
 }
 
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 parse_ofp_group_mod_file(const char *file_name, uint16_t command,
                          struct ofputil_group_mod **gms, size_t *n_gms,
                          enum ofputil_protocol *usable_protocols)