gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Anthony Gutierrez
29  * Mohammad Alian
30  */
31 
32 /* @file
33  * Device model for an ethernet switch
34  */
35 
36 #include "dev/net/etherswitch.hh"
37 
38 #include "base/random.hh"
39 #include "base/trace.hh"
40 #include "debug/EthernetAll.hh"
41 #include "sim/core.hh"
42 
43 using namespace std;
44 
46  : SimObject(p), ttl(p->time_to_live)
47 {
48  for (int i = 0; i < p->port_interface_connection_count; ++i) {
49  std::string interfaceName = csprintf("%s.interface%d", name(), i);
50  Interface *interface = new Interface(interfaceName, this,
51  p->output_buffer_size, p->delay,
52  p->delay_var, p->fabric_speed, i);
53  interfaces.push_back(interface);
54  }
55 }
56 
58 {
59  for (auto it : interfaces)
60  delete it;
61 
62  interfaces.clear();
63 }
64 
65 Port &
66 EtherSwitch::getPort(const std::string &if_name, PortID idx)
67 {
68  if (if_name == "interface") {
69  panic_if(idx < 0 || idx >= interfaces.size(), "index out of bounds");
70  return *interfaces.at(idx);
71  }
72 
73  return SimObject::getPort(if_name, idx);
74 }
75 
76 bool
78 {
79  assert(ptr->length);
80 
81  _size += ptr->length;
82  fifo.emplace_hint(fifo.end(), ptr, curTick(), senderId);
83 
84  // Drop the extra pushed packets from end of the fifo
85  while (avail() < 0) {
86  DPRINTF(Ethernet, "Fifo is full. Drop packet: len=%d\n",
87  std::prev(fifo.end())->packet->length);
88 
89  _size -= std::prev(fifo.end())->packet->length;
90  fifo.erase(std::prev(fifo.end()));
91  }
92 
93  if (empty()) {
94  warn("EtherSwitch: Packet length (%d) exceeds the maximum storage "
95  "capacity of port fifo (%d)", ptr->length, _maxsize);
96  }
97 
98  // Return true if the newly pushed packet gets inserted
99  // at the head of the queue, otherwise return false
100  // We need this information to deschedule the event that has been
101  // scheduled for the old head of queue packet and schedule a new one
102  if (!empty() && fifo.begin()->packet == ptr) {
103  return true;
104  }
105  return false;
106 }
107 
108 void
110 {
111  if (empty())
112  return;
113 
114  assert(_size >= fifo.begin()->packet->length);
115  // Erase the packet at the head of the queue
116  _size -= fifo.begin()->packet->length;
117  fifo.erase(fifo.begin());
118 }
119 
120 void
122 {
123  fifo.clear();
124  _size = 0;
125 }
126 
128  EtherSwitch *etherSwitch,
129  uint64_t outputBufferSize, Tick delay,
130  Tick delay_var, double rate, unsigned id)
131  : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
132  delayVar(delay_var), interfaceId(id), parent(etherSwitch),
133  outputFifo(name + ".outputFifo", outputBufferSize),
134  txEvent([this]{ transmit(); }, name)
135 {
136 }
137 
138 bool
140 {
141  Net::EthAddr destMacAddr(packet->data);
142  Net::EthAddr srcMacAddr(&packet->data[6]);
143 
144  learnSenderAddr(srcMacAddr, this);
145  Interface *receiver = lookupDestPort(destMacAddr);
146 
147  if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
148  for (auto it : parent->interfaces)
149  if (it != this)
150  it->enqueue(packet, interfaceId);
151  } else {
152  DPRINTF(Ethernet, "sending packet from MAC %x on port "
153  "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
154  this->name(), uint64_t(destMacAddr), receiver->name());
155 
156  receiver->enqueue(packet, interfaceId);
157  }
158  // At the output port, we either have buffer space (no drop) or
159  // don't (drop packet); in both cases packet is received on
160  // the interface successfully and there is no notion of busy
161  // interface here (as we don't have inputFifo)
162  return true;
163 }
164 
165 void
167 {
168  // assuming per-interface transmission events,
169  // if the newly push packet gets inserted at the head of the queue
170  // (either there was nothing in the queue or the priority of the new
171  // packet was higher than the packets already in the fifo)
172  // then we need to schedule an event at
173  // "curTick" + "switchingDelay of the packet at the head of the fifo"
174  // to send this packet out the external link
175  // otherwise, there is already a txEvent scheduled
176  if (outputFifo.push(packet, senderId)) {
178  }
179 }
180 
181 void
183 {
184  // there should be something in the output queue
185  assert(!outputFifo.empty());
186 
187  if (!sendPacket(outputFifo.front())) {
188  DPRINTF(Ethernet, "output port busy...retry later\n");
189  if (!txEvent.scheduled())
191  } else {
192  DPRINTF(Ethernet, "packet sent: len=%d\n", outputFifo.front()->length);
193  outputFifo.pop();
194  // schedule an event to send the pkt at
195  // the head of queue, if there is any
196  if (!outputFifo.empty()) {
198  }
199  }
200 }
201 
202 Tick
204 {
205  Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength
206  * ticksPerByte) + 1.0);
207  if (delayVar != 0)
208  delay += random_mt.random<Tick>(0, delayVar);
209  delay += switchDelay;
210  return delay;
211 }
212 
215 {
216  auto it = parent->forwardingTable.find(uint64_t(destMacAddr));
217 
218  if (it == parent->forwardingTable.end()) {
219  DPRINTF(Ethernet, "no entry in forwaring table for MAC: "
220  "%x\n", uint64_t(destMacAddr));
221  return nullptr;
222  }
223 
224  // check if this entry is valid based on TTL and lastUseTime
225  if ((curTick() - it->second.lastUseTime) > parent->ttl) {
226  // TTL for this mapping has been expired, so this item is not
227  // valide anymore, let's remove it from the map
228  parent->forwardingTable.erase(it);
229  return nullptr;
230  }
231 
232  DPRINTF(Ethernet, "found entry for MAC address %x on port %s\n",
233  uint64_t(destMacAddr), it->second.interface->name());
234  return it->second.interface;
235 }
236 
237 void
239  Interface *sender)
240 {
241  // learn the port for the sending MAC address
242  auto it = parent->forwardingTable.find(uint64_t(srcMacAddr));
243 
244  // if the port for sender's MAC address is not cached,
245  // cache it now, otherwise just update lastUseTime time
246  if (it == parent->forwardingTable.end()) {
247  DPRINTF(Ethernet, "adding forwarding table entry for MAC "
248  " address %x on port %s\n", uint64_t(srcMacAddr),
249  sender->name());
250  EtherSwitch::SwitchTableEntry forwardingTableEntry;
251  forwardingTableEntry.interface = sender;
252  forwardingTableEntry.lastUseTime = curTick();
253  parent->forwardingTable.insert(std::make_pair(uint64_t(srcMacAddr),
254  forwardingTableEntry));
255  } else {
256  it->second.lastUseTime = curTick();
257  }
258 }
259 
260 void
262 {
263  for (auto it : interfaces)
264  it->serializeSection(cp, it->name());
265 
266 }
267 
268 void
270 {
271  for (auto it : interfaces)
272  it->unserializeSection(cp, it->name());
273 
274 }
275 
276 void
278 {
279  bool event_scheduled = txEvent.scheduled();
280  SERIALIZE_SCALAR(event_scheduled);
281 
282  if (event_scheduled) {
283  Tick event_time = txEvent.when();
284  SERIALIZE_SCALAR(event_time);
285  }
286  outputFifo.serializeSection(cp, "outputFifo");
287 }
288 
289 void
291 {
292  bool event_scheduled;
293  UNSERIALIZE_SCALAR(event_scheduled);
294 
295  if (event_scheduled) {
296  Tick event_time;
297  UNSERIALIZE_SCALAR(event_time);
298  parent->schedule(txEvent, event_time);
299  }
300  outputFifo.unserializeSection(cp, "outputFifo");
301 }
302 
303 void
305 {
306  packet->serialize("packet", cp);
307  SERIALIZE_SCALAR(recvTick);
308  SERIALIZE_SCALAR(srcId);
309 }
310 
311 void
313 {
314  packet = make_shared<EthPacketData>(16384);
315  packet->unserialize("packet", cp);
316  UNSERIALIZE_SCALAR(recvTick);
317  UNSERIALIZE_SCALAR(srcId);
318 }
319 
320 void
322 {
323  SERIALIZE_SCALAR(_size);
324  int fifosize = fifo.size();
325 
326  SERIALIZE_SCALAR(fifosize);
327 
328  int i = 0;
329  for (const auto &entry : fifo)
330  entry.serializeSection(cp, csprintf("entry%d", i++));
331 }
332 
333 void
335 {
336  UNSERIALIZE_SCALAR(_size);
337  int fifosize;
338 
339  UNSERIALIZE_SCALAR(fifosize);
340  fifo.clear();
341 
342  for (int i = 0; i < fifosize; ++i) {
343  PortFifoEntry entry(nullptr, 0, 0);
344 
345  entry.unserializeSection(cp, csprintf("entry%d", i));
346 
347  fifo.insert(entry);
348 
349  }
350 }
351 
352 EtherSwitch *
353 EtherSwitchParams::create()
354 {
355  return new EtherSwitch(this);
356 }
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: etherswitch.cc:261
#define DPRINTF(x,...)
Definition: trace.hh:229
const double ttl
Definition: etherswitch.hh:186
const std::string & name() const
Return port name (for DPRINTF).
Definition: etherint.hh:61
Ports are used to interface objects to each other.
Definition: port.hh:60
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: etherswitch.cc:66
bool recvPacket(EthPacketPtr packet)
When a packet is received from a device, route it through an (several) output queue(s) ...
Definition: etherswitch.cc:139
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition: serialize.cc:176
Bitfield< 7 > i
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:401
Interface(const std::string &name, EtherSwitch *_etherSwitch, uint64_t outputBufferSize, Tick delay, Tick delay_var, double rate, unsigned id)
Definition: etherswitch.cc:127
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition: serialize.cc:183
Model for an Ethernet switch port.
Definition: etherswitch.hh:71
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
Definition: cprintf.cc:42
std::vector< Interface * > interfaces
Definition: etherswitch.hh:188
std::map< uint64_t, SwitchTableEntry > forwardingTable
Definition: etherswitch.hh:190
EventFunctionWrapper txEvent
Definition: etherswitch.hh:176
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:83
PortFifo outputFifo
output fifo at each interface
Definition: etherswitch.hh:174
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
void learnSenderAddr(Net::EthAddr srcMacAddr, Interface *sender)
Definition: etherswitch.cc:238
Tick curTick()
The current simulated tick.
Definition: core.hh:47
Interface * lookupDestPort(Net::EthAddr destAddr)
Definition: etherswitch.cc:214
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:385
EtherSwitchParams Params
Definition: etherswitch.hh:54
uint64_t Tick
Tick count type.
Definition: types.hh:63
void unserialize(CheckpointIn &cp)
Unserialize an object.
Definition: etherswitch.cc:334
EtherSwitch * parent
Definition: etherswitch.hh:101
void serialize(CheckpointOut &cp) const
Serialize an object.
Definition: etherswitch.cc:277
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:90
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: etherswitch.cc:269
virtual const std::string name() const
Definition: sim_object.hh:120
bool push(EthPacketPtr ptr, unsigned senderId)
Push a packet into the fifo and sort the packets with same recv tick by port id.
Definition: etherswitch.cc:77
const unsigned interfaceId
Definition: etherswitch.hh:99
EtherSwitch(const Params *p)
Definition: etherswitch.cc:45
const double ticksPerByte
Definition: etherswitch.hh:96
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
bool multicast() const
Definition: inet.hh:97
bool sendPacket(EthPacketPtr packet)
Definition: etherint.hh:72
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:756
std::ostream CheckpointOut
Definition: serialize.hh:68
void unserialize(CheckpointIn &cp)
Unserialize an object.
Definition: etherswitch.cc:312
void enqueue(EthPacketPtr packet, unsigned senderId)
enqueue packet to the outputFifo
Definition: etherswitch.cc:166
Random random_mt
Definition: random.cc:100
const Tick retryTime
Definition: core.hh:49
void schedule(Event &event, Tick when)
Definition: eventq.hh:744
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
bool broadcast() const
Definition: inet.hh:98
void serialize(CheckpointOut &cp) const
Serialization stuff.
Definition: etherswitch.cc:321
#define warn(...)
Definition: logging.hh:212
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
void serialize(CheckpointOut &cp) const
Serialize an object.
Definition: etherswitch.cc:304
Bitfield< 51, 48 > ttl
Abstract superclass for simulation objects.
Definition: sim_object.hh:96
void unserialize(CheckpointIn &cp)
Unserialize an object.
Definition: etherswitch.cc:290

Generated on Fri Feb 28 2020 16:27:01 for gem5 by doxygen 1.8.13