Add helpers that tell whether a redirector instance should create an
AF_PACKET capture socket or inject socket. Later commits use them when
wiring up the TAP datapath.
While here, let the indev-only inject role enable
allow_send_when_stopped, and guard
filter_redirector_vm_state_change() against a missing nc.
Signed-off-by: Cindy Lu <lulu@redhat.com>
---
net/filter-mirror.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index ab711e8835..376b7da025 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -22,6 +22,7 @@
#include "qemu/error-report.h"
#include "trace.h"
#include "chardev/char-fe.h"
+#include "net/vhost_net.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
#include "block/aio-wait.h"
@@ -62,6 +63,24 @@ typedef struct FilterSendCo {
int ret;
} FilterSendCo;
+static bool filter_redirector_use_inject_netdev(NetFilterState *nf)
+{
+ MirrorState *s = FILTER_REDIRECTOR(nf);
+
+ return s->indev && !s->outdev &&
+ nf->netdev &&
+ get_vhost_net(nf->netdev);
+}
+
+static bool filter_redirector_use_capture_netdev(NetFilterState *nf)
+{
+ MirrorState *s = FILTER_REDIRECTOR(nf);
+
+ return s->outdev && !s->indev &&
+ nf->netdev &&
+ get_vhost_net(nf->netdev);
+}
+
static int _filter_send(MirrorState *s,
char *buf,
ssize_t size)
@@ -318,13 +337,13 @@ filter_redirector_refresh_allow_send_when_stopped(NetFilterState *nf)
/*
* Allow sending when stopped if enable_when_stopped is set and we have
- * an outdev. This must be independent of nf->on (status) so that packets
- * can still flow through the filter chain to other filters even when this
- * redirector is disabled. Otherwise, tap_send() will disable read_poll
- * when qemu_can_send_packet() returns false, preventing further packet
- * processing.
+ * a redirector output endpoint and the redirector is enabled.
+ * Keeping this active while redirector status=off can unexpectedly
+ * drain packets in migration stop windows and perturb vhost ring state.
*/
- nc->allow_send_when_stopped = (s->enable_when_stopped && s->outdev);
+ nc->allow_send_when_stopped = (s->enable_when_stopped &&
+ (s->outdev ||
+ filter_redirector_use_inject_netdev(nf)));
}
static void filter_redirector_vm_state_change(void *opaque, bool running,
@@ -334,7 +353,7 @@ static void filter_redirector_vm_state_change(void *opaque, bool running,
MirrorState *s = FILTER_REDIRECTOR(nf);
NetClientState *nc = nf->netdev;
- if (!running && s->enable_when_stopped && nc->info->read_poll) {
+ if (!running && nc && s->enable_when_stopped && nc->info->read_poll) {
nc->info->read_poll(nc, true);
}
}
--
2.52.0