net: ipv6: Hook into time based transmission
Add a struct sockcm_cookie parameter to ip6_setup_cork() so we can easily re-use the transmit_time field from struct inet_cork for most paths, by copying the timestamp from the CMSG cookie. This is later copied into the skb during __ip6_make_skb(). For the raw fast path, also pass the sockcm_cookie as a parameter so we can just perform the copy at rawv6_send_hdrinc() directly. Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
bc969a9778
commit
a818f75e31
@@ -1158,7 +1158,8 @@ static void ip6_append_data_mtu(unsigned int *mtu,
|
|||||||
|
|
||||||
static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
|
static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
|
||||||
struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6,
|
struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6,
|
||||||
struct rt6_info *rt, struct flowi6 *fl6)
|
struct rt6_info *rt, struct flowi6 *fl6,
|
||||||
|
const struct sockcm_cookie *sockc)
|
||||||
{
|
{
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||||
unsigned int mtu;
|
unsigned int mtu;
|
||||||
@@ -1226,6 +1227,8 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
|
|||||||
cork->base.flags |= IPCORK_ALLFRAG;
|
cork->base.flags |= IPCORK_ALLFRAG;
|
||||||
cork->base.length = 0;
|
cork->base.length = 0;
|
||||||
|
|
||||||
|
cork->base.transmit_time = sockc->transmit_time;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1575,7 +1578,7 @@ int ip6_append_data(struct sock *sk,
|
|||||||
* setup for corking
|
* setup for corking
|
||||||
*/
|
*/
|
||||||
err = ip6_setup_cork(sk, &inet->cork, &np->cork,
|
err = ip6_setup_cork(sk, &inet->cork, &np->cork,
|
||||||
ipc6, rt, fl6);
|
ipc6, rt, fl6, sockc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -1673,6 +1676,8 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
|||||||
skb->priority = sk->sk_priority;
|
skb->priority = sk->sk_priority;
|
||||||
skb->mark = sk->sk_mark;
|
skb->mark = sk->sk_mark;
|
||||||
|
|
||||||
|
skb->tstamp = cork->base.transmit_time;
|
||||||
|
|
||||||
skb_dst_set(skb, dst_clone(&rt->dst));
|
skb_dst_set(skb, dst_clone(&rt->dst));
|
||||||
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
|
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
|
||||||
if (proto == IPPROTO_ICMPV6) {
|
if (proto == IPPROTO_ICMPV6) {
|
||||||
@@ -1765,7 +1770,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
|||||||
cork->base.opt = NULL;
|
cork->base.opt = NULL;
|
||||||
cork->base.dst = NULL;
|
cork->base.dst = NULL;
|
||||||
v6_cork.opt = NULL;
|
v6_cork.opt = NULL;
|
||||||
err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt, fl6);
|
err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt, fl6, sockc);
|
||||||
if (err) {
|
if (err) {
|
||||||
ip6_cork_release(cork, &v6_cork);
|
ip6_cork_release(cork, &v6_cork);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
@@ -620,7 +620,7 @@ out:
|
|||||||
|
|
||||||
static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
|
static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
|
||||||
struct flowi6 *fl6, struct dst_entry **dstp,
|
struct flowi6 *fl6, struct dst_entry **dstp,
|
||||||
unsigned int flags)
|
unsigned int flags, const struct sockcm_cookie *sockc)
|
||||||
{
|
{
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
@@ -650,6 +650,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
|
|||||||
skb->protocol = htons(ETH_P_IPV6);
|
skb->protocol = htons(ETH_P_IPV6);
|
||||||
skb->priority = sk->sk_priority;
|
skb->priority = sk->sk_priority;
|
||||||
skb->mark = sk->sk_mark;
|
skb->mark = sk->sk_mark;
|
||||||
|
skb->tstamp = sockc->transmit_time;
|
||||||
skb_dst_set(skb, &rt->dst);
|
skb_dst_set(skb, &rt->dst);
|
||||||
*dstp = NULL;
|
*dstp = NULL;
|
||||||
|
|
||||||
@@ -848,6 +849,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
fl6.flowi6_oif = sk->sk_bound_dev_if;
|
fl6.flowi6_oif = sk->sk_bound_dev_if;
|
||||||
|
|
||||||
sockc.tsflags = sk->sk_tsflags;
|
sockc.tsflags = sk->sk_tsflags;
|
||||||
|
sockc.transmit_time = 0;
|
||||||
if (msg->msg_controllen) {
|
if (msg->msg_controllen) {
|
||||||
opt = &opt_space;
|
opt = &opt_space;
|
||||||
memset(opt, 0, sizeof(struct ipv6_txoptions));
|
memset(opt, 0, sizeof(struct ipv6_txoptions));
|
||||||
@@ -921,7 +923,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
|
|
||||||
back_from_confirm:
|
back_from_confirm:
|
||||||
if (inet->hdrincl)
|
if (inet->hdrincl)
|
||||||
err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst, msg->msg_flags);
|
err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst,
|
||||||
|
msg->msg_flags, &sockc);
|
||||||
else {
|
else {
|
||||||
ipc6.opt = opt;
|
ipc6.opt = opt;
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
@@ -1148,6 +1148,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
ipc6.dontfrag = -1;
|
ipc6.dontfrag = -1;
|
||||||
ipc6.gso_size = up->gso_size;
|
ipc6.gso_size = up->gso_size;
|
||||||
sockc.tsflags = sk->sk_tsflags;
|
sockc.tsflags = sk->sk_tsflags;
|
||||||
|
sockc.transmit_time = 0;
|
||||||
|
|
||||||
/* destination address check */
|
/* destination address check */
|
||||||
if (sin6) {
|
if (sin6) {
|
||||||
|
Reference in New Issue
Block a user