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 <[email protected]>
---
 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


Reply via email to