Fix table checking for goto table instruction.
[sliver-openvswitch.git] / lib / ofp-util.c
index 6c58415..aa4009d 100644 (file)
@@ -1086,8 +1086,19 @@ ofputil_usable_protocols(const struct match *match)
             | OFPUTIL_P_OF13_OXM;
     }
 
-    /* NXM and OXM support matching IPv6 traffic. */
-    if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
+    /* NXM and OXM support matching L3 and L4 fields within IPv6.
+     *
+     * (arp_sha, arp_tha, nw_frag, and nw_ttl are covered elsewhere so they
+     * don't need to be included in this test too.) */
+    if (match->flow.dl_type == htons(ETH_TYPE_IPV6)
+        && (!ipv6_mask_is_any(&wc->masks.ipv6_src)
+            || !ipv6_mask_is_any(&wc->masks.ipv6_dst)
+            || !ipv6_mask_is_any(&wc->masks.nd_target)
+            || wc->masks.ipv6_label
+            || wc->masks.tp_src
+            || wc->masks.tp_dst
+            || wc->masks.nw_proto
+            || wc->masks.nw_tos)) {
         return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
             | OFPUTIL_P_OF13_OXM;
     }
@@ -1112,12 +1123,6 @@ ofputil_usable_protocols(const struct match *match)
             | OFPUTIL_P_OF13_OXM;
     }
 
-    /* NXM and OXM support matching IPv6 flow label. */
-    if (wc->masks.ipv6_label) {
-        return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
-            | OFPUTIL_P_OF13_OXM;
-    }
-
     /* NXM and OXM support matching IP ECN bits. */
     if (wc->masks.nw_tos & IP_ECN_MASK) {
         return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
@@ -1502,8 +1507,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
             return error;
         }
 
-        error = ofpacts_pull_openflow11_instructions(&b, b.size, ofm->table_id,
-                                                     ofpacts);
+        error = ofpacts_pull_openflow11_instructions(&b, b.size, ofpacts);
         if (error) {
             return error;
         }
@@ -1646,7 +1650,7 @@ ofputil_pull_bands(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
 
     while (len >= sizeof (struct ofp13_meter_band_drop)) {
         size_t ombh_len = ntohs(ombh->len);
-        /* All supported band types have the same length */
+        /* All supported band types have the same length. */
         if (ombh_len != sizeof (struct ofp13_meter_band_drop)) {
             return OFPERR_OFPBRC_BAD_LEN;
         }
@@ -1693,8 +1697,7 @@ ofputil_decode_meter_mod(const struct ofp_header *oh,
         mm->meter.flags = ntohs(omm->flags);
         mm->meter.bands = bands->data;
 
-        error = ofputil_pull_bands(&b, b.size, &mm->meter.n_bands,
-                                   bands);
+        error = ofputil_pull_bands(&b, b.size, &mm->meter.n_bands, bands);
         if (error) {
             return error;
         }
@@ -1748,7 +1751,7 @@ ofputil_put_bands(uint16_t n_bands, const struct ofputil_meter_band *mb,
     uint16_t n = 0;
 
     for (n = 0; n < n_bands; ++n) {
-        /* Currently all band types have same size */
+        /* Currently all band types have same size. */
         struct ofp13_meter_band_dscp_remark *ombh;
         size_t ombh_len = sizeof *ombh;
 
@@ -1842,8 +1845,9 @@ ofputil_decode_meter_config(struct ofpbuf *msg,
 
     omc = ofpbuf_try_pull(msg, sizeof *omc);
     if (!omc) {
-        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPMP_METER_CONFIG reply has %zu "
-                     "leftover bytes at end", msg->size);
+        VLOG_WARN_RL(&bad_ofmsg_rl,
+                     "OFPMP_METER_CONFIG reply has %zu leftover bytes at end",
+                     msg->size);
         return OFPERR_OFPBRC_BAD_LEN;
     }
 
@@ -1868,13 +1872,16 @@ ofputil_pull_band_stats(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
     struct ofputil_meter_band_stats *mbs;
     uint16_t n, i;
 
+    ombs = ofpbuf_try_pull(msg, len);
+    if (!ombs) {
+        return OFPERR_OFPBRC_BAD_LEN;
+    }
+
     n = len / sizeof *ombs;
     if (len != n * sizeof *ombs) {
         return OFPERR_OFPBRC_BAD_LEN;
     }
 
-    ombs = ofpbuf_pull(msg, len);
-
     mbs = ofpbuf_put_uninit(bands, len);
 
     for (i = 0; i < n; ++i) {
@@ -1901,7 +1908,6 @@ ofputil_decode_meter_stats(struct ofpbuf *msg,
                            struct ofpbuf *bands)
 {
     const struct ofp13_meter_stats *oms;
-    uint16_t len;
     enum ofperr err;
 
     /* Pull OpenFlow headers for the first call. */
@@ -1915,15 +1921,15 @@ ofputil_decode_meter_stats(struct ofpbuf *msg,
 
     oms = ofpbuf_try_pull(msg, sizeof *oms);
     if (!oms) {
-        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPMP_METER reply has %zu leftover "
-                     "bytes at end", msg->size);
+        VLOG_WARN_RL(&bad_ofmsg_rl,
+                     "OFPMP_METER reply has %zu leftover bytes at end",
+                     msg->size);
         return OFPERR_OFPBRC_BAD_LEN;
     }
-    len = ntohs(oms->len);
-    len -= sizeof *oms;
 
     ofpbuf_clear(bands);
-    err = ofputil_pull_band_stats(msg, len, &ms->n_bands, bands);
+    err = ofputil_pull_band_stats(msg, ntohs(oms->len) - sizeof *oms,
+                                  &ms->n_bands, bands);
     if (err) {
         return err;
     }
@@ -2377,8 +2383,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
         }
 
         if (ofpacts_pull_openflow11_instructions(msg, length - sizeof *ofs -
-                                                 padded_match_len,
-                                                 ofs->table_id, ofpacts)) {
+                                                 padded_match_len, ofpacts)) {
             VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
             return EINVAL;
         }