public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
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 v2 15/15] pesto: Read current ruleset from passt/pasta and display it
Date: Thu, 19 Mar 2026 17:11:57 +1100	[thread overview]
Message-ID: <20260319061157.1983818-16-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260319061157.1983818-1-david@gibson.dropbear.id.au>

Implement serialisation of our current forwarding rules in conf.c,
deserialising it to display in the pesto client.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 conf.c     | 44 +++++++++++++++++++++++++++++++
 fwd_rule.c | 40 ++++++++++++++++++++++++++++
 fwd_rule.h |  3 +++
 pesto.c    | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 160 insertions(+), 4 deletions(-)

diff --git a/conf.c b/conf.c
index 603ca2ac..b235221f 100644
--- a/conf.c
+++ b/conf.c
@@ -2339,6 +2339,47 @@ static int conf_send_pifs(const struct ctx *c, int fd)
 	return 0;
 }
 
+/**
+ * conf_send_rules() - Send current forwarding rules to dynamic update client (pesto)
+ * @c:		Execution context
+ * @fd:		Socket to the client
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int conf_send_rules(const struct ctx *c, int fd)
+{
+	unsigned pif;
+
+	for (pif = 0; pif < PIF_NUM_TYPES; pif++) {
+		const struct fwd_table *fwd = c->fwd[pif];
+		unsigned i;
+
+		if (!fwd)
+			continue;
+
+		assert(pif);
+
+		/* PIF id */
+		if (sewrite_u8(fd, pif))
+			return -1;
+
+		/* Number of rules */
+		if (sewrite_u32(fd, fwd->count))
+			return -1;
+
+		for (i = 0; i < fwd->count; i++) {
+			if (fwd_rule_sewrite(fd, &fwd->rules[i].rule))
+				return -1;
+		}
+	}
+
+	/* Write 0 PIF id to finish */
+	if (sewrite_u8(fd, 0))
+		return -1;
+
+	return 0;
+}
+
 /**
  * conf_listen_handler() - Handle events on configuration listening socket
  * @c:		Execution context
@@ -2398,6 +2439,9 @@ void conf_listen_handler(struct ctx *c, uint32_t events)
 	if (conf_send_pifs(c, fd) < 0)
 		goto fail;
 
+	if (conf_send_rules(c, fd) < 0)
+		goto fail;
+
 	return;
 
 fail:
diff --git a/fwd_rule.c b/fwd_rule.c
index dfbdf683..3e39b4f9 100644
--- a/fwd_rule.c
+++ b/fwd_rule.c
@@ -17,6 +17,8 @@
 
 #include <stdio.h>
 
+#include "serialise.h"
+
 #include "fwd_rule.h"
 
 /**
@@ -71,3 +73,41 @@ const char *fwd_rule_ntop(const struct fwd_rule *rule, char *dst, size_t size)
 
 	return dst;
 }
+
+/**
+ * fwd_rule_seread() - Read erialised rule from an fd
+ * @fd:		fd to serialise to
+ * @rule:	Buffer to store rule into
+ *
+ * Return: 0 on success, -1 on error (with errno set)
+ */
+int fwd_rule_seread(int fd, struct fwd_rule *rule)
+{
+	if (seread_var(fd, rule))
+		return -1;
+
+	/* Byteswap for host */
+	rule->first = ntohs(rule->first);
+	rule->last = ntohs(rule->last);
+	rule->to = htons(rule->to);
+	return 0;
+}
+
+/**
+ * fwd_rule_sewrite() - Serialise rule to an fd
+ * @fd:		fd to serialise to
+ * @rule:	Rule to send
+ *
+ * Return: 0 on success, -1 on error (with errno set)
+ */
+int fwd_rule_sewrite(int fd, const struct fwd_rule *rule)
+{
+	struct fwd_rule tmp = *rule;
+
+	/* Byteswap for transport */
+	tmp.first = htons(tmp.first);
+	tmp.last = htons(tmp.last);
+	tmp.to = htons(tmp.to);
+
+	return sewrite_var(fd, &tmp);
+}
diff --git a/fwd_rule.h b/fwd_rule.h
index 59db0e95..500b955d 100644
--- a/fwd_rule.h
+++ b/fwd_rule.h
@@ -53,4 +53,7 @@ const union inany_addr *fwd_rule_addr(const struct fwd_rule *rule);
 	 + 15)
 const char *fwd_rule_ntop(const struct fwd_rule *rule, char *dst, size_t size);
 
+int fwd_rule_seread(int fd, struct fwd_rule *rule);
+int fwd_rule_sewrite(int fd, const struct fwd_rule *rule);
+
 #endif /* FWD_RULE_H */
diff --git a/pesto.c b/pesto.c
index dbc27a58..f021cdb6 100644
--- a/pesto.c
+++ b/pesto.c
@@ -34,6 +34,7 @@
 #include "common.h"
 #include "seccomp_pesto.h"
 #include "serialise.h"
+#include "fwd_rule.h"
 #include "pesto.h"
 
 static int verbosity = 1;
@@ -108,6 +109,8 @@ static const char *pesto_recv_str(int fd)
 struct pif_state {
 	uint8_t pif;
 	const char *name;
+	uint32_t count;
+	struct fwd_rule *rule;
 };
 
 struct conf_state {
@@ -119,7 +122,7 @@ struct conf_state {
  * pesto_read_pifs() - Read pif names and IDs from passt/pasta
  * @fd:		Control socket
  */
-static const struct conf_state *pesto_read_pifs(int fd)
+static struct conf_state *pesto_read_pifs(int fd)
 {
 	uint32_t num;
 	struct conf_state *state;
@@ -146,18 +149,81 @@ static const struct conf_state *pesto_read_pifs(int fd)
 	return state;
 }
 
+/**
+ * find_pif_state() - Find the pif state structure for a given pif id
+ * @state:	Rule state information
+ * @pif:	pif id
+ *
+ * Return: pointer to the pif_state for @pif, or NULL if not found
+ */
+static struct pif_state *find_pif_state(struct conf_state *state, uint8_t pif)
+{
+	unsigned i;
+
+	for (i = 0; i < state->npifs; i++) {
+		if (state->pif[i].pif == pif)
+			return &state->pif[i];
+	}
+
+	return NULL;
+}
+
+/**
+ * pesto_read_rules() - Read a set of rules for one pif
+ * @fd:		Control socket
+ * @state:	Rule state information to update
+ *
+ * Return: true if there may be more rules to read, false if finished
+ */
+static bool pesto_read_rules(int fd, struct conf_state *state)
+{
+	struct pif_state *ps;
+	uint8_t pif;
+	unsigned i;
+
+	if (seread_u8(fd, &pif) < 0)
+		die("Error reading from control socket");
+
+	if (!pif)
+		return false;
+
+	ps = find_pif_state(state, pif);
+	if (!ps)
+		die("Received rules for an unknown pif");
+
+	if (seread_u32(fd, &ps->count) < 0)
+		die("Error reading from control socket");
+
+	debug("Receiving rules %"PRIu32" rules for %s", ps->count, ps->name);
+
+	ps->rule = xmalloc(sizeof(*ps->rule) * ps->count);
+
+	for (i = 0; i < ps->count; i++) {
+		if (fwd_rule_seread(fd, &ps->rule[i]) < 0)
+			die("Error reading from control socket");
+	}
+
+	return true;
+}
+
 /**
  * show_state() - Show current rule state obtained from passt/pasta
  * @pifs:	PIF name information
  */
 static void show_state(const struct conf_state *state)
 {
-	unsigned i;
+	unsigned i, j;
 
 	for (i = 0; i < state->npifs; i++) {
 		const struct pif_state *ps = &state->pif[i];
 		printf("Forwarding rules for %s interface\n", ps->name);
-		printf("\tTBD\n");
+		for (j = 0; j < ps->count; j++) {
+			const struct fwd_rule *rule = &ps->rule[j];
+			char rulestr[FWD_RULE_STRLEN];
+
+			printf("    %s\n", fwd_rule_ntop(rule, rulestr,
+							 sizeof(rulestr)));
+		}
 	}
 }
 
@@ -183,9 +249,9 @@ int main(int argc, char **argv)
 		{ 0 },
 	};
 	struct sockaddr_un a = { AF_UNIX, "" };
-	const struct conf_state *state;
 	const char *optstring = "vh";
 	struct pesto_hello hello;
+	struct conf_state *state;
 	struct sock_fprog prog;
 	int optname, ret, s;
 	uint32_t s_version;
@@ -266,6 +332,9 @@ int main(int argc, char **argv)
 
 	state = pesto_read_pifs(s);
 
+	while (pesto_read_rules(s, state))
+		;
+
 	show_state(state);
 
 	exit(0);
-- 
2.53.0


      parent reply	other threads:[~2026-03-19  6:12 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-19  6:11 [PATCH v2 00/15] RFC: Read-only dynamic update implementation David Gibson
2026-03-19  6:11 ` [PATCH v2 01/15] treewide: Spell ASSERT() as assert() David Gibson
2026-03-19  6:11 ` [PATCH v2 02/15] serialise: Split functions user for serialisation from util.c David Gibson
2026-03-19  6:11 ` [PATCH v2 03/15] serialise: Add helpers for serialising unsigned integers David Gibson
2026-03-19  6:11 ` [PATCH v2 04/15] fwd: Move selecting correct scan bitmap into fwd_sync_one() David Gibson
2026-03-19  6:11 ` [PATCH v2 05/15] fwd: Look up rule index in fwd_sync_one() David Gibson
2026-03-19  6:11 ` [PATCH v2 06/15] fwd: Store forwarding tables indexed by (origin) pif David Gibson
2026-03-19  6:11 ` [PATCH v2 07/15] pesto: Introduce stub configuration interface and tool David Gibson
2026-03-19  6:11 ` [PATCH v2 08/15] pesto: Add command line option parsing and debug messages David Gibson
2026-03-19  6:11 ` [PATCH v2 09/15] pesto: Expose list of pifs to pesto David Gibson
2026-03-19  6:11 ` [PATCH v2 10/15] ip: Prepare ip.[ch] for sharing with pesto tool David Gibson
2026-03-19  6:11 ` [PATCH v2 11/15] inany: Prepare inany.[ch] " David Gibson
2026-03-19  6:11 ` [PATCH v2 12/15] fwd: Split forwading rule specification from its implementation state David Gibson
2026-03-19  6:11 ` [PATCH v2 13/15] ip: Define a bound for the string returned by ipproto_name() David Gibson
2026-03-19  6:11 ` [PATCH v2 14/15] fwd_rule: Move forwarding rule text formatting to common code David Gibson
2026-03-19  6:11 ` David Gibson [this message]

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=20260319061157.1983818-16-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).