1/* 2 * Copyright (c) 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabor Dozsa 38 */ 39 40/* @file 41 * Device module for a full duplex ethernet link for dist gem5 simulations. 42 */ 43 44#include "dev/net/dist_etherlink.hh" 45 46#include <arpa/inet.h> 47#include <sys/socket.h> 48#include <unistd.h> 49 50#include <cmath> 51#include <deque> 52#include <string> 53#include <vector> 54 55#include "base/random.hh" 56#include "base/trace.hh" 57#include "debug/DistEthernet.hh" 58#include "debug/DistEthernetPkt.hh" 59#include "debug/EthernetData.hh" 60#include "dev/net/dist_iface.hh" 61#include "dev/net/etherdump.hh" 62#include "dev/net/etherint.hh" 63#include "dev/net/etherlink.hh" 64#include "dev/net/etherpkt.hh" 65#include "dev/net/tcp_iface.hh" 66#include "params/EtherLink.hh" 67#include "sim/core.hh" 68#include "sim/serialize.hh" 69#include "sim/system.hh" 70 71using namespace std; 72 73DistEtherLink::DistEtherLink(const Params *p) 74 : SimObject(p), linkDelay(p->delay) 75{ 76 DPRINTF(DistEthernet,"DistEtherLink::DistEtherLink() " 77 "link delay:%llu ticksPerByte:%f\n", p->delay, p->speed); 78 79 txLink = new TxLink(name() + ".link0", this, p->speed, p->delay_var, 80 p->dump); 81 rxLink = new RxLink(name() + ".link1", this, p->delay, p->dump); 82 83 Tick sync_repeat; 84 if (p->sync_repeat != 0) { 85 if (p->sync_repeat != p->delay) 86 warn("DistEtherLink(): sync_repeat is %lu and linkdelay is %lu", 87 p->sync_repeat, p->delay); 88 sync_repeat = p->sync_repeat; 89 } else { 90 sync_repeat = p->delay; 91 } 92 93 // create the dist (TCP) interface to talk to the peer gem5 processes. 94 distIface = new TCPIface(p->server_name, p->server_port, 95 p->dist_rank, p->dist_size, 96 p->sync_start, sync_repeat, this, 97 p->dist_sync_on_pseudo_op, p->is_switch, 98 p->num_nodes); 99 100 localIface = new LocalIface(name() + ".int0", txLink, rxLink, distIface); 101} 102 103DistEtherLink::~DistEtherLink() 104{ 105 delete txLink; 106 delete rxLink; 107 delete localIface; 108 delete distIface; 109} 110 111Port & 112DistEtherLink::getPort(const std::string &if_name, PortID idx) 113{ 114 if (if_name == "int0") 115 return *localIface; 116 return SimObject::getPort(if_name, idx); 117} 118 119void 120DistEtherLink::serialize(CheckpointOut &cp) const 121{ 122 distIface->serializeSection(cp, "distIface"); 123 txLink->serializeSection(cp, "txLink"); 124 rxLink->serializeSection(cp, "rxLink"); 125} 126 127void 128DistEtherLink::unserialize(CheckpointIn &cp) 129{ 130 distIface->unserializeSection(cp, "distIface"); 131 txLink->unserializeSection(cp, "txLink"); 132 rxLink->unserializeSection(cp, "rxLink"); 133} 134 135void 136DistEtherLink::init() 137{ 138 DPRINTF(DistEthernet,"DistEtherLink::init() called\n"); 139 distIface->init(rxLink->doneEvent(), linkDelay); 140} 141 142void 143DistEtherLink::startup() 144{ 145 DPRINTF(DistEthernet,"DistEtherLink::startup() called\n"); 146 distIface->startup(); 147} 148 149void 150DistEtherLink::RxLink::setDistInt(DistIface *m) 151{ 152 assert(!distIface); 153 distIface = m; 154} 155 156void 157DistEtherLink::RxLink::rxDone() 158{ 159 assert(!busy()); 160 161 // retrieve the packet that triggered the receive done event 162 packet = distIface->packetIn(); 163 164 if (dump) 165 dump->dump(packet); 166 167 DPRINTF(DistEthernetPkt, "DistEtherLink::DistLink::rxDone() " 168 "packet received: len=%d\n", packet->length); 169 DDUMP(EthernetData, packet->data, packet->length); 170 171 localIface->sendPacket(packet); 172 173 packet = nullptr; 174} 175 176void 177DistEtherLink::TxLink::txDone() 178{ 179 if (dump) 180 dump->dump(packet); 181 182 packet = nullptr; 183 assert(!busy()); 184 185 localIface->sendDone(); 186} 187 188bool 189DistEtherLink::TxLink::transmit(EthPacketPtr pkt) 190{ 191 if (busy()) { 192 DPRINTF(DistEthernet, "packet not sent, link busy\n"); 193 return false; 194 } 195 196 packet = pkt; 197 Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0); 198 if (delayVar != 0) 199 delay += random_mt.random<Tick>(0, delayVar); 200 201 // send the packet to the peers 202 assert(distIface); 203 distIface->packetOut(pkt, delay); 204 205 // schedule the send done event 206 parent->schedule(doneEvent, curTick() + delay); 207 208 return true; 209} 210 211void 212DistEtherLink::Link::serialize(CheckpointOut &cp) const 213{ 214 bool packet_exists = (packet != nullptr); 215 SERIALIZE_SCALAR(packet_exists); 216 if (packet_exists) 217 packet->serialize("packet", cp); 218 219 bool event_scheduled = event->scheduled(); 220 SERIALIZE_SCALAR(event_scheduled); 221 if (event_scheduled) { 222 Tick event_time = event->when(); 223 SERIALIZE_SCALAR(event_time); 224 } 225} 226 227void 228DistEtherLink::Link::unserialize(CheckpointIn &cp) 229{ 230 bool packet_exists; 231 UNSERIALIZE_SCALAR(packet_exists); 232 if (packet_exists) { 233 packet = make_shared<EthPacketData>(); 234 packet->unserialize("packet", cp); 235 } 236 237 bool event_scheduled; 238 UNSERIALIZE_SCALAR(event_scheduled); 239 if (event_scheduled) { 240 Tick event_time; 241 UNSERIALIZE_SCALAR(event_time); 242 parent->schedule(*event, event_time); 243 } 244} 245 246DistEtherLink::LocalIface::LocalIface(const std::string &name, 247 TxLink *tx, 248 RxLink *rx, 249 DistIface *m) : 250 EtherInt(name), txLink(tx) 251{ 252 tx->setLocalInt(this); 253 rx->setLocalInt(this); 254 tx->setDistInt(m); 255 rx->setDistInt(m); 256} 257 258DistEtherLink * 259DistEtherLinkParams::create() 260{ 261 return new DistEtherLink(this); 262} 263 264 265