bfrt_helper.match

Base Match Type

Masked

class Masked[source]

Bases: object

Base class for all matches which can be represented in terms of a value and a mask.

subset_of(other: Masked) bool[source]

Compares whether self is a subset of other.

If all the elements in self are also in other, then this object is a subset. This is True even if both objects contain exactly the same elements.

This is broadly equivalent to a <= (less than or equal to) operation, and is called by the Masked.__le__() special method.

See also: Masked.proper_subset_of()

Parameters:

other (Masked) – Other masked value to compare against.

Returns:

True if self is subset of other

Return type:

bool

superset_of(other: Masked) bool[source]

Compares whether other is a subset of self.

If all the elements in other are also in self, then this object is a superset. This is True even if both objects contain exactly the same elements.

This is broadly equivalent to a >= (less than or equal to) operation, and is called by the Masked.__ge__() special method.

See also: Masked.proper_superset_of()

Parameters:

other (Masked) – Other masked value to compare against.

Returns:

True if self is superset of other

Return type:

bool

proper_subset_of(other: Masked) bool[source]

Compares with another match, where self is found to be a proper subset of the other.

If all the elements in self are present in other, and, other contains at least one element not in self, then this object can be considered a proper subset.

This is broadly equivalent to a < (less than) operation, and is called by the Masked.__lt__() special method.

See also: Masked.subset_of()

Parameters:

other (Masked) – Other masked value to compare against.

Returns:

True if self is proper superset of other

Return type:

bool

proper_superset_of(other: Masked) bool[source]

Compares with another match, where self is found to be a proper superset of the other.

If all the elements in other are present in self, and, self contains at least one element not in other, then this object can be considered a proper superset.

This is broadly equivalent to a > (less than) operation, and is called by the Masked.__gt__() special method.

See also: Masked.uperset_of()

Parameters:

other (Masked) – Other masked value to compare against.

Returns:

True if self is proper superset of other

Return type:

bool

intersection(other: Masked) Masked[source]

Returns the intersection of self and other.

The intersection of two masked values is the common potential values between self and other.

The following relations should hold true, noting the use of proper subset and superset comparisons:

intersection = a & b
assert a > intersection # Intersection is subset of a
assert b > intersection # Intersection also subset of b

Since the intersection is the common elements, and if both a and b are proper supersets of the intersection, they must contain different/unique values.

Returns:

Contains the elements which are common to self and other.

Return type:

Masked

merged(other: Masked) Masked[source]

Derives a Masked object whose mask has all “don’t care” bits from both self and other.

Note

This is not a union. As an example, a ternary expression \(A = 0101xxxx\) contains all possible values beginning with \(0101\). Another value \(B = xxxx0101\) contains all the possible values ending in \(0101\). A merge between the two yields the ternary expression \(I = xxxxxxxx\), where another value \(C = 11001100\) is subset to \(I\) but is in neither \(A\) or \(B\). If it were a union, any value that is subset must be in either \(A\) or :math`B`.

Returns:

Contains values derived from

Return type:

Masked

overlaps(other: Masked) bool[source]

Returns whether or not two Masked matches overlap.

Overlapping ternary expressions are defined where some, but not all, elements in a ternary \(A\) exist in a ternary \(B\), and, some, but not all, elements in \(B\) exist in \(A\). That is to say that they are neither proper superset or subset of each other, but they share elements.

If only one of these conditions held true, they would either be a proper subset or superset of one another. A corollary to this is that longest prefix matches do not overlap, they are strictly a subset or superset of one another.

That is to say that \(A\), being a proper superset of the intersection \(I\), has at least one element not in \(I\), and, \(B\), being a proper superset of \(I\), has at least one element not in intersection \(I\), implying that the elements contained in the differences between either \(A\) or \(B\) and the intersection are unique to each other.

__le__(other: Masked) bool[source]

See subset_of()

__ge__(other: Masked) bool[source]

See superset_of()

__lt__(other: Masked) bool[source]

See proper_subset_of()

__gt__(other: Masked) bool[source]

See proper_superset_of()

__eq__(other: Masked) bool[source]

Equality compares two ternary expressions.

If both value and mask are the same between the two objects, then True is returned.

__and__(other: Masked) Masked[source]

Returns the intersection of self and other.

see intersection()

__or__(other: Masked) Masked[source]

Returns a ternary with a merged mask of self and other.

see merged()

__iter__() iterator[source]

Creates an iterator that returns consecutive elements in the set of Masked, starting from the current value.

The iterator itself is not efficient, it’s internal value is incremented until it finds a match on every iteration.

When the iterator is dereferenced, it returns either an LPM or Ternary expression, depending on what the derived class is.

Examples

Using a PortID:

>>> match = Ternary(PortId(0x0), mask=0xc)
>>> [str(x) for x in iter(match)]
[
    '0x0 &&& 0xf3',
    '0x4 &&& 0xf3',
    '0x8 &&& 0xf3',
    '0xc &&& 0xf3'
]

Or an IPv4Address:

>>> match = Ternary(IPv4Address("192.168.42.24"),
..      mask="255.255.255.252")
>>> [str()]
[
    '192.168.42.24 &&& 255.255.255.252',
    '192.168.42.25 &&& 255.255.255.252',
    '192.168.42.26 &&& 255.255.255.252',
    '192.168.42.27 &&& 255.255.255.252',
]
Returns:

An iterator object that

Supported Types

Exact

class Exact(value)[source]

Bases: object

An exact match

Comparisons between exact matches are on the basis of equality alone.

value_bytes()[source]

LongestPrefixMatch

class LongestPrefixMatch(value: Field, prefix: int)[source]

Bases: Masked

Class that represents only the first prefix bits are considered in a match.

value_bytes()[source]

Ternary

class Ternary(value: Field, mask: Field | None = None, dont_care=False)[source]

Bases: Masked

Matches values on specific bits.

A Ternary match is a match type which matches on specific bits of the value. This is achieved by the use of a mask; when a match is performed, both the the expected value and the compared value are ANDed with the mask, and an equality operation can be performed without comparing every single bit.

Ternary values are associated with TCAM () memory; and are stored in hardware as trits. These are like bits but have 3 states, on, off, and “don’t care”.

Note

Masks could be represented by either 0 or 1 for a match. In this case, 1 bits represent bit’s which are matched against.

This class represents a ternary expression as a combination of an integer value and a mask. This is because:

  • Python supports arbitrary length integers;

  • It is easier to perform bitwise operations on integers.

Parameters:
  • value (Field) – The instance of a field, e.g. VlanID(), MACAddress(), etc.

  • mask (Field) – The mask representing the bits to match against, either as an instance of the value’s type, or, a value that can be passed to that type’s constructor.

  • dont_care (bool) – If True, no bits will be considered.

The semantics of this match can change depending on whether a mask or dont_care is specified. By default, creating a Ternary match without a mask will match on every single bit, effectively acting in the same way as bfrt_helper.match.Exact.

The mask value does not have to be specified explictly as the same type as the value, any value will be accepted so long as it would be accepted by the value types constructor.

If dont_care is specified, no bits will be compared (i.e, the mask will contain all zeroes). This means that it will match on any value it’s compared against. This can be useful if a table specifies multiple key fields, and you wanted to match on another field, but not this specific Ternary element.

Examples

A match on a PortId which only considers the 4 least significant bits:

my_field = Ternary(PortId(42), PortId(0xf))

A match on a PortId which only considers the 4 least significant bits, but not specifying the mask in terms of the original type:

my_field = Ternary(PortId(42), 0xf)

A match that will match exactly on a PortId of 42:

my_field = Ternary(PortId(42))

A match that will match on any other PortId:

my_field = Ternary(PortId(42), dont_care=True)
value_bytes()[source]

Returns the match value as bytes.

Returns:

Internal value converted into bytes.

Return type:

bytes

mask_bytes()[source]

Returns the mask value as bytes.

Returns:

Internal mask converted into bytes.

Return type:

bytes

classmethod dont_care()[source]

Not implemented

Exceptions

MismatchedKeys

class MismatchedKeys(message)[source]

Bases: Exception

Raised when the key’s name doesn’t match when comparing two match objects