Skip to content

Commit b17fc99

Browse files
Hans Schillstromhorms
authored andcommitted
IPVS: netns, ip_vs_stats and its procfs
The statistic counter locks for every packet are now removed, and that statistic is now per CPU, i.e. no locks needed. However summing is made in ip_vs_est into ip_vs_stats struct which is moved to ipvs struc. procfs, ip_vs_stats now have a "per cpu" count and a grand total. A new function seq_file_single_net() in ip_vs.h created for handling of single_open_net() since it does not place net ptr in a struct, like others. /var/lib/lxc # cat /proc/net/ip_vs_stats_percpu Total Incoming Outgoing Incoming Outgoing CPU Conns Packets Packets Bytes Bytes 0 0 3 1 9D 34 1 0 1 2 49 70 2 0 1 2 34 76 3 1 2 2 70 74 ~ 1 7 7 18A 18E Conns/s Pkts/s Pkts/s Bytes/s Bytes/s 0 0 0 0 0 *v3 ip_vs_stats reamains as before, instead ip_vs_stats_percpu is added. u64 seq lock added *v4 Bug correction inbytes and outbytes as own vars.. per_cpu counter for all stats now as suggested by Julian. [horms@verge.net.au: removed whitespace-change-only hunk] Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
1 parent f131315 commit b17fc99

File tree

5 files changed

+256
-61
lines changed

5 files changed

+256
-61
lines changed

include/net/ip_vs.h

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ static inline struct net *skb_sknet(struct sk_buff *skb)
9090
return &init_net;
9191
#endif
9292
}
93+
/*
94+
* This one needed for single_open_net since net is stored directly in
95+
* private not as a struct i.e. seq_file_net cant be used.
96+
*/
97+
static inline struct net *seq_file_single_net(struct seq_file *seq)
98+
{
99+
#ifdef CONFIG_NET_NS
100+
return (struct net *)seq->private;
101+
#else
102+
return &init_net;
103+
#endif
104+
}
93105

94106
/* Connections' size value needed by ip_vs_ctl.c */
95107
extern int ip_vs_conn_tab_size;
@@ -320,6 +332,23 @@ struct ip_vs_seq {
320332
before last resized pkt */
321333
};
322334

335+
/*
336+
* counters per cpu
337+
*/
338+
struct ip_vs_counters {
339+
__u32 conns; /* connections scheduled */
340+
__u32 inpkts; /* incoming packets */
341+
__u32 outpkts; /* outgoing packets */
342+
__u64 inbytes; /* incoming bytes */
343+
__u64 outbytes; /* outgoing bytes */
344+
};
345+
/*
346+
* Stats per cpu
347+
*/
348+
struct ip_vs_cpu_stats {
349+
struct ip_vs_counters ustats;
350+
struct u64_stats_sync syncp;
351+
};
323352

324353
/*
325354
* IPVS statistics objects
@@ -341,12 +370,28 @@ struct ip_vs_estimator {
341370
};
342371

343372
struct ip_vs_stats {
344-
struct ip_vs_stats_user ustats; /* statistics */
373+
struct ip_vs_stats_user ustats; /* statistics */
345374
struct ip_vs_estimator est; /* estimator */
346-
347-
spinlock_t lock; /* spin lock */
375+
struct ip_vs_cpu_stats *cpustats; /* per cpu counters */
376+
spinlock_t lock; /* spin lock */
348377
};
349378

379+
/*
380+
* Helper Macros for per cpu
381+
* ipvs->tot_stats->ustats.count
382+
*/
383+
#define IPVS_STAT_INC(ipvs, count) \
384+
__this_cpu_inc((ipvs)->ustats->count)
385+
386+
#define IPVS_STAT_ADD(ipvs, count, value) \
387+
do {\
388+
write_seqcount_begin(per_cpu_ptr((ipvs)->ustats_seq, \
389+
raw_smp_processor_id())); \
390+
__this_cpu_add((ipvs)->ustats->count, value); \
391+
write_seqcount_end(per_cpu_ptr((ipvs)->ustats_seq, \
392+
raw_smp_processor_id())); \
393+
} while (0)
394+
350395
struct dst_entry;
351396
struct iphdr;
352397
struct ip_vs_conn;

include/net/netns/ip_vs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ struct netns_ipvs {
6161
struct list_head sctp_apps[SCTP_APP_TAB_SIZE];
6262
spinlock_t sctp_app_lock;
6363
#endif
64+
/* ip_vs_ctl */
65+
struct ip_vs_stats *tot_stats; /* Statistics & est. */
66+
struct ip_vs_cpu_stats __percpu *cpustats; /* Stats per cpu */
67+
seqcount_t *ustats_seq; /* u64 read retry */
6468

6569
/* ip_vs_lblc */
6670
int sysctl_lblc_expiration;

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,28 @@ static inline void
115115
ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
116116
{
117117
struct ip_vs_dest *dest = cp->dest;
118+
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
119+
118120
if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
119-
spin_lock(&dest->stats.lock);
120-
dest->stats.ustats.inpkts++;
121-
dest->stats.ustats.inbytes += skb->len;
122-
spin_unlock(&dest->stats.lock);
123-
124-
spin_lock(&dest->svc->stats.lock);
125-
dest->svc->stats.ustats.inpkts++;
126-
dest->svc->stats.ustats.inbytes += skb->len;
127-
spin_unlock(&dest->svc->stats.lock);
128-
129-
spin_lock(&ip_vs_stats.lock);
130-
ip_vs_stats.ustats.inpkts++;
131-
ip_vs_stats.ustats.inbytes += skb->len;
132-
spin_unlock(&ip_vs_stats.lock);
121+
struct ip_vs_cpu_stats *s;
122+
123+
s = this_cpu_ptr(dest->stats.cpustats);
124+
s->ustats.inpkts++;
125+
u64_stats_update_begin(&s->syncp);
126+
s->ustats.inbytes += skb->len;
127+
u64_stats_update_end(&s->syncp);
128+
129+
s = this_cpu_ptr(dest->svc->stats.cpustats);
130+
s->ustats.inpkts++;
131+
u64_stats_update_begin(&s->syncp);
132+
s->ustats.inbytes += skb->len;
133+
u64_stats_update_end(&s->syncp);
134+
135+
s = this_cpu_ptr(ipvs->cpustats);
136+
s->ustats.inpkts++;
137+
u64_stats_update_begin(&s->syncp);
138+
s->ustats.inbytes += skb->len;
139+
u64_stats_update_end(&s->syncp);
133140
}
134141
}
135142

@@ -138,39 +145,46 @@ static inline void
138145
ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
139146
{
140147
struct ip_vs_dest *dest = cp->dest;
148+
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
149+
141150
if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
142-
spin_lock(&dest->stats.lock);
143-
dest->stats.ustats.outpkts++;
144-
dest->stats.ustats.outbytes += skb->len;
145-
spin_unlock(&dest->stats.lock);
146-
147-
spin_lock(&dest->svc->stats.lock);
148-
dest->svc->stats.ustats.outpkts++;
149-
dest->svc->stats.ustats.outbytes += skb->len;
150-
spin_unlock(&dest->svc->stats.lock);
151-
152-
spin_lock(&ip_vs_stats.lock);
153-
ip_vs_stats.ustats.outpkts++;
154-
ip_vs_stats.ustats.outbytes += skb->len;
155-
spin_unlock(&ip_vs_stats.lock);
151+
struct ip_vs_cpu_stats *s;
152+
153+
s = this_cpu_ptr(dest->stats.cpustats);
154+
s->ustats.outpkts++;
155+
u64_stats_update_begin(&s->syncp);
156+
s->ustats.outbytes += skb->len;
157+
u64_stats_update_end(&s->syncp);
158+
159+
s = this_cpu_ptr(dest->svc->stats.cpustats);
160+
s->ustats.outpkts++;
161+
u64_stats_update_begin(&s->syncp);
162+
s->ustats.outbytes += skb->len;
163+
u64_stats_update_end(&s->syncp);
164+
165+
s = this_cpu_ptr(ipvs->cpustats);
166+
s->ustats.outpkts++;
167+
u64_stats_update_begin(&s->syncp);
168+
s->ustats.outbytes += skb->len;
169+
u64_stats_update_end(&s->syncp);
156170
}
157171
}
158172

159173

160174
static inline void
161175
ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
162176
{
163-
spin_lock(&cp->dest->stats.lock);
164-
cp->dest->stats.ustats.conns++;
165-
spin_unlock(&cp->dest->stats.lock);
177+
struct netns_ipvs *ipvs = net_ipvs(svc->net);
178+
struct ip_vs_cpu_stats *s;
166179

167-
spin_lock(&svc->stats.lock);
168-
svc->stats.ustats.conns++;
169-
spin_unlock(&svc->stats.lock);
180+
s = this_cpu_ptr(cp->dest->stats.cpustats);
181+
s->ustats.conns++;
170182

171-
spin_lock(&ip_vs_stats.lock);
172-
ip_vs_stats.ustats.conns++;
173-
spin_unlock(&ip_vs_stats.lock);
183+
s = this_cpu_ptr(svc->stats.cpustats);
184+
s->ustats.conns++;
185+
186+
s = this_cpu_ptr(ipvs->cpustats);
187+
s->ustats.conns++;
174188
}
175189

176190

@@ -1841,7 +1855,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
18411855
},
18421856
#endif
18431857
};
1844-
18451858
/*
18461859
* Initialize IP Virtual Server netns mem.
18471860
*/

0 commit comments

Comments
 (0)