From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 2/8] tap: Pass source address to protocol handler functions
Date: Fri, 28 Jul 2023 19:48:25 +1000 [thread overview]
Message-ID: <20230728094831.4097571-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20230728094831.4097571-1-david@gibson.dropbear.id.au>
The tap code passes the IPv4 or IPv6 destination address of packets it
receives to the protocol specific code. Currently that protocol code
doesn't use the source address, but we want it to in future. So, in
preparation, pass the IPv4/IPv6 source address of tap packets to those
functions as well.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
icmp.c | 12 ++++++++----
icmp.h | 3 ++-
tap.c | 19 +++++++++++--------
tcp.c | 28 +++++++++++++++++-----------
tcp.h | 2 +-
udp.c | 14 ++++++++------
udp.h | 2 +-
7 files changed, 48 insertions(+), 32 deletions(-)
diff --git a/icmp.c b/icmp.c
index 44f73c8..65e3ec9 100644
--- a/icmp.c
+++ b/icmp.c
@@ -138,17 +138,21 @@ void icmp_sock_handler(const struct ctx *c, union epoll_ref ref,
* icmp_tap_handler() - Handle packets from tap
* @c: Execution context
* @af: Address family, AF_INET or AF_INET6
- * @addr: Destination address
+ * @saddr: Source address
+ * @daddr: Destination address
* @p: Packet pool, single packet with ICMP/ICMPv6 header
* @now: Current timestamp
*
* Return: count of consumed packets (always 1, even if malformed)
*/
-int icmp_tap_handler(const struct ctx *c, int af, const void *addr,
+int icmp_tap_handler(const struct ctx *c, int af,
+ const void *saddr, const void *daddr,
const struct pool *p, const struct timespec *now)
{
size_t plen;
+ (void)saddr;
+
if (af == AF_INET) {
union icmp_epoll_ref iref = { .icmp.v6 = 0 };
struct sockaddr_in sa = {
@@ -194,7 +198,7 @@ int icmp_tap_handler(const struct ctx *c, int af, const void *addr,
icmp_id_map[V4][id].ts = now->tv_sec;
bitmap_set(icmp_act[V4], id);
- sa.sin_addr = *(struct in_addr *)addr;
+ sa.sin_addr = *(struct in_addr *)daddr;
if (sendto(s, ih, sizeof(*ih) + plen, MSG_NOSIGNAL,
(struct sockaddr *)&sa, sizeof(sa)) < 0) {
debug("ICMP: failed to relay request to socket");
@@ -248,7 +252,7 @@ int icmp_tap_handler(const struct ctx *c, int af, const void *addr,
icmp_id_map[V6][id].ts = now->tv_sec;
bitmap_set(icmp_act[V6], id);
- sa.sin6_addr = *(struct in6_addr *)addr;
+ sa.sin6_addr = *(struct in6_addr *)daddr;
if (sendto(s, ih, sizeof(*ih) + plen, MSG_NOSIGNAL,
(struct sockaddr *)&sa, sizeof(sa)) < 1) {
debug("ICMPv6: failed to relay request to socket");
diff --git a/icmp.h b/icmp.h
index f899e6d..231f6f0 100644
--- a/icmp.h
+++ b/icmp.h
@@ -12,7 +12,8 @@ struct ctx;
void icmp_sock_handler(const struct ctx *c, union epoll_ref ref,
uint32_t events, const struct timespec *now);
-int icmp_tap_handler(const struct ctx *c, int af, const void *addr,
+int icmp_tap_handler(const struct ctx *c,
+ int af, const void *saddr, const void *daddr,
const struct pool *p, const struct timespec *now);
void icmp_timer(const struct ctx *c, const struct timespec *ts);
void icmp_init(void);
diff --git a/tap.c b/tap.c
index d8aa633..5e1daf8 100644
--- a/tap.c
+++ b/tap.c
@@ -642,7 +642,8 @@ resume:
tap_packet_debug(iph, NULL, NULL, 0, NULL, 1);
packet_add(pkt, l4_len, l4h);
- icmp_tap_handler(c, AF_INET, &iph->daddr, pkt, now);
+ icmp_tap_handler(c, AF_INET, &iph->saddr, &iph->daddr,
+ pkt, now);
continue;
}
@@ -707,7 +708,6 @@ append:
for (j = 0, seq = tap4_l4; j < seq_count; j++, seq++) {
struct pool *p = (struct pool *)&seq->p;
- struct in_addr *da = &seq->daddr;
size_t n = p->count;
tap_packet_debug(NULL, NULL, seq, 0, NULL, n);
@@ -715,11 +715,13 @@ append:
if (seq->protocol == IPPROTO_TCP) {
if (c->no_tcp)
continue;
- while ((n -= tcp_tap_handler(c, AF_INET, da, p, now)));
+ while ((n -= tcp_tap_handler(c, AF_INET, &seq->saddr,
+ &seq->daddr, p, now)));
} else if (seq->protocol == IPPROTO_UDP) {
if (c->no_udp)
continue;
- while ((n -= udp_tap_handler(c, AF_INET, da, p, now)));
+ while ((n -= udp_tap_handler(c, AF_INET, &seq->saddr,
+ &seq->daddr, p, now)));
}
}
@@ -800,7 +802,7 @@ resume:
tap_packet_debug(NULL, ip6h, NULL, proto, NULL, 1);
packet_add(pkt, l4_len, l4h);
- icmp_tap_handler(c, AF_INET6, daddr, pkt, now);
+ icmp_tap_handler(c, AF_INET6, saddr, daddr, pkt, now);
continue;
}
@@ -867,7 +869,6 @@ append:
for (j = 0, seq = tap6_l4; j < seq_count; j++, seq++) {
struct pool *p = (struct pool *)&seq->p;
- struct in6_addr *da = &seq->daddr;
size_t n = p->count;
tap_packet_debug(NULL, NULL, NULL, seq->protocol, seq, n);
@@ -875,11 +876,13 @@ append:
if (seq->protocol == IPPROTO_TCP) {
if (c->no_tcp)
continue;
- while ((n -= tcp_tap_handler(c, AF_INET6, da, p, now)));
+ while ((n -= tcp_tap_handler(c, AF_INET6, &seq->saddr,
+ &seq->daddr, p, now)));
} else if (seq->protocol == IPPROTO_UDP) {
if (c->no_udp)
continue;
- while ((n -= udp_tap_handler(c, AF_INET6, da, p, now)));
+ while ((n -= udp_tap_handler(c, AF_INET6, &seq->saddr,
+ &seq->daddr, p, now)));
}
}
diff --git a/tcp.c b/tcp.c
index 0ed9bfa..482c25b 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2007,13 +2007,15 @@ static void tcp_bind_outbound(const struct ctx *c, int s, sa_family_t af)
* tcp_conn_from_tap() - Handle connection request (SYN segment) from tap
* @c: Execution context
* @af: Address family, AF_INET or AF_INET6
- * @addr: Remote address, pointer to in_addr or in6_addr
+ * @saddr: Source address, pointer to in_addr or in6_addr
+ * @daddr: Destination address, pointer to in_addr or in6_addr
* @th: TCP header from tap: caller MUST ensure it's there
* @opts: Pointer to start of options
* @optlen: Bytes in options: caller MUST ensure available length
* @now: Current timestamp
*/
-static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
+static void tcp_conn_from_tap(struct ctx *c,
+ int af, const void *saddr, const void *daddr,
const struct tcphdr *th, const char *opts,
size_t optlen, const struct timespec *now)
{
@@ -2021,18 +2023,20 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
struct sockaddr_in addr4 = {
.sin_family = AF_INET,
.sin_port = th->dest,
- .sin_addr = *(struct in_addr *)addr,
+ .sin_addr = *(struct in_addr *)daddr,
};
struct sockaddr_in6 addr6 = {
.sin6_family = AF_INET6,
.sin6_port = th->dest,
- .sin6_addr = *(struct in6_addr *)addr,
+ .sin6_addr = *(struct in6_addr *)daddr,
};
const struct sockaddr *sa;
struct tcp_tap_conn *conn;
socklen_t sl;
int s, mss;
+ (void)saddr;
+
if (c->tcp.conn_count >= TCP_MAX_CONNS)
return;
@@ -2041,9 +2045,9 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
return;
if (!c->no_map_gw) {
- if (af == AF_INET && IN4_ARE_ADDR_EQUAL(addr, &c->ip4.gw))
+ if (af == AF_INET && IN4_ARE_ADDR_EQUAL(daddr, &c->ip4.gw))
addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- if (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw))
+ if (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.gw))
addr6.sin6_addr = in6addr_loopback;
}
@@ -2080,7 +2084,7 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
if (!(conn->wnd_from_tap = (htons(th->window) >> conn->ws_from_tap)))
conn->wnd_from_tap = 1;
- inany_from_af(&conn->addr, af, addr);
+ inany_from_af(&conn->addr, af, daddr);
if (af == AF_INET) {
sa = (struct sockaddr *)&addr4;
@@ -2558,13 +2562,14 @@ static void tcp_conn_from_sock_finish(struct ctx *c, struct tcp_tap_conn *conn,
* tcp_tap_handler() - Handle packets from tap and state transitions
* @c: Execution context
* @af: Address family, AF_INET or AF_INET6
- * @addr: Destination address
+ * @saddr: Source address
+ * @daddr: Destination address
* @p: Pool of TCP packets, with TCP headers
* @now: Current timestamp
*
* Return: count of consumed packets
*/
-int tcp_tap_handler(struct ctx *c, int af, const void *addr,
+int tcp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
const struct pool *p, const struct timespec *now)
{
struct tcp_tap_conn *conn;
@@ -2585,12 +2590,13 @@ int tcp_tap_handler(struct ctx *c, int af, const void *addr,
optlen = MIN(optlen, ((1UL << 4) /* from doff width */ - 6) * 4UL);
opts = packet_get(p, 0, sizeof(*th), optlen, NULL);
- conn = tcp_hash_lookup(c, af, addr, htons(th->source), htons(th->dest));
+ conn = tcp_hash_lookup(c, af, daddr, htons(th->source), htons(th->dest));
/* New connection from tap */
if (!conn) {
if (opts && th->syn && !th->ack)
- tcp_conn_from_tap(c, af, addr, th, opts, optlen, now);
+ tcp_conn_from_tap(c, af, saddr, daddr, th,
+ opts, optlen, now);
return 1;
}
diff --git a/tcp.h b/tcp.h
index a9e3425..66a73eb 100644
--- a/tcp.h
+++ b/tcp.h
@@ -15,7 +15,7 @@ struct ctx;
void tcp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
const struct timespec *now);
-int tcp_tap_handler(struct ctx *c, int af, const void *addr,
+int tcp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
const struct pool *p, const struct timespec *now);
int tcp_sock_init(const struct ctx *c, sa_family_t af, const void *addr,
const char *ifname, in_port_t port);
diff --git a/udp.c b/udp.c
index 39c59d4..47b4a61 100644
--- a/udp.c
+++ b/udp.c
@@ -801,7 +801,8 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
* udp_tap_handler() - Handle packets from tap
* @c: Execution context
* @af: Address family, AF_INET or AF_INET6
- * @addr: Destination address
+ * @saddr: Source address
+ * @daddr: Destination address
* @p: Pool of UDP packets, with UDP headers
* @now: Current timestamp
*
@@ -809,7 +810,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 *addr,
+int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
const struct pool *p, const struct timespec *now)
{
struct mmsghdr mm[UIO_MAXIOV];
@@ -823,6 +824,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
socklen_t sl;
(void)c;
+ (void)saddr;
uh = packet_get(p, 0, 0, sizeof(*uh), NULL);
if (!uh)
@@ -838,7 +840,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
s_in = (struct sockaddr_in) {
.sin_family = AF_INET,
.sin_port = uh->dest,
- .sin_addr = *(struct in_addr *)addr,
+ .sin_addr = *(struct in_addr *)daddr,
};
sa = (struct sockaddr *)&s_in;
@@ -883,17 +885,17 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
s_in6 = (struct sockaddr_in6) {
.sin6_family = AF_INET6,
.sin6_port = uh->dest,
- .sin6_addr = *(struct in6_addr *)addr,
+ .sin6_addr = *(struct in6_addr *)daddr,
};
const struct in6_addr *bind_addr = &in6addr_any;
sa = (struct sockaddr *)&s_in6;
sl = sizeof(s_in6);
- if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
+ if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.dns_match) &&
ntohs(s_in6.sin6_port) == 53) {
s_in6.sin6_addr = c->ip6.dns_host;
- } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) &&
+ } else if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.gw) &&
!c->no_map_gw) {
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
(udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
diff --git a/udp.h b/udp.h
index e64ef18..060ae35 100644
--- a/udp.h
+++ b/udp.h
@@ -10,7 +10,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 *addr,
+int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
const struct pool *p, 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);
--
@@ -10,7 +10,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 *addr,
+int udp_tap_handler(struct ctx *c, int af, const void *saddr, const void *daddr,
const struct pool *p, 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);
--
2.41.0
next prev parent reply other threads:[~2023-07-28 9:48 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-28 9:48 [PATCH 0/8] RFC: Generalize flow tracking, part 1 David Gibson
2023-07-28 9:48 ` [PATCH 1/8] tap: Don't clobber source address in tap6_handler() David Gibson
2023-07-28 9:48 ` David Gibson [this message]
2023-07-28 9:48 ` [PATCH 3/8] tcp: More precise terms for addresses and ports David Gibson
2023-07-28 9:48 ` [PATCH 4/8] tcp, udp: Don't include destination address in partially precomputed csums David Gibson
2023-07-28 9:48 ` [PATCH 5/8] tcp, udp: Don't pre-fill IPv4 destination address in headers David Gibson
2023-07-28 9:48 ` [PATCH 6/8] tcp: Track guest-side correspondent address David Gibson
2023-07-28 9:48 ` [PATCH 7/8] tcp, flow: Introduce struct demiflow David Gibson
2023-07-28 9:48 ` [PATCH 8/8] tcp, flow: Perform TCP hash calculations based on demiflow structure David Gibson
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=20230728094831.4097571-3-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--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).