[ovs-dev] [PATCH net-next] openvswitch: Only set mark and labels when commiting a connection.

Jarno Rajahalme jarno at ovn.org
Tue Jun 21 00:24:05 UTC 2016


The title should have been:

openvswitch: Only set mark and labels with a commit flag.

This reflects the fact that modifying the mark and/or labels of an existing connection is allowed. The commit flag is still required to do that, though.

  Jarno

> On Jun 20, 2016, at 5:19 PM, Jarno Rajahalme <jarno at ovn.org> wrote:
> 
> Only allow setting conntrack mark or labels when the commit flag is
> specified.  This makes sure we can not set them before the connection
> has been persisted, as in that case the mark and labels would be lost
> in an event of an userspace upcall.
> 
> OVS userspace already requires the commit flag to accept setting
> ct_mark and/or ct_labels.  Validate for this on the kernel API.
> 
> Finally, set conntrack mark and labels right before committing so that
> the initial conntrack NEW event has the mark and labels.
> 
> Signed-off-by: Jarno Rajahalme <jarno at ovn.org>
> ---
> net/openvswitch/conntrack.c | 72 ++++++++++++++++++++++++++++++---------------
> 1 file changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> index 3d5feed..f1612f5 100644
> --- a/net/openvswitch/conntrack.c
> +++ b/net/openvswitch/conntrack.c
> @@ -824,6 +824,17 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
> 	return 0;
> }
> 
> +static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < sizeof(*labels); i++)
> +		if (labels->ct_labels[i])
> +			return true;
> +
> +	return false;
> +}
> +
> /* Lookup connection and confirm if unconfirmed. */
> static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
> 			 const struct ovs_conntrack_info *info,
> @@ -834,24 +845,35 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
> 	err = __ovs_ct_lookup(net, key, info, skb);
> 	if (err)
> 		return err;
> -	/* This is a no-op if the connection has already been confirmed. */
> +
> +	/* As any changes to an unconfirmed connection may be lost due
> +	 * to an upcall, we require the presence of the 'commit' flag
> +	 * for setting mask and/or labels.  Perform the changes before
> +	 * confirming the connection so that the initial mark and label
> +	 * values are present in the initial CT NEW netlink event.
> +	 */
> +	if (info->mark.mask) {
> +		err = ovs_ct_set_mark(skb, key, info->mark.value,
> +				      info->mark.mask);
> +		if (err)
> +			return err;
> +	}
> +	if (labels_nonzero(&info->labels.mask)) {
> +		err = ovs_ct_set_labels(skb, key, &info->labels.value,
> +					&info->labels.mask);
> +		if (err)
> +			return err;
> +	}
> +
> +	/* Will take care of sending queued events even if the connection is
> +	 * already confirmed.
> +	 */
> 	if (nf_conntrack_confirm(skb) != NF_ACCEPT)
> 		return -EINVAL;
> 
> 	return 0;
> }
> 
> -static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
> -{
> -	size_t i;
> -
> -	for (i = 0; i < sizeof(*labels); i++)
> -		if (labels->ct_labels[i])
> -			return true;
> -
> -	return false;
> -}
> -
> /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
>  * value if 'skb' is freed.
>  */
> @@ -876,19 +898,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
> 		err = ovs_ct_commit(net, key, info, skb);
> 	else
> 		err = ovs_ct_lookup(net, key, info, skb);
> -	if (err)
> -		goto err;
> 
> -	if (info->mark.mask) {
> -		err = ovs_ct_set_mark(skb, key, info->mark.value,
> -				      info->mark.mask);
> -		if (err)
> -			goto err;
> -	}
> -	if (labels_nonzero(&info->labels.mask))
> -		err = ovs_ct_set_labels(skb, key, &info->labels.value,
> -					&info->labels.mask);
> -err:
> 	skb_push(skb, nh_ofs);
> 	if (err)
> 		kfree_skb(skb);
> @@ -1145,6 +1155,20 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
> 		}
> 	}
> 
> +#ifdef CONFIG_NF_CONNTRACK_MARK
> +	if (!info->commit && info->mark.mask) {
> +		OVS_NLERR(log,
> +			  "Setting conntrack mark requires 'commit' flag.");
> +		return -EINVAL;
> +	}
> +#endif
> +#ifdef CONFIG_NF_CONNTRACK_LABELS
> +	if (!info->commit && labels_nonzero(&info->labels.mask)) {
> +		OVS_NLERR(log,
> +			  "Setting conntrack labels requires 'commit' flag.");
> +		return -EINVAL;
> +	}
> +#endif
> 	if (rem > 0) {
> 		OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
> 		return -EINVAL;
> -- 
> 2.1.4
> 




More information about the dev mailing list