From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: jlesev@gmail.com, David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 2/8] udp, tap: Correctly advance through packets in udp_tap_handler()
Date: Fri, 8 Sep 2023 11:49:47 +1000 [thread overview]
Message-ID: <20230908014953.822952-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20230908014953.822952-1-david@gibson.dropbear.id.au>
In both tap4_handler() and tap6_handler(), once we've sorted incoming l3
packets into "sequences", we then step through all the packets in each DUP
sequence calling udp_tap_handler(). Or so it appears.
In fact, udp_tap_handler() doesn't take an index and always starts with
packet 0 of the sequence, even if called repeatedly. It appears to be
written with the idea that the struct pool is a queue, from which it
consumes packets as it processes them, but that's not how the pool data
structure works.
Correct this by adding an index parameter to udp_tap_handler() and altering
the loops in tap.c to step through the pool properly.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
tap.c | 20 ++++++++------------
udp.c | 15 ++++++++-------
udp.h | 2 +-
3 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/tap.c b/tap.c
index 445a5ca..93db989 100644
--- a/tap.c
+++ b/tap.c
@@ -707,24 +707,22 @@ append:
for (j = 0, seq = tap4_l4; j < seq_count; j++, seq++) {
struct pool *p = (struct pool *)&seq->p;
+ size_t k;
tap_packet_debug(NULL, NULL, seq, 0, NULL, p->count);
if (seq->protocol == IPPROTO_TCP) {
- size_t k;
-
if (c->no_tcp)
continue;
for (k = 0; k < p->count; )
k += tcp_tap_handler(c, AF_INET, &seq->saddr,
&seq->daddr, p, k, now);
} else if (seq->protocol == IPPROTO_UDP) {
- size_t n = p->count;
-
if (c->no_udp)
continue;
- while ((n -= udp_tap_handler(c, AF_INET, &seq->saddr,
- &seq->daddr, p, now)));
+ for (k = 0; k < p->count; )
+ k += udp_tap_handler(c, AF_INET, &seq->saddr,
+ &seq->daddr, p, k, now);
}
}
@@ -872,25 +870,23 @@ append:
for (j = 0, seq = tap6_l4; j < seq_count; j++, seq++) {
struct pool *p = (struct pool *)&seq->p;
+ size_t k;
tap_packet_debug(NULL, NULL, NULL, seq->protocol, seq,
p->count);
if (seq->protocol == IPPROTO_TCP) {
- size_t k;
-
if (c->no_tcp)
continue;
for (k = 0; k < p->count; )
k += tcp_tap_handler(c, AF_INET6, &seq->saddr,
&seq->daddr, p, k, now);
} else if (seq->protocol == IPPROTO_UDP) {
- size_t n = p->count;
-
if (c->no_udp)
continue;
- while ((n -= udp_tap_handler(c, AF_INET6, &seq->saddr,
- &seq->daddr, p, now)));
+ for (k = 0; k < p->count; )
+ k += udp_tap_handler(c, AF_INET6, &seq->saddr,
+ &seq->daddr, p, k, now);
}
}
diff --git a/udp.c b/udp.c
index f4ed660..ed1b7a5 100644
--- a/udp.c
+++ b/udp.c
@@ -789,6 +789,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
* @saddr: Source address
* @daddr: Destination address
* @p: Pool of UDP packets, with UDP headers
+ * @idx: Index of first packet to process
* @now: Current timestamp
*
* Return: count of consumed packets
@@ -796,7 +797,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
* #syscalls sendmmsg
*/
int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
- const struct pool *p, const struct timespec *now)
+ const struct pool *p, int idx, const struct timespec *now)
{
struct mmsghdr mm[UIO_MAXIOV];
struct iovec m[UIO_MAXIOV];
@@ -811,7 +812,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
(void)c;
(void)saddr;
- uh = packet_get(p, 0, 0, sizeof(*uh), NULL);
+ uh = packet_get(p, idx, 0, sizeof(*uh), NULL);
if (!uh)
return 1;
@@ -859,7 +860,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
s = sock_l4(c, AF_INET, IPPROTO_UDP, &bind_addr,
bind_if, src, uref.u32);
if (s < 0)
- return p->count;
+ return p->count - idx;
udp_tap_map[V4][src].sock = s;
bitmap_set(udp_act[V4][UDP_ACT_TAP], src);
@@ -909,7 +910,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
s = sock_l4(c, AF_INET6, IPPROTO_UDP, bind_addr,
bind_if, src, uref.u32);
if (s < 0)
- return p->count;
+ return p->count - idx;
udp_tap_map[V6][src].sock = s;
bitmap_set(udp_act[V6][UDP_ACT_TAP], src);
@@ -918,13 +919,13 @@ int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
udp_tap_map[V6][src].ts = now->tv_sec;
}
- for (i = 0; i < (int)p->count; i++) {
+ for (i = 0; i < (int)p->count - idx; i++) {
struct udphdr *uh_send;
size_t len;
- uh_send = packet_get(p, i, 0, sizeof(*uh), &len);
+ uh_send = packet_get(p, idx + i, 0, sizeof(*uh), &len);
if (!uh_send)
- return p->count;
+ return p->count - idx;
mm[i].msg_hdr.msg_name = sa;
mm[i].msg_hdr.msg_namelen = sl;
diff --git a/udp.h b/udp.h
index f553de2..0ee0695 100644
--- a/udp.h
+++ b/udp.h
@@ -11,7 +11,7 @@
void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
const struct timespec *now);
int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
- const struct pool *p, const struct timespec *now);
+ const struct pool *p, int idx, const struct timespec *now);
int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
const void *addr, const char *ifname, in_port_t port);
int udp_init(struct ctx *c);
--
@@ -11,7 +11,7 @@
void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
const struct timespec *now);
int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
- const struct pool *p, const struct timespec *now);
+ const struct pool *p, int idx, const struct timespec *now);
int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
const void *addr, const char *ifname, in_port_t port);
int udp_init(struct ctx *c);
--
2.41.0
next prev parent reply other threads:[~2023-09-08 1:50 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-08 1:49 [PATCH 0/8] Fix a number of bugs with handling of TCP packets from tap David Gibson
2023-09-08 1:49 ` [PATCH 1/8] tcp, tap: Correctly advance through packets in tcp_tap_handler() David Gibson
2023-09-08 1:49 ` David Gibson [this message]
2023-09-08 1:49 ` [PATCH 3/8] tcp: Remove some redundant packet_get() operations David Gibson
2023-09-08 1:49 ` [PATCH 4/8] tcp: Never hash match closed connections David Gibson
2023-09-08 1:49 ` [PATCH 5/8] tcp: Return consumed packet count from tcp_data_from_tap() David Gibson
2023-09-08 1:49 ` [PATCH 6/8] tcp: Correctly handle RST followed rapidly by SYN David Gibson
2023-09-08 1:49 ` [PATCH 7/8] tcp: Consolidate paths where we initiate reset on tap interface David Gibson
2023-09-08 1:49 ` [PATCH 8/8] tcp: Correct handling of FIN,ACK followed by SYN David Gibson
2023-09-08 15:27 ` [PATCH 0/8] Fix a number of bugs with handling of TCP packets from tap Stefano Brivio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230908014953.822952-3-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=jlesev@gmail.com \
--cc=passt-dev@passt.top \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).