etherlink.cc revision 10905
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 * Authors: Nathan Binkert 29 * Ron Dreslinski 30 */ 31 32/* @file 33 * Device module for modelling a fixed bandwidth full duplex ethernet link 34 */ 35 36#include <cmath> 37#include <deque> 38#include <string> 39#include <vector> 40 41#include "base/random.hh" 42#include "base/trace.hh" 43#include "debug/Ethernet.hh" 44#include "debug/EthernetData.hh" 45#include "dev/etherdump.hh" 46#include "dev/etherint.hh" 47#include "dev/etherlink.hh" 48#include "dev/etherpkt.hh" 49#include "params/EtherLink.hh" 50#include "sim/core.hh" 51#include "sim/serialize.hh" 52#include "sim/system.hh" 53 54using namespace std; 55 56EtherLink::EtherLink(const Params *p) 57 : EtherObject(p) 58{ 59 link[0] = new Link(name() + ".link0", this, 0, p->speed, 60 p->delay, p->delay_var, p->dump); 61 link[1] = new Link(name() + ".link1", this, 1, p->speed, 62 p->delay, p->delay_var, p->dump); 63 64 interface[0] = new Interface(name() + ".int0", link[0], link[1]); 65 interface[1] = new Interface(name() + ".int1", link[1], link[0]); 66} 67 68 69EtherLink::~EtherLink() 70{ 71 delete link[0]; 72 delete link[1]; 73 74 delete interface[0]; 75 delete interface[1]; 76} 77 78EtherInt* 79EtherLink::getEthPort(const std::string &if_name, int idx) 80{ 81 Interface *i; 82 if (if_name == "int0") 83 i = interface[0]; 84 else if (if_name == "int1") 85 i = interface[1]; 86 else 87 return NULL; 88 if (i->getPeer()) 89 panic("interface already connected to\n"); 90 91 return i; 92} 93 94 95EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 96 : EtherInt(name), txlink(tx) 97{ 98 tx->setTxInt(this); 99 rx->setRxInt(this); 100} 101 102EtherLink::Link::Link(const string &name, EtherLink *p, int num, 103 double rate, Tick delay, Tick delay_var, EtherDump *d) 104 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 105 ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 106 doneEvent(this) 107{ } 108 109void 110EtherLink::serialize(CheckpointOut &cp) const 111{ 112 link[0]->serialize("link0", cp); 113 link[1]->serialize("link1", cp); 114} 115 116void 117EtherLink::unserialize(CheckpointIn &cp) 118{ 119 link[0]->unserialize("link0", cp); 120 link[1]->unserialize("link1", cp); 121} 122 123void 124EtherLink::Link::txComplete(EthPacketPtr packet) 125{ 126 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 127 DDUMP(EthernetData, packet->data, packet->length); 128 rxint->sendPacket(packet); 129} 130 131class LinkDelayEvent : public Event 132{ 133 protected: 134 EtherLink::Link *link; 135 EthPacketPtr packet; 136 137 public: 138 // non-scheduling version for createForUnserialize() 139 LinkDelayEvent(); 140 LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt); 141 142 void process(); 143 144 void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; 145 void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE {} 146 void unserializeEvent(CheckpointIn &cp, 147 EventQueue *eventq) M5_ATTR_OVERRIDE; 148 static Serializable *createForUnserialize(CheckpointIn &cp, 149 const string §ion); 150}; 151 152void 153EtherLink::Link::txDone() 154{ 155 if (dump) 156 dump->dump(packet); 157 158 if (linkDelay > 0) { 159 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 160 Event *event = new LinkDelayEvent(this, packet); 161 parent->schedule(event, curTick() + linkDelay); 162 } else { 163 txComplete(packet); 164 } 165 166 packet = 0; 167 assert(!busy()); 168 169 txint->sendDone(); 170} 171 172bool 173EtherLink::Link::transmit(EthPacketPtr pkt) 174{ 175 if (busy()) { 176 DPRINTF(Ethernet, "packet not sent, link busy\n"); 177 return false; 178 } 179 180 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 181 DDUMP(EthernetData, pkt->data, pkt->length); 182 183 packet = pkt; 184 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 185 if (delayVar != 0) 186 delay += random_mt.random<Tick>(0, delayVar); 187 188 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 189 delay, ticksPerByte); 190 parent->schedule(doneEvent, curTick() + delay); 191 192 return true; 193} 194 195void 196EtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 197{ 198 bool packet_exists = packet != nullptr; 199 paramOut(cp, base + ".packet_exists", packet_exists); 200 if (packet_exists) 201 packet->serialize(base + ".packet", cp); 202 203 bool event_scheduled = doneEvent.scheduled(); 204 paramOut(cp, base + ".event_scheduled", event_scheduled); 205 if (event_scheduled) { 206 Tick event_time = doneEvent.when(); 207 paramOut(cp, base + ".event_time", event_time); 208 } 209 210} 211 212void 213EtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 214{ 215 bool packet_exists; 216 paramIn(cp, base + ".packet_exists", packet_exists); 217 if (packet_exists) { 218 packet = make_shared<EthPacketData>(16384); 219 packet->unserialize(base + ".packet", cp); 220 } 221 222 bool event_scheduled; 223 paramIn(cp, base + ".event_scheduled", event_scheduled); 224 if (event_scheduled) { 225 Tick event_time; 226 paramIn(cp, base + ".event_time", event_time); 227 parent->schedule(doneEvent, event_time); 228 } 229} 230 231LinkDelayEvent::LinkDelayEvent() 232 : Event(Default_Pri, AutoSerialize | AutoDelete), link(NULL) 233{ 234} 235 236LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p) 237 : Event(Default_Pri, AutoSerialize | AutoDelete), link(l), packet(p) 238{ 239} 240 241void 242LinkDelayEvent::process() 243{ 244 link->txComplete(packet); 245} 246 247void 248LinkDelayEvent::serialize(CheckpointOut &cp) const 249{ 250 paramOut(cp, "type", string("LinkDelayEvent")); 251 Event::serialize(cp); 252 253 EtherLink *parent = link->parent; 254 bool number = link->number; 255 SERIALIZE_OBJPTR(parent); 256 SERIALIZE_SCALAR(number); 257 258 packet->serialize("packet", cp); 259} 260 261 262void 263LinkDelayEvent::unserializeEvent(CheckpointIn &cp, EventQueue *eventq) 264{ 265 Event::unserializeEvent(cp, eventq); 266 267 EtherLink *parent; 268 bool number; 269 UNSERIALIZE_OBJPTR(parent); 270 UNSERIALIZE_SCALAR(number); 271 272 link = parent->link[number]; 273 274 packet = make_shared<EthPacketData>(16384); 275 packet->unserialize("packet", cp); 276} 277 278 279Serializable * 280LinkDelayEvent::createForUnserialize(CheckpointIn &cp, const string §ion) 281{ 282 return new LinkDelayEvent(); 283} 284 285REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 286 287EtherLink * 288EtherLinkParams::create() 289{ 290 return new EtherLink(this); 291} 292