On a Sunday in 2023, Laine Stump wrote:
This implements XML config to represent a subset of the features
supported by 'passt' (
https://passt.top), which is an alternative
backend for emulated network devices that requires no elevated
privileges (similar to slirp, but "better").
Along with setting the backend to use passt (via <backend
type='passt'/> when the interface type='user'), we also support
passt's --log-file and --interface options (via the <backend>
subelement logFile and upstream attributes) and its --tcp-ports and
--udp-ports options (which selectively forward incoming connections to
the host on to the guest) via the new <portForward> subelement of
<interface>. Here is an example of the config for a network interface
that uses passt to connect:
<interface type='user'>
<mac address='52:54:00:a8:33:fc'/>
<ip address='192.168.221.122' family='ipv4'/>
<model type='virtio'/>
<backend type='passt' logFile='/tmp/xyzzy.log'
upstream='eth0'/>
<portForward address='10.0.0.1' proto='tcp'
dev='eth0'>
<range start='2022' to='22'/>
<range start='5000' end='5099' to='1000'/>
<range start='5010' end='5029' exclude='yes'/>
</portForward>
<portForward proto='udp'>
<range start='10101'/>
</portForward>
</interface>
In this case:
* the guest will be offered address 192.168.221.122 for its interface
via DHCP
* the passt process will write all log messages to /tmp/xyzzy.log
* routes to the outside for the guest will be derived from the
addresses and routes associated with the host interface "eth0".
* incoming tcp port 2022 to the host will be forwarded to port 22
on the guest.
* incoming tcp ports 5000-5099 (with the exception of ports 5010-5029)
to the host will be forwarded to port 1000-1099 on the guest.
* incoming udp packets on port 10101 will be forwarded (unchanged) to
the guest.
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
docs/formatdomain.rst | 95 +++++++-
src/conf/domain_conf.c | 242 +++++++++++++++++++-
src/conf/domain_conf.h | 40 ++++
src/conf/domain_validate.c | 32 ++-
src/conf/virconftypes.h | 4 +
src/libvirt_private.syms | 1 +
tests/qemuxml2xmloutdata/net-user-passt.xml | 1 +
tests/qemuxml2xmltest.c | 1 +
8 files changed, 401 insertions(+), 15 deletions(-)
create mode 120000 tests/qemuxml2xmloutdata/net-user-passt.xml
Reviewed-by: Ján Tomko <jtomko(a)redhat.com>
The XML looks reasonable to me. All my comments below are just
nitpicking.
+static int
+virDomainNetPortForwardRangesParseXML(virDomainNetPortForward *def,
+ xmlXPathContextPtr ctxt)
+{
+ int nRanges;
+ g_autofree xmlNodePtr *ranges = NULL;
+ size_t i;
+
+ if ((nRanges = virXPathNodeSet("./range",
+ ctxt, &ranges)) <= 0) {
This would fit on one line. Also, the braces are not necessary,
but allowed per our coding style.
+ return nRanges;
+ }
+
+ def->ranges = g_new0(virDomainNetPortForwardRange *, nRanges);
+
+ for (i = 0; i < nRanges; i++) {
+ g_autofree virDomainNetPortForwardRange *range = NULL;
+
[...]
@@ -23274,17 +23435,91 @@ static void
virDomainNetBackendFormat(virBuffer *buf,
virDomainNetBackend *backend)
{
-
- if (!(backend->tap || backend->vhost))
+ if (!(backend->type || backend->tap || backend->vhost
+ || backend->logFile || backend->upstream)) {
The prevalent style is to put the operator on the preceding line.
Best way to avoid it here is to use virXMLFormatElement.
return;
+ }
[...]
+ if (net->type != VIR_DOMAIN_NET_TYPE_USER) {
+ if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("\"<backend type='passt'/>\"
can only be used with \"<interface type='user'>\""));
Including XML in the error message can be confusing if the error reaches
users that did not use XML to configure the domain.
+ return -1;
+ }
+ }
+
switch (net->type) {
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
if (!virDomainNetIsVirtioModel(net)) {
Reviewed-by: Ján Tomko <jtomko(a)redhat.com>
Jano