Skip to content

Commit 3d8068c

Browse files
committed
Merge branch 'net-dst_entry-shrink'
David Miller says: ==================== net: Significantly shrink the size of routes. Through a combination of several things, our route structures are larger than they need to be. Mostly this stems from having members in dst_entry which are only used by one class of routes. So the majority of the work in this series is about "un-commoning" these members and pushing them into the type specific structures. Unfortunately, IPSEC needed the most surgery. The majority of the changes here had to do with bundle creation and management. The other issue is the refcount alignment in dst_entry. Once we get rid of the not-so-common members, it really opens the door to removing that alignment entirely. I think the new layout looks really nice, so I'll reproduce it here: struct net_device *dev; struct dst_ops *ops; unsigned long _metrics; unsigned long expires; struct xfrm_state *xfrm; int (*input)(struct sk_buff *); int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); unsigned short flags; short obsolete; unsigned short header_len; unsigned short trailer_len; atomic_t __refcnt; int __use; unsigned long lastuse; struct lwtunnel_state *lwtstate; struct rcu_head rcu_head; short error; short __pad; __u32 tclassid; (This is for 64-bit, on 32-bit the __refcnt comes at the very end) So, the good news: 1) struct dst_entry shrinks from 160 to 112 bytes. 2) struct rtable shrinks from 216 to 168 bytes. 3) struct rt6_info shrinks from 384 to 320 bytes. Enjoy. v2: Collapse some patches logically based upon feedback. Fix the strange patch #7. v3: xfrm_dst_path() needs inline keyword Properly align __refcnt on 32-bit. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b78a6aa + 7149f81 commit 3d8068c

File tree

20 files changed

+204
-183
lines changed

20 files changed

+204
-183
lines changed

include/net/dn_route.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
6969
*/
7070
struct dn_route {
7171
struct dst_entry dst;
72+
struct dn_route __rcu *dn_next;
7273

7374
struct neighbour *n;
7475

include/net/dst.h

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,9 @@ struct sk_buff;
3434

3535
struct dst_entry {
3636
struct net_device *dev;
37-
struct rcu_head rcu_head;
38-
struct dst_entry *child;
3937
struct dst_ops *ops;
4038
unsigned long _metrics;
4139
unsigned long expires;
42-
struct dst_entry *path;
43-
struct dst_entry *from;
4440
#ifdef CONFIG_XFRM
4541
struct xfrm_state *xfrm;
4642
#else
@@ -59,8 +55,6 @@ struct dst_entry {
5955
#define DST_XFRM_QUEUE 0x0040
6056
#define DST_METADATA 0x0080
6157

62-
short error;
63-
6458
/* A non-zero value of dst->obsolete forces by-hand validation
6559
* of the route entry. Positive values are set by the generic
6660
* dst layer to indicate that the entry has been forcefully
@@ -76,35 +70,24 @@ struct dst_entry {
7670
#define DST_OBSOLETE_KILL -2
7771
unsigned short header_len; /* more space at head required */
7872
unsigned short trailer_len; /* space to reserve at tail */
79-
unsigned short __pad3;
8073

81-
#ifdef CONFIG_IP_ROUTE_CLASSID
82-
__u32 tclassid;
83-
#else
84-
__u32 __pad2;
85-
#endif
86-
87-
#ifdef CONFIG_64BIT
88-
/*
89-
* Align __refcnt to a 64 bytes alignment
90-
* (L1_CACHE_SIZE would be too much)
91-
*/
92-
long __pad_to_align_refcnt[2];
93-
#endif
9474
/*
9575
* __refcnt wants to be on a different cache line from
9676
* input/output/ops or performance tanks badly
9777
*/
98-
atomic_t __refcnt; /* client references */
78+
#ifdef CONFIG_64BIT
79+
atomic_t __refcnt; /* 64-bit offset 64 */
80+
#endif
9981
int __use;
10082
unsigned long lastuse;
10183
struct lwtunnel_state *lwtstate;
102-
union {
103-
struct dst_entry *next;
104-
struct rtable __rcu *rt_next;
105-
struct rt6_info __rcu *rt6_next;
106-
struct dn_route __rcu *dn_next;
107-
};
84+
struct rcu_head rcu_head;
85+
short error;
86+
short __pad;
87+
__u32 tclassid;
88+
#ifndef CONFIG_64BIT
89+
atomic_t __refcnt; /* 32-bit offset 64 */
90+
#endif
10891
};
10992

11093
struct dst_metrics {
@@ -250,7 +233,7 @@ static inline void dst_hold(struct dst_entry *dst)
250233
{
251234
/*
252235
* If your kernel compilation stops here, please check
253-
* __pad_to_align_refcnt declaration in struct dst_entry
236+
* the placement of __refcnt in struct dst_entry
254237
*/
255238
BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
256239
WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0);

include/net/ip6_fib.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ struct rt6_exception {
129129

130130
struct rt6_info {
131131
struct dst_entry dst;
132+
struct rt6_info __rcu *rt6_next;
133+
struct rt6_info *from;
132134

133135
/*
134136
* Tail elements of dst_entry (__refcnt etc.)
@@ -176,11 +178,11 @@ struct rt6_info {
176178

177179
#define for_each_fib6_node_rt_rcu(fn) \
178180
for (rt = rcu_dereference((fn)->leaf); rt; \
179-
rt = rcu_dereference(rt->dst.rt6_next))
181+
rt = rcu_dereference(rt->rt6_next))
180182

181183
#define for_each_fib6_walker_rt(w) \
182184
for (rt = (w)->leaf; rt; \
183-
rt = rcu_dereference_protected(rt->dst.rt6_next, 1))
185+
rt = rcu_dereference_protected(rt->rt6_next, 1))
184186

185187
static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
186188
{
@@ -203,11 +205,9 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
203205
{
204206
struct rt6_info *rt;
205207

206-
for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
207-
rt = (struct rt6_info *)rt->dst.from);
208+
for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); rt = rt->from);
208209
if (rt && rt != rt0)
209210
rt0->dst.expires = rt->dst.expires;
210-
211211
dst_set_expires(&rt0->dst, timeout);
212212
rt0->rt6i_flags |= RTF_EXPIRES;
213213
}
@@ -242,8 +242,8 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt)
242242
u32 cookie = 0;
243243

244244
if (rt->rt6i_flags & RTF_PCPU ||
245-
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from))
246-
rt = (struct rt6_info *)(rt->dst.from);
245+
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
246+
rt = rt->from;
247247

248248
rt6_get_cookie_safe(rt, &cookie);
249249

include/net/xfrm.h

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ static inline bool xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_c
968968

969969
/* A struct encoding bundle of transformations to apply to some set of flow.
970970
*
971-
* dst->child points to the next element of bundle.
971+
* xdst->child points to the next element of bundle.
972972
* dst->xfrm points to an instanse of transformer.
973973
*
974974
* Due to unfortunate limitations of current routing cache, which we
@@ -984,6 +984,8 @@ struct xfrm_dst {
984984
struct rt6_info rt6;
985985
} u;
986986
struct dst_entry *route;
987+
struct dst_entry *child;
988+
struct dst_entry *path;
987989
struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
988990
int num_pols, num_xfrms;
989991
u32 xfrm_genid;
@@ -994,7 +996,35 @@ struct xfrm_dst {
994996
u32 path_cookie;
995997
};
996998

999+
static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
1000+
{
9971001
#ifdef CONFIG_XFRM
1002+
if (dst->xfrm) {
1003+
const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
1004+
1005+
return xdst->path;
1006+
}
1007+
#endif
1008+
return (struct dst_entry *) dst;
1009+
}
1010+
1011+
static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
1012+
{
1013+
#ifdef CONFIG_XFRM
1014+
if (dst->xfrm) {
1015+
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
1016+
return xdst->child;
1017+
}
1018+
#endif
1019+
return NULL;
1020+
}
1021+
1022+
#ifdef CONFIG_XFRM
1023+
static inline void xfrm_dst_set_child(struct xfrm_dst *xdst, struct dst_entry *child)
1024+
{
1025+
xdst->child = child;
1026+
}
1027+
9981028
static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
9991029
{
10001030
xfrm_pols_put(xdst->pols, xdst->num_pols);
@@ -1866,12 +1896,14 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
18661896
static inline bool xfrm_dst_offload_ok(struct dst_entry *dst)
18671897
{
18681898
struct xfrm_state *x = dst->xfrm;
1899+
struct xfrm_dst *xdst;
18691900

18701901
if (!x || !x->type_offload)
18711902
return false;
18721903

1873-
if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) &&
1874-
!dst->child->xfrm)
1904+
xdst = (struct xfrm_dst *) dst;
1905+
if (x->xso.offload_handle && (x->xso.dev == xfrm_dst_path(dst)->dev) &&
1906+
!xdst->child->xfrm)
18751907
return true;
18761908

18771909
return false;

net/bridge/br_nf_core.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ void br_netfilter_rtable_init(struct net_bridge *br)
7878

7979
atomic_set(&rt->dst.__refcnt, 1);
8080
rt->dst.dev = br->dev;
81-
rt->dst.path = &rt->dst;
8281
dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
8382
rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE;
8483
rt->dst.ops = &fake_dst_ops;

net/core/dst.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/sched.h>
2222
#include <linux/prefetch.h>
2323
#include <net/lwtunnel.h>
24+
#include <net/xfrm.h>
2425

2526
#include <net/dst.h>
2627
#include <net/dst_metadata.h>
@@ -62,15 +63,12 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
6263
struct net_device *dev, int initial_ref, int initial_obsolete,
6364
unsigned short flags)
6465
{
65-
dst->child = NULL;
6666
dst->dev = dev;
6767
if (dev)
6868
dev_hold(dev);
6969
dst->ops = ops;
7070
dst_init_metrics(dst, dst_default_metrics.metrics, true);
7171
dst->expires = 0UL;
72-
dst->path = dst;
73-
dst->from = NULL;
7472
#ifdef CONFIG_XFRM
7573
dst->xfrm = NULL;
7674
#endif
@@ -88,7 +86,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
8886
dst->__use = 0;
8987
dst->lastuse = jiffies;
9088
dst->flags = flags;
91-
dst->next = NULL;
9289
if (!(flags & DST_NOCOUNT))
9390
dst_entries_add(ops, 1);
9491
}
@@ -116,12 +113,17 @@ EXPORT_SYMBOL(dst_alloc);
116113

117114
struct dst_entry *dst_destroy(struct dst_entry * dst)
118115
{
119-
struct dst_entry *child;
116+
struct dst_entry *child = NULL;
120117

121118
smp_rmb();
122119

123-
child = dst->child;
120+
#ifdef CONFIG_XFRM
121+
if (dst->xfrm) {
122+
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
124123

124+
child = xdst->child;
125+
}
126+
#endif
125127
if (!(dst->flags & DST_NOCOUNT))
126128
dst_entries_add(dst->ops, -1);
127129

net/core/pktgen.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ struct pktgen_dev {
399399
__u8 ipsmode; /* IPSEC mode (config) */
400400
__u8 ipsproto; /* IPSEC type (config) */
401401
__u32 spi;
402-
struct dst_entry dst;
402+
struct xfrm_dst xdst;
403403
struct dst_ops dstops;
404404
#endif
405405
char result[512];
@@ -2609,7 +2609,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
26092609
* supports both transport/tunnel mode + ESP/AH type.
26102610
*/
26112611
if ((x->props.mode == XFRM_MODE_TUNNEL) && (pkt_dev->spi != 0))
2612-
skb->_skb_refdst = (unsigned long)&pkt_dev->dst | SKB_DST_NOREF;
2612+
skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF;
26132613

26142614
rcu_read_lock_bh();
26152615
err = x->outer_mode->output(x, skb);
@@ -3742,10 +3742,10 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
37423742
* performance under such circumstance.
37433743
*/
37443744
pkt_dev->dstops.family = AF_INET;
3745-
pkt_dev->dst.dev = pkt_dev->odev;
3746-
dst_init_metrics(&pkt_dev->dst, pktgen_dst_metrics, false);
3747-
pkt_dev->dst.child = &pkt_dev->dst;
3748-
pkt_dev->dst.ops = &pkt_dev->dstops;
3745+
pkt_dev->xdst.u.dst.dev = pkt_dev->odev;
3746+
dst_init_metrics(&pkt_dev->xdst.u.dst, pktgen_dst_metrics, false);
3747+
pkt_dev->xdst.child = &pkt_dev->xdst.u.dst;
3748+
pkt_dev->xdst.u.dst.ops = &pkt_dev->dstops;
37493749
#endif
37503750

37513751
return add_dev_to_thread(t, pkt_dev);

0 commit comments

Comments
 (0)