mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ip: support for TX timestamps on UDP and RAW sockets
Instructions for time stamping outgoing packets are take from the socket layer and later copied into the new skb. Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									20d4947353
								
							
						
					
					
						commit
						51f31cabe3
					
				
					 7 changed files with 19 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -56,6 +56,8 @@ and including the link layer, the scm_timestamping control message and
 | 
			
		|||
a sock_extended_err control message with ee_errno==ENOMSG and
 | 
			
		||||
ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
 | 
			
		||||
bounced packet is ready for reading as far as select() is concerned.
 | 
			
		||||
If the outgoing packet has to be fragmented, then only the first
 | 
			
		||||
fragment is time stamped and returned to the sending socket.
 | 
			
		||||
 | 
			
		||||
All three values correspond to the same event in time, but were
 | 
			
		||||
generated in different ways. Each of these values may be empty (= all
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,7 @@ struct ipcm_cookie
 | 
			
		|||
	__be32			addr;
 | 
			
		||||
	int			oif;
 | 
			
		||||
	struct ip_options	*opt;
 | 
			
		||||
	union skb_shared_tx	shtx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -646,6 +646,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
 | 
			
		|||
		goto put_dev;
 | 
			
		||||
 | 
			
		||||
	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto free_skb;
 | 
			
		||||
	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto free_skb;
 | 
			
		||||
	skb->dev = dev;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 | 
			
		|||
	inet->tos = ip_hdr(skb)->tos;
 | 
			
		||||
	daddr = ipc.addr = rt->rt_src;
 | 
			
		||||
	ipc.opt = NULL;
 | 
			
		||||
	ipc.shtx.flags = 0;
 | 
			
		||||
	if (icmp_param->replyopts.optlen) {
 | 
			
		||||
		ipc.opt = &icmp_param->replyopts;
 | 
			
		||||
		if (ipc.opt->srr)
 | 
			
		||||
| 
						 | 
				
			
			@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 | 
			
		|||
	inet_sk(sk)->tos = tos;
 | 
			
		||||
	ipc.addr = iph->saddr;
 | 
			
		||||
	ipc.opt = &icmp_param.replyopts;
 | 
			
		||||
	ipc.shtx.flags = 0;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		struct flowi fl = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -935,6 +935,10 @@ int ip_append_data(struct sock *sk,
 | 
			
		|||
							   sk->sk_allocation);
 | 
			
		||||
				if (unlikely(skb == NULL))
 | 
			
		||||
					err = -ENOBUFS;
 | 
			
		||||
				else
 | 
			
		||||
					/* only the initial fragment is
 | 
			
		||||
					   time stamped */
 | 
			
		||||
					ipc->shtx.flags = 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (skb == NULL)
 | 
			
		||||
				goto error;
 | 
			
		||||
| 
						 | 
				
			
			@ -945,6 +949,7 @@ int ip_append_data(struct sock *sk,
 | 
			
		|||
			skb->ip_summed = csummode;
 | 
			
		||||
			skb->csum = 0;
 | 
			
		||||
			skb_reserve(skb, hh_len);
 | 
			
		||||
			*skb_tx(skb) = ipc->shtx;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			 *	Find where to start putting bytes.
 | 
			
		||||
| 
						 | 
				
			
			@ -1364,6 +1369,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 | 
			
		|||
 | 
			
		||||
	daddr = ipc.addr = rt->rt_src;
 | 
			
		||||
	ipc.opt = NULL;
 | 
			
		||||
	ipc.shtx.flags = 0;
 | 
			
		||||
 | 
			
		||||
	if (replyopts.opt.optlen) {
 | 
			
		||||
		ipc.opt = &replyopts.opt;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
			
		|||
 | 
			
		||||
	ipc.addr = inet->saddr;
 | 
			
		||||
	ipc.opt = NULL;
 | 
			
		||||
	ipc.shtx.flags = 0;
 | 
			
		||||
	ipc.oif = sk->sk_bound_dev_if;
 | 
			
		||||
 | 
			
		||||
	if (msg->msg_controllen) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
			
		|||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	ipc.opt = NULL;
 | 
			
		||||
	ipc.shtx.flags = 0;
 | 
			
		||||
 | 
			
		||||
	if (up->pending) {
 | 
			
		||||
		/*
 | 
			
		||||
| 
						 | 
				
			
			@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
			
		|||
	ipc.addr = inet->saddr;
 | 
			
		||||
 | 
			
		||||
	ipc.oif = sk->sk_bound_dev_if;
 | 
			
		||||
	err = sock_tx_timestamp(msg, sk, &ipc.shtx);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	if (msg->msg_controllen) {
 | 
			
		||||
		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
 | 
			
		||||
		if (err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue