dpif: Change dpif API to allow multiple handler threads read upcall.
[sliver-openvswitch.git] / lib / ofp-parse.c
index e7fdd3b..b254ac6 100644 (file)
@@ -147,8 +147,7 @@ str_to_be64(const char *str, ovs_be64 *valuep)
 static char * WARN_UNUSED_RESULT
 str_to_mac(const char *str, uint8_t mac[6])
 {
-    if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
-        != ETH_ADDR_SCAN_COUNT) {
+    if (!ovs_scan(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
         return xasprintf("invalid mac address %s", str);
     }
     return NULL;
@@ -179,12 +178,13 @@ static char * WARN_UNUSED_RESULT
 parse_enqueue(char *arg, struct ofpbuf *ofpacts)
 {
     char *sp = NULL;
-    char *port = strtok_r(arg, ":q", &sp);
+    char *port = strtok_r(arg, ":q,", &sp);
     char *queue = strtok_r(NULL, "", &sp);
     struct ofpact_enqueue *enqueue;
 
     if (port == NULL || queue == NULL) {
-        return xstrdup("\"enqueue\" syntax is \"enqueue:PORT:QUEUE\"");
+        return xstrdup("\"enqueue\" syntax is \"enqueue:PORT:QUEUE\" or "
+                       "\"enqueue(PORT,QUEUE)\"");
     }
 
     enqueue = ofpact_put_ENQUEUE(ofpacts);
@@ -212,10 +212,10 @@ parse_output(const char *arg, struct ofpbuf *ofpacts)
         struct ofpact_output *output;
 
         output = ofpact_put_OUTPUT(ofpacts);
-        output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
         if (!ofputil_port_from_string(arg, &output->port)) {
             return xasprintf("%s: output to unknown port", arg);
         }
+        output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
         return NULL;
     }
 }
@@ -438,6 +438,42 @@ parse_dec_ttl(struct ofpbuf *b, char *arg)
     return NULL;
 }
 
+/* Parses 'arg' as the argument to a "set_mpls_label" action, and appends such
+ * an action to 'b'.
+ *
+ * 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
+parse_set_mpls_label(struct ofpbuf *b, const char *arg)
+{
+    struct ofpact_mpls_label *mpls_label = ofpact_put_SET_MPLS_LABEL(b);
+
+    if (*arg == '\0') {
+        return xstrdup("parse_set_mpls_label: expected label.");
+    }
+
+    mpls_label->label = htonl(atoi(arg));
+    return NULL;
+}
+
+/* Parses 'arg' as the argument to a "set_mpls_tc" action, and appends such an
+ * action to 'b'.
+ *
+ * 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
+parse_set_mpls_tc(struct ofpbuf *b, const char *arg)
+{
+    struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(b);
+
+    if (*arg == '\0') {
+        return xstrdup("parse_set_mpls_tc: expected tc.");
+    }
+
+    mpls_tc->tc = atoi(arg);
+    return NULL;
+}
+
 /* Parses 'arg' as the argument to a "set_mpls_ttl" action, and appends such an
  * action to 'ofpacts'.
  *
@@ -603,12 +639,14 @@ parse_named_action(enum ofputil_action_code code,
     char *error = NULL;
     uint16_t ethertype = 0;
     uint16_t vid = 0;
-    uint8_t tos = 0, ecn, ttl;
+    uint8_t tos = 0;
+    uint8_t ecn = 0;
+    uint8_t ttl = 0;
     uint8_t pcp = 0;
 
     switch (code) {
     case OFPUTIL_ACTION_INVALID:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
 
     case OFPUTIL_OFPAT10_OUTPUT:
     case OFPUTIL_OFPAT11_OUTPUT:
@@ -729,7 +767,7 @@ parse_named_action(enum ofputil_action_code code,
         break;
 
     case OFPUTIL_OFPAT11_DEC_NW_TTL:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
 
     case OFPUTIL_OFPAT10_SET_TP_SRC:
     case OFPUTIL_OFPAT11_SET_TP_SRC:
@@ -797,7 +835,7 @@ parse_named_action(enum ofputil_action_code code,
     case OFPUTIL_NXAST_RESUBMIT_TABLE:
     case OFPUTIL_NXAST_OUTPUT_REG:
     case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
 
     case OFPUTIL_NXAST_LEARN:
         error = learn_parse(arg, ofpacts);
@@ -811,6 +849,16 @@ parse_named_action(enum ofputil_action_code code,
         error = parse_dec_ttl(ofpacts, arg);
         break;
 
+    case OFPUTIL_NXAST_SET_MPLS_LABEL:
+    case OFPUTIL_OFPAT11_SET_MPLS_LABEL:
+        error = parse_set_mpls_label(ofpacts, arg);
+        break;
+
+    case OFPUTIL_NXAST_SET_MPLS_TC:
+    case OFPUTIL_OFPAT11_SET_MPLS_TC:
+        error = parse_set_mpls_tc(ofpacts, arg);
+        break;
+
     case OFPUTIL_NXAST_SET_MPLS_TTL:
     case OFPUTIL_OFPAT11_SET_MPLS_TTL:
         error = parse_set_mpls_ttl(ofpacts, arg);
@@ -975,7 +1023,7 @@ parse_named_instruction(enum ovs_instruction_type type,
 
     switch (type) {
     case OVSINST_OFPIT11_APPLY_ACTIONS:
-        NOT_REACHED();  /* This case is handled by str_to_inst_ofpacts() */
+        OVS_NOT_REACHED();  /* This case is handled by str_to_inst_ofpacts() */
         break;
 
     case OVSINST_OFPIT11_WRITE_ACTIONS: {
@@ -1159,8 +1207,7 @@ parse_field(const struct mf_field *mf, const char *s, struct match *match,
 
 static char * WARN_UNUSED_RESULT
 parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
-                enum ofputil_protocol *usable_protocols,
-                bool enforce_consistency)
+                enum ofputil_protocol *usable_protocols)
 {
     enum {
         F_OUT_PORT = 1 << 0,
@@ -1201,7 +1248,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
         break;
 
     default:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
 
     match_init_catchall(&fm->match);
@@ -1368,23 +1415,15 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
             enum ofperr err;
 
             err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
-                                true, OFPP_MAX, fm->table_id, 255);
+                                OFPP_MAX, fm->table_id, 255, usable_protocols);
+            if (!err && !usable_protocols) {
+                err = OFPERR_OFPBAC_MATCH_INCONSISTENT;
+            }
             if (err) {
-                if (!enforce_consistency &&
-                    err == OFPERR_OFPBAC_MATCH_INCONSISTENT) {
-                    /* Allow inconsistent actions to be used with OF 1.0. */
-                    *usable_protocols &= OFPUTIL_P_OF10_ANY;
-                    /* Try again, allowing for inconsistency.
-                     * XXX: As a side effect, logging may be duplicated. */
-                    err = ofpacts_check(ofpacts.data, ofpacts.size,
-                                        &fm->match.flow, false,
-                                        OFPP_MAX, fm->table_id, 255);
-                }
-                if (err) {
-                    error = xasprintf("actions are invalid with specified match "
-                                      "(%s)", ofperr_to_string(err));
-                }
+                error = xasprintf("actions are invalid with specified match "
+                                  "(%s)", ofperr_to_string(err));
             }
+
         }
         if (error) {
             ofpbuf_uninit(&ofpacts);
@@ -1413,14 +1452,12 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
  * error.  The caller is responsible for freeing the returned string. */
 char * WARN_UNUSED_RESULT
 parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
-              enum ofputil_protocol *usable_protocols,
-              bool enforce_consistency)
+              enum ofputil_protocol *usable_protocols)
 {
     char *string = xstrdup(str_);
     char *error;
 
-    error = parse_ofp_str__(fm, command, string, usable_protocols,
-                            enforce_consistency);
+    error = parse_ofp_str__(fm, command, string, usable_protocols);
     if (error) {
         fm->ofpacts = NULL;
         fm->ofpacts_len = 0;
@@ -1465,7 +1502,7 @@ parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
         break;
 
     default:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
 
     mm->command = command;
@@ -1767,11 +1804,9 @@ parse_ofpacts(const char *s_, struct ofpbuf *ofpacts,
 char * WARN_UNUSED_RESULT
 parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
                        uint16_t command,
-                       enum ofputil_protocol *usable_protocols,
-                       bool enforce_consistency)
+                       enum ofputil_protocol *usable_protocols)
 {
-    char *error = parse_ofp_str(fm, command, string, usable_protocols,
-                                enforce_consistency);
+    char *error = parse_ofp_str(fm, command, string, usable_protocols);
     if (!error) {
         /* Normalize a copy of the match.  This ensures that non-normalized
          * flows get logged but doesn't affect what gets sent to the switch, so
@@ -1798,7 +1833,7 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
     *usable_protocols = OFPUTIL_P_OF11_UP;
 
     if (!strcasecmp(table_id, "all")) {
-        tm->table_id = 255;
+        tm->table_id = OFPTT_ALL;
     } else {
         char *error = str_to_u8(table_id, "table_id", &tm->table_id);
         if (error) {
@@ -1833,8 +1868,7 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
 char * 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,
-                        bool enforce_consistency)
+                        enum ofputil_protocol *usable_protocols)
 {
     size_t allocated_fms;
     int line_number;
@@ -1863,7 +1897,7 @@ parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
             *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
         }
         error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command,
-                                       &usable, enforce_consistency);
+                                       &usable);
         if (error) {
             size_t i;
 
@@ -1895,14 +1929,12 @@ parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
 char * 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,
-                                 bool enforce_consistency)
+                                 enum ofputil_protocol *usable_protocols)
 {
     struct ofputil_flow_mod fm;
     char *error;
 
-    error = parse_ofp_str(&fm, -1, string, usable_protocols,
-                          enforce_consistency);
+    error = parse_ofp_str(&fm, -1, string, usable_protocols);
     if (error) {
         return error;
     }
@@ -2116,7 +2148,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
         break;
 
     default:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
 
     memset(gm, 0, sizeof *gm);
@@ -2286,7 +2318,12 @@ parse_ofp_group_mod_file(const char *file_name, uint16_t command,
         char *error;
 
         if (*n_gms >= allocated_gms) {
+            size_t i;
+
             *gms = x2nrealloc(*gms, &allocated_gms, sizeof **gms);
+            for (i = 0; i < *n_gms; i++) {
+                list_moved(&(*gms)[i].buckets);
+            }
         }
         error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s),
                                         &usable);