etherlink.cc revision 1961
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 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 163 if (delayVar != 0) { 164 Random<Tick> var; 165 delay += var.uniform(delayVar); 166 } 167 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 168 delay, ticksPerByte); 169 doneEvent.schedule(curTick + delay); 170 171 return true; 172} 173 174void 175EtherLink::Link::serialize(const string &base, ostream &os) 176{ 177 bool packet_exists = packet; 178 paramOut(os, base + ".packet_exists", packet_exists); 179 if (packet_exists) 180 packet->serialize(base + ".packet", os); 181 182 bool event_scheduled = doneEvent.scheduled(); 183 paramOut(os, base + ".event_scheduled", event_scheduled); 184 if (event_scheduled) { 185 Tick event_time = doneEvent.when(); 186 paramOut(os, base + ".event_time", event_time); 187 } 188 189} 190 191void 192EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 193 const string §ion) 194{ 195 bool packet_exists; 196 paramIn(cp, section, base + ".packet_exists", packet_exists); 197 if (packet_exists) { 198 packet = new PacketData(16384); 199 packet->unserialize(base + ".packet", cp, section); 200 } 201 202 bool event_scheduled; 203 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 204 if (event_scheduled) { 205 Tick event_time; 206 paramIn(cp, section, base + ".event_time", event_time); 207 doneEvent.schedule(event_time); 208 } 209} 210 211LinkDelayEvent::LinkDelayEvent() 212 : Event(&mainEventQueue), link(NULL) 213{ 214 setFlags(AutoSerialize); 215 setFlags(AutoDelete); 216} 217 218LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) 219 : Event(&mainEventQueue), link(l), packet(p) 220{ 221 setFlags(AutoSerialize); 222 setFlags(AutoDelete); 223 schedule(when); 224} 225 226void 227LinkDelayEvent::process() 228{ 229 link->txComplete(packet); 230} 231 232void 233LinkDelayEvent::serialize(ostream &os) 234{ 235 paramOut(os, "type", string("LinkDelayEvent")); 236 Event::serialize(os); 237 238 EtherLink *parent = link->parent; 239 bool number = link->number; 240 SERIALIZE_OBJPTR(parent); 241 SERIALIZE_SCALAR(number); 242 243 packet->serialize("packet", os); 244} 245 246 247void 248LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 249{ 250 Event::unserialize(cp, section); 251 252 EtherLink *parent; 253 bool number; 254 UNSERIALIZE_OBJPTR(parent); 255 UNSERIALIZE_SCALAR(number); 256 257 link = parent->link[number]; 258 259 packet = new PacketData(16384); 260 packet->unserialize("packet", cp, section); 261} 262 263 264Serializable * 265LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 266{ 267 return new LinkDelayEvent(); 268} 269 270REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 271 272BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 273 274 SimObjectParam<EtherInt *> int1; 275 SimObjectParam<EtherInt *> int2; 276 Param<double> speed; 277 Param<Tick> delay; 278 Param<Tick> delay_var; 279 SimObjectParam<EtherDump *> dump; 280 281END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 282 283BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 284 285 INIT_PARAM(int1, "interface 1"), 286 INIT_PARAM(int2, "interface 2"), 287 INIT_PARAM(speed, "link speed in bits per second"), 288 INIT_PARAM(delay, "transmit delay of packets in us"), 289 INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), 290 INIT_PARAM(dump, "object to dump network packets to") 291 292END_INIT_SIM_OBJECT_PARAMS(EtherLink) 293 294CREATE_SIM_OBJECT(EtherLink) 295{ 296 return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, 297 dump); 298} 299 300REGISTER_SIM_OBJECT("EtherLink", EtherLink) 301