etherlink.cc revision 1954
11689SN/A/* 22326SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 291689SN/A/* @file 301689SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 311060SN/A */ 321060SN/A 331689SN/A#include <cmath> 341060SN/A#include <deque> 351060SN/A#include <string> 361060SN/A#include <vector> 371060SN/A 382292SN/A#include "base/random.hh" 391717SN/A#include "base/trace.hh" 401060SN/A#include "dev/etherdump.hh" 411681SN/A#include "dev/etherint.hh" 422292SN/A#include "dev/etherlink.hh" 432873Sktlim@umich.edu#include "dev/etherpkt.hh" 441060SN/A#include "sim/builder.hh" 451061SN/A#include "sim/serialize.hh" 462292SN/A#include "sim/system.hh" 472292SN/A#include "sim/root.hh" 482292SN/A 492292SN/Ausing namespace std; 502820Sktlim@umich.edu 512292SN/AEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 522820Sktlim@umich.edu double rate, Tick delay, Tick delayVar, EtherDump *dump) 532820Sktlim@umich.edu : SimObject(name) 542307SN/A{ 552307SN/A link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 561060SN/A link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 572292SN/A 582292SN/A interface[0] = new Interface(name + ".int0", link[0], link[1]); 592292SN/A interface[1] = new Interface(name + ".int1", link[1], link[0]); 601060SN/A 611060SN/A interface[0]->setPeer(peer0); 621060SN/A peer0->setPeer(interface[0]); 631060SN/A interface[1]->setPeer(peer1); 641060SN/A peer1->setPeer(interface[1]); 651060SN/A} 661681SN/A 672292SN/AEtherLink::~EtherLink() 681681SN/A{ 692292SN/A delete link[0]; 702292SN/A delete link[1]; 712292SN/A 722292SN/A delete interface[0]; 732292SN/A delete interface[1]; 742935Sksewell@umich.edu} 752292SN/A 762292SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 772820Sktlim@umich.edu : EtherInt(name), txlink(tx) 782820Sktlim@umich.edu{ 792292SN/A tx->setTxInt(this); 802292SN/A rx->setRxInt(this); 812820Sktlim@umich.edu} 822820Sktlim@umich.edu 832292SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 842292SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 852292SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 862292SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 872292SN/A doneEvent(this) 882292SN/A{ } 892292SN/A 902292SN/Avoid 911060SN/AEtherLink::serialize(ostream &os) 921060SN/A{ 931681SN/A link[0]->serialize("link0", os); 941062SN/A link[1]->serialize("link1", os); 952292SN/A} 961062SN/A 972301SN/Avoid 982301SN/AEtherLink::unserialize(Checkpoint *cp, const string §ion) 991062SN/A{ 1002727Sktlim@umich.edu link[0]->unserialize("link0", cp, section); 1011062SN/A link[1]->unserialize("link1", cp, section); 1021062SN/A} 1031062SN/A 1041062SN/Avoid 1051062SN/AEtherLink::Link::txComplete(PacketPtr packet) 1061062SN/A{ 1071062SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1081062SN/A DDUMP(EthernetData, packet->data, packet->length); 1091062SN/A rxint->sendPacket(packet); 1101062SN/A} 1111062SN/A 1121062SN/Aclass LinkDelayEvent : public Event 1131062SN/A{ 1141062SN/A protected: 1151062SN/A EtherLink::Link *link; 1161062SN/A PacketPtr packet; 1171062SN/A 1181062SN/A public: 1191062SN/A // non-scheduling version for createForUnserialize() 1201062SN/A LinkDelayEvent(); 1211062SN/A LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); 1221062SN/A 1231062SN/A void process(); 1241062SN/A 1251062SN/A virtual void serialize(ostream &os); 1261062SN/A virtual void unserialize(Checkpoint *cp, const string §ion); 1271062SN/A static Serializable *createForUnserialize(Checkpoint *cp, 1281062SN/A const string §ion); 1291062SN/A}; 1301062SN/A 1311062SN/Avoid 1321062SN/AEtherLink::Link::txDone() 1331062SN/A{ 1341062SN/A if (dump) 1351062SN/A dump->dump(packet); 1361062SN/A 1371062SN/A if (linkDelay > 0) { 1381062SN/A DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1391062SN/A new LinkDelayEvent(this, packet, curTick + linkDelay); 1401062SN/A } else { 1411062SN/A txComplete(packet); 1422292SN/A } 1432292SN/A 1442292SN/A packet = 0; 1452292SN/A assert(!busy()); 1461062SN/A 1471062SN/A txint->sendDone(); 1481062SN/A} 1491062SN/A 1501062SN/Abool 1511062SN/AEtherLink::Link::transmit(PacketPtr pkt) 1521062SN/A{ 1532292SN/A if (busy()) { 1542292SN/A DPRINTF(Ethernet, "packet not sent, link busy\n"); 1552292SN/A return false; 1562292SN/A } 1572292SN/A 1582292SN/A DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1592292SN/A DDUMP(EthernetData, pkt->data, pkt->length); 1602292SN/A 1612292SN/A packet = pkt; 1622292SN/A Random<Tick> var; 1632301SN/A Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0 + 1642727Sktlim@umich.edu var.uniform(delayVar)); 1652353SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 1662727Sktlim@umich.edu delay, ticksPerByte); 1672727Sktlim@umich.edu doneEvent.schedule(curTick + delay); 1682727Sktlim@umich.edu 1692727Sktlim@umich.edu return true; 1702353SN/A} 1712727Sktlim@umich.edu 1722727Sktlim@umich.eduvoid 1732727Sktlim@umich.eduEtherLink::Link::serialize(const string &base, ostream &os) 1742727Sktlim@umich.edu{ 1752353SN/A bool packet_exists = packet; 1762727Sktlim@umich.edu paramOut(os, base + ".packet_exists", packet_exists); 1772727Sktlim@umich.edu if (packet_exists) 1782727Sktlim@umich.edu packet->serialize(base + ".packet", os); 1792301SN/A 1802301SN/A bool event_scheduled = doneEvent.scheduled(); 1812301SN/A paramOut(os, base + ".event_scheduled", event_scheduled); 1822727Sktlim@umich.edu if (event_scheduled) { 1832301SN/A Tick event_time = doneEvent.when(); 1842727Sktlim@umich.edu paramOut(os, base + ".event_time", event_time); 1852301SN/A } 1862301SN/A 1872301SN/A} 1882727Sktlim@umich.edu 1892301SN/Avoid 1902727Sktlim@umich.eduEtherLink::Link::unserialize(const string &base, Checkpoint *cp, 1912301SN/A const string §ion) 1922301SN/A{ 1932301SN/A bool packet_exists; 1942727Sktlim@umich.edu paramIn(cp, section, base + ".packet_exists", packet_exists); 1952301SN/A if (packet_exists) { 1962727Sktlim@umich.edu packet = new PacketData(16384); 1972301SN/A packet->unserialize(base + ".packet", cp, section); 1982301SN/A } 1992301SN/A 2002727Sktlim@umich.edu bool event_scheduled; 2012301SN/A paramIn(cp, section, base + ".event_scheduled", event_scheduled); 2022301SN/A if (event_scheduled) { 2032301SN/A Tick event_time; 2042301SN/A paramIn(cp, section, base + ".event_time", event_time); 2052727Sktlim@umich.edu doneEvent.schedule(event_time); 2062727Sktlim@umich.edu } 2072727Sktlim@umich.edu} 2082727Sktlim@umich.edu 2092727Sktlim@umich.eduLinkDelayEvent::LinkDelayEvent() 2102727Sktlim@umich.edu : Event(&mainEventQueue), link(NULL) 2112727Sktlim@umich.edu{ 2122727Sktlim@umich.edu setFlags(AutoSerialize); 2132727Sktlim@umich.edu setFlags(AutoDelete); 2142301SN/A} 2152301SN/A 2162301SN/ALinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) 2172301SN/A : Event(&mainEventQueue), link(l), packet(p) 2182301SN/A{ 2192727Sktlim@umich.edu setFlags(AutoSerialize); 2202301SN/A setFlags(AutoDelete); 2212326SN/A schedule(when); 2222301SN/A} 2232301SN/A 2242301SN/Avoid 2252727Sktlim@umich.eduLinkDelayEvent::process() 2262301SN/A{ 2272326SN/A link->txComplete(packet); 2282301SN/A} 2292301SN/A 2302301SN/Avoid 2312727Sktlim@umich.eduLinkDelayEvent::serialize(ostream &os) 2322301SN/A{ 2332326SN/A paramOut(os, "type", string("LinkDelayEvent")); 2342301SN/A Event::serialize(os); 2352301SN/A 2362301SN/A EtherLink *parent = link->parent; 2372727Sktlim@umich.edu bool number = link->number; 2382301SN/A SERIALIZE_OBJPTR(parent); 2392326SN/A SERIALIZE_SCALAR(number); 2402301SN/A 2412301SN/A packet->serialize("packet", os); 2422301SN/A} 2432727Sktlim@umich.edu 2442301SN/A 2452326SN/Avoid 2462301SN/ALinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 2472301SN/A{ 2482727Sktlim@umich.edu Event::unserialize(cp, section); 2492301SN/A 2502326SN/A EtherLink *parent; 2512301SN/A bool number; 2522326SN/A UNSERIALIZE_OBJPTR(parent); 2532301SN/A UNSERIALIZE_SCALAR(number); 2542301SN/A 2552727Sktlim@umich.edu link = parent->link[number]; 2562301SN/A 2572326SN/A packet = new PacketData(16384); 2582301SN/A packet->unserialize("packet", cp, section); 2592326SN/A} 2602301SN/A 2612301SN/A 2622727Sktlim@umich.eduSerializable * 2632326SN/ALinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 2641062SN/A{ 2651062SN/A return new LinkDelayEvent(); 2661681SN/A} 2671060SN/A 2682292SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 2691060SN/A 2702292SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 2712292SN/A 2722292SN/A SimObjectParam<EtherInt *> int1; 2732292SN/A SimObjectParam<EtherInt *> int2; 2742292SN/A Param<double> speed; 2752292SN/A Param<Tick> delay; 2762292SN/A Param<Tick> delay_var; 2772292SN/A SimObjectParam<EtherDump *> dump; 2782292SN/A 2792292SN/AEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 2802292SN/A 2812292SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 2822292SN/A 2832733Sktlim@umich.edu INIT_PARAM(int1, "interface 1"), 2842292SN/A INIT_PARAM(int2, "interface 2"), 2852292SN/A INIT_PARAM(speed, "link speed in bits per second"), 2861060SN/A INIT_PARAM(delay, "transmit delay of packets in us"), 2871060SN/A INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), 2881060SN/A INIT_PARAM(dump, "object to dump network packets to") 2891061SN/A 2902292SN/AEND_INIT_SIM_OBJECT_PARAMS(EtherLink) 2912733Sktlim@umich.edu 2921060SN/ACREATE_SIM_OBJECT(EtherLink) 2931060SN/A{ 2941681SN/A return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, 2951060SN/A dump); 2962292SN/A} 2971060SN/A 2982292SN/AREGISTER_SIM_OBJECT("EtherLink", EtherLink) 2991060SN/A