aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-09-12 16:19:57 -0700
committerBen Pfaff <blp@nicira.com>2011-09-13 11:46:09 -0700
commit75a75043564dc9b002fffa6c6ad71e0d4d5c892e (patch)
tree2e059054c5b3e146e3777c013f6cac42246ffa4c /include
parent308881afb61e292c629b36a357cfc37153884000 (diff)
Implement new "learn" action.
There are a few loose ends here. First, learning actions cause too much flow revalidation. Upcoming commits will fix that problem. The following additional issues have not yet been addressed: * Resource limits: nothing yet limits the maximum number of flows that can be learned. It is possible to exhaust all system memory. * Age reporting: there is no way to find out how soon a learned table entry is due to be evicted. To try this action out, here's a recipe for a very simple-minded MAC learning switch. It uses a 10-second MAC expiration time to make it easier to see what's going on: 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
Diffstat (limited to 'include')
-rw-r--r--include/openflow/nicira-ext.h216
1 files changed, 215 insertions, 1 deletions
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 4fab6f17..6ce87a25 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -281,7 +281,8 @@ enum nx_action_subtype {
NXAST_BUNDLE, /* struct nx_action_bundle */
NXAST_BUNDLE_LOAD, /* struct nx_action_bundle */
NXAST_RESUBMIT_TABLE, /* struct nx_action_resubmit */
- NXAST_OUTPUT_REG /* struct nx_action_output_reg */
+ NXAST_OUTPUT_REG, /* struct nx_action_output_reg */
+ NXAST_LEARN /* struct nx_action_learn */
};
/* Header for Nicira-defined actions. */
@@ -656,6 +657,219 @@ enum nx_mp_algorithm {
NX_MP_ALG_ITER_HASH /* Iterative Hash. */
};
+/* Action structure for NXAST_LEARN.
+ *
+ * This action adds or modifies a flow in an OpenFlow table, similar to
+ * OFPT_FLOW_MOD with OFPFC_MODIFY_STRICT as 'command'. The new flow has the
+ * specified idle timeout, hard timeout, priority, cookie, and flags. The new
+ * flow's match criteria and actions are built by applying each of the series
+ * of flow_mod_spec elements included as part of the action.
+ *
+ * A flow_mod_spec starts with a 16-bit header. A header that is all-bits-0 is
+ * a no-op used for padding the action as a whole to a multiple of 8 bytes in
+ * length. Otherwise, the flow_mod_spec can be thought of as copying 'n_bits'
+ * bits from a source to a destination. In this case, the header contains
+ * multiple fields:
+ *
+ * 15 14 13 12 11 10 0
+ * +------+---+------+---------------------------------+
+ * | 0 |src| dst | n_bits |
+ * +------+---+------+---------------------------------+
+ *
+ * The meaning and format of a flow_mod_spec depends on 'src' and 'dst'. The
+ * following table summarizes the meaning of each possible combination.
+ * Details follow the table:
+ *
+ * src dst meaning
+ * --- --- ----------------------------------------------------------
+ * 0 0 Add match criteria based on value in a field.
+ * 1 0 Add match criteria based on an immediate value.
+ * 0 1 Add NXAST_REG_LOAD action to copy field into a different field.
+ * 1 1 Add NXAST_REG_LOAD action to load immediate value into a field.
+ * 0 2 Add OFPAT_OUTPUT action to output to port from specified field.
+ * All other combinations are undefined and not allowed.
+ *
+ * The flow_mod_spec header is followed by a source specification and a
+ * destination specification. The format and meaning of the source
+ * specification depends on 'src':
+ *
+ * - If 'src' is 0, the source bits are taken from a field in the flow to
+ * which this action is attached. (This should be a wildcarded field. If
+ * its value is fully specified then the source bits being copied have
+ * constant values.)
+ *
+ * The source specification is an ovs_be32 'field' and an ovs_be16 'ofs'.
+ * 'field' is an nxm_header with nxm_hasmask=0, and 'ofs' the starting bit
+ * offset within that field. The source bits are field[ofs:ofs+n_bits-1].
+ * 'field' and 'ofs' are subject to the same restrictions as the source
+ * field in NXAST_REG_MOVE.
+ *
+ * - If 'src' is 1, the source bits are a constant value. The source
+ * specification is (n_bits+15)/16*2 bytes long. Taking those bytes as a
+ * number in network order, the source bits are the 'n_bits'
+ * least-significant bits. The switch will report an error if other bits
+ * in the constant are nonzero.
+ *
+ * The flow_mod_spec destination specification, for 'dst' of 0 or 1, is an
+ * ovs_be32 'field' and an ovs_be16 'ofs'. 'field' is an nxm_header with
+ * nxm_hasmask=0 and 'ofs' is a starting bit offset within that field. The
+ * meaning of the flow_mod_spec depends on 'dst':
+ *
+ * - If 'dst' is 0, the flow_mod_spec specifies match criteria for the new
+ * flow. The new flow matches only if bits field[ofs:ofs+n_bits-1] in a
+ * packet equal the source bits. 'field' may be any nxm_header with
+ * nxm_hasmask=0 that is allowed in NXT_FLOW_MOD.
+ *
+ * Order is significant. Earlier flow_mod_specs must satisfy any
+ * prerequisites for matching fields specified later, by copying constant
+ * values into prerequisite fields.
+ *
+ * The switch will reject flow_mod_specs that do not satisfy NXM masking
+ * restrictions.
+ *
+ * - If 'dst' is 1, the flow_mod_spec specifies an NXAST_REG_LOAD action for
+ * the new flow. The new flow copies the source bits into
+ * field[ofs:ofs+n_bits-1]. Actions are executed in the same order as the
+ * flow_mod_specs.
+ *
+ * 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.
+ *
+ * Resource Management
+ * -------------------
+ *
+ * A switch has a finite amount of flow table space available for learning.
+ * When this space is exhausted, no new learning table entries will be learned
+ * until some existing flow table entries expire. The controller should be
+ * prepared to handle this by flooding (which can be implemented as a
+ * low-priority flow).
+ *
+ * Examples
+ * --------
+ *
+ * The following examples give a prose description of the flow_mod_specs along
+ * with informal notation for how those would be represented and a hex dump of
+ * the bytes that would be required.
+ *
+ * These examples could work with various nx_action_learn parameters. Typical
+ * values would be idle_timeout=OFP_FLOW_PERMANENT, hard_timeout=60,
+ * priority=OFP_DEFAULT_PRIORITY, flags=0, table_id=10.
+ *
+ * 1. Learn input port based on the source MAC, with lookup into
+ * NXM_NX_REG1[16:31] by resubmit to in_port=99:
+ *
+ * Match on in_port=99:
+ * ovs_be16(src=1, dst=0, n_bits=16), 20 10
+ * ovs_be16(99), 00 63
+ * ovs_be32(NXM_OF_IN_PORT), ovs_be16(0) 00 00 00 02 00 00
+ *
+ * Match Ethernet destination on Ethernet source from packet:
+ * ovs_be16(src=0, dst=0, n_bits=48), 00 30
+ * ovs_be32(NXM_OF_ETH_SRC), ovs_be16(0) 00 00 04 06 00 00
+ * ovs_be32(NXM_OF_ETH_DST), ovs_be16(0) 00 00 02 06 00 00
+ *
+ * Set NXM_NX_REG1[16:31] to the packet's input port:
+ * ovs_be16(src=0, dst=1, n_bits=16), 08 10
+ * ovs_be32(NXM_OF_IN_PORT), ovs_be16(0) 00 00 00 02 00 00
+ * ovs_be32(NXM_NX_REG1), ovs_be16(16) 00 01 02 04 00 10
+ *
+ * Given a packet that arrived on port A with Ethernet source address B,
+ * this would set up the flow "in_port=99, dl_dst=B,
+ * actions=load:A->NXM_NX_REG1[16..31]".
+ *
+ * In syntax accepted by ovs-ofctl, this action is: learn(in_port=99,
+ * NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
+ *
+ * 2. Output to input port based on the source MAC and VLAN VID, with lookup
+ * into NXM_NX_REG1[16:31]:
+ *
+ * Match on same VLAN ID as packet:
+ * ovs_be16(src=0, dst=0, n_bits=12), 00 0c
+ * ovs_be32(NXM_OF_VLAN_TCI), ovs_be16(0) 00 00 08 02 00 00
+ * ovs_be32(NXM_OF_VLAN_TCI), ovs_be16(0) 00 00 08 02 00 00
+ *
+ * Match Ethernet destination on Ethernet source from packet:
+ * ovs_be16(src=0, dst=0, n_bits=48), 00 30
+ * ovs_be32(NXM_OF_ETH_SRC), ovs_be16(0) 00 00 04 06 00 00
+ * ovs_be32(NXM_OF_ETH_DST), ovs_be16(0) 00 00 02 06 00 00
+ *
+ * Output to the packet's input port:
+ * ovs_be16(src=0, dst=2, n_bits=16), 10 10
+ * ovs_be32(NXM_OF_IN_PORT), ovs_be16(0) 00 00 00 02 00 00
+ *
+ * Given a packet that arrived on port A with Ethernet source address B in
+ * VLAN C, this would set up the flow "dl_dst=B, vlan_vid=C,
+ * actions=output:A".
+ *
+ * In syntax accepted by ovs-ofctl, this action is:
+ * learn(NXM_OF_VLAN_TCI[0..11], NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],
+ * output:NXM_OF_IN_PORT[])
+ *
+ * 3. Here's a recipe for a very simple-minded MAC learning switch. It uses a
+ * 10-second MAC expiration time to make it easier to see what's going on
+ *
+ * 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
+ *
+ * Usage Advice
+ * ------------
+ *
+ * For best performance, segregate learned flows into a table that is not used
+ * for any other flows except possibly for a lowest-priority "catch-all" flow
+ * (a flow with no match criteria). If different learning actions specify
+ * different match criteria, use different tables for the learned flows.
+ *
+ * The meaning of 'hard_timeout' and 'idle_timeout' can be counterintuitive.
+ * These timeouts apply to the flow that is added, which means that a flow with
+ * an idle timeout will expire when no traffic has been sent *to* the learned
+ * address. This is not usually the intent in MAC learning; instead, we want
+ * the MAC learn entry to expire when no traffic has been sent *from* the
+ * learned address. Use a hard timeout for that.
+ */
+struct nx_action_learn {
+ ovs_be16 type; /* OFPAT_VENDOR. */
+ ovs_be16 len; /* At least 24. */
+ ovs_be32 vendor; /* NX_VENDOR_ID. */
+ ovs_be16 subtype; /* NXAST_LEARN. */
+ ovs_be16 idle_timeout; /* Idle time before discarding (seconds). */
+ ovs_be16 hard_timeout; /* Max time before discarding (seconds). */
+ ovs_be16 priority; /* Priority level of flow entry. */
+ ovs_be64 cookie; /* Cookie for new flow. */
+ ovs_be16 flags; /* Either 0 or OFPFF_SEND_FLOW_REM. */
+ uint8_t table_id; /* Table to insert flow entry. */
+ uint8_t pad[5]; /* Must be zero. */
+ /* Followed by a sequence of flow_mod_spec elements, as described above,
+ * until the end of the action is reached. */
+};
+OFP_ASSERT(sizeof(struct nx_action_learn) == 32);
+
+#define NX_LEARN_N_BITS_MASK 0x3ff
+
+#define NX_LEARN_SRC_FIELD (0 << 13) /* Copy from field. */
+#define NX_LEARN_SRC_IMMEDIATE (1 << 13) /* Copy from immediate value. */
+#define NX_LEARN_SRC_MASK (1 << 13)
+
+#define NX_LEARN_DST_MATCH (0 << 11) /* Add match criterion. */
+#define NX_LEARN_DST_LOAD (1 << 11) /* Add NXAST_REG_LOAD action. */
+#define NX_LEARN_DST_OUTPUT (2 << 11) /* Add OFPAT_OUTPUT action. */
+#define NX_LEARN_DST_RESERVED (3 << 11) /* Not yet defined. */
+#define NX_LEARN_DST_MASK (3 << 11)
+
/* Action structure for NXAST_AUTOPATH.
*
* This action performs the following steps in sequence: