Loading learning content...
In our exploration of reliable data transfer, we've seen that Stop-and-Wait ARQ provides correctness but sacrifices efficiency. When a sender transmits a single frame and waits for its acknowledgment before sending the next, the communication channel sits idle during the entire round-trip propagation time. For high bandwidth-delay product links—satellite connections, transcontinental fiber, or high-speed networks—this idle time represents an enormous waste of capacity.
Go-Back-N ARQ revolutionizes this approach by introducing pipelining: the sender maintains multiple outstanding (unacknowledged) frames simultaneously, keeping the channel continuously utilized. This conceptually simple yet operationally sophisticated protocol forms the backbone of reliable data transfer in protocols like HDLC, and its principles underpin TCP's reliability mechanisms.
But pipelining introduces complexity. When frames can be in flight simultaneously, how do we handle losses? How do we prevent buffer overflow at the receiver? How do we ensure frames are delivered in order? Go-Back-N answers these questions with an elegant design that prioritizes simplicity at the receiver while accepting strategic trade-offs at the sender.
By the end of this page, you will understand the complete operational mechanics of Go-Back-N ARQ: how the sender window enables pipelining, how the protocol maintains frame ordering, how the finite state machines of sender and receiver interact, and how timeouts trigger the distinctive 'go back' retransmission behavior that gives the protocol its name. You'll develop the intuition to trace through GBN scenarios and predict protocol behavior under various error conditions.
At its core, Go-Back-N ARQ allows the sender to transmit up to N frames before receiving any acknowledgment, where N is the window size. This window of outstanding frames slides forward as acknowledgments arrive, hence the broader category name: sliding window protocols.
The defining characteristics of Go-Back-N:
The name "Go-Back-N" derives from this retransmission behavior: upon detecting an error, the sender "goes back" N frames (or to the last unacknowledged frame) and retransmits from that point, even if subsequent frames were received correctly.
Go-Back-N embodies a specific design philosophy: simplify the receiver at the cost of potentially redundant retransmissions. The receiver maintains minimal state—only tracking the next expected sequence number—while the sender bears the burden of buffering and retransmission. This trade-off was historically significant when receiver hardware was expensive, and remains relevant in asymmetric systems where one endpoint has constrained resources.
| Characteristic | Stop-and-Wait | Go-Back-N |
|---|---|---|
| Outstanding frames | 1 | Up to N |
| Channel utilization | Low (1 frame per RTT) | High (N frames per RTT) |
| Sender buffer | 1 frame | N frames |
| Receiver buffer | 1 frame | 1 frame (minimal) |
| Acknowledgment style | Individual ACK per frame | Cumulative ACK |
| Retransmission scope | Single frame | All frames from error point |
| Sequence number space | 2 (0, 1) | At least N+1 |
| Receiver complexity | Simple | Simple |
| Sender complexity | Simple | Moderate |
The Go-Back-N sender is more sophisticated than its Stop-and-Wait counterpart, maintaining several critical state variables:
Sender State Variables:
send_base: The sequence number of the oldest unacknowledged frame (left edge of the window)nextseqnum: The sequence number to be assigned to the next frame to be sentN: The window size (maximum number of outstanding frames)buffer[0..N-1]: Storage for frames that may need retransmissionThe Sender Window:
Conceptually, the sequence number space is divided into four regions:
The usable window consists of regions 2 and 3: frames already in flight plus frames available for immediate transmission. The invariant maintained is:
send_base <= nextseqnum <= send_base + N
This ensures no more than N frames are ever outstanding.
Imagine a window of size N sliding over an infinite tape of sequence numbers. The left edge (send_base) advances when ACKs arrive; the right edge (send_base + N) advances correspondingly. The sender can transmit any frame within the window but must wait for acknowledgments before the window can slide forward to expose new sequence numbers.
Sender Events and Actions:
Event 1: Data from Upper Layer
When the upper layer (e.g., network layer) has data to send:
if (nextseqnum < send_base + N) {
// Window has room
buffer[nextseqnum mod N] = make_frame(data, nextseqnum);
send(buffer[nextseqnum mod N]);
if (send_base == nextseqnum) {
start_timer(); // Start timer for oldest outstanding frame
}
nextseqnum++;
} else {
// Window full - refuse data or buffer at application level
refuse_data(data);
}
Event 2: ACK Received
When an acknowledgment for frame with sequence number ack_num arrives:
if (ack_num >= send_base) {
// Cumulative ACK: all frames up to ack_num are now acknowledged
send_base = ack_num + 1;
if (send_base == nextseqnum) {
stop_timer(); // All frames acknowledged
} else {
restart_timer(); // Reset timer for new oldest outstanding frame
}
}
// If ack_num < send_base, this is a duplicate ACK (ignore or handle specially)
Event 3: Timeout
When the timer expires (no ACK received within timeout period):
start_timer();
for (i = send_base; i < nextseqnum; i++) {
// Retransmit ALL outstanding frames
send(buffer[i mod N]);
}
This is the "Go-Back-N" behavior: the sender retransmits every frame from send_base to nextseqnum - 1, regardless of which frame actually caused the timeout.
The Go-Back-N receiver is deliberately simple, maintaining only a single state variable:
Receiver State Variable:
expectedseqnum: The sequence number of the next frame expected (the only frame that will be accepted)Receiver Behavior:
The receiver enforces strict in-order delivery with the following logic:
receive(frame):
if (frame.seqnum == expectedseqnum && !corrupted(frame)) {
// Frame is exactly what we expect
deliver_data(frame.data);
send(ACK, expectedseqnum);
expectedseqnum++;
} else {
// Frame is out of order, corrupted, or duplicate
// Discard the frame
// Send ACK for last correctly received in-order frame
send(ACK, expectedseqnum - 1);
}
Critical Insight: Out-of-Order Frames Are Discarded
This is the most distinctive aspect of Go-Back-N receiver behavior. If the receiver expects frame 5 but receives frame 6 (because frame 5 was lost), it discards frame 6 and sends an ACK for frame 4 (the last in-order frame received). This happens even though frame 6 is a perfectly valid frame!
Why discard correct frames?
The receiver's simplicity comes at a cost: correctly received frames are discarded and must be retransmitted. If frame 5 is lost but frames 6, 7, 8 arrive correctly, the receiver discards all of them. The sender must retransmit frames 5, 6, 7, and 8—even though 6, 7, 8 were already received. This redundant retransmission wastes bandwidth, especially when error rates are high or the window is large. This trade-off motivates the more sophisticated Selective Repeat protocol.
expectedseqnumexpectedseqnum (out of order)expectedseqnum (duplicate)ACK Semantics in Go-Back-N:
The ACK sent by the receiver carries the sequence number of the last correctly received in-order frame. When the receiver sends ACK n, it means:
"I have correctly received all frames with sequence numbers ≤ n. I am now expecting frame n+1."
This cumulative semantics has important implications:
ACK 7 arrives, the sender knows frames 0-7 are all receivedACK 5 was lost, receiving ACK 7 retroactively acknowledges frames 5, 6, and 7send_base based on a single ACKLet's trace through a complete Go-Back-N scenario to solidify understanding. Consider a sender with window size N = 4 and data frames 0, 1, 2, 3, 4, 5 to transmit. We'll examine both normal operation and error recovery.
Scenario Setup:
send_base = 0, nextseqnum = 0, expectedseqnum = 0| Time | Sender Action | Network | Receiver Action | Sender State |
|---|---|---|---|---|
| T1 | Send Frame 0 | Frame 0 → | — | base=0, next=1 |
| T2 | Send Frame 1 | Frame 1 → | — | base=0, next=2 |
| T3 | Send Frame 2 | Frame 2 LOST ✗ | — | base=0, next=3 |
| T4 | Send Frame 3 | Frame 3 → | — | base=0, next=4 |
| T5 | Window full, wait | — | Receive Frame 0, send ACK 0 | base=0, next=4 |
| T6 | — | ← ACK 0 | Receive Frame 1, send ACK 1 | — |
| T7 | Receive ACK 0, slide window | — | Receive Frame 3, discard! Send ACK 1 | base=1, next=4 |
| T8 | Send Frame 4 | Frame 4 → | — | base=1, next=5 |
| T9 | Receive ACK 1, slide window | ← ACK 1 (repeat) | Receive Frame 4, discard! Send ACK 1 | base=2, next=5 |
| T10 | TIMEOUT! Retransmit 2,3,4 | Frames 2,3,4 → | — | base=2, next=5 |
| T11 | — | — | Receive Frame 2, send ACK 2 | — |
| T12 | Receive ACK 2, slide | ← ACK 2 | Receive Frame 3, send ACK 3 | base=3, next=5 |
| T13 | Send Frame 5 | Frame 5 → | Receive Frame 4, send ACK 4 | base=3, next=6 |
| T14 | Receive ACK 3, ACK 4 | ← ACK 3,4 | Receive Frame 5, send ACK 5 | base=5, next=6 |
| T15 | Receive ACK 5, complete | ← ACK 5 | — | base=6, next=6 |
Understanding the Go-Back Behavior:
When the timeout occurred at T10, the sender's state showed send_base = 2 (oldest unacknowledged frame) and nextseqnum = 5 (next frame to send would be 5). The go-back behavior retransmitted frames 2, 3, and 4—everything from send_base to nextseqnum - 1.
The sender effectively "goes back" to the point of the error and retransmits from there. This is simpler than selectively retransmitting only Frame 2, but wastes bandwidth resending Frames 3 and 4.
Duplicate ACKs as Error Signals:
Notice that the receiver sent ACK 1 multiple times (at T6, T7, T9). These duplicate ACKs signal that the receiver keeps getting frames after frame 1 but is still waiting for frame 2. Some implementations use duplicate ACKs to trigger fast retransmission before timeout expires—a technique later refined in TCP's Fast Retransmit mechanism.
Timer management in Go-Back-N is crucial for correct operation and efficiency. Unlike Selective Repeat (which maintains a timer per outstanding frame), Go-Back-N uses a single timer associated with the oldest unacknowledged frame.
Timer Lifecycle:
send_base == nextseqnum)send_base advances but window is not empty)Why a Single Timer?
When the timer for the oldest outstanding frame expires, we know that at least one frame was lost (or its ACK was lost). Due to cumulative acknowledgments and the receiver's in-order delivery requirement, if frame k is lost, all frames k+1, k+2, ... must be retransmitted anyway. Therefore, a single timer suffices—timeout always triggers retransmission of all outstanding frames.
The timeout value must be chosen carefully:
• Too short: Causes unnecessary retransmissions when frames/ACKs are merely delayed • Too long: Leaves the sender idle when a frame is actually lost, wasting bandwidth
Ideal timeout ≈ RTT + small margin for variance. In practice, adaptive timeout algorithms (like those in TCP) dynamically adjust based on observed RTT measurements.
Timer Implementation Strategies:
Strategy 1: Hardware Timer
- Single countdown timer
- On expiry: Interrupt CPU, trigger retransmission
- On ACK: Reset timer to initial value
- Simple but requires hardware support
Strategy 2: Software Timer with Timestamps
- Record transmission time of oldest outstanding frame
- Periodically check: if (current_time - oldest_tx_time > timeout)
trigger retransmission
- More flexible, works without dedicated timer hardware
Strategy 3: Piggyback on Event Loop
- Use select() / poll() with timeout parameter
- Timeout = min(remaining_timeout, ...)
- Integrate with network I/O multiplexing
- Common in modern implementations
Timeout and RTT Estimation:
In real implementations, the timeout value adapts to network conditions:
Estimated_RTT = (1 - α) × Estimated_RTT + α × Sample_RTT
Timeout = β × Estimated_RTT
Where:
Sample_RTT = measured round-trip time for a recent frameα = smoothing factor (typically 0.125 or 1/8)β = safety margin multiplier (typically 2-4)For complete clarity and implementation guidance, here is the formal specification of Go-Back-N ARQ as finite state machines.
GBN Sender FSM:
1234567891011121314151617181920212223242526272829303132333435363738
// Go-Back-N Sender Finite State Machine// State Variables:// send_base: oldest unacknowledged sequence number// nextseqnum: next sequence number to assign// N: window size// buffer[]: frame buffer for retransmission// timer: single retransmission timer initialize: send_base = 0 nextseqnum = 0 timer = STOPPED event: rdt_send(data) from upper layer if (nextseqnum < send_base + N): // Window has space sndpkt[nextseqnum] = make_pkt(nextseqnum, data, checksum) buffer[nextseqnum mod N] = sndpkt[nextseqnum] udt_send(sndpkt[nextseqnum]) if (send_base == nextseqnum): // First outstanding frame start_timer() nextseqnum = nextseqnum + 1 else: refuse_data(data) // Window full event: receive(rcvpkt) from network if (notcorrupt(rcvpkt)): ack_num = getacknum(rcvpkt) if (ack_num >= send_base): // Valid cumulative ACK send_base = ack_num + 1 // Slide window if (send_base == nextseqnum): // All acknowledged stop_timer() else: restart_timer() // New oldest outstanding event: timeout start_timer() for i = send_base to nextseqnum - 1: // Retransmit ALL outstanding udt_send(buffer[i mod N])GBN Receiver FSM:
1234567891011121314151617181920
// Go-Back-N Receiver Finite State Machine// State Variable:// expectedseqnum: sequence number of next expected frame initialize: expectedseqnum = 0 sndpkt = make_pkt(ACK, -1, checksum) // Initial dummy ACK event: receive(rcvpkt) from network if (notcorrupt(rcvpkt) AND getseqnum(rcvpkt) == expectedseqnum): // Frame is exactly what we expect extract(rcvpkt, data) deliver_data(data) // To upper layer sndpkt = make_pkt(ACK, expectedseqnum, checksum) udt_send(sndpkt) expectedseqnum = expectedseqnum + 1 else: // Corrupted, out-of-order, or duplicate // Resend ACK for last correctly received in-order frame udt_send(sndpkt) // sndpkt still holds previous ACKThe GBN protocol guarantees:
Reliability: Every frame sent by the sender is eventually delivered exactly once (assuming finite error rate and infinite retries).
Order: Frames are delivered to the upper layer in the exact order they were submitted by the sender.
Liveness: The protocol makes progress as long as the channel has finite delay and error rate.
These properties can be formally verified using model checking or proof techniques.
We've now established a complete understanding of Go-Back-N ARQ operation. Let's consolidate the essential knowledge:
send_base (oldest unACKed) and nextseqnum (next to send), buffering all outstanding framesexpectedseqnum; discards out-of-order frames to guarantee in-order deliveryWhat's Next:
With the operational mechanics established, the next page dives deep into cumulative acknowledgments—exploring their semantics, advantages, implications for lost ACKs, and how they enable the window to slide efficiently. Understanding cumulative ACKs is essential for grasping GBN's efficiency characteristics and its relationship to TCP's acknowledgment scheme.
You now understand how Go-Back-N ARQ operates at a fundamental level: the sliding window mechanism, sender and receiver state machines, timer management, and the distinctive go-back retransmission behavior. This foundation enables deeper exploration of cumulative acknowledgments, window sizing constraints, and efficiency analysis in subsequent pages.