// IPv4: PTA model with digitial clocks // one concrete host attempting to choose an ip address // when a number of (abstract) hosts have already got ip addresses // gxn/dxp/jzs 02/05/03 // reset or noreset model const bool reset=true; //------------------------------------------------------------- // we suppose that // - the abstract hosts have already picked their addresses // and always defend their addresses // - the concrete host never picks the same ip address twice // (this can happen only with a verys small probability) // under these assumptions we do not need message types because: // 1) since messages to the concrete host will never be a probe, // this host will react to all messages in the same way // 2) since the abstract hosts always defend their addresses, // all messages from the host will get an arp reply if the ip matches // following from the above assumptions we require only three abstract IP addresses // (0,1 and 2) which correspond to the following sets of IP addresses: // 0 - the IP addresses of the abstract hosts which the concrete host // previously tried to configure // 1 - an IP address of an abstract host which the concrete host is // currently trying to configure // 2 - a fresh IP address which the concrete host is currently trying to configure // if the host picks an address that is being used it may end up picking another ip address // in which case there may still be messages corresponding to the old ip address // to be sent both from and to the host which the host should now disregard // (since it will never pick the same ip address) // to deal with this situation: when a host picks a new ip address we reconfigure the // messages that are still be be sent or are being sent by changing the ip address to 0 // (an old ip address of the host) // all the messages from the abstract hosts for the 'old' address (in fact the // set of old addresses since it may have started again more than once) // can arrive in any order since they are equivalent to the host - it ignores then all // also the messages for the old and new address will come from different hosts // (the ones with that ip address) which we model by allowing them to arrive in any order // i.e. not neccessarily in the order they where sent //------------------------------------------------------------- // model is an pta pta //------------------------------------------------------------- // VARIABLES const int N=1000; // number of abstract hosts const int K=2; // number of probes to send const double loss = 0.1; // probability of message loss // PROBABILITIES const double old = N/65024; // probability pick an ip address being used const double new = (1-old); // probability pick a new ip address // TIMING CONSTANTS const int CONSEC = 2; // time interval between sending consecutive probles const int TRANSTIME = 1; // upper bound on transmission time delay const int LONGWAIT = 60; // minimum time delay after a high number of address collisions const int DEFEND = 10; const int TIME_MAX_X = 60; // max value of clock x const int TIME_MAX_Y = 10; // max value of clock y const int TIME_MAX_Z = 1; // max value of clock z // OTHER CONSTANTS const int MAXCOLL = 10; // maximum number of collisions before long wait // size of buffers for other hosts const int B0 = 20; // buffer size for one abstract host const int B1 = 8; // buffer sizes for all abstract hosts //------------------------------------------------------------- // ENVIRONMENT - models: medium, output buffer of concrete host and all other hosts module environment // buffer of concrete host b_ip7 : [0..2]; // ip address of message in buffer position 8 b_ip6 : [0..2]; // ip address of message in buffer position 7 b_ip5 : [0..2]; // ip address of message in buffer position 6 b_ip4 : [0..2]; // ip address of message in buffer position 5 b_ip3 : [0..2]; // ip address of message in buffer position 4 b_ip2 : [0..2]; // ip address of message in buffer position 3 b_ip1 : [0..2]; // ip address of message in buffer position 2 b_ip0 : [0..2]; // ip address of message in buffer position 1 n : [0..8]; // number of places in the buffer used (from host) // messages to be sent from abstract hosts to concrete host n0 : [0..B0]; // number of messages which do not have the host's current ip address n1 : [0..B1]; // number of messages which have the host's current ip address b : [0..2]; // local state // 0 - idle // 1 - sending message from concrete host // 2 - sending message from abstract host z : clock; // clock of environment (needed for the time to send a message) ip_mess : [0..2]; // ip in the current message being sent // 0 - different from concrete host // 1 - same as the concrete host and in use // 2 - same as the concrete host and not in use invariant (b=0 & n=0 & n0=0 & n1=0 => true) & // nothing to send (b=0 & !(n=0 & n0=0 & n1=0) => z<=0) & // something to send (b>0 => z<=1) // sending endinvariant // RESET/RECONFIG: when host is about to choose new ip address // suppose that the host cannot choose the same ip address // (since happens with very small probability). // Therefore all messages will have a different ip address, // i.e. all n1 messages become n0 ones. // Note this include any message currently being sent (ip is set to zero 0) [reset] true -> (n1'=0) & (n0'=min(B0,n0+n1)) // abstract buffers & (ip_mess'=0) // message being set & (n'=(reset)?0:n) // concrete buffer (remove this update to get NO_RESET model) & (b_ip7'=0) & (b_ip6'=0) & (b_ip5'=0) & (b_ip4'=0) & (b_ip3'=0) & (b_ip2'=0) & (b_ip1'=0) & (b_ip0'=0); // note: prevent anything else from happening when reconfiguration needs to take place // get messages to be sent (so message has same ip address as host) [send1] n=0 -> (b_ip0'=1) & (n'=n+1); [send1] n=1 -> (b_ip1'=1) & (n'=n+1); [send1] n=2 -> (b_ip2'=1) & (n'=n+1); [send1] n=3 -> (b_ip3'=1) & (n'=n+1); [send1] n=4 -> (b_ip4'=1) & (n'=n+1); [send1] n=5 -> (b_ip5'=1) & (n'=n+1); [send1] n=6 -> (b_ip6'=1) & (n'=n+1); [send1] n=7 -> (b_ip7'=1) & (n'=n+1); [send1] n=8 -> (n'=n); // buffer full so lose message [send2] n=0 -> (b_ip0'=2) & (n'=n+1); [send2] n=1 -> (b_ip1'=2) & (n'=n+1); [send2] n=2 -> (b_ip2'=2) & (n'=n+1); [send2] n=3 -> (b_ip3'=2) & (n'=n+1); [send2] n=4 -> (b_ip4'=2) & (n'=n+1); [send2] n=5 -> (b_ip5'=2) & (n'=n+1); [send2] n=6 -> (b_ip6'=2) & (n'=n+1); [send2] n=7 -> (b_ip7'=2) & (n'=n+1); [send2] n=8 -> (n'=n); // buffer full so lose message // start sending message from host [a] b=0 & n>0 -> (1-loss) : (b'=1) & (ip_mess'=b_ip0) & (n'=n-1) & (b_ip7'=0) & (b_ip6'=b_ip7) & (b_ip5'=b_ip6) & (b_ip4'=b_ip5) & (b_ip3'=b_ip4) & (b_ip2'=b_ip3) & (b_ip1'=b_ip2) & (b_ip0'=b_ip1) // send message + loss : (n'=n-1) & (b_ip7'=0) & (b_ip6'=b_ip7) & (b_ip5'=b_ip6) & (b_ip4'=b_ip5) & (b_ip3'=b_ip4) & (b_ip2'=b_ip3) & (b_ip1'=b_ip2) & (b_ip0'=b_ip1); // lose message // start sending message to host [a] b=0 & n0>0 -> (1-loss) : (b'=2) & (ip_mess'=0) & (n0'=n0-1) + loss : (n0'=n0-1); // different ip [a] b=0 & n1>0 -> (1-loss) : (b'=2) & (ip_mess'=1) & (n1'=n1-1) + loss : (n1'=n1-1); // same ip // finish sending message from host [a] b=1 & ip_mess=0 -> (b'=0) & (z'=0) & (n0'=min(n0+1,B0)) & (ip_mess'=0); [a] b=1 & ip_mess=1 -> (b'=0) & (z'=0) & (n1'=min(n1+1,B1)) & (ip_mess'=0); [a] b=1 & ip_mess=2 -> (b'=0) & (z'=0) & (ip_mess'=0); // finish sending message to host [rec0] b=2 & ip_mess=0 -> (b'=0) & (z'=0) & (ip_mess'=0); [rec1] b=2 & ip_mess=1 -> (b'=0) & (z'=0) & (ip_mess'=0); [rec2] b=2 & ip_mess=2 -> (b'=0) & (z'=0) & (ip_mess'=0); endmodule //------------------------------------------------------------- // CONCRETE HOST module host0 x : clock; // first clock of the host y : clock; // second clock of the host coll : [0..MAXCOLL]; // number of address collisions probes : [0..K]; // counter (number of probes sent) mess : [0..1]; // need to send a message or not defend : [0..1]; // defend (if =1, try to defend IP address) ip : [1..2]; // ip address (1 - in use & 2 - fresh) l : [0..4] init 1; // location // 0 : RECONFIGURE // 1 : RANDOM // 2 : WAITSP // 3 : WAITSG // 4 : USE invariant (l=0 => x<=0) & (l=1 & coll x<=0) & (l=1 & coll=MAXCOLL => x<=LONGWAIT) & (l=2 => x<=CONSEC) & (l=3 => x<=CONSEC) & (l=4 => true) endinvariant // needed to prevent environment from moving before a reset [a] l>0 -> true; // RECONFIGURE [reset] l=0 -> (l'=1); // RANDOM (choose IP address) [rec0] (l=1) -> true; // get message (ignore since have no ip address) [rec1] (l=1) -> true; // get message (ignore since have no ip address) [rec2] (l=1) -> true; // get message (ignore since have no ip address) // small number of collisions (choose straight away) [] l=1 & coll 1/3*old : (l'=2) & (ip'=1) & (x'=0) + 1/3*old : (l'=2) & (ip'=1) & (x'=1) + 1/3*old : (l'=2) & (ip'=1) & (x'=2) + 1/3*new : (l'=2) & (ip'=2) & (x'=0) + 1/3*new : (l'=2) & (ip'=2) & (x'=1) + 1/3*new : (l'=2) & (ip'=2) & (x'=2); // large number of collisions: (wait for LONGWAIT) [] l=1 & coll=MAXCOLL & x=LONGWAIT -> 1/3*old : (l'=2) & (ip'=1) & (x'=0) + 1/3*old : (l'=2) & (ip'=1) & (x'=1) + 1/3*old : (l'=2) & (ip'=1) & (x'=2) + 1/3*new : (l'=2) & (ip'=2) & (x'=0) + 1/3*new : (l'=2) & (ip'=2) & (x'=1) + 1/3*new : (l'=2) & (ip'=2) & (x'=2); // WAITSP // send probe [send1] l=2 & ip=1 & probes=2 -> (x'=0) & (probes'=probes+1); [send2] l=2 & ip=2 & probes=2 -> (x'=0) & (probes'=probes+1); // sent K probes and waited 2 seconds [] l=2 & probes=K & x>=2 -> (l'=3) & (probes'=0) & (coll'=0) & (x'=0); // get message and ip does not match: ignore [rec0] l=2 & 0!=ip -> (l'=l); [rec1] l=2 & 1!=ip -> (l'=l); [rec2] l=2 & 2!=ip -> (l'=l); // get a message with matching ip: reconfigure [rec0] l=2 & 0=ip -> (l'=0) & (coll'=min(coll+1,MAXCOLL)) & (x'=0) & (probes'=0); [rec1] l=2 & 1=ip -> (l'=0) & (coll'=min(coll+1,MAXCOLL)) & (x'=0) & (probes'=0); [rec2] l=2 & 2=ip -> (l'=0) & (coll'=min(coll+1,MAXCOLL)) & (x'=0) & (probes'=0); // receive message and same ip: defend [rec0] l=3 & mess=0 & 0=ip & (defend=0 | y>=DEFEND) -> (defend'=1) & (mess'=1) & (y'=0); [rec1] l=3 & mess=0 & 1=ip & (defend=0 | y>=DEFEND) -> (defend'=1) & (mess'=1) & (y'=0); [rec2] l=3 & mess=0 & 2=ip & (defend=0 | y>=DEFEND) -> (defend'=1) & (mess'=1) & (y'=0); // receive message and same ip: defer [rec0] l=3 & mess=0 & 0=ip & (defend=0 | y (l'=0) & (probes'=0) & (defend'=0) & (x'=0) & (y'=0); [rec1] l=3 & mess=0 & 1=ip & (defend=0 | y (l'=0) & (probes'=0) & (defend'=0) & (x'=0) & (y'=0); [rec2] l=3 & mess=0 & 2=ip & (defend=0 | y (l'=0) & (probes'=0) & (defend'=0) & (x'=0) & (y'=0); // receive message and different ip [rec0] l=3 & mess=0 & 0!=ip -> (l'=l); [rec1] l=3 & mess=0 & 1!=ip -> (l'=l); [rec2] l=3 & mess=0 & 2!=ip -> (l'=l); // send probe reply or message for defence [send1] l=3 & mess=1 & ip=1 -> (mess'=0); [send2] l=3 & mess=1 & ip=2 -> (mess'=0); // send first gratuitous arp message [send1] l=3 & mess=0 & probes<1 & ip=1 & x>=CONSEC -> (x'=0) & (probes'=probes+1); [send2] l=3 & mess=0 & probes<1 & ip=2 & x>=CONSEC -> (x'=0) & (probes'=probes+1); // send second gratuitous arp message (move to use) [send1] l=3 & mess=0 & probes=1 & ip=1 & x>=CONSEC -> (l'=4) & (x'=0) & (y'=0) & (probes'=0); [send2] l=3 & mess=0 & probes=1 & ip=2 & x>=CONSEC -> (l'=4) & (x'=0) & (y'=0) & (probes'=0); // USE (only interested in reaching this state so do not need to add anything here) [] l=4 -> true; endmodule //------------------------------------------------------------- rewards "time" true : 1; endrewards label "done" = l=4; label "done_error" = l=4 & ip=0; label "done_fresh" = l=4 & ip=1;