37 #if defined(__OpenBSD__) || defined(__APPLE__) 38 #include <sys/param.h> 42 #if USE_TUNTAP && defined(__linux__) 43 #if 1 // Hide from the style checker since these have to be out of order. 44 #include <sys/socket.h> 49 #include <linux/if_tun.h> 54 #include <netinet/in.h> 55 #include <sys/ioctl.h> 66 #include "debug/Ethernet.hh" 67 #include "debug/EthernetData.hh" 97 txEvent([this]{
retransmit(); },
"EtherTapBase retransmit")
100 interface = new EtherTapInt(name() + ".interface", this);
114 uint8_t *
buffer = (uint8_t *)this->buffer;
117 bool tapevent_present =
false;
119 tapevent_present =
true;
121 event->serialize(cp);
131 uint8_t *
buffer = (uint8_t *)this->buffer;
134 bool tapevent_present;
136 if (tapevent_present) {
138 event->unserialize(cp);
149 event =
new TapEvent(
this, fd, POLLIN|POLLERR);
165 if (if_name ==
"tap")
176 DPRINTF(Ethernet,
"EtherTap sim->real len=%d\n", packet->length);
177 DDUMP(EthernetData, packet->data, packet->length);
179 bool success =
sendReal(packet->data, packet->length);
190 packet = make_shared<EthPacketData>(
len);
191 packet->length =
len;
192 packet->simLength =
len;
193 memcpy(packet->data, data, len);
195 DPRINTF(Ethernet,
"EtherTap real->sim len=%d\n", packet->length);
196 DDUMP(EthernetData, packet->data, packet->length);
198 DPRINTF(Ethernet,
"bus busy...buffer for retransmission\n");
217 DPRINTF(Ethernet,
"EtherTap retransmit\n");
261 while (!listener.listen(port,
true)) {
262 DPRINTF(Ethernet,
"TapListener(listen): Can't bind port %d\n", port);
266 ccprintf(cerr,
"Listening for tap connection on port %d\n", port);
267 event =
new Event(
this, listener.getfd(), POLLIN|POLLERR);
279 if (!listener.islistening())
280 panic(
"TapListener(accept): cannot accept if we're not listening!");
282 int sfd = listener.accept(
true);
291 fatal(
"All listeners are disabled! EtherTapStub can't work!");
332 DPRINTF(Ethernet,
"EtherTapStub attached\n");
339 DPRINTF(Ethernet,
"EtherTapStub detached\n");
348 if (revent & POLLERR) {
353 if (!(revent & POLLIN))
371 DPRINTF(Ethernet,
"Received data from peer: len=%d buffer_used=%d " 374 uint8_t *frame_start = &buffer[
sizeof(uint32_t)];
395 ssize_t ret = write(
socket, &frame_len,
sizeof(frame_len));
396 if (ret !=
sizeof(frame_len))
406 int fd = open(
p->tun_clone_device.c_str(), O_RDWR | O_NONBLOCK);
408 panic(
"Couldn't open %s.\n",
p->tun_clone_device);
411 memset(&ifr, 0,
sizeof(ifr));
412 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
413 strncpy(ifr.ifr_name,
p->tap_device_name.c_str(), IFNAMSIZ - 1);
415 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0)
416 panic(
"Failed to access tap device %s.\n", ifr.ifr_name);
422 EtherTap::~EtherTap()
430 EtherTap::recvReal(
int revent)
432 if (revent & POLLERR)
433 panic(
"Error polling for tap data.\n");
435 if (!(revent & POLLIN))
443 panic(
"Failed to read from tap device.\n");
451 EtherTap::sendReal(
const void *
data,
size_t len)
456 pfd->events = POLLOUT;
460 while ((n = write(tap,
data, len)) != len) {
462 panic(
"Failed to write data to tap device.\n");
464 int ret = poll(pfd, 1, -1);
467 if (ret == -1 || (ret == 1 && (pfd->revents & POLLERR))) {
468 panic(
"Failed when polling to write data to tap device.\n");
475 EtherTapParams::create()
477 return new EtherTap(
this);
483 EtherTapStubParams::create()
#define panic(...)
This implements a cprintf based panic() function.
void ccprintf(cp::Print &print)
Ports are used to interface objects to each other.
EtherTapStub(const Params *p)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define fatal(...)
This implements a cprintf based fatal() function.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void serialize(CheckpointOut &cp) const override
Serialize an object.
TapListener(EtherTapStub *t, int p)
void sendSimulated(void *data, size_t len)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
#define DDUMP(x, data, count)
Overload hash function for BasicBlockRange type.
void schedule(PollEvent *event)
#define UNSERIALIZE_SCALAR(scalar)
Tick curTick()
The current simulated tick.
Temporarily migrate execution to a different event queue.
bool scheduled() const
Determine if the current event is scheduled.
EventFunctionWrapper txEvent
bool recvSimulated(EthPacketPtr packet)
static bool allDisabled()
void dump(EthPacketPtr &pkt)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
virtual bool sendReal(const void *data, size_t len)=0
#define SERIALIZE_ARRAY(member, size)
std::shared_ptr< EthPacketData > EthPacketPtr
bool sendReal(const void *data, size_t len) override
EtherTapBase(const Params *p)
#define SERIALIZE_SCALAR(scalar)
void process(int revent) override
#define UNSERIALIZE_ARRAY(member, size)
bool sendPacket(EthPacketPtr packet)
Event(TapListener *l, int fd, int e)
EventQueue * eventQueue() const
Event(Priority p=Default_Pri, Flags f=0)
virtual void recvReal(int revent)=0
std::ostream CheckpointOut
EtherTapBaseParams Params
TapEvent(EtherTapBase *_tap, int fd, int e)
void schedule(Event &event, Tick when)
std::queue< EthPacketPtr > packetBuffer
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
void dump()
Dump all statistics data to the registered outputs.
void recvReal(int revent) override
Abstract superclass for simulation objects.
void process(int revent) override