summaryrefslogtreecommitdiff
path: root/src/dev/net
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2017-06-03 07:23:05 -0700
committerGabe Black <gabeblack@google.com>2017-06-03 15:24:02 +0000
commitc58537ca206f2fb3829050a4a0e342edef0bd64b (patch)
treeb0813e58558ed89290b11cf9aa4561f19e0ffddc /src/dev/net
parent2ce045341b73166cad2ef95b37c87d8d4c590d80 (diff)
downloadgem5-c58537ca206f2fb3829050a4a0e342edef0bd64b.tar.xz
dev: Add a version of EtherTap which uses the tap driver.
The object is called EtherTap (as opposed to EtherTapStub, what the former EtherTap was renamed to), and its existance is gated on the linux/if_tun.h header file existing. That's probably overly strict, but it will hopefully be minimally likely to break the build for other systems. Change-Id: Ie03507fadf0d843a4d4d52f283c44a416c6f2a74 Reviewed-on: https://gem5-review.googlesource.com/3646 Reviewed-by: Nathan Binkert <nate@binkert.org> Maintainer: Nathan Binkert <nate@binkert.org>
Diffstat (limited to 'src/dev/net')
-rw-r--r--src/dev/net/Ethernet.py9
-rw-r--r--src/dev/net/ethertap.cc74
-rw-r--r--src/dev/net/ethertap.hh31
3 files changed, 114 insertions, 0 deletions
diff --git a/src/dev/net/Ethernet.py b/src/dev/net/Ethernet.py
index 68867c00f..71665c564 100644
--- a/src/dev/net/Ethernet.py
+++ b/src/dev/net/Ethernet.py
@@ -38,6 +38,7 @@
#
# Authors: Nathan Binkert
+from m5.defines import buildEnv
from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
@@ -103,6 +104,14 @@ class EtherTapBase(EtherObject):
dump = Param.EtherDump(NULL, "dump object")
tap = SlavePort("Ethernet interface to connect to gem5's network")
+if buildEnv['USE_TUNTAP']:
+ class EtherTap(EtherTapBase):
+ type = 'EtherTap'
+ cxx_header = "dev/net/ethertap.hh"
+ tun_clone_device = Param.String('/dev/net/tun',
+ "Path to the tun clone device node")
+ tap_device_name = Param.String('gem5-tap', "Tap device name")
+
class EtherTapStub(EtherTapBase):
type = 'EtherTapStub'
cxx_header = "dev/net/ethertap.hh"
diff --git a/src/dev/net/ethertap.cc b/src/dev/net/ethertap.cc
index f08de0ebf..0c027b621 100644
--- a/src/dev/net/ethertap.cc
+++ b/src/dev/net/ethertap.cc
@@ -38,9 +38,24 @@
#include <sys/param.h>
#endif
+
+#if USE_TUNTAP && defined(__linux__)
+#if 1 // Hide from the style checker since these have to be out of order.
+#include <sys/socket.h> // Has to be included before if.h for some reason.
+
+#endif
+
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#endif
+
+#include <fcntl.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
#include <unistd.h>
+#include <cstring>
#include <deque>
#include <string>
@@ -377,6 +392,65 @@ EtherTapStub::sendReal(const void *data, size_t len)
}
+#if USE_TUNTAP
+
+EtherTap::EtherTap(const Params *p) : EtherTapBase(p)
+{
+ int fd = open(p->tun_clone_device.c_str(), O_RDWR);
+ if (fd < 0)
+ panic("Couldn't open %s.\n", p->tun_clone_device);
+
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ strncpy(ifr.ifr_name, p->tap_device_name.c_str(), IFNAMSIZ);
+
+ if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)
+ panic("Failed to access tap device %s.\n", ifr.ifr_name);
+ // fd now refers to the tap device.
+ tap = fd;
+ pollFd(tap);
+}
+
+EtherTap::~EtherTap()
+{
+ stopPolling();
+ close(tap);
+ tap = -1;
+}
+
+void
+EtherTap::recvReal(int revent)
+{
+ if (revent & POLLERR)
+ panic("Error polling for tap data.\n");
+
+ if (!(revent & POLLIN))
+ return;
+
+ ssize_t ret = read(tap, buffer, buflen);
+ if (ret < 0)
+ panic("Failed to read from tap device.\n");
+
+ sendSimulated(buffer, ret);
+}
+
+bool
+EtherTap::sendReal(const void *data, size_t len)
+{
+ if (write(tap, data, len) != len)
+ panic("Failed to write data to tap device.\n");
+ return true;
+}
+
+EtherTap *
+EtherTapParams::create()
+{
+ return new EtherTap(this);
+}
+
+#endif
+
EtherTapStub *
EtherTapStubParams::create()
{
diff --git a/src/dev/net/ethertap.hh b/src/dev/net/ethertap.hh
index 718af1808..96cc4710c 100644
--- a/src/dev/net/ethertap.hh
+++ b/src/dev/net/ethertap.hh
@@ -39,9 +39,16 @@
#include <string>
#include "base/pollevent.hh"
+#include "config/use_tuntap.hh"
#include "dev/net/etherint.hh"
#include "dev/net/etherobject.hh"
#include "dev/net/etherpkt.hh"
+
+#if USE_TUNTAP
+#include "params/EtherTap.hh"
+
+#endif
+
#include "params/EtherTapStub.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
@@ -176,4 +183,28 @@ class EtherTapStub : public EtherTapBase
};
+#if USE_TUNTAP
+class EtherTap : public EtherTapBase
+{
+ public:
+ typedef EtherTapParams Params;
+ EtherTap(const Params *p);
+ ~EtherTap();
+
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+
+
+ protected:
+ int tap;
+
+ void recvReal(int revent) override;
+ bool sendReal(const void *data, size_t len) override;
+};
+#endif
+
+
#endif // __DEV_NET_ETHERTAP_HH__