diff options
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 37 | 
1 files changed, 35 insertions, 2 deletions
| diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2078a277e06b..9a17f28b1253 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -83,6 +83,7 @@  #include <linux/if_vlan.h>  #include <linux/virtio_net.h>  #include <linux/errqueue.h> +#include <linux/net_tstamp.h>  #ifdef CONFIG_INET  #include <net/inet_common.h> @@ -202,6 +203,7 @@ struct packet_sock {  	unsigned int		tp_hdrlen;  	unsigned int		tp_reserve;  	unsigned int		tp_loss:1; +	unsigned int		tp_tstamp;  	struct packet_type	prot_hook ____cacheline_aligned_in_smp;  }; @@ -656,6 +658,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  	struct sk_buff *copy_skb = NULL;  	struct timeval tv;  	struct timespec ts; +	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);  	if (skb->pkt_type == PACKET_LOOPBACK)  		goto drop; @@ -737,7 +740,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  		h.h1->tp_snaplen = snaplen;  		h.h1->tp_mac = macoff;  		h.h1->tp_net = netoff; -		if (skb->tstamp.tv64) +		if ((po->tp_tstamp & SOF_TIMESTAMPING_SYS_HARDWARE) +				&& shhwtstamps->syststamp.tv64) +			tv = ktime_to_timeval(shhwtstamps->syststamp); +		else if ((po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE) +				&& shhwtstamps->hwtstamp.tv64) +			tv = ktime_to_timeval(shhwtstamps->hwtstamp); +		else if (skb->tstamp.tv64)  			tv = ktime_to_timeval(skb->tstamp);  		else  			do_gettimeofday(&tv); @@ -750,7 +759,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  		h.h2->tp_snaplen = snaplen;  		h.h2->tp_mac = macoff;  		h.h2->tp_net = netoff; -		if (skb->tstamp.tv64) +		if ((po->tp_tstamp & SOF_TIMESTAMPING_SYS_HARDWARE) +				&& shhwtstamps->syststamp.tv64) +			ts = ktime_to_timespec(shhwtstamps->syststamp); +		else if ((po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE) +				&& shhwtstamps->hwtstamp.tv64) +			ts = ktime_to_timespec(shhwtstamps->hwtstamp); +		else if (skb->tstamp.tv64)  			ts = ktime_to_timespec(skb->tstamp);  		else  			getnstimeofday(&ts); @@ -2027,6 +2042,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv  		po->has_vnet_hdr = !!val;  		return 0;  	} +	case PACKET_TIMESTAMP: +	{ +		int val; + +		if (optlen != sizeof(val)) +			return -EINVAL; +		if (copy_from_user(&val, optval, sizeof(val))) +			return -EFAULT; + +		po->tp_tstamp = val; +		return 0; +	}  	default:  		return -ENOPROTOOPT;  	} @@ -2119,6 +2146,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,  		val = po->tp_loss;  		data = &val;  		break; +	case PACKET_TIMESTAMP: +		if (len > sizeof(int)) +			len = sizeof(int); +		val = po->tp_tstamp; +		data = &val; +		break;  	default:  		return -ENOPROTOOPT;  	} |