dist_etherlink.cc revision 11263
14484Sbinkertn@umich.edu/*
24484Sbinkertn@umich.edu * Copyright (c) 2015 ARM Limited
34484Sbinkertn@umich.edu * All rights reserved
44484Sbinkertn@umich.edu *
54484Sbinkertn@umich.edu * The license below extends only to copyright in the software and shall
64484Sbinkertn@umich.edu * not be construed as granting a license to any other intellectual
74484Sbinkertn@umich.edu * property including but not limited to intellectual property relating
84484Sbinkertn@umich.edu * to a hardware implementation of the functionality of the software
94484Sbinkertn@umich.edu * licensed hereunder.  You may use the software subject to the license
104484Sbinkertn@umich.edu * terms below provided that you ensure that this notice is replicated
114484Sbinkertn@umich.edu * unmodified and in its entirety in all distributions of the software,
124484Sbinkertn@umich.edu * modified or unmodified, in source code or in binary form.
134484Sbinkertn@umich.edu *
144484Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
154484Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are
164484Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright
174484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer;
184484Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright
194484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the
204484Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution;
214484Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its
224484Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from
234484Sbinkertn@umich.edu * this software without specific prior written permission.
244484Sbinkertn@umich.edu *
254484Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
264484Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
274484Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
284484Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
294484Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
304484Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
314484Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
324484Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
334484Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
344484Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
354484Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364484Sbinkertn@umich.edu *
374484Sbinkertn@umich.edu * Authors: Gabor Dozsa
384484Sbinkertn@umich.edu */
394484Sbinkertn@umich.edu
404484Sbinkertn@umich.edu/* @file
414484Sbinkertn@umich.edu * Device module for a full duplex ethernet link for multi gem5 simulations.
424484Sbinkertn@umich.edu */
434484Sbinkertn@umich.edu
444484Sbinkertn@umich.edu#include "dev/net/multi_etherlink.hh"
454484Sbinkertn@umich.edu
464484Sbinkertn@umich.edu#include <arpa/inet.h>
474484Sbinkertn@umich.edu#include <sys/socket.h>
484484Sbinkertn@umich.edu#include <unistd.h>
494484Sbinkertn@umich.edu
504484Sbinkertn@umich.edu#include <cmath>
514484Sbinkertn@umich.edu#include <deque>
524484Sbinkertn@umich.edu#include <string>
534484Sbinkertn@umich.edu#include <vector>
544484Sbinkertn@umich.edu
554484Sbinkertn@umich.edu#include "base/random.hh"
564484Sbinkertn@umich.edu#include "base/trace.hh"
574484Sbinkertn@umich.edu#include "debug/EthernetData.hh"
584484Sbinkertn@umich.edu#include "debug/MultiEthernet.hh"
594484Sbinkertn@umich.edu#include "debug/MultiEthernetPkt.hh"
604484Sbinkertn@umich.edu#include "dev/net/etherdump.hh"
614484Sbinkertn@umich.edu#include "dev/net/etherint.hh"
624484Sbinkertn@umich.edu#include "dev/net/etherlink.hh"
634484Sbinkertn@umich.edu#include "dev/net/etherobject.hh"
644484Sbinkertn@umich.edu#include "dev/net/etherpkt.hh"
654484Sbinkertn@umich.edu#include "dev/net/multi_iface.hh"
664484Sbinkertn@umich.edu#include "dev/net/tcp_iface.hh"
674484Sbinkertn@umich.edu#include "params/EtherLink.hh"
684484Sbinkertn@umich.edu#include "sim/core.hh"
694484Sbinkertn@umich.edu#include "sim/serialize.hh"
704484Sbinkertn@umich.edu#include "sim/system.hh"
714484Sbinkertn@umich.edu
724484Sbinkertn@umich.eduusing namespace std;
734484Sbinkertn@umich.edu
744484Sbinkertn@umich.eduMultiEtherLink::MultiEtherLink(const Params *p)
754484Sbinkertn@umich.edu    : EtherObject(p)
764484Sbinkertn@umich.edu{
774484Sbinkertn@umich.edu    DPRINTF(MultiEthernet,"MultiEtherLink::MultiEtherLink() "
784484Sbinkertn@umich.edu            "link delay:%llu\n", p->delay);
794484Sbinkertn@umich.edu
804484Sbinkertn@umich.edu    txLink = new TxLink(name() + ".link0", this, p->speed, p->delay_var,
814484Sbinkertn@umich.edu                        p->dump);
824484Sbinkertn@umich.edu    rxLink = new RxLink(name() + ".link1", this, p->delay, p->dump);
834484Sbinkertn@umich.edu
844484Sbinkertn@umich.edu    // create the multi (TCP) interface to talk to the peer gem5 processes.
854484Sbinkertn@umich.edu    multiIface = new TCPIface(p->server_name, p->server_port, p->multi_rank,
864484Sbinkertn@umich.edu                              p->sync_start, p->sync_repeat, this);
874484Sbinkertn@umich.edu
884484Sbinkertn@umich.edu    localIface = new LocalIface(name() + ".int0", txLink, rxLink, multiIface);
894484Sbinkertn@umich.edu}
904484Sbinkertn@umich.edu
914484Sbinkertn@umich.eduMultiEtherLink::~MultiEtherLink()
924484Sbinkertn@umich.edu{
934484Sbinkertn@umich.edu    delete txLink;
944484Sbinkertn@umich.edu    delete rxLink;
954484Sbinkertn@umich.edu    delete localIface;
964484Sbinkertn@umich.edu    delete multiIface;
974484Sbinkertn@umich.edu}
984484Sbinkertn@umich.edu
994484Sbinkertn@umich.eduEtherInt*
1004484Sbinkertn@umich.eduMultiEtherLink::getEthPort(const std::string &if_name, int idx)
1014484Sbinkertn@umich.edu{
1024484Sbinkertn@umich.edu    if (if_name != "int0") {
1034484Sbinkertn@umich.edu        return nullptr;
1044484Sbinkertn@umich.edu    } else {
1054484Sbinkertn@umich.edu        panic_if(localIface->getPeer(), "interface already connected to");
1064484Sbinkertn@umich.edu    }
1074484Sbinkertn@umich.edu    return localIface;
1084484Sbinkertn@umich.edu}
1094484Sbinkertn@umich.edu
1104484Sbinkertn@umich.eduvoid MultiEtherLink::memWriteback()
1114484Sbinkertn@umich.edu{
1124484Sbinkertn@umich.edu    DPRINTF(MultiEthernet,"MultiEtherLink::memWriteback() called\n");
1134484Sbinkertn@umich.edu    multiIface->drainDone();
1144484Sbinkertn@umich.edu}
1154484Sbinkertn@umich.edu
1164484Sbinkertn@umich.eduvoid
1174484Sbinkertn@umich.eduMultiEtherLink::serialize(CheckpointOut &cp) const
1184484Sbinkertn@umich.edu{
1194484Sbinkertn@umich.edu    multiIface->serialize("multiIface", cp);
1204484Sbinkertn@umich.edu    txLink->serialize("txLink", cp);
1214484Sbinkertn@umich.edu    rxLink->serialize("rxLink", cp);
1224484Sbinkertn@umich.edu}
1234484Sbinkertn@umich.edu
1244484Sbinkertn@umich.eduvoid
1254484Sbinkertn@umich.eduMultiEtherLink::unserialize(CheckpointIn &cp)
1264484Sbinkertn@umich.edu{
1274484Sbinkertn@umich.edu    multiIface->unserialize("multiIface", cp);
1284484Sbinkertn@umich.edu    txLink->unserialize("txLink", cp);
1294484Sbinkertn@umich.edu    rxLink->unserialize("rxLink", cp);
1304484Sbinkertn@umich.edu}
1314484Sbinkertn@umich.edu
1324484Sbinkertn@umich.eduvoid
1334484Sbinkertn@umich.eduMultiEtherLink::init()
1344484Sbinkertn@umich.edu{
1354484Sbinkertn@umich.edu    DPRINTF(MultiEthernet,"MultiEtherLink::init() called\n");
1364484Sbinkertn@umich.edu    multiIface->initRandom();
1374484Sbinkertn@umich.edu}
1384484Sbinkertn@umich.edu
1394484Sbinkertn@umich.eduvoid
1404484Sbinkertn@umich.eduMultiEtherLink::startup()
1414484Sbinkertn@umich.edu{
1424484Sbinkertn@umich.edu    DPRINTF(MultiEthernet,"MultiEtherLink::startup() called\n");
1434484Sbinkertn@umich.edu    multiIface->startPeriodicSync();
1444484Sbinkertn@umich.edu}
1454484Sbinkertn@umich.edu
1464484Sbinkertn@umich.eduvoid
1474484Sbinkertn@umich.eduMultiEtherLink::RxLink::setMultiInt(MultiIface *m)
1484484Sbinkertn@umich.edu{
1494484Sbinkertn@umich.edu    assert(!multiIface);
1504484Sbinkertn@umich.edu    multiIface = m;
1514484Sbinkertn@umich.edu    // Spawn a new receiver thread that will process messages
1524484Sbinkertn@umich.edu    // coming in from peer gem5 processes.
1534484Sbinkertn@umich.edu    // The receive thread will also schedule a (receive) doneEvent
1544484Sbinkertn@umich.edu    // for each incoming data packet.
1554484Sbinkertn@umich.edu    multiIface->spawnRecvThread(&doneEvent, linkDelay);
1564484Sbinkertn@umich.edu}
1574484Sbinkertn@umich.edu
1584484Sbinkertn@umich.eduvoid
1594484Sbinkertn@umich.eduMultiEtherLink::RxLink::rxDone()
1604484Sbinkertn@umich.edu{
1614484Sbinkertn@umich.edu    assert(!busy());
1624484Sbinkertn@umich.edu
1634484Sbinkertn@umich.edu    // retrieve the packet that triggered the receive done event
1644484Sbinkertn@umich.edu    packet = multiIface->packetIn();
1654484Sbinkertn@umich.edu
1664484Sbinkertn@umich.edu    if (dump)
1674484Sbinkertn@umich.edu        dump->dump(packet);
1684484Sbinkertn@umich.edu
1694484Sbinkertn@umich.edu    DPRINTF(MultiEthernetPkt, "MultiEtherLink::MultiLink::rxDone() "
1704484Sbinkertn@umich.edu            "packet received: len=%d\n", packet->length);
1714484Sbinkertn@umich.edu    DDUMP(EthernetData, packet->data, packet->length);
1724484Sbinkertn@umich.edu
1734484Sbinkertn@umich.edu    localIface->sendPacket(packet);
1744484Sbinkertn@umich.edu
1754484Sbinkertn@umich.edu    packet = nullptr;
1764484Sbinkertn@umich.edu}
1774484Sbinkertn@umich.edu
1784484Sbinkertn@umich.eduvoid
1794484Sbinkertn@umich.eduMultiEtherLink::TxLink::txDone()
1804484Sbinkertn@umich.edu{
1814484Sbinkertn@umich.edu    if (dump)
1824484Sbinkertn@umich.edu        dump->dump(packet);
1834484Sbinkertn@umich.edu
1844484Sbinkertn@umich.edu    packet = nullptr;
1854484Sbinkertn@umich.edu    assert(!busy());
1864484Sbinkertn@umich.edu
1874484Sbinkertn@umich.edu    localIface->sendDone();
1884484Sbinkertn@umich.edu}
1894484Sbinkertn@umich.edu
1904484Sbinkertn@umich.edubool
1914484Sbinkertn@umich.eduMultiEtherLink::TxLink::transmit(EthPacketPtr pkt)
1924484Sbinkertn@umich.edu{
1934484Sbinkertn@umich.edu    if (busy()) {
1944484Sbinkertn@umich.edu        DPRINTF(MultiEthernet, "packet not sent, link busy\n");
1954484Sbinkertn@umich.edu        return false;
1964484Sbinkertn@umich.edu    }
1974484Sbinkertn@umich.edu
1984484Sbinkertn@umich.edu    packet = pkt;
1994484Sbinkertn@umich.edu    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
2004484Sbinkertn@umich.edu    if (delayVar != 0)
2014484Sbinkertn@umich.edu        delay += random_mt.random<Tick>(0, delayVar);
2024484Sbinkertn@umich.edu
2034484Sbinkertn@umich.edu    // send the packet to the peers
2044484Sbinkertn@umich.edu    assert(multiIface);
2054484Sbinkertn@umich.edu    multiIface->packetOut(pkt, delay);
2064484Sbinkertn@umich.edu
2074484Sbinkertn@umich.edu    // schedule the send done event
2084484Sbinkertn@umich.edu    parent->schedule(doneEvent, curTick() + delay);
2094484Sbinkertn@umich.edu
2104484Sbinkertn@umich.edu    return true;
2114484Sbinkertn@umich.edu}
2124484Sbinkertn@umich.edu
2134484Sbinkertn@umich.eduvoid
2144484Sbinkertn@umich.eduMultiEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const
2154484Sbinkertn@umich.edu{
2164484Sbinkertn@umich.edu    bool packet_exists = (packet != nullptr);
2174484Sbinkertn@umich.edu    paramOut(cp, base + ".packet_exists", packet_exists);
2184484Sbinkertn@umich.edu    if (packet_exists)
2194484Sbinkertn@umich.edu        packet->serialize(base + ".packet", cp);
2204484Sbinkertn@umich.edu
2214484Sbinkertn@umich.edu    bool event_scheduled = event->scheduled();
2224484Sbinkertn@umich.edu    paramOut(cp, base + ".event_scheduled", event_scheduled);
2234484Sbinkertn@umich.edu    if (event_scheduled) {
2244484Sbinkertn@umich.edu        Tick event_time = event->when();
2254484Sbinkertn@umich.edu        paramOut(cp, base + ".event_time", event_time);
2264484Sbinkertn@umich.edu    }
2274484Sbinkertn@umich.edu}
2284484Sbinkertn@umich.edu
2294484Sbinkertn@umich.eduvoid
2304484Sbinkertn@umich.eduMultiEtherLink::Link::unserialize(const string &base, CheckpointIn &cp)
2314484Sbinkertn@umich.edu{
2324484Sbinkertn@umich.edu    bool packet_exists;
2334484Sbinkertn@umich.edu    paramIn(cp, base + ".packet_exists", packet_exists);
2344484Sbinkertn@umich.edu    if (packet_exists) {
2354484Sbinkertn@umich.edu        packet = make_shared<EthPacketData>(16384);
2364484Sbinkertn@umich.edu        packet->unserialize(base + ".packet", cp);
2374484Sbinkertn@umich.edu    }
2384484Sbinkertn@umich.edu
2394484Sbinkertn@umich.edu    bool event_scheduled;
2404484Sbinkertn@umich.edu    paramIn(cp, base + ".event_scheduled", event_scheduled);
2414484Sbinkertn@umich.edu    if (event_scheduled) {
2424484Sbinkertn@umich.edu        Tick event_time;
2434484Sbinkertn@umich.edu        paramIn(cp, base + ".event_time", event_time);
2444484Sbinkertn@umich.edu        parent->schedule(*event, event_time);
2454484Sbinkertn@umich.edu    }
2464484Sbinkertn@umich.edu}
2474484Sbinkertn@umich.edu
2484484Sbinkertn@umich.eduMultiEtherLink::LocalIface::LocalIface(const std::string &name,
2494484Sbinkertn@umich.edu                                       TxLink *tx,
2504484Sbinkertn@umich.edu                                       RxLink *rx,
2514484Sbinkertn@umich.edu                                       MultiIface *m) :
2524484Sbinkertn@umich.edu    EtherInt(name), txLink(tx)
2534484Sbinkertn@umich.edu{
2544484Sbinkertn@umich.edu    tx->setLocalInt(this);
2554484Sbinkertn@umich.edu    rx->setLocalInt(this);
2564484Sbinkertn@umich.edu    tx->setMultiInt(m);
2574484Sbinkertn@umich.edu    rx->setMultiInt(m);
2584484Sbinkertn@umich.edu}
2594484Sbinkertn@umich.edu
2604484Sbinkertn@umich.eduMultiEtherLink *
2614484Sbinkertn@umich.eduMultiEtherLinkParams::create()
2624484Sbinkertn@umich.edu{
2634484Sbinkertn@umich.edu    return new MultiEtherLink(this);
2644484Sbinkertn@umich.edu}
2654484Sbinkertn@umich.edu
2664484Sbinkertn@umich.edu
2674484Sbinkertn@umich.edu