]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipv6: colocate inet6_cork in inet_cork_full
authorEric Dumazet <edumazet@google.com>
Fri, 30 Jan 2026 21:03:03 +0000 (21:03 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 3 Feb 2026 01:49:30 +0000 (17:49 -0800)
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>
include/linux/ipv6.h
include/net/inet_sock.h
include/net/ipv6.h
net/ipv6/ip6_output.c
net/ipv6/raw.c

index 7294e4e89b797b1c45d1920686c2553e10badb81..20aae8357dd151e8c7d6972f41e77cebf1379177 100644 (file)
@@ -205,13 +205,6 @@ struct ipv6_mc_socklist;
 struct ipv6_ac_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 {
        /* Used in tx path (inet6_csk_route_socket(), ip6_xmit()) */
@@ -267,7 +260,6 @@ struct ipv6_pinfo {
 
        struct sk_buff          *pktoptions;
        struct sk_buff          *rxpmtu;
-       struct inet6_cork       cork;
 
        struct ipv6_mc_socklist __rcu *ipv6_mc_list;
        struct ipv6_ac_socklist *ipv6_ac_list;
index 903b2263ec8031565990dc52b921352e6a642b1a..7cdcbed3e5cbfd1a13698942da05b9ceabf72950 100644 (file)
@@ -159,6 +159,13 @@ static inline bool inet_sk_bound_dev_eq(const struct net *net,
 #endif
 }
 
+struct inet6_cork {
+       struct ipv6_txoptions *opt;
+       u8 hop_limit;
+       u8 tclass;
+       u8 dontfrag:1;
+};
+
 struct inet_cork {
        unsigned int            flags;
        __be32                  addr;
@@ -179,6 +186,9 @@ struct inet_cork {
 struct inet_cork_full {
        struct inet_cork        base;
        struct flowi            fl;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct inet6_cork       base6;
+#endif
 };
 
 struct ip_mc_socklist;
index a35f0a8114c093c65d3706f53b945cb426bd212b..c27b9d7aeb7cf4611a55abc133d6aaa0d1508a47 100644 (file)
@@ -1107,8 +1107,7 @@ void ip6_flush_pending_frames(struct sock *sk);
 int ip6_send_skb(struct sk_buff *skb);
 
 struct sk_buff *__ip6_make_skb(struct sock *sk, struct sk_buff_head *queue,
-                              struct inet_cork_full *cork,
-                              struct inet6_cork *v6_cork);
+                              struct inet_cork_full *cork);
 struct sk_buff *ip6_make_skb(struct sock *sk,
                             int getfrag(void *from, char *to, int offset,
                                         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)
 {
-       return __ip6_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork,
-                             &inet6_sk(sk)->cork);
+       return __ip6_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
 }
 
 int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst,
index f110701d1eca1e5f763d9138a43e11e92c15412f..e622a9e086cc0a3bc775fc87a379115bcf438e77 100644 (file)
@@ -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,
-                         struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6,
+                         struct ipcm6_cookie *ipc6,
                          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);
        unsigned int mtu, frag_size;
-       struct ipv6_txoptions *nopt, *opt = ipc6->opt;
 
        /* callers pass dst together with a reference, set it first so
         * 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,
                             struct sk_buff_head *queue,
                             struct inet_cork_full *cork_full,
-                            struct inet6_cork *v6_cork,
                             struct page_frag *pfrag,
                             int getfrag(void *from, char *to, int offset,
                                         int len, int odd, struct sk_buff *skb),
                             void *from, size_t length, int transhdrlen,
                             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 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;
        int 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 inet_sock *inet = inet_sk(sk);
-       struct ipv6_pinfo *np = inet6_sk(sk);
        int exthdrlen;
        int err;
 
@@ -1855,7 +1855,7 @@ int ip6_append_data(struct sock *sk,
                 * setup for corking
                 */
                dst_hold(&rt->dst);
-               err = ip6_setup_cork(sk, &inet->cork, &np->cork,
+               err = ip6_setup_cork(sk, &inet->cork,
                                     ipc6, rt);
                if (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,
-                                &np->cork, sk_page_frag(sk), getfrag,
+                                sk_page_frag(sk), getfrag,
                                 from, length, transhdrlen, flags);
 }
 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);
 }
 
-static void ip6_cork_release(struct inet_cork_full *cork,
-                            struct inet6_cork *v6_cork)
+static void ip6_cork_release(struct inet_cork_full *cork)
 {
+       struct inet6_cork *v6_cork = &cork->base6;
+
        if (unlikely(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_head *queue,
-                              struct inet_cork_full *cork,
-                              struct inet6_cork *v6_cork)
+                              struct inet_cork_full *cork)
 {
        struct sk_buff *skb, *tmp_skb;
        struct sk_buff **tail_skb;
        struct in6_addr *final_dst;
        struct net *net = sock_net(sk);
        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 flowi6 *fl6 = &cork->fl.u.ip6;
        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));
 
        final_dst = &fl6->daddr;
+       opt = cork->base6.opt;
        if (unlikely(opt)) {
                if (opt->opt_flen)
                        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);
        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_autoflowlabel(net, sk), fl6));
-       hdr->hop_limit = v6_cork->hop_limit;
+       hdr->hop_limit = cork->base6.hop_limit;
        hdr->nexthdr = proto;
        hdr->saddr = fl6->saddr;
        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);
        }
 
-       ip6_cork_release(cork, v6_cork);
+       ip6_cork_release(cork);
 out:
        return skb;
 }
@@ -2021,8 +2022,7 @@ EXPORT_SYMBOL_GPL(ip6_push_pending_frames);
 
 static void __ip6_flush_pending_frames(struct sock *sk,
                                       struct sk_buff_head *queue,
-                                      struct inet_cork_full *cork,
-                                      struct inet6_cork *v6_cork)
+                                      struct inet_cork_full *cork)
 {
        struct sk_buff *skb;
 
@@ -2033,13 +2033,13 @@ static void __ip6_flush_pending_frames(struct sock *sk,
                kfree_skb(skb);
        }
 
-       ip6_cork_release(cork, v6_cork);
+       ip6_cork_release(cork);
 }
 
 void ip6_flush_pending_frames(struct sock *sk)
 {
        __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);
 
@@ -2050,9 +2050,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
                             struct ipcm6_cookie *ipc6, struct rt6_info *rt,
                             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);
+       struct sk_buff_head queue;
        int err;
 
        if (flags & MSG_PROBE) {
@@ -2065,21 +2064,21 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
        cork->base.flags = 0;
        cork->base.addr = 0;
        cork->base.opt = NULL;
-       v6_cork.opt = NULL;
-       err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt);
+       cork->base6.opt = NULL;
+       err = ip6_setup_cork(sk, cork, ipc6, rt);
        if (err) {
-               ip6_cork_release(cork, &v6_cork);
+               ip6_cork_release(cork);
                return ERR_PTR(err);
        }
 
-       err = __ip6_append_data(sk, &queue, cork, &v6_cork,
+       err = __ip6_append_data(sk, &queue, cork,
                                &current->task_frag, getfrag, from,
                                length + exthdrlen, transhdrlen + exthdrlen,
                                flags);
        if (err) {
-               __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork);
+               __ip6_flush_pending_frames(sk, &queue, cork);
                return ERR_PTR(err);
        }
 
-       return __ip6_make_skb(sk, &queue, cork, &v6_cork);
+       return __ip6_make_skb(sk, &queue, cork);
 }
index b4cd05dba9b6d209bfb1024b7e1b0c703f906e5b..ee6beba03e9b498c8ea5b9e5834e26251f81e958 100644 (file)
@@ -529,7 +529,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
 
        offset = rp->offset;
        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;
 
        if (offset >= total_len - 1) {