Go to the documentation of this file.
35 #if defined(__OpenBSD__) || defined(__APPLE__)
36 #include <sys/param.h>
40 #if USE_TUNTAP && defined(__linux__)
41 #if 1 // Hide from the style checker since these have to be out of order.
42 #include <sys/socket.h>
47 #include <linux/if_tun.h>
52 #include <netinet/in.h>
53 #include <sys/ioctl.h>
64 #include "debug/Ethernet.hh"
65 #include "debug/EthernetData.hh"
95 txEvent([this]{
retransmit(); },
"EtherTapBase retransmit")
97 buffer =
new uint8_t[buflen];
112 uint8_t *
buffer = (uint8_t *)this->buffer;
115 bool tapevent_present =
false;
117 tapevent_present =
true;
119 event->serialize(
cp);
129 uint8_t *
buffer = (uint8_t *)this->buffer;
132 bool tapevent_present;
134 if (tapevent_present) {
136 event->unserialize(
cp);
147 event =
new TapEvent(
this,
fd, POLLIN|POLLERR);
163 if (if_name ==
"tap")
174 DPRINTF(Ethernet,
"EtherTap sim->real len=%d\n", packet->length);
175 DDUMP(EthernetData, packet->data, packet->length);
177 bool success =
sendReal(packet->data, packet->length);
188 packet = make_shared<EthPacketData>(
len);
189 packet->length =
len;
190 packet->simLength =
len;
191 memcpy(packet->data,
data,
len);
193 DPRINTF(Ethernet,
"EtherTap real->sim len=%d\n", packet->length);
194 DDUMP(EthernetData, packet->data, packet->length);
196 DPRINTF(Ethernet,
"bus busy...buffer for retransmission\n");
215 DPRINTF(Ethernet,
"EtherTap retransmit\n");
260 DPRINTF(Ethernet,
"TapListener(listen): Can't bind port %d\n",
port);
264 ccprintf(cerr,
"Listening for tap connection on port %d\n",
port);
278 panic(
"TapListener(accept): cannot accept if we're not listening!");
289 fatal(
"All listeners are disabled! EtherTapStub can't work!");
330 DPRINTF(Ethernet,
"EtherTapStub attached\n");
337 DPRINTF(Ethernet,
"EtherTapStub detached\n");
346 if (revent & POLLERR) {
351 if (!(revent & POLLIN))
369 DPRINTF(Ethernet,
"Received data from peer: len=%d buffer_used=%d "
372 uint8_t *frame_start = &
buffer[
sizeof(uint32_t)];
404 int fd = open(
p->tun_clone_device.c_str(), O_RDWR | O_NONBLOCK);
406 panic(
"Couldn't open %s.\n",
p->tun_clone_device);
409 memset(&ifr, 0,
sizeof(ifr));
410 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
411 strncpy(ifr.ifr_name,
p->tap_device_name.c_str(), IFNAMSIZ - 1);
413 if (ioctl(
fd, TUNSETIFF, (
void *)&ifr) < 0)
414 panic(
"Failed to access tap device %s.\n", ifr.ifr_name);
420 EtherTap::~EtherTap()
428 EtherTap::recvReal(
int revent)
430 if (revent & POLLERR)
431 panic(
"Error polling for tap data.\n");
433 if (!(revent & POLLIN))
437 while ((ret = read(tap, buffer, buflen))) {
441 panic(
"Failed to read from tap device.\n");
444 sendSimulated(buffer, ret);
449 EtherTap::sendReal(
const void *
data,
size_t len)
454 pfd->events = POLLOUT;
460 panic(
"Failed to write data to tap device.\n");
462 int ret = poll(pfd, 1, -1);
465 if (ret == -1 || (ret == 1 && (pfd->revents & POLLERR))) {
466 panic(
"Failed when polling to write data to tap device.\n");
473 EtherTapParams::create()
475 return new EtherTap(
this);
481 EtherTapStubParams::create()
#define fatal(...)
This implements a cprintf based fatal() function.
bool scheduled() const
Determine if the current event is scheduled.
void recvReal(int revent) override
virtual bool listen(int port, bool reuse=true)
TapListener(EtherTapStub *t, int p)
virtual bool sendReal(const void *data, size_t len)=0
#define UNSERIALIZE_SCALAR(scalar)
TapEvent(EtherTapBase *_tap, int fd, int e)
EtherTapStub(const Params *p)
virtual int accept(bool nodelay=false)
void sendSimulated(void *data, size_t len)
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
virtual void recvReal(int revent)=0
void schedule(PollEvent *event)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void schedule(Event &event, Tick when)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Ports are used to interface objects to each other.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
#define SERIALIZE_ARRAY(member, size)
void serialize(CheckpointOut &cp) const override
Serialize an object.
EventQueue * eventQueue() const
const std::string & name()
#define SERIALIZE_SCALAR(scalar)
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void process(int revent) override
EtherTapBase(const Params *p)
std::shared_ptr< EthPacketData > EthPacketPtr
static bool allDisabled()
void process(int revent) override
#define UNSERIALIZE_ARRAY(member, size)
Overload hash function for BasicBlockRange type.
void dump()
Dump all statistics data to the registered outputs.
void ccprintf(cp::Print &print)
EtherTapBaseParams Params
std::ostream CheckpointOut
bool sendPacket(EthPacketPtr packet)
Event(TapListener *l, int fd, int e)
EventFunctionWrapper txEvent
std::queue< EthPacketPtr > packetBuffer
bool recvSimulated(EthPacketPtr packet)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void dump(EthPacketPtr &pkt)
#define panic(...)
This implements a cprintf based panic() function.
Tick curTick()
The current simulated tick.
bool sendReal(const void *data, size_t len) override
Abstract superclass for simulation objects.
Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17