59,60c59,204
< /**
< */
---
> class TapEvent : public PollEvent
> {
> protected:
> EtherTapBase *tap;
>
> public:
> TapEvent(EtherTapBase *_tap, int fd, int e)
> : PollEvent(fd, e), tap(_tap) {}
> virtual void process(int revent) { tap->recvReal(revent); }
> };
>
> EtherTapBase::EtherTapBase(const Params *p)
> : EtherObject(p), buflen(p->bufsz), dump(p->dump), event(NULL),
> interface(NULL), txEvent(this)
> {
> buffer = new uint8_t[buflen];
> interface = new EtherTapInt(name() + ".interface", this);
> }
>
> EtherTapBase::~EtherTapBase()
> {
> delete buffer;
> delete event;
> delete interface;
> }
>
> void
> EtherTapBase::serialize(CheckpointOut &cp) const
> {
> SERIALIZE_SCALAR(buflen);
> uint8_t *buffer = (uint8_t *)this->buffer;
> SERIALIZE_ARRAY(buffer, buflen);
>
> bool tapevent_present = false;
> if (event) {
> tapevent_present = true;
> SERIALIZE_SCALAR(tapevent_present);
> event->serialize(cp);
> } else {
> SERIALIZE_SCALAR(tapevent_present);
> }
> }
>
> void
> EtherTapBase::unserialize(CheckpointIn &cp)
> {
> UNSERIALIZE_SCALAR(buflen);
> uint8_t *buffer = (uint8_t *)this->buffer;
> UNSERIALIZE_ARRAY(buffer, buflen);
>
> bool tapevent_present;
> UNSERIALIZE_SCALAR(tapevent_present);
> if (tapevent_present) {
> event = new TapEvent(this, 0, 0);
> event->unserialize(cp);
> if (event->queued())
> pollQueue.schedule(event);
> }
> }
>
>
> void
> EtherTapBase::pollFd(int fd)
> {
> assert(!event);
> event = new TapEvent(this, fd, POLLIN|POLLERR);
> pollQueue.schedule(event);
> }
>
> void
> EtherTapBase::stopPolling()
> {
> assert(event);
> delete event;
> event = NULL;
> }
>
>
> EtherInt*
> EtherTapBase::getEthPort(const std::string &if_name, int idx)
> {
> if (if_name == "tap") {
> if (interface->getPeer())
> panic("Interface already connected to\n");
> return interface;
> }
> return NULL;
> }
>
> bool
> EtherTapBase::recvSimulated(EthPacketPtr packet)
> {
> if (dump)
> dump->dump(packet);
>
> DPRINTF(Ethernet, "EtherTap sim->real len=%d\n", packet->length);
> DDUMP(EthernetData, packet->data, packet->length);
>
> bool success = sendReal(packet->data, packet->length);
>
> interface->recvDone();
>
> return success;
> }
>
> void
> EtherTapBase::sendSimulated(void *data, size_t len)
> {
> EthPacketPtr packet;
> packet = make_shared<EthPacketData>(len);
> packet->length = len;
> packet->simLength = len;
> memcpy(packet->data, data, len);
>
> DPRINTF(Ethernet, "EtherTap real->sim len=%d\n", packet->length);
> DDUMP(EthernetData, packet->data, packet->length);
> if (!packetBuffer.empty() || !interface->sendPacket(packet)) {
> DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
> packetBuffer.push(packet);
> if (!txEvent.scheduled())
> schedule(txEvent, curTick() + retryTime);
> } else if (dump) {
> dump->dump(packet);
> }
> }
>
> void
> EtherTapBase::retransmit()
> {
> if (packetBuffer.empty())
> return;
>
> EthPacketPtr packet = packetBuffer.front();
> if (interface->sendPacket(packet)) {
> if (dump)
> dump->dump(packet);
> DPRINTF(Ethernet, "EtherTap retransmit\n");
> packetBuffer.front() = NULL;
> packetBuffer.pop();
> }
>
> if (!packetBuffer.empty() && !txEvent.scheduled())
> schedule(txEvent, curTick() + retryTime);
> }
>
>
64,65d207
< /**
< */
72,73c214
< Event(TapListener *l, int fd, int e)
< : PollEvent(fd, e), listener(l) {}
---
> Event(TapListener *l, int fd, int e) : PollEvent(fd, e), listener(l) {}
75c216
< virtual void process(int revent) { listener->accept(); }
---
> void process(int revent) override { listener->accept(); }
80a222,223
> void accept();
>
87,89c230,231
< TapListener(EtherTapStub *t, int p)
< : event(NULL), tap(t), port(p) {}
< ~TapListener() { if (event) delete event; }
---
> TapListener(EtherTapStub *t, int p) : event(NULL), tap(t), port(p) {}
> ~TapListener() { delete event; }
91d232
< void accept();
124,129d264
< /**
< */
< class TapEvent : public PollEvent
< {
< protected:
< EtherTapStub *tap;
131,139c266
< public:
< TapEvent(EtherTapStub *_tap, int fd, int e)
< : PollEvent(fd, e), tap(_tap) {}
< virtual void process(int revent) { tap->process(revent); }
< };
<
< EtherTapStub::EtherTapStub(const Params *p)
< : EtherObject(p), event(NULL), socket(-1), buflen(p->bufsz), dump(p->dump),
< interface(NULL), txEvent(this)
---
> EtherTapStub::EtherTapStub(const Params *p) : EtherTapBase(p), socket(-1)
144d270
< buffer = new char[buflen];
147d272
< interface = new EtherTapInt(name() + ".interface", this);
152,157d276
< if (event)
< delete event;
< if (buffer)
< delete [] buffer;
<
< delete interface;
161a281,301
> EtherTapStub::serialize(CheckpointOut &cp) const
> {
> EtherTapBase::serialize(cp);
>
> SERIALIZE_SCALAR(socket);
> SERIALIZE_SCALAR(buffer_used);
> SERIALIZE_SCALAR(frame_len);
> }
>
> void
> EtherTapStub::unserialize(CheckpointIn &cp)
> {
> EtherTapBase::unserialize(cp);
>
> UNSERIALIZE_SCALAR(socket);
> UNSERIALIZE_SCALAR(buffer_used);
> UNSERIALIZE_SCALAR(frame_len);
> }
>
>
> void
167,168c307,308
< buffer_offset = 0;
< data_len = 0;
---
> buffer_used = 0;
> frame_len = 0;
171,172c311
< event = new TapEvent(this, socket, POLLIN|POLLERR);
< pollQueue.schedule(event);
---
> pollFd(socket);
179,180c318
< delete event;
< event = 0;
---
> stopPolling();
185,205d322
< bool
< EtherTapStub::recvPacket(EthPacketPtr packet)
< {
< if (dump)
< dump->dump(packet);
<
< DPRINTF(Ethernet, "EtherTapStub output len=%d\n", packet->length);
< DDUMP(EthernetData, packet->data, packet->length);
< uint32_t len = htonl(packet->length);
< ssize_t ret = write(socket, &len, sizeof(len));
< if (ret != sizeof(len))
< return false;
< ret = write(socket, packet->data, packet->length);
< if (ret != packet->length)
< return false;
<
< interface->recvDone();
<
< return true;
< }
<
207,211c324
< EtherTapStub::sendDone()
< {}
<
< void
< EtherTapStub::process(int revent)
---
> EtherTapStub::recvReal(int revent)
218d330
< char *data = buffer + sizeof(uint32_t);
222,235c334,338
< if (buffer_offset < data_len + sizeof(uint32_t)) {
< int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
< if (len == 0) {
< detach();
< return;
< }
<
< buffer_offset += len;
<
< if (data_len == 0)
< data_len = ntohl(*(uint32_t *)buffer);
<
< DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
< "data_len=%d\n", len, buffer_offset, data_len);
---
> // Read in as much of the new data as we can.
> int len = read(socket, buffer + buffer_used, buflen - buffer_used);
> if (len == 0) {
> detach();
> return;
236a340
> buffer_used += len;
238,269c342,343
< while (data_len != 0 && buffer_offset >= data_len + sizeof(uint32_t)) {
< EthPacketPtr packet;
< packet = make_shared<EthPacketData>(data_len);
< packet->length = data_len;
< packet->simLength = data_len;
< memcpy(packet->data, data, data_len);
<
< assert(buffer_offset >= data_len + sizeof(uint32_t));
< buffer_offset -= data_len + sizeof(uint32_t);
< if (buffer_offset > 0) {
< memmove(buffer, data + data_len, buffer_offset);
< data_len = ntohl(*(uint32_t *)buffer);
< } else
< data_len = 0;
<
< DPRINTF(Ethernet, "EtherTapStub input len=%d\n", packet->length);
< DDUMP(EthernetData, packet->data, packet->length);
< if (!interface->sendPacket(packet)) {
< DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
< packetBuffer.push(packet);
< if (!txEvent.scheduled())
< schedule(txEvent, curTick() + retryTime);
< } else if (dump) {
< dump->dump(packet);
< }
< }
< }
<
< void
< EtherTapStub::retransmit()
< {
< if (packetBuffer.empty())
---
> // If there's not enough data for the frame length, wait for more.
> if (buffer_used < sizeof(uint32_t))
272,279c346,347
< EthPacketPtr packet = packetBuffer.front();
< if (interface->sendPacket(packet)) {
< if (dump)
< dump->dump(packet);
< DPRINTF(Ethernet, "EtherTapStub retransmit\n");
< packetBuffer.front() = NULL;
< packetBuffer.pop();
< }
---
> if (frame_len == 0)
> frame_len = ntohl(*(uint32_t *)buffer);
281,283c349,350
< if (!packetBuffer.empty() && !txEvent.scheduled())
< schedule(txEvent, curTick() + retryTime);
< }
---
> DPRINTF(Ethernet, "Received data from peer: len=%d buffer_used=%d "
> "frame_len=%d\n", len, buffer_used, frame_len);
285,294c352,354
< EtherInt*
< EtherTapStub::getEthPort(const std::string &if_name, int idx)
< {
< if (if_name == "tap") {
< if (interface->getPeer())
< panic("Interface already connected to\n");
< return interface;
< }
< return NULL;
< }
---
> uint8_t *frame_start = &buffer[sizeof(uint32_t)];
> while (frame_len != 0 && buffer_used >= frame_len + sizeof(uint32_t)) {
> sendSimulated(frame_start, frame_len);
295a356,362
> // Bookkeeping.
> buffer_used -= frame_len + sizeof(uint32_t);
> if (buffer_used > 0) {
> // If there's still any data left, move it into position.
> memmove(buffer, frame_start + frame_len, buffer_used);
> }
> frame_len = 0;
297,313c364,365
< //=====================================================================
<
< void
< EtherTapStub::serialize(CheckpointOut &cp) const
< {
< SERIALIZE_SCALAR(socket);
< SERIALIZE_SCALAR(buflen);
< uint8_t *buffer = (uint8_t *)this->buffer;
< SERIALIZE_ARRAY(buffer, buflen);
< SERIALIZE_SCALAR(buffer_offset);
< SERIALIZE_SCALAR(data_len);
<
< bool tapevent_present = false;
< if (event) {
< tapevent_present = true;
< SERIALIZE_SCALAR(tapevent_present);
< event->serialize(cp);
---
> if (buffer_used >= sizeof(uint32_t))
> frame_len = ntohl(*(uint32_t *)buffer);
315,317d366
< else {
< SERIALIZE_SCALAR(tapevent_present);
< }
320,321c369,370
< void
< EtherTapStub::unserialize(CheckpointIn &cp)
---
> bool
> EtherTapStub::sendReal(const void *data, size_t len)
323,340c372,376
< UNSERIALIZE_SCALAR(socket);
< UNSERIALIZE_SCALAR(buflen);
< uint8_t *buffer = (uint8_t *)this->buffer;
< UNSERIALIZE_ARRAY(buffer, buflen);
< UNSERIALIZE_SCALAR(buffer_offset);
< UNSERIALIZE_SCALAR(data_len);
<
< bool tapevent_present;
< UNSERIALIZE_SCALAR(tapevent_present);
< if (tapevent_present) {
< event = new TapEvent(this, socket, POLLIN|POLLERR);
<
< event->unserialize(cp);
<
< if (event->queued()) {
< pollQueue.schedule(event);
< }
< }
---
> uint32_t frame_len = htonl(len);
> ssize_t ret = write(socket, &frame_len, sizeof(frame_len));
> if (ret != sizeof(frame_len))
> return false;
> return write(socket, data, len) == len;
343d378
< //=====================================================================