etherswitch.cc (11317:766c3eb44fd8) etherswitch.cc (11533:2aa4d7bd47ec)
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;

--- 33 unchanged lines hidden (view full) ---

42
43EtherSwitch::EtherSwitch(const Params *p)
44 : EtherObject(p), ttl(p->time_to_live)
45{
46 for (int i = 0; i < p->port_interface_connection_count; ++i) {
47 std::string interfaceName = csprintf("%s.interface%d", name(), i);
48 Interface *interface = new Interface(interfaceName, this,
49 p->output_buffer_size, p->delay,
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;

--- 33 unchanged lines hidden (view full) ---

42
43EtherSwitch::EtherSwitch(const Params *p)
44 : EtherObject(p), ttl(p->time_to_live)
45{
46 for (int i = 0; i < p->port_interface_connection_count; ++i) {
47 std::string interfaceName = csprintf("%s.interface%d", name(), i);
48 Interface *interface = new Interface(interfaceName, this,
49 p->output_buffer_size, p->delay,
50 p->delay_var, p->fabric_speed);
50 p->delay_var, p->fabric_speed, i);
51 interfaces.push_back(interface);
52 }
53}
54
55EtherSwitch::~EtherSwitch()
56{
57 for (auto it : interfaces)
58 delete it;

--- 8 unchanged lines hidden (view full) ---

67 return nullptr;
68
69 Interface *interface = interfaces.at(idx);
70 panic_if(interface->getPeer(), "interface already connected\n");
71
72 return interface;
73}
74
51 interfaces.push_back(interface);
52 }
53}
54
55EtherSwitch::~EtherSwitch()
56{
57 for (auto it : interfaces)
58 delete it;

--- 8 unchanged lines hidden (view full) ---

67 return nullptr;
68
69 Interface *interface = interfaces.at(idx);
70 panic_if(interface->getPeer(), "interface already connected\n");
71
72 return interface;
73}
74
75bool
76EtherSwitch::Interface::PortFifo::push(EthPacketPtr ptr, unsigned senderId)
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
108EtherSwitch::Interface::PortFifo::pop()
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
120EtherSwitch::Interface::PortFifo::clear()
121{
122 fifo.clear();
123 _size = 0;
124}
125
75EtherSwitch::Interface::Interface(const std::string &name,
76 EtherSwitch *etherSwitch,
77 uint64_t outputBufferSize, Tick delay,
126EtherSwitch::Interface::Interface(const std::string &name,
127 EtherSwitch *etherSwitch,
128 uint64_t outputBufferSize, Tick delay,
78 Tick delay_var, double rate)
129 Tick delay_var, double rate, unsigned id)
79 : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
130 : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
80 delayVar(delay_var), parent(etherSwitch),
81 outputFifo(outputBufferSize), txEvent(this)
131 delayVar(delay_var), interfaceId(id), parent(etherSwitch),
132 outputFifo(name + ".outputFifo", outputBufferSize), txEvent(this)
82{
83}
84
85bool
86EtherSwitch::Interface::recvPacket(EthPacketPtr packet)
87{
88 Net::EthAddr destMacAddr(packet->data);
89 Net::EthAddr srcMacAddr(&packet->data[6]);
90
91 learnSenderAddr(srcMacAddr, this);
92 Interface *receiver = lookupDestPort(destMacAddr);
93
94 if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
95 for (auto it : parent->interfaces)
96 if (it != this)
133{
134}
135
136bool
137EtherSwitch::Interface::recvPacket(EthPacketPtr packet)
138{
139 Net::EthAddr destMacAddr(packet->data);
140 Net::EthAddr srcMacAddr(&packet->data[6]);
141
142 learnSenderAddr(srcMacAddr, this);
143 Interface *receiver = lookupDestPort(destMacAddr);
144
145 if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
146 for (auto it : parent->interfaces)
147 if (it != this)
97 it->enqueue(packet);
148 it->enqueue(packet, interfaceId);
98 } else {
99 DPRINTF(Ethernet, "sending packet from MAC %x on port "
100 "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
101 this->name(), uint64_t(destMacAddr), receiver->name());
102
149 } else {
150 DPRINTF(Ethernet, "sending packet from MAC %x on port "
151 "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
152 this->name(), uint64_t(destMacAddr), receiver->name());
153
103 receiver->enqueue(packet);
154 receiver->enqueue(packet, interfaceId);
104 }
105 // At the output port, we either have buffer space (no drop) or
106 // don't (drop packet); in both cases packet is received on
107 // the interface successfully and there is no notion of busy
108 // interface here (as we don't have inputFifo)
109 return true;
110}
111
112void
155 }
156 // At the output port, we either have buffer space (no drop) or
157 // don't (drop packet); in both cases packet is received on
158 // the interface successfully and there is no notion of busy
159 // interface here (as we don't have inputFifo)
160 return true;
161}
162
163void
113EtherSwitch::Interface::enqueue(EthPacketPtr packet)
164EtherSwitch::Interface::enqueue(EthPacketPtr packet, unsigned senderId)
114{
165{
115 if (!outputFifo.push(packet)) {
116 // output buffer full, drop packet
117 DPRINTF(Ethernet, "output buffer full, drop packet\n");
118 return;
119 }
120
121 // assuming per-interface transmission events,
166 // assuming per-interface transmission events,
122 // if there was nothing in the Fifo before push the
123 // current packet, then we need to schedule an event at
124 // curTick + switchingDelay to send this packet out the external link
167 // if the newly push packet gets inserted at the head of the queue
168 // (either there was nothing in the queue or the priority of the new
169 // packet was higher than the packets already in the fifo)
170 // then we need to schedule an event at
171 // "curTick" + "switchingDelay of the packet at the head of the fifo"
172 // to send this packet out the external link
125 // otherwise, there is already a txEvent scheduled
173 // otherwise, there is already a txEvent scheduled
126 if (!txEvent.scheduled()) {
127 parent->schedule(txEvent, curTick() + switchingDelay());
174 if (outputFifo.push(packet, senderId)) {
175 parent->reschedule(txEvent, curTick() + switchingDelay());
128 }
129}
130
131void
132EtherSwitch::Interface::transmit()
133{
134 // there should be something in the output queue
135 assert(!outputFifo.empty());

--- 70 unchanged lines hidden (view full) ---

206 it->second.lastUseTime = curTick();
207 }
208}
209
210void
211EtherSwitch::serialize(CheckpointOut &cp) const
212{
213 for (auto it : interfaces)
176 }
177}
178
179void
180EtherSwitch::Interface::transmit()
181{
182 // there should be something in the output queue
183 assert(!outputFifo.empty());

--- 70 unchanged lines hidden (view full) ---

254 it->second.lastUseTime = curTick();
255 }
256}
257
258void
259EtherSwitch::serialize(CheckpointOut &cp) const
260{
261 for (auto it : interfaces)
214 it->serialize(it->name(), cp);
262 it->serializeSection(cp, it->name());
263
215}
216
217void
218EtherSwitch::unserialize(CheckpointIn &cp)
219{
220 for (auto it : interfaces)
264}
265
266void
267EtherSwitch::unserialize(CheckpointIn &cp)
268{
269 for (auto it : interfaces)
221 it->unserialize(it->name(), cp);
270 it->unserializeSection(cp, it->name());
271
222}
223
224void
272}
273
274void
225EtherSwitch::Interface::serialize(const std::string &base, CheckpointOut &cp)
226const
275EtherSwitch::Interface::serialize(CheckpointOut &cp) const
227{
228 bool event_scheduled = txEvent.scheduled();
276{
277 bool event_scheduled = txEvent.scheduled();
229 paramOut(cp, base + ".event_scheduled", event_scheduled);
278 SERIALIZE_SCALAR(event_scheduled);
279
230 if (event_scheduled) {
231 Tick event_time = txEvent.when();
280 if (event_scheduled) {
281 Tick event_time = txEvent.when();
232 paramOut(cp, base + ".event_time", event_time);
282 SERIALIZE_SCALAR(event_time);
233 }
283 }
234
235 outputFifo.serialize(base + "outputFifo", cp);
284 outputFifo.serializeSection(cp, "outputFifo");
236}
237
238void
285}
286
287void
239EtherSwitch::Interface::unserialize(const std::string &base, CheckpointIn &cp)
288EtherSwitch::Interface::unserialize(CheckpointIn &cp)
240{
241 bool event_scheduled;
289{
290 bool event_scheduled;
242 paramIn(cp, base + ".event_scheduled", event_scheduled);
291 UNSERIALIZE_SCALAR(event_scheduled);
292
243 if (event_scheduled) {
244 Tick event_time;
293 if (event_scheduled) {
294 Tick event_time;
245 paramIn(cp, base + ".event_time", event_time);
295 UNSERIALIZE_SCALAR(event_time);
246 parent->schedule(txEvent, event_time);
247 }
296 parent->schedule(txEvent, event_time);
297 }
298 outputFifo.unserializeSection(cp, "outputFifo");
299}
248
300
249 outputFifo.unserialize(base + "outputFifo", cp);
301void
302EtherSwitch::Interface::PortFifoEntry::serialize(CheckpointOut &cp) const
303{
304 packet->serialize("packet", cp);
305 SERIALIZE_SCALAR(recvTick);
306 SERIALIZE_SCALAR(srcId);
250}
251
307}
308
309void
310EtherSwitch::Interface::PortFifoEntry::unserialize(CheckpointIn &cp)
311{
312 packet = make_shared<EthPacketData>(16384);
313 packet->unserialize("packet", cp);
314 UNSERIALIZE_SCALAR(recvTick);
315 UNSERIALIZE_SCALAR(srcId);
316}
317
318void
319EtherSwitch::Interface::PortFifo::serialize(CheckpointOut &cp) const
320{
321 SERIALIZE_SCALAR(_size);
322 int fifosize = fifo.size();
323
324 SERIALIZE_SCALAR(fifosize);
325
326 int i = 0;
327 for (const auto &entry : fifo)
328 entry.serializeSection(cp, csprintf("entry%d", i++));
329}
330
331void
332EtherSwitch::Interface::PortFifo::unserialize(CheckpointIn &cp)
333{
334 UNSERIALIZE_SCALAR(_size);
335 int fifosize;
336
337 UNSERIALIZE_SCALAR(fifosize);
338 fifo.clear();
339
340 for (int i = 0; i < fifosize; ++i) {
341 PortFifoEntry entry(nullptr, 0, 0);
342
343 entry.unserializeSection(cp, csprintf("entry%d", i));
344
345 fifo.insert(entry);
346
347 }
348}
349
252EtherSwitch *
253EtherSwitchParams::create()
254{
255 return new EtherSwitch(this);
256}
350EtherSwitch *
351EtherSwitchParams::create()
352{
353 return new EtherSwitch(this);
354}