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")
98 interface = new EtherTapInt(name() + ".interface", this);
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");
259 while (!listener.listen(port,
true)) {
260 DPRINTF(Ethernet,
"TapListener(listen): Can't bind port %d\n", port);
264 ccprintf(cerr,
"Listening for tap connection on port %d\n", port);
265 event =
new Event(
this, listener.getfd(), POLLIN|POLLERR);
277 if (!listener.islistening())
278 panic(
"TapListener(accept): cannot accept if we're not listening!");
280 int sfd = listener.accept(
true);
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)];
393 ssize_t ret = write(
socket, &frame_len,
sizeof(frame_len));
394 if (ret !=
sizeof(frame_len))
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))
441 panic(
"Failed to read from tap device.\n");
449 EtherTap::sendReal(
const void *
data,
size_t len)
454 pfd->events = POLLOUT;
458 while ((n = write(tap,
data, len)) != len) {
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 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)
#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.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
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
std::shared_ptr< EthPacketData > EthPacketPtr
void schedule(Event &event, Tick when)
bool sendReal(const void *data, size_t len) override
EtherTapBase(const Params *p)
#define SERIALIZE_ARRAY(member, size)
#define SERIALIZE_SCALAR(scalar)
void process(int revent) override
bool scheduled() const
Determine if the current event is scheduled.
bool sendPacket(EthPacketPtr packet)
Event(TapListener *l, int fd, int e)
#define UNSERIALIZE_ARRAY(member, size)
Event(Priority p=Default_Pri, Flags f=0)
virtual void recvReal(int revent)=0
std::ostream CheckpointOut
EtherTapBaseParams Params
EventQueue * eventQueue() const
TapEvent(EtherTapBase *_tap, int fd, int e)
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