This project involved the development of a simulation for a network queueing system incorporating Random Early Drop for congestion control. The simulation was structured around three fundamental components:
- A Global Clock: This central element dictates the temporal ordering and scheduling of all events within the simulation.
- Interactive Components (Router and Sources): These entities operate reactively, performing actions only when signaled by the global clock.
- An Event Log: A comprehensive log was maintained to record all significant occurrences and system states throughout the simulation run.
The foundation of our simulation relies on a few key data structures:
Events are the atomic units of activity within our simulation, stored in a min-heap data structure, ordered by their time attribute. Three primary event types were sufficient for our model:
TIMER: Used to schedule future actions for packet generators.ARRIVAL: Denotes the moment a packet reaches the router's input.DEPARTURE: Represents the completion of service for a packet at the router's output.
Packet instances are generated by sources and passed to the router. Each Packet encapsulates essential attributes including a unique id, createdAt timestamp, sizeBytes, source, and destination.
This structure models the router's buffer as a FIFO queue with a predefined maximum capacity. It provides standard queue operations: push, pop, front, size, empty, and capacity.
Acts as the central orchestrator, managing the global clock, scheduling events, and dispatching them to the appropriate components.
- Maintains a min-heap of
Eventobjects. - The
schedule(Event)method adds a future event to the heap. - The
run(until)method iteratively:- Extracts the earliest
Eventfrom the heap, providede.time ≤ until. - Advances the internal simulation time (
_now) toe.time. - Emits a
packetEventcontaininge.nodeId,e.pkt,e.type, ande.timeto notify relevant components.
- Extracts the earliest
- The
record(...)method forwards simulation data points to theMetricscomponent for collection.
This centralized approach ensures a single authority for time progression and event ordering, allowing other actors to react deterministically to a unified signal, filtering events by their nodeId.
Represents the bottleneck link in the network, integrating the RED algorithm for buffer management and a single-server model for packet processing.
- State: Comprises one output
Port(defined bytxRateandpropDelay), aBoundedQueuefor its buffer, simple counters for statistics, and a Random Number Generator (RNG) for RED's probabilistic dropping. - Connectivity: Establishes a
Qt::UniqueConnectiontoSimulator::packetEventin its constructor, ensuring it receives all relevant events. - Event Filtering: An internal guard (
if (nodeId != _id) return;) within itsonEventmethod ensures it only processes events intended for itself.
Arrival Handling:
- Upon packet
ARRIVAL, the router queries its current queue length (qlen). - It then computes the packet drop probability (
p) using the RED algorithm based onqlen. - A packet is either dropped with probability
por if the buffer is at itscapacity:- Drop counters are incremented, a
congested()signal isemitted, andrecord(queue_len, drop=1, forward=0, t)is called.
- Drop counters are incremented, a
- If the packet is accepted, it is pushed into the
BoundedQueue, andrecord(..., drop=0, forward=0, t)is called.- Crucially, if the queue transitioned from empty to having one packet (0 → 1), a DEPARTURE event is scheduled for this packet at
now + 1/txRate + propDelay.
- Crucially, if the queue transitioned from empty to having one packet (0 → 1), a DEPARTURE event is scheduled for this packet at
Departure Handling:
- Upon a DEPARTURE event, one packet is popped from the queue and counted as forwarded.
record(..., drop=0, forward=1, t)is called. - If the queue remains non-empty, the next DEPARTURE event is scheduled immediately.
- The "0→1 rule" for scheduling departures prevents the accumulation of multiple departure events for a single head-of-line packet, ensuring efficient processing.
Congestion Signal:
- Each time a packet is dropped, a
congested()signal is emitted. Packet generators subscribe to this signal to trigger their backoff mechanisms.
Two identical PacketGenerator instances are responsible for generating packet streams following a Poisson distribution and dynamically reducing their offered load in response to congestion signals from the router.
State:
_genRate(packets per unit time),_txRate(serialization rate),_propDelay.- Random Number Generators (RNGs): an exponential distribution for Poisson arrivals and a uniform distribution for backoff jitter.
- Backoff state variables:
_backoffflag,_resumeAttimestamp, and_lastResumeScheduledtimestamp for managing backoff periods. - A
_ctrfor assigning unique packet IDs.
Connections:
- They listen to
Simulator::packetEventbut primarily act uponTIMERevents designated for their specificnodeId. - They are connected to
Router::congested, triggering theironCongested()method when a drop occurs.
Key Functions:
start(at): Initializes the generator by scheduling its first TIMER event atat + Exp(_genRate).onEvent(..., TIMER, t):- If not currently in a backoff state,
send(t)is called. - If in backoff and
t ≥ _resumeAt, the backoff state is cleared, andsend(t)is called. - Otherwise (in backoff but before
_resumeAt), the event is ignored.
- If not currently in a backoff state,
send(now):- Constructs a
Packet. - Schedules an ARRIVAL event for this packet at the router, at
now + 1/_txRate + _propDelay. - Schedules the next TIMER event for itself at
now + Exp(_genRate).
- Constructs a
onCongested():- Calculates a
deadlinefor resuming transmission (now + U(0.5, 1.5)/_genRate). - If not currently backing off: sets
_backoff=true,_resumeAt=deadline, and schedules one resumeTIMER. - If already backing off: extends
_resumeAt = max(_, deadline). A new, later resumeTIMERis scheduled only if this extension pushes_resumeAtpast the previously scheduled resume time.
- Calculates a
This coalesced backoff mechanism demonstrates robustness by effectively reducing the offered load during periods of router congestion, which is visibly reflected in the simulation's metrics.
Serves as a straightforward data sink for collecting time-series data from the simulation.
- Stores parallel
QVectors to recordtimes,queueLens,drops(binary 0/1), andforwards(binary 0/1) for each port. - The router invokes
sim.record(...)on every packet arrival and departure to log these samples. - After the simulation
run()completes,main.cppexports these collected arrays into CSV files.
Note: The queue_len recorded in events.csv represents the post-event queue size. The accompanying plotting script performs a conversion for arrivals to derive the pre-enqueue queue length, which is crucial for empirically validating the RED curve (specifically, q_pre = q_logged if dropped, and q_pre = q_logged − 1 if accepted).
-
Startup: The simulation begins by instantiating the
Simulator,Metricscollector, aRouter(configured with a capacity of 6 andtxRate=1), and twoPacketGenerators (each with agenRate=2). Therouter.congestedsignal is connected to thegen.onCongestedslot for both packet sources. Each generator is started withgen.start(0.0), followed bysim.run(until)to initiate the simulation. -
TIMER → Send: The simulator dispatches a generator's
TIMERevent. The generator responds by constructing aPacket, scheduling its ARRIVAL at the router fornow + 1/_txRate + _propDelay, and then scheduling its own nextTIMERbased on an exponential distribution. -
ARRIVAL → RED/Enqueue: Upon receiving an ARRIVAL event, the router evaluates its current
qlenand applies the RED algorithm. If a packet is dropped, acongested()signal is emitted. If accepted, the packet is enqueued, and if the queue was previously empty, the first DEPARTURE event for this packet is scheduled. -
DEPARTURE → Forward: During a DEPARTURE event, the router removes a packet from the queue, increments its forwarded packet count, and, if the queue is not yet empty, immediately schedules the next DEPARTURE event.
-
Backoff in Action: During periods of high load and drops, the
_resumeAttime for generators is extended. Each extension schedules, at most, one laterTIMERevent for resuming transmission. When_resumeAtis finally reached, the generator resumes its normal packet sending rate. -
Recording: Every significant event (packet arrival, departure, or drop) triggers a call to
record(...). Following the completion of therun()method, the accumulated data is exported into CSV files, which are then processed by a Python helper script to generate plots that validate the configured RED curve's behavior.
Below plots are for --until 200 --seed 8121:
samples=878 total_forwarded=199 total_dropped=477






