diff options
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/conntrack.c | 21 | ||||
| -rw-r--r-- | net/openvswitch/flow.c | 16 | ||||
| -rw-r--r-- | net/openvswitch/vport-netdev.c | 9 | ||||
| -rw-r--r-- | net/openvswitch/vport.h | 2 | 
4 files changed, 35 insertions, 13 deletions
| diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 1b5eae57bc90..c07afff57dd3 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -25,6 +25,8 @@  #include <net/netfilter/nf_nat.h>  #endif +#include <net/netfilter/nf_conntrack_act_ct.h> +  #include "datapath.h"  #include "conntrack.h"  #include "flow.h" @@ -574,7 +576,7 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,  			struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);  			nf_ct_delete(ct, 0, 0); -			nf_conntrack_put(&ct->ct_general); +			nf_ct_put(ct);  		}  	} @@ -723,7 +725,7 @@ static bool skb_nfct_cached(struct net *net,  		if (nf_ct_is_confirmed(ct))  			nf_ct_delete(ct, 0, 0); -		nf_conntrack_put(&ct->ct_general); +		nf_ct_put(ct);  		nf_ct_set(skb, NULL, 0);  		return false;  	} @@ -967,7 +969,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,  		/* Associate skb with specified zone. */  		if (tmpl) { -			nf_conntrack_put(skb_nfct(skb)); +			ct = nf_ct_get(skb, &ctinfo); +			nf_ct_put(ct);  			nf_conntrack_get(&tmpl->ct_general);  			nf_ct_set(skb, tmpl, IP_CT_NEW);  		} @@ -1045,6 +1048,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,  			 */  			nf_ct_set_tcp_be_liberal(ct);  		} + +		nf_conn_act_ct_ext_fill(skb, ct, ctinfo);  	}  	return 0; @@ -1245,6 +1250,8 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,  					 &info->labels.mask);  		if (err)  			return err; + +		nf_conn_act_ct_ext_add(ct);  	} else if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&  		   labels_nonzero(&info->labels.mask)) {  		err = ovs_ct_set_labels(ct, key, &info->labels.value, @@ -1328,7 +1335,12 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,  int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)  { -	nf_conntrack_put(skb_nfct(skb)); +	enum ip_conntrack_info ctinfo; +	struct nf_conn *ct; + +	ct = nf_ct_get(skb, &ctinfo); + +	nf_ct_put(ct);  	nf_ct_set(skb, NULL, IP_CT_UNTRACKED);  	ovs_ct_fill_key(skb, key, false); @@ -1716,7 +1728,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,  		goto err_free_ct;  	__set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); -	nf_conntrack_get(&ct_info.ct->ct_general);  	return 0;  err_free_ct:  	__ovs_ct_free_action(&ct_info); diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 6d262d9aa10e..02096f2ec678 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -859,7 +859,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,  #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)  	struct tc_skb_ext *tc_ext;  #endif -	bool post_ct = false; +	bool post_ct = false, post_ct_snat = false, post_ct_dnat = false;  	int res, err;  	u16 zone = 0; @@ -900,6 +900,8 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,  		key->recirc_id = tc_ext ? tc_ext->chain : 0;  		OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;  		post_ct = tc_ext ? tc_ext->post_ct : false; +		post_ct_snat = post_ct ? tc_ext->post_ct_snat : false; +		post_ct_dnat = post_ct ? tc_ext->post_ct_dnat : false;  		zone = post_ct ? tc_ext->zone : 0;  	} else {  		key->recirc_id = 0; @@ -911,8 +913,16 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,  	err = key_extract(skb, key);  	if (!err) {  		ovs_ct_fill_key(skb, key, post_ct);   /* Must be after key_extract(). */ -		if (post_ct && !skb_get_nfct(skb)) -			key->ct_zone = zone; +		if (post_ct) { +			if (!skb_get_nfct(skb)) { +				key->ct_zone = zone; +			} else { +				if (!post_ct_dnat) +					key->ct_state &= ~OVS_CS_F_DST_NAT; +				if (!post_ct_snat) +					key->ct_state &= ~OVS_CS_F_SRC_NAT; +			} +		}  	}  	return err;  } diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 8e1a88f13622..b498dac4e1e0 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -82,7 +82,7 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)  		err = -ENODEV;  		goto error_free_vport;  	} - +	netdev_tracker_alloc(vport->dev, &vport->dev_tracker, GFP_KERNEL);  	if (vport->dev->flags & IFF_LOOPBACK ||  	    (vport->dev->type != ARPHRD_ETHER &&  	     vport->dev->type != ARPHRD_NONE) || @@ -115,7 +115,7 @@ error_master_upper_dev_unlink:  error_unlock:  	rtnl_unlock();  error_put: -	dev_put(vport->dev); +	dev_put_track(vport->dev, &vport->dev_tracker);  error_free_vport:  	ovs_vport_free(vport);  	return ERR_PTR(err); @@ -137,8 +137,7 @@ static void vport_netdev_free(struct rcu_head *rcu)  {  	struct vport *vport = container_of(rcu, struct vport, rcu); -	if (vport->dev) -		dev_put(vport->dev); +	dev_put_track(vport->dev, &vport->dev_tracker);  	ovs_vport_free(vport);  } @@ -174,7 +173,7 @@ void ovs_netdev_tunnel_destroy(struct vport *vport)  	 */  	if (vport->dev->reg_state == NETREG_REGISTERED)  		rtnl_delete_link(vport->dev); -	dev_put(vport->dev); +	dev_put_track(vport->dev, &vport->dev_tracker);  	vport->dev = NULL;  	rtnl_unlock(); diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 8a930ca6d6b1..9de5030d9801 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -58,6 +58,7 @@ struct vport_portids {  /**   * struct vport - one port within a datapath   * @dev: Pointer to net_device. + * @dev_tracker: refcount tracker for @dev reference   * @dp: Datapath to which this port belongs.   * @upcall_portids: RCU protected 'struct vport_portids'.   * @port_no: Index into @dp's @ports array. @@ -69,6 +70,7 @@ struct vport_portids {   */  struct vport {  	struct net_device *dev; +	netdevice_tracker dev_tracker;  	struct datapath	*dp;  	struct vport_portids __rcu *upcall_portids;  	u16 port_no; |