[ovs-dev] [PATCH 06/10] ofproto: Probe for masked set action support.
Jarno Rajahalme
jrajahalme at nicira.com
Tue Apr 8 23:38:48 UTC 2014
Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
ofproto/ofproto-dpif-xlate.c | 8 ++++-
ofproto/ofproto-dpif-xlate.h | 3 +-
ofproto/ofproto-dpif.c | 70 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index ca5f7fb..c1ca6d4 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -102,6 +102,10 @@ struct xbridge {
/* Number of MPLS label stack entries that the datapath supports
* in matches. */
size_t max_mpls_depth;
+
+ /* True if the datapath supports masked data in OVS_ACTION_ATTR_SET
+ * actions. */
+ bool masked_set_action;
};
struct xbundle {
@@ -264,7 +268,8 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
bool forward_bpdu, bool has_in_band,
bool enable_recirc,
bool variable_length_userdata,
- size_t max_mpls_depth)
+ size_t max_mpls_depth,
+ bool masked_set_action)
{
struct xbridge *xbridge = xbridge_lookup(ofproto);
@@ -319,6 +324,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
xbridge->enable_recirc = enable_recirc;
xbridge->variable_length_userdata = variable_length_userdata;
xbridge->max_mpls_depth = max_mpls_depth;
+ xbridge->masked_set_action = masked_set_action;
}
void
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 8b53e10..31dec11 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -140,7 +140,8 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name,
enum ofp_config_flags, bool forward_bpdu,
bool has_in_band, bool enable_recirc,
bool variable_length_userdata,
- size_t mpls_label_stack_length)
+ size_t mpls_label_stack_length,
+ bool masked_set_action)
OVS_REQ_WRLOCK(xlate_rwlock);
void xlate_remove_ofproto(struct ofproto_dpif *) OVS_REQ_WRLOCK(xlate_rwlock);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index a92fe81..f081cb6 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -262,6 +262,10 @@ struct dpif_backer {
* False if the datapath supports only 8-byte (or shorter) userdata. */
bool variable_length_userdata;
+ /* True if the datapath supports masked data in OVS_ACTION_ATTR_SET
+ * actions. */
+ bool masked_set_action;
+
/* Maximum number of MPLS label stack entries that the datapath supports
* in a match */
size_t max_mpls_depth;
@@ -593,7 +597,8 @@ type_run(const char *type)
connmgr_has_in_band(ofproto->up.connmgr),
ofproto->backer->enable_recirc,
ofproto->backer->variable_length_userdata,
- ofproto->backer->max_mpls_depth);
+ ofproto->backer->max_mpls_depth,
+ ofproto->backer->masked_set_action);
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
xlate_bundle_set(ofproto, bundle, bundle->name,
@@ -818,6 +823,7 @@ struct odp_garbage {
static bool check_variable_length_userdata(struct dpif_backer *backer);
static size_t check_max_mpls_depth(struct dpif_backer *backer);
static bool check_recirc(struct dpif_backer *backer);
+static bool check_masked_set_action(struct dpif_backer *backer);
static int
open_dpif_backer(const char *type, struct dpif_backer **backerp)
@@ -921,6 +927,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
backer->enable_recirc = check_recirc(backer);
backer->variable_length_userdata = check_variable_length_userdata(backer);
backer->max_mpls_depth = check_max_mpls_depth(backer);
+ backer->masked_set_action = check_masked_set_action(backer);
backer->rid_pool = recirc_id_pool_create();
if (backer->recv_set_enable) {
@@ -1108,6 +1115,67 @@ check_max_mpls_depth(struct dpif_backer *backer)
return n;
}
+/* Tests whether 'backer''s datapath supports masked data in
+ * OVS_ACTION_ATTR_SET actions. We need to disable some features on older
+ * datapaths that don't support this feature. */
+static bool
+check_masked_set_action(struct dpif_backer *backer)
+{
+ struct eth_header *eth;
+ struct ofpbuf actions;
+ struct dpif_execute execute;
+ struct ofpbuf packet;
+ int error;
+ struct ovs_key_ethernet key, mask;
+
+ /* Compose a set action that will cause an EINVAL error on older
+ * datapaths that don't support masked set actions.
+ * Avoid using a full mask, in case it will be translated to a non-masked
+ * set action instead. */
+ ofpbuf_init(&actions, 64);
+ memset(&key, 0x53, sizeof key);
+ memset(&mask, 0x7f, sizeof mask);
+ commit_masked_set_action(&actions, OVS_KEY_ATTR_ETHERNET, &key, &mask,
+ sizeof key);
+
+ /* Compose a dummy ethernet packet. */
+ ofpbuf_init(&packet, ETH_HEADER_LEN);
+ eth = ofpbuf_put_zeros(&packet, ETH_HEADER_LEN);
+ eth->eth_type = htons(0x1234);
+
+ /* Execute the actions. On older datapaths this fails with ERANGE, on
+ * newer datapaths it succeeds. */
+ execute.actions = ofpbuf_data(&actions);
+ execute.actions_len = ofpbuf_size(&actions);
+ execute.packet = &packet;
+ execute.md = PKT_METADATA_INITIALIZER(0);
+ execute.needs_help = false;
+
+ error = dpif_execute(backer->dpif, &execute);
+
+ ofpbuf_uninit(&packet);
+ ofpbuf_uninit(&actions);
+
+ switch (error) {
+ case 0:
+ /* Masked set action is supported. */
+ return true;
+
+ case EINVAL:
+ /* Masked set action is not supported. */
+ VLOG_INFO("%s: datapath does not support masked set action feature.",
+ dpif_name(backer->dpif));
+ return false;
+
+ default:
+ /* Something odd happened. We're not sure whether masked set action
+ * is supported. Default to "yes". */
+ VLOG_WARN("%s: masked set action feature probe failed (%s)",
+ dpif_name(backer->dpif), ovs_strerror(error));
+ return true;
+ }
+}
+
static int
construct(struct ofproto *ofproto_)
{
--
1.7.10.4
More information about the dev
mailing list