summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
authorAndy Zhou <azhou@ovn.org>2017-01-10 18:13:47 -0800
committerAndy Zhou <azhou@ovn.org>2017-01-23 22:58:34 -0800
commit535e3acfa70b1c1a44daf91de3a63b80d673dc33 (patch)
tree5701ea8f91c95467a28b7b8949e326462bc40c37 /ofproto
parentbf6b1d052e793ebadd48b05b6595319caa08c026 (diff)
downloadopenvswitch-535e3acfa70b1c1a44daf91de3a63b80d673dc33.tar.gz
dpif-netdev: Add clone action
Add support for userspace datapath clone action. The clone action provides an action envelope to enclose an action list. For example, with actions A, B, C and D, and an action list: A, clone(B, C), D The clone action will ensure that: - D will see the same packet, and any meta states, such as flow, as action B. - D will be executed regardless whether B, or C drops a packet. They can only drop a clone. - When B drops a packet, clone will skip all remaining actions within the clone envelope. This feature is useful when we add meter action later: The meter action can be implemented as a simple action without its own envolop (unlike the sample action). When necessary, the flow translation layer can enclose a meter action in clone. The clone action is very similar with the OpenFlow clone action. This is by design to simplify vswitchd flow translation logic. Without datapath clone, vswitchd simulate the effect by inserting datapath actions to "undo" clone actions. The above flow will be translated into A, B, C, -C, -B, D. However, there are two issues: - The resulting datapath action list may be longer without using clone. - Some actions, such as NAT may not be possible to reverse. This patch implements clone() simply with packet copy. The performance can be improved with later patches, for example, to delay or avoid packet copy if possible. It seems datapath should have enough context to carry out such optimization without the userspace context. Signed-off-by: Andy Zhou <azhou@ovn.org> Acked-by: Jarno Rajahalme <jarno@ovn.org>
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/ofproto-dpif-sflow.c1
-rw-r--r--ofproto/ofproto-dpif.c55
-rw-r--r--ofproto/ofproto-dpif.h5
3 files changed, 60 insertions, 1 deletions
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 37992b430..e4ae760c1 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -1162,6 +1162,7 @@ dpif_sflow_read_actions(const struct flow *flow,
break;
}
case OVS_ACTION_ATTR_SAMPLE:
+ case OVS_ACTION_ATTR_CLONE:
case OVS_ACTION_ATTR_UNSPEC:
case __OVS_ACTION_ATTR_MAX:
default:
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d7bde69b1..df291f363 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1097,6 +1097,58 @@ check_trunc_action(struct dpif_backer *backer)
return !error;
}
+/* Tests whether 'backer''s datapath supports the clone action
+ * OVS_ACTION_ATTR_CLONE. */
+static bool
+check_clone(struct dpif_backer *backer)
+{
+ struct dpif_execute execute;
+ struct eth_header *eth;
+ struct flow flow;
+ struct dp_packet packet;
+ struct ofpbuf actions;
+ size_t clone_start;
+ int error;
+
+ /* Compose clone with an empty action list.
+ * and check if datapath can decode the message. */
+ ofpbuf_init(&actions, 64);
+ clone_start = nl_msg_start_nested(&actions, OVS_ACTION_ATTR_CLONE);
+ nl_msg_end_nested(&actions, clone_start);
+
+ /* Compose a dummy Ethernet packet. */
+ dp_packet_init(&packet, ETH_HEADER_LEN);
+ eth = dp_packet_put_zeros(&packet, ETH_HEADER_LEN);
+ eth->eth_type = htons(0x1234);
+
+ flow_extract(&packet, &flow);
+
+ /* Execute the actions. On older datapaths this fails with EINVAL, on
+ * newer datapaths it succeeds. */
+ execute.actions = actions.data;
+ execute.actions_len = actions.size;
+ execute.packet = &packet;
+ execute.flow = &flow;
+ execute.needs_help = false;
+ execute.probe = true;
+ execute.mtu = 0;
+
+ error = dpif_execute(backer->dpif, &execute);
+
+ dp_packet_uninit(&packet);
+ ofpbuf_uninit(&actions);
+
+ if (error) {
+ VLOG_INFO("%s: Datapath does not support clone action",
+ dpif_name(backer->dpif));
+ } else {
+ VLOG_INFO("%s: Datapath supports clone action",
+ dpif_name(backer->dpif));
+ }
+
+ return !error;
+}
+
#define CHECK_FEATURE__(NAME, SUPPORT, FIELD, VALUE) \
static bool \
check_##NAME(struct dpif_backer *backer) \
@@ -1145,13 +1197,16 @@ check_support(struct dpif_backer *backer)
/* This feature needs to be tested after udpif threads are set. */
backer->support.variable_length_userdata = false;
+ /* Actions. */
backer->support.odp.recirc = check_recirc(backer);
backer->support.odp.max_mpls_depth = check_max_mpls_depth(backer);
backer->support.masked_set_action = check_masked_set_action(backer);
backer->support.trunc = check_trunc_action(backer);
backer->support.ufid = check_ufid(backer);
backer->support.tnl_push_pop = dpif_supports_tnl_push_pop(backer->dpif);
+ backer->support.clone = check_clone(backer);
+ /* Flow fields. */
backer->support.odp.ct_state = check_ct_state(backer);
backer->support.odp.ct_zone = check_ct_zone(backer);
backer->support.odp.ct_mark = check_ct_mark(backer);
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index c4f7baa53..533fadf66 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
+/* Copyright (c) 2009-2017 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -165,6 +165,9 @@ struct dpif_backer_support {
/* Each member represents support for related OVS_KEY_ATTR_* fields. */
struct odp_support odp;
+
+ /* True if the datapath supports OVS_ACTION_ATTR_CLONE action. */
+ bool clone;
};
/* Reasons that we might need to revalidate every datapath flow, and