etherlink.cc revision 633
112863Sgabeblack@google.com/* 212863Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan 312863Sgabeblack@google.com * All rights reserved. 412863Sgabeblack@google.com * 512863Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612863Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712863Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812863Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912863Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012863Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112863Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212863Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312863Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412863Sgabeblack@google.com * this software without specific prior written permission. 1512863Sgabeblack@google.com * 1612863Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712863Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812863Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912863Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012863Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112863Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212863Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312863Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412863Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512863Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612863Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712863Sgabeblack@google.com */ 2812863Sgabeblack@google.com 2912863Sgabeblack@google.com/* @file 3012863Sgabeblack@google.com * Device module for modelling a fixed bandwidth full duplex ethernet link 3112863Sgabeblack@google.com */ 3212950Sgabeblack@google.com 3312863Sgabeblack@google.com#include <cmath> 3412863Sgabeblack@google.com#include <deque> 3513317Sgabeblack@google.com#include <string> 3613191Sgabeblack@google.com#include <vector> 3713091Sgabeblack@google.com 3813079Sgabeblack@google.com#include "base/trace.hh" 3912863Sgabeblack@google.com#include "dev/etherdump.hh" 4012950Sgabeblack@google.com#include "dev/etherint.hh" 4112863Sgabeblack@google.com#include "dev/etherlink.hh" 4212863Sgabeblack@google.com#include "dev/etherpkt.hh" 4312863Sgabeblack@google.com#include "sim/builder.hh" 4412863Sgabeblack@google.com#include "sim/universe.hh" 4512863Sgabeblack@google.com#include "sim/system.hh" 4612863Sgabeblack@google.com 4712950Sgabeblack@google.comusing namespace std; 4812863Sgabeblack@google.com 4912863Sgabeblack@google.comEtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2, 5012863Sgabeblack@google.com Tick speed, Tick dly, EtherDump *dump) 5113303Sgabeblack@google.com : SimObject(name) 5213303Sgabeblack@google.com{ 5313191Sgabeblack@google.com double rate = ((double)ticksPerSecond * 8.0) / (double)speed; 5413191Sgabeblack@google.com Tick delay = US2Ticks(dly); 5513291Sgabeblack@google.com 5612950Sgabeblack@google.com link1 = new Link(name + ".link1", rate, delay, dump); 5712950Sgabeblack@google.com link2 = new Link(name + ".link2", rate, delay, dump); 5812950Sgabeblack@google.com 5912950Sgabeblack@google.com int1 = new Interface(name + ".int1", link1, link2); 6012950Sgabeblack@google.com int2 = new Interface(name + ".int2", link2, link1); 6113079Sgabeblack@google.com 6213079Sgabeblack@google.com int1->setPeer(i1); 6313268Sgabeblack@google.com i1->setPeer(int1); 6413268Sgabeblack@google.com int2->setPeer(i2); 6513079Sgabeblack@google.com i2->setPeer(int2); 6613268Sgabeblack@google.com} 6713268Sgabeblack@google.com 6813268Sgabeblack@google.comEtherLink::~EtherLink() 6913268Sgabeblack@google.com{ 7013268Sgabeblack@google.com delete link1; 7113268Sgabeblack@google.com delete link2; 7213079Sgabeblack@google.com 7313079Sgabeblack@google.com delete int1; 7412982Sgabeblack@google.com delete int2; 7512863Sgabeblack@google.com} 7612950Sgabeblack@google.com 7712863Sgabeblack@google.comEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 7812950Sgabeblack@google.com : EtherInt(name), txlink(tx) 7912950Sgabeblack@google.com{ 8012863Sgabeblack@google.com tx->setTxInt(this); 8113268Sgabeblack@google.com rx->setRxInt(this); 8213268Sgabeblack@google.com} 8313268Sgabeblack@google.com 8413268Sgabeblack@google.comEtherLink::Link::Link(const string &name, double rate, Tick delay, 8513268Sgabeblack@google.com EtherDump *d) 8613268Sgabeblack@google.com : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate), 8713268Sgabeblack@google.com linkDelay(delay), dump(d), doneEvent(this) 8813268Sgabeblack@google.com{} 8913268Sgabeblack@google.com 9013268Sgabeblack@google.comvoid 9113268Sgabeblack@google.comEtherLink::serialize(ostream &os) 9212863Sgabeblack@google.com{ 9312863Sgabeblack@google.com nameOut(os, name() + ".link1"); 9412863Sgabeblack@google.com link1->serialize(os); 9512863Sgabeblack@google.com nameOut(os, name() + ".link2"); 9612863Sgabeblack@google.com link2->serialize(os); 9713268Sgabeblack@google.com} 9813268Sgabeblack@google.com 9913268Sgabeblack@google.comvoid 10012950Sgabeblack@google.comEtherLink::unserialize(Checkpoint *cp, const string §ion) 10113268Sgabeblack@google.com{ 10212950Sgabeblack@google.com link1->unserialize(cp, section + ".link1"); 10313268Sgabeblack@google.com link2->unserialize(cp, section + ".link2"); 10412863Sgabeblack@google.com} 10512863Sgabeblack@google.com 10613091Sgabeblack@google.comvoid 10713091Sgabeblack@google.comEtherLink::Link::txComplete(PacketPtr &packet) 10813091Sgabeblack@google.com{ 10913091Sgabeblack@google.com DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 11013091Sgabeblack@google.com DDUMP(EthernetData, packet->data, packet->length); 11113091Sgabeblack@google.com rxint->sendPacket(packet); 11213091Sgabeblack@google.com} 11313091Sgabeblack@google.com 11413091Sgabeblack@google.comclass LinkDelayEvent : public Event 11513291Sgabeblack@google.com{ 11613091Sgabeblack@google.com protected: 11713091Sgabeblack@google.com EtherLink::Link *link; 11813091Sgabeblack@google.com PacketPtr packet; 11913091Sgabeblack@google.com 12013091Sgabeblack@google.com // non-scheduling version for createForUnserialize() 12113091Sgabeblack@google.com LinkDelayEvent(EtherLink::Link *link); 12213091Sgabeblack@google.com 12313091Sgabeblack@google.com public: 12413291Sgabeblack@google.com LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when); 12513091Sgabeblack@google.com 12613091Sgabeblack@google.com void process(); 12713191Sgabeblack@google.com 12813191Sgabeblack@google.com virtual void serialize(ostream &os); 12913191Sgabeblack@google.com virtual void unserialize(Checkpoint *cp, const string §ion); 13013268Sgabeblack@google.com static Serializable *createForUnserialize(Checkpoint *cp, 13113268Sgabeblack@google.com const string §ion); 13213268Sgabeblack@google.com}; 13313268Sgabeblack@google.com 13413268Sgabeblack@google.com 13513268Sgabeblack@google.comvoid 13613268Sgabeblack@google.comEtherLink::Link::txDone() 13713268Sgabeblack@google.com{ 13813268Sgabeblack@google.com if (dump) 13913268Sgabeblack@google.com dump->dump(packet); 14013191Sgabeblack@google.com 14113191Sgabeblack@google.com if (linkDelay > 0) { 14213191Sgabeblack@google.com DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 14313191Sgabeblack@google.com new LinkDelayEvent(this, packet, curTick + linkDelay); 14413191Sgabeblack@google.com } else { 14513191Sgabeblack@google.com txComplete(packet); 14613191Sgabeblack@google.com } 14713317Sgabeblack@google.com 14813191Sgabeblack@google.com packet = 0; 14913268Sgabeblack@google.com assert(!busy()); 15013268Sgabeblack@google.com 15113268Sgabeblack@google.com txint->sendDone(); 15213268Sgabeblack@google.com} 15313268Sgabeblack@google.com 15413268Sgabeblack@google.combool 15513268Sgabeblack@google.comEtherLink::Link::transmit(PacketPtr &pkt) 15613268Sgabeblack@google.com{ 15713268Sgabeblack@google.com if (busy()) { 15813268Sgabeblack@google.com DPRINTF(Ethernet, "packet not sent, link busy\n"); 15913191Sgabeblack@google.com return false; 16013191Sgabeblack@google.com } 16113191Sgabeblack@google.com 16213191Sgabeblack@google.com DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 16313191Sgabeblack@google.com DDUMP(EthernetData, pkt->data, pkt->length); 16413268Sgabeblack@google.com 16513268Sgabeblack@google.com packet = pkt; 16613268Sgabeblack@google.com Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 16713268Sgabeblack@google.com DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 16813268Sgabeblack@google.com delay, ticksPerByte); 16913268Sgabeblack@google.com doneEvent.schedule(curTick + delay); 17013268Sgabeblack@google.com 17113268Sgabeblack@google.com return true; 17213268Sgabeblack@google.com} 17313268Sgabeblack@google.com 17413191Sgabeblack@google.comvoid 17513191Sgabeblack@google.comEtherLink::Link::serialize(ostream &os) 17613191Sgabeblack@google.com{ 17713191Sgabeblack@google.com bool packet_exists = packet; 17813191Sgabeblack@google.com SERIALIZE_SCALAR(packet_exists); 17913268Sgabeblack@google.com 18013268Sgabeblack@google.com bool event_scheduled = doneEvent.scheduled(); 18113268Sgabeblack@google.com SERIALIZE_SCALAR(event_scheduled); 18213268Sgabeblack@google.com if (event_scheduled) { 18313268Sgabeblack@google.com Tick event_time = doneEvent.when(); 18413268Sgabeblack@google.com SERIALIZE_SCALAR(event_time); 18513268Sgabeblack@google.com } 18613268Sgabeblack@google.com 18713268Sgabeblack@google.com if (packet_exists) { 18813268Sgabeblack@google.com nameOut(os, csprintf("%s.packet", name())); 18913191Sgabeblack@google.com packet->serialize(os); 19013191Sgabeblack@google.com } 19112863Sgabeblack@google.com} 19212950Sgabeblack@google.com 19312863Sgabeblack@google.comvoid 19412950Sgabeblack@google.comEtherLink::Link::unserialize(Checkpoint *cp, const string §ion) 19512950Sgabeblack@google.com{ 19612950Sgabeblack@google.com bool packet_exists; 19712863Sgabeblack@google.com UNSERIALIZE_SCALAR(packet_exists); 19812863Sgabeblack@google.com if (packet_exists) { 19912950Sgabeblack@google.com packet = new EtherPacket; 20013079Sgabeblack@google.com packet->unserialize(cp, csprintf("%s.packet", section)); 20113079Sgabeblack@google.com } 20213317Sgabeblack@google.com 20313317Sgabeblack@google.com bool event_scheduled; 20413079Sgabeblack@google.com UNSERIALIZE_SCALAR(event_scheduled); 20513079Sgabeblack@google.com if (event_scheduled) { 20613079Sgabeblack@google.com Tick event_time; 20713079Sgabeblack@google.com UNSERIALIZE_SCALAR(event_time); 20812950Sgabeblack@google.com doneEvent.schedule(event_time); 20912950Sgabeblack@google.com } 21012950Sgabeblack@google.com} 21112950Sgabeblack@google.com 21212950Sgabeblack@google.comLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l) 21313046Sgabeblack@google.com : Event(&mainEventQueue), link(l) 21412982Sgabeblack@google.com{ 21512950Sgabeblack@google.com setFlags(AutoSerialize); 216 setFlags(AutoDelete); 217} 218 219LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when) 220 : Event(&mainEventQueue), link(l), packet(p) 221{ 222 setFlags(AutoSerialize); 223 setFlags(AutoDelete); 224 schedule(when); 225} 226 227void 228LinkDelayEvent::process() 229{ 230 link->txComplete(packet); 231} 232 233void 234LinkDelayEvent::serialize(ostream &os) 235{ 236 paramOut(os, "type", string("LinkDelayEvent")); 237 Event::serialize(os); 238 SERIALIZE_OBJPTR(link); 239 240 nameOut(os, csprintf("%s.packet", name())); 241 packet->serialize(os); 242} 243 244 245void 246LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 247{ 248 Event::unserialize(cp, section); 249 packet = new EtherPacket; 250 packet->unserialize(cp, csprintf("%s.packet", section)); 251} 252 253 254Serializable * 255LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 256{ 257 EtherLink::Link *link; 258 UNSERIALIZE_OBJPTR(link); 259 return new LinkDelayEvent(link); 260} 261 262REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 263 264BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 265 266 SimObjectParam<EtherInt *> interface1; 267 SimObjectParam<EtherInt *> interface2; 268 Param<Tick> link_speed; 269 Param<Tick> link_delay; 270 SimObjectParam<EtherDump *> packet_dump; 271 272END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 273 274BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 275 276 INIT_PARAM(interface1, "interface 1"), 277 INIT_PARAM(interface2, "interface 2"), 278 INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000), 279 INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0), 280 INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL) 281 282END_INIT_SIM_OBJECT_PARAMS(EtherLink) 283 284CREATE_SIM_OBJECT(EtherLink) 285{ 286 return new EtherLink(getInstanceName(), interface1, interface2, link_speed, 287 link_delay, packet_dump); 288} 289 290REGISTER_SIM_OBJECT("EtherLink", EtherLink) 291