Rate This Document
Findability
Accuracy
Completeness
Readability

Actions

Built-in Actions

The hydra_builtin.hdr architecture file provides a series of built-in actions. You can declare required built-in actions in the action list of a table.

Table 1 Built-in actions

Action Signature

Description

Constraint

@flexda action flexda_no_action()

Performs no operation upon a flow table miss.

It can be used as a default action only, not in the action list of the table.

@flexda @pre action flexda_upcall()

Triggers a packet upcall.

It can be used as a default action or in the action list of the table.

@flexda action flexda_drop()

Drops the packet upon a flow table miss.

It can be used as a default action only, not in the action list of the table.

@flexda @pre @main action flexda_ct()

Triggers a TCP state packet upcall.

This action deals with TCP state packets. When this action is performed, other actions can be performed on other packets.

@flexda @main action flexda_inner_rss(bit<8> rss)

Allows users to customize inner RSS of a specified packet layer.

  • It can be used only in a main table.
  • The system supports inner RSS for up to two tunnel layers. The valid values are 0, 1, and 2. Any other values will trigger the default RSS procedure.
  • The packet parsing logic must include the parsing process for the corresponding layers intended for RSS.
  • In the OVS scenario, the issuing logic of the control plane needs to be implemented separately.
  • Default RSS procedure:

    1. For non-tunneled packets: TCP/UDP packets support hashing based on the source IP (SIP), destination IP (DIP), source port, and destination port. IP packets support hashing based on the SIP and DIP. Other packet types are not hashed.

    2. For single-layer tunneled packets: VXLAN and GENEVE support inner RSS, with a hashing method similar to that for non-tunneled packets. Other tunneled packets are treated as non-tunneled packets for hashing.

    3. For multi-layer tunneled packets: These are treated as single-layer tunneled packets for hashing.

@dpdk @persist action rte_count()

Performs counting.

It is implicitly added to the action list of each table. Do not manually add it to a table's action list.

@dpdk @main action rte_port_id(bit<16> id)

Sends the packet to a specified port.

It can be used only in a main table.

@dpdk action rte_set_mac_src(macAddr_t src)

Modifies the src_mac field in the Ethernet header.

N/A

@dpdk action rte_set_mac_dst(macAddr_t dst)

Modifies the dst_mac field in the Ethernet header.

N/A

@dpdk action rte_set_ipv4_src(ip4Addr_t src)

Modifies the src_ip field in the IPv4 header.

N/A

@dpdk action rte_set_ipv4_dst(ip4Addr_t dst)

Modifies the dst_ip field in the IPv4 header.

N/A

@dpdk action rte_set_ipv6_src(ip6Addr_t src)

Modifies the src_ip field in the IPv6 header.

N/A

@dpdk action rte_set_ipv6_dst(ip6Addr_t dst)

Modifies the dst_ip field in the IPv6 header.

N/A

@dpdk action rte_set_ttl(bit<8> ttl)

Modifies the TTL value in the IP header.

N/A

@dpdk action rte_dec_ttl()

Decrements the TTL value in the IP header by 1.

N/A

@dpdk action rte_set_tp_src(portAddr_t src)

Modifies the src_port field in the TCP/UDP header.

N/A

@dpdk action rte_set_tp_dst(portAddr_t dst)

Modifies the dst_port field in the TCP/UDP header.

N/A

@dpdk action rte_of_pop_vlan()

Deletes the VLAN frame from the Ethernet header.

N/A

@dpdk action rte_of_push_vlan(bit<16> vlan_id)

Inserts a VLAN frame into the Ethernet header.

N/A

@dpdk action rte_of_set_vlan_vid(bit<16> vlan_vid)

Modifies the vid field of the VLAN frame.

N/A

@dpdk action rte_of_set_vlan_pcp(bit<8> vlan_pcp)

Modifies the pcp field of the VLAN frame.

N/A

@dpdk @encap action rte_vxlan_encap(bit<512> item)

Encapsulates a VXLAN tunnel.

N/A

@dpdk @decap action rte_vxlan_decap()

Decapsulates a VXLAN tunnel.

N/A

@dpdk action rte_queue(bit<8> queue_index) {}

Sends data packets to the upcall queue with a specified index.

  • To prevent data overflow when the queue action is issued, ensure that the queue index is less than 256. If the queue index is greater than or equal to 256, the flow entry will fail to be issued.
  • During a queue action, if the queue index exceeds the number of upcall queues configured for the port, it will be wrapped around using a modulo operation against the configured upcall queue number.

@dpdk action rte_rss(bit<704> item) {}

Processes data packets and hashes them to multiple upcall queues based on the provided parameters.

  • Supported hash functions include RTE_ETH_HASH_FUNCTION_TOEPLITZ, RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, and RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ (that is, TOEPLITZ, simple XOR, and symmetric TOEPLITZ). If you do not specify a hash algorithm (that is, func = RTE_ETH_HASH_FUNCTION_DEFAULT), simple XOR is used to calculate the hash value.
  • Supported levels include 0, 1, and 2.

    0 and 1 indicate the outer packet header. 2 indicates the inner packet header. Only a single level of inner encapsulation is supported.

  • Supported types include RTE_ETH_RSS_IPV4, RTE_ETH_RSS_FRAG_IPV4, RTE_ETH_RSS_NONFRAG_IPV4_TCP, RTE_ETH_RSS_NONFRAG_IPV4_UDP, RTE_ETH_RSS_IPV6, RTE_ETH_RSS_FRAG_IPV6, RTE_ETH_RSS_NONFRAG_IPV6_TCP, RTE_ETH_RSS_NONFRAG_IPV6_UDP, RTE_ETH_RSS_L2_PAYLOAD, RTE_ETH_RSS_IPV6_EX, RTE_ETH_RSS_IPV6_TCP_EX, and RTE_ETH_RSS_IPV6_UDP_EX.
  • If the configured types do not match the data packets, the system falls back to the default upcall process. If only IPv4 or IPv6 is specified for L3 types, the match is limited to the specified protocol. You can specify both IPv4 and IPv6. If so, the system will match according to the actual packet protocol.
  • The value of queue_num ranges from 0 to 32.

    If queue_num is set to 0, packets are hashed to each upcall queue configured for the port by default.

  • The queue array cannot be empty, and its valid length must be consistent with queue_num. If the queue index exceeds the number of upcall queues configured for the port, it will be wrapped around using a modulo operation against the configured upcall queue number.
  • Do not modify the statements of built-in actions. Otherwise, unexpected results may occur.
  • Built-in actions do not support structures as input parameters. Consequently, in flow table dumps, such data can only be displayed in its raw bitstream format.

Table 2 describes the action annotations.

Table 2 Annotation description

Annotation

Description

@flexda

Built-in actions provided by the FlexDA programming framework.

@dpdk

Built-in actions corresponding to the DPDK standard enumerations.

@persist

This action is implicitly added to the action list of each table. Do not manually add it again.

@pre

Pre-actions, which can be used in a pre-auxiliary table.

@main

Main actions, which can be used in a main table.

@post

Post-actions, which can be used in a post-auxiliary table.

@encap

Tunnel encapsulation action. The @encap annotation is also required for custom tunnel encapsulation actions.

@decap

Tunnel decapsulation action. The @decap annotation is also required for custom tunnel decapsulation actions.

Actions that are not marked by @pre, @main, or @post can be used only in a main table.

Custom Actions

You can customize actions for operations that are not covered by built-in actions. Actions in Hydra are similar to functions in other languages. The difference is that actions do not have return values. The action syntax is as follows:

action max(in bit<16> a, action_data data) {
...
}
  • Directional parameters (in/out/inout) are parameters from the data plane. Directionless headers or other data types containing headers cannot be used as action parameters.

    Data plane parameters must be bound within the action list of the table (for example, ovs_action_mod_tos(hdr); in a control block).

  • Directionless parameters are parameters from the control plane.

    Control plane parameters are read from the flow entry after a flow table hit; therefore, they do not require binding in the action list.

  • Custom actions must be defined at the top level and must not be defined within a control block.
  • A custom action supports only one data plane parameter. This parameter must be the first input parameter of the corresponding control block, and its direction must be set to in.
  • Custom actions can utilize the extern interfaces provided by the framework to implement custom packet editing. The packet editing capability is subject to the constraints defined in the extern interface specifications.
  • The number of custom actions cannot exceed 128.
  • The action data for a single custom action must not exceed 128 bytes. Otherwise, the portion beyond 128 bytes will result in unexpected behavior.

You can implement a series of operations, such as packet insertion, deletion, and modification, by invoking extern functions within custom actions. The following uses FullNAT as an example to describe how to utilize custom actions to modify the tos and ttl fields in the IPv4 header.

struct action_data {
    bit<8>      tos;
}
action ovs_action_mod_tos(in headers hdr, action_data data) {
    packet_incr_cs_param incr_checksum_para;
    incr_checksum_para.old_val = (bit<32>)hdr.l3.ipv4.diff_serv;
    incr_checksum_para.new_val = (bit<32>)data.tos;
    incr_checksum_para.old_cs = hdr.l3.ipv4.hdr_checksum;
    incr_checksum_para.cs_alg = RFC.RFC_1624;
    hdr_packet_modify(hdr.l3.ipv4.diff_serv, data.tos);
    hdr_packet_calc_checksum_incr(hdr.l3.ipv4.diff_serv, hdr.l3.ipv4.hdr_checksum, incr_checksum_para);
}
action ovs_action_mod_ttl(in headers hdr) {
    packet_incr_cs_param incr_checksum_para;
    incr_checksum_para.old_val = (bit<32>)hdr.l3.ipv4.ttl;
    incr_checksum_para.new_val = (bit<32>)(hdr.l3.ipv4.ttl - 1);
    incr_checksum_para.old_cs = hdr.l3.ipv4.hdr_checksum;
    incr_checksum_para.cs_alg = RFC.RFC_1624;
    hdr_packet_modify(hdr.l3.ipv4.ttl, hdr.l3.ipv4.ttl - 1);
    hdr_packet_calc_checksum_incr(hdr.l3.ipv4.ttl, hdr.l3.ipv4.hdr_checksum, incr_checksum_para);
}