Variable Type System
Figure C-1 shows the variable type system used by the substitution system. The rightmost types are called terminal types. They are the types of all the parts of policies that can be parameterized. In the diagram any, number, and string are nonterminal types.
![]()
number - the type of all numeric values. This includes integers, floating point numbers, and numeric expressions that may contain variables.
- Integers are written signed decimal (-3, 0, 123). You can also specify integers in hexidecimal, octal, and binary by prefixing the integer with 0x, 0o, or 0b, respectively.
- Floating point numbers in decimal and scientific notation (1.2, -3.1, 2.0e23, 17.12e-4).
- Numeric expressions use the standard operators (+,-,*,/) with the traditional precedences (* and / are evaluated before + and -). Numeric expressions can also use some not so standard operators, such as ** for exponentiation, \ for bitwise not, /\ for bitwise and, \/ for bitwise or, // for integer division, and rem for remainder of integer division. When a numeric expression is evaluated during value acquisition, the result is rounded to the nearest integer.
string - used for strings. Strings are prefixed by a "$" to distinguish them from variable names. If strings contain spaces, start with uppercase letters, or contain operators that can be used in expressions, they must be enclosed in single quotes.
Terminal Numeric Types
protocolOperation, networkOperation - used for values that indicate whether a protocol or network field of a packet should match or not match the value specified in a policy condition. 0 means "does not match" and 1 means "matches"
ipFlags, ipFlagsMask - used for three bit values that represent patterns for the IP flags field in an IP packet. The high bit is "reserved", the middle bit is "don't fragment" and the low bit is "more fragments".
tcpFlags, tcpFlagsMask - used for six-bit values that represent patterns for the TCP flags field in IP packets. The bits from high to low mean the following: urgent, acknowledge, push, reset, synchronize, finish.
protocol, tosByte, tosByteMask, icmpType, icmpCode, igmpType - used for 8-bit values that represent patterns in the protocol, TOS byte, ICMP type, ICMP code, and IGMP type fields in IP packets. When tosByteMask is used in TOSCondition, the allowed values are 0, 224, 252, 255. The policy engine and Policy Editor validate these values; the substitution engine does not.
port - used for 16-bit values that represent patterns in the port fields in IP packets.
burst - used for values between 214 and 232-1, which can be used as burst sizes in rate limit actions.
rate - used for values between 0 and 232-1, which can be used as rates in rate limit rules.
Terminal String Types
trafficClassSpec, qosProfileSpec - used for the strings that are used in traffic class actions to specify traffic class profiles and quality of service profiles. They can be any string that names a traffic class or quality of service profile on the E-series router.
rateLimitType - used for the strings that specify the rate limit type types in rate limit actions. The allowed values are $'one-rate' and $'two-rate'. The policy engine and editor validate these values, the substitution engine does not.
fragOffset - used for strings that specify patterns in the fragment offset field of IP packets. The allowed values are $'eq 0', $'eq 1', $'gt 1', and $'any'. The policy engine and editor validate these values, the substitution engine does not.
portOperation - used for strings that specify values that indicate whether a port field of a packet should match or not match the value(s) specified in a policy condition. The allowed values are $'eq ', $'lt', $'gt', $'neq' and $'range'. The policy engine and editor validate these values, the substitution engine does not.
packetOperation - used for strings that specify committed, conformed and exceeded actions for rate limit actions. The allowed values are $'forward', $'filter', and $'mark <tosByte> <tosMask>'. The policy engine and editor validate these values, the substitution engine does not.
Terminal Subtypes of Any
address, addressMask - used to specify IP addresses and masks. The traditional dotted decimal notation is used to specify values of these types.
network - used to specify IP subnets using two forms: <address>/<mask> and <address>/<prefexLength> where <address> and <mask> are in the traditional dotted decimal notation and <prefixLength> is a number in 0..32 which specifies how many of the first bits in the address specify the network. Networks are used in policy conditions to specify patterns for the address fields in packets. Networks can optionally be preceded by "not" indicate that the condition matches every address not in the given subnet.
interfaceSpec - used to specify the E-series router IP interface in next interface actions. It is of the form <attribute> = '<value>' where <attribute> is one of "name", "alias", or "description" and <value> is the value of the attribute of the E-series router IP interface.
The lines between the types in Figure C-1 denote a more specific compatible type relationship. For instance, all other types are more specific than and compatible with the any type. Numbers are compatible only with the numeric terminal types.
Each time a substitution is read from the directory or user input, it can be validated. Regardless of whether the type for a variable in a substitution is given, the substitution system deduces the most specific type based on the value. If the optionally supplied type is more specific and compatible with the value, it is used. Otherwise, the type of the value is used. It is a semantic error to declare the type of the variable inconsistent with its value. For instance, x:burst=1.2.3.4/5 is an error.
The substitution system also can check type compatibility when acquiring values for variables. This includes checking each use of a substitution and the results of evaluating expressions. For instance, acquiring the value for x with the path (x:burst=y, y=1) y is too small for a burst, and substituting 1 for y in x:burst=y fails. Another example that fails is (x:burst=y/2, y:burst=20000). Both substitutions are valid, but acquiring a value for x fails because the result of evaluating the expression is too small to be a burst.