|
|
|
@ -18,6 +18,7 @@ |
|
|
|
#include <linux/proc_fs.h> |
|
|
|
#include <linux/spinlock.h> |
|
|
|
#include <linux/bsearch.h> |
|
|
|
#include <linux/atomic.h> |
|
|
|
#include <linux/netfilter_ipv4/ip_tables.h> |
|
|
|
#include <linux/netfilter_ipv4.h> |
|
|
|
#include <linux/netfilter_ipv6.h> |
|
|
|
@ -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: |
|
|
|
|