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} |