From c8d014c1f6b35cb8bb3f02ab46ebfa07c2dda689 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 27 Jul 2026 09:38:38 -0400 Subject: [PATCH] MT#55283 add zero-copy stats Change-Id: I743ad3dbaee397f79db13b3e0929667187607884 --- kernel-module/nft_rtpengine.c | 57 ++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/kernel-module/nft_rtpengine.c b/kernel-module/nft_rtpengine.c index dbeb13dd9..8928d7eeb 100644 --- a/kernel-module/nft_rtpengine.c +++ b/kernel-module/nft_rtpengine.c @@ -304,9 +304,9 @@ static int srtcp_decrypt_aes_gcm(struct re_crypto_context *, struct rtpengine_sr static int send_proxy_packet_output(struct sk_buff *skb, struct rtpengine_target *g, int rtp_pt_idx, struct rtpengine_output *o, struct rtp_parsed *rtp, int ssrc_idx, - struct net *); + struct net *, struct rtpengine_table *t); static int send_proxy_packet(struct sk_buff *skb, const struct re_address *src, const struct re_address *dst, - unsigned char tos, struct net *); + unsigned char tos, struct net *, struct rtpengine_table *); static uint32_t proxy_packet_srtp_encrypt(struct sk_buff *skb, struct re_crypto_context *ctx, struct rtpengine_srtp *srtp, struct rtp_parsed *rtp, int ssrc_idx, @@ -489,6 +489,9 @@ struct rtpengine_table { struct global_stats_counter *rtpe_stats; + atomic64_t skb_refs; + atomic64_t skb_copies; + spinlock_t player_lock; struct list_head play_streams; unsigned int num_play_streams; @@ -1447,6 +1450,9 @@ static int proc_status_show(struct seq_file *m, void *v) { seq_printf(m, "Targets: %u\n", t->num_targets); read_unlock_irqrestore(&t->target_lock, flags); + seq_printf(m, "Skb refs: %lu\n", (unsigned long) atomic64_read(&t->skb_refs)); + seq_printf(m, "Skb copies: %lu\n", (unsigned long) atomic64_read(&t->skb_copies)); + // unlocked/unsafe read seq_printf(m, "Players: %u\n", t->num_play_streams); seq_printf(m, "PStreams: %u\n", t->num_packet_streams); @@ -4089,7 +4095,7 @@ static bool re_ring_send(const void *payload, size_t length, data = skb_put(skb, length); memcpy(data, payload, length); - send_proxy_packet(skb, src, dst, tos, NULL); + send_proxy_packet(skb, src, dst, tos, NULL, NULL); return true; } @@ -4128,7 +4134,7 @@ static int re_ring_sender(void *p) { struct rtpengine_buf_slot *slot = &slots[s]; struct rtpengine_buf_metadata *metaslot = &metadata[s]; - if (! re_ring_send(slot->steps[0].offset + buf->head, slot->steps[0].length, + if (!re_ring_send(slot->steps[0].offset + buf->head, slot->steps[0].length, &metaslot->src, &metaslot->dst, metaslot->tos)) atomic_inc(&pair->errors); } @@ -4501,7 +4507,7 @@ static void play_stream_send_packet(struct re_play_stream *stream, struct re_pla rtp.rtcp = 0; proxy_packet_srtp_encrypt(skb, &stream->encrypt, &stream->info.encrypt, &rtp, 0, &stream->info.ssrc_stats); - send_proxy_packet(skb, &stream->info.src_addr, &stream->info.dst_addr, stream->info.tos, NULL); + send_proxy_packet(skb, &stream->info.src_addr, &stream->info.dst_addr, stream->info.tos, NULL, NULL); atomic64_inc(&stream->info.stats->packets); atomic64_add(packet->len, &stream->info.stats->bytes); @@ -5425,7 +5431,7 @@ static ssize_t proc_control_read(struct file *file, char __user *ubuf, size_t bu static int send_proxy_packet4(struct sk_buff *skb, const struct re_address *src, const struct re_address *dst, - unsigned char tos, struct net *net) + unsigned char tos, struct net *net, struct rtpengine_table *t) { struct iphdr *ih; struct udphdr *uh; @@ -5443,6 +5449,8 @@ static int send_proxy_packet4(struct sk_buff *skb, const struct re_address *src, struct sk_buff *skb2 = skb_copy_expand(skb, MAX_HEADER, MAX_SKB_TAIL_ROOM, GFP_ATOMIC); if (!skb2) goto drop; + if (t) + atomic64_inc(&t->skb_copies); kfree_skb(skb); skb = skb2; } @@ -5540,7 +5548,7 @@ drop: static int send_proxy_packet6(struct sk_buff *skb, const struct re_address *src, const struct re_address *dst, - unsigned char tos, struct net *net) + unsigned char tos, struct net *net, struct rtpengine_table *t) { struct ipv6hdr *ih; struct udphdr *uh; @@ -5559,6 +5567,8 @@ static int send_proxy_packet6(struct sk_buff *skb, const struct re_address *src, struct sk_buff *skb2 = skb_copy_expand(skb, MAX_HEADER, MAX_SKB_TAIL_ROOM, GFP_ATOMIC); if (!skb2) goto drop; + if (t) + atomic64_inc(&t->skb_copies); kfree_skb(skb); skb = skb2; } @@ -5641,7 +5651,7 @@ drop: static int send_proxy_packet(struct sk_buff *skb, const struct re_address *src, const struct re_address *dst, - unsigned char tos, struct net *net) + unsigned char tos, struct net *net, struct rtpengine_table *t) { if (src->family != dst->family) { log_err("address family mismatch"); @@ -5655,11 +5665,11 @@ static int send_proxy_packet(struct sk_buff *skb, const struct re_address *src, switch (src->family) { case AF_INET: - return send_proxy_packet4(skb, src, dst, tos, net); + return send_proxy_packet4(skb, src, dst, tos, net, t); break; case AF_INET6: - return send_proxy_packet6(skb, src, dst, tos, net); + return send_proxy_packet6(skb, src, dst, tos, net, t); break; default: @@ -6572,7 +6582,7 @@ static struct sk_buff *intercept_skb_copy(struct sk_buff *oskb, const struct re_ static struct sk_buff *rtpe_skb_cpy(const struct sk_buff *oskb, const struct rtp_parsed *rtp, - struct rtp_parsed *rtp2) + struct rtp_parsed *rtp2, struct rtpengine_table *t) { struct sk_buff *skb; long offset; @@ -6581,6 +6591,8 @@ static struct sk_buff *rtpe_skb_cpy(const struct sk_buff *oskb, const struct rtp if (!skb) return NULL; + atomic64_inc(&t->skb_copies); + // adjust RTP pointers *rtp2 = *rtp; offset = skb->data - oskb->data; @@ -6643,7 +6655,7 @@ static uint32_t proxy_packet_srtp_encrypt(struct sk_buff *skb, struct re_crypto_ static struct sk_buff *proxy_packet_output_rtXp(struct sk_buff *skb, struct rtpengine_output *o, int rtp_pt_idx, - struct rtp_parsed *rtp, int ssrc_idx) + struct rtp_parsed *rtp, int ssrc_idx, struct rtpengine_table *t) { int i; uint32_t pkt_idx; @@ -6690,7 +6702,7 @@ static struct sk_buff *proxy_packet_output_rtXp(struct sk_buff *skb, struct rtpe // copy to encrypt/authenticate needed? if (o->output.encrypt.hmac != REH_NULL || o->encrypt_rtp.cipher->encrypt_rtp) { - struct sk_buff *skb2 = rtpe_skb_cpy(skb, rtp, rtp); + struct sk_buff *skb2 = rtpe_skb_cpy(skb, rtp, rtp, t); if (!skb2) goto drop; kfree_skb(skb); @@ -6717,12 +6729,12 @@ drop: static int send_proxy_packet_output(struct sk_buff *skb, struct rtpengine_target *g, int rtp_pt_idx, struct rtpengine_output *o, struct rtp_parsed *rtp, int ssrc_idx, - struct net *net) + struct net *net, struct rtpengine_table *t) { - skb = proxy_packet_output_rtXp(skb, o, rtp_pt_idx, rtp, ssrc_idx); + skb = proxy_packet_output_rtXp(skb, o, rtp_pt_idx, rtp, ssrc_idx, t); if (!skb) return 0; - return send_proxy_packet(skb, &o->output.src_addr, &o->output.dst_addr, o->output.tos, net); + return send_proxy_packet(skb, &o->output.src_addr, &o->output.dst_addr, o->output.tos, net, t); } @@ -7183,7 +7195,7 @@ static int rtpengine46(struct sk_buff *oskb, // copy to decrypt/authenticate needed? if (g->target.decrypt.hmac != REH_NULL || g->decrypt_rtp.cipher->decrypt_rtp) { errstr = "out of memory"; - skb = rtpe_skb_cpy(oskb, &rtp, &rtp); + skb = rtpe_skb_cpy(oskb, &rtp, &rtp, t); if (!skb) goto out_error; } @@ -7218,8 +7230,10 @@ static int rtpengine46(struct sk_buff *oskb, nf_action = NF_DROP; // if we haven't made a copy yet, we can use the original skb directly - if (!skb) + if (!skb) { skb = skb_get(oskb); + atomic64_inc(&t->skb_refs); + } rtpe_pull_trim(skb, datalen); @@ -7245,7 +7259,7 @@ static int rtpengine46(struct sk_buff *oskb, // always make a copy for RTCP // (even if technically not needed for NF_DROP case below) errstr = "out of memory"; - skb = rtpe_skb_cpy(oskb, &rtp, &rtp); + skb = rtpe_skb_cpy(oskb, &rtp, &rtp, t); if (!skb) goto out_error; @@ -7272,6 +7286,7 @@ static int rtpengine46(struct sk_buff *oskb, else { // forward non-RTP/RTCP. no copy needed skb = skb_get(oskb); + atomic64_inc(&t->skb_refs); nf_action = NF_DROP; rtpe_pull_trim(skb, datalen); @@ -7311,7 +7326,7 @@ static int rtpengine46(struct sk_buff *oskb, } else { // make copy - skb2 = rtpe_skb_cpy(skb, &rtp, &rtp2); + skb2 = rtpe_skb_cpy(skb, &rtp, &rtp2, t); if (!skb2) { log_err("out of memory while creating skb copy"); atomic64_inc(&g->target.stats->errors); @@ -7323,7 +7338,7 @@ static int rtpengine46(struct sk_buff *oskb, datalen_out = skb2->len; - err = send_proxy_packet_output(skb2, g, rtp_pt_idx, o, &rtp2, ssrc_idx, net); + err = send_proxy_packet_output(skb2, g, rtp_pt_idx, o, &rtp2, ssrc_idx, net, t); if (err) { atomic64_inc(&g->target.stats->errors); atomic64_inc(&g->target.iface_stats->in.errors);