mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net-timestamp: Make the clone operation stand-alone from phy timestamping
The phy timestamping takes a different path than the regular timestamping does in that it will create a clone first so that the packets needing to be timestamped can be placed in a queue, or the context block could be used. In order to support these use cases I am pulling the core of the code out so it can be used in other drivers beyond just phy devices. In addition I have added a destructor named sock_efree which is meant to provide a simple way for dropping the reference to skb exceptions that aren't part of either the receive or send windows for the socket, and I have removed some duplication in spots where this destructor could be used in place of sock_edemux. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									37846ef018
								
							
						
					
					
						commit
						62bccb8cdb
					
				
					 6 changed files with 40 additions and 21 deletions
				
			
		| 
						 | 
				
			
			@ -1148,7 +1148,7 @@ static void dp83640_remove(struct phy_device *phydev)
 | 
			
		|||
		kfree_skb(skb);
 | 
			
		||||
 | 
			
		||||
	while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL)
 | 
			
		||||
		skb_complete_tx_timestamp(skb, NULL);
 | 
			
		||||
		kfree_skb(skb);
 | 
			
		||||
 | 
			
		||||
	clock = dp83640_clock_get(dp83640->clock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1405,7 +1405,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
 | 
			
		|||
 | 
			
		||||
	case HWTSTAMP_TX_ONESTEP_SYNC:
 | 
			
		||||
		if (is_sync(skb, type)) {
 | 
			
		||||
			skb_complete_tx_timestamp(skb, NULL);
 | 
			
		||||
			kfree_skb(skb);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		/* fall through */
 | 
			
		||||
| 
						 | 
				
			
			@ -1416,7 +1416,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
 | 
			
		|||
 | 
			
		||||
	case HWTSTAMP_TX_OFF:
 | 
			
		||||
	default:
 | 
			
		||||
		skb_complete_tx_timestamp(skb, NULL);
 | 
			
		||||
		kfree_skb(skb);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2690,6 +2690,8 @@ static inline ktime_t net_invalid_timestamp(void)
 | 
			
		|||
	return ktime_set(0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sk_buff *skb_clone_sk(struct sk_buff *skb);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
 | 
			
		||||
 | 
			
		||||
void skb_clone_tx_timestamp(struct sk_buff *skb);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1574,6 +1574,7 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
 | 
			
		|||
void sock_wfree(struct sk_buff *skb);
 | 
			
		||||
void skb_orphan_partial(struct sk_buff *skb);
 | 
			
		||||
void sock_rfree(struct sk_buff *skb);
 | 
			
		||||
void sock_efree(struct sk_buff *skb);
 | 
			
		||||
void sock_edemux(struct sk_buff *skb);
 | 
			
		||||
 | 
			
		||||
int sock_setsockopt(struct socket *sock, int level, int op,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3511,6 +3511,27 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(sock_dequeue_err_skb);
 | 
			
		||||
 | 
			
		||||
struct sk_buff *skb_clone_sk(struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk = skb->sk;
 | 
			
		||||
	struct sk_buff *clone;
 | 
			
		||||
 | 
			
		||||
	if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	clone = skb_clone(skb, GFP_ATOMIC);
 | 
			
		||||
	if (!clone) {
 | 
			
		||||
		sock_put(sk);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clone->sk = sk;
 | 
			
		||||
	clone->destructor = sock_efree;
 | 
			
		||||
 | 
			
		||||
	return clone;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(skb_clone_sk);
 | 
			
		||||
 | 
			
		||||
static void __skb_complete_tx_timestamp(struct sk_buff *skb,
 | 
			
		||||
					struct sock *sk,
 | 
			
		||||
					int tstype)
 | 
			
		||||
| 
						 | 
				
			
			@ -3540,14 +3561,11 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,
 | 
			
		|||
{
 | 
			
		||||
	struct sock *sk = skb->sk;
 | 
			
		||||
 | 
			
		||||
	skb->sk = NULL;
 | 
			
		||||
	/* take a reference to prevent skb_orphan() from freeing the socket */
 | 
			
		||||
	sock_hold(sk);
 | 
			
		||||
 | 
			
		||||
	if (hwtstamps) {
 | 
			
		||||
	*skb_hwtstamps(skb) = *hwtstamps;
 | 
			
		||||
	__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
 | 
			
		||||
	} else {
 | 
			
		||||
		kfree_skb(skb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1637,6 +1637,12 @@ void sock_rfree(struct sk_buff *skb)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(sock_rfree);
 | 
			
		||||
 | 
			
		||||
void sock_efree(struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	sock_put(skb->sk);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(sock_efree);
 | 
			
		||||
 | 
			
		||||
void sock_edemux(struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	struct sock *sk = skb->sk;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,10 +36,9 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
 | 
			
		|||
{
 | 
			
		||||
	struct phy_device *phydev;
 | 
			
		||||
	struct sk_buff *clone;
 | 
			
		||||
	struct sock *sk = skb->sk;
 | 
			
		||||
	unsigned int type;
 | 
			
		||||
 | 
			
		||||
	if (!sk)
 | 
			
		||||
	if (!skb->sk)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	type = classify(skb);
 | 
			
		||||
| 
						 | 
				
			
			@ -48,16 +47,9 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
 | 
			
		|||
 | 
			
		||||
	phydev = skb->dev->phydev;
 | 
			
		||||
	if (likely(phydev->drv->txtstamp)) {
 | 
			
		||||
		if (!atomic_inc_not_zero(&sk->sk_refcnt))
 | 
			
		||||
		clone = skb_clone_sk(skb);
 | 
			
		||||
		if (!clone)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		clone = skb_clone(skb, GFP_ATOMIC);
 | 
			
		||||
		if (!clone) {
 | 
			
		||||
			sock_put(sk);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		clone->sk = sk;
 | 
			
		||||
		phydev->drv->txtstamp(phydev, clone, type);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue