Commit 51f31cab authored by Patrick Ohly's avatar Patrick Ohly Committed by David S. Miller

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: default avatarPatrick Ohly <patrick.ohly@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 20d49473
...@@ -56,6 +56,8 @@ and including the link layer, the scm_timestamping control message and ...@@ -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 a sock_extended_err control message with ee_errno==ENOMSG and
ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
bounced packet is ready for reading as far as select() is concerned. 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 All three values correspond to the same event in time, but were
generated in different ways. Each of these values may be empty (= all generated in different ways. Each of these values may be empty (= all
......
...@@ -55,6 +55,7 @@ struct ipcm_cookie ...@@ -55,6 +55,7 @@ struct ipcm_cookie
__be32 addr; __be32 addr;
int oif; int oif;
struct ip_options *opt; struct ip_options *opt;
union skb_shared_tx shtx;
}; };
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
......
...@@ -646,6 +646,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -646,6 +646,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
goto put_dev; goto put_dev;
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 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) if (err < 0)
goto free_skb; goto free_skb;
skb->dev = dev; skb->dev = dev;
......
...@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) ...@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
inet->tos = ip_hdr(skb)->tos; inet->tos = ip_hdr(skb)->tos;
daddr = ipc.addr = rt->rt_src; daddr = ipc.addr = rt->rt_src;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0;
if (icmp_param->replyopts.optlen) { if (icmp_param->replyopts.optlen) {
ipc.opt = &icmp_param->replyopts; ipc.opt = &icmp_param->replyopts;
if (ipc.opt->srr) if (ipc.opt->srr)
...@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) ...@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
inet_sk(sk)->tos = tos; inet_sk(sk)->tos = tos;
ipc.addr = iph->saddr; ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts; ipc.opt = &icmp_param.replyopts;
ipc.shtx.flags = 0;
{ {
struct flowi fl = { struct flowi fl = {
......
...@@ -935,6 +935,10 @@ int ip_append_data(struct sock *sk, ...@@ -935,6 +935,10 @@ int ip_append_data(struct sock *sk,
sk->sk_allocation); sk->sk_allocation);
if (unlikely(skb == NULL)) if (unlikely(skb == NULL))
err = -ENOBUFS; err = -ENOBUFS;
else
/* only the initial fragment is
time stamped */
ipc->shtx.flags = 0;
} }
if (skb == NULL) if (skb == NULL)
goto error; goto error;
...@@ -945,6 +949,7 @@ int ip_append_data(struct sock *sk, ...@@ -945,6 +949,7 @@ int ip_append_data(struct sock *sk,
skb->ip_summed = csummode; skb->ip_summed = csummode;
skb->csum = 0; skb->csum = 0;
skb_reserve(skb, hh_len); skb_reserve(skb, hh_len);
*skb_tx(skb) = ipc->shtx;
/* /*
* Find where to start putting bytes. * 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 ...@@ -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; daddr = ipc.addr = rt->rt_src;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0;
if (replyopts.opt.optlen) { if (replyopts.opt.optlen) {
ipc.opt = &replyopts.opt; ipc.opt = &replyopts.opt;
......
...@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
ipc.addr = inet->saddr; ipc.addr = inet->saddr;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0;
ipc.oif = sk->sk_bound_dev_if; ipc.oif = sk->sk_bound_dev_if;
if (msg->msg_controllen) { if (msg->msg_controllen) {
......
...@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
return -EOPNOTSUPP; return -EOPNOTSUPP;
ipc.opt = NULL; ipc.opt = NULL;
ipc.shtx.flags = 0;
if (up->pending) { if (up->pending) {
/* /*
...@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
ipc.addr = inet->saddr; ipc.addr = inet->saddr;
ipc.oif = sk->sk_bound_dev_if; ipc.oif = sk->sk_bound_dev_if;
err = sock_tx_timestamp(msg, sk, &ipc.shtx);
if (err)
return err;
if (msg->msg_controllen) { if (msg->msg_controllen) {
err = ip_cmsg_send(sock_net(sk), msg, &ipc); err = ip_cmsg_send(sock_net(sk), msg, &ipc);
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment