[ovs-dev] [learning v2 15/19] Implement new "learn" action.

Ethan Jackson ethan at nicira.com
Fri Sep 9 22:34:09 UTC 2011


I get the following compiler warning:

lib/learn.c: In function 'learn_format':
lib/learn.c:463:32: error: variable 'src_field' set but not used
[-Werror=unused-but-set-variable]

>     ovs-vsctl del-controller br0
>     ovs-ofctl del-flows br0
>     ovs-ofctl add-flow br0 "table=0 actions=learn(table=1, hard_timeout=10, \
>     	NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
>     	output:NXM_OF_IN_PORT[]), resubmit(,1)"
>     ovs-ofctl add-flow br0 "table=1 priority=0 actions=flood"
>
>     You can then dump the MAC learning table with:
>
>     ovs-ofctl dump-flows br0 table=1

This seems nifty.  Perhaps we should put this in the actual documentation
somewhere.  Maybe in the NXAST_LEARN documentation, or ovs-ofctl?

+      - Added an OpenFlow extension for flexible MAC learning.

I would just say "learning" not "MAC learning".  It's way more powerful than
that.

+ * The flow_mod_spec destination spec for 'dst' of 2 (when 'src' is 0) is
+ * empty.  It has the following meaning:
+ *
+ *   - The flow_mod_spec specifies an OFPAT_OUTPUT action for the new flow.
+ *     The new flow outputs to the OpenFlow port specified by the source field.
+ *     Of the special output ports with value OFPP_MAX or larger, OFPP_IN_PORT,
+ *     OFPP_FLOOD, OFPP_LOCAL, and OFPP_ALL are supported.  Other special ports
+ *     may not be used.

Do we need this?  I feel like it's going to get stale if unused.  I'd prefer
the action be orthogonal, users can just write the OpenFlow port to a register
and output to that register.

+ * These examples could work with various nx_action_learn parameters.  Typical
+ * values would be hard_timeout=OFP_FLOW_PERMANENT, hard_timeout=60,
+ * priority=OFP_DEFAULT_PRIORITY, flags=0, table_id=10.

Did you intend to specify hard_timeout twice in this sentence?

+#define NX_LEARN_DST_RESERVED  (3 << 11)
+#define NX_LEARN_DST_MASK      (3 << 11)

Do you intend to have NX_LEARN_DST_MASK in this patch?  If so, do we need
NX_LEARN_DST_RESERVED?  I'm slightly confused that they have the same value.

+static bool
+is_all_zeros(const uint8_t *field, size_t length)
+{
+    size_t i;
+
+    for (i = 0; i < length; i++) {
+        if (field[i] != 0x00) {
+            return false;
+        }
+    }
+    return true;
+}

This same function is in meta-flow along with it's cousin is_all_ones().
Perhaps we should pull it into util.  Seems generally useful.

+int
+learn_check(const struct nx_action_learn *learn, const struct flow *flow)
+{
+    struct cls_rule rule;
+    const void *p, *end;
+
+    cls_rule_init_catchall(&rule, 0);
+
+    if (learn->flags & ~htons(OFPFF_SEND_FLOW_REM)
+        || !is_all_zeros(learn->pad, sizeof learn->pad)
+        || learn->table_id == 0xff) {
+        return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
+    }
+
+    end = (char *) learn + ntohs(learn->len);
+    for (p = learn + 1; p != end; ) {

Should we check that learn->len >= sizeof learn before the for loop?

+            if (dst_type == NX_LEARN_DST_MATCH
+                && src_type == NX_LEARN_SRC_IMMEDIATE) {
+                mf_set_subfield(nxm_field_to_mf_field(ntohl(dst_field)), value,
+                                dst_ofs, n_bits, &rule);
+            }

It's not clear to me why we we need to make this call to mf_set_subfield().  If
there's a good reason for it, it could benefit from a comment.  If we don't need
it, then we could get rid of the cls_rule in this function, and the computation
of 'value'.

+        /* Check that the arguments don't overrun the end of the action. */
+        min_len = 0;
+        if (src_type == NX_LEARN_SRC_FIELD) {
+            min_len += sizeof(ovs_be32); /* src_header */
+            min_len += sizeof(ovs_be16); /* src_ofs */
+        } else {
+            min_len += 2 * DIV_ROUND_UP(n_bits, 16);
+        }
+        if (dst_type == NX_LEARN_DST_MATCH ||
+            dst_type == NX_LEARN_DST_LOAD) {
+            min_len += sizeof(ovs_be32); /* dst_header */
+            min_len += sizeof(ovs_be16); /* dst_ofs */
+        }

I wonder if this should be factored out into a helper since it's done twice.  It
could take 'header' as an argument.

+        switch (src_type | dst_type) {

Awesome! I had no idea you could do this.

+#ifndef LEARN_H
+#define LEARN_H 1
+
+#include <stdint.h>

I don't think this include is necessary.

diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index a97a0e3..6705ae4 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -16,6 +16,7 @@

 #include <config.h>
 #include "ofp-print.h"
+#include <ctype.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <netinet/icmp6.h>

Is this include addition necessary?

Ethan



More information about the dev mailing list