You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							213 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							213 lines
						
					
					
						
							5.5 KiB
						
					
					
				| // Modest PTA model of the bounded retransmission protocol (BRP) | |
| // [HH09], http://www.modestchecker.net/CaseStudies/BRP/ | |
| action put, get, put_k, get_k, put_l, get_l; | |
| action new_file; | |
| action s_ok, s_dk, s_nok, s_restart; | |
| action r_ok, r_inc, r_fst, r_nok, r_timeout; | |
| exception error; | |
| 
 | |
| const int N = 16; // number of frames per file | |
| const int MAX = 2; // maximum number of retransmissions per frame | |
| const int TD = 1; // transmission delay | |
| const int TS = 2 * TD + 1; // sender timeout | |
| const int TR = 2 * MAX * TS + 3 * TD; // receiver timeout | |
| const int SYNC = TR; | |
| 
 | |
| bool ff, lf, ab; // channel data: first/last frame, alternating bit | |
| int(0..N) i; // sender chunk counter | |
| bool inTransitK = false; | |
| bool inTransitL = false; | |
| 
 | |
| bool first_file_done = false; | |
| bool get_k_seen, s_ok_seen, s_nok_seen, s_dk_seen, s_restart_seen, r_ok_seen, r_timeout_seen; | |
| 
 | |
| // Invariant (timed) properties (from [BrpOnTime], the TA model) | |
| bool premature_timeout, channel_k_overflow, channel_l_overflow; | |
| // "there is at most one message in transit for each channel" | |
| property T_1 = A[] (!(channel_k_overflow || channel_l_overflow)); | |
| // "there is at most one message in transit in total" | |
| property T_2 = A[] (!(inTransitK && inTransitL)); | |
| // Assumption (A1): "no premature timeouts" | |
| property T_A1 = A[] (!premature_timeout); | |
| // Assumption (A2): "sender starts new file only after receiver reacted to failure" | |
| // Note that receiver can only notice failure if it received at least one chunk, i.e. get_k_seen | |
| property T_A2 = A[] (!s_restart_seen || !get_k_seen || r_timeout_seen); | |
| 
 | |
| // Probabilistic reachability properties (from [D'AJJL01], the RAPTURE/PRISM model) | |
| // property A of [D'AJJL01]: "the maximum probability that eventually the sender reports  | |
| // a certain unsuccessful transmission but the receiver got the complete file" | |
| property P_A = Pmax(<>(s_nok_seen && r_ok_seen)); | |
| // property B of [D'AJJL01]: "the maximum probability that eventually the sender reports | |
| // a certain successful transmission but the receiver did not get the complete file" | |
| property P_B = Pmax(<>(s_ok_seen && !r_ok_seen)); | |
| // property 1 of [D'AJJL01]: "the maximum probability that eventually the sender | |
| // does not report a successful transmission" | |
| property P_1 = Pmax(<>(s_nok_seen || s_dk_seen)); | |
| // property 2 of [D'AJJL01]: "the maximum probability that eventually the sender | |
| // reports an uncertainty on the success of the transmission" | |
| property P_2 = Pmax(<>(s_dk_seen)); | |
| // property 3 of [D'AJJL01]: "the maximum probability that eventually the sender | |
| // reports an unsuccessful transmission after more than 8 chunks have been sent successfully" | |
| property P_3 = Pmax(<>(s_nok_seen && i > 8)); | |
| // property 4 of [D'AJJL01]: "the maximum probability that eventually the receiver | |
| // does not receive any chunk and the sender tried to send a chunk" | |
| property P_4 = Pmax(<>((s_ok_seen || s_nok_seen || s_dk_seen) && !get_k_seen)); | |
| 
 | |
| 
 | |
| process Sender() | |
| { | |
| 	bool bit; | |
| 	int(0..MAX) rc; | |
| 	clock c; | |
| 
 | |
| 	try | |
| 	{ | |
| 		do { | |
| 		::	when urgent(i < N) {= i++ =}; | |
| 			do | |
| 			{ | |
| 				// send frame | |
| 				invariant(c <= 0) put_k {= ff = (i == 1), lf = (i == N), ab = bit, c = 0 =}; | |
| 				invariant(c <= TS) alt { | |
| 				::	// receive ack | |
| 					get_l {= bit = !bit, rc = 0, c = 0 =}; | |
| 					urgent break | |
| 				:: // timeout | |
| 					when(c >= TS) | |
| 					if(rc < MAX) | |
| 					{ | |
| 						// retry | |
| 						{= rc++, c = 0 =} | |
| 					} | |
| 					else if(i < N) | |
| 					{ | |
| 						// no retries left | |
| 						s_nok {= rc = 0, c = 0 =}; | |
| 						urgent throw(error) | |
| 					} | |
| 					else | |
| 					{ | |
| 						// no retries left | |
| 						s_dk {= rc = 0, c = 0 =}; | |
| 						urgent throw(error) | |
| 					} | |
| 				} | |
| 			} | |
| 		::	when(i == N) | |
| 			// file transmission successfully completed | |
| 			invariant(c <= 0) s_ok {= first_file_done = true =}; | |
| 			urgent break | |
| 		} | |
| 	} | |
| 	catch error | |
| 	{ | |
| 		// File transfer did not succeed: wait, then restart with next file | |
| 		invariant(c <= SYNC) when(c >= SYNC) | |
| 		s_restart {= bit = false, first_file_done = true =} | |
| 	} | |
| } | |
| 
 | |
| process Receiver() | |
| { | |
| 	bool r_ff, r_lf, r_ab; | |
| 	bool bit; | |
| 	clock c; | |
| 
 | |
| 	// receive first frame | |
| 	if(ff) { get_k {= c = 0, bit = ab, r_ff = ff, r_lf = lf, r_ab = ab =} } | |
| 	else { get_k {= c = 0, premature_timeout = true =}; stop }; | |
| 	do | |
| 	{ | |
| 		invariant(c <= 0) | |
| 		{ | |
| 			if(r_ab != bit) | |
| 			{ | |
| 				// repetition, re-ack | |
| 				put_l | |
| 			} | |
| 			else | |
| 			{ | |
| 				// report frame | |
| 				if(r_lf)      { r_ok } | |
| 				else if(r_ff) { r_fst } | |
| 				else          { r_inc }; | |
| 				put_l {= bit = !bit =} | |
| 			} | |
| 		}; | |
| 		invariant(c <= TR) | |
| 		{ | |
| 			alt { | |
| 			::	// receive next frame | |
| 				get_k {= c = 0, r_ff = ff, r_lf = lf, r_ab = ab =} | |
| 			::	// timeout | |
| 				when(c == TR) | |
| 				if(r_lf) | |
| 				{ | |
| 					// we just got the last frame, though | |
| 					r_timeout; break | |
| 				} | |
| 				else | |
| 				{ | |
| 					r_nok; | |
| 					// abort transfer | |
| 					r_timeout; break | |
| 				} | |
| 			} | |
| 		} | |
| 	}; | |
| 	Receiver() | |
| } | |
| 
 | |
| process ChannelK() | |
| { | |
| 	clock c; | |
| 
 | |
| 	put_k palt | |
| 	{ | |
| 		:98:	{= c = 0, inTransitK = true =}; | |
| 				invariant(c <= TD) alt { | |
| 				::	get_k {= inTransitK = false =} | |
| 				::	put_k {= channel_k_overflow = true =}; stop | |
| 				} | |
| 		: 2:	{==} | |
| 	}; | |
| 	ChannelK() | |
| } | |
| 
 | |
| process ChannelL() | |
| { | |
| 	clock c; | |
| 
 | |
| 	put_l palt | |
| 	{ | |
| 		:99:	{= c = 0, inTransitL = true =}; | |
| 				invariant(c <= TD) alt { | |
| 				::	get_l {= inTransitL = false =} | |
| 				::	put_l {= channel_l_overflow = true =}; stop | |
| 				} | |
| 		: 1:	{==} | |
| 	}; | |
| 	ChannelL() | |
| } | |
| 
 | |
| process Observer() | |
| { | |
| 	alt { | |
| 	::	get_k     {= get_k_seen     = true =} | |
| 	::	s_ok      {= s_ok_seen      = true =} | |
| 	::	s_nok     {= s_nok_seen     = true =} | |
| 	::	s_dk      {= s_dk_seen      = true =} | |
| 	::	s_restart {= s_restart_seen = true =} | |
| 	::	r_ok      {= r_ok_seen      = true =} | |
| 	::	r_timeout {= r_timeout_seen = true =} | |
| 	}; | |
| 	Observer() | |
| } | |
| 
 | |
| par { | |
| ::	Sender() | |
| ::	Receiver() | |
| ::	ChannelK() | |
| ::	ChannelL() | |
| ::	Observer() | |
| }
 |