/*
*PROMELAValidationModel
*协议层验证
*
*验证BCL可靠性协议Aversion5.0
*
*Yuhuang
*2007-7-26
*/
/*
*本版本特点:采用集合点来通信,允许ACK、DATA丢包,实现了队列自动重发。
*加入了对传输介质的模拟。介质可以丢包,导致包失序。
*
*未完全模拟的问题:ACK、DATA失序问题
*/
/* *************数据结构定义************ */
/* 序号范围定义 */
# defineWIN9
/* 发送队列大小定义 */
# defineQSIZE4
/* 消息类型定义 */
mtype = {ACK , DATA}
/*
*{ACK,s_seqno}
*/
chansevts = [ 0 ]of{mtype , byte};
chanrevts = [ 0 ]of{mtype , byte};
/*
*{DATA,r_seqno}
*数据队列
*/
chansdata = [ 0 ]of{mtype , byte};
chanrdata = [ 0 ]of{mtype , byte};
/* 发送记录队列 */
/* 当ACK发生的时候,ACK(含)之前的内容都被清除 */
bytehead_seq;
bytetail_seq;
bytecur_seq;
/*
#defineinc(x)(x=(x+1)%WIN)
*/
proctypesender2media()
{
byteseq;
do
:: sdata ? DATA , seq ->
if
:: rdata ! DATA , seq
:: skip
fi
od
}
proctypereceiver2media()
{
byteseq;
do
:: revts ? ACK , seq ->
if
:: sevts ! ACK , seq
:: skip
fi
od
}
proctypesender(byteid)
{
bytes;
head_seq = 0 ;
tail_seq = 0 ;
cur_seq = 0 ;
do
:: (tail_seq + WIN - head_seq + 1 ) % WIN != QSIZE -> /* 队列不为满,允许发送 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
progress_2 : cur_seq = (cur_seq + 1 ) % WIN;
tail_seq = (tail_seq + 1 ) % WIN;; /* 更新tail,head保持不变 */
:: sevts ? ACK , s ->
/* 进行ACK失序处理 */
/* 若s不在当前的head_seq~tail_seq范围内,则简单忽略之 */
if
:: (head_seq < tail_seq) -> /* 顺序递增情景 */
if
:: (s > tail_seq || s < head_seq) ->
gotoendofack
:: else
fi
:: (head_seq > tail_seq) -> /* 非递增情景 */
if
:: (s < head_seq && s > tail_seq) ->
gotoendofack
:: else
fi
:: else
fi;
assert (s < WIN);
head_seq = (s + 1 ) % WIN; /* 根据ACK更新head_seq,暗含了累积更新 */
cur_seq = head_seq;
endofack : skip
:: ((cur_seq != tail_seq) && (tail_seq - head_seq) != 0 ) ->
/* 队列不为空,允许发送.此情景配合timeout时重发使用 */
/* 第一个判断是为了防止发送不存在内容 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
cur_seq = (cur_seq + 1 ) % WIN;
:: timeout -> /* 超时 */
/* 更新指针,准备重发队列 */
cur_seq = head_seq;
/* 尝试重发队列 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
cur_seq = (cur_seq + 1 ) % WIN; /* 发送了一个包,更新cur_seq */
/* 这里不用更新tail_seq,因为这个值只在有新的包加入到队列的时候才更新 */
od
}
proctypereceiver(byteid)
{
byteexpected_seqno;
bytes;
expected_seqno = 0 ;
do
:: rdata ? DATA , s ->
if
:: (s != expected_seqno) -> /* 非期望数据包 */
if
:: revts ! ACK , (expected_seqno + WIN - 1 ) % WIN /* someackswaslost,ackagain! */
fi
:: (s == expected_seqno) -> /* 期望数据包 */
if
:: revts ! ACK , expected_seqno -> /* ack */
expected_seqno = (expected_seqno + 1 ) % WIN
fi
fi
od
}
init
{
atomic{
runsender( 0 );
runsender2media();
runreceiver( 1 );
runreceiver2media();
}
}
*PROMELAValidationModel
*协议层验证
*
*验证BCL可靠性协议Aversion5.0
*
*Yuhuang
*2007-7-26
*/
/*
*本版本特点:采用集合点来通信,允许ACK、DATA丢包,实现了队列自动重发。
*加入了对传输介质的模拟。介质可以丢包,导致包失序。
*
*未完全模拟的问题:ACK、DATA失序问题
*/
/* *************数据结构定义************ */
/* 序号范围定义 */
# defineWIN9
/* 发送队列大小定义 */
# defineQSIZE4
/* 消息类型定义 */
mtype = {ACK , DATA}
/*
*{ACK,s_seqno}
*/
chansevts = [ 0 ]of{mtype , byte};
chanrevts = [ 0 ]of{mtype , byte};
/*
*{DATA,r_seqno}
*数据队列
*/
chansdata = [ 0 ]of{mtype , byte};
chanrdata = [ 0 ]of{mtype , byte};
/* 发送记录队列 */
/* 当ACK发生的时候,ACK(含)之前的内容都被清除 */
bytehead_seq;
bytetail_seq;
bytecur_seq;
/*
#defineinc(x)(x=(x+1)%WIN)
*/
proctypesender2media()
{
byteseq;
do
:: sdata ? DATA , seq ->
if
:: rdata ! DATA , seq
:: skip
fi
od
}
proctypereceiver2media()
{
byteseq;
do
:: revts ? ACK , seq ->
if
:: sevts ! ACK , seq
:: skip
fi
od
}
proctypesender(byteid)
{
bytes;
head_seq = 0 ;
tail_seq = 0 ;
cur_seq = 0 ;
do
:: (tail_seq + WIN - head_seq + 1 ) % WIN != QSIZE -> /* 队列不为满,允许发送 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
progress_2 : cur_seq = (cur_seq + 1 ) % WIN;
tail_seq = (tail_seq + 1 ) % WIN;; /* 更新tail,head保持不变 */
:: sevts ? ACK , s ->
/* 进行ACK失序处理 */
/* 若s不在当前的head_seq~tail_seq范围内,则简单忽略之 */
if
:: (head_seq < tail_seq) -> /* 顺序递增情景 */
if
:: (s > tail_seq || s < head_seq) ->
gotoendofack
:: else
fi
:: (head_seq > tail_seq) -> /* 非递增情景 */
if
:: (s < head_seq && s > tail_seq) ->
gotoendofack
:: else
fi
:: else
fi;
assert (s < WIN);
head_seq = (s + 1 ) % WIN; /* 根据ACK更新head_seq,暗含了累积更新 */
cur_seq = head_seq;
endofack : skip
:: ((cur_seq != tail_seq) && (tail_seq - head_seq) != 0 ) ->
/* 队列不为空,允许发送.此情景配合timeout时重发使用 */
/* 第一个判断是为了防止发送不存在内容 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
cur_seq = (cur_seq + 1 ) % WIN;
:: timeout -> /* 超时 */
/* 更新指针,准备重发队列 */
cur_seq = head_seq;
/* 尝试重发队列 */
if
:: sdata ! DATA , cur_seq /* normalsendaction */
fi;
cur_seq = (cur_seq + 1 ) % WIN; /* 发送了一个包,更新cur_seq */
/* 这里不用更新tail_seq,因为这个值只在有新的包加入到队列的时候才更新 */
od
}
proctypereceiver(byteid)
{
byteexpected_seqno;
bytes;
expected_seqno = 0 ;
do
:: rdata ? DATA , s ->
if
:: (s != expected_seqno) -> /* 非期望数据包 */
if
:: revts ! ACK , (expected_seqno + WIN - 1 ) % WIN /* someackswaslost,ackagain! */
fi
:: (s == expected_seqno) -> /* 期望数据包 */
if
:: revts ! ACK , expected_seqno -> /* ack */
expected_seqno = (expected_seqno + 1 ) % WIN
fi
fi
od
}
init
{
atomic{
runsender( 0 );
runsender2media();
runreceiver( 1 );
runreceiver2media();
}
}