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
|
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
|
|||||||
__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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@ alloc_new_skb:
|
|||||||
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 @@ alloc_new_skb:
|
|||||||
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
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user