diff options
author | Gabe Black <gabeblack@google.com> | 2017-06-03 07:23:05 -0700 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2017-06-03 15:24:02 +0000 |
commit | c58537ca206f2fb3829050a4a0e342edef0bd64b (patch) | |
tree | b0813e58558ed89290b11cf9aa4561f19e0ffddc /src/dev/net/ethertap.cc | |
parent | 2ce045341b73166cad2ef95b37c87d8d4c590d80 (diff) | |
download | gem5-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/ethertap.cc')
-rw-r--r-- | src/dev/net/ethertap.cc | 74 |
1 files changed, 74 insertions, 0 deletions
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() { |