mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
ipv6: colocate inet6_cork in inet_cork_full
All inet6_cork users also use one inet_cork_full. Reduce number of parameters and increase data locality. This saves ~275 bytes of code on x86_64. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260130210303.3888261-9-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
fe8570186f
commit
b409a7f717
|
|
@ -205,13 +205,6 @@ struct ipv6_mc_socklist;
|
||||||
struct ipv6_ac_socklist;
|
struct ipv6_ac_socklist;
|
||||||
struct ipv6_fl_socklist;
|
struct ipv6_fl_socklist;
|
||||||
|
|
||||||
struct inet6_cork {
|
|
||||||
struct ipv6_txoptions *opt;
|
|
||||||
u8 hop_limit;
|
|
||||||
u8 tclass;
|
|
||||||
u8 dontfrag:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* struct ipv6_pinfo - ipv6 private area */
|
/* struct ipv6_pinfo - ipv6 private area */
|
||||||
struct ipv6_pinfo {
|
struct ipv6_pinfo {
|
||||||
/* Used in tx path (inet6_csk_route_socket(), ip6_xmit()) */
|
/* Used in tx path (inet6_csk_route_socket(), ip6_xmit()) */
|
||||||
|
|
@ -267,7 +260,6 @@ struct ipv6_pinfo {
|
||||||
|
|
||||||
struct sk_buff *pktoptions;
|
struct sk_buff *pktoptions;
|
||||||
struct sk_buff *rxpmtu;
|
struct sk_buff *rxpmtu;
|
||||||
struct inet6_cork cork;
|
|
||||||
|
|
||||||
struct ipv6_mc_socklist __rcu *ipv6_mc_list;
|
struct ipv6_mc_socklist __rcu *ipv6_mc_list;
|
||||||
struct ipv6_ac_socklist *ipv6_ac_list;
|
struct ipv6_ac_socklist *ipv6_ac_list;
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,13 @@ static inline bool inet_sk_bound_dev_eq(const struct net *net,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct inet6_cork {
|
||||||
|
struct ipv6_txoptions *opt;
|
||||||
|
u8 hop_limit;
|
||||||
|
u8 tclass;
|
||||||
|
u8 dontfrag:1;
|
||||||
|
};
|
||||||
|
|
||||||
struct inet_cork {
|
struct inet_cork {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
__be32 addr;
|
__be32 addr;
|
||||||
|
|
@ -179,6 +186,9 @@ struct inet_cork {
|
||||||
struct inet_cork_full {
|
struct inet_cork_full {
|
||||||
struct inet_cork base;
|
struct inet_cork base;
|
||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
struct inet6_cork base6;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_mc_socklist;
|
struct ip_mc_socklist;
|
||||||
|
|
|
||||||
|
|
@ -1107,8 +1107,7 @@ void ip6_flush_pending_frames(struct sock *sk);
|
||||||
int ip6_send_skb(struct sk_buff *skb);
|
int ip6_send_skb(struct sk_buff *skb);
|
||||||
|
|
||||||
struct sk_buff *__ip6_make_skb(struct sock *sk, struct sk_buff_head *queue,
|
struct sk_buff *__ip6_make_skb(struct sock *sk, struct sk_buff_head *queue,
|
||||||
struct inet_cork_full *cork,
|
struct inet_cork_full *cork);
|
||||||
struct inet6_cork *v6_cork);
|
|
||||||
struct sk_buff *ip6_make_skb(struct sock *sk,
|
struct sk_buff *ip6_make_skb(struct sock *sk,
|
||||||
int getfrag(void *from, char *to, int offset,
|
int getfrag(void *from, char *to, int offset,
|
||||||
int len, int odd, struct sk_buff *skb),
|
int len, int odd, struct sk_buff *skb),
|
||||||
|
|
@ -1119,8 +1118,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
||||||
|
|
||||||
static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
|
static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
|
||||||
{
|
{
|
||||||
return __ip6_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork,
|
return __ip6_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
|
||||||
&inet6_sk(sk)->cork);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst,
|
int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst,
|
||||||
|
|
|
||||||
|
|
@ -1353,12 +1353,13 @@ 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 ipcm6_cookie *ipc6,
|
||||||
struct rt6_info *rt)
|
struct rt6_info *rt)
|
||||||
{
|
{
|
||||||
|
struct ipv6_txoptions *nopt, *opt = ipc6->opt;
|
||||||
|
struct inet6_cork *v6_cork = &cork->base6;
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||||
unsigned int mtu, frag_size;
|
unsigned int mtu, frag_size;
|
||||||
struct ipv6_txoptions *nopt, *opt = ipc6->opt;
|
|
||||||
|
|
||||||
/* callers pass dst together with a reference, set it first so
|
/* callers pass dst together with a reference, set it first so
|
||||||
* ip6_cork_release() can put it down even in case of an error.
|
* ip6_cork_release() can put it down even in case of an error.
|
||||||
|
|
@ -1431,17 +1432,17 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
|
||||||
static int __ip6_append_data(struct sock *sk,
|
static int __ip6_append_data(struct sock *sk,
|
||||||
struct sk_buff_head *queue,
|
struct sk_buff_head *queue,
|
||||||
struct inet_cork_full *cork_full,
|
struct inet_cork_full *cork_full,
|
||||||
struct inet6_cork *v6_cork,
|
|
||||||
struct page_frag *pfrag,
|
struct page_frag *pfrag,
|
||||||
int getfrag(void *from, char *to, int offset,
|
int getfrag(void *from, char *to, int offset,
|
||||||
int len, int odd, struct sk_buff *skb),
|
int len, int odd, struct sk_buff *skb),
|
||||||
void *from, size_t length, int transhdrlen,
|
void *from, size_t length, int transhdrlen,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb, *skb_prev = NULL;
|
unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
|
||||||
|
struct inet6_cork *v6_cork = &cork_full->base6;
|
||||||
struct inet_cork *cork = &cork_full->base;
|
struct inet_cork *cork = &cork_full->base;
|
||||||
struct flowi6 *fl6 = &cork_full->fl.u.ip6;
|
struct flowi6 *fl6 = &cork_full->fl.u.ip6;
|
||||||
unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu;
|
struct sk_buff *skb, *skb_prev = NULL;
|
||||||
struct ubuf_info *uarg = NULL;
|
struct ubuf_info *uarg = NULL;
|
||||||
int exthdrlen = 0;
|
int exthdrlen = 0;
|
||||||
int dst_exthdrlen = 0;
|
int dst_exthdrlen = 0;
|
||||||
|
|
@ -1844,7 +1845,6 @@ int ip6_append_data(struct sock *sk,
|
||||||
struct rt6_info *rt, unsigned int flags)
|
struct rt6_info *rt, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
|
||||||
int exthdrlen;
|
int exthdrlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
@ -1855,7 +1855,7 @@ int ip6_append_data(struct sock *sk,
|
||||||
* setup for corking
|
* setup for corking
|
||||||
*/
|
*/
|
||||||
dst_hold(&rt->dst);
|
dst_hold(&rt->dst);
|
||||||
err = ip6_setup_cork(sk, &inet->cork, &np->cork,
|
err = ip6_setup_cork(sk, &inet->cork,
|
||||||
ipc6, rt);
|
ipc6, rt);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -1869,7 +1869,7 @@ int ip6_append_data(struct sock *sk,
|
||||||
}
|
}
|
||||||
|
|
||||||
return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork,
|
return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork,
|
||||||
&np->cork, sk_page_frag(sk), getfrag,
|
sk_page_frag(sk), getfrag,
|
||||||
from, length, transhdrlen, flags);
|
from, length, transhdrlen, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ip6_append_data);
|
EXPORT_SYMBOL_GPL(ip6_append_data);
|
||||||
|
|
@ -1882,9 +1882,10 @@ static void ip6_cork_steal_dst(struct sk_buff *skb, struct inet_cork_full *cork)
|
||||||
skb_dst_set(skb, dst);
|
skb_dst_set(skb, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ip6_cork_release(struct inet_cork_full *cork,
|
static void ip6_cork_release(struct inet_cork_full *cork)
|
||||||
struct inet6_cork *v6_cork)
|
|
||||||
{
|
{
|
||||||
|
struct inet6_cork *v6_cork = &cork->base6;
|
||||||
|
|
||||||
if (unlikely(v6_cork->opt)) {
|
if (unlikely(v6_cork->opt)) {
|
||||||
struct ipv6_txoptions *opt = v6_cork->opt;
|
struct ipv6_txoptions *opt = v6_cork->opt;
|
||||||
|
|
||||||
|
|
@ -1904,15 +1905,14 @@ static void ip6_cork_release(struct inet_cork_full *cork,
|
||||||
|
|
||||||
struct sk_buff *__ip6_make_skb(struct sock *sk,
|
struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||||
struct sk_buff_head *queue,
|
struct sk_buff_head *queue,
|
||||||
struct inet_cork_full *cork,
|
struct inet_cork_full *cork)
|
||||||
struct inet6_cork *v6_cork)
|
|
||||||
{
|
{
|
||||||
struct sk_buff *skb, *tmp_skb;
|
struct sk_buff *skb, *tmp_skb;
|
||||||
struct sk_buff **tail_skb;
|
struct sk_buff **tail_skb;
|
||||||
struct in6_addr *final_dst;
|
struct in6_addr *final_dst;
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
struct ipv6hdr *hdr;
|
struct ipv6hdr *hdr;
|
||||||
struct ipv6_txoptions *opt = v6_cork->opt;
|
struct ipv6_txoptions *opt;
|
||||||
struct rt6_info *rt = dst_rt6_info(cork->base.dst);
|
struct rt6_info *rt = dst_rt6_info(cork->base.dst);
|
||||||
struct flowi6 *fl6 = &cork->fl.u.ip6;
|
struct flowi6 *fl6 = &cork->fl.u.ip6;
|
||||||
unsigned char proto = fl6->flowi6_proto;
|
unsigned char proto = fl6->flowi6_proto;
|
||||||
|
|
@ -1941,6 +1941,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||||
__skb_pull(skb, skb_network_header_len(skb));
|
__skb_pull(skb, skb_network_header_len(skb));
|
||||||
|
|
||||||
final_dst = &fl6->daddr;
|
final_dst = &fl6->daddr;
|
||||||
|
opt = cork->base6.opt;
|
||||||
if (unlikely(opt)) {
|
if (unlikely(opt)) {
|
||||||
if (opt->opt_flen)
|
if (opt->opt_flen)
|
||||||
proto = ipv6_push_frag_opts(skb, opt, proto);
|
proto = ipv6_push_frag_opts(skb, opt, proto);
|
||||||
|
|
@ -1952,10 +1953,10 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||||
skb_reset_network_header(skb);
|
skb_reset_network_header(skb);
|
||||||
hdr = ipv6_hdr(skb);
|
hdr = ipv6_hdr(skb);
|
||||||
|
|
||||||
ip6_flow_hdr(hdr, v6_cork->tclass,
|
ip6_flow_hdr(hdr, cork->base6.tclass,
|
||||||
ip6_make_flowlabel(net, skb, fl6->flowlabel,
|
ip6_make_flowlabel(net, skb, fl6->flowlabel,
|
||||||
ip6_autoflowlabel(net, sk), fl6));
|
ip6_autoflowlabel(net, sk), fl6));
|
||||||
hdr->hop_limit = v6_cork->hop_limit;
|
hdr->hop_limit = cork->base6.hop_limit;
|
||||||
hdr->nexthdr = proto;
|
hdr->nexthdr = proto;
|
||||||
hdr->saddr = fl6->saddr;
|
hdr->saddr = fl6->saddr;
|
||||||
hdr->daddr = *final_dst;
|
hdr->daddr = *final_dst;
|
||||||
|
|
@ -1982,7 +1983,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
|
||||||
ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
|
ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip6_cork_release(cork, v6_cork);
|
ip6_cork_release(cork);
|
||||||
out:
|
out:
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
@ -2021,8 +2022,7 @@ EXPORT_SYMBOL_GPL(ip6_push_pending_frames);
|
||||||
|
|
||||||
static void __ip6_flush_pending_frames(struct sock *sk,
|
static void __ip6_flush_pending_frames(struct sock *sk,
|
||||||
struct sk_buff_head *queue,
|
struct sk_buff_head *queue,
|
||||||
struct inet_cork_full *cork,
|
struct inet_cork_full *cork)
|
||||||
struct inet6_cork *v6_cork)
|
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
|
@ -2033,13 +2033,13 @@ static void __ip6_flush_pending_frames(struct sock *sk,
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip6_cork_release(cork, v6_cork);
|
ip6_cork_release(cork);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ip6_flush_pending_frames(struct sock *sk)
|
void ip6_flush_pending_frames(struct sock *sk)
|
||||||
{
|
{
|
||||||
__ip6_flush_pending_frames(sk, &sk->sk_write_queue,
|
__ip6_flush_pending_frames(sk, &sk->sk_write_queue,
|
||||||
&inet_sk(sk)->cork, &inet6_sk(sk)->cork);
|
&inet_sk(sk)->cork);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ip6_flush_pending_frames);
|
EXPORT_SYMBOL_GPL(ip6_flush_pending_frames);
|
||||||
|
|
||||||
|
|
@ -2050,9 +2050,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
||||||
struct ipcm6_cookie *ipc6, struct rt6_info *rt,
|
struct ipcm6_cookie *ipc6, struct rt6_info *rt,
|
||||||
unsigned int flags, struct inet_cork_full *cork)
|
unsigned int flags, struct inet_cork_full *cork)
|
||||||
{
|
{
|
||||||
struct inet6_cork v6_cork;
|
|
||||||
struct sk_buff_head queue;
|
|
||||||
int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
|
int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
|
||||||
|
struct sk_buff_head queue;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (flags & MSG_PROBE) {
|
if (flags & MSG_PROBE) {
|
||||||
|
|
@ -2065,21 +2064,21 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
||||||
cork->base.flags = 0;
|
cork->base.flags = 0;
|
||||||
cork->base.addr = 0;
|
cork->base.addr = 0;
|
||||||
cork->base.opt = NULL;
|
cork->base.opt = NULL;
|
||||||
v6_cork.opt = NULL;
|
cork->base6.opt = NULL;
|
||||||
err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt);
|
err = ip6_setup_cork(sk, cork, ipc6, rt);
|
||||||
if (err) {
|
if (err) {
|
||||||
ip6_cork_release(cork, &v6_cork);
|
ip6_cork_release(cork);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = __ip6_append_data(sk, &queue, cork, &v6_cork,
|
err = __ip6_append_data(sk, &queue, cork,
|
||||||
¤t->task_frag, getfrag, from,
|
¤t->task_frag, getfrag, from,
|
||||||
length + exthdrlen, transhdrlen + exthdrlen,
|
length + exthdrlen, transhdrlen + exthdrlen,
|
||||||
flags);
|
flags);
|
||||||
if (err) {
|
if (err) {
|
||||||
__ip6_flush_pending_frames(sk, &queue, cork, &v6_cork);
|
__ip6_flush_pending_frames(sk, &queue, cork);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return __ip6_make_skb(sk, &queue, cork, &v6_cork);
|
return __ip6_make_skb(sk, &queue, cork);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -529,7 +529,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
|
||||||
|
|
||||||
offset = rp->offset;
|
offset = rp->offset;
|
||||||
total_len = inet_sk(sk)->cork.base.length;
|
total_len = inet_sk(sk)->cork.base.length;
|
||||||
opt = inet6_sk(sk)->cork.opt;
|
opt = inet_sk(sk)->cork.base6.opt;
|
||||||
total_len -= opt ? opt->opt_flen : 0;
|
total_len -= opt ? opt->opt_flen : 0;
|
||||||
|
|
||||||
if (offset >= total_len - 1) {
|
if (offset >= total_len - 1) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user