appveyor: Renew SSL link.
[cascardo/ovs.git] / lib / nx-match.c
index 1a6b89a..54645df 100644 (file)
@@ -31,6 +31,7 @@
 #include "openflow/nicira-ext.h"
 #include "packets.h"
 #include "shash.h"
+#include "tun-metadata.h"
 #include "unaligned.h"
 #include "util.h"
 #include "openvswitch/vlog.h"
@@ -682,7 +683,7 @@ nxm_put_unmasked(struct ofpbuf *b, enum mf_field_id field,
     ofpbuf_put(b, value, n_bytes);
 }
 
-static void
+void
 nxm_put(struct ofpbuf *b, enum mf_field_id field, enum ofp_version version,
         const void *value, const void *mask, size_t n_bytes)
 {
@@ -894,7 +895,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
     int match_len;
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 31);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33);
 
     /* Metadata. */
     if (match->wc.masks.dp_hash) {
@@ -999,6 +1000,8 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
                 flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
 
     /* Other tunnel metadata. */
+    nxm_put_16m(b, MFF_TUN_FLAGS, oxm,
+                htons(flow->tunnel.flags), htons(match->wc.masks.tunnel.flags));
     nxm_put_32m(b, MFF_TUN_SRC, oxm,
                 flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
     nxm_put_32m(b, MFF_TUN_DST, oxm,
@@ -1007,6 +1010,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
                 flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id);
     nxm_put_8m(b, MFF_TUN_GBP_FLAGS, oxm,
                flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags);
+    tun_metadata_to_nx_match(b, oxm, match);
 
     /* Registers. */
     if (oxm < OFP15_VERSION) {
@@ -1168,8 +1172,10 @@ oxm_put_field_array(struct ofpbuf *b, const struct field_array *fa,
 
     for (i = 0; i < MFF_N_IDS; i++) {
         if (bitmap_is_set(fa->used.bm, i)) {
-            nxm_put_unmasked(b, i, version, &fa->value[i],
-                             mf_from_id(i)->n_bytes);
+            int len = mf_field_len(mf_from_id(i), &fa->value[i], NULL);
+            nxm_put_unmasked(b, i, version,
+                             &fa->value[i].u8 + mf_from_id(i)->n_bytes - len,
+                             len);
         }
     }
 
@@ -1210,13 +1216,17 @@ nx_put_entry(struct ofpbuf *b,
              enum mf_field_id field, enum ofp_version version,
              const union mf_value *value, const union mf_value *mask)
 {
-    int n_bytes = mf_from_id(field)->n_bytes;
-    bool masked = mask && !is_all_ones(mask, n_bytes);
+    const struct mf_field *mf = mf_from_id(field);
+    bool masked = mask && !is_all_ones(mask, mf->n_bytes);
+    int len, offset;
 
-    nx_put_header(b, field, version, masked);
-    ofpbuf_put(b, value, n_bytes);
+    len = mf_field_len(mf, value, mask);
+    offset = mf->n_bytes - len;
+
+    nx_put_header_len(b, field, version, masked, len);
+    ofpbuf_put(b, &value->u8 + offset, len);
     if (masked) {
-        ofpbuf_put(b, mask, n_bytes);
+        ofpbuf_put(b, &mask->u8 + offset, len);
     }
 }
 \f
@@ -1409,6 +1419,8 @@ nx_match_from_string_raw(const char *s, struct ofpbuf *b)
     for (s += strspn(s, ", "); *s; s += strspn(s, ", ")) {
         const char *name;
         uint64_t header;
+        ovs_be64 nw_header;
+        ovs_be64 *header_ptr;
         int name_len;
         size_t n;
 
@@ -1425,11 +1437,31 @@ nx_match_from_string_raw(const char *s, struct ofpbuf *b)
 
         s += name_len + 1;
 
-        nx_put_header__(b, header, false);
+        header_ptr = ofpbuf_put_uninit(b, nxm_header_len(header));
         s = ofpbuf_put_hex(b, s, &n);
         if (n != nxm_field_bytes(header)) {
-            ovs_fatal(0, "%.2s: hex digits expected", s);
+            const struct mf_field *field = mf_from_oxm_header(header);
+
+            if (field && field->variable_len) {
+                if (n <= field->n_bytes) {
+                    int len = (nxm_hasmask(header) ? n * 2 : n) +
+                              nxm_experimenter_len(header);
+
+                    header = NXM_HEADER(nxm_vendor(header), nxm_class(header),
+                                        nxm_field(header),
+                                        nxm_hasmask(header) ? 1 : 0, len);
+                } else {
+                    ovs_fatal(0, "expected to read at most %d bytes but got "
+                              "%"PRIuSIZE, field->n_bytes, n);
+                }
+            } else {
+                ovs_fatal(0, "expected to read %d bytes but got %"PRIuSIZE,
+                          nxm_field_bytes(header), n);
+            }
         }
+        nw_header = htonll(header);
+        memcpy(header_ptr, &nw_header, nxm_header_len(header));
+
         if (nxm_hasmask(header)) {
             s += strspn(s, " ");
             if (*s != '/') {
@@ -1545,8 +1577,8 @@ nxm_execute_reg_move(const struct ofpact_reg_move *move,
     union mf_value src_value;
     union mf_value dst_value;
 
-    mf_mask_field_and_prereqs(move->dst.field, &wc->masks);
-    mf_mask_field_and_prereqs(move->src.field, &wc->masks);
+    mf_mask_field_and_prereqs(move->dst.field, wc);
+    mf_mask_field_and_prereqs(move->src.field, wc);
 
     /* A flow may wildcard nw_frag.  Do nothing if setting a transport
      * header field on a packet that does not have them. */