With -t auto and similar options we need to periodically scan /proc for
listening ports. Currently we do this separately for TCP and UDP, from
tcp_timer() and udp_timer().
For upcoming changes (leading eventually to a more general forwarding
table), it's awkward to have these separate. Move them to a single common
timer. For now this just calls new tcp_scan_ports() and udp_scan_ports()
functions, but we'll consolidate more thoroughly in later patches.
Signed-off-by: David Gibson
---
fwd.c | 24 ++++++++++++++++++++++++
fwd.h | 3 +++
passt.c | 7 +++----
tcp.c | 33 ++++++++++++++++++++-------------
tcp.h | 3 ++-
udp.c | 29 ++++++++++++-----------------
udp.h | 4 +---
7 files changed, 65 insertions(+), 38 deletions(-)
diff --git a/fwd.c b/fwd.c
index 250cf564..bd89a94a 100644
--- a/fwd.c
+++ b/fwd.c
@@ -230,6 +230,30 @@ void fwd_scan_ports_init(struct ctx *c)
}
}
+/* Last time we scanned for open ports */
+static struct timespec scan_ports_run;
+
+/**
+ * fwd_scan_ports_timer() - Rescan open port information when necessary
+ * @c: Execution context
+ * @now: Current (monotonic) time
+ */
+void fwd_scan_ports_timer(struct ctx *c, const struct timespec *now)
+{
+ if (c->mode != MODE_PASTA)
+ return;
+
+ if (timespec_diff_ms(now, &scan_ports_run) < FWD_PORT_SCAN_INTERVAL)
+ return;
+
+ scan_ports_run = *now;
+
+ if (!c->no_tcp)
+ tcp_scan_ports(c);
+ if (!c->no_udp)
+ udp_scan_ports(c);
+}
+
/**
* is_dns_flow() - Determine if flow appears to be a DNS request
* @proto: Protocol (IP L4 protocol number)
diff --git a/fwd.h b/fwd.h
index 65c7c964..385e5bd8 100644
--- a/fwd.h
+++ b/fwd.h
@@ -42,11 +42,14 @@ struct fwd_ports {
in_port_t delta[NUM_PORTS];
};
+#define FWD_PORT_SCAN_INTERVAL 1000 /* ms */
+
void fwd_scan_ports_tcp(struct fwd_ports *fwd, const struct fwd_ports *rev);
void fwd_scan_ports_udp(struct fwd_ports *fwd, const struct fwd_ports *rev,
const struct fwd_ports *tcp_fwd,
const struct fwd_ports *tcp_rev);
void fwd_scan_ports_init(struct ctx *c);
+void fwd_scan_ports_timer(struct ctx *c, const struct timespec *now);
bool nat_inbound(const struct ctx *c, const union inany_addr *addr,
union inany_addr *translated);
diff --git a/passt.c b/passt.c
index b877659e..28ce5711 100644
--- a/passt.c
+++ b/passt.c
@@ -56,7 +56,7 @@
#define EPOLL_EVENTS 8
-#define TIMER_INTERVAL_ MIN(TCP_TIMER_INTERVAL, UDP_TIMER_INTERVAL)
+#define TIMER_INTERVAL_ MIN(TCP_TIMER_INTERVAL, FWD_PORT_SCAN_INTERVAL)
#define TIMER_INTERVAL MIN(TIMER_INTERVAL_, FLOW_TIMER_INTERVAL)
char pkt_buf[PKT_BUF_BYTES] __attribute__ ((aligned(PAGE_SIZE)));
@@ -117,11 +117,10 @@ static void post_handler(struct ctx *c, const struct timespec *now)
/* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */
CALL_PROTO_HANDLER(tcp, TCP);
- /* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */
- CALL_PROTO_HANDLER(udp, UDP);
+#undef CALL_PROTO_HANDLER
flow_defer_handler(c, now);
-#undef CALL_PROTO_HANDLER
+ fwd_scan_ports_timer(c, now);
if (!c->no_ndp)
ndp_timer(c, now);
diff --git a/tcp.c b/tcp.c
index 0f9e9b3f..dbbb00c4 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2869,25 +2869,32 @@ static int tcp_port_rebind_outbound(void *arg)
}
/**
- * tcp_timer() - Periodic tasks: port detection, closed connections, pool refill
+ * tcp_scan_ports() - Update forwarding maps based on scan of listening ports
* @c: Execution context
- * @now: Current timestamp
*/
-void tcp_timer(struct ctx *c, const struct timespec *now)
+void tcp_scan_ports(struct ctx *c)
{
- (void)now;
+ ASSERT(c->mode == MODE_PASTA && !c->no_tcp);
- if (c->mode == MODE_PASTA) {
- if (c->tcp.fwd_out.mode == FWD_AUTO) {
- fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
- NS_CALL(tcp_port_rebind_outbound, c);
- }
+ if (c->tcp.fwd_out.mode == FWD_AUTO) {
+ fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
+ NS_CALL(tcp_port_rebind_outbound, c);
+ }
- if (c->tcp.fwd_in.mode == FWD_AUTO) {
- fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
- tcp_port_rebind(c, false);
- }
+ if (c->tcp.fwd_in.mode == FWD_AUTO) {
+ fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
+ tcp_port_rebind(c, false);
}
+}
+
+/**
+ * tcp_timer() - Periodic tasks: port detection, closed connections, pool refill
+ * @c: Execution context
+ * @now: Current timestamp
+ */
+void tcp_timer(const struct ctx *c, const struct timespec *now)
+{
+ (void)now;
tcp_sock_refill_init(c);
if (c->mode == MODE_PASTA)
diff --git a/tcp.h b/tcp.h
index 234a8033..43ab0655 100644
--- a/tcp.h
+++ b/tcp.h
@@ -21,7 +21,8 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
int tcp_sock_init(const struct ctx *c, const union inany_addr *addr,
const char *ifname, in_port_t port);
int tcp_init(struct ctx *c);
-void tcp_timer(struct ctx *c, const struct timespec *now);
+void tcp_scan_ports(struct ctx *c);
+void tcp_timer(const struct ctx *c, const struct timespec *now);
void tcp_defer_handler(struct ctx *c);
void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s);
diff --git a/udp.c b/udp.c
index 86585b7e..d15f03dc 100644
--- a/udp.c
+++ b/udp.c
@@ -1239,28 +1239,23 @@ static int udp_port_rebind_outbound(void *arg)
}
/**
- * udp_timer() - Scan activity bitmaps for ports with associated timed events
+ * udp_scan_ports() - Update forwarding maps based on scan of listening ports
* @c: Execution context
- * @now: Current timestamp
*/
-void udp_timer(struct ctx *c, const struct timespec *now)
+void udp_scan_ports(struct ctx *c)
{
- (void)now;
-
- ASSERT(!c->no_udp);
+ ASSERT(c->mode == MODE_PASTA && !c->no_udp);
- if (c->mode == MODE_PASTA) {
- if (c->udp.fwd_out.mode == FWD_AUTO) {
- fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.fwd_in,
- &c->tcp.fwd_out, &c->tcp.fwd_in);
- NS_CALL(udp_port_rebind_outbound, c);
- }
+ if (c->udp.fwd_out.mode == FWD_AUTO) {
+ fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.fwd_in,
+ &c->tcp.fwd_out, &c->tcp.fwd_in);
+ NS_CALL(udp_port_rebind_outbound, c);
+ }
- if (c->udp.fwd_in.mode == FWD_AUTO) {
- fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.fwd_out,
- &c->tcp.fwd_in, &c->tcp.fwd_out);
- udp_port_rebind(c, false);
- }
+ if (c->udp.fwd_in.mode == FWD_AUTO) {
+ fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.fwd_out,
+ &c->tcp.fwd_in, &c->tcp.fwd_out);
+ udp_port_rebind(c, false);
}
}
diff --git a/udp.h b/udp.h
index 8f8531ad..a6de1f1c 100644
--- a/udp.h
+++ b/udp.h
@@ -6,8 +6,6 @@
#ifndef UDP_H
#define UDP_H
-#define UDP_TIMER_INTERVAL 1000 /* ms */
-
void udp_portmap_clear(void);
void udp_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
uint32_t events, const struct timespec *now);
@@ -20,7 +18,7 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif,
int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr,
const char *ifname, in_port_t port);
int udp_init(struct ctx *c);
-void udp_timer(struct ctx *c, const struct timespec *now);
+void udp_scan_ports(struct ctx *c);
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s);
/**
--
2.51.0