diff options
| author | Ingo Molnar <mingo@kernel.org> | 2015-09-13 12:25:35 +0300 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-09-13 12:25:35 +0300 | 
| commit | d2bb1d42b95fa88f092623bbb8ed533f316b6a3c (patch) | |
| tree | fb796db809a266906fa358f24f1c07ced4df33f0 /net/openvswitch/datapath.c | |
| parent | 3bd7617596df560e2cb22ad97888cb42dae39d02 (diff) | |
| parent | 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff) | |
| download | linux-d2bb1d42b95fa88f092623bbb8ed533f316b6a3c.tar.xz | |
Merge tag 'v4.3-rc1' into perf/core, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/openvswitch/datapath.c')
| -rw-r--r-- | net/openvswitch/datapath.c | 109 | 
1 files changed, 72 insertions, 37 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index ff8c4a4c1609..6fbd2decb19e 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -176,7 +176,7 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex)  const char *ovs_dp_name(const struct datapath *dp)  {  	struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL); -	return vport->ops->get_name(vport); +	return ovs_vport_name(vport);  }  static int get_dpifindex(const struct datapath *dp) @@ -188,7 +188,7 @@ static int get_dpifindex(const struct datapath *dp)  	local = ovs_vport_rcu(dp, OVSP_LOCAL);  	if (local) -		ifindex = netdev_vport_priv(local)->dev->ifindex; +		ifindex = local->dev->ifindex;  	else  		ifindex = 0; @@ -275,6 +275,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)  		memset(&upcall, 0, sizeof(upcall));  		upcall.cmd = OVS_PACKET_CMD_MISS;  		upcall.portid = ovs_vport_find_upcall_portid(p, skb); +		upcall.mru = OVS_CB(skb)->mru;  		error = ovs_dp_upcall(dp, skb, key, &upcall);  		if (unlikely(error))  			kfree_skb(skb); @@ -400,9 +401,23 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,  	if (upcall_info->actions_len)  		size += nla_total_size(upcall_info->actions_len); +	/* OVS_PACKET_ATTR_MRU */ +	if (upcall_info->mru) +		size += nla_total_size(sizeof(upcall_info->mru)); +  	return size;  } +static void pad_packet(struct datapath *dp, struct sk_buff *skb) +{ +	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { +		size_t plen = NLA_ALIGN(skb->len) - skb->len; + +		if (plen > 0) +			memset(skb_put(skb, plen), 0, plen); +	} +} +  static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,  				  const struct sw_flow_key *key,  				  const struct dp_upcall_info *upcall_info) @@ -476,7 +491,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,  	if (upcall_info->egress_tun_info) {  		nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);  		err = ovs_nla_put_egress_tunnel_key(user_skb, -						    upcall_info->egress_tun_info); +						    upcall_info->egress_tun_info, +						    upcall_info->egress_tun_opts);  		BUG_ON(err);  		nla_nest_end(user_skb, nla);  	} @@ -492,6 +508,16 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,  			nla_nest_cancel(user_skb, nla);  	} +	/* Add OVS_PACKET_ATTR_MRU */ +	if (upcall_info->mru) { +		if (nla_put_u16(user_skb, OVS_PACKET_ATTR_MRU, +				upcall_info->mru)) { +			err = -ENOBUFS; +			goto out; +		} +		pad_packet(dp, user_skb); +	} +  	/* Only reserve room for attribute header, packet data is added  	 * in skb_zerocopy() */  	if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) { @@ -505,12 +531,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,  		goto out;  	/* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ -	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { -		size_t plen = NLA_ALIGN(user_skb->len) - user_skb->len; - -		if (plen > 0) -			memset(skb_put(user_skb, plen), 0, plen); -	} +	pad_packet(dp, user_skb);  	((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; @@ -527,6 +548,7 @@ out:  static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)  {  	struct ovs_header *ovs_header = info->userhdr; +	struct net *net = sock_net(skb->sk);  	struct nlattr **a = info->attrs;  	struct sw_flow_actions *acts;  	struct sk_buff *packet; @@ -535,6 +557,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)  	struct datapath *dp;  	struct ethhdr *eth;  	struct vport *input_vport; +	u16 mru = 0;  	int len;  	int err;  	bool log = !a[OVS_PACKET_ATTR_PROBE]; @@ -564,29 +587,35 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)  	else  		packet->protocol = htons(ETH_P_802_2); +	/* Set packet's mru */ +	if (a[OVS_PACKET_ATTR_MRU]) { +		mru = nla_get_u16(a[OVS_PACKET_ATTR_MRU]); +		packet->ignore_df = 1; +	} +	OVS_CB(packet)->mru = mru; +  	/* Build an sw_flow for sending this packet. */  	flow = ovs_flow_alloc();  	err = PTR_ERR(flow);  	if (IS_ERR(flow))  		goto err_kfree_skb; -	err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet, -					     &flow->key, log); +	err = ovs_flow_key_extract_userspace(net, a[OVS_PACKET_ATTR_KEY], +					     packet, &flow->key, log);  	if (err)  		goto err_flow_free; -	err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], +	err = ovs_nla_copy_actions(net, a[OVS_PACKET_ATTR_ACTIONS],  				   &flow->key, &acts, log);  	if (err)  		goto err_flow_free;  	rcu_assign_pointer(flow->sf_acts, acts); -	OVS_CB(packet)->egress_tun_info = NULL;  	packet->priority = flow->key.phy.priority;  	packet->mark = flow->key.phy.skb_mark;  	rcu_read_lock(); -	dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex); +	dp = get_dp_rcu(net, ovs_header->dp_ifindex);  	err = -ENODEV;  	if (!dp)  		goto err_unlock; @@ -598,6 +627,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)  	if (!input_vport)  		goto err_unlock; +	packet->dev = input_vport->dev;  	OVS_CB(packet)->input_vport = input_vport;  	sf_acts = rcu_dereference(flow->sf_acts); @@ -624,6 +654,7 @@ static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {  	[OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED },  	[OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },  	[OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG }, +	[OVS_PACKET_ATTR_MRU] = { .type = NLA_U16 },  };  static const struct genl_ops dp_packet_genl_ops[] = { @@ -713,7 +744,7 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts,  	/* OVS_FLOW_ATTR_ACTIONS */  	if (should_fill_actions(ufid_flags)) -		len += nla_total_size(acts->actions_len); +		len += nla_total_size(acts->orig_len);  	return len  		+ nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */ @@ -880,6 +911,7 @@ static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,  static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)  { +	struct net *net = sock_net(skb->sk);  	struct nlattr **a = info->attrs;  	struct ovs_header *ovs_header = info->userhdr;  	struct sw_flow *flow = NULL, *new_flow; @@ -915,7 +947,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)  	/* Extract key. */  	ovs_match_init(&match, &key, &mask); -	error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], +	error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],  				  a[OVS_FLOW_ATTR_MASK], log);  	if (error)  		goto err_kfree_flow; @@ -929,8 +961,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)  		goto err_kfree_flow;  	/* Validate actions. */ -	error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key, -				     &acts, log); +	error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS], +				     &new_flow->key, &acts, log);  	if (error) {  		OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");  		goto err_kfree_flow; @@ -944,7 +976,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)  	}  	ovs_lock(); -	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); +	dp = get_dp(net, ovs_header->dp_ifindex);  	if (unlikely(!dp)) {  		error = -ENODEV;  		goto err_unlock_ovs; @@ -1018,7 +1050,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)  		}  		ovs_unlock(); -		ovs_nla_free_flow_actions(old_acts); +		ovs_nla_free_flow_actions_rcu(old_acts);  		ovs_flow_free(new_flow, false);  	} @@ -1030,7 +1062,7 @@ err_unlock_ovs:  	ovs_unlock();  	kfree_skb(reply);  err_kfree_acts: -	kfree(acts); +	ovs_nla_free_flow_actions(acts);  err_kfree_flow:  	ovs_flow_free(new_flow, false);  error: @@ -1038,7 +1070,8 @@ error:  }  /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */ -static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, +static struct sw_flow_actions *get_flow_actions(struct net *net, +						const struct nlattr *a,  						const struct sw_flow_key *key,  						const struct sw_flow_mask *mask,  						bool log) @@ -1048,7 +1081,7 @@ static struct sw_flow_actions *get_flow_actions(const struct nlattr *a,  	int error;  	ovs_flow_mask_key(&masked_key, key, mask); -	error = ovs_nla_copy_actions(a, &masked_key, &acts, log); +	error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log);  	if (error) {  		OVS_NLERR(log,  			  "Actions may not be safe on all matching packets"); @@ -1060,6 +1093,7 @@ static struct sw_flow_actions *get_flow_actions(const struct nlattr *a,  static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)  { +	struct net *net = sock_net(skb->sk);  	struct nlattr **a = info->attrs;  	struct ovs_header *ovs_header = info->userhdr;  	struct sw_flow_key key; @@ -1084,15 +1118,15 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)  	ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);  	ovs_match_init(&match, &key, &mask); -	error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], +	error = ovs_nla_get_match(net, &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, -					log); +		acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key, +					&mask, log);  		if (IS_ERR(acts)) {  			error = PTR_ERR(acts);  			goto error; @@ -1108,7 +1142,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)  	}  	ovs_lock(); -	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); +	dp = get_dp(net, ovs_header->dp_ifindex);  	if (unlikely(!dp)) {  		error = -ENODEV;  		goto err_unlock_ovs; @@ -1157,7 +1191,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)  	if (reply)  		ovs_notify(&dp_flow_genl_family, reply, info);  	if (old_acts) -		ovs_nla_free_flow_actions(old_acts); +		ovs_nla_free_flow_actions_rcu(old_acts);  	return 0; @@ -1165,7 +1199,7 @@ err_unlock_ovs:  	ovs_unlock();  	kfree_skb(reply);  err_kfree_acts: -	kfree(acts); +	ovs_nla_free_flow_actions(acts);  error:  	return error;  } @@ -1174,6 +1208,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)  {  	struct nlattr **a = info->attrs;  	struct ovs_header *ovs_header = info->userhdr; +	struct net *net = sock_net(skb->sk);  	struct sw_flow_key key;  	struct sk_buff *reply;  	struct sw_flow *flow; @@ -1188,7 +1223,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)  	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);  	if (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(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,  					log);  	} else if (!ufid_present) {  		OVS_NLERR(log, @@ -1232,6 +1267,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)  {  	struct nlattr **a = info->attrs;  	struct ovs_header *ovs_header = info->userhdr; +	struct net *net = sock_net(skb->sk);  	struct sw_flow_key key;  	struct sk_buff *reply;  	struct sw_flow *flow = NULL; @@ -1246,8 +1282,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)  	ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);  	if (a[OVS_FLOW_ATTR_KEY]) {  		ovs_match_init(&match, &key, NULL); -		err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, -					log); +		err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], +					NULL, log);  		if (unlikely(err))  			return err;  	} @@ -1800,7 +1836,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,  	if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||  	    nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||  	    nla_put_string(skb, OVS_VPORT_ATTR_NAME, -			   vport->ops->get_name(vport))) +			   ovs_vport_name(vport)))  		goto nla_put_failure;  	ovs_vport_get_stats(vport, &vport_stats); @@ -2203,6 +2239,7 @@ static int __net_init ovs_init_net(struct net *net)  	INIT_LIST_HEAD(&ovs_net->dps);  	INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq); +	ovs_ct_init(net);  	return 0;  } @@ -2219,13 +2256,10 @@ static void __net_exit list_vports_from_net(struct net *net, struct net *dnet,  			struct vport *vport;  			hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) { -				struct netdev_vport *netdev_vport; -  				if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL)  					continue; -				netdev_vport = netdev_vport_priv(vport); -				if (dev_net(netdev_vport->dev) == dnet) +				if (dev_net(vport->dev) == dnet)  					list_add(&vport->detach_list, head);  			}  		} @@ -2240,6 +2274,7 @@ static void __net_exit ovs_exit_net(struct net *dnet)  	struct net *net;  	LIST_HEAD(head); +	ovs_ct_exit(dnet);  	ovs_lock();  	list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)  		__dp_destroy(dp);  | 
