Remove NXAST_DROP_SPOOFED_ARP action.
[sliver-openvswitch.git] / lib / ofp-parse.c
index c7ff4c3..afcaf87 100644 (file)
@@ -83,6 +83,27 @@ str_to_mac(const char *str, uint8_t mac[6])
     }
 }
 
+static void
+str_to_eth_dst(const char *str,
+               uint8_t mac[ETH_ADDR_LEN], uint8_t mask[ETH_ADDR_LEN])
+{
+    if (sscanf(str, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT,
+               ETH_ADDR_SCAN_ARGS(mac), ETH_ADDR_SCAN_ARGS(mask))
+        == ETH_ADDR_SCAN_COUNT * 2) {
+        if (!flow_wildcards_is_dl_dst_mask_valid(mask)) {
+            ovs_fatal(0, "%s: invalid Ethernet destination mask (only "
+                      "00:00:00:00:00:00, 01:00:00:00:00:00, "
+                      "fe:ff:ff:ff:ff:ff, and ff:ff:ff:ff:ff:ff are allowed)",
+                      str);
+        }
+    } else if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
+               == ETH_ADDR_SCAN_COUNT) {
+        memset(mask, 0xff, ETH_ADDR_LEN);
+    } else {
+        ovs_fatal(0, "invalid mac address %s", str);
+    }
+}
+
 static void
 str_to_ip(const char *str_, ovs_be32 *ip, ovs_be32 *maskp)
 {
@@ -389,11 +410,6 @@ str_to_action(char *str, struct ofpbuf *b)
                 nast->subtype = htons(NXAST_SET_TUNNEL);
                 nast->tun_id = htonl(tun_id);
             }
-        } else if (!strcasecmp(act, "drop_spoofed_arp")) {
-            struct nx_action_header *nah;
-            nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
-            nah->vendor = htonl(NX_VENDOR_ID);
-            nah->subtype = htons(NXAST_DROP_SPOOFED_ARP);
         } else if (!strcasecmp(act, "set_queue")) {
             struct nx_action_set_queue *nasq;
             nasq = put_action(b, sizeof *nasq, OFPAT_VENDOR);
@@ -537,7 +553,7 @@ parse_protocol(const char *name, const struct protocol **p_out)
     FIELD(F_DL_VLAN,     "dl_vlan",     0)                  \
     FIELD(F_DL_VLAN_PCP, "dl_vlan_pcp", 0)                  \
     FIELD(F_DL_SRC,      "dl_src",      FWW_DL_SRC)         \
-    FIELD(F_DL_DST,      "dl_dst",      FWW_DL_DST)         \
+    FIELD(F_DL_DST,      "dl_dst",      FWW_DL_DST | FWW_ETH_MCAST) \
     FIELD(F_DL_TYPE,     "dl_type",     FWW_DL_TYPE)        \
     FIELD(F_NW_SRC,      "nw_src",      0)                  \
     FIELD(F_NW_DST,      "nw_dst",      0)                  \
@@ -592,7 +608,7 @@ static void
 parse_field_value(struct cls_rule *rule, enum field_index index,
                   const char *value)
 {
-    uint8_t mac[ETH_ADDR_LEN];
+    uint8_t mac[ETH_ADDR_LEN], mac_mask[ETH_ADDR_LEN];
     ovs_be64 tun_id, tun_mask;
     ovs_be32 ip, mask;
     struct in6_addr ipv6, ipv6_mask;
@@ -625,8 +641,8 @@ parse_field_value(struct cls_rule *rule, enum field_index index,
         break;
 
     case F_DL_DST:
-        str_to_mac(value, mac);
-        cls_rule_set_dl_dst(rule, mac);
+        str_to_eth_dst(value, mac, mac_mask);
+        cls_rule_set_dl_dst_masked(rule, mac, mac_mask);
         break;
 
     case F_DL_TYPE:
@@ -845,6 +861,7 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
 {
     bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT;
     enum nx_flow_format min_format, next_format;
+    struct cls_rule rule_copy;
     struct ofpbuf actions;
     struct ofpbuf *ofm;
     struct flow_mod fm;
@@ -853,7 +870,7 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
     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);
@@ -861,6 +878,12 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
         *cur_format = next_format;
     }
 
+    /* Normalize a copy of the rule.  This ensures that non-normalized flows
+     * get logged but doesn't affect what gets sent to the switch, so that the
+     * switch can do whatever it likes with the flow. */
+    rule_copy = fm.cr;
+    ofputil_normalize_rule(&rule_copy, next_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);