111317Sm.alian1369@gmail.com/*
211317Sm.alian1369@gmail.com * Copyright (c) 2014 The Regents of The University of Michigan
311317Sm.alian1369@gmail.com * All rights reserved.
411317Sm.alian1369@gmail.com *
511317Sm.alian1369@gmail.com * Redistribution and use in source and binary forms, with or without
611317Sm.alian1369@gmail.com * modification, are permitted provided that the following conditions are
711317Sm.alian1369@gmail.com * met: redistributions of source code must retain the above copyright
811317Sm.alian1369@gmail.com * notice, this list of conditions and the following disclaimer;
911317Sm.alian1369@gmail.com * redistributions in binary form must reproduce the above copyright
1011317Sm.alian1369@gmail.com * notice, this list of conditions and the following disclaimer in the
1111317Sm.alian1369@gmail.com * documentation and/or other materials provided with the distribution;
1211317Sm.alian1369@gmail.com * neither the name of the copyright holders nor the names of its
1311317Sm.alian1369@gmail.com * contributors may be used to endorse or promote products derived from
1411317Sm.alian1369@gmail.com * this software without specific prior written permission.
1511317Sm.alian1369@gmail.com *
1611317Sm.alian1369@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711317Sm.alian1369@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811317Sm.alian1369@gmail.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911317Sm.alian1369@gmail.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011317Sm.alian1369@gmail.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111317Sm.alian1369@gmail.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211317Sm.alian1369@gmail.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311317Sm.alian1369@gmail.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411317Sm.alian1369@gmail.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511317Sm.alian1369@gmail.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611317Sm.alian1369@gmail.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711317Sm.alian1369@gmail.com *
2811317Sm.alian1369@gmail.com * Authors: Anthony Gutierrez
2911317Sm.alian1369@gmail.com *          Mohammad Alian
3011317Sm.alian1369@gmail.com */
3111317Sm.alian1369@gmail.com
3211317Sm.alian1369@gmail.com/* @file
3311317Sm.alian1369@gmail.com * Device model for an ethernet switch
3411317Sm.alian1369@gmail.com */
3511317Sm.alian1369@gmail.com
3611317Sm.alian1369@gmail.com#include "dev/net/etherswitch.hh"
3711317Sm.alian1369@gmail.com
3811317Sm.alian1369@gmail.com#include "base/random.hh"
3911800Sbrandon.potter@amd.com#include "base/trace.hh"
4011317Sm.alian1369@gmail.com#include "debug/EthernetAll.hh"
4111800Sbrandon.potter@amd.com#include "sim/core.hh"
4211317Sm.alian1369@gmail.com
4311317Sm.alian1369@gmail.comusing namespace std;
4411317Sm.alian1369@gmail.com
4511317Sm.alian1369@gmail.comEtherSwitch::EtherSwitch(const Params *p)
4613766Sgabeblack@google.com    : SimObject(p), ttl(p->time_to_live)
4711317Sm.alian1369@gmail.com{
4811317Sm.alian1369@gmail.com    for (int i = 0; i < p->port_interface_connection_count; ++i) {
4911317Sm.alian1369@gmail.com        std::string interfaceName = csprintf("%s.interface%d", name(), i);
5011317Sm.alian1369@gmail.com        Interface *interface = new Interface(interfaceName, this,
5111317Sm.alian1369@gmail.com                                        p->output_buffer_size, p->delay,
5211533Sm.alian1369@gmail.com                                        p->delay_var, p->fabric_speed, i);
5311317Sm.alian1369@gmail.com        interfaces.push_back(interface);
5411317Sm.alian1369@gmail.com    }
5511317Sm.alian1369@gmail.com}
5611317Sm.alian1369@gmail.com
5711317Sm.alian1369@gmail.comEtherSwitch::~EtherSwitch()
5811317Sm.alian1369@gmail.com{
5911317Sm.alian1369@gmail.com    for (auto it : interfaces)
6011317Sm.alian1369@gmail.com        delete it;
6111317Sm.alian1369@gmail.com
6211317Sm.alian1369@gmail.com    interfaces.clear();
6311317Sm.alian1369@gmail.com}
6411317Sm.alian1369@gmail.com
6513784Sgabeblack@google.comPort &
6613784Sgabeblack@google.comEtherSwitch::getPort(const std::string &if_name, PortID idx)
6711317Sm.alian1369@gmail.com{
6813784Sgabeblack@google.com    if (if_name == "interface") {
6913784Sgabeblack@google.com        panic_if(idx < 0 || idx >= interfaces.size(), "index out of bounds");
7013784Sgabeblack@google.com        return *interfaces.at(idx);
7113784Sgabeblack@google.com    }
7211317Sm.alian1369@gmail.com
7313784Sgabeblack@google.com    return SimObject::getPort(if_name, idx);
7411317Sm.alian1369@gmail.com}
7511317Sm.alian1369@gmail.com
7611533Sm.alian1369@gmail.combool
7711533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifo::push(EthPacketPtr ptr, unsigned senderId)
7811533Sm.alian1369@gmail.com{
7911533Sm.alian1369@gmail.com    assert(ptr->length);
8011533Sm.alian1369@gmail.com
8111533Sm.alian1369@gmail.com    _size += ptr->length;
8211533Sm.alian1369@gmail.com    fifo.emplace_hint(fifo.end(), ptr, curTick(), senderId);
8311533Sm.alian1369@gmail.com
8411533Sm.alian1369@gmail.com    // Drop the extra pushed packets from end of the fifo
8511533Sm.alian1369@gmail.com    while (avail() < 0) {
8611533Sm.alian1369@gmail.com        DPRINTF(Ethernet, "Fifo is full. Drop packet: len=%d\n",
8711533Sm.alian1369@gmail.com                std::prev(fifo.end())->packet->length);
8811533Sm.alian1369@gmail.com
8911533Sm.alian1369@gmail.com        _size -= std::prev(fifo.end())->packet->length;
9011533Sm.alian1369@gmail.com        fifo.erase(std::prev(fifo.end()));
9111533Sm.alian1369@gmail.com    }
9211533Sm.alian1369@gmail.com
9311533Sm.alian1369@gmail.com    if (empty()) {
9411533Sm.alian1369@gmail.com        warn("EtherSwitch: Packet length (%d) exceeds the maximum storage "
9511533Sm.alian1369@gmail.com             "capacity of port fifo (%d)", ptr->length, _maxsize);
9611533Sm.alian1369@gmail.com    }
9711533Sm.alian1369@gmail.com
9811533Sm.alian1369@gmail.com    // Return true if the newly pushed packet gets inserted
9911533Sm.alian1369@gmail.com    // at the head of the queue, otherwise return false
10011533Sm.alian1369@gmail.com    // We need this information to deschedule the event that has been
10111533Sm.alian1369@gmail.com    // scheduled for the old head of queue packet and schedule a new one
10211533Sm.alian1369@gmail.com    if (!empty() && fifo.begin()->packet == ptr) {
10311533Sm.alian1369@gmail.com        return true;
10411533Sm.alian1369@gmail.com    }
10511533Sm.alian1369@gmail.com    return false;
10611533Sm.alian1369@gmail.com}
10711533Sm.alian1369@gmail.com
10811533Sm.alian1369@gmail.comvoid
10911533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifo::pop()
11011533Sm.alian1369@gmail.com{
11111533Sm.alian1369@gmail.com    if (empty())
11211533Sm.alian1369@gmail.com        return;
11311533Sm.alian1369@gmail.com
11411533Sm.alian1369@gmail.com    assert(_size >= fifo.begin()->packet->length);
11511533Sm.alian1369@gmail.com    // Erase the packet at the head of the queue
11611533Sm.alian1369@gmail.com    _size -= fifo.begin()->packet->length;
11711533Sm.alian1369@gmail.com    fifo.erase(fifo.begin());
11811533Sm.alian1369@gmail.com}
11911533Sm.alian1369@gmail.com
12011533Sm.alian1369@gmail.comvoid
12111533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifo::clear()
12211533Sm.alian1369@gmail.com{
12311533Sm.alian1369@gmail.com    fifo.clear();
12411533Sm.alian1369@gmail.com    _size = 0;
12511533Sm.alian1369@gmail.com}
12611533Sm.alian1369@gmail.com
12711317Sm.alian1369@gmail.comEtherSwitch::Interface::Interface(const std::string &name,
12811317Sm.alian1369@gmail.com                                  EtherSwitch *etherSwitch,
12911317Sm.alian1369@gmail.com                                  uint64_t outputBufferSize, Tick delay,
13011533Sm.alian1369@gmail.com                                  Tick delay_var, double rate, unsigned id)
13111317Sm.alian1369@gmail.com    : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
13211533Sm.alian1369@gmail.com      delayVar(delay_var), interfaceId(id), parent(etherSwitch),
13312087Sspwilson2@wisc.edu      outputFifo(name + ".outputFifo", outputBufferSize),
13412087Sspwilson2@wisc.edu      txEvent([this]{ transmit(); }, name)
13511317Sm.alian1369@gmail.com{
13611317Sm.alian1369@gmail.com}
13711317Sm.alian1369@gmail.com
13811317Sm.alian1369@gmail.combool
13911317Sm.alian1369@gmail.comEtherSwitch::Interface::recvPacket(EthPacketPtr packet)
14011317Sm.alian1369@gmail.com{
14111317Sm.alian1369@gmail.com    Net::EthAddr destMacAddr(packet->data);
14211317Sm.alian1369@gmail.com    Net::EthAddr srcMacAddr(&packet->data[6]);
14311317Sm.alian1369@gmail.com
14411317Sm.alian1369@gmail.com    learnSenderAddr(srcMacAddr, this);
14511317Sm.alian1369@gmail.com    Interface *receiver = lookupDestPort(destMacAddr);
14611317Sm.alian1369@gmail.com
14711317Sm.alian1369@gmail.com    if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
14811317Sm.alian1369@gmail.com        for (auto it : parent->interfaces)
14911317Sm.alian1369@gmail.com            if (it != this)
15011533Sm.alian1369@gmail.com                it->enqueue(packet, interfaceId);
15111317Sm.alian1369@gmail.com    } else {
15211317Sm.alian1369@gmail.com        DPRINTF(Ethernet, "sending packet from MAC %x on port "
15311317Sm.alian1369@gmail.com                "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
15411317Sm.alian1369@gmail.com                this->name(), uint64_t(destMacAddr), receiver->name());
15511317Sm.alian1369@gmail.com
15611533Sm.alian1369@gmail.com        receiver->enqueue(packet, interfaceId);
15711317Sm.alian1369@gmail.com    }
15811317Sm.alian1369@gmail.com    // At the output port, we either have buffer space (no drop) or
15911317Sm.alian1369@gmail.com    // don't (drop packet); in both cases packet is received on
16011317Sm.alian1369@gmail.com    // the interface successfully and there is no notion of busy
16111317Sm.alian1369@gmail.com    // interface here (as we don't have inputFifo)
16211317Sm.alian1369@gmail.com    return true;
16311317Sm.alian1369@gmail.com}
16411317Sm.alian1369@gmail.com
16511317Sm.alian1369@gmail.comvoid
16611533Sm.alian1369@gmail.comEtherSwitch::Interface::enqueue(EthPacketPtr packet, unsigned senderId)
16711317Sm.alian1369@gmail.com{
16811317Sm.alian1369@gmail.com    // assuming per-interface transmission events,
16911533Sm.alian1369@gmail.com    // if the newly push packet gets inserted at the head of the queue
17011533Sm.alian1369@gmail.com    // (either there was nothing in the queue or the priority of the new
17111533Sm.alian1369@gmail.com    // packet was higher than the packets already in the fifo)
17211533Sm.alian1369@gmail.com    // then we need to schedule an event at
17311533Sm.alian1369@gmail.com    // "curTick" + "switchingDelay of the packet at the head of the fifo"
17411533Sm.alian1369@gmail.com    // to send this packet out the external link
17511317Sm.alian1369@gmail.com    // otherwise, there is already a txEvent scheduled
17611533Sm.alian1369@gmail.com    if (outputFifo.push(packet, senderId)) {
17711562Sm.alian1369@gmail.com        parent->reschedule(txEvent, curTick() + switchingDelay(), true);
17811317Sm.alian1369@gmail.com    }
17911317Sm.alian1369@gmail.com}
18011317Sm.alian1369@gmail.com
18111317Sm.alian1369@gmail.comvoid
18211317Sm.alian1369@gmail.comEtherSwitch::Interface::transmit()
18311317Sm.alian1369@gmail.com{
18411317Sm.alian1369@gmail.com    // there should be something in the output queue
18511317Sm.alian1369@gmail.com    assert(!outputFifo.empty());
18611317Sm.alian1369@gmail.com
18711317Sm.alian1369@gmail.com    if (!sendPacket(outputFifo.front())) {
18811317Sm.alian1369@gmail.com        DPRINTF(Ethernet, "output port busy...retry later\n");
18911317Sm.alian1369@gmail.com        if (!txEvent.scheduled())
19011317Sm.alian1369@gmail.com            parent->schedule(txEvent, curTick() + retryTime);
19111317Sm.alian1369@gmail.com    } else {
19211317Sm.alian1369@gmail.com        DPRINTF(Ethernet, "packet sent: len=%d\n", outputFifo.front()->length);
19311317Sm.alian1369@gmail.com        outputFifo.pop();
19411317Sm.alian1369@gmail.com        // schedule an event to send the pkt at
19511317Sm.alian1369@gmail.com        // the head of queue, if there is any
19611317Sm.alian1369@gmail.com        if (!outputFifo.empty()) {
19711317Sm.alian1369@gmail.com            parent->schedule(txEvent, curTick() + switchingDelay());
19811317Sm.alian1369@gmail.com        }
19911317Sm.alian1369@gmail.com    }
20011317Sm.alian1369@gmail.com}
20111317Sm.alian1369@gmail.com
20211317Sm.alian1369@gmail.comTick
20311317Sm.alian1369@gmail.comEtherSwitch::Interface::switchingDelay()
20411317Sm.alian1369@gmail.com{
20511701Smichael.lebeane@amd.com    Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength
20611317Sm.alian1369@gmail.com                                     * ticksPerByte) + 1.0);
20711317Sm.alian1369@gmail.com    if (delayVar != 0)
20811317Sm.alian1369@gmail.com                delay += random_mt.random<Tick>(0, delayVar);
20911317Sm.alian1369@gmail.com    delay += switchDelay;
21011317Sm.alian1369@gmail.com    return delay;
21111317Sm.alian1369@gmail.com}
21211317Sm.alian1369@gmail.com
21311317Sm.alian1369@gmail.comEtherSwitch::Interface*
21411317Sm.alian1369@gmail.comEtherSwitch::Interface::lookupDestPort(Net::EthAddr destMacAddr)
21511317Sm.alian1369@gmail.com{
21611317Sm.alian1369@gmail.com    auto it = parent->forwardingTable.find(uint64_t(destMacAddr));
21711317Sm.alian1369@gmail.com
21811317Sm.alian1369@gmail.com    if (it == parent->forwardingTable.end()) {
21911317Sm.alian1369@gmail.com        DPRINTF(Ethernet, "no entry in forwaring table for MAC: "
22011317Sm.alian1369@gmail.com                "%x\n", uint64_t(destMacAddr));
22111317Sm.alian1369@gmail.com        return nullptr;
22211317Sm.alian1369@gmail.com    }
22311317Sm.alian1369@gmail.com
22411317Sm.alian1369@gmail.com    // check if this entry is valid based on TTL and lastUseTime
22511317Sm.alian1369@gmail.com    if ((curTick() - it->second.lastUseTime) > parent->ttl) {
22611317Sm.alian1369@gmail.com        // TTL for this mapping has been expired, so this item is not
22711317Sm.alian1369@gmail.com        // valide anymore, let's remove it from the map
22811317Sm.alian1369@gmail.com        parent->forwardingTable.erase(it);
22911317Sm.alian1369@gmail.com        return nullptr;
23011317Sm.alian1369@gmail.com    }
23111317Sm.alian1369@gmail.com
23211317Sm.alian1369@gmail.com    DPRINTF(Ethernet, "found entry for MAC address %x on port %s\n",
23311317Sm.alian1369@gmail.com            uint64_t(destMacAddr), it->second.interface->name());
23411317Sm.alian1369@gmail.com    return it->second.interface;
23511317Sm.alian1369@gmail.com}
23611317Sm.alian1369@gmail.com
23711317Sm.alian1369@gmail.comvoid
23811317Sm.alian1369@gmail.comEtherSwitch::Interface::learnSenderAddr(Net::EthAddr srcMacAddr,
23911317Sm.alian1369@gmail.com                                          Interface *sender)
24011317Sm.alian1369@gmail.com{
24111317Sm.alian1369@gmail.com    // learn the port for the sending MAC address
24211317Sm.alian1369@gmail.com    auto it = parent->forwardingTable.find(uint64_t(srcMacAddr));
24311317Sm.alian1369@gmail.com
24411317Sm.alian1369@gmail.com    // if the port for sender's MAC address is not cached,
24511317Sm.alian1369@gmail.com    // cache it now, otherwise just update lastUseTime time
24611317Sm.alian1369@gmail.com    if (it == parent->forwardingTable.end()) {
24711317Sm.alian1369@gmail.com        DPRINTF(Ethernet, "adding forwarding table entry for MAC "
24811317Sm.alian1369@gmail.com                " address %x on port %s\n", uint64_t(srcMacAddr),
24911317Sm.alian1369@gmail.com                sender->name());
25011317Sm.alian1369@gmail.com        EtherSwitch::SwitchTableEntry forwardingTableEntry;
25111317Sm.alian1369@gmail.com        forwardingTableEntry.interface = sender;
25211317Sm.alian1369@gmail.com        forwardingTableEntry.lastUseTime = curTick();
25311317Sm.alian1369@gmail.com        parent->forwardingTable.insert(std::make_pair(uint64_t(srcMacAddr),
25411317Sm.alian1369@gmail.com            forwardingTableEntry));
25511317Sm.alian1369@gmail.com    } else {
25611317Sm.alian1369@gmail.com        it->second.lastUseTime = curTick();
25711317Sm.alian1369@gmail.com    }
25811317Sm.alian1369@gmail.com}
25911317Sm.alian1369@gmail.com
26011317Sm.alian1369@gmail.comvoid
26111317Sm.alian1369@gmail.comEtherSwitch::serialize(CheckpointOut &cp) const
26211317Sm.alian1369@gmail.com{
26311317Sm.alian1369@gmail.com    for (auto it : interfaces)
26411533Sm.alian1369@gmail.com        it->serializeSection(cp, it->name());
26511533Sm.alian1369@gmail.com
26611317Sm.alian1369@gmail.com}
26711317Sm.alian1369@gmail.com
26811317Sm.alian1369@gmail.comvoid
26911317Sm.alian1369@gmail.comEtherSwitch::unserialize(CheckpointIn &cp)
27011317Sm.alian1369@gmail.com{
27111317Sm.alian1369@gmail.com    for (auto it : interfaces)
27211533Sm.alian1369@gmail.com        it->unserializeSection(cp, it->name());
27311533Sm.alian1369@gmail.com
27411317Sm.alian1369@gmail.com}
27511317Sm.alian1369@gmail.com
27611317Sm.alian1369@gmail.comvoid
27711533Sm.alian1369@gmail.comEtherSwitch::Interface::serialize(CheckpointOut &cp) const
27811317Sm.alian1369@gmail.com{
27911317Sm.alian1369@gmail.com    bool event_scheduled = txEvent.scheduled();
28011533Sm.alian1369@gmail.com    SERIALIZE_SCALAR(event_scheduled);
28111533Sm.alian1369@gmail.com
28211317Sm.alian1369@gmail.com    if (event_scheduled) {
28311317Sm.alian1369@gmail.com        Tick event_time = txEvent.when();
28411533Sm.alian1369@gmail.com        SERIALIZE_SCALAR(event_time);
28511317Sm.alian1369@gmail.com    }
28611533Sm.alian1369@gmail.com    outputFifo.serializeSection(cp, "outputFifo");
28711317Sm.alian1369@gmail.com}
28811317Sm.alian1369@gmail.com
28911317Sm.alian1369@gmail.comvoid
29011533Sm.alian1369@gmail.comEtherSwitch::Interface::unserialize(CheckpointIn &cp)
29111317Sm.alian1369@gmail.com{
29211317Sm.alian1369@gmail.com    bool event_scheduled;
29311533Sm.alian1369@gmail.com    UNSERIALIZE_SCALAR(event_scheduled);
29411533Sm.alian1369@gmail.com
29511317Sm.alian1369@gmail.com    if (event_scheduled) {
29611317Sm.alian1369@gmail.com        Tick event_time;
29711533Sm.alian1369@gmail.com        UNSERIALIZE_SCALAR(event_time);
29811317Sm.alian1369@gmail.com        parent->schedule(txEvent, event_time);
29911317Sm.alian1369@gmail.com    }
30011533Sm.alian1369@gmail.com    outputFifo.unserializeSection(cp, "outputFifo");
30111533Sm.alian1369@gmail.com}
30211317Sm.alian1369@gmail.com
30311533Sm.alian1369@gmail.comvoid
30411533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifoEntry::serialize(CheckpointOut &cp) const
30511533Sm.alian1369@gmail.com{
30611533Sm.alian1369@gmail.com    packet->serialize("packet", cp);
30711533Sm.alian1369@gmail.com    SERIALIZE_SCALAR(recvTick);
30811533Sm.alian1369@gmail.com    SERIALIZE_SCALAR(srcId);
30911533Sm.alian1369@gmail.com}
31011533Sm.alian1369@gmail.com
31111533Sm.alian1369@gmail.comvoid
31211533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifoEntry::unserialize(CheckpointIn &cp)
31311533Sm.alian1369@gmail.com{
31411533Sm.alian1369@gmail.com    packet = make_shared<EthPacketData>(16384);
31511533Sm.alian1369@gmail.com    packet->unserialize("packet", cp);
31611533Sm.alian1369@gmail.com    UNSERIALIZE_SCALAR(recvTick);
31711533Sm.alian1369@gmail.com    UNSERIALIZE_SCALAR(srcId);
31811533Sm.alian1369@gmail.com}
31911533Sm.alian1369@gmail.com
32011533Sm.alian1369@gmail.comvoid
32111533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifo::serialize(CheckpointOut &cp) const
32211533Sm.alian1369@gmail.com{
32311533Sm.alian1369@gmail.com    SERIALIZE_SCALAR(_size);
32411533Sm.alian1369@gmail.com    int fifosize = fifo.size();
32511533Sm.alian1369@gmail.com
32611533Sm.alian1369@gmail.com    SERIALIZE_SCALAR(fifosize);
32711533Sm.alian1369@gmail.com
32811533Sm.alian1369@gmail.com    int i = 0;
32911533Sm.alian1369@gmail.com    for (const auto &entry : fifo)
33011533Sm.alian1369@gmail.com        entry.serializeSection(cp, csprintf("entry%d", i++));
33111533Sm.alian1369@gmail.com}
33211533Sm.alian1369@gmail.com
33311533Sm.alian1369@gmail.comvoid
33411533Sm.alian1369@gmail.comEtherSwitch::Interface::PortFifo::unserialize(CheckpointIn &cp)
33511533Sm.alian1369@gmail.com{
33611533Sm.alian1369@gmail.com    UNSERIALIZE_SCALAR(_size);
33711533Sm.alian1369@gmail.com    int fifosize;
33811533Sm.alian1369@gmail.com
33911533Sm.alian1369@gmail.com    UNSERIALIZE_SCALAR(fifosize);
34011533Sm.alian1369@gmail.com    fifo.clear();
34111533Sm.alian1369@gmail.com
34211533Sm.alian1369@gmail.com    for (int i = 0; i < fifosize; ++i) {
34311533Sm.alian1369@gmail.com        PortFifoEntry entry(nullptr, 0, 0);
34411533Sm.alian1369@gmail.com
34511533Sm.alian1369@gmail.com        entry.unserializeSection(cp, csprintf("entry%d", i));
34611533Sm.alian1369@gmail.com
34711533Sm.alian1369@gmail.com        fifo.insert(entry);
34811533Sm.alian1369@gmail.com
34911533Sm.alian1369@gmail.com    }
35011317Sm.alian1369@gmail.com}
35111317Sm.alian1369@gmail.com
35211317Sm.alian1369@gmail.comEtherSwitch *
35311317Sm.alian1369@gmail.comEtherSwitchParams::create()
35411317Sm.alian1369@gmail.com{
35511317Sm.alian1369@gmail.com    return new EtherSwitch(this);
35611317Sm.alian1369@gmail.com}
357