Key Tests

Reference Documentation

Napatech SmartNIC
Reference Information

This section specifies the syntax and semantics for the Key tests.

Supported Options Per Feature Set


Feature Sets





The syntax for the Key tests is shown below:

<KeyTest>       :== 'Key' '(' <Identifier> [ ',' 'ColorInfo' '=' <TrueFalseValue> ')' <EqualNotEqualTest> <KeySetIdOrAny>
<KeySetIdOrAny>      :== <KeySetId> | 'ANY'

The Key test is a generalization of the KeyMatch Test, where instead of testing on fields in a frame, tests are conducted on a key definition, that can contain multiple fields from a frame. The key definition is matched against keys entered through the KeyList command. If the key is found and it has a key set id contained in the right-hand-side (RHS) of the test, the result of the test is a match. If the key is not found, the result is a miss.

The key set id used on the RHS expression must either be tied to the key type of the key definition used on the left-hand-side (LHS) or not be tied to any key type. In the latter case (i.e. no keys have yet been added to the database with that key set id) the key set id will be tied to the key type at this time.

Key tests can be combined using the 'AND' and 'OR' operators. If both keys in a combined Key test expression matches a frame and both keys have color information attached to them, the resulting color will be the logical OR of the two colors. The stream info of a key is internally stored in the upper 7 bits of the color. Only one key can contribute to the stream info and therefore the color contribution of one of the keys must be turned off if both of them carry stream information. That is what the "ColorInfo" option in the Key test is for. If one key type carries stream information and the other key type carries color information, care should be taken to not set the the upper 7 color bits on any keys of the latter key type as this could yield unexpected results.

Note:As also noted in the KeyMatch Test section, it is important, that if you have multiple assign commands only with Key filters, then the key definitions used must be the same. You cannot test one key definition in one filter and the other key definition in another filter. You will then have to include both key definitions in both filter expressions. The 'ANY' keyword can be used in this case to specify a "dummy" Key statement that will always evaluate to true. However, if the Key filters are combined with other mutually exclusive filters, these restrictions do not apply. See example below.


This section presents several examples of Key test usage.

"Port matching"

This example demonstrates how to use the Key Matcher to match packets based on layer 4 destination port values. The keys are tagged with 2 different key sets (3 or 4) in order to differentiate between tcp and udp ports.

// Define Key Type KeyType[Name=DstPortKT] = {16} // Create key definition KeyDef[Name=DstPort; KeyType=DstPortKT] = (Layer4Header[0]/16) // Add a number of tcp port values to key set 3 KeyList[KeyType=DstPortKT; KeySet=3] = (80),(21),(22) // Add a number of udp port values to key set 4 KeyList[KeyType=DstPortKT; KeySet=4] = (53), (5353) // Add a range of udp port values to key set 4 KeyList[KeyType=DstPortKT; KeySet=4] = ((27000..27015)) // Set up filter matching tcp ports in key set 3 Assign[StreamId=0] = Layer4Protocol == TCP and Key(DstPort) == 3 // Set up filter matching udp ports in key set 4 Assign[StreamId=1] = Layer4Protocol == UDP and Key(DstPort) == 4

"Single IPv4 address"

In this example a single key definition is used to match on the source address of IPv4 frames. Color information is added to the keys a key in the database will set the descriptor color when it matches in the Key test:

// Define Key Type KeyType[name=KT_IPv4; ColorInfo=True] = {32} // Create key definition KeyDef[Name=SrcIPv4; KeyType=KT_IPv4] = (Layer3Header[12]/32) // Add some keys with color information KeyList[KeySet = 7; Color = 23; KeyType = KT_IPv4] = ( [] ), ( [] ), ( []; Color = 24 ) KeyList[KeySet = 8; Color = 25; KeyType = KT_IPv4] = ( [] ), ( [] ), ( []; Color = 26 ) // Set up filters Assign[StreamId=0] = Layer3Protocol == IPv4 AND Key(SrcIPv4) == 7 Assign[StreamId=1] = Layer3Protocol == IPv4 AND Key(SrcIPv4) == 8

"Source and destination IPv6 addresses"

In this example we are interested in matching both the source and destination addresses of IPv6 frames. Furthermore we want both the SA and DA to be matched against a collection of keys belonging to the same key type. This would be useful in scenarios where one wants to match bidirectional traffic where an address appears in both the SA or DA fields in the incoming frames. In this example upstream frames from the same client IP <-> remote IP address pair should end up in the same stream as when they are reversed in the downstream direction. This is done by applying a different hash recipe based on whether the traffic is upstream or downstream. It is assumed that both up- and downstream traffic arrives on the same port. When we cannot use the port number to logically separate the packets they must be separated based on whether SA or DA matches an ip address in the database. Both the SA and DA must be matched at that same time when a frame arrives. It is necessary to signal this condition/scenario when defining the key type. This is where the 'Access = Full' option comes into play.

// Define fields Define IPv6Src = Field(Layer3Header[8]/128) Define IPv6Dst = Field(Layer3Header[24]/128) // Define Up- and Downstream hash recipes Define HashUp = Hash(HashWord0_3=IPv6Src, HashWord4_7=IPv6Dst) Define HashDown = Hash(HashWord0_3=IPv6Dst, HashWord4_7=IPv6Src) // Define Key Type KeyType[name=KT_IPv6; Access = Full; ColorInfo=True] = {128} // Define keys KeyDef[name=SrcIPv6; KeyType=KT_IPv6] = (IPv6Src) KeyDef[name=DstIPv6; KeyType=KT_IPv6] = (IPv6Dst) // Add a masked key KeyList[KeySet = 8; Color = 25; KeyType = KT_IPv6] = ( {[ffff:ffff:ffff:ffff:ffff:ffff:ffff:0000]:[d7a0:4e95:0:0:0:0:af:0000]} ) // Set up filters Assign[StreamId=(0..31); Hash=HashUp] = Port == 0 AND Layer3Protocol == IPv6 AND (Key(SrcIPv6) == 8 AND Key(DstIPv6) == ANY) Assign[StreamId=(0..31); Hash=HashDown] = Port == 0 AND Layer3Protocol == IPv6 AND (Key(SrcIPv6) == ANY AND Key(DstIPv6) == 8) As mentioned in the note above, since the filters are not mutually exclusive (same port), both keys must use the same keys in both filters, hence the use of the ANY keyword.

Inner IPv6 address

This example shows how to filter GTP-U packets where the tunneled packet is IPv6 and the source or destination address matches a key. Coloring is used to identify each "subscriber" on the tunneled network:

// Define key type KeyType[Name=KT; Access=Full; ColorInfo=True] = {128} // Define keys for source- and destination address KeyDef[Name=SrcKD; KeyType=KT] = (InnerLayer3Header[8]/128) KeyDef[Name=DstKD; KeyType=KT] = (InnerLayer3Header[24]/128) // Set up filter Assign[StreamId=0] = TunnelType == GTPv1-U and InnerLayer3Protocol == IPv6 and (Key(SrcKD) == 3 or Key(DstKD) == 3) // Keys can now be added KeyList[KeyType=KT; Color=23] = ([1234:abcd:0:0:0:0:0:c0ed])

"Flow matching"

This example shows how to implement a flow matching scheme where a composite key is used. The key is composed of VLAN Id, SA, DA as well as layer 4 source and destination port. Since field sizes must be a multiple of 8 bits and the VLAN Id is 12 bits, it is extracted as a 16 bit field and a 12 bit mask applied to it in the 'KeyDef' definition. It is assumed that up- and downstream traffic enters the adapter on the same port. Here two keys are defined: one for upstream and one for downstream traffic. Because up- and downstream traffic enters the same port, both keys will be used in the filters, so the "Access=Full" option must be set on the key type. The downstream key has its source and destination fields swapped. The keys have color information attached to them. Two hash recipes are used (up- and downstream) to ensure that packets from the same flow end up in the same stream:

// Define fields Define VLANId = Field(FirstVLAN[2]/16) Define IPv4Src = Field(Layer3Header[12]/32) Define Ipv4Dst = Field(Layer3Header[16]/32) Define DstPort = Field(Layer4Header[0]/16) Define SrcPort = Field(Layer4Header[2]/16) // Define Up- and Downstream hash recipes Define HashUp = Hash(HashWord0_3=IPv4Src, HashWord4_7=IPv4Dst, HashWord8=SrcPort, HashWord9=DstPort) Define HashDown = Hash(HashWord0_3=IPv4Dst, HashWord4_7=IPv4Src, HashWord8=DstPort, HashWord9=SrcPort) // Define Key Type KeyType[name=KT_4TupleV4; Access=Full; ColorInfo=True] = {16, 32, 32, 16, 16} // Define keys KeyDef[name=KD_TupleV4Up; KeyType=KT_4TupleV4] = ({0xFFF:VLANId}, IPv4Src, IPv4Dst, SrcPort, DstPort) KeyDef[name=KD_TupleV4Down; KeyType=KT_4TupleV4] = ({0xFFF:VLANId}, IPv4Dst, IPv4Src, DstPort, SrcPort) // Add single key KeyList[KeySet = 7; Color = 23; KeyType = KT_4TupleV4] = (0x234, [], [], 0x0dc0, 'b10), (436, 0xaf3322de, 0xadbeef60, 0x0dc0, 0xde00; Color = 24) // Color overridden // Add masked key KeyList[KeySet = 7; Color = 25; KeyType = KT_4TupleV4] = ( {0xf00:400}, {[ff.ff.00.00]:[]}, {[ff.ff.00.00]:[]}, 0xde00, 0x0dff ) // Set up filters Assign[StreamId=(0..31); Hash=HashUp] = Layer3Protocol == IPv4 AND Key(KD_4TupleV4Up) == 7 AND Key(KD_4TupleV4Down) == ANY Assign[StreamId=(0..31); Hash=HashDown] = Layer3Protocol == IPv4 AND Key(KD_4TupleV4Up) == ANY AND Key(KD_4TupleV4Down) == 7 Note that because the two filters are not mutually exclusive, two lookups are necessary per filter and so we must use the ANY keyword since both keys must be present in both filters.

"NAT Mapping"

This example assumes a setup involving a NAT router, where both sides are monitored by an aggregation switch sending traffic into one port on the adapter. On the LAN side a 5-tuple hash distributes flows to a number of streams. The goal is to have the corresponding packets on the WAN side sent to the same streams. On the WAN side hashing cannot be used, because the NAT router mangles the source IP address and port on the outgoing packets. The packets would consequently not end up in the same streams. It is assumed that the port mapping in the NAT router can be learned by the application responsible for configuring the adapter. The following key sets are used:

  • IPv4/TCP : 3

  • IPv4/UDP : 4

  • IPv6/TCP : 5

  • IPv6/UDP : 6

The NTPL for this example looks as follows:

// Set up hashing on the LAN side HashMode(Priority=1; Layer3Type=IP) = Hash5TupleSorted // Define key types and keys for IPv4 and IPv6 packets KeyType[Name=KT_IPv4; Access=Full; StreamInfo=True] = {32, 16, 16} KeyDef[Name=KD_IPv4Up; KeyType=KT_IPv4] = (Layer3Header[16]/32, Layer4Header[0]/16, Layer4Header[2]/16) KeyDef[Name=KD_IPv4Down; KeyType=KT_IPv4] = (Layer3Header[12]/32, Layer4Header[2]/16, Layer4Header[0]/16) KeyType[Name=KT_IPv6; Access=Full; StreamInfo=True] = {128, 16, 16} KeyDef[Name=KD_IPv6Up; KeyType=KT_IPv6] = (Layer3Header[24]/128, Layer4Header[0]/16, Layer4Header[2]/16) KeyDef[Name=KD_IPv6Down; KeyType=KT_IPv6] = (Layer3Header[8]/128, Layer4Header[2]/16, Layer4Header[0]/16) // Assign key match filters for the WAN side (IPv4 and IPv6) Assign[StreamId=Key] = Layer3Protocol == IPv4 AND Layer4Protocol == TCP AND (Key(KD_IPv4Up) == 3 or Key(KD_IPv4Down) == 3) Assign[StreamId=Key] = Layer3Protocol == IPv4 AND Layer4Protocol == UDP AND (Key(KD_IPv4Up) == 4 or Key(KD_IPv4Down) == 4) Assign[StreamId=Key] = Layer3Protocol == IPv6 AND Layer4Protocol == TCP AND (Key(KD_IPv6Up) == 5 or Key(KD_IPv6Down) == 5) Assign[StreamId=Key] = Layer3Protocol == IPv6 AND Layer4Protocol == UDP AND (Key(KD_IPv6Up) == 6 or Key(KD_IPv6Down) == 6) // Assign an "All" filter for the LAN packets Assign[StreamId=(0..63);Priority=1] = All // Add keys as the NAT mapping is learned e.g. TCP: ( –> (<NAT-IP>- KeyList[KeyType=KT_IPv4;KeySet=3;StreamId=45] = ([], 4560, 80)