Add helper functions for sending packets through the AF_PACKET out
socket or the chardev backend, and add netdev RX/TX packet and byte
counters to MirrorState.

The follow-up receive-path changes use these helpers and expose the new
statistics via filter_redirector_get_stats().

Signed-off-by: Cindy Lu <[email protected]>
---
 net/filter-mirror.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 915f2f8b35..e57fbc94b8 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -64,6 +64,11 @@ struct MirrorState {
     uint64_t indev_bytes;
     uint64_t outdev_packets;
     uint64_t outdev_bytes;
+    /* netdev replay/capture statistics for filter-redirector */
+    uint64_t netdev_rx_packets;
+    uint64_t netdev_rx_bytes;
+    uint64_t netdev_tx_packets;
+    uint64_t netdev_tx_bytes;
 };
 
 typedef struct FilterSendCo {
@@ -175,6 +180,59 @@ static int filter_send(MirrorState *s,
     return data.ret;
 }
 
+static ssize_t filter_redirector_send_netdev_packet(MirrorState *s,
+                                                    const struct iovec *iov,
+                                                    int iovcnt)
+{
+    ssize_t size = iov_size(iov, iovcnt);
+    g_autofree uint8_t *buf = NULL;
+
+    if (s->out_netfd < 0) {
+        return -ENODEV;
+    }
+    if (size > NET_BUFSIZE) {
+        return -EINVAL;
+    }
+
+    buf = g_malloc(size);
+    iov_to_buf(iov, iovcnt, 0, buf, size);
+
+    ssize_t ret = send(s->out_netfd, buf, size, 0);
+    if (ret < 0) {
+        return -errno;
+    }
+    if (ret > 0) {
+        s->netdev_tx_packets++;
+        s->netdev_tx_bytes += ret;
+    }
+    return ret;
+}
+static ssize_t filter_redirector_send_chardev_iov(MirrorState *s,
+                                                  const struct iovec *iov,
+                                                  int iovcnt)
+{
+    if (!s->outdev) {
+        return -ENODEV;
+    }
+
+    if (!qemu_chr_fe_backend_connected(&s->chr_out)) {
+        return 0;
+    }
+
+    return filter_send(s, iov, iovcnt);
+}
+
+static ssize_t filter_redirector_send_netdev_iov(MirrorState *s,
+                                                 const struct iovec *iov,
+                                                 int iovcnt)
+{
+    if (s->out_netfd < 0) {
+        return -ENODEV;
+    }
+
+    return filter_redirector_send_netdev_packet(s, iov, iovcnt);
+}
+
 static void redirector_to_filter(NetFilterState *nf,
                                  const uint8_t *buf,
                                  int len)
@@ -763,6 +821,18 @@ static GList *filter_redirector_get_stats(NetFilterState 
*nf)
     counter->bytes = s->outdev_bytes;
     list = g_list_append(list, counter);
 
+    counter = g_new0(NetFilterCounter, 1);
+    counter->name = g_strdup("netdev_rx");
+    counter->packets = s->netdev_rx_packets;
+    counter->bytes = s->netdev_rx_bytes;
+    list = g_list_append(list, counter);
+
+    counter = g_new0(NetFilterCounter, 1);
+    counter->name = g_strdup("netdev_tx");
+    counter->packets = s->netdev_tx_packets;
+    counter->bytes = s->netdev_tx_bytes;
+    list = g_list_append(list, counter);
+
     return list;
 }
 
-- 
2.52.0


Reply via email to