etherlink.cc revision 1954
1/* 2 * Copyright (c) 2002-2005 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/random.hh" 39#include "base/trace.hh" 40#include "dev/etherdump.hh" 41#include "dev/etherint.hh" 42#include "dev/etherlink.hh" 43#include "dev/etherpkt.hh" 44#include "sim/builder.hh" 45#include "sim/serialize.hh" 46#include "sim/system.hh" 47#include "sim/root.hh" 48 49using namespace std; 50 51EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 52 double rate, Tick delay, Tick delayVar, EtherDump *dump) 53 : SimObject(name) 54{ 55 link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 56 link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 57 58 interface[0] = new Interface(name + ".int0", link[0], link[1]); 59 interface[1] = new Interface(name + ".int1", link[1], link[0]); 60 61 interface[0]->setPeer(peer0); 62 peer0->setPeer(interface[0]); 63 interface[1]->setPeer(peer1); 64 peer1->setPeer(interface[1]); 65} 66 67EtherLink::~EtherLink() 68{ 69 delete link[0]; 70 delete link[1]; 71 72 delete interface[0]; 73 delete interface[1]; 74} 75 76EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 77 : EtherInt(name), txlink(tx) 78{ 79 tx->setTxInt(this); 80 rx->setRxInt(this); 81} 82 83EtherLink::Link::Link(const string &name, EtherLink *p, int num, 84 double rate, Tick delay, Tick delay_var, EtherDump *d) 85 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 86 ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 87 doneEvent(this) 88{ } 89 90void 91EtherLink::serialize(ostream &os) 92{ 93 link[0]->serialize("link0", os); 94 link[1]->serialize("link1", os); 95} 96 97void 98EtherLink::unserialize(Checkpoint *cp, const string §ion) 99{ 100 link[0]->unserialize("link0", cp, section); 101 link[1]->unserialize("link1", cp, section); 102} 103 104void 105EtherLink::Link::txComplete(PacketPtr packet) 106{ 107 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 108 DDUMP(EthernetData, packet->data, packet->length); 109 rxint->sendPacket(packet); 110} 111 112class LinkDelayEvent : public Event 113{ 114 protected: 115 EtherLink::Link *link; 116 PacketPtr packet; 117 118 public: 119 // non-scheduling version for createForUnserialize() 120 LinkDelayEvent(); 121 LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); 122 123 void process(); 124 125 virtual void serialize(ostream &os); 126 virtual void unserialize(Checkpoint *cp, const string §ion); 127 static Serializable *createForUnserialize(Checkpoint *cp, 128 const string §ion); 129}; 130 131void 132EtherLink::Link::txDone() 133{ 134 if (dump) 135 dump->dump(packet); 136 137 if (linkDelay > 0) { 138 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 139 new LinkDelayEvent(this, packet, curTick + linkDelay); 140 } else { 141 txComplete(packet); 142 } 143 144 packet = 0; 145 assert(!busy()); 146 147 txint->sendDone(); 148} 149 150bool 151EtherLink::Link::transmit(PacketPtr pkt) 152{ 153 if (busy()) { 154 DPRINTF(Ethernet, "packet not sent, link busy\n"); 155 return false; 156 } 157 158 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 159 DDUMP(EthernetData, pkt->data, pkt->length); 160 161 packet = pkt; 162 Random<Tick> var; 163 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0 + 164 var.uniform(delayVar)); 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_scheduled", 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<double> speed; 275 Param<Tick> delay; 276 Param<Tick> delay_var; 277 SimObjectParam<EtherDump *> dump; 278 279END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 280 281BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 282 283 INIT_PARAM(int1, "interface 1"), 284 INIT_PARAM(int2, "interface 2"), 285 INIT_PARAM(speed, "link speed in bits per second"), 286 INIT_PARAM(delay, "transmit delay of packets in us"), 287 INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), 288 INIT_PARAM(dump, "object to dump network packets to") 289 290END_INIT_SIM_OBJECT_PARAMS(EtherLink) 291 292CREATE_SIM_OBJECT(EtherLink) 293{ 294 return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, 295 dump); 296} 297 298REGISTER_SIM_OBJECT("EtherLink", EtherLink) 299