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"
82 virtual void process(
int revent) { tap->recvReal(revent); }
87 interface(NULL), txEvent(this)
90 interface = new EtherTapInt(name() + ".interface", this);
104 uint8_t *
buffer = (uint8_t *)this->buffer;
107 bool tapevent_present =
false;
109 tapevent_present =
true;
111 event->serialize(cp);
121 uint8_t *
buffer = (uint8_t *)this->buffer;
124 bool tapevent_present;
126 if (tapevent_present) {
128 event->unserialize(cp);
139 event =
new TapEvent(
this, fd, POLLIN|POLLERR);
155 if (if_name ==
"tap") {
157 panic(
"Interface already connected to\n");
169 DPRINTF(Ethernet,
"EtherTap sim->real len=%d\n", packet->length);
170 DDUMP(EthernetData, packet->data, packet->length);
172 bool success =
sendReal(packet->data, packet->length);
183 packet = make_shared<EthPacketData>(
len);
184 packet->length =
len;
185 packet->simLength =
len;
186 memcpy(packet->data, data, len);
188 DPRINTF(Ethernet,
"EtherTap real->sim len=%d\n", packet->length);
189 DDUMP(EthernetData, packet->data, packet->length);
191 DPRINTF(Ethernet,
"bus busy...buffer for retransmission\n");
210 DPRINTF(Ethernet,
"EtherTap retransmit\n");
255 DPRINTF(Ethernet,
"TapListener(listen): Can't bind port %d\n",
port);
259 ccprintf(cerr,
"Listening for tap connection on port %d\n",
port);
273 panic(
"TapListener(accept): cannot accept if we're not listening!");
284 fatal(
"All listeners are disabled! EtherTapStub can't work!");
325 DPRINTF(Ethernet,
"EtherTapStub attached\n");
332 DPRINTF(Ethernet,
"EtherTapStub detached\n");
341 if (revent & POLLERR) {
346 if (!(revent & POLLIN))
364 DPRINTF(Ethernet,
"Received data from peer: len=%d buffer_used=%d "
367 uint8_t *frame_start = &
buffer[
sizeof(uint32_t)];
388 ssize_t ret = write(
socket, &frame_len,
sizeof(frame_len));
389 if (ret !=
sizeof(frame_len))
399 int fd = open(p->tun_clone_device.c_str(), O_RDWR);
401 panic(
"Couldn't open %s.\n", p->tun_clone_device);
404 memset(&ifr, 0,
sizeof(ifr));
405 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
406 strncpy(ifr.ifr_name, p->tap_device_name.c_str(), IFNAMSIZ);
408 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0)
409 panic(
"Failed to access tap device %s.\n", ifr.ifr_name);
415 EtherTap::~EtherTap()
423 EtherTap::recvReal(
int revent)
425 if (revent & POLLERR)
426 panic(
"Error polling for tap data.\n");
428 if (!(revent & POLLIN))
431 ssize_t ret = read(tap, buffer, buflen);
433 panic(
"Failed to read from tap device.\n");
435 sendSimulated(buffer, ret);
439 EtherTap::sendReal(
const void *
data,
size_t len)
441 if (write(tap, data, len) != len)
442 panic(
"Failed to write data to tap device.\n");
447 EtherTapParams::create()
449 return new EtherTap(
this);
455 EtherTapStubParams::create()
void ccprintf(cp::Print &print)
EtherTapStub(const Params *p)
virtual bool listen(int port, bool reuse=true)
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)
bool scheduled() const
Determine if the current event is scheduled.
#define DDUMP(x, data, count)
void schedule(PollEvent *event)
#define UNSERIALIZE_SCALAR(scalar)
Tick curTick()
The current simulated tick.
Temporarily migrate execution to a different event queue.
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
virtual int accept(bool nodelay=false)
bool sendReal(const void *data, size_t len) override
EtherTapBase(const Params *p)
virtual void process(int revent)
EventQueue * eventQueue() const
The base EtherObject class, allows for an accesor function to a simobj that returns the Port...
#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)
std::ostream CheckpointOut
TapEvent(EtherTapBase *_tap, int fd, int e)
void schedule(Event &event, Tick when)
EtherInt * getEthPort(const std::string &if_name, int idx) override
Additional function to return the Port of a memory object.
std::queue< EthPacketPtr > packetBuffer
void dump()
Dump all statistics data to the registered outputs.
void recvReal(int revent) override