35#if defined(__OpenBSD__) || defined(__APPLE__)
40#if HAVE_TUNTAP && defined(__linux__)
42#include <sys/socket.h>
47#include <linux/if_tun.h>
52#include <netinet/in.h>
64#include "debug/Ethernet.hh"
65#include "debug/EthernetData.hh"
98 txEvent([this]{
retransmit(); },
"EtherTapBase retransmit")
100 buffer =
new uint8_t[buflen];
115 uint8_t *
buffer = (uint8_t *)this->buffer;
118 bool tapevent_present =
false;
120 tapevent_present =
true;
122 event->serialize(cp);
132 uint8_t *
buffer = (uint8_t *)this->buffer;
135 bool tapevent_present;
137 if (tapevent_present) {
139 event->unserialize(cp);
150 event =
new TapEvent(
this,
fd, POLLIN|POLLERR);
166 if (if_name ==
"tap")
177 DPRINTF(Ethernet,
"EtherTap sim->real len=%d\n", packet->length);
178 DDUMP(EthernetData, packet->data, packet->length);
180 bool success =
sendReal(packet->data, packet->length);
191 packet = std::make_shared<EthPacketData>(
len);
192 packet->length =
len;
193 packet->simLength =
len;
194 memcpy(packet->data,
data,
len);
196 DPRINTF(Ethernet,
"EtherTap real->sim len=%d\n", packet->length);
197 DDUMP(EthernetData, packet->data, packet->length);
199 DPRINTF(Ethernet,
"bus busy...buffer for retransmission\n");
218 DPRINTF(Ethernet,
"EtherTap retransmit\n");
277 panic(
"TapListener(accept): cannot accept if we're not listening!");
288 fatal(
"All listeners are disabled! EtherTapStub can't work!");
329 DPRINTF(Ethernet,
"EtherTapStub attached\n");
336 DPRINTF(Ethernet,
"EtherTapStub detached\n");
345 if (revent & POLLERR) {
350 if (!(revent & POLLIN))
368 DPRINTF(Ethernet,
"Received data from peer: len=%d buffer_used=%d "
371 uint8_t *frame_start = &
buffer[
sizeof(uint32_t)];
403 int fd = open(
p.tun_clone_device.c_str(), O_RDWR | O_NONBLOCK);
405 panic(
"Couldn't open %s.\n",
p.tun_clone_device);
408 memset(&ifr, 0,
sizeof(ifr));
409 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
410 strncpy(ifr.ifr_name,
p.tap_device_name.c_str(), IFNAMSIZ - 1);
412 if (ioctl(
fd, TUNSETIFF, (
void *)&ifr) < 0)
413 panic(
"Failed to access tap device %s.\n", ifr.ifr_name);
427EtherTap::recvReal(
int revent)
429 if (revent & POLLERR)
430 panic(
"Error polling for tap data.\n");
432 if (!(revent & POLLIN))
436 while ((ret = read(tap, buffer, buflen))) {
440 panic(
"Failed to read from tap device.\n");
443 sendSimulated(buffer, ret);
448EtherTap::sendReal(
const void *
data,
size_t len)
453 pfd->events = POLLOUT;
459 panic(
"Failed to write data to tap device.\n");
461 int ret = poll(pfd, 1, -1);
464 if (ret == -1 || (ret == 1 && (pfd->revents & POLLERR))) {
465 panic(
"Failed when polling to write data to tap device.\n");
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
void dump(EthPacketPtr &pkt)
bool sendPacket(EthPacketPtr packet)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void sendSimulated(void *data, size_t len)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
EtherTapBaseParams Params
virtual void recvReal(int revent)=0
bool recvSimulated(EthPacketPtr packet)
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::queue< EthPacketPtr > packetBuffer
virtual bool sendReal(const void *data, size_t len)=0
EventFunctionWrapper txEvent
EtherTapBase(const Params &p)
EtherTapStub(const Params &p)
void serialize(CheckpointOut &cp) const override
Serialize an object.
EtherTapStubParams Params
void recvReal(int revent) override
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool sendReal(const void *data, size_t len) override
static bool allDisabled()
virtual std::string name() const
Ports are used to interface objects to each other.
Abstract superclass for simulation objects.
TapEvent(EtherTapBase *_tap, int fd, int e)
void process(int revent) override
void process(int revent) override
Event(TapListener *l, int fd, int e)
TapListener(EtherTapStub *t, ListenSocketPtr _listener)
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
EventQueue * eventQueue() const
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
void schedule(PollEvent *event)
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
void dump()
Dump all statistics data to the registered outputs.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
std::unique_ptr< ListenSocket > ListenSocketPtr
std::shared_ptr< EthPacketData > EthPacketPtr
Overload hash function for BasicBlockRange type.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()