INET Framework for OMNeT++/OMNEST
inet::EtherBus Class Reference

Implements the shared coaxial cable in classic Ethernet. More...

#include <EtherBus.h>

Inheritance diagram for inet::EtherBus:

Classes

struct  BusTap
 Implements the physical locations on the bus where each network entity is connected to on the bus. More...
 

Public Member Functions

 EtherBus ()
 
virtual ~EtherBus ()
 

Protected Member Functions

virtual void initialize () override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void finish () override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
virtual void checkConnections (bool errorWhenAsymmetric)
 

Protected Attributes

double propagationSpeed = NaN
 
BusTaptap = nullptr
 
int numTaps = -1
 
int inputGateBaseId = -1
 
int outputGateBaseId = -1
 
bool dataratesDiffer = false
 
long numMessages = 0
 

Detailed Description

Implements the shared coaxial cable in classic Ethernet.

See the NED file for more description.

Constructor & Destructor Documentation

inet::EtherBus::EtherBus ( )
32 {
33 }
inet::EtherBus::~EtherBus ( )
virtual
36 {
37  delete[] tap;
38 }
BusTap * tap
Definition: EtherBus.h:51

Member Function Documentation

void inet::EtherBus::checkConnections ( bool  errorWhenAsymmetric)
protectedvirtual

Referenced by handleMessage(), initialize(), and receiveSignal().

104 {
105  int numActiveTaps = 0;
106 
107  double datarate = 0.0;
108 
109  for (int i = 0; i < numTaps; i++) {
110  cGate *igate = gate(inputGateBaseId + i);
111  cGate *ogate = gate(outputGateBaseId + i);
112  if (!igate->isConnected() && !ogate->isConnected())
113  continue;
114 
115  if (!igate->isConnected() || !ogate->isConnected()) {
116  // half connected gate
117  if (errorWhenAsymmetric)
118  throw cRuntimeError("The input or output gate not connected at tap %i", i);
119  dataratesDiffer = true;
120  EV << "The input or output gate not connected at tap " << i << ".\n";
121  continue;
122  }
123 
124  numActiveTaps++;
125  double drate = igate->getIncomingTransmissionChannel()->getNominalDatarate();
126 
127  if (numActiveTaps == 1)
128  datarate = drate;
129  else if (datarate != drate) {
130  if (errorWhenAsymmetric)
131  throw cRuntimeError("The input datarate at tap %i differs from datarates of previous taps", i);
132  dataratesDiffer = true;
133  EV << "The input datarate at tap " << i << " differs from datarates of previous taps.\n";
134  }
135 
136  cChannel *outTrChannel = ogate->getTransmissionChannel();
137  drate = outTrChannel->getNominalDatarate();
138 
139  if (datarate != drate) {
140  if (errorWhenAsymmetric)
141  throw cRuntimeError("The output datarate at tap %i differs from datarates of previous taps", i);
142  dataratesDiffer = true;
143  EV << "The output datarate at tap " << i << " differs from datarates of previous taps.\n";
144  }
145 
146  if (!outTrChannel->isSubscribed(POST_MODEL_CHANGE, this))
147  outTrChannel->subscribe(POST_MODEL_CHANGE, this);
148  }
149 }
int outputGateBaseId
Definition: EtherBus.h:54
int numTaps
Definition: EtherBus.h:52
int inputGateBaseId
Definition: EtherBus.h:53
bool dataratesDiffer
Definition: EtherBus.h:57
void inet::EtherBus::finish ( )
overrideprotectedvirtual
262 {
263  simtime_t t = simTime();
264  recordScalar("simulated time", t);
265  recordScalar("messages handled", numMessages);
266 
267  if (t > 0)
268  recordScalar("messages/sec", numMessages / t);
269 }
long numMessages
Definition: EtherBus.h:60
void inet::EtherBus::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
192 {
193  if (dataratesDiffer)
194  checkConnections(true);
195 
196  if (!msg->isSelfMessage()) {
197  // Handle frame sent down from the network entity
198  int tapPoint = msg->getArrivalGate()->getIndex();
199  EV << "Frame " << msg << " arrived on tap " << tapPoint << endl;
200 
201  // create upstream and downstream events
202  if (tapPoint > 0) {
203  // start UPSTREAM travel
204  // if goes downstream too, we need to make a copy
205  cMessage *msg2 = (tapPoint < numTaps - 1) ? msg->dup() : msg;
206  msg2->setKind(UPSTREAM);
207  msg2->setContextPointer(&tap[tapPoint - 1]);
208  scheduleAt(simTime() + tap[tapPoint].propagationDelay[UPSTREAM], msg2);
209  }
210 
211  if (tapPoint < numTaps - 1) {
212  // start DOWNSTREAM travel
213  msg->setKind(DOWNSTREAM);
214  msg->setContextPointer(&tap[tapPoint + 1]);
215  scheduleAt(simTime() + tap[tapPoint].propagationDelay[DOWNSTREAM], msg);
216  }
217 
218  if (numTaps == 1) {
219  // if there's only one tap, there's nothing to do
220  delete msg;
221  }
222  }
223  else {
224  // handle upstream and downstream events
225  int direction = msg->getKind();
226  BusTap *thistap = (BusTap *)msg->getContextPointer();
227  int tapPoint = thistap->id;
228 
229  EV << "Event " << msg << " on tap " << tapPoint << ", sending out frame\n";
230 
231  // send out on gate
232  bool isLast = (direction == UPSTREAM) ? (tapPoint == 0) : (tapPoint == numTaps - 1);
233  cGate *ogate = gate(outputGateBaseId + tapPoint);
234  if (ogate->isConnected()) {
235  // send out on gate
236  cMessage *msg2 = isLast ? msg : msg->dup();
237 
238  // stop current transmission
239  ogate->getTransmissionChannel()->forceTransmissionFinishTime(SIMTIME_ZERO);
240  send(msg2, ogate);
241  }
242  else {
243  // skip gate
244  if (isLast)
245  delete msg;
246  }
247 
248  // if not end of the bus, schedule for next tap
249  if (isLast) {
250  EV << "End of bus reached\n";
251  }
252  else {
253  EV << "Scheduling for next tap\n";
254  int nextTap = (direction == UPSTREAM) ? (tapPoint - 1) : (tapPoint + 1);
255  msg->setContextPointer(&tap[nextTap]);
256  scheduleAt(simTime() + tap[tapPoint].propagationDelay[direction], msg);
257  }
258  }
259 }
#define UPSTREAM
Definition: EtherBus.h:28
virtual void checkConnections(bool errorWhenAsymmetric)
Definition: EtherBus.cc:103
int outputGateBaseId
Definition: EtherBus.h:54
int numTaps
Definition: EtherBus.h:52
BusTap * tap
Definition: EtherBus.h:51
#define DOWNSTREAM
Definition: EtherBus.h:29
bool dataratesDiffer
Definition: EtherBus.h:57
void inet::EtherBus::initialize ( )
overrideprotectedvirtual
41 {
42  numMessages = 0;
43  WATCH(numMessages);
44 
45  propagationSpeed = par("propagationSpeed").doubleValue();
46 
47  // initialize the positions where the hosts connects to the bus
48  numTaps = gateSize("ethg");
49  inputGateBaseId = gateBaseId("ethg$i");
50  outputGateBaseId = gateBaseId("ethg$o");
51 
52  // read positions and check if positions are defined in order (we're lazy to sort...)
53  std::vector<double> pos = cStringTokenizer(par("positions").stringValue()).asDoubleVector();
54  int numPos = pos.size();
55 
56  if (numPos > numTaps)
57  EV << "Note: `positions' parameter contains more values (" << numPos << ") than "
58  "the number of taps (" << numTaps << "), ignoring excess values.\n";
59  else if (numPos < numTaps && numPos >= 2)
60  EV << "Note: `positions' parameter contains less values (" << numPos << ") than "
61  "the number of taps (" << numTaps << "), repeating distance between last 2 positions.\n";
62  else if (numPos < numTaps && numPos < 2)
63  EV << "Note: `positions' parameter contains too few values, using 5m distances.\n";
64 
65  tap = new BusTap[numTaps];
66 
67  int i;
68  double distance = numPos >= 2 ? pos[numPos - 1] - pos[numPos - 2] : 5;
69 
70  for (i = 0; i < numTaps; i++) {
71  tap[i].id = i;
72  tap[i].position = i < numPos ? pos[i] : i == 0 ? 5 : tap[i - 1].position + distance;
73  }
74 
75  for (i = 0; i < numTaps - 1; i++) {
76  if (tap[i].position > tap[i + 1].position)
77  throw cRuntimeError("Tap positions must be ordered in ascending fashion, modify 'positions' parameter and rerun\n");
78  }
79 
80  // Prints out data of parameters for parameter checking...
81  EV << "Parameters of (" << getClassName() << ") " << getFullPath() << "\n";
82  EV << "propagationSpeed: " << propagationSpeed << "\n";
83 
84  // Calculate propagation of delays between tap points on the bus
85  for (i = 0; i < numTaps; i++) {
86  // Propagation delay between adjacent tap points
87  tap[i].propagationDelay[UPSTREAM] = (i > 0) ? tap[i - 1].propagationDelay[DOWNSTREAM] : 0;
88  tap[i].propagationDelay[DOWNSTREAM] = (i + 1 < numTaps) ? (tap[i + 1].position - tap[i].position) / propagationSpeed : 0;
89  EV << "tap[" << i << "] pos: " << tap[i].position
90  << " upstream delay: " << tap[i].propagationDelay[UPSTREAM]
91  << " downstream delay: " << tap[i].propagationDelay[DOWNSTREAM] << endl;
92  }
93  EV << "\n";
94 
95  // ensure we receive frames when their first bits arrive
96  for (int i = 0; i < numTaps; i++)
97  gate(inputGateBaseId + i)->setDeliverOnReceptionStart(true);
98  subscribe(POST_MODEL_CHANGE, this); // we'll need to do the same for dynamically added gates as well
99 
100  checkConnections(true);
101 }
#define UPSTREAM
Definition: EtherBus.h:28
virtual void checkConnections(bool errorWhenAsymmetric)
Definition: EtherBus.cc:103
double position
Definition: EtherBus.h:45
int outputGateBaseId
Definition: EtherBus.h:54
int numTaps
Definition: EtherBus.h:52
BusTap * tap
Definition: EtherBus.h:51
double propagationSpeed
Definition: EtherBus.h:50
#define DOWNSTREAM
Definition: EtherBus.h:29
int id
Definition: EtherBus.h:44
int inputGateBaseId
Definition: EtherBus.h:53
#define stringValue()
Definition: NedFunctions.cc:24
long numMessages
Definition: EtherBus.h:60
simtime_t propagationDelay[2]
Definition: EtherBus.h:46
void inet::EtherBus::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
152 {
153  Enter_Method_Silent();
154 
155  ASSERT(signalID == POST_MODEL_CHANGE);
156 
157  // throw error if new gates have been added
158  cPostGateVectorResizeNotification *notif = dynamic_cast<cPostGateVectorResizeNotification *>(obj);
159  if (notif) {
160  if (strcmp(notif->gateName, "ethg") == 0)
161  throw cRuntimeError("EtherBus does not allow adding/removing links dynamically");
162  }
163 
164  cPostPathCreateNotification *connNotif = dynamic_cast<cPostPathCreateNotification *>(obj);
165  if (connNotif) {
166  if ((this == connNotif->pathStartGate->getOwnerModule()) || (this == connNotif->pathEndGate->getOwnerModule()))
167  checkConnections(false);
168  return;
169  }
170 
171  cPostPathCutNotification *cutNotif = dynamic_cast<cPostPathCutNotification *>(obj);
172  if (cutNotif) {
173  if ((this == cutNotif->pathStartGate->getOwnerModule()) || (this == cutNotif->pathEndGate->getOwnerModule()))
174  checkConnections(false);
175  return;
176  }
177 
178  // note: we are subscribed to the channel object too
179  cPostParameterChangeNotification *parNotif = dynamic_cast<cPostParameterChangeNotification *>(obj);
180  if (parNotif) {
181  cChannel *channel = dynamic_cast<cDatarateChannel *>(parNotif->par->getOwner());
182  if (channel) {
183  cGate *gate = channel->getSourceGate();
184  if (gate->pathContains(this))
185  checkConnections(false);
186  }
187  return;
188  }
189 }
virtual void checkConnections(bool errorWhenAsymmetric)
Definition: EtherBus.cc:103

Member Data Documentation

bool inet::EtherBus::dataratesDiffer = false
protected

Referenced by checkConnections(), and handleMessage().

int inet::EtherBus::inputGateBaseId = -1
protected

Referenced by checkConnections(), and initialize().

long inet::EtherBus::numMessages = 0
protected

Referenced by finish(), and initialize().

int inet::EtherBus::numTaps = -1
protected
int inet::EtherBus::outputGateBaseId = -1
protected
double inet::EtherBus::propagationSpeed = NaN
protected

Referenced by initialize().

BusTap* inet::EtherBus::tap = nullptr
protected

The documentation for this class was generated from the following files: