Rate This Document
Findability
Accuracy
Completeness
Readability

Derived Data Types

header

A header is a key data structure used to define a protocol header architecture. Its purpose is to map the raw bitstream into a set of fields with distinct semantics, enabling the access and manipulation of these fields during subsequent packet processing.

header <header_name> {
    <field_type> <field_name>;
    ...
}
  • header_name: Name of a header, which is usually named after the protocol. For example, ethernet_t or ipv4_t.
  • field_type: Type of a field, which is usually the bit type with a fixed width. For example, bit<16>.
  • field_name: Name of a field, which identifies a specific attribute of a protocol.
  • header_name and field_name cannot be DSL keywords like action and match_kind. They can contain only digits, letters, and underscores, and cannot start with a digit.

The following code block is the definition of ethernet_t:

typedef bit<48> macAddr_t;
header ethernet_t {
    macAddr_t dstAddr;    // Destination MAC address
    macAddr_t srcAddr;    // Source MAC address
    bit<16>   etherType;  // Protocol type field
}

The header type supports the setValid(), isValid(), and setInvalid() methods.

  • setValid(): Sets the protocol type that is valid in the header. This method is called after the extract() function for packet parsing takes effect.
  • isValid(): Checks whether the protocol type in the header is valid. Before accessing data at a specific protocol layer, it is necessary to verify whether the layer is valid. Failure to perform this verification before accessing header data will result in null pointer exceptions, leading to functional exceptions.
  • setInvalid(): Sets the protocol type that is invalid in the header.
  • The architecture file hydra_headers.hdr provides common protocol headers for users.
  • The header type supports only basic-type members.

header_union

The header_union type is similar to the union type in C. It is used to define a group of protocol types and dynamically select which one to use when processing packets. Each member of header_union must be of the header type.

header_union <header_union_name> {
    header <header_name>;
    ...
}
  • header_union_name: Name of the protocol group (for example, ip_union). It cannot be DSL keywords like action and match_kind. It can contain only digits, letters, and underscores, and cannot start with a digit.

The following code block is the definition of ip_union, which indicates the union of IPv4 and IPv6 packet headers.

header_union ip_union {
    ipv4_t ipv4;
    ipv6_t ipv6;
}
  • header_union supports only header members.
  • header_union cannot be passed as a generic parameter.
  • header_union cannot be used as a control-plane parameter of an action.

struct

In a DSL, struct is a data type used to define general data structures. Unlike headers, a struct does not map directly to the packet bitstream; instead, it is used to store metadata associated with the packet, intermediate processing data, or collections of multi-layer network headers. Its flexibility makes it ideal for maintaining auxiliary information during the logical processing of a program.

The syntax for defining a struct is as follows:

struct <struct_name> {
    <field_type> <field_name>;
    ...
}
  • struct_name: Name of the data structure, typically named based on its function. For example, metadata_t or headers.
  • field_type: Type of a field, which can be bit<N>, Boolean, enumeration, or nested struct.
  • field_name: Name of a field, which identifies a specific attribute in the data structure.
  • field_name and struct_name cannot be DSL keywords like action and match_kind. They can contain only digits, letters, and underscores, and cannot start with a digit.

enum

An enumeration type is used to declare a group of named constants. It applies to the scenario where a variable is restricted to a finite set of defined options. For example, the Hydra architecture file hydra_core.hdr utilizes an enum to represent packet layers.

enum layers_e {
    l2,
    l3,
    l4,
    tunnel,
    inner_l2,
    inner_l3,
    inner_l4
}

You can specify the underlying representation of an enum, such as bit<8>, and specify a value for each member.

enum bit<8> E {
    e1 = 0,
    e2 = 1,
    e3 = 2
}
  • The enum name and member names cannot be DSL keywords like action and match_kind. They can contain only digits, letters, and underscores, and cannot start with a digit.

Generic Types

Generic types represent types that have not yet been determined and must be provided by users. They are used for extern functions and packages. For example, the following extern function is used to modify packet fields:

extern void hdr_packet_modify<T>(in T field, in T value);

When the extern function is called, the type T should be instantiated and can represent any type.

hdr_packet_modify(hdr.ipv4.sip, new_sip);
hdr_packet_modify(hdr.ethernet.smac, new_smac);

In the above case, the sip type is bit<32>, and the smac type is bit<48>.

  • The generic type of an extern function cannot be instantiated as a struct.
  • You can use the preceding data types to define variables. Example: <field_type> <field_name>
  • field_name cannot be a DSL keyword, such as action or match_kind. A field name can contain only digits, letters, and underscores, and cannot start with a digit.