etherlink.cc revision 1078
12686Sksewell@umich.edu/*
22100SN/A * Copyright (c) 2002-2004 The Regents of The University of Michigan
35222Sksewell@umich.edu * All rights reserved.
45222Sksewell@umich.edu *
55222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65222Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115222Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145222Sksewell@umich.edu * this software without specific prior written permission.
155222Sksewell@umich.edu *
165222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275222Sksewell@umich.edu */
285222Sksewell@umich.edu
295222Sksewell@umich.edu/* @file
305222Sksewell@umich.edu * Device module for modelling a fixed bandwidth full duplex ethernet link
315222Sksewell@umich.edu */
325222Sksewell@umich.edu
335222Sksewell@umich.edu#include <cmath>
345222Sksewell@umich.edu#include <deque>
355222Sksewell@umich.edu#include <string>
365222Sksewell@umich.edu#include <vector>
375222Sksewell@umich.edu
382706Sksewell@umich.edu#include "base/trace.hh"
392022SN/A#include "dev/etherdump.hh"
402022SN/A#include "dev/etherint.hh"
412043SN/A#include "dev/etherlink.hh"
422024SN/A#include "dev/etherpkt.hh"
432024SN/A#include "sim/builder.hh"
442043SN/A#include "sim/serialize.hh"
452686Sksewell@umich.edu#include "sim/system.hh"
464661Sksewell@umich.edu#include "sim/universe.hh"
472022SN/A
482083SN/Ausing namespace std;
492686Sksewell@umich.edu
502101SN/AEtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2,
512043SN/A                     Tick speed, Tick dly, EtherDump *dump)
522043SN/A    : SimObject(name)
532101SN/A{
542101SN/A    double rate = ((double)ticksPerSecond * 8.0) / (double)speed;
552686Sksewell@umich.edu    Tick delay = US2Ticks(dly);
562686Sksewell@umich.edu
572101SN/A    link1 = new Link(name + ".link1", rate, delay, dump);
582101SN/A    link2 = new Link(name + ".link2", rate, delay, dump);
592101SN/A
602046SN/A    int1 = new Interface(name + ".int1", link1, link2);
612686Sksewell@umich.edu    int2 = new Interface(name + ".int2", link2, link1);
622686Sksewell@umich.edu
632686Sksewell@umich.edu    int1->setPeer(i1);
642470SN/A    i1->setPeer(int1);
652686Sksewell@umich.edu    int2->setPeer(i2);
664661Sksewell@umich.edu    i2->setPeer(int2);
675222Sksewell@umich.edu}
685222Sksewell@umich.edu
692686Sksewell@umich.eduEtherLink::~EtherLink()
702686Sksewell@umich.edu{
712470SN/A    delete link1;
722241SN/A    delete link2;
732101SN/A
742495SN/A    delete int1;
752495SN/A    delete int2;
762495SN/A}
772101SN/A
782495SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
792495SN/A    : EtherInt(name), txlink(tx)
802495SN/A{
812101SN/A    tx->setTxInt(this);
822101SN/A    rx->setRxInt(this);
832495SN/A}
842495SN/A
852495SN/AEtherLink::Link::Link(const string &name, double rate, Tick delay,
862495SN/A                      EtherDump *d)
872495SN/A    : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate),
882495SN/A      linkDelay(delay), dump(d), doneEvent(this)
892495SN/A{}
902495SN/A
912495SN/Avoid
922495SN/AEtherLink::serialize(ostream &os)
932495SN/A{
942495SN/A    nameOut(os, name() + ".link1");
952495SN/A    link1->serialize(os);
962101SN/A    nameOut(os, name() + ".link2");
972101SN/A    link2->serialize(os);
982101SN/A}
992101SN/A
1002101SN/Avoid
1012101SN/AEtherLink::unserialize(Checkpoint *cp, const string &section)
1022101SN/A{
1032101SN/A    link1->unserialize(cp, section + ".link1");
1042101SN/A    link2->unserialize(cp, section + ".link2");
1052101SN/A}
1062495SN/A
1072495SN/Avoid
1082495SN/AEtherLink::Link::txComplete(PacketPtr &packet)
1092495SN/A{
1102495SN/A    DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
1112495SN/A    DDUMP(EthernetData, packet->data, packet->length);
1122495SN/A    rxint->sendPacket(packet);
1132495SN/A}
1142495SN/A
1152495SN/Aclass LinkDelayEvent : public Event
1162495SN/A{
1172495SN/A  protected:
1182495SN/A    EtherLink::Link *link;
1192495SN/A    PacketPtr packet;
1202495SN/A
1212043SN/A    // non-scheduling version for createForUnserialize()
1222043SN/A    LinkDelayEvent(EtherLink::Link *link);
1232025SN/A
1242043SN/A  public:
1252686Sksewell@umich.edu    LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when);
1262686Sksewell@umich.edu
1272123SN/A    void process();
1282101SN/A
1295222Sksewell@umich.edu    virtual void serialize(ostream &os);
1305222Sksewell@umich.edu    virtual void unserialize(Checkpoint *cp, const string &section);
1312101SN/A    static Serializable *createForUnserialize(Checkpoint *cp,
1322042SN/A                                              const string &section);
1332101SN/A};
1344661Sksewell@umich.edu
1352686Sksewell@umich.edu
1364661Sksewell@umich.eduvoid
1372101SN/AEtherLink::Link::txDone()
1382101SN/A{
1392042SN/A    if (dump)
1402101SN/A        dump->dump(packet);
1412686Sksewell@umich.edu
1422686Sksewell@umich.edu    if (linkDelay > 0) {
1435222Sksewell@umich.edu        DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
1445222Sksewell@umich.edu        new LinkDelayEvent(this, packet, curTick + linkDelay);
1455222Sksewell@umich.edu    } else {
1465222Sksewell@umich.edu        txComplete(packet);
1475222Sksewell@umich.edu    }
1482965Sksewell@umich.edu
1495222Sksewell@umich.edu    packet = 0;
1505222Sksewell@umich.edu    assert(!busy());
1512686Sksewell@umich.edu
1525222Sksewell@umich.edu    txint->sendDone();
1532101SN/A}
1542083SN/A
1552043SN/Abool
1562025SN/AEtherLink::Link::transmit(PacketPtr &pkt)
1572043SN/A{
1585222Sksewell@umich.edu    if (busy()) {
1594661Sksewell@umich.edu        DPRINTF(Ethernet, "packet not sent, link busy\n");
1605222Sksewell@umich.edu        return false;
1614661Sksewell@umich.edu    }
1622083SN/A
1632025SN/A    DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
1642043SN/A    DDUMP(EthernetData, pkt->data, pkt->length);
1654661Sksewell@umich.edu
1665222Sksewell@umich.edu    packet = pkt;
1675222Sksewell@umich.edu    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
1684661Sksewell@umich.edu    DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
1694661Sksewell@umich.edu            delay, ticksPerByte);
1702686Sksewell@umich.edu    doneEvent.schedule(curTick + delay);
1714661Sksewell@umich.edu
1724661Sksewell@umich.edu    return true;
1734661Sksewell@umich.edu}
1744661Sksewell@umich.edu
1755222Sksewell@umich.eduvoid
1765222Sksewell@umich.eduEtherLink::Link::serialize(ostream &os)
1774661Sksewell@umich.edu{
1784661Sksewell@umich.edu    bool packet_exists = packet;
1794661Sksewell@umich.edu    SERIALIZE_SCALAR(packet_exists);
1804661Sksewell@umich.edu
1815222Sksewell@umich.edu    bool event_scheduled = doneEvent.scheduled();
1822101SN/A    SERIALIZE_SCALAR(event_scheduled);
1832084SN/A    if (event_scheduled) {
1842025SN/A        Tick event_time = doneEvent.when();
1852495SN/A        SERIALIZE_SCALAR(event_time);
1862495SN/A    }
1872495SN/A
1885222Sksewell@umich.edu    if (packet_exists) {
1895222Sksewell@umich.edu        nameOut(os, csprintf("%s.packet", name()));
1905222Sksewell@umich.edu        packet->serialize(os);
1915222Sksewell@umich.edu    }
1925222Sksewell@umich.edu}
1935222Sksewell@umich.edu
1945222Sksewell@umich.eduvoid
1955222Sksewell@umich.eduEtherLink::Link::unserialize(Checkpoint *cp, const string &section)
1965222Sksewell@umich.edu{
1975222Sksewell@umich.edu    bool packet_exists;
1985222Sksewell@umich.edu    UNSERIALIZE_SCALAR(packet_exists);
1995222Sksewell@umich.edu    if (packet_exists) {
2005222Sksewell@umich.edu        packet = new PacketData;
2015222Sksewell@umich.edu        packet->unserialize(cp, csprintf("%s.packet", section));
2025222Sksewell@umich.edu    }
2035222Sksewell@umich.edu
2045222Sksewell@umich.edu    bool event_scheduled;
2055222Sksewell@umich.edu    UNSERIALIZE_SCALAR(event_scheduled);
2065222Sksewell@umich.edu    if (event_scheduled) {
2075222Sksewell@umich.edu        Tick event_time;
2082495SN/A        UNSERIALIZE_SCALAR(event_time);
2095222Sksewell@umich.edu        doneEvent.schedule(event_time);
2105222Sksewell@umich.edu    }
2115222Sksewell@umich.edu}
2125222Sksewell@umich.edu
2135222Sksewell@umich.eduLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
2145222Sksewell@umich.edu    : Event(&mainEventQueue), link(l)
2155222Sksewell@umich.edu{
2165222Sksewell@umich.edu    setFlags(AutoSerialize);
2175222Sksewell@umich.edu    setFlags(AutoDelete);
2185222Sksewell@umich.edu}
2195222Sksewell@umich.edu
2205222Sksewell@umich.eduLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when)
2215222Sksewell@umich.edu    : Event(&mainEventQueue), link(l), packet(p)
2225222Sksewell@umich.edu{
2235222Sksewell@umich.edu    setFlags(AutoSerialize);
2242495SN/A    setFlags(AutoDelete);
2252495SN/A    schedule(when);
2262495SN/A}
2272495SN/A
2282495SN/Avoid
2292495SN/ALinkDelayEvent::process()
2302101SN/A{
2312043SN/A    link->txComplete(packet);
2322025SN/A}
2332495SN/A
2342495SN/Avoid
2352495SN/ALinkDelayEvent::serialize(ostream &os)
2362495SN/A{
2372495SN/A    paramOut(os, "type", string("LinkDelayEvent"));
2382495SN/A    Event::serialize(os);
2392101SN/A    SERIALIZE_OBJPTR(link);
2402084SN/A
2412024SN/A    nameOut(os, csprintf("%s.packet", name()));
2422043SN/A    packet->serialize(os);
2432239SN/A}
2442239SN/A
2452101SN/A
2462101SN/Avoid
2475222Sksewell@umich.eduLinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
2482101SN/A{
2492101SN/A    Event::unserialize(cp, section);
2502101SN/A    packet = new PacketData;
2512043SN/A    packet->unserialize(cp, csprintf("%s.packet", section));
2522043SN/A}
2532025SN/A
2542043SN/A
2552043SN/ASerializable *
2562101SN/ALinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
2572101SN/A{
2582101SN/A    EtherLink::Link *link;
2592686Sksewell@umich.edu    UNSERIALIZE_OBJPTR(link);
2602686Sksewell@umich.edu    return new LinkDelayEvent(link);
2612101SN/A}
2622043SN/A
2632025SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
2642043SN/A
2655222Sksewell@umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
2665222Sksewell@umich.edu
2675222Sksewell@umich.edu    SimObjectParam<EtherInt *> interface1;
2685222Sksewell@umich.edu    SimObjectParam<EtherInt *> interface2;
2695222Sksewell@umich.edu    Param<Tick> link_speed;
2705222Sksewell@umich.edu    Param<Tick> link_delay;
2715222Sksewell@umich.edu    SimObjectParam<EtherDump *> packet_dump;
2722101SN/A
2732043SN/AEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
2742043SN/A
2752043SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
2762101SN/A
2772686Sksewell@umich.edu    INIT_PARAM(interface1, "interface 1"),
2782686Sksewell@umich.edu    INIT_PARAM(interface2, "interface 2"),
2792686Sksewell@umich.edu    INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000),
2802686Sksewell@umich.edu    INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0),
2812686Sksewell@umich.edu    INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
2822686Sksewell@umich.edu
2832686Sksewell@umich.eduEND_INIT_SIM_OBJECT_PARAMS(EtherLink)
2842101SN/A
2852043SN/ACREATE_SIM_OBJECT(EtherLink)
2862043SN/A{
2872043SN/A    return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
2884661Sksewell@umich.edu                         link_delay, packet_dump);
2894661Sksewell@umich.edu}
2902101SN/A
2912101SN/AREGISTER_SIM_OBJECT("EtherLink", EtherLink)
2922101SN/A