etherlink.cc revision 1078
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 *i1, EtherInt *i2, 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 link1 = new Link(name + ".link1", rate, delay, dump); 58 link2 = new Link(name + ".link2", rate, delay, dump); 59 60 int1 = new Interface(name + ".int1", link1, link2); 61 int2 = new Interface(name + ".int2", link2, link1); 62 63 int1->setPeer(i1); 64 i1->setPeer(int1); 65 int2->setPeer(i2); 66 i2->setPeer(int2); 67} 68 69EtherLink::~EtherLink() 70{ 71 delete link1; 72 delete link2; 73 74 delete int1; 75 delete int2; 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, double rate, Tick delay, 86 EtherDump *d) 87 : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate), 88 linkDelay(delay), dump(d), doneEvent(this) 89{} 90 91void 92EtherLink::serialize(ostream &os) 93{ 94 nameOut(os, name() + ".link1"); 95 link1->serialize(os); 96 nameOut(os, name() + ".link2"); 97 link2->serialize(os); 98} 99 100void 101EtherLink::unserialize(Checkpoint *cp, const string §ion) 102{ 103 link1->unserialize(cp, section + ".link1"); 104 link2->unserialize(cp, section + ".link2"); 105} 106 107void 108EtherLink::Link::txComplete(PacketPtr &packet) 109{ 110 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 111 DDUMP(EthernetData, packet->data, packet->length); 112 rxint->sendPacket(packet); 113} 114 115class LinkDelayEvent : public Event 116{ 117 protected: 118 EtherLink::Link *link; 119 PacketPtr packet; 120 121 // non-scheduling version for createForUnserialize() 122 LinkDelayEvent(EtherLink::Link *link); 123 124 public: 125 LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when); 126 127 void process(); 128 129 virtual void serialize(ostream &os); 130 virtual void unserialize(Checkpoint *cp, const string §ion); 131 static Serializable *createForUnserialize(Checkpoint *cp, 132 const string §ion); 133}; 134 135 136void 137EtherLink::Link::txDone() 138{ 139 if (dump) 140 dump->dump(packet); 141 142 if (linkDelay > 0) { 143 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 144 new LinkDelayEvent(this, packet, curTick + linkDelay); 145 } else { 146 txComplete(packet); 147 } 148 149 packet = 0; 150 assert(!busy()); 151 152 txint->sendDone(); 153} 154 155bool 156EtherLink::Link::transmit(PacketPtr &pkt) 157{ 158 if (busy()) { 159 DPRINTF(Ethernet, "packet not sent, link busy\n"); 160 return false; 161 } 162 163 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 164 DDUMP(EthernetData, pkt->data, pkt->length); 165 166 packet = pkt; 167 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 168 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 169 delay, ticksPerByte); 170 doneEvent.schedule(curTick + delay); 171 172 return true; 173} 174 175void 176EtherLink::Link::serialize(ostream &os) 177{ 178 bool packet_exists = packet; 179 SERIALIZE_SCALAR(packet_exists); 180 181 bool event_scheduled = doneEvent.scheduled(); 182 SERIALIZE_SCALAR(event_scheduled); 183 if (event_scheduled) { 184 Tick event_time = doneEvent.when(); 185 SERIALIZE_SCALAR(event_time); 186 } 187 188 if (packet_exists) { 189 nameOut(os, csprintf("%s.packet", name())); 190 packet->serialize(os); 191 } 192} 193 194void 195EtherLink::Link::unserialize(Checkpoint *cp, const string §ion) 196{ 197 bool packet_exists; 198 UNSERIALIZE_SCALAR(packet_exists); 199 if (packet_exists) { 200 packet = new PacketData; 201 packet->unserialize(cp, csprintf("%s.packet", section)); 202 } 203 204 bool event_scheduled; 205 UNSERIALIZE_SCALAR(event_scheduled); 206 if (event_scheduled) { 207 Tick event_time; 208 UNSERIALIZE_SCALAR(event_time); 209 doneEvent.schedule(event_time); 210 } 211} 212 213LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l) 214 : Event(&mainEventQueue), link(l) 215{ 216 setFlags(AutoSerialize); 217 setFlags(AutoDelete); 218} 219 220LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when) 221 : Event(&mainEventQueue), link(l), packet(p) 222{ 223 setFlags(AutoSerialize); 224 setFlags(AutoDelete); 225 schedule(when); 226} 227 228void 229LinkDelayEvent::process() 230{ 231 link->txComplete(packet); 232} 233 234void 235LinkDelayEvent::serialize(ostream &os) 236{ 237 paramOut(os, "type", string("LinkDelayEvent")); 238 Event::serialize(os); 239 SERIALIZE_OBJPTR(link); 240 241 nameOut(os, csprintf("%s.packet", name())); 242 packet->serialize(os); 243} 244 245 246void 247LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 248{ 249 Event::unserialize(cp, section); 250 packet = new PacketData; 251 packet->unserialize(cp, csprintf("%s.packet", section)); 252} 253 254 255Serializable * 256LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 257{ 258 EtherLink::Link *link; 259 UNSERIALIZE_OBJPTR(link); 260 return new LinkDelayEvent(link); 261} 262 263REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 264 265BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 266 267 SimObjectParam<EtherInt *> interface1; 268 SimObjectParam<EtherInt *> interface2; 269 Param<Tick> link_speed; 270 Param<Tick> link_delay; 271 SimObjectParam<EtherDump *> packet_dump; 272 273END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 274 275BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 276 277 INIT_PARAM(interface1, "interface 1"), 278 INIT_PARAM(interface2, "interface 2"), 279 INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000), 280 INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0), 281 INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL) 282 283END_INIT_SIM_OBJECT_PARAMS(EtherLink) 284 285CREATE_SIM_OBJECT(EtherLink) 286{ 287 return new EtherLink(getInstanceName(), interface1, interface2, link_speed, 288 link_delay, packet_dump); 289} 290 291REGISTER_SIM_OBJECT("EtherLink", EtherLink) 292