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