Setting tag sliver-openvswitch-1.10.90-3
[sliver-openvswitch.git] / lib / learn.c
index cd75321..0cc562d 100644 (file)
@@ -339,7 +339,6 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
         case NX_LEARN_DST_LOAD:
             for (ofs = 0; ofs < spec->n_bits; ofs += chunk) {
                 struct ofpact_reg_load *load;
-                ovs_be64 value_be;
 
                 chunk = MIN(spec->n_bits - ofs, 64);
 
@@ -347,21 +346,18 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
                 load->dst.field = spec->dst.field;
                 load->dst.ofs = spec->dst.ofs + ofs;
                 load->dst.n_bits = chunk;
-
-                memset(&value_be, 0, sizeof value_be);
                 bitwise_copy(&value, sizeof value, ofs,
-                             &value_be, sizeof value_be, 0,
+                             &load->subvalue, sizeof load->subvalue, 0,
                              chunk);
-                load->value = ntohll(value_be);
             }
             break;
 
         case NX_LEARN_DST_OUTPUT:
             if (spec->n_bits <= 16
                 || is_all_zeros(value.u8, sizeof value - 2)) {
-                uint16_t port = ntohs(value.be16[7]);
+                ofp_port_t port = u16_to_ofp(ntohs(value.be16[7]));
 
-                if (port < OFPP_MAX
+                if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX)
                     || port == OFPP_IN_PORT
                     || port == OFPP_FLOOD
                     || port == OFPP_LOCAL
@@ -378,6 +374,22 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
     fm->ofpacts_len = ofpacts->size;
 }
 
+/* Perform a bitwise-OR on 'wc''s fields that are relevant as sources in
+ * the learn action 'learn'. */
+void
+learn_mask(const struct ofpact_learn *learn, struct flow_wildcards *wc)
+{
+    const struct ofpact_learn_spec *spec;
+    union mf_subvalue value;
+
+    memset(&value, 0xff, sizeof value);
+    for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {
+        if (spec->src_type == NX_LEARN_SRC_FIELD) {
+            mf_write_subfield_flow(&spec->src, &value, &wc->masks);
+        }
+    }
+}
+
 static void
 learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
 {
@@ -516,14 +528,13 @@ learn_parse_spec(const char *orig, char *name, char *value,
  *
  * Modifies 'arg'. */
 void
-learn_parse(char *arg, const struct flow *flow, struct ofpbuf *ofpacts)
+learn_parse(char *arg, struct ofpbuf *ofpacts)
 {
     char *orig = xstrdup(arg);
     char *name, *value;
 
     struct ofpact_learn *learn;
     struct match match;
-    enum ofperr error;
 
     learn = ofpact_put_LEARN(ofpacts);
     learn->idle_timeout = OFP_FLOW_PERMANENT;
@@ -560,21 +571,6 @@ learn_parse(char *arg, const struct flow *flow, struct ofpbuf *ofpacts)
 
             learn_parse_spec(orig, name, value, spec);
 
-            /* Check prerequisites. */
-            if (spec->src_type == NX_LEARN_SRC_FIELD
-                && flow && !mf_are_prereqs_ok(spec->src.field, flow)) {
-                ovs_fatal(0, "%s: cannot specify source field %s because "
-                          "prerequisites are not satisfied",
-                          orig, spec->src.field->name);
-            }
-            if ((spec->dst_type == NX_LEARN_DST_MATCH
-                 || spec->dst_type == NX_LEARN_DST_LOAD)
-                && !mf_are_prereqs_ok(spec->dst.field, &match.flow)) {
-                ovs_fatal(0, "%s: cannot specify destination field %s because "
-                          "prerequisites are not satisfied",
-                          orig, spec->dst.field->name);
-            }
-
             /* Update 'match' to allow for satisfying destination
              * prerequisites. */
             if (spec->src_type == NX_LEARN_SRC_IMMEDIATE
@@ -585,33 +581,9 @@ learn_parse(char *arg, const struct flow *flow, struct ofpbuf *ofpacts)
     }
     ofpact_update_len(ofpacts, &learn->ofpact);
 
-    /* In theory the above should have caught any errors, but... */
-    if (flow) {
-        error = learn_check(learn, flow);
-        if (error) {
-            ovs_fatal(0, "%s: %s", orig, ofperr_to_string(error));
-        }
-    }
     free(orig);
 }
 
-static void
-format_subvalue(const union mf_subvalue *subvalue, struct ds *s)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(subvalue->u8); i++) {
-        if (subvalue->u8[i]) {
-            ds_put_format(s, "0x%"PRIx8, subvalue->u8[i]);
-            for (i++; i < ARRAY_SIZE(subvalue->u8); i++) {
-                ds_put_format(s, "%02"PRIx8, subvalue->u8[i]);
-            }
-            return;
-        }
-    }
-    ds_put_char(s, '0');
-}
-
 /* Appends a description of 'learn' to 's', in the format that ovs-ofctl(8)
  * describes. */
 void
@@ -663,7 +635,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s)
             } else {
                 mf_format_subfield(&spec->dst, s);
                 ds_put_char(s, '=');
-                format_subvalue(&spec->src_imm, s);
+                mf_format_subvalue(&spec->src_imm, s);
             }
             break;
 
@@ -678,7 +650,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s)
 
         case NX_LEARN_SRC_IMMEDIATE | NX_LEARN_DST_LOAD:
             ds_put_format(s, "load:");
-            format_subvalue(&spec->src_imm, s);
+            mf_format_subvalue(&spec->src_imm, s);
             ds_put_cstr(s, "->");
             mf_format_subfield(&spec->dst, s);
             break;