Skip to content

Commit

Permalink
openvswitch: Add support for OVS_FLOW_ATTR_PROBE.
Browse files Browse the repository at this point in the history
This new flag is useful for suppressing error logging while probing
for datapath features using flow commands.  For backwards
compatibility reasons the commands are executed normally, but error
logging is suppressed.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
  • Loading branch information
Jarno Rajahalme authored and Pravin B Shelar committed Nov 10, 2014
1 parent 12eb18f commit 05da589
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 168 deletions.
2 changes: 2 additions & 0 deletions include/uapi/linux/openvswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ enum ovs_flow_attr {
OVS_FLOW_ATTR_USED, /* u64 msecs last used in monotonic time. */
OVS_FLOW_ATTR_CLEAR, /* Flag to clear stats, tcp_flags, used. */
OVS_FLOW_ATTR_MASK, /* Sequence of OVS_KEY_ATTR_* attributes. */
OVS_FLOW_ATTR_PROBE, /* Flow operation is a feature probe, error
* logging should be suppressed. */
__OVS_FLOW_ATTR_MAX
};

Expand Down
49 changes: 31 additions & 18 deletions net/openvswitch/datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
struct vport *input_vport;
int len;
int err;
bool log = !a[OVS_FLOW_ATTR_PROBE];

err = -EINVAL;
if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] ||
Expand Down Expand Up @@ -559,12 +560,12 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
goto err_kfree_skb;

err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
&flow->key);
&flow->key, log);
if (err)
goto err_flow_free;

err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS],
&flow->key, &acts);
&flow->key, &acts, log);
if (err)
goto err_flow_free;

Expand Down Expand Up @@ -855,15 +856,16 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
struct sw_flow_actions *acts;
struct sw_flow_match match;
int error;
bool log = !a[OVS_FLOW_ATTR_PROBE];

/* Must have key and actions. */
error = -EINVAL;
if (!a[OVS_FLOW_ATTR_KEY]) {
OVS_NLERR("Flow key attribute not present in new flow.\n");
OVS_NLERR(log, "Flow key attr not present in new flow.");
goto error;
}
if (!a[OVS_FLOW_ATTR_ACTIONS]) {
OVS_NLERR("Flow actions attribute not present in new flow.\n");
OVS_NLERR(log, "Flow actions attr not present in new flow.");
goto error;
}

Expand All @@ -878,18 +880,18 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)

/* Extract key. */
ovs_match_init(&match, &new_flow->unmasked_key, &mask);
error = ovs_nla_get_match(&match,
a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY],
a[OVS_FLOW_ATTR_MASK], log);
if (error)
goto err_kfree_flow;

ovs_flow_mask_key(&new_flow->key, &new_flow->unmasked_key, &mask);

/* Validate actions. */
error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key,
&acts);
&acts, log);
if (error) {
OVS_NLERR("Flow actions may not be safe on all matching packets.\n");
OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
goto err_kfree_flow;
}

Expand Down Expand Up @@ -942,6 +944,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
}
/* The unmasked key has to be the same for flow updates. */
if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) {
/* Look for any overlapping flow. */
flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
if (!flow) {
error = -ENOENT;
Expand Down Expand Up @@ -984,16 +987,18 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
/* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
static struct sw_flow_actions *get_flow_actions(const struct nlattr *a,
const struct sw_flow_key *key,
const struct sw_flow_mask *mask)
const struct sw_flow_mask *mask,
bool log)
{
struct sw_flow_actions *acts;
struct sw_flow_key masked_key;
int error;

ovs_flow_mask_key(&masked_key, key, mask);
error = ovs_nla_copy_actions(a, &masked_key, &acts);
error = ovs_nla_copy_actions(a, &masked_key, &acts, log);
if (error) {
OVS_NLERR("Actions may not be safe on all matching packets.\n");
OVS_NLERR(log,
"Actions may not be safe on all matching packets");
return ERR_PTR(error);
}

Expand All @@ -1012,23 +1017,25 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
struct sw_flow_actions *old_acts = NULL, *acts = NULL;
struct sw_flow_match match;
int error;
bool log = !a[OVS_FLOW_ATTR_PROBE];

/* Extract key. */
error = -EINVAL;
if (!a[OVS_FLOW_ATTR_KEY]) {
OVS_NLERR("Flow key attribute not present in set flow.\n");
OVS_NLERR(log, "Flow key attribute not present in set flow.");
goto error;
}

ovs_match_init(&match, &key, &mask);
error = ovs_nla_get_match(&match,
a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY],
a[OVS_FLOW_ATTR_MASK], log);
if (error)
goto error;

/* Validate actions. */
if (a[OVS_FLOW_ATTR_ACTIONS]) {
acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask);
acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask,
log);
if (IS_ERR(acts)) {
error = PTR_ERR(acts);
goto error;
Expand Down Expand Up @@ -1109,14 +1116,16 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
struct datapath *dp;
struct sw_flow_match match;
int err;
bool log = !a[OVS_FLOW_ATTR_PROBE];

if (!a[OVS_FLOW_ATTR_KEY]) {
OVS_NLERR("Flow get message rejected, Key attribute missing.\n");
OVS_NLERR(log,
"Flow get message rejected, Key attribute missing.");
return -EINVAL;
}

ovs_match_init(&match, &key, NULL);
err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, log);
if (err)
return err;

Expand Down Expand Up @@ -1157,10 +1166,12 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
struct datapath *dp;
struct sw_flow_match match;
int err;
bool log = !a[OVS_FLOW_ATTR_PROBE];

if (likely(a[OVS_FLOW_ATTR_KEY])) {
ovs_match_init(&match, &key, NULL);
err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL,
log);
if (unlikely(err))
return err;
}
Expand Down Expand Up @@ -1250,8 +1261,10 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)

static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
[OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
[OVS_FLOW_ATTR_MASK] = { .type = NLA_NESTED },
[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
[OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG },
};

static const struct genl_ops dp_flow_genl_ops[] = {
Expand Down
6 changes: 3 additions & 3 deletions net/openvswitch/datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ void ovs_dp_notify_wq(struct work_struct *work);
int action_fifos_init(void);
void action_fifos_exit(void);

#define OVS_NLERR(fmt, ...) \
#define OVS_NLERR(logging_allowed, fmt, ...) \
do { \
if (net_ratelimit()) \
pr_info("netlink: " fmt, ##__VA_ARGS__); \
if (logging_allowed && net_ratelimit()) \
pr_info("netlink: " fmt "\n", ##__VA_ARGS__); \
} while (0)
#endif /* datapath.h */
4 changes: 2 additions & 2 deletions net/openvswitch/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -712,12 +712,12 @@ int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,

int ovs_flow_key_extract_userspace(const struct nlattr *attr,
struct sk_buff *skb,
struct sw_flow_key *key)
struct sw_flow_key *key, bool log)
{
int err;

/* Extract metadata from netlink attributes. */
err = ovs_nla_get_flow_metadata(attr, key);
err = ovs_nla_get_flow_metadata(attr, key, log);
if (err)
return err;

Expand Down
2 changes: 1 addition & 1 deletion net/openvswitch/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,6 @@ int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
/* Extract key from packet coming from userspace. */
int ovs_flow_key_extract_userspace(const struct nlattr *attr,
struct sk_buff *skb,
struct sw_flow_key *key);
struct sw_flow_key *key, bool log);

#endif /* flow.h */
Loading

0 comments on commit 05da589

Please sign in to comment.