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 @@ | |||
| 83 | #include <linux/if_vlan.h> | 83 | #include <linux/if_vlan.h> | 
| 84 | #include <linux/virtio_net.h> | 84 | #include <linux/virtio_net.h> | 
| 85 | #include <linux/errqueue.h> | 85 | #include <linux/errqueue.h> | 
| 86 | #include <linux/net_tstamp.h> | ||
| 86 | 87 | ||
| 87 | #ifdef CONFIG_INET | 88 | #ifdef CONFIG_INET | 
| 88 | #include <net/inet_common.h> | 89 | #include <net/inet_common.h> | 
| @@ -202,6 +203,7 @@ struct packet_sock { | |||
| 202 | unsigned int tp_hdrlen; | 203 | unsigned int tp_hdrlen; | 
| 203 | unsigned int tp_reserve; | 204 | unsigned int tp_reserve; | 
| 204 | unsigned int tp_loss:1; | 205 | unsigned int tp_loss:1; | 
| 206 | unsigned int tp_tstamp; | ||
| 205 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | 207 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | 
| 206 | }; | 208 | }; | 
| 207 | 209 | ||
| @@ -656,6 +658,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 656 | struct sk_buff *copy_skb = NULL; | 658 | struct sk_buff *copy_skb = NULL; | 
| 657 | struct timeval tv; | 659 | struct timeval tv; | 
| 658 | struct timespec ts; | 660 | struct timespec ts; | 
| 661 | struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); | ||
| 659 | 662 | ||
| 660 | if (skb->pkt_type == PACKET_LOOPBACK) | 663 | if (skb->pkt_type == PACKET_LOOPBACK) | 
| 661 | goto drop; | 664 | goto drop; | 
| @@ -737,7 +740,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 737 | h.h1->tp_snaplen = snaplen; | 740 | h.h1->tp_snaplen = snaplen; | 
| 738 | h.h1->tp_mac = macoff; | 741 | h.h1->tp_mac = macoff; | 
| 739 | h.h1->tp_net = netoff; | 742 | h.h1->tp_net = netoff; | 
| 740 | if (skb->tstamp.tv64) | 743 | if ((po->tp_tstamp & SOF_TIMESTAMPING_SYS_HARDWARE) | 
| 744 | && shhwtstamps->syststamp.tv64) | ||
| 745 | tv = ktime_to_timeval(shhwtstamps->syststamp); | ||
| 746 | else if ((po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE) | ||
| 747 | && shhwtstamps->hwtstamp.tv64) | ||
| 748 | tv = ktime_to_timeval(shhwtstamps->hwtstamp); | ||
| 749 | else if (skb->tstamp.tv64) | ||
| 741 | tv = ktime_to_timeval(skb->tstamp); | 750 | tv = ktime_to_timeval(skb->tstamp); | 
| 742 | else | 751 | else | 
| 743 | do_gettimeofday(&tv); | 752 | do_gettimeofday(&tv); | 
| @@ -750,7 +759,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 750 | h.h2->tp_snaplen = snaplen; | 759 | h.h2->tp_snaplen = snaplen; | 
| 751 | h.h2->tp_mac = macoff; | 760 | h.h2->tp_mac = macoff; | 
| 752 | h.h2->tp_net = netoff; | 761 | h.h2->tp_net = netoff; | 
| 753 | if (skb->tstamp.tv64) | 762 | if ((po->tp_tstamp & SOF_TIMESTAMPING_SYS_HARDWARE) | 
| 763 | && shhwtstamps->syststamp.tv64) | ||
| 764 | ts = ktime_to_timespec(shhwtstamps->syststamp); | ||
| 765 | else if ((po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE) | ||
| 766 | && shhwtstamps->hwtstamp.tv64) | ||
| 767 | ts = ktime_to_timespec(shhwtstamps->hwtstamp); | ||
| 768 | else if (skb->tstamp.tv64) | ||
| 754 | ts = ktime_to_timespec(skb->tstamp); | 769 | ts = ktime_to_timespec(skb->tstamp); | 
| 755 | else | 770 | else | 
| 756 | getnstimeofday(&ts); | 771 | getnstimeofday(&ts); | 
| @@ -2027,6 +2042,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
| 2027 | po->has_vnet_hdr = !!val; | 2042 | po->has_vnet_hdr = !!val; | 
| 2028 | return 0; | 2043 | return 0; | 
| 2029 | } | 2044 | } | 
| 2045 | case PACKET_TIMESTAMP: | ||
| 2046 | { | ||
| 2047 | int val; | ||
| 2048 | |||
| 2049 | if (optlen != sizeof(val)) | ||
| 2050 | return -EINVAL; | ||
| 2051 | if (copy_from_user(&val, optval, sizeof(val))) | ||
| 2052 | return -EFAULT; | ||
| 2053 | |||
| 2054 | po->tp_tstamp = val; | ||
| 2055 | return 0; | ||
| 2056 | } | ||
| 2030 | default: | 2057 | default: | 
| 2031 | return -ENOPROTOOPT; | 2058 | return -ENOPROTOOPT; | 
| 2032 | } | 2059 | } | 
| @@ -2119,6 +2146,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
| 2119 | val = po->tp_loss; | 2146 | val = po->tp_loss; | 
| 2120 | data = &val; | 2147 | data = &val; | 
| 2121 | break; | 2148 | break; | 
| 2149 | case PACKET_TIMESTAMP: | ||
| 2150 | if (len > sizeof(int)) | ||
| 2151 | len = sizeof(int); | ||
| 2152 | val = po->tp_tstamp; | ||
| 2153 | data = &val; | ||
| 2154 | break; | ||
| 2122 | default: | 2155 | default: | 
| 2123 | return -ENOPROTOOPT; | 2156 | return -ENOPROTOOPT; | 
| 2124 | } | 2157 | } | 
