Você está na página 1de 38

TECHNISCHE UNIVERSITEIT EINDHOVEN Department of Mathematics and Computer Science

MASTERS THESIS

A sliding window protocol


by Arjan van Leeuwen

Supervisor: dr. ir. R. R. Hoogerwoord Eindhoven, January 2006

Acknowledgements
I would like to thank ir. W.H.J. Feijen for introducing me and many others to the art of programming, for teaching an inspiring course in Design of Multiprograms, for giving me a direction to pursue and for suggesting me to ask dr.ir. R.R. Hoogerwoord as my supervisor. I would like to thank dr.ir. R.R. Hoogerwoord for many stimulating technical discussions and for always being able to give me new ideas and things to try. Thanks also go to my parents for supporting me, to Leon for our discussions about each others projects, to Fons and Tim for being fantastic roommates and to Maurice, Walter and everybody at Dynamic Solutions for giving me a great job during my study.

iii

Contents
1 Introduction 1.1 Problem description 1.2 Methods used . . . 1.3 Notation . . . . . . 1.4 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 2 2 3 3 3 3 4 4 4 5 5 5 5 6 6 6 7 8 9 10 11 11 11 11 11 12 16 18 18

2 Modelling faulty channels 2.1 Channel usage . . . . . . . . . . . . . . . . . 2.2 Channel interface . . . . . . . . . . . . . . . 2.2.1 Sending . . . . . . . . . . . . . . . . 2.2.2 Receiving . . . . . . . . . . . . . . . 2.2.3 Rule of import and export . . . . . . 2.3 Desired features . . . . . . . . . . . . . . . . 2.3.1 Formalization of the desired features . 2.4 Implementation of a reliable channel . . . . . 2.4.1 Send . . . . . . . . . . . . . . . . . 2.4.2 Receive . . . . . . . . . . . . . . . . 2.5 Implementation of a faulty channel . . . . . . 2.5.1 Loss . . . . . . . . . . . . . . . . . . 2.5.2 Duplication . . . . . . . . . . . . . . 2.5.3 No FIFO . . . . . . . . . . . . . . . 2.5.4 Rule of import and export . . . . . . 2.6 A faulty channel with bounded buffering . . . 2.7 Function for potential output . . . . . . . . . 3 A sliding window protocol 3.1 Introduction . . . . . . . . . . . . . . 3.2 Situation . . . . . . . . . . . . . . . . 3.3 Transferring N messages . . . . . . . 3.3.1 Specication . . . . . . . . . 3.3.2 Implementation . . . . . . . . 3.3.3 Progress . . . . . . . . . . . . 3.4 Transferring innitely many messages 3.4.1 Specication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

iv

3.5

3.6

3.4.2 Implementation . . . . . . . . . 3.4.3 Progress . . . . . . . . . . . . . Recycling indices . . . . . . . . . . . . 3.5.1 Reducing indices on channel F . 3.5.2 Reducing indices on channel G . 3.5.3 Implementing cyclic indices . . Limiting the size of sets . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

18 20 20 21 24 26 27 30 30 30 30 31 31 32

4 Summary and conclusions 4.1 Summary . . . . . . . . . . . . . . . . . . . 4.2 Comparison to existing research . . . . . . . 4.2.1 Research of J.L.A. van de Snepscheut 4.2.2 Research of N.V. Stenning . . . . . . 4.3 Conclusions . . . . . . . . . . . . . . . . . . 4.4 Recommendations for future research . . . .

Chapter 1

Introduction
1.1 Problem description
Between physically separated machines, communication is often only possible over socalled faulty channels i.e., an asynchronous channel that can lose and duplicate messages and can receive messages in an order different from the one in which the messages were sent. Our main goal is to derive a protocol that enables the reliable transfer of a data stream from one machine to another machine over a faulty channel, i.e., the receiving side outputs a data stream that is equal to the data stream input on the sending side. Furthermore, the following is demanded from the protocol: the protocol should not hamper throughput unnecessarily, the protocol must be provably correct, and the protocol must exhibit progress. This problem is usually solved by a so-called sliding window protocol [Ste76, Sne95]. We will derive such a sliding window protocol and prove that it complies to all the given demands. We also show that our protocol is more general than [Sne95], and that the proof is more complete than [Ste76].

1.2 Methods used


The correctness of the protocol is proved using Owicki/Gries theory for parallel processes [OG76]. The protocol is developed using the proof-by-design methods explored in [FG99]. To use these methods, the protocol is implemented as two processes running in parallel, albeit with faulty channels as the only way of communication between the two processes.

To be able to completely prove the correctness of the protocol using Owicki/Gries theory, the faulty channels are rst modelled as a set of program operations in Chapter 2. This model is then used to derive the protocol in Chapter 3.

1.3 Notation
The program notation used in this thesis is derived from the Guarded Command Language (GCL), and is the same as the notation used in [FG99]. In addition, these notations are used: Intervals of integers: for integers a and b, [a..b) denotes the set {i | a i < b }. Array segments: for any array X and natural numbers a and b that are at most the size of X, X[a..b) denotes the array segment that contains all array elements of X with an index in interval [a..b). Assignments using a proposition: x : P is a statement that assigns a value to variable x such that proposition P holds. It is only dened if (x :: P) holds. Channel names: because multiple channels are used, we distinguish the variables used by these channels by prexing variables and procedures that operate on these variables with a channel name, e.g., F.ct is a different variable from G.ct, and F.Recei ve is equal to the procedure Recei ve with all variable names prexed by F.

1.4 Terminology
This terminology is used throughout the document: Message: unit of communication over channels Sending: The action of posting a message to a channel by the sending process Receiving: The action of assigning a message, sent earlier, to a local variable of the receiving process Transferring: Sending and receiving a message

Chapter 2

Modelling faulty channels


2.1 Channel usage
Each channel is connected to two processes: the sending process and the receiving process. The sending process of a channel cannot receive any messages via that channel, and the receiving process of a channel cannot send any messages via that channel. A process can be connected to multiple channels, creating a situation where a single process can be both the sending process of one channel and the receiving process of another channel.

4 U iiii F UUUUUUU iiii * 89:; 89:; ?>=< jUU B A UU i?>=< UUUU iiii i G tii Figure 2.1: Two processes connected by two channels Figure 2.1 shows an example setup, consisting of two processes, A and B, and two channels, F and G. The direction of the communication over the channels is signied by the arrows: A is the sending process of F and the receiving process of G, B is the receiving process of F and the sending process of G.

2.2 Channel interface


2.2.1 Sending
Sending a message is modelled by the Send-operation. The sending process of a channel F can send an expression b as follows: F.Send(b) 3

This operation is guaranteed to terminate.

2.2.2 Receiving
Receiving a message is modelled by the Recei ve-operation. Receiving a message from a channel F into variable y can be implemented by the receiving process as follows: F.Recei ve(y) This operation is not guaranteed to terminate: Recei ve will not end until a message is received.

2.2.3 Rule of import and export


To simplify proving certain properties of messages transferred via a faulty channel, we use the rule of import and export for faulty channels. This rule species that in this program fragment from the receiving process of channel F F.Recei ve(y) {Q } and this fragment from the sending process of channel F {P } F.Send(b) the assertion Q is locally correct, if [ P Q(y := b) ] holds.

2.3 Desired features


The faulty channels are modelled using these desired features: 1. No invented messages: every message received via a channel has been sent via that channel 2. No FIFO: messages can be received in a different order than they were sent 3. Unreliable: every sent message can be lost (will not be received) or duplicated (will be received multiple times) 4. Finite duplication: a message is not duplicated innitely many times 5. Finite loss: after sending sufciently many messages, at least one of these messages will be received 6. Rule of import and export: the channel respects the rule of import and export, as described in 2.2.3 Features 4 and 5 make it possible to give progress guarantees about receiving messages. Without these features, it is impossible to guarantee the transfer of messages in nite time. 4

2.3.1 Formalization of the desired features


To represent sent messages, we introduce, for each channel, an (unbounded) array C that contains all sent messages for that channel and a variable ct : N that represents the number of messages already sent, where ct = 0 initially. The array segment C[0..ct) represents all sent messages. A channel has feature 1 if for a variable y, y C[0..ct) is a correct postassertion of Recei ve(y).

2.4 Implementation of a reliable channel


We will rst implement a reliable channel, that is to say a channel that has feature 1, receives messages in the same order as they were sent, and that doesnt lose or duplicate any messages.

2.4.1 Send
The Send-operation is easy to implement, given the array C and variable ct introduced in 2.3.1. Sending a message b is implemented by: Send(b) : ; C.ct := b ct := ct + 1

2.4.2 Receive
C[0..ct) contains all sent messages. We introduce a variable cb : N that represents how many message have already been received. Initially, cb = 0. As messages will be received in the same order as they are sent, cb also represents the index of the next message to be received. Receiving a message in variable y can be implemented as follows: Recei ve(y) : ; ; if cb < ct ski p { cb < ct } y := C.cb { y C[0..ct) } cb := cb + 1 { y C[0..ct) } Note that the Recei ve-operation establishes the desired postassertion y C[0..ct), and that none of the assertions in the operation can be disturbed by a Send-operation, making them globally correct.

2.5 Implementation of a faulty channel


2.5.1 Loss
By increasing cb before the guarded skip in the Recei ve-operation, messages with an index at least the previous value of cb and smaller than the new value of cb will be lost. We introduce a variable th : N to signify that the next th messages to be delivered will be lost. This can be established by choosing a value for th and increasing cb by th: Recei ve(y) : ; ; ; ; th : 0 th cb := cb + th if cb < ct ski p { cb < ct } y := C.cb { y C[0..ct) } cb := cb + 1 { y C[0..ct) } The channel will not lose innitely many messages, because th is a natural number. Interval [0..cb) now represents the indices of messages that will not be received anymore (messages that have been received or lost).

2.5.2 Duplication
Receiving a message always increases cb, making it impossible for message cb to be received multiple times. By omitting the increase of cb at the end of the Recei veoperation, messages can be duplicated: if th = 0, cb is not increased, and C.cb can be received again. Recei ve(y) : ; ; ; th : 0 th cb := cb + th if cb < ct ski p { cb < ct } y := C.cb { y C[0..ct) } However, this duplication is not nite. If the value 0 is consistently chosen for th, message C.cb is duplicated innitely many times. To make duplication nite, we introduce an unbounded array D[0..) of natural numbers, which is assumed to initially contain an arbitrary number larger than 0 for every possible index. Array D represents the number of times a message can be received: a message C.i will be received at most D.i times. Every number in array D is initially larger than 0 in order to keep losing and duplicating messages separate. 6

Finite duplication can now be implemented in the Recei ve-operation by decreasing D.cb after receiving a message, and increasing cb if D.cb = 0. Recei ve(y) : ; ; ; ; ; th : 0 th cb := cb + th do D.cb = 0 cb := cb + 1 od { (note 0) } { D.cb > 0 } if cb < ct ski p { cb < ct } { D.cb > 0 } y := C.cb { cb < ct } { D.cb > 0 } { y C[0..ct) } D.cb := D.cb 1 { y C[0..ct) } The added assertions are globally correct, because Send does not modify D. This implementation keeps K0 : (i : ct i : D.i > 0)

invariant. K 0 holds initially, because all elements of D are initially larger than 0. Statement ct := ct + 1 in Send does not disturb K 0. Statement D.cb := D.cb 1 in Recei ve does not disturb K 0, because cb < ct is a valid preassertion of that statement. (note 0): This loop terminates. To see this, consider this variant function: ( i : cb i D.i > 0 : i ) cb The domain of the minimum in this variant function is not empty, because of K 0. The value of this variant function is not changed by the Send-operation. Every iteration of the loop decreases the variant function by 1, and if it is 0, this implies D.cb > 0.

2.5.3 No FIFO
Because the Recei ve-operation always receives the message with index cb and because cb is only increasing, values are received in the same order as they are sent. It is of course possible to receive a message with an arbitrary index from [0..ct), but that would give too much freedom: in paragraph 2.5.1, we concluded that [0..cb) represented the indices of messages that would not be received anymore. The method for losing messages is based on this property. Messages with an index i for which D.i = 0 should also not be received anymore. To keep the previously introduced features of nite loss and nite duplication, but lose the FIFO property, an arbitrary index h is chosen, such that cb h < ct and D.h > 0. To accomplish this, we introduce local variable h : N. Recei ve(y) : th : 0 th 7

; ; ; ; ; ;

cb := cb + th do D.cb = 0 cb := cb + 1 od { D.cb > 0 } if cb < ct ski p { cb < ct } { D.cb > 0 } h : cb h < ct D.h > 0 y := C.h D.h := D.h 1 { y C[0..ct) }

This change will allow messages to be received in a different order than the one in which they were sent. The nite loss and nite duplication features that were added earlier are still present: messages can be lost because cb is increased, and messages can be duplicated because one index can be selected more than once. Because D is an array of natural numbers, duplication is nite; because cb is increased by a natural number, loss is nite.

2.5.4 Rule of import and export


The rule of import and export, as dened in 2.2.3, should apply to the channel implementation. To simplify the process of proving that the rule of import and export holds, we consider a simple system where two processes A and B are respectively the sending and receiving process of a channel F. Process A sends one message to process B. What are the proof obligations of adding an arbitrary assertion Q as a postassertion of the Recei ve-operation in process B? We assume assertion Q does not contain any variables used by the channels themselves. The only statement in F.Recei ve(y) that inuences the correctness of Q is the assignment to y: Q(y := C.h) {0 h < ct } (i : 0 i < ct : Q(y := C.i ) )

We will introduce this assertion as a system invariant: K 1 : (i : 0 i < ct : Q(y := C.i ) ) This system invariant can be falsied by increasing ct. This gives an extra proof obligation in the Send-operation: Send(b) : ; { ? Q(y := b) } C.ct := b { Q(y := C.ct) (note 0) } ct := ct + 1

(note 0): The global correctness of this assertion is irrelevant, because Send(b) can be seen as an atomic statement that only changes private variables. 8

The queried preassertion Q(y := b) indicates that the rule of import and export applies to this implementation of faulty channels.

2.6 A faulty channel with bounded buffering


The faulty channels modelled here can reorder messages. The reordering of messages can be seen as delaying messages. In practice, we expect a faulty channel to lose a message if that message has not been received after a certain amount of time has passed since it was sent. Time is, however, inconvenient to work with. It is suggested in [Ste76] to view the loss of delayed messages in the faulty channels in terms of the number of messages available for reception. C[cb..ct) contains the messages that have been sent but not yet been received. The number of messages available for reception can be limited to M (1 M) by enforcing this system invariant: K2 K 2 can be rewritten as: K2 : ct M + cb : ct cb M

The only statement that disturbs K 2 is the increase of ct in the Send-operation: Send(b) : ; C.ct := b { ? ct < M + cb } ct := ct + 1

The queried assertion can be established by using an extra guard: Send(b) : ; C.ct := b if ct < M + cb ct := ct + 1

This means that Send is able to block the calling process, which is not desired. To avoid this, the oldest message in the buffer is removed when the buffer is full, by increasing cb: Send(b) : ; C.ct := b if ct < M + cb ct := ct + 1 ct = M + cb ct, cb := ct + 1, cb + 1

This introduces a new loss of messages, but the loss is nite: ct = M + cb implies cb < ct, causing a Recei ve-operation to either receive a message or increase cb (establishing ct < M + cb). The modied Send-operation can disturb assertion D.cb > 0 in Recei ve. Luckily, this assertion can safely be replaced by (i : cb i < ct : D.i > 0) which is locally correct in Recei ve. This assertion is not disturbed by assignment ct, cb := 9

ct + 1, cb + 1 in Send, because that assignment establishes D.(ct 1) > 0 due to the invariance of K 0. Recei ve(y) : ; ; ; ; ; ; th : 0 th cb := cb + th do D.cb = 0 cb := cb + 1 od { (i : cb i < ct : D.i > 0) } if cb < ct ski p { cb < ct } { (i : cb i < ct : D.i > 0) } h : cb h < ct D.h > 0 y := C.h D.h := D.h 1 { y C[0..ct) }

2.7 Function for potential output


To simplify progress discussions of algorithms that use the faulty channels, we introduce for every channel a function Pot that takes a message b as its argument, and returns a natural number that species a maximum to the number of times message b will be received from that channel. Pot (b) = ( i : 0 i < ct C.i = b : D.i )

Send(b) increases Pot (b): Send(b) increases ct, establishing C.(ct 1) = b and D.(ct 1) > 0 (because of K 0), which increases Pot (b). Recei ve(y) decreases Pot (b) if this operation establishes y = b, because that means Recei ve has decreased D.h, where h is such that 0 h < ct C.h = b. Recei ve(y) does not change Pot (b) if this operation establishes y = b, because that means Recei ve has decreased D.h, where h is such that C.h = b.

10

Chapter 3

A sliding window protocol


3.1 Introduction
We derive a protocol that enables the reliable transfer of a data stream from one process to another process, and that conforms to the requirements from 1.1. The processes are only allowed to communicate via the faulty channels model described in Chapter 2. We will rst develop an algorithm to transfer a nite stream of data in a nite amount of time from one process to another process. We will use this algorithm as a foundation for an algorithm that transfers an ininite stream of data.

3.2 Situation
Consider two processes, A and B. A is to transfer data to B. The only way of communication that is allowed between A and B is the usage of faulty channels. Because the channels are faulty, at least two channels are needed: one channel for A to transfer data to B, and one channel that allows B to acknowledge reception of data. The types of the messages that are transferred over the channels is not important at this moment. The two channels are named F and G. Process A is the sending process of F and the receiving process of G, process B is the receiving process of F and the sending process of G. The situation is the same as the one depicted in gure 2.1.

3.3 Transferring N messages


3.3.1 Specication
Process A has a constant array X[0..N), with 1 N. This array represents the data that has to be transferred in nite time to process B. Process B has an array Y [0..N) to which X is to be copied. The desired postcondition is therefore R0 : X[0..N) = Y [0..N)

11

We consider R0 to be a postcondition of A; if the postcondition has been established, A can stop sending messages.

3.3.2 Implementation
An obvious suggestion for an invariant for A is: P0 P1 : X[0..q) = Y [0..q) : 0qN

where q is a local variable of A. P0 and P1 hold initially if q = 0. Postcondition R0 is established if q = N. Invariant P0 suggests this structure for A: A: do q = N { ? X.q = Y.q (note 0) } q := q + 1 od {q = N }

(note 0): Y is a local variable of B and can neither be inspected nor changed by A. The assertion can therefore not be established by inspecting or changing Y . Assume that the indices i for which X.i = Y.i holds are known. We introduce a set Ackd of natural numbers that contains these indices. This can be captured in an invariant: P2 : (i : i Ackd : X.i = Y.i 0 i < N)

Using P2, the queried assertion X.q = Y.q can be established assuming global correctness will not be disturbed by other components by using a guarded skip: A: do q = N if q Ackd ski p ; { X.q = Y.q } q := q + 1 od {q = N }

This implementation will give us the next invariant for free: P3 : [0..q) Ackd

To enable progress, elements will have to be added to Ackd. We will not introduce a new component to do this; expanding Ackd can be done synchronously with q := q+1, because test q Ackd is only useful after changing Ackd. The value of a new local

12

variable of A, r : N, is added to Ackd: A: do q = N ; { ? X.r = Y.r 0 r < N (note 0) } Ackd := Ackd {r } ; if q Ackd ski p ; { X.q = Y.q } q := q + 1 od {q = N }

(note 0): This assertion is necessary to keep P2 invariant. A can only communicate with B via channels F and G. This means that this assertion can only be established locally by applying the rule of import and export on channel G. Global correctness is established by never assigning a value other than X.i to Y.i , for i : 0 i < N. What is the type of the messages transferred via channel G? The simplest form of an acknowledgement is the single index i , that represents the boolean value X.i = Y.i . We decide to use single indices as acknowledgements. This allows messages received via G to be added directly to Ackd: A: do q = N G.Recei ve(r ) ; { X.r = Y.r 0 r < N } Ackd := Ackd {r } ; if q Ackd ski p ; { X.q = Y.q } q := q + 1 od {q = N }

This construction allows for deadlock: the element added to Ackd does not necessarily equal q. In that case, the process blocks. To avoid this, the guarded skip is replaced by a loop: A: do q = N G.Recei ve(r ) ; { X.r = Y.r 0 r < N } Ackd := Ackd {r } ; do q Ackd { X.q = Y.q } ; q := q + 1 od od {q = N }

To allow for progress in A, B will have to send indices via G. Applying the rule of

13

import and export suggests this structure for B, where p is a local variable of B. B: [ ] (note 0): The rst conjunct of this assertion can be established by assignment Y. p := X. p, but X is a local variable of A and can neither be inspected nor changed by B. Therefore, a new local variable m of B is introduced. The value of m is assigned to Y. p: B: [ { ? X. p = m 0 p < N (note 1) } Y. p := m ; { X. p = Y. p 0 p < N (note 0) } G.Send( p) ] (note 0): This assertion is globally correct, because Y and p are local variables, and X is a constant. (note 1): This assertion can only be established by communication with A, because X is a local variable of A. Locally, this assertion can be established by applying the rule of import and export on channel F. What is the type of the messages transferred via channel F? A single element of X is insufcient; how can the value of p be extracted from this element? The value i for which X.i = m holds has to be available for that. To accomplish this, we assume that all messages received via channel F consist of a pair a, i , where a is an element of X, and i is the index of that element. B: [ ; ; ] (note 0): This assertion is globally correct, because p and m are local variables, and X is a constant. To allow for progress in B, A will have to send messages via F. This can be done in parallel with receiving the acknowledgements in A. The structure of A is changed to obtain a parallel composition with two components: A: do q = N A1 od do q = N A2 od F.Recei ve( m, p ) { X. p = m 0 p < N (note 0) } Y. p := m { X. p = Y. p 0 p < N } G.Send( p) { ? X. p = Y. p 0 p < N (note 0) } G.Send( p)

where A1 is the program fragment that processes the acknowledgements (the code is equal to the code previously assigned to A):

14

A1 : ; ;

G.Recei ve(r ) { X.r = Y.r 0 r < N } Ackd := Ackd {r } do q Ackd { X.q = Y.q } ; q := q + 1 od

A2 sends messages via F. The rule of import and export dictates the following structure for A2: A2 : { ? X.t = b 0 t < N (note 0) } F.Send( b, t ) (note 0): The rst conjunct of this assertion can of course be established by replacing b with X.t. A2 : { ? X.t = X.t 0 t < N (note 0) } F.Send( X.t, t ) (note 0): The second conjunct of this assertion is established by assigning a suitable value to t. A possible choice for t is q, but that would be unnecessarily hampering the throughput: it would mean that every message is sent repeatedly until an acknowledgement for that message is received. Only then another message will be sent. It seems more efcient to allow other messages than X.q to be sent; it also allows for more strategic freedom in choosing the value to be sent. It is useless to resend messages for which an acknowledgement has already been received. Therefore, a value for t is chosen from [0..N) \ Ackd. A2 : ; { ? [0..N)\Ackd = (note 0) } t : t [0..N) \ Ackd { X.t = X.t 0 t < N } F.Send( X.t, t )

(note 0): This assertion can be established locally by using a guarded skip, but is not globally correct, because elements are added to Ackd in A1. To avoid deadlock, we introduce a new set AckdCopy, to which Ackd is copied by A2, causing invariance of P4 : AckdCopy Ackd

This holds initially if AckdCopy = , and can be used in A2: A2 : ; ; { ? [0..N)\AckdCopy = (note 0) } t : t [0..N) \ AckdCopy { X.t = X.t 0 t < N } F.Send( X.t, t ) AckdCopy := Ackd

15

(note 0): This assertion is established by replacing the guard of the loop that surrounds A2 by [0..N)\AckdCopy = : A: do q = N A1 od do [0..N)\AckdCopy = A2 od

Does this hamper progress? Consider: [0..N)\AckdCopy = { set theor y } [0..N) AckdCopy { P4, tr ansi ti vi t y o f } [0..N) Ackd { P2 } (i : 0 i < N : X.i = Y.i ) { de f R0 } R0

The postcondition is implied if [0..N)\AckdCopy = , meaning that the loop can end without affecting the progress. Moreover, the loop ends if q = N, because q = N [0..N) Ackd holds because of the invariance of P3; the loop will end after copying Ackd to AckdCopy.

3.3.3 Progress
To prove progress in this implementation, we will rst prove that there is no individual deadlock in the components of the system as long as the postcondition R0 is not established. This is not enough to prove progress: it doesnt prove that the repetitions in A will terminate. From the structure of A1 it is clear that q = N, which will terminate both repetitions (see the end of the previous section), will be established if Ackd = [0..N) holds. This can only be established if the set Ackd is expanded, which cannot be concluded from the assertions in A1. This is why we present a variant function that increases in all situations and has an upper bound that implies Ackd = [0..N). Because there is no individual deadlock, the variant function will increase, assuring progress. It is sufcient to only consider individual deadlock; starvation does not occur, because all guards become stably true. 3.3.3.1 No individual deadlock While R0 holds, there is no individual deadlock in the system. This can be proved: There is no danger of individual deadlock in A1, as long as B repeatedly sends messages over channel G, because of the nite loss feature of the channels. B contains an innite loop, and sends one message in every iteration of that loop. There is no deadlock in A if there is no deadlock in B. 16

There is no danger of individual deadlock in B, as long as A repeatedly sends messages over channel F, because of the nite loss feature of the channels. The component in A that contains A2 is a loop that doesnt terminate until [0..N)\AckdCopy = , which implies R0 (see 3.3.2). A2 sends one message in every iteration of that loop. There is no deadlock in B if there is no deadlock in A2. There is no danger of individual deadlock in A2, because there are no blocking statements. 3.3.3.2 Variant function We claim that this is a variant function for our algorithm: v f = # AckdCopy + # Ackd, ( i : i Ackd : F.Pot ( X.i, i ) ), ( i : i Ackd : G.Pot (i ) )

The set of all tuple values for v f is lexicogracally ordered. To prove that the variant function increases while the postcondition is not established, it is sufcient to prove that one deadlock and starvation free component increases v f , and no other component decreases v f . We prove that the subcomponent of A that contains A1 increases the variant function: If statement G.Recei ve(r ) establishes that r Ackd, then this statement has increased the variant function, because ( i : i Ackd : G.Pot (i ) ) has been increased without decreasing the rst two parts of v f . If statement G.Recei ve(r ) establishes that r Ackd, statement Ackd := Ackd / {r } will increase the variant function. There are no statements in A1 that decrease v f . Additionally, we prove that none of the other components decrease v f : The subcomponent of A that uses A2 contains one statement that can decrease v f : F.Send( X.t, t ). This statement decreases ( i : i Ackd : F.Pot ( X.i, i ) ) if t Ackd. Considering t AckdCopy is a valid preassertion of F.Send( X.t, t ), / this implies AckdCopy = Ackd. A2 as a whole will increase v f , because # AckdCopy + # Ackd is increased by statement AckdCopy := Ackd. Component B contains one statement that can decrease v f : G.Send( p). This statement decreases ( i : i Ackd : G.Pot (i ) ) if p Ackd. If the preceding statement F.Recei ve( m, p ) has established p Ackd, this is a stable condition. In that case the body of B seen as a whole increases v f , because ( i : i Ackd : F.Pot ( X.i, i ) ) is increased by F.Recei ve( m, p ), and the rst part of v f is not decreased.

17

If F.Recei ve( m, p ) has established p Ackd, this is not a stable con/ dition, but it can only be changed by expanding Ackd, which means an increase of v f . Because the last two parts of v f have an upper bound of 0, and the variant function increases with every execution of A1, # AckdCopy +# Ackd will increase in nite time. # AckdCopy and # Ackd both have an upper bound of N (because of the invariance of P2 and P4).

3.4 Transferring innitely many messages


3.4.1 Specication
Process A has a constant array X[0..). The contents of this array have to be transferred to process B. Process B has an array Y [0..), to which X is to be copied. The system setup is as described in 3.2.

3.4.2 Implementation
The algorithm from 3.3 is changed to transfer elements with indices [0 .. q+N) instead of [0..N). If q increases (that is to say there is progress), innitely many messages will be transferred. The invariants from A as specied in 3.3 are updated to reect this change (P1 and P2 have been weakened): P0 P1 P2 P3 P4 : : : : : X[0..q) = Y [0..q) 0q (i : i Ackd : X.i = Y.i 0 i < q + N) [0..q) Ackd AckdCopy Ackd

The structure of component A has to be changed, because A doesnt have to end anymore: A : [ [ A1 A2 ] ] Component A1 is updated as follows (only assertion (1) has been weakened, because P2 has been weakened): A1 : ; ; G.Recei ve(r ) {X.r = Y.r 0 r < q + N (1)} Ackd := Ackd {r } do q Ackd {X.q = Y.q (0)} ; q := q + 1 od 18

Weakening assertion (1) in A1 allows us to weaken assertions (2) and (3) in component B (because of the rule of import and export): B: [ ; ; ] In A2, it is now allowed (by the rule of import and export) to weaken assertion (4), because assertion (3) in B has been weakened. This allows for an expansion of the domain from which t is selected to [0 .. q + N). A2 : ; ; { ? [0 .. q + N)\AckdCopy = (5) } t : t [0 .. q + N) \ AckdCopy { X.t = X.t 0 t < q + N (4) } F.Send( X.t, t ) AckdCopy := Ackd F.Recei ve( m, p ) { X. p = m 0 p < q + N (3) } Y. p := m { X. p = Y. p 0 p < q + N (2) } G.Send( p)

Assertion (5) is no longer established by the guard of the loop in A. It can be established by using a guarded skip: A2 : ; ; ; if [0 .. q + N)\AckdCopy = ski p { [0 .. q + N)\AckdCopy = (5) } t : t [0 .. q + N) \ AckdCopy { X.t = X.t 0 t < q + N (4) } F.Send( X.t, t ) AckdCopy := Ackd

Assertion (5) is globally correct: the only statement that can falsify it is q := q + 1 in A1. A valid postassertion of q := q + 1 is q 1 + N AckdCopy: / (q 1 + N AckdCopy) (q := q + 1) / {substi tuti on } q + N AckdCopy / { P4 } q + N Ackd / { pr edi cate logi c } P2 The guarded skip does not cause deadlock, because [0 .. q + N)\AckdCopy = {set theor y } [0 .. q + N) AckdCopy { P4 } [0 .. q + N) Ackd { N 1, set theor y } q Ackd 19

If q Ackd, A1 will increase q until q Ackd, which implies q AckdCopy and / / will cause the guard to be stably true. Its now possible to speak of a sliding window protocol: A sends elements from X that have indices in a certain integer interval, the window, where q is the start of the window and the window size is N. All elements that are before the window, with indices less than q, have already been received (see P3). Whenever q is increased, the window progresses.

3.4.3 Progress
According to 3.4.2, there is progress if q increases. Using the variant function dened in 3.3.3, it can be proved that q increases. The changes to the components do not introduce a possibility of individual deadlock, as described above. With the same arguments as in paragraph 3.3.3, it can now be proved that v f increases. The only difference is that theres no upper bound anymore to the size of Ackd and AckdCopy and consequently to the variant function; this corresponds with the changed specication of the problem, because theres no upper bound to the array that is to be transferred. The invariance of P2 guarantees that expanding Ackd means that q is increasing. If v f increases over time, this implies that # Ackd increases over time, because the last two parts of v f have an upper bound of 0 and # AckdCopy can not increase without an increase of # Ackd (because of P4). We conclude that the set Ackd grows because v f increases, which means q increases and there is progress.

3.5 Recycling indices


Until now, it has been assumed that the indices used to specify which array element is sent and as acknowledgements have no upper limit. Is it possible to reuse indices in a non-ambiguous way, such that an upper limit for the indices is established? We assume that the faulty channels perform as if bounded by a buffer of size M, as described in 2.6. To make the derivation easier, we examine a modied version of the algorithm introduced in 3.4.2, where the messages on channel F consist of just an index and the actual assignment of values to Y is ignored. The modied algorithm is as follows: A : [ [ A1 A2 ] ]

20

A1 : ; ;

G.Recei ve(r ) {0 r < q + N } Ackd := Ackd {r } do q Ackd q := q + 1 od if [0 .. q + N)\AckdCopy = ski p { [0 .. q + N)\AckdCopy = } t : t [0 .. q + N) \ AckdCopy {0 t < q + N } F.Send(t) AckdCopy := Ackd F.Recei ve( p) {0 p < q + N } G.Send( p)

A2 : ; ; ; B: [ ; ]

The goal is to nd expressions k and m such that k p < k + m is a valid postassertion of F.Recei ve( p) in B and k r < k + m is a valid postassertion of G.Recei ve(r ) in A1. This means that the indices transferred via the channels may be reduced modulo m.

3.5.1 Reducing indices on channel F


First, we establish some system invariants that mostly concern the contents of channel F, that is array F.C. In this paragraph, we will use C instead of F.C, cb instead of F.cb and ct instead of F.ct. First: P5 : (i : 0 i < ct : C.i < q + N)

This is easily seen by taking into account that t < q + N is a preassertion of F.Send(t) in A2 and the fact that q never decreases. P6 : Ackd G.C[0 .. G.ct)

This is trivial to prove, because r G.C[0 .. G.ct) is a valid postassertion of G.Recei ve(r ), and therefore a valid preassertion of Ackd := Ackd {r }. P7 : (i, j : 0 i j < ct : C.i N < C. j )

To prove this invariant, we add a dummy variable qCopy : N to A2, which acts as a local copy of q just like AckdCopy is a local copy of Ackd. Initially qCopy = q = 0,

21

and it is updated whenever AckdCopy is updated: A2 : ; ; ; if [0 .. q + N)\AckdCopy = ski p { [0 .. q + N)\AckdCopy = } t : t [0 .. q + N) \ AckdCopy {0 t < q + N } F.Send(t) AckdCopy, qCopy := Ackd, q

Note that the last assignment establishes (i : 0 i < ct : C.i < qCopy + N) (because of P5), which also holds initially and is therefore a loop invariant of the loop that contains A2, only disturbed by the increase of ct in F.Send(t). Also note that P8 : [0 .. qCopy) AckdCopy is invariant: it holds initially, and the assignment AckdCopy, qCopy := Ackd, q does not disturb it because of P3. Initially P7 holds, and it is only disturbed by the increase of ct in F.Send(t), which has C.ct = t and t [0 .. q + N)\AckdCopy as valid preassertions. We derive: P7(ct := ct + 1) {substi tuti on } (i, j : 0 i j < ct + 1 : C.i N < C. j ) {spli t o f f j = ct, P7 } (i : 0 i ct : C.i N < C.ct) {1 N C.ct N < C.ct } (i : 0 i < ct : C.i N < C.ct) {loop i nvari ant (i : 0 i < ct : C.i < qCopy + N) } (i : 0 i < ct : qCopy 1 < C.ct) {C.ct = t } (i : 0 i < ct : qCopy 1 < t) {t AckdCopy, P8 } / tr ue which proves the invariance of P7. Variable q is a local variable of A, and is therefore not available to B. We introduce variable s : N, local to B, that represents the smallest index that has not yet been received. To update this variable, we introduce a set Rcvd, in which all the indices of received array elements are stored (analogous to Ackd in A). These invariants should hold: P9 : P10 : Rcvd C[0..ct) [0..s) Rcvd

Initially, Rcvd = and s = 0 satisfy the invariants. The updating of Rcvd and s in B

22

can occur in a manner very similar to the updating of Ackd and q in A: B: [ ; ; F.Recei ve( p) {0 p < q + N } Rcvd := Rcvd {p} do s Rcvd s := s + 1 od G.Send( p)

] It is trivial to see that P9 and P10 are not disturbed by these assignments. With the help of the previously dened and proved invariants, it is now possible to prove the main invariant of this section, that together with P5 will enable the use of recycable indices on channel F: P11 : (i : (ct M) 0 i < ct : s N (M 1) C.i )

For ct M, the invariant is trivial to prove because P9 P10 ct M s M s N (M 1) 0, and C consists of natural numbers. For ct > M, this invariant is proved via induction on M. We rst provide a proof for P11(M := 1): P11(M := 1) {substi tuti on, ct > M } (i : ct 1 i < ct : s N C.i ) {one poi nt domai n } s N C.(ct 1) {algebr a } s 1 N < C.(ct 1) { P9 P10 s 1 C[0..ct), P7( j := ct 1) } tr ue

Assuming P11 holds, we now prove for P11(M := M +1): P11(M := M + 1) {substi tuti on, ct M +1 } (i : ct M 1 i < ct : s N M C.i ) {spli t o f f i = ct M 1, P11 } s N M C.(ct M 1) {algebr a } s (C.(ct M 1) + N) M {set theor y } [C.(ct M 1)+ N .. s) C[ct M .. ct) {note (0) } [0..s) C[0..ct) { P9, P10 } tr ue 23

note (0): [0..s) C[0..ct) {set theor y } [0..s) C[0 .. ct M) C[ct M .. ct) {set theor y } [C.(ct M 1)+ N .. s) C[0 .. ct M) C[ct M .. ct) { P7( j := ct M 1) [C.(ct M 1)+ N .. s) C[0 .. ct M) = } [C.(ct M 1)+ N .. s) C[ct M .. ct)

This proves invariance of P11.

3.5.2 Reducing indices on channel G


In this paragraph, an invariant concerning channel G similar to P11 for channel F is proved. We will use C instead of G.C, cb instead G.cb and ct instead of G.ct in this paragraph. To do this, it is rst proved that P12 : qsq+N

is invariant. One part of P12, s q + N, holds because s < q + N is a correct preassertion of s := s + 1: all elements added to Rcvd are smaller than q + N, and q doesnt decrease. To prove the invariance of the other part of P12, q s, these invariants are rst proved: P13 : C[0..ct) Rcvd P14 : ( j : [0.. j ) C[0...ct) : j s) The proof for the invariance of P13 is trivial, since p Rcvd is a valid preassertion of G.Send( p), and set Rcvd never shrinks. Invariant P14 holds initially and can be disturbed by increasing ct, as happens in G.Send( p). Valid preassertions of the increase of ct are s Rcvd, p Rcvd and / C.ct = p. P14(ct := ct + 1) {substi tuti on } ( j : [0.. j ) C[0 .. ct +1) : j s) { P13 C.ct Rcvd } ( j : [0.. j ) Rcvd : j s) { P10, s Rcvd, set theor y } / tr ue which proves the invariance of P14. The remaining part of P12 is easy to prove with P14: P14 { P6 } ( j : [0.. j ) Ackd : j s) { P3 } qs 24

Using P12, some unnecessary content can be removed from channel G: since s q + N and [0..q) Ackd (see P3), it is not necessary to send acknowledgements for indices smaller than s N. Therefore B is modied as follows: B: [ ; ; F.Recei ve( p) {0 p < q + N } Rcvd := Rcvd {p} do s Rcvd s := s + 1 od if p s N G.Send( p) p < s N ski p

] The following is now invariant: P15 : ( j : 0 j < ct : ( i : [0..i ) C[0 .. j +1) : i ) N C. j )

Invariant P15 holds initially, and is not disturbed by the increase of ct in G.Send( p) (valid preassertions of that increase are C.ct = p, p sN, p Rcvd and s Rcvd): / P15(ct := ct + 1) {substi tuti on } ( j : 0 j < ct +1 : ( i : [0..i ) C[0 .. j +1) : i ) N C. j ) {spli t o ff j = ct, P15 } ( i : [0..i ) C[0 .. ct +1) : i ) N C.ct { P12 C.ct = p p Rcvd } ( i : [0..i ) Rcvd : i ) N p { P10 s Rcvd } / sN p { p sN } tr ue

P15 can be used to prove that this invariant holds: P16 : (i : (ct M) 0 i < ct : q N M C.i )

For ct M the invariance of P16 is easy to see, because P3 P6 ct M q M q N M < 0, and C contains only natural numbers. For ct > M, The proof is by induction on M. For P16(M := 1): P16(M := 1) {substi tuti on, ct > M } (i : ct 1 i < ct : q N 1 C.i ) {si ngle poi nt domai n } q N 1 C.(ct 1) { P3 P6 } ( i : [0..i ) C[0 .. ct) : i ) N 1 C.(ct 1) { P15 } tr ue 25

For P16(M := M +1), assuming P16 holds: P16(M := M +1) {substi tuti on, ct M +1 } (i : ct M 1 i < ct : q N M 1 C.i ) {spli t o f f i = ct M 1, P16 } q N M 1 C.(ct M 1) { P15 } q N M 1 ( i : [0..i ) C[0 .. ct M) : i ) N {algebr a } q ( i : [0..i ) C[0 .. ct M) : i ) 1 M {set theor y } [ ( i : [0..i ) C[0 .. ct M) : i )+1 .. q ) C[ct M .. ct) {de f. , set theor y } [ ( i : [0..i ) C[0 .. ct M) : i )+1 .. q ) C[0..ct) ( P3 P6 } tr ue

3.5.3 Implementing cyclic indices


A valid postassertion of the assignment to p in F.Recei ve( p) in B is p F.C[ (ct M) 0 .. ct ). This implies: p F.C[ (ct M) 0 .. ct ) { P14, P11, p < q + N } sN M < p < s+N {algebr a } 0 < p+ N + M s < 2N + M

Knowing this, an important coassertion can be derived: p = = = = = {algebr a } s (N + M) + ( p+ N + M s) {0 < p+ N + M s < 2N + M } s (N + M) + ( p+ N + M s) mod (2N + M) {0 < N + M < 2N + M } s ((N + M) mod (2N + M)) + ( p+ N + M s) mod (2N + M) {modular ari thmeti c } s + ( ps) mod (2N + M) {modular ari thmeti c } s + ( p mod (2N + M)s) mod (2N + M)

In other words, p can be calculated from p mod (2N + M). Because P16 is invariant, a similar assertion r = q + (r mod (2N +M)q) mod (2N +M) can be derived from the postassertion r G.C[ct M .. ct) of the assignment to r in G.Recei ve(r ) in A1. It therefore sufces to send indices over channels F and G that are reduced modulo (2N + M): 26

A1 : ; ; ;

G.Recei ve(r ) r := q + (r q) mod (2N + M) {0 r < q + N } Ackd := Ackd {r } do q Ackd q := q + 1 od if [0 .. q + N)\AckdCopy = ski p { [0 .. q + N)\AckdCopy = } t : t [0 .. q + N) \ AckdCopy {0 t < q + N } F.Send(t mod (2N + M) ) AckdCopy, qCopy := Ackd, q F.Recei ve( p) p := s + ( ps) mod (2N + M) {0 p < q + N } Rcvd := Rcvd {p} do s Rcvd s := s + 1 od if p s N G.Send( p mod (2N + M) ) p < s N ski p

A2 : ; ; ; B: [ ; ;

3.6 Limiting the size of sets


Until now, it was assumed that setsAckd, AckdCopy and Rcvd have no upper bound on their size. Can we limit the size of these sets? There exists a set Ackd N such that Ackd N = Ackd\[0..q) that never grows larger than N elements (because of P2). Because [0..q) Ackd holds (according to P3), Ackd = [0..q) Ackd N and it is sufcient to maintain set Ackd N. Knowing this, A1 can be changed so that Ackd N is maintained instead of Ackd. Note that q [0..q) Ackd N equals q Ackd N.

27

A1 : ; ;

G.Recei ve(r ) r := q + (r q) mod (2N + M) { X.r = Y.r 0 r < q + N } if q r Ackd N := Ackd N {r } q > r ski p do q Ackd N { X.q = Y.q } ; q, Ackd N := q + 1, Ackd N\{q} od

The size of set AckdCopy can be limited in the same way: it is obvious that there exists a set AckdCopy N = AckdCopy\[0..qCopy), where AckdCopy = AckdCopy N [0..qCopy) (because of P8), and it sufces to maintain AckdCopy N. The only statement in A that affects AckdCopy N is AckdCopy, qCopy := Ackd N [0..q), q, for which this holds: = = = AckdCopy N( AckdCopy, qCopy := Ackd N [0..q), q ) { De f. AckdCopy N, substi tuti on } (Ackd N [0..q)) \ [0..q) {set theor y } Ackd N\[0..q) {de f. Ackd N } Ackd N

A2 can now be rewritten to (note that [0 .. q+N) \ AckdCopy = [0 .. q+N) \ ( AckdCopy N [0..qCopy) ) can be simplied to [qCopy .. q + N) \ AckdCopy N): A2 : ; ; ; if [qCopy .. q + N) \ AckdCopy N = ski p { [qCopy .. q + N) \ AckdCopy N = } t : t [qCopy .. q + N) \ AckdCopy N { X.t = X.t 0 t < q + N } F.Send( X.t, t mod (2N + M) ) AckdCopy N, qCopy := Ackd N, q

Because AckdCopy N is a copy of Ackd N, it will contain at most N elements. The same tactic used to create the Ackd N set can also be used to create a set Rcvd N = Rcvd\[0..s), where Rcvd = Rcvd N [0..s) because of P10. Rcvd N will contain at most N elements, because P9 P5 P12 (i : i Rcvd : i < s + N).

28

Rcvd N is maintained as follows: B : [ ; F.Recei ve( p) p := s + ( ps) mod (2N + M) {0 p < q + N } if p s Rcvd N := Rcvd N {p} p < s ski p do s Rcvd N s, Rcvd N := s + 1, Rcvd N\s od if p s N G.Send( p mod (2N + M) ) p < s N ski p

29

Chapter 4

Summary and conclusions


4.1 Summary
In this thesis, we have shown how to model faulty channels that can reorder, lose and duplicate messages as multiprograms. The modelled channels are nitely faulty; there is a limit to the number of messages that can be consecutively lost or duplicated. Using this model, we have derived a provably correct protocol that enables the reliable transfer of a data stream from one machine to another machine over a faulty channel. We have proven that the protocol exhibits progress. Furthermore, we have proven that it is possible to limit the memory requirements of the protocol by recycling the indices contained in the messages that the protocol transfers, and by limiting the size of the sets that the protocol maintains.

4.2 Comparison to existing research


We compare our research to two existing papers that give a correctness proof of a sliding window protocol.

4.2.1 Research of J.L.A. van de Snepscheut


In [Sne95], J.L.A. van de Snepscheut derives a sliding window protocol by developing a sequential program and distributing the statements and variables of the sequential program over a number of processes. This has the advantage of being able to use the usual proof techniques for the sequential program, without worries about global correctness of assertions. A disadvantage is that this method is not formalized, where the Owicki/Gries-theory used in this thesis is well-documented (see [OG76], [FG99]). Van de Snepscheut also gives a program that implements a faulty channel, but it is assumed that messages sent over such a channel arrive in the order in which they are sent (the channel has the FIFO-property), where we assume that messages can be reordered. The program relies on fairness of the scheduler to assure that only a nite number of messages can be lost or duplicated consecutively, where we make this 30

explicit by using natural numbers that represent the number of messages that can be lost and duplicated consecutively (see 2.5.1 and 2.5.2). The protocol developed in [Sne95] sends a (reduced) set of all received indices as an acknowledgement, while our protocol sends only a single index. Sending a set could be a more efcient solution, because if an acknowledgement is lost, the next received acknowledgement will contain a superset of the lost acknowledgement (because the channels are FIFO). Even if the channels are not FIFO, the acknowledgements still carry more information and might increase efciency. Van de Snepscheut also proves that indices can be reduced modulo 2N; the result can be compared to our own result of 2N + M if we use M = 1 (which is equal to a FIFO-channel). The difference of 1 can be explained by taking into account that only channel G requires the wider 2N + M reduction (channel F will do with 2N +(M 1), as can be seen from invariants P11, P5 and P12). If the assumption is made that F and G are both FIFO, G can also be reduced modulo 2N. There is a proof of progress given for the sequential program that is rst developed, using a variant function; it is explained that the nal, distributed program meets the progress requirements of the original sequential program, because of the method used to partition the sequential program into processes.

4.2.2 Research of N.V. Stenning


In [Ste76], N.V. Stenning gives an a posteriori correctness proof of a sliding window protocol. The protocol uses faulty channels that have the same properties as in this thesis. The channels are not modeled as programs. The proof is established using a number of invariants, although most of these invariants are not explicitly proven in the paper this thesis is more complete in that respect. These invariants are also used to prove that it is possible recycle indices by reducing them modulo (tr ansmi twi ndow + ((M + r ecei vewi ndow) (tr ansmi twi ndow)), where tr ansmi twi ndow is equal to constant N in this thesis, and r ecei vewi ndow is the size of a separate receiver window that buffers received messages that have not yet been output (comparable to Y [s .. s + N) in our protocol). This is equal to the conclusion in this paper that indices can be reduced modulo 2N + M if r ecei vewi ndow = tr ansmi twi ndow = N (the author mentions in the conclusion that in practice, M + tr ansmi twi ndow + r ecei vewi ndow is always a satisfactory cycle period for the indices if one is not concerned with whether a received message lies in the receiver window). Stenning gives no proof of progress in his paper.

4.3 Conclusions
The proof-by-design methods explored in [FG99] can be employed to develop a sliding window protocol, and lead to a complete proof of correctness. By using a step-by-step approach to developing the protocol, working from the

31

desired result to the solution, an elegant implementation can be obtained where the structure of the design can be explained in a clear manner. By modelling the faulty channels, their properties have been formalized, enabling a more formal proof of correctness and progress of the nal protocol. The faulty channels model can be used to prove that the rule of import and export applies to faulty channels, which makes it easier to prove properties of the messages transferred over the channels without introducing more system invariants. Proving that indices can be recycled requires proving a substantial number of invariants that are not necessary to prove the correctness of the protocol when indices are not recycled.

4.4 Recommendations for future research


We have mostly ignored discussions about the performance of the protocol in this thesis. In particular, the method that is used to choose an element to be sent from the current window has been left unspecied. Further research is necessary to investigate how the performance of the protocol is affected by using different methods for choosing this element. Using a set of indices as acknowledgements instead of a single index, like in [Sne95], could also affect the performance.

32

Bibliography
[OG76] S. Owicki and D. Gries, An Axiomatic Proof Technique for Parallel Programs I, Acta Informatica, Vol. 6, pp. 319-340, 1976. [FG99] W.H.J. Feijen and A.J.M. van Gasteren, On a method of multiprogramming, Springer Verlag, 1999. [Sne95] J.L.A. van de Snepscheut, The Sliding-Window Protocol Revisited, Formal Aspects of Computing, Vol. 7, pp. 3-17, 1995. [Ste76] N.V. Stenning, A data transfer protocol, Computer Networks, Vol. 1, pp. 99110, 1976.

33

Você também pode gostar