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
|
@ -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 @@ alloc_new_skb:
|
|||
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 @@ alloc_new_skb:
|
|||
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 New Issue