Add a helper function to read the host tap device's configured
MTU via SIOCGIFMTU. Since this ioctl requires a socket rather than
the tap character device fd itself, a separate control socket is
opened to perform the query, following the same pattern used by
net/can/can_socketcan.c.

This is implemented for Linux only, with stub implementations
returning -1 for BSD, Solaris, and the tap-stub backend, matching
the existing pattern used by tap_fd_get_ifname() and
tap_fd_set_steering_ebpf() in those files.

This is a preparatory patch; the function is not yet called from
anywhere.

Signed-off-by: Nariman Sayed <[email protected]>
---
 net/tap-bsd.c     |  5 +++++
 net/tap-linux.c   | 30 ++++++++++++++++++++++++++++++
 net/tap-solaris.c |  5 +++++
 net/tap-stub.c    |  5 +++++
 net/tap_int.h     |  1 +
 5 files changed, 46 insertions(+)

diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index c39daf9385..17cedccf9e 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -264,6 +264,11 @@ int tap_fd_get_ifname(int fd, char *ifname)
     return -1;
 }
 
+int tap_fd_get_mtu(int fd)
+{
+    return -1;
+}
+
 int tap_fd_set_steering_ebpf(int fd, int prog_fd)
 {
     return -1;
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 3cd7d26710..23a10151c1 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -34,6 +34,7 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
+#include "qemu/sockets.h"
 
 #define PATH_NET_TUN "/dev/net/tun"
 
@@ -346,6 +347,35 @@ int tap_fd_get_ifname(int fd, char *ifname)
     return 0;
 }
 
+int tap_fd_get_mtu(int fd)
+{
+    struct ifreq ifr;
+    int s, ret, mtu;
+
+    memset(&ifr, 0, sizeof(ifr));
+    if (tap_fd_get_ifname(fd, ifr.ifr_name) != 0) {
+        return -1;
+    }
+
+    s = qemu_socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0) {
+        error_report("could not create control socket: %s",
+                      strerror(errno));
+        return -1;
+    }
+
+    ret = ioctl(s, SIOCGIFMTU, &ifr);
+    if (ret != 0) {
+        error_report("SIOCGIFMTU ioctl() failed: %s", strerror(errno));
+        close(s);
+        return -1;
+    }
+
+    mtu = ifr.ifr_mtu;
+    close(s);
+    return mtu;
+}
+
 int tap_fd_set_steering_ebpf(int fd, int prog_fd)
 {
     if (ioctl(fd, TUNSETSTEERINGEBPF, (void *) &prog_fd) != 0) {
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 8704b1084b..d3bd6e6b48 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -266,6 +266,11 @@ int tap_fd_get_ifname(int fd, char *ifname)
     return -1;
 }
 
+int tap_fd_get_mtu(int fd)
+{
+    return -1;
+}
+
 int tap_fd_set_steering_ebpf(int fd, int prog_fd)
 {
     return -1;
diff --git a/net/tap-stub.c b/net/tap-stub.c
index 6aa60d96ad..756ce882a7 100644
--- a/net/tap-stub.c
+++ b/net/tap-stub.c
@@ -91,6 +91,11 @@ int tap_fd_get_ifname(int fd, char *ifname)
     return -1;
 }
 
+int tap_fd_get_mtu(int fd)
+{
+    return -1;
+}
+
 int tap_fd_set_steering_ebpf(int fd, int prog_fd)
 {
     return -1;
diff --git a/net/tap_int.h b/net/tap_int.h
index dc4f484006..360d61c889 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -45,6 +45,7 @@ int tap_fd_set_vnet_be(int fd, int vnet_is_be);
 int tap_fd_enable(int fd);
 int tap_fd_disable(int fd);
 int tap_fd_get_ifname(int fd, char *ifname);
+int tap_fd_get_mtu(int fd);
 int tap_fd_set_steering_ebpf(int fd, int prog_fd);
 
 #endif /* NET_TAP_INT_H */
-- 
2.34.1


Reply via email to