Prepare Open vSwitch 1.1.2 release.
[sliver-openvswitch.git] / lib / ofp-parse.c
index e77453e..e58ae27 100644 (file)
@@ -43,7 +43,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 +61,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 +275,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 +325,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 +415,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;
 
@@ -435,6 +440,7 @@ str_to_action(char *str, struct ofpbuf *b)
             if (remainder) {
                 ofpbuf_put_zeros(b, OFP_ACTION_ALIGN - remainder);
             }
+            nan = (struct nx_action_note *)((char *)b->data + start_ofs);
             nan->len = htons(b->size - start_ofs);
         } else if (!strcasecmp(act, "move")) {
             struct nx_action_reg_move *move;
@@ -472,7 +478,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);
@@ -540,7 +546,10 @@ parse_protocol(const char *name, const struct protocol **p_out)
     FIELD(F_ARP_SHA,     "arp_sha",     FWW_ARP_SHA)        \
     FIELD(F_ARP_THA,     "arp_tha",     FWW_ARP_THA)        \
     FIELD(F_IPV6_SRC,    "ipv6_src",    0)                  \
-    FIELD(F_IPV6_DST,    "ipv6_dst",    0)
+    FIELD(F_IPV6_DST,    "ipv6_dst",    0)                  \
+    FIELD(F_ND_TARGET,   "nd_target",   FWW_ND_TARGET)      \
+    FIELD(F_ND_SLL,      "nd_sll",      FWW_ARP_SHA)        \
+    FIELD(F_ND_TLL,      "nd_tll",      FWW_ARP_THA)
 
 enum field_index {
 #define FIELD(ENUM, NAME, WILDCARD) ENUM,
@@ -677,6 +686,21 @@ parse_field_value(struct cls_rule *rule, enum field_index index,
         cls_rule_set_ipv6_dst_masked(rule, &ipv6, &ipv6_mask);
         break;
 
+    case F_ND_TARGET:
+        str_to_ipv6(value, &ipv6, NULL);
+        cls_rule_set_nd_target(rule, ipv6);
+        break;
+
+    case F_ND_SLL:
+        str_to_mac(value, mac);
+        cls_rule_set_arp_sha(rule, mac);
+        break;
+
+    case F_ND_TLL:
+        str_to_mac(value, mac);
+        cls_rule_set_arp_tha(rule, mac);
+        break;
+
     case N_FIELDS:
         NOT_REACHED();
     }
@@ -703,7 +727,7 @@ 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
+void
 parse_ofp_str(struct flow_mod *fm, uint8_t *table_idx,
               struct ofpbuf *actions, char *string)
 {
@@ -797,7 +821,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);
@@ -848,30 +873,16 @@ 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,
+                        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;
+    struct ds s;
+    bool ok;
 
-        /* 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;
+    ds_init(&s);
+    ok = ds_get_preprocessed_line(&s, stream) == 0;
+    if (ok) {
+        parse_ofp_flow_mod_str(packets, cur, ds_cstr(&s), command);
     }
     ds_destroy(&s);
 
@@ -891,4 +902,3 @@ parse_ofp_flow_stats_request_str(struct flow_stats_request *fsr,
     fsr->out_port = fm.out_port;
     fsr->table_id = table_id;
 }
-