etherlink.cc revision 1435
1/* 2 * Copyright (c) 2002-2004 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* @file 30 * Device module for modelling a fixed bandwidth full duplex ethernet link 31 */ 32 33#include <cmath> 34#include <deque> 35#include <string> 36#include <vector> 37 38#include "base/trace.hh" 39#include "dev/etherdump.hh" 40#include "dev/etherint.hh" 41#include "dev/etherlink.hh" 42#include "dev/etherpkt.hh" 43#include "sim/builder.hh" 44#include "sim/serialize.hh" 45#include "sim/system.hh" 46#include "sim/universe.hh" 47 48using namespace std; 49 50EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 51 Tick speed, Tick dly, EtherDump *dump) 52 : SimObject(name) 53{ 54 double rate = ((double)ticksPerSecond * 8.0) / (double)speed; 55 Tick delay = US2Ticks(dly); 56 57 link[0] = new Link(name + ".link0", this, 0, rate, delay, dump); 58 link[1] = new Link(name + ".link1", this, 1, rate, delay, dump); 59 60 interface[0] = new Interface(name + ".int0", link[0], link[1]); 61 interface[1] = new Interface(name + ".int1", link[1], link[0]); 62 63 interface[0]->setPeer(peer0); 64 peer0->setPeer(interface[0]); 65 interface[1]->setPeer(peer1); 66 peer1->setPeer(interface[1]); 67} 68 69EtherLink::~EtherLink() 70{ 71 delete link[0]; 72 delete link[1]; 73 74 delete interface[0]; 75 delete interface[1]; 76} 77 78EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 79 : EtherInt(name), txlink(tx) 80{ 81 tx->setTxInt(this); 82 rx->setRxInt(this); 83} 84 85EtherLink::Link::Link(const string &name, EtherLink *p, int num, 86 double rate, Tick delay, EtherDump *d) 87 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 88 ticksPerByte(rate), linkDelay(delay), dump(d), 89 doneEvent(this) 90{ } 91 92void 93EtherLink::serialize(ostream &os) 94{ 95 link[0]->serialize("link0", os); 96 link[1]->serialize("link1", os); 97} 98 99void 100EtherLink::unserialize(Checkpoint *cp, const string §ion) 101{ 102 link[0]->unserialize("link0", cp, section); 103 link[1]->unserialize("link1", cp, section); 104} 105 106void 107EtherLink::Link::txComplete(PacketPtr packet) 108{ 109 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 110 DDUMP(EthernetData, packet->data, packet->length); 111 rxint->sendPacket(packet); 112} 113 114class LinkDelayEvent : public Event 115{ 116 protected: 117 EtherLink::Link *link; 118 PacketPtr packet; 119 120 public: 121 // non-scheduling version for createForUnserialize() 122 LinkDelayEvent(); 123 LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); 124 125 void process(); 126 127 virtual void serialize(ostream &os); 128 virtual void unserialize(Checkpoint *cp, const string §ion); 129 static Serializable *createForUnserialize(Checkpoint *cp, 130 const string §ion); 131}; 132 133void 134EtherLink::Link::txDone() 135{ 136 if (dump) 137 dump->dump(packet); 138 139 if (linkDelay > 0) { 140 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 141 new LinkDelayEvent(this, packet, curTick + linkDelay); 142 } else { 143 txComplete(packet); 144 } 145 146 packet = 0; 147 assert(!busy()); 148 149 txint->sendDone(); 150} 151 152bool 153EtherLink::Link::transmit(PacketPtr pkt) 154{ 155 if (busy()) { 156 DPRINTF(Ethernet, "packet not sent, link busy\n"); 157 return false; 158 } 159 160 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 161 DDUMP(EthernetData, pkt->data, pkt->length); 162 163 packet = pkt; 164 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 165 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 166 delay, ticksPerByte); 167 doneEvent.schedule(curTick + delay); 168 169 return true; 170} 171 172void 173EtherLink::Link::serialize(const string &base, ostream &os) 174{ 175 bool packet_exists = packet; 176 paramOut(os, base + ".packet_exists", packet_exists); 177 if (packet_exists) 178 packet->serialize(base + ".packet", os); 179 180 bool event_scheduled = doneEvent.scheduled(); 181 paramOut(os, base + ".event_scheuled", event_scheduled); 182 if (event_scheduled) { 183 Tick event_time = doneEvent.when(); 184 paramOut(os, base + ".event_time", event_time); 185 } 186 187} 188 189void 190EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 191 const string §ion) 192{ 193 bool packet_exists; 194 paramIn(cp, section, base + ".packet_exists", packet_exists); 195 if (packet_exists) { 196 packet = new PacketData(16384); 197 packet->unserialize(base + ".packet", cp, section); 198 } 199 200 bool event_scheduled; 201 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 202 if (event_scheduled) { 203 Tick event_time; 204 paramIn(cp, section, base + ".event_time", event_time); 205 doneEvent.schedule(event_time); 206 } 207} 208 209LinkDelayEvent::LinkDelayEvent() 210 : Event(&mainEventQueue), link(NULL) 211{ 212 setFlags(AutoSerialize); 213 setFlags(AutoDelete); 214} 215 216LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) 217 : Event(&mainEventQueue), link(l), packet(p) 218{ 219 setFlags(AutoSerialize); 220 setFlags(AutoDelete); 221 schedule(when); 222} 223 224void 225LinkDelayEvent::process() 226{ 227 link->txComplete(packet); 228} 229 230void 231LinkDelayEvent::serialize(ostream &os) 232{ 233 paramOut(os, "type", string("LinkDelayEvent")); 234 Event::serialize(os); 235 236 EtherLink *parent = link->parent; 237 bool number = link->number; 238 SERIALIZE_OBJPTR(parent); 239 SERIALIZE_SCALAR(number); 240 241 packet->serialize("packet", os); 242} 243 244 245void 246LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 247{ 248 Event::unserialize(cp, section); 249 250 EtherLink *parent; 251 bool number; 252 UNSERIALIZE_OBJPTR(parent); 253 UNSERIALIZE_SCALAR(number); 254 255 link = parent->link[number]; 256 257 packet = new PacketData(16384); 258 packet->unserialize("packet", cp, section); 259} 260 261 262Serializable * 263LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 264{ 265 return new LinkDelayEvent(); 266} 267 268REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 269 270BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 271 272 SimObjectParam<EtherInt *> int1; 273 SimObjectParam<EtherInt *> int2; 274 Param<Tick> speed; 275 Param<Tick> delay; 276 SimObjectParam<EtherDump *> dump; 277 278END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 279 280BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 281 282 INIT_PARAM(int1, "interface 1"), 283 INIT_PARAM(int2, "interface 2"), 284 INIT_PARAM_DFLT(speed, "link speed in bits per second", 100000000), 285 INIT_PARAM_DFLT(delay, "transmit delay of packets in us", 0), 286 INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL) 287 288END_INIT_SIM_OBJECT_PARAMS(EtherLink) 289 290CREATE_SIM_OBJECT(EtherLink) 291{ 292 return new EtherLink(getInstanceName(), int1, int2, speed, delay, dump); 293} 294 295REGISTER_SIM_OBJECT("EtherLink", EtherLink) 296