Skip to content

Commit

Permalink
IPVS: netns, ip_vs_stats and its procfs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hans Schillstrom authored and Simon Horman committed Jan 13, 2011
1 parent f131315 commit b17fc99
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 61 deletions.
51 changes: 48 additions & 3 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ static inline struct net *skb_sknet(struct sk_buff *skb)
return &init_net;
#endif
}
/*
* This one needed for single_open_net since net is stored directly in
* private not as a struct i.e. seq_file_net cant be used.
*/
static inline struct net *seq_file_single_net(struct seq_file *seq)
{
#ifdef CONFIG_NET_NS
return (struct net *)seq->private;
#else
return &init_net;
#endif
}

/* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size;
Expand Down Expand Up @@ -320,6 +332,23 @@ struct ip_vs_seq {
before last resized pkt */
};

/*
* counters per cpu
*/
struct ip_vs_counters {
__u32 conns; /* connections scheduled */
__u32 inpkts; /* incoming packets */
__u32 outpkts; /* outgoing packets */
__u64 inbytes; /* incoming bytes */
__u64 outbytes; /* outgoing bytes */
};
/*
* Stats per cpu
*/
struct ip_vs_cpu_stats {
struct ip_vs_counters ustats;
struct u64_stats_sync syncp;
};

/*
* IPVS statistics objects
Expand All @@ -341,12 +370,28 @@ struct ip_vs_estimator {
};

struct ip_vs_stats {
struct ip_vs_stats_user ustats; /* statistics */
struct ip_vs_stats_user ustats; /* statistics */
struct ip_vs_estimator est; /* estimator */

spinlock_t lock; /* spin lock */
struct ip_vs_cpu_stats *cpustats; /* per cpu counters */
spinlock_t lock; /* spin lock */
};

/*
* Helper Macros for per cpu
* ipvs->tot_stats->ustats.count
*/
#define IPVS_STAT_INC(ipvs, count) \
__this_cpu_inc((ipvs)->ustats->count)

#define IPVS_STAT_ADD(ipvs, count, value) \
do {\
write_seqcount_begin(per_cpu_ptr((ipvs)->ustats_seq, \
raw_smp_processor_id())); \
__this_cpu_add((ipvs)->ustats->count, value); \
write_seqcount_end(per_cpu_ptr((ipvs)->ustats_seq, \
raw_smp_processor_id())); \
} while (0)

struct dst_entry;
struct iphdr;
struct ip_vs_conn;
Expand Down
4 changes: 4 additions & 0 deletions include/net/netns/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ struct netns_ipvs {
struct list_head sctp_apps[SCTP_APP_TAB_SIZE];
spinlock_t sctp_app_lock;
#endif
/* ip_vs_ctl */
struct ip_vs_stats *tot_stats; /* Statistics & est. */
struct ip_vs_cpu_stats __percpu *cpustats; /* Stats per cpu */
seqcount_t *ustats_seq; /* u64 read retry */

/* ip_vs_lblc */
int sysctl_lblc_expiration;
Expand Down
89 changes: 51 additions & 38 deletions net/netfilter/ipvs/ip_vs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,21 +115,28 @@ static inline void
ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
{
struct ip_vs_dest *dest = cp->dest;
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));

if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
spin_lock(&dest->stats.lock);
dest->stats.ustats.inpkts++;
dest->stats.ustats.inbytes += skb->len;
spin_unlock(&dest->stats.lock);

spin_lock(&dest->svc->stats.lock);
dest->svc->stats.ustats.inpkts++;
dest->svc->stats.ustats.inbytes += skb->len;
spin_unlock(&dest->svc->stats.lock);

spin_lock(&ip_vs_stats.lock);
ip_vs_stats.ustats.inpkts++;
ip_vs_stats.ustats.inbytes += skb->len;
spin_unlock(&ip_vs_stats.lock);
struct ip_vs_cpu_stats *s;

s = this_cpu_ptr(dest->stats.cpustats);
s->ustats.inpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.inbytes += skb->len;
u64_stats_update_end(&s->syncp);

s = this_cpu_ptr(dest->svc->stats.cpustats);
s->ustats.inpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.inbytes += skb->len;
u64_stats_update_end(&s->syncp);

s = this_cpu_ptr(ipvs->cpustats);
s->ustats.inpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.inbytes += skb->len;
u64_stats_update_end(&s->syncp);
}
}

Expand All @@ -138,39 +145,46 @@ static inline void
ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
{
struct ip_vs_dest *dest = cp->dest;
struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));

if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
spin_lock(&dest->stats.lock);
dest->stats.ustats.outpkts++;
dest->stats.ustats.outbytes += skb->len;
spin_unlock(&dest->stats.lock);

spin_lock(&dest->svc->stats.lock);
dest->svc->stats.ustats.outpkts++;
dest->svc->stats.ustats.outbytes += skb->len;
spin_unlock(&dest->svc->stats.lock);

spin_lock(&ip_vs_stats.lock);
ip_vs_stats.ustats.outpkts++;
ip_vs_stats.ustats.outbytes += skb->len;
spin_unlock(&ip_vs_stats.lock);
struct ip_vs_cpu_stats *s;

s = this_cpu_ptr(dest->stats.cpustats);
s->ustats.outpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.outbytes += skb->len;
u64_stats_update_end(&s->syncp);

s = this_cpu_ptr(dest->svc->stats.cpustats);
s->ustats.outpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.outbytes += skb->len;
u64_stats_update_end(&s->syncp);

s = this_cpu_ptr(ipvs->cpustats);
s->ustats.outpkts++;
u64_stats_update_begin(&s->syncp);
s->ustats.outbytes += skb->len;
u64_stats_update_end(&s->syncp);
}
}


static inline void
ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
{
spin_lock(&cp->dest->stats.lock);
cp->dest->stats.ustats.conns++;
spin_unlock(&cp->dest->stats.lock);
struct netns_ipvs *ipvs = net_ipvs(svc->net);
struct ip_vs_cpu_stats *s;

spin_lock(&svc->stats.lock);
svc->stats.ustats.conns++;
spin_unlock(&svc->stats.lock);
s = this_cpu_ptr(cp->dest->stats.cpustats);
s->ustats.conns++;

spin_lock(&ip_vs_stats.lock);
ip_vs_stats.ustats.conns++;
spin_unlock(&ip_vs_stats.lock);
s = this_cpu_ptr(svc->stats.cpustats);
s->ustats.conns++;

s = this_cpu_ptr(ipvs->cpustats);
s->ustats.conns++;
}


Expand Down Expand Up @@ -1841,7 +1855,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
},
#endif
};

/*
* Initialize IP Virtual Server netns mem.
*/
Expand Down
Loading

0 comments on commit b17fc99

Please sign in to comment.