[Coral-dev] Sequence number arithmetic in perl

David Moore dmoore@caida.org
Wed, 20 Nov 2002 13:11:56 -0800


On Wed, Nov 20, 2002 at 08:03:59PM +0200, Markus Peuhkuri wrote:
> David Moore writes:
>  > Why are you using `use integer'?  performance?
> 
> Performance is not an issue as this is just proof-of-concept trial.
> I'm not sure about this, but based on perl docs perl uses signed ints,
> and if the number is larger than 2**31-1, it gets "promoted" to float.
> 
> Actually, if I have code like:
> my $tcp_up = new Unpacker("tcp", [ "th_sport", "th_dport", "th_seq",
> 		    "th_ack", "th_off", "th_flags" ]);
> ...
>   my($th_sport, $th_dport, $th_seq, $th_ack, $th_off, $th_flags) 
>       = $tcp_up->unpack($ip_record, $ip_hl * 4);
> 
> then $th_seq, $th_ack are *negative* values (if they are larger than
> 2**31-1).

Oh, we should have made th_seq (and th_ack) unsigned.   probably
easiest thing to do is:

my($th_sport, $th_dport, $th_seq, $th_ack, $th_off, $th_flags)
    = $tcp_up->unpack($ip_record, $ip_hl * 4);
if ($th_seq < 0) { $th_seq += 2**32; }
if ($th_ack < 0) { $th_ack += 2**32; }

The double representation used holds more than 32 bits of precision,
so this is fine to do.  Then you can just do the comparisons you
want.  Although you still have to be careful about when sequence
numbers actually wrap, which is why there is no generic way to
provide the perl-routines you want.  ie, seq#100 is the expected next
number after seq#4294965936 with 1500 byte MTU.

> What i'm looking for is perl-routines for 
> int before(u32 seq1, u32 seq2);
> int after(u32 seq1, u32 seq2);
> /* is s2<=s1<=s3 ? */
> int between(u32 seq1, u32 seq2, u32 seq3)
> int difference(u32 seq1, u32 seq2);