gem5 v24.0.0.0
Loading...
Searching...
No Matches
etherswitch.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* @file
30 * Device model for an ethernet switch
31 */
32
34
35#include "base/random.hh"
36#include "base/trace.hh"
37#include "debug/EthernetAll.hh"
38#include "sim/core.hh"
39#include "sim/cur_tick.hh"
40
41namespace gem5
42{
43
45 : SimObject(p), ttl(p.time_to_live)
46{
47 for (int i = 0; i < p.port_interface_connection_count; ++i) {
48 std::string interfaceName = csprintf("%s.interface%d", name(), i);
49 Interface *interface = new Interface(interfaceName, this,
50 p.output_buffer_size, p.delay,
51 p.delay_var, p.fabric_speed, i);
52 interfaces.push_back(interface);
53 }
54}
55
57{
58 for (auto it : interfaces)
59 delete it;
60
61 interfaces.clear();
62}
63
64Port &
65EtherSwitch::getPort(const std::string &if_name, PortID idx)
66{
67 if (if_name == "interface") {
68 panic_if(idx < 0 || idx >= interfaces.size(), "index out of bounds");
69 return *interfaces.at(idx);
70 }
71
72 return SimObject::getPort(if_name, idx);
73}
74
75bool
77{
78 assert(ptr->length);
79
80 _size += ptr->length;
81 fifo.emplace_hint(fifo.end(), ptr, curTick(), senderId);
82
83 // Drop the extra pushed packets from end of the fifo
84 while (avail() < 0) {
85 DPRINTF(Ethernet, "Fifo is full. Drop packet: len=%d\n",
86 std::prev(fifo.end())->packet->length);
87
88 _size -= std::prev(fifo.end())->packet->length;
89 fifo.erase(std::prev(fifo.end()));
90 }
91
92 if (empty()) {
93 warn("EtherSwitch: Packet length (%d) exceeds the maximum storage "
94 "capacity of port fifo (%d)", ptr->length, _maxsize);
95 }
96
97 // Return true if the newly pushed packet gets inserted
98 // at the head of the queue, otherwise return false
99 // We need this information to deschedule the event that has been
100 // scheduled for the old head of queue packet and schedule a new one
101 if (!empty() && fifo.begin()->packet == ptr) {
102 return true;
103 }
104 return false;
105}
106
107void
109{
110 if (empty())
111 return;
112
113 assert(_size >= fifo.begin()->packet->length);
114 // Erase the packet at the head of the queue
115 _size -= fifo.begin()->packet->length;
116 fifo.erase(fifo.begin());
117}
118
119void
121{
122 fifo.clear();
123 _size = 0;
124}
125
127 EtherSwitch *etherSwitch,
128 uint64_t outputBufferSize, Tick delay,
129 Tick delay_var, double rate, unsigned id)
130 : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
131 delayVar(delay_var), interfaceId(id), parent(etherSwitch),
132 outputFifo(name + ".outputFifo", outputBufferSize),
133 txEvent([this]{ transmit(); }, name)
134{
135}
136
137bool
139{
140 networking::EthAddr destMacAddr(packet->data);
141 networking::EthAddr srcMacAddr(&packet->data[6]);
142
143 learnSenderAddr(srcMacAddr, this);
144 Interface *receiver = lookupDestPort(destMacAddr);
145
146 if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
147 for (auto it : parent->interfaces)
148 if (it != this)
149 it->enqueue(packet, interfaceId);
150 } else {
151 DPRINTF(Ethernet, "sending packet from MAC %x on port "
152 "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
153 this->name(), uint64_t(destMacAddr), receiver->name());
154
155 receiver->enqueue(packet, interfaceId);
156 }
157 // At the output port, we either have buffer space (no drop) or
158 // don't (drop packet); in both cases packet is received on
159 // the interface successfully and there is no notion of busy
160 // interface here (as we don't have inputFifo)
161 return true;
162}
163
164void
166{
167 // assuming per-interface transmission events,
168 // if the newly push packet gets inserted at the head of the queue
169 // (either there was nothing in the queue or the priority of the new
170 // packet was higher than the packets already in the fifo)
171 // then we need to schedule an event at
172 // "curTick" + "switchingDelay of the packet at the head of the fifo"
173 // to send this packet out the external link
174 // otherwise, there is already a txEvent scheduled
175 if (outputFifo.push(packet, senderId)) {
176 parent->reschedule(txEvent, curTick() + switchingDelay(), true);
177 }
178}
179
180void
182{
183 // there should be something in the output queue
184 assert(!outputFifo.empty());
185
186 if (!sendPacket(outputFifo.front())) {
187 DPRINTF(Ethernet, "output port busy...retry later\n");
188 if (!txEvent.scheduled())
189 parent->schedule(txEvent, curTick() + sim_clock::as_int::ns);
190 } else {
191 DPRINTF(Ethernet, "packet sent: len=%d\n", outputFifo.front()->length);
192 outputFifo.pop();
193 // schedule an event to send the pkt at
194 // the head of queue, if there is any
195 if (!outputFifo.empty()) {
196 parent->schedule(txEvent, curTick() + switchingDelay());
197 }
198 }
199}
200
201Tick
203{
204 Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength
205 * ticksPerByte) + 1.0);
206 if (delayVar != 0)
207 delay += random_mt.random<Tick>(0, delayVar);
208 delay += switchDelay;
209 return delay;
210}
211
214{
215 auto it = parent->forwardingTable.find(uint64_t(destMacAddr));
216
217 if (it == parent->forwardingTable.end()) {
218 DPRINTF(Ethernet, "no entry in forwaring table for MAC: "
219 "%x\n", uint64_t(destMacAddr));
220 return nullptr;
221 }
222
223 // check if this entry is valid based on TTL and lastUseTime
224 if ((curTick() - it->second.lastUseTime) > parent->ttl) {
225 // TTL for this mapping has been expired, so this item is not
226 // valide anymore, let's remove it from the map
227 parent->forwardingTable.erase(it);
228 return nullptr;
229 }
230
231 DPRINTF(Ethernet, "found entry for MAC address %x on port %s\n",
232 uint64_t(destMacAddr), it->second.interface->name());
233 return it->second.interface;
234}
235
236void
238 Interface *sender)
239{
240 // learn the port for the sending MAC address
241 auto it = parent->forwardingTable.find(uint64_t(srcMacAddr));
242
243 // if the port for sender's MAC address is not cached,
244 // cache it now, otherwise just update lastUseTime time
245 if (it == parent->forwardingTable.end()) {
246 DPRINTF(Ethernet, "adding forwarding table entry for MAC "
247 " address %x on port %s\n", uint64_t(srcMacAddr),
248 sender->name());
249 EtherSwitch::SwitchTableEntry forwardingTableEntry;
250 forwardingTableEntry.interface = sender;
251 forwardingTableEntry.lastUseTime = curTick();
252 parent->forwardingTable.insert(std::make_pair(uint64_t(srcMacAddr),
253 forwardingTableEntry));
254 } else {
255 it->second.lastUseTime = curTick();
256 }
257}
258
259void
261{
262 for (auto it : interfaces)
263 it->serializeSection(cp, it->name());
264
265}
266
267void
269{
270 for (auto it : interfaces)
271 it->unserializeSection(cp, it->name());
272
273}
274
275void
277{
278 bool event_scheduled = txEvent.scheduled();
279 SERIALIZE_SCALAR(event_scheduled);
280
281 if (event_scheduled) {
282 Tick event_time = txEvent.when();
283 SERIALIZE_SCALAR(event_time);
284 }
285 outputFifo.serializeSection(cp, "outputFifo");
286}
287
288void
290{
291 bool event_scheduled;
292 UNSERIALIZE_SCALAR(event_scheduled);
293
294 if (event_scheduled) {
295 Tick event_time;
296 UNSERIALIZE_SCALAR(event_time);
297 parent->schedule(txEvent, event_time);
298 }
299 outputFifo.unserializeSection(cp, "outputFifo");
300}
301
302void
304{
305 packet->serialize("packet", cp);
306 SERIALIZE_SCALAR(recvTick);
307 SERIALIZE_SCALAR(srcId);
308}
309
310void
312{
313 packet = std::make_shared<EthPacketData>(16384);
314 packet->unserialize("packet", cp);
315 UNSERIALIZE_SCALAR(recvTick);
316 UNSERIALIZE_SCALAR(srcId);
317}
318
319void
321{
322 SERIALIZE_SCALAR(_size);
323 int fifosize = fifo.size();
324
325 SERIALIZE_SCALAR(fifosize);
326
327 int i = 0;
328 for (const auto &entry : fifo)
329 entry.serializeSection(cp, csprintf("entry%d", i++));
330}
331
332void
334{
335 UNSERIALIZE_SCALAR(_size);
336 int fifosize;
337
338 UNSERIALIZE_SCALAR(fifosize);
339 fifo.clear();
340
341 for (int i = 0; i < fifosize; ++i) {
342 PortFifoEntry entry(nullptr, 0, 0);
343
344 entry.unserializeSection(cp, csprintf("entry%d", i));
345
346 fifo.insert(entry);
347
348 }
349}
350
351} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const std::string & name() const
Return port name (for DPRINTF).
Definition etherint.hh:62
bool push(EthPacketPtr ptr, unsigned senderId)
Push a packet into the fifo and sort the packets with same recv tick by port id.
std::set< PortFifoEntry, EntryOrder > fifo
void serialize(CheckpointOut &cp) const
Serialization stuff.
void unserialize(CheckpointIn &cp)
Unserialize an object.
Model for an Ethernet switch port.
PortFifo outputFifo
output fifo at each interface
void learnSenderAddr(networking::EthAddr srcMacAddr, Interface *sender)
Interface * lookupDestPort(networking::EthAddr destAddr)
void unserialize(CheckpointIn &cp)
Unserialize an object.
void enqueue(EthPacketPtr packet, unsigned senderId)
enqueue packet to the outputFifo
bool recvPacket(EthPacketPtr packet)
When a packet is received from a device, route it through an (several) output queue(s)
EventFunctionWrapper txEvent
Interface(const std::string &name, EtherSwitch *_etherSwitch, uint64_t outputBufferSize, Tick delay, Tick delay_var, double rate, unsigned id)
void serialize(CheckpointOut &cp) const
Serialize an object.
std::vector< Interface * > interfaces
EtherSwitchParams Params
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void serialize(CheckpointOut &cp) const override
Serialize an object.
EtherSwitch(const Params &p)
virtual std::string name() const
Definition named.hh:47
Ports are used to interface objects to each other.
Definition port.hh:62
const PortID id
A numeric identifier to distinguish ports in a vector, and set to InvalidPortID in case this port is ...
Definition port.hh:79
Abstract superclass for simulation objects.
Random random_mt
Definition random.cc:99
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition random.hh:90
bool broadcast() const
Definition inet.hh:116
bool multicast() const
Definition inet.hh:115
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition serialize.cc:81
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define warn(...)
Definition logging.hh:256
Bitfield< 51, 48 > ttl
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 0 > p
Tick ns
nanosecond
Definition core.cc:68
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
std::shared_ptr< EthPacketData > EthPacketPtr
Definition etherpkt.hh:90
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
void unserialize(CheckpointIn &cp)
Unserialize an object.
void serialize(CheckpointOut &cp) const
Serialize an object.

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0