cnet v2.0.5

simulation model

topology files
cmdline options
the API



The CnetInt64 datatype

As of v2.0, cnet supports a 64-bit integer datatype named CnetInt64 which is used to store all times (now in microseconds) and large statistics. The datatype and a number of arithmetic, conversion, and I/O routines are defined in the <cnet64bits.h> header file which, like the <cnet.h> header file (and included by it), is located via the value of CNETPATH. Some modern C compilers support 64-bit integers directly (in a variety of ways) and others don't. cnet attempts to hide the differences with the CnetInt64 datatype.

cnet uses the CnetInt64 datatype extensively itself (internally) and defines the node and link attributes of nodeinfo.messagerate, nodeinfo.time_in_usec, and linkinfo[i].propagationdelay to be of type CnetInt64. The second parameter to the CNET_start_timer() function is also of type CnetInt64.

Invoke the cnet simulator without any arguments. If your C compiler provides native support for the CnetInt64 datatype, then you can use the 64-bit integers as you would any others - in assignments, in arithmetic expressions, in Boolean comparisons, and in (most) I/O statements.

prompt> cnet

The cnet header file is /usr/local/cnetlib/cnet.h.
Protocols will be compiled with /usr/bin/gcc.
Your compiler provides native support for the CnetInt64 type.
Protocols will be linked with /usr/bin/gcc.

However, if your compiler does not provide such native support, or if you wish to write portable protocol codes to be used on machines with and without CnetInt64 support, then you'll need to be a bit more ``long-winded'' when dealing with the 64-bit integers.


Functions supporting the CnetInt64 datatype

Without native compiler support, cnet supports the 64-bit integers using a C structure of two 32-bit integers, and many supporting functions. You do not need to manipulate this structure directly; instead you should use the following functions to assign, convert, and compare values of the CnetInt64 datatype.

To provide maximum portability, cnet is itself written using these exact same functions. If your compiler does provide native support for the CnetInt64 datatype, you can still use these functions in your protocols with virtually no loss of performance, albeit with some loss of readability. A number of other, far less common, CnetInt64 functions are also available in the <cnet64bits.h> header file.

Declarations, initialization, and constants
Variables of type CnetInt64 may be declared and defined in the same locations as all other variables, as fields in structures, passed as parameters to functions, and returned as function results. However, as members of structures, they cannot be (consistently) initialized at compile-time, and so it is best to initialize them at run-time.

CnetInt64  result;    declares a 64-bit integer variable

int64_INIT(hi, lo)    a constant specifying its 2x32-bit halves

int64_ZERO            provides the 64-bit value for zero
int64_ONE             provides the 64-bit value for one
int64_MAXINT          provides the largest possible 64-bit integer
int64_MININT          provides the smallest possible 64-bit integer

Type conversions
Each of these type conversions is called first with the variable in which the result will be placed, and then the expression (or variable) from which the initial value should be taken. The first example of these, pronouced ``int-to-long'' (32-bit integer to 64-bit integer), is frequently used to initialize a CnetInt64 variable with a small constant value. When converting from a longer to a shorter type, there may be the inevitable loss of accuracy or precision.

int64_I2L(l, i)         assigns  ((l) = (CnetInt64)(i))
int64_L2I(i, l)         assigns  ((i) = (CnetInt32)(l))
int64_L2F(f, l)         assigns  ((f) = (CnetFloat64)(l))
int64_F2L(l, f)         assigns  ((l) = (CnetInt64)(f))

Arithmetic must be performed as if we were dealing with a 3-register assembly language. Each function takes the variable of its eventual 64-bit result as its first parameter, and one or two other 64-bit integers. It is permissible for any or all of the parameters to be the same variable.

int64_NEG(r, a)         performs ((r) = -(a))
int64_ADD(r, a, b)      performs ((r) = (a) + (b))
int64_SUB(r, a, b)      performs ((r) = (a) - (b))

int64_MUL(r, a, b)      performs ((r) = (a) * (b))
int64_DIV(r, a, b)      performs ((r) = (a) / (b))
int64_MOD(r, a, b)      performs ((r) = (a) % (b))

The following Boolean predicates each take one or two CnetInt64 values and return the result of the indicated comparison.

int64_IS_ZERO(a)        tests  ((a) == 0)
int64_EQ(a, b)          tests  ((a) == (b))
int64_NE(a, b)          tests  ((a) != (b))
int64_GE_ZERO(a)        tests  ((a) >= 0)

int64_CMP(a, op, b)     tests  ((CnetInt64)(a) op (CnetInt64)(b))

The last one is a little tricky, as any of the 6 relational operators may be provided as the second parameter, for example if(int64_CMP(a, >, b)) ...

Input and output
Without compiler support for the CnetInt64 datatype, we cannot simply pass it to functions such as printf(). Instead, we use two conversion functions to convert a CnetInt64 value either to or from a character array (a string), and then deal with the character array instead, probably with %s. A note of caution that int64_L2A(), pronounced ``long-to-alpha'', formats the 64-bit integer into an internal static character array. A copy of this array should be taken, with strdup(), if necessary.

int64_A2L(string)          converts the string, returning a 64-bit int.

int64_L2A(value, commas)   formats the indicated value, returning the
                           address of the array holding the character
                           representation.  The Boolean commas requests
                           that commas be included every third digit.

cnet was written and is maintained by Chris McDonald (