diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 65cd243a7..713c34997 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -142,14 +143,22 @@ struct re_crypto_context { const struct re_hmac *hmac; }; +struct rtpengine_stats_a { + atomic64_t packets; + atomic64_t bytes; + atomic64_t errors; +}; +struct rtpengine_rtp_stats_a { + atomic64_t packets; + atomic64_t bytes; +}; struct rtpengine_target { atomic_t refcnt; u_int32_t table; struct rtpengine_target_info target; - spinlock_t stats_lock; - struct rtpengine_stats stats; - struct rtpengine_rtp_stats rtp_stats[NUM_PAYLOAD_TYPES]; + struct rtpengine_stats_a stats; + struct rtpengine_rtp_stats_a rtp_stats[NUM_PAYLOAD_TYPES]; struct re_crypto_context decrypt; struct re_crypto_context encrypt; @@ -817,10 +826,9 @@ static ssize_t proc_blist_read(struct file *f, char __user *b, size_t l, loff_t u_int32_t id; struct rtpengine_table *t; struct rtpengine_list_entry op; - int err; + int err, port, i; struct rtpengine_target *g; unsigned long flags; - int port; if (l != sizeof(op)) return -EINVAL; @@ -843,10 +851,14 @@ static ssize_t proc_blist_read(struct file *f, char __user *b, size_t l, loff_t memset(&op, 0, sizeof(op)); memcpy(&op.target, &g->target, sizeof(op.target)); - spin_lock_irqsave(&g->stats_lock, flags); - memcpy(&op.stats, &g->stats, sizeof(op.stats)); - memcpy(&op.rtp_stats, &g->rtp_stats, sizeof(op.rtp_stats)); - spin_unlock_irqrestore(&g->stats_lock, flags); + op.stats.packets = atomic64_read(&g->stats.packets); + op.stats.bytes = atomic64_read(&g->stats.bytes); + op.stats.errors = atomic64_read(&g->stats.errors); + + for (i = 0; i < g->target.num_payload_types; i++) { + op.rtp_stats[i].packets = atomic64_read(&g->rtp_stats[i].packets); + op.rtp_stats[i].bytes = atomic64_read(&g->rtp_stats[i].bytes); + } spin_lock_irqsave(&g->decrypt.lock, flags); op.target.decrypt.last_index = g->target.decrypt.last_index; @@ -973,7 +985,6 @@ static void proc_list_crypto_print(struct seq_file *f, struct re_crypto_context static int proc_list_show(struct seq_file *f, void *v) { struct rtpengine_target *g = v; - unsigned long flags; int i; seq_printf(f, "port %5u:\n", g->target.target_port); @@ -983,14 +994,15 @@ static int proc_list_show(struct seq_file *f, void *v) { proc_list_addr_print(f, "expect", &g->target.expected_src); if (g->target.src_mismatch > 0 && g->target.src_mismatch <= ARRAY_SIZE(re_msm_strings)) seq_printf(f, " src mismatch action: %s\n", re_msm_strings[g->target.src_mismatch]); - spin_lock_irqsave(&g->stats_lock, flags); seq_printf(f, " stats: %20llu bytes, %20llu packets, %20llu errors\n", - g->stats.bytes, g->stats.packets, g->stats.errors); + (unsigned long long) atomic64_read(&g->stats.bytes), + (unsigned long long) atomic64_read(&g->stats.packets), + (unsigned long long) atomic64_read(&g->stats.errors)); for (i = 0; i < g->target.num_payload_types; i++) seq_printf(f, " RTP payload type %3u: %20llu bytes, %20llu packets\n", g->target.payload_types[i], - g->rtp_stats[i].bytes, g->rtp_stats[i].packets); - spin_unlock_irqrestore(&g->stats_lock, flags); + (unsigned long long) atomic64_read(&g->rtp_stats[i].bytes), + (unsigned long long) atomic64_read(&g->rtp_stats[i].packets)); proc_list_crypto_print(f, &g->decrypt, &g->target.decrypt, "decryption (incoming)"); proc_list_crypto_print(f, &g->encrypt, &g->target.encrypt, "encryption (outgoing)"); if (g->target.rtcp_mux) @@ -1381,7 +1393,7 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i struct rtpengine_target *g; struct re_bucket *b, *ba = NULL; struct rtpengine_target *og = NULL; - int err; + int err, j; unsigned long flags; if (!i->target_port) @@ -1412,7 +1424,6 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i memset(g, 0, sizeof(*g)); g->table = t->id; atomic_set(&g->refcnt, 1); - spin_lock_init(&g->stats_lock); spin_lock_init(&g->decrypt.lock); spin_lock_init(&g->encrypt.lock); memcpy(&g->target, i, sizeof(*i)); @@ -1460,10 +1471,14 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i if (!og) goto fail4; - spin_lock(&og->stats_lock); /* nested lock! irqs are disabled already */ - memcpy(&g->stats, &og->stats, sizeof(g->stats)); - memcpy(&g->rtp_stats, &og->rtp_stats, sizeof(g->rtp_stats)); - spin_unlock(&og->stats_lock); + atomic64_set(&g->stats.packets, atomic64_read(&og->stats.packets)); + atomic64_set(&g->stats.bytes, atomic64_read(&og->stats.bytes)); + atomic64_set(&g->stats.errors, atomic64_read(&og->stats.errors)); + + for (j = 0; j < NUM_PAYLOAD_TYPES; j++) { + atomic64_set(&g->rtp_stats[j].packets, atomic64_read(&og->rtp_stats[j].packets)); + atomic64_set(&g->rtp_stats[j].bytes, atomic64_read(&og->rtp_stats[j].bytes)); + } } else { err = -EEXIST; @@ -2175,7 +2190,6 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct sk_buff *skb2; int err, rtp_pt_idx = -2; unsigned int datalen; - unsigned long flags; u_int32_t *u32; struct rtp_parsed rtp; u_int64_t pkt_idx = 0, pkt_idx_u; @@ -2272,11 +2286,8 @@ not_rtp: DBG("sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); skb2 = skb_copy(skb, GFP_ATOMIC); err = send_proxy_packet(skb2, &g->target.src_addr, &g->target.mirror_addr, g->target.tos); - if (err) { - spin_lock_irqsave(&g->stats_lock, flags); - g->stats.errors++; - spin_unlock_irqrestore(&g->stats_lock, flags); - } + if (err) + atomic64_inc(&g->stats.errors); } if (rtp.ok) { @@ -2288,22 +2299,20 @@ not_rtp: err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos); out: - spin_lock_irqsave(&g->stats_lock, flags); if (err) - g->stats.errors++; + atomic64_inc(&g->stats.errors); else { - g->stats.packets++; - g->stats.bytes += datalen; + atomic64_inc(&g->stats.packets); + atomic64_add(datalen, &g->stats.bytes); } if (rtp_pt_idx >= 0) { - g->rtp_stats[rtp_pt_idx].packets++; - g->rtp_stats[rtp_pt_idx].bytes += datalen; + atomic64_inc(&g->rtp_stats[rtp_pt_idx].packets); + atomic64_add(datalen, &g->rtp_stats[rtp_pt_idx].bytes); } else if (rtp_pt_idx == -2) /* not RTP */ ; else if (rtp_pt_idx == -1) - g->stats.errors++; - spin_unlock_irqrestore(&g->stats_lock, flags); + atomic64_inc(&g->stats.errors); target_push(g); table_push(t); @@ -2311,9 +2320,7 @@ out: return NF_DROP; skip_error: - spin_lock_irqsave(&g->stats_lock, flags); - g->stats.errors++; - spin_unlock_irqrestore(&g->stats_lock, flags); + atomic64_inc(&g->stats.errors); skip1: target_push(g); skip2: