Simplify some of the ofp-actions interface.
Signed-off-by: Jarno Rajahalme <[email protected]>
---
lib/ofp-actions.c | 137 +++++++++++++++++++++++--------------------------
lib/ofp-actions.h | 17 +++---
lib/ofp-util.c | 77 +++++++++++++++++----------
lib/ofp-util.h | 1 +
utilities/ovs-ofctl.c | 11 ++--
5 files changed, 128 insertions(+), 115 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 0963874..d5e3acd 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -481,7 +481,8 @@ ofpact_from_nxast(const union ofp_action *a, enum
ofputil_action_code code,
}
static enum ofperr
-ofpact_from_openflow10(const union ofp_action *a, struct ofpbuf *out)
+ofpact_from_openflow10(const union ofp_action *a, struct ofpbuf *out,
+ enum ofp_version ofp_version OVS_UNUSED)
{
enum ofputil_action_code code;
enum ofperr error;
@@ -565,6 +566,10 @@ ofpact_from_openflow10(const union ofp_action *a, struct
ofpbuf *out)
return error;
}
+static enum ofperr ofpact_from_openflow11(const union ofp_action *,
+ struct ofpbuf *out,
+ enum ofp_version);
+
static inline union ofp_action *
action_next(const union ofp_action *a)
{
@@ -605,15 +610,18 @@ log_bad_action(const union ofp_action *actions, size_t
n_actions, size_t ofs,
static enum ofperr
ofpacts_from_openflow(const union ofp_action *in, size_t n_in,
- struct ofpbuf *out,
- enum ofperr (*ofpact_from_openflow)(
- const union ofp_action *a, struct ofpbuf *out))
+ struct ofpbuf *out, enum ofp_version ofp_version)
{
const union ofp_action *a;
size_t left;
+ enum ofperr (*ofpact_from_openflow)
+ (const union ofp_action *a, struct ofpbuf *out,
+ enum ofp_version) = (ofp_version == OFP10_VERSION) ?
+ ofpact_from_openflow10 : ofpact_from_openflow11;
+
ACTION_FOR_EACH (a, left, in, n_in) {
- enum ofperr error = ofpact_from_openflow(a, out);
+ enum ofperr error = ofpact_from_openflow(a, out, ofp_version);
if (error) {
log_bad_action(in, n_in, a - in, error);
return error;
@@ -629,19 +637,25 @@ ofpacts_from_openflow(const union ofp_action *in, size_t
n_in,
return 0;
}
-static enum ofperr
-ofpacts_from_openflow10(const union ofp_action *in, size_t n_in,
- struct ofpbuf *out)
-{
- return ofpacts_from_openflow(in, n_in, out, ofpact_from_openflow10);
-}
-
-static enum ofperr
-ofpacts_pull_actions(struct ofpbuf *openflow, unsigned int actions_len,
- struct ofpbuf *ofpacts,
- enum ofperr (*translate)(const union ofp_action *actions,
- size_t n_actions,
- struct ofpbuf *ofpacts))
+/* Attempts to convert 'actions_len' bytes of OpenFlow actions from the
+ * front of 'openflow' into ofpacts. On success, replaces any existing content
+ * in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
+ * Returns 0 if successful, otherwise an OpenFlow error.
+ *
+ * In most places in OpenFlow 1.1 and 1.2, actions appear encapsulated in
+ * instructions, so you should call ofpacts_pull_openflow_instructions()
+ * instead of this function.
+ *
+ * The parsed actions are valid generically, but they may not be valid in a
+ * specific context. For example, port numbers up to OFPP_MAX are valid
+ * generically, but specific datapaths may only support port numbers in a
+ * smaller range. Use ofpacts_check() to additional check whether actions are
+ * valid in a specific context. */
+enum ofperr
+ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
+ unsigned int actions_len,
+ struct ofpbuf *ofpacts,
+ enum ofp_version ofp_version)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
const union ofp_action *actions;
@@ -663,7 +677,8 @@ ofpacts_pull_actions(struct ofpbuf *openflow, unsigned int
actions_len,
return OFPERR_OFPBRC_BAD_LEN;
}
- error = translate(actions, actions_len / OFP_ACTION_ALIGN, ofpacts);
+ error = ofpacts_from_openflow(actions, actions_len / OFP_ACTION_ALIGN,
+ ofpacts, ofp_version);
if (error) {
ofpbuf_clear(ofpacts);
return error;
@@ -676,23 +691,6 @@ ofpacts_pull_actions(struct ofpbuf *openflow, unsigned int
actions_len,
return error;
}
-/* Attempts to convert 'actions_len' bytes of OpenFlow 1.0 actions from the
- * front of 'openflow' into ofpacts. On success, replaces any existing content
- * in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
- * Returns 0 if successful, otherwise an OpenFlow error.
- *
- * The parsed actions are valid generically, but they may not be valid in a
- * specific context. For example, port numbers up to OFPP_MAX are valid
- * generically, but specific datapaths may only support port numbers in a
- * smaller range. Use ofpacts_check() to additional check whether actions are
- * valid in a specific context. */
-enum ofperr
-ofpacts_pull_openflow10(struct ofpbuf *openflow, unsigned int actions_len,
- struct ofpbuf *ofpacts)
-{
- return ofpacts_pull_actions(openflow, actions_len, ofpacts,
- ofpacts_from_openflow10);
-}
/* OpenFlow 1.1 actions. */
@@ -796,7 +794,8 @@ output_from_openflow11(const struct ofp11_action_output
*oao,
}
static enum ofperr
-ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
+ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out,
+ enum ofp_version ofp_version)
{
enum ofputil_action_code code;
enum ofperr error;
@@ -806,6 +805,23 @@ ofpact_from_openflow11(const union ofp_action *a, struct
ofpbuf *out)
return error;
}
+ if (ofp_version >= OFP12_VERSION) {
+ switch ((int)code) {
+ case OFPUTIL_OFPAT11_SET_VLAN_VID:
+ case OFPUTIL_OFPAT11_SET_VLAN_PCP:
+ case OFPUTIL_OFPAT11_SET_DL_SRC:
+ case OFPUTIL_OFPAT11_SET_DL_DST:
+ case OFPUTIL_OFPAT11_SET_NW_SRC:
+ case OFPUTIL_OFPAT11_SET_NW_DST:
+ case OFPUTIL_OFPAT11_SET_NW_TOS:
+ case OFPUTIL_OFPAT11_SET_TP_SRC:
+ case OFPUTIL_OFPAT11_SET_TP_DST:
+ VLOG_WARN_RL(&rl, "Deprecated action %s received over %s",
+ ofputil_action_name_from_code(code),
+ ofputil_version_to_string(ofp_version));
+ }
+ }
+
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
@@ -942,13 +958,6 @@ ofpact_from_openflow11(const union ofp_action *a, struct
ofpbuf *out)
return error;
}
-static enum ofperr
-ofpacts_from_openflow11(const union ofp_action *in, size_t n_in,
- struct ofpbuf *out)
-{
- return ofpacts_from_openflow(in, n_in, out, ofpact_from_openflow11);
-}
-
/* True if an action sets the value of a field
* in a way that is compatibile with the action set.
* False otherwise. */
@@ -1160,13 +1169,14 @@ ofpacts_execute_action_set(struct ofpbuf *action_list,
static enum ofperr
ofpacts_from_openflow11_for_action_set(const union ofp_action *in,
- size_t n_in, struct ofpbuf *out)
+ size_t n_in, struct ofpbuf *out,
+ enum ofp_version ofp_version)
{
enum ofperr error;
struct ofpact *a;
size_t start = out->size;
- error = ofpacts_from_openflow(in, n_in, out, ofpact_from_openflow11);
+ error = ofpacts_from_openflow(in, n_in, out, ofp_version);
if (error) {
return error;
}
@@ -1391,33 +1401,11 @@ get_actions_from_instruction(const struct
ofp11_instruction *inst,
*n_actions = (ntohs(inst->len) - sizeof *inst) / OFP11_INSTRUCTION_ALIGN;
}
-/* Attempts to convert 'actions_len' bytes of OpenFlow 1.1 actions from the
- * front of 'openflow' into ofpacts. On success, replaces any existing content
- * in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
- * Returns 0 if successful, otherwise an OpenFlow error.
- *
- * In most places in OpenFlow 1.1 and 1.2, actions appear encapsulated in
- * instructions, so you should call ofpacts_pull_openflow11_instructions()
- * instead of this function.
- *
- * The parsed actions are valid generically, but they may not be valid in a
- * specific context. For example, port numbers up to OFPP_MAX are valid
- * generically, but specific datapaths may only support port numbers in a
- * smaller range. Use ofpacts_check() to additional check whether actions are
- * valid in a specific context. */
-enum ofperr
-ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
- unsigned int actions_len,
- struct ofpbuf *ofpacts)
-{
- return ofpacts_pull_actions(openflow, actions_len, ofpacts,
- ofpacts_from_openflow11);
-}
-
enum ofperr
-ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
- unsigned int instructions_len,
- struct ofpbuf *ofpacts)
+ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
+ unsigned int instructions_len,
+ struct ofpbuf *ofpacts,
+ enum ofp_version ofp_version)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
const struct ofp11_instruction *instructions;
@@ -1466,7 +1454,8 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf
*openflow,
get_actions_from_instruction(insts[OVSINST_OFPIT11_APPLY_ACTIONS],
&actions, &n_actions);
- error = ofpacts_from_openflow11(actions, n_actions, ofpacts);
+ error = ofpacts_from_openflow(actions, n_actions, ofpacts,
+ ofp_version);
if (error) {
goto exit;
}
@@ -1487,7 +1476,7 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf
*openflow,
get_actions_from_instruction(insts[OVSINST_OFPIT11_WRITE_ACTIONS],
&actions, &n_actions);
error = ofpacts_from_openflow11_for_action_set(actions, n_actions,
- ofpacts);
+ ofpacts, ofp_version);
if (error) {
goto exit;
}
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 4e13472..b6868db 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -593,15 +593,14 @@ struct ofpact_group {
};
/* Converting OpenFlow to ofpacts. */
-enum ofperr ofpacts_pull_openflow10(struct ofpbuf *openflow,
- unsigned int actions_len,
- struct ofpbuf *ofpacts);
-enum ofperr ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
- unsigned int actions_len,
- struct ofpbuf *ofpacts);
-enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
- unsigned int instructions_len,
- struct ofpbuf *ofpacts);
+enum ofperr ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
+ unsigned int actions_len,
+ struct ofpbuf *ofpacts,
+ enum ofp_version ofp_version);
+enum ofperr ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
+ unsigned int instructions_len,
+ struct ofpbuf *ofpacts,
+ enum ofp_version ofp_version);
enum ofperr ofpacts_check(struct ofpact[], size_t ofpacts_len,
struct flow *, ofp_port_t max_ports,
uint8_t table_id);
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index ee701e9..879b384 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1504,7 +1504,8 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
return error;
}
- error = ofpacts_pull_openflow11_instructions(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow_instructions(&b, b.size, ofpacts,
+ oh->version);
if (error) {
return error;
}
@@ -1560,7 +1561,8 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
ofputil_normalize_match(&fm->match);
/* Now get the actions. */
- error = ofpacts_pull_openflow10(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow_actions(&b, b.size, ofpacts,
+ oh->version);
if (error) {
return error;
}
@@ -1593,7 +1595,8 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
if (error) {
return error;
}
- error = ofpacts_pull_openflow10(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow_actions(&b, b.size, ofpacts,
+ oh->version);
if (error) {
return error;
}
@@ -2363,8 +2366,9 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats
*fs,
return EINVAL;
}
- if (ofpacts_pull_openflow11_instructions(msg, length - sizeof *ofs -
- padded_match_len, ofpacts)) {
+ if (ofpacts_pull_openflow_instructions(msg, length - sizeof *ofs -
+ padded_match_len, ofpacts,
+ oh->version)) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
return EINVAL;
}
@@ -2407,7 +2411,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats
*fs,
return EINVAL;
}
- if (ofpacts_pull_openflow10(msg, length - sizeof *ofs, ofpacts)) {
+ if (ofpacts_pull_openflow_actions(msg, length - sizeof *ofs, ofpacts,
+ oh->version)) {
return EINVAL;
}
@@ -2447,7 +2452,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats
*fs,
}
actions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);
- if (ofpacts_pull_openflow10(msg, actions_len, ofpacts)) {
+ if (ofpacts_pull_openflow_actions(msg, actions_len, ofpacts,
+ oh->version)) {
return EINVAL;
}
@@ -3095,8 +3101,8 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
return error;
}
- error = ofpacts_pull_openflow11_actions(&b, ntohs(opo->actions_len),
- ofpacts);
+ error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
+ ofpacts, oh->version);
if (error) {
return error;
}
@@ -3107,7 +3113,8 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
po->buffer_id = ntohl(opo->buffer_id);
po->in_port = u16_to_ofp(ntohs(opo->in_port));
- error = ofpacts_pull_openflow10(&b, ntohs(opo->actions_len), ofpacts);
+ error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
+ ofpacts, oh->version);
if (error) {
return error;
}
@@ -4179,6 +4186,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update
*update,
{
struct nx_flow_update_header *nfuh;
unsigned int length;
+ struct ofp_header *oh;
if (!msg->l2) {
msg->l2 = msg->data;
@@ -4193,6 +4201,8 @@ ofputil_decode_flow_update(struct ofputil_flow_update
*update,
goto bad_len;
}
+ oh = msg->l2;
+
nfuh = msg->data;
update->event = ntohs(nfuh->event);
length = ntohs(nfuh->length);
@@ -4241,7 +4251,8 @@ ofputil_decode_flow_update(struct ofputil_flow_update
*update,
}
actions_len = length - sizeof *nfuf - ROUND_UP(match_len, 8);
- error = ofpacts_pull_openflow10(msg, actions_len, ofpacts);
+ error = ofpacts_pull_openflow_actions(msg, actions_len, ofpacts,
+ oh->version);
if (error) {
return error;
}
@@ -4745,22 +4756,21 @@ size_t ofputil_count_phy_ports(uint8_t ofp_version,
struct ofpbuf *b)
return b->size / ofputil_get_phy_port_size(ofp_version);
}
-/* Returns the 'enum ofputil_action_code' corresponding to 'name' (e.g. if
- * 'name' is "output" then the return value is OFPUTIL_OFPAT10_OUTPUT), or -1
if
- * 'name' is not the name of any action.
- *
- * ofp-util.def lists the mapping from names to action. */
-int
-ofputil_action_code_from_name(const char *name)
-{
- static const char *const names[OFPUTIL_N_ACTIONS] = {
- NULL,
+/* ofp-util.def lists the mapping from names to action. */
+static const char *const names[OFPUTIL_N_ACTIONS] = {
+ NULL,
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME,
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
#include "ofp-util.def"
- };
+};
+/* Returns the 'enum ofputil_action_code' corresponding to 'name' (e.g. if
+ * 'name' is "output" then the return value is OFPUTIL_OFPAT10_OUTPUT), or -1
+ * if 'name' is not the name of any action. */
+int
+ofputil_action_code_from_name(const char *name)
+{
const char *const *p;
for (p = names; p < &names[ARRAY_SIZE(names)]; p++) {
@@ -4771,6 +4781,15 @@ ofputil_action_code_from_name(const char *name)
return -1;
}
+/* Returns name corresponding to the 'enum ofputil_action_code',
+ * or "Unkonwn action", if the name is not available. */
+const char *
+ofputil_action_name_from_code(enum ofputil_action_code code)
+{
+ return code < OFPUTIL_N_ACTIONS && names[code] ? names[code]
+ : "Unknown action";
+}
+
/* Appends an action of the type specified by 'code' to 'buf' and returns the
* action. Initializes the parts of 'action' that identify it as having type
* <ENUM> and length 'sizeof *action' and zeros the rest. For actions that
@@ -5681,7 +5700,7 @@ ofputil_append_group_desc_reply(const struct
ofputil_group_desc *gds,
static enum ofperr
ofputil_pull_buckets(struct ofpbuf *msg, size_t buckets_length,
- struct list *buckets)
+ struct list *buckets, enum ofp_version ofp_version)
{
struct ofp11_bucket *ob;
@@ -5714,8 +5733,8 @@ ofputil_pull_buckets(struct ofpbuf *msg, size_t
buckets_length,
buckets_length -= ob_len;
ofpbuf_init(&ofpacts, 0);
- error = ofpacts_pull_openflow11_actions(msg, ob_len - sizeof *ob,
- &ofpacts);
+ error = ofpacts_pull_openflow_actions(msg, ob_len - sizeof *ob,
+ &ofpacts, ofp_version);
if (error) {
ofpbuf_uninit(&ofpacts);
ofputil_bucket_list_destroy(buckets);
@@ -5755,6 +5774,7 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc
*gd,
{
struct ofp11_group_desc_stats *ogds;
size_t length;
+ struct ofp_header *oh;
if (!msg->l2) {
ofpraw_pull_assert(msg);
@@ -5763,6 +5783,7 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc
*gd,
if (!msg->size) {
return EOF;
}
+ oh = msg->l2;
ogds = ofpbuf_try_pull(msg, sizeof *ogds);
if (!ogds) {
@@ -5780,7 +5801,8 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc
*gd,
return OFPERR_OFPBRC_BAD_LEN;
}
- return ofputil_pull_buckets(msg, length - sizeof *ogds, &gd->buckets);
+ return ofputil_pull_buckets(msg, length - sizeof *ogds, &gd->buckets,
+ oh->version);
}
/* Converts abstract group mod 'gm' into a message for OpenFlow version
@@ -5864,7 +5886,8 @@ ofputil_decode_group_mod(const struct ofp_header *oh,
gm->type = ogm->type;
gm->group_id = ntohl(ogm->group_id);
- return ofputil_pull_buckets(&msg, msg.size, &gm->buckets);
+ return ofputil_pull_buckets(&msg, msg.size, &gm->buckets,
+ oh->version);
}
/* Parse a queue status request message into 'oqsr'.
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 17d14c0..83cd031 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -809,6 +809,7 @@ enum {
};
int ofputil_action_code_from_name(const char *);
+const char * ofputil_action_name_from_code(enum ofputil_action_code code);
void *ofputil_put_action(enum ofputil_action_code, struct ofpbuf *buf);
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 5ec8f11..586fc04 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -2784,7 +2784,8 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char
*argv[] OVS_UNUSED)
/* Convert to ofpacts. */
ofpbuf_init(&ofpacts, 0);
size = of10_in.size;
- error = ofpacts_pull_openflow10(&of10_in, of10_in.size, &ofpacts);
+ error = ofpacts_pull_openflow_actions(&of10_in, of10_in.size, &ofpacts,
+ OFP10_VERSION);
if (error) {
printf("bad OF1.1 actions: %s\n\n", ofperr_get_name(error));
ofpbuf_uninit(&ofpacts);
@@ -2971,8 +2972,8 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char
*argv[] OVS_UNUSED)
/* Convert to ofpacts. */
ofpbuf_init(&ofpacts, 0);
size = of11_in.size;
- error = ofpacts_pull_openflow11_actions(&of11_in, of11_in.size,
- &ofpacts);
+ error = ofpacts_pull_openflow_actions(&of11_in, of11_in.size,
+ &ofpacts, OFP11_VERSION);
if (error) {
printf("bad OF1.1 actions: %s\n\n", ofperr_get_name(error));
ofpbuf_uninit(&ofpacts);
@@ -3041,8 +3042,8 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char
*argv[] OVS_UNUSED)
/* Convert to ofpacts. */
ofpbuf_init(&ofpacts, 0);
size = of11_in.size;
- error = ofpacts_pull_openflow11_instructions(&of11_in, of11_in.size,
- &ofpacts);
+ error = ofpacts_pull_openflow_instructions(&of11_in, of11_in.size,
+ &ofpacts, OFP11_VERSION);
if (!error) {
/* Verify actions. */
struct flow flow;
--
1.7.10.4
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev