ARM: Add snoop control unit device.
[gem5.git] / src / dev / ethertap.cc
index 2d72383c5c6f83f0d55fbc8b8d28a43d1041a029..2a85aa524d94fc5dcc67c6e86428625b9aa174f9 100644 (file)
@@ -36,7 +36,6 @@
 #include <sys/param.h>
 #endif
 #include <netinet/in.h>
-
 #include <unistd.h>
 
 #include <deque>
 #include "base/pollevent.hh"
 #include "base/socket.hh"
 #include "base/trace.hh"
+#include "debug/Ethernet.hh"
+#include "debug/EthernetData.hh"
 #include "dev/etherdump.hh"
 #include "dev/etherint.hh"
 #include "dev/etherpkt.hh"
 #include "dev/ethertap.hh"
-#include "sim/builder.hh"
 
 using namespace std;
 
@@ -127,13 +127,17 @@ class TapEvent : public PollEvent
     virtual void process(int revent) { tap->process(revent); }
 };
 
-EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz)
-    : EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d),
-      txEvent(this)
+EtherTap::EtherTap(const Params *p)
+    : EtherObject(p), event(NULL), socket(-1), buflen(p->bufsz), dump(p->dump),
+      interface(NULL), txEvent(this)
 {
+    if (ListenSocket::allDisabled())
+        fatal("All listeners are disabled! EtherTap can't work!");
+
     buffer = new char[buflen];
-    listener = new TapListener(this, port);
+    listener = new TapListener(this, p->port);
     listener->listen();
+    interface = new EtherTapInt(name() + ".interface", this);
 }
 
 EtherTap::~EtherTap()
@@ -178,11 +182,15 @@ EtherTap::recvPacket(EthPacketPtr packet)
 
     DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
     DDUMP(EthernetData, packet->data, packet->length);
-    u_int32_t len = htonl(packet->length);
-    write(socket, &len, sizeof(len));
-    write(socket, 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;
 
-    recvDone();
+    interface->recvDone();
 
     return true;
 }
@@ -199,11 +207,11 @@ EtherTap::process(int revent)
         return;
     }
 
-    char *data = buffer + sizeof(u_int32_t);
+    char *data = buffer + sizeof(uint32_t);
     if (!(revent & POLLIN))
         return;
 
-    if (buffer_offset < data_len + sizeof(u_int32_t)) {
+    if (buffer_offset < data_len + sizeof(uint32_t)) {
         int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
         if (len == 0) {
             detach();
@@ -213,33 +221,33 @@ EtherTap::process(int revent)
         buffer_offset += len;
 
         if (data_len == 0)
-            data_len = ntohl(*(u_int32_t *)buffer);
+            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);
     }
 
-    while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
+    while (data_len != 0 && buffer_offset >= data_len + sizeof(uint32_t)) {
         EthPacketPtr packet;
         packet = new EthPacketData(data_len);
         packet->length = data_len;
         memcpy(packet->data, data, data_len);
 
-        buffer_offset -= data_len + sizeof(u_int32_t);
+        buffer_offset -= data_len + sizeof(uint32_t);
         assert(buffer_offset >= 0);
         if (buffer_offset > 0) {
             memmove(buffer, data + data_len, buffer_offset);
-            data_len = ntohl(*(u_int32_t *)buffer);
+            data_len = ntohl(*(uint32_t *)buffer);
         } else
             data_len = 0;
 
         DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
         DDUMP(EthernetData, packet->data, packet->length);
-        if (!sendPacket(packet)) {
+        if (!interface->sendPacket(packet)) {
             DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
             packetBuffer.push(packet);
             if (!txEvent.scheduled())
-                txEvent.schedule(curTick + retryTime);
+                schedule(txEvent, curTick() + retryTime);
         } else if (dump) {
             dump->dump(packet);
         }
@@ -253,7 +261,7 @@ EtherTap::retransmit()
         return;
 
     EthPacketPtr packet = packetBuffer.front();
-    if (sendPacket(packet)) {
+    if (interface->sendPacket(packet)) {
         if (dump)
             dump->dump(packet);
         DPRINTF(Ethernet, "EtherTap retransmit\n");
@@ -262,9 +270,21 @@ EtherTap::retransmit()
     }
 
     if (!packetBuffer.empty() && !txEvent.scheduled())
-        txEvent.schedule(curTick + retryTime);
+        schedule(txEvent, curTick() + retryTime);
 }
 
+EtherInt*
+EtherTap::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;
+}
+
+
 //=====================================================================
 
 void
@@ -313,35 +333,8 @@ EtherTap::unserialize(Checkpoint *cp, const std::string &section)
 
 //=====================================================================
 
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
-
-    SimObjectParam<EtherInt *> peer;
-    SimObjectParam<EtherDump *> dump;
-    Param<unsigned> port;
-    Param<unsigned> bufsz;
-
-END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
-
-    INIT_PARAM_DFLT(peer, "peer interface", NULL),
-    INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL),
-    INIT_PARAM_DFLT(port, "tap port", 3500),
-    INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
-
-END_INIT_SIM_OBJECT_PARAMS(EtherTap)
-
-
-CREATE_SIM_OBJECT(EtherTap)
+EtherTap *
+EtherTapParams::create()
 {
-    EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz);
-
-    if (peer) {
-        tap->setPeer(peer);
-        peer->setPeer(tap);
-    }
-
-    return tap;
+    return new EtherTap(this);
 }
-
-REGISTER_SIM_OBJECT("EtherTap", EtherTap)