Merge 'master' into 'next'.
[sliver-openvswitch.git] / lib / ofp-parse.c
index 3fac474..29137ac 100644 (file)
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include "autopath.h"
 #include "byte-order.h"
 #include "dynamic-string.h"
 #include "netdev.h"
@@ -43,7 +44,7 @@ str_to_u32(const char *str)
     char *tail;
     uint32_t value;
 
-    if (!str) {
+    if (!str[0]) {
         ovs_fatal(0, "missing required numeric argument");
     }
 
@@ -61,6 +62,10 @@ str_to_u64(const char *str)
     char *tail;
     uint64_t value;
 
+    if (!str[0]) {
+        ovs_fatal(0, "missing required numeric argument");
+    }
+
     errno = 0;
     value = strtoull(str, &tail, 0);
     if (errno == EINVAL || errno == ERANGE || *tail) {
@@ -271,6 +276,7 @@ str_to_action(char *str, struct ofpbuf *b)
     pos = str;
     n_actions = 0;
     for (;;) {
+        char empty_string[] = "";
         char *act, *arg;
         size_t actlen;
         uint16_t port;
@@ -320,7 +326,7 @@ str_to_action(char *str, struct ofpbuf *b)
             pos = arg + arglen;
         } else {
             /* There might be no argument at all. */
-            arg = NULL;
+            arg = empty_string;
             pos = act + actlen + (act[actlen] != '\0');
         }
         act[actlen] = '\0';
@@ -410,7 +416,7 @@ str_to_action(char *str, struct ofpbuf *b)
             nan->subtype = htons(NXAST_NOTE);
 
             b->size -= sizeof nan->note;
-            while (arg && *arg != '\0') {
+            while (*arg != '\0') {
                 uint8_t byte;
                 bool ok;
 
@@ -448,6 +454,10 @@ str_to_action(char *str, struct ofpbuf *b)
             struct nx_action_multipath *nam;
             nam = ofpbuf_put_uninit(b, sizeof *nam);
             multipath_parse(nam, arg);
+        } else if (!strcasecmp(act, "autopath")) {
+            struct nx_action_autopath *naa;
+            naa = ofpbuf_put_uninit(b, sizeof *naa);
+            autopath_parse(naa, arg);
         } else if (!strcasecmp(act, "output")) {
             put_output_action(b, str_to_u32(arg));
         } else if (!strcasecmp(act, "enqueue")) {
@@ -472,7 +482,7 @@ str_to_action(char *str, struct ofpbuf *b)
 
             /* Unless a numeric argument is specified, we send the whole
              * packet to the controller. */
-            if (arg && (strspn(arg, "0123456789") == strlen(arg))) {
+            if (arg[0] && (strspn(arg, "0123456789") == strlen(arg))) {
                oao->max_len = htons(str_to_u32(arg));
             } else {
                 oao->max_len = htons(UINT16_MAX);
@@ -598,9 +608,6 @@ parse_field_value(struct cls_rule *rule, enum field_index index,
         if (!parse_port_name(value, &port_no)) {
             port_no = atoi(value);
         }
-        if (port_no == OFPP_LOCAL) {
-            port_no = ODPP_LOCAL;
-        }
         cls_rule_set_in_port(rule, port_no);
         break;
 
@@ -721,18 +728,15 @@ parse_reg_value(struct cls_rule *rule, int reg_idx, const char *value)
 /* Convert 'string' (as described in the Flow Syntax section of the ovs-ofctl
  * man page) into 'pf'.  If 'actions' is specified, an action must be in
  * 'string' and may be expanded or reallocated. */
-static void
-parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
-              struct ofpbuf *actions, char *string)
+void
+parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string)
 {
     char *save_ptr = NULL;
     char *name;
 
-    if (table_idx) {
-        *table_idx = 0xff;
-    }
     cls_rule_init_catchall(&fm->cr, OFP_DEFAULT_PRIORITY);
     fm->cookie = htonll(0);
+    fm->table_id = 0xff;
     fm->command = UINT16_MAX;
     fm->idle_timeout = OFP_FLOW_PERMANENT;
     fm->hard_timeout = OFP_FLOW_PERMANENT;
@@ -778,8 +782,8 @@ parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
                 ovs_fatal(0, "field %s missing value", name);
             }
 
-            if (table_idx && !strcmp(name, "table")) {
-                *table_idx = atoi(value);
+            if (!strcmp(name, "table")) {
+                fm->table_id = atoi(value);
             } else if (!strcmp(name, "out_port")) {
                 fm->out_port = atoi(value);
             } else if (!strcmp(name, "priority")) {
@@ -815,7 +819,8 @@ parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
                 } else {
                     parse_field_value(&fm->cr, f->index, value);
                 }
-            } else if (!strncmp(name, "reg", 3) && isdigit(name[3])) {
+            } else if (!strncmp(name, "reg", 3)
+                       && isdigit((unsigned char) name[3])) {
                 unsigned int reg_idx = atoi(name + 3);
                 if (reg_idx >= FLOW_N_REGS) {
                     ovs_fatal(0, "only %d registers supported", FLOW_N_REGS);
@@ -836,7 +841,7 @@ parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
  * flow. */
 void
 parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
-                       char *string, uint16_t command)
+                       bool *flow_mod_table_id, char *string, uint16_t command)
 {
     bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT;
     enum nx_flow_format min_format, next_format;
@@ -845,10 +850,10 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
     struct flow_mod fm;
 
     ofpbuf_init(&actions, 64);
-    parse_ofp_str(&fm, NULL, is_del ? NULL : &actions, string);
+    parse_ofp_str(&fm, is_del ? NULL : &actions, string);
     fm.command = command;
 
-    min_format = ofputil_min_flow_format(&fm.cr, true, fm.cookie);
+    min_format = ofputil_min_flow_format(&fm.cr);
     next_format = MAX(*cur_format, min_format);
     if (next_format != *cur_format) {
         struct ofpbuf *sff = ofputil_make_set_flow_format(next_format);
@@ -856,7 +861,13 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
         *cur_format = next_format;
     }
 
-    ofm = ofputil_encode_flow_mod(&fm, *cur_format);
+    if (fm.table_id != 0xff && !*flow_mod_table_id) {
+        struct ofpbuf *sff = ofputil_make_flow_mod_table_id(true);
+        list_push_back(packets, &sff->list_node);
+        *flow_mod_table_id = true;
+    }
+
+    ofm = ofputil_encode_flow_mod(&fm, *cur_format, *flow_mod_table_id);
     list_push_back(packets, &ofm->list_node);
 
     ofpbuf_uninit(&actions);
@@ -866,30 +877,18 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
  * 'stream' and the command is always OFPFC_ADD.  Returns false if end-of-file
  * is reached before reading a flow, otherwise true. */
 bool
-parse_ofp_add_flow_file(struct list *packets, enum nx_flow_format *cur,
-                        FILE *stream)
+parse_ofp_flow_mod_file(struct list *packets,
+                        enum nx_flow_format *cur, bool *flow_mod_table_id,
+                        FILE *stream, uint16_t command)
 {
-    struct ds s = DS_EMPTY_INITIALIZER;
-    bool ok = false;
-
-    while (!ds_get_line(&s, stream)) {
-        char *line = ds_cstr(&s);
-        char *comment;
-
-        /* Delete comments. */
-        comment = strchr(line, '#');
-        if (comment) {
-            *comment = '\0';
-        }
-
-        /* Drop empty lines. */
-        if (line[strspn(line, " \t\n")] == '\0') {
-            continue;
-        }
-
-        parse_ofp_flow_mod_str(packets, cur, line, OFPFC_ADD);
-        ok = true;
-        break;
+    struct ds s;
+    bool ok;
+
+    ds_init(&s);
+    ok = ds_get_preprocessed_line(&s, stream) == 0;
+    if (ok) {
+        parse_ofp_flow_mod_str(packets, cur, flow_mod_table_id,
+                               ds_cstr(&s), command);
     }
     ds_destroy(&s);
 
@@ -901,12 +900,10 @@ parse_ofp_flow_stats_request_str(struct flow_stats_request *fsr,
                                  bool aggregate, char *string)
 {
     struct flow_mod fm;
-    uint8_t table_id;
 
-    parse_ofp_str(&fm, &table_id, NULL, string);
+    parse_ofp_str(&fm, NULL, string);
     fsr->aggregate = aggregate;
     fsr->match = fm.cr;
     fsr->out_port = fm.out_port;
-    fsr->table_id = table_id;
+    fsr->table_id = fm.table_id;
 }
-