DOCA SDK Documentation

P4 Language Support in DPL

This section outlines the P4-16 language features supported by the DOCA Pipeline Language (DPL) and notes any known deviations or limitations. All references are based on the P4 Language Specification version v1.2.4.

Introduction

NVIDIA® BlueField® networking platforms (DPU or SuperNIC) are designed to accelerate data center workloads by offloading and isolating key infrastructure tasks, including networking, storage, and security. BlueField-3 combines ASIC performance with programmable flexibility, supporting up to 400G connectivity—ideal for AI and HPC environments.

To optimize for high-performance hardware, the P4 implementation on BlueField differs from generic software targets. As a result, DOCA Pipeline Language (DPL) selectively supports P4 features that align with its target architecture. This section details which P4 features are currently supported, restricted, or unsupported.

A feature labeled as “unsupported” is either not implemented or has not been validated. The compiler may reject such usage explicitly or accept it only if the feature is resolved at compile time (e.g., constant folding). However, acceptance does not imply support and should not be relied upon.

P4 Language Features

The DPL compiler implements a performance-oriented subset of P4-16, aligned with the capabilities of the BlueField hardware. Unsupported features are typically those that require runtime flexibility (e.g., dynamic parsing or general-purpose control logic) which are not efficient in ASIC-based systems. Developers should reference this section during development to ensure compatibility and portability of P4 programs targeting DPL.

Identifiers

  • Identifiers starting with __ are reserved for internal compiler use

  • All other identifiers conform to P4 spec §6.4.1

Data Types

Type

Support Level

Notes

bool

Supported

Fully supported

Arbitrary-precision int

Limited

Only for literals (see spec

§7.1.6.5

)

int (signed integers)

Unsupported


String literals

Unsupported

Accepted, but no operations or validity checks (see spec

§6.4.3.3

). Only supported in annotations.

Bit strings

Supported

Subject to hardware resource limits

Refer to section "P4 Language Support in DPL | id (3.0.0)P4LanguageSupportinDPL Operators" for support of operations on values with these types.

Derived Types

Type

Support Level

Notes

enum

Supported

As per spec

§7.2.1

, with restrictions based on target-supported types

header

Supported

All field types except varbit<> (only supported via NvOptionParser). See spec

§7.2.2

.

header_stack

Unsupported


struct

Supported

Must use only supported field types. See spec

§7.2.5

.

union

Unsupported


tuple / list

Supported

As per spec

§7.2.6

extern types

Limited

Only the externs provided with the DPL compiler are allowed; no custom externs. See spec 

§7.2.9

.

Type specialization

Supported

As per spec

§7.2.10

Statements and Expressions

Feature

Support Level

Notes

assignment

Limited

L-values are restricted. Cannot assign to method calls, packet_out metadata, flex-header fields, or unsupported metadata fields. Only some fixed headers are valid L-values.

op-assignment (+=, -=)

Supported

See operators and header field add/sub sections for details.

if / conditionals

Limited

Only within control apply blocks; must evaluate to bit or bool

switch

Limited

Only within control apply blocks; switch expression must be bool

Fall-through, default, and empty switch cases are supported per spec §11.7.

The following tables describe the compiler support for expressions using the built in header fields and standard metadata as L-values and R-values. Note, this is separate of header fields that can be used as match keys. 

Alias of header fields

In the default hardware parser, some fields that are mutually exclusive are extracted to the same buffer location (referred to in the table as an alias). Assignments to and copy from these fields can use either of the aliased field names.

Fixed Header Fields

Assign

Copy

Add/Sub

Notes

headers.ethernet.dst_addr


headers.ethernet.src_addr


headers.ethernet.ether_type

Last extracted outer etherType value

headers.vlan.vlan_pcp

 

headers.vlan.vlan_dei

 

headers.vlan.vlan_id


headers.vlan.vlan_ether_type

Last extracted outer etherType value

headers.inner_ethernet.dst_addr


headers.inner_ethernet.src_addr


headers.inner_ethernet.ether_type

Last extracted inner etherType value

headers.inner_vlan.vlan_pcp

 

headers.inner_vlan.vlan_dei

 

headers.inner_vlan.vlan_id

 

headers.inner_vlan.vlan_ether_type

Last extracted inner etherType value

headers.ipv4.version

 Alias with headers.ipv6.version

 

headers.ipv4.ihl

 ✔

 

headers.ipv4.diffserv

Alias with headers.ipv6.diffserv

Can be set through nv_set_ip_dscp extern

headers.ipv4.ecn

Alias with headers.ipv6.ecn

Can be set through nv_set_ip_ecn extern

headers.ipv4.total_len

May be updated also by hardware

headers.ipv4.identification

 

headers.ipv4.flags

 

headers.ipv4.frag_offset

 

headers.ipv4.ttl


headers.ipv4.protocol

Alias with headers.ipv6.next_header

Can be set through nv_set_ip_protocol extern

headers.ipv4.hdr_checksum

Value is write only by hardware

headers.ipv4.src_addr


headers.ipv4.dst_addr

 

headers.inner_ipv4.version

Alias with headers.inner_ipv6.version

 

headers.inner_ipv4.ihl

 

headers.inner_ipv4.diffserv

Alias with headers.inner_ipv6.diffserv


headers.inner_ipv4.ecn

Alias with headers.inner_ipv6.ecn

 

headers.inner_ipv4.total_len

 

headers.inner_ipv4.identification

 

headers.inner_ipv4.flags

 

headers.inner_ipv4.frag_offset

 

headers.inner_ipv4.ttl


headers.inner_ipv4.protocol

Alias with headers.inner_ipv6.protocol

 

headers.inner_ipv4.hdr_checksum

 

 

headers.inner_ipv4.src_addr


headers.inner_ipv4.dst_addr


headers.ipv6.flow_label

 

headers.ipv6.hop_limit

 

headers.ipv6.payload_length

✔ 

 

headers.ipv6.src_addr


headers.ipv6.dst_addr


headers.inner_ipv6.flow_label

 

headers.inner_ipv6.hop_limit

 

headers.inner_ipv6.payload_length

 

headers.inner_ipv6.src_addr


headers.inner_ipv6.dst_addr


headers.mpls.label


headers.mpls.tc


headers.mpls.bos


headers.mpls.ttl


headers.inner_mpls.label


headers.inner_mpls.tc


headers.inner_mpls.bos


headers.inner_mpls.ttl


headers.icmp.type

 

headers.icmp.code

 

headers.icmp.checksum

 

headers.icmp.identifier

 

headers.icmp.sequence_number

 

headers.inner_icmp.type

 

headers.inner_icmp.code

 

headers.inner_icmp.checksum

 

headers.inner_icmp.identifier

 

headers.inner_icmp.sequence_number

 

headers.icmpv6.type

 

headers.icmpv6.code

 

headers.icmpv6.checksum

 

headers.icmpv6.payload_1

 

headers.icmpv6.payload_2

 

headers.inner_icmpv6.type

 

headers.inner_icmpv6.code

 

headers.inner_icmpv6.checksum

 

headers.inner_icmpv6.payload_1

 

headers.inner_icmpv6.payload_2

 

headers.tcp.src_port

Alias with headers.udp.src_port

Can be set through nv_set_l4_src_port extern

headers.tcp.dst_port

Alias with headers.udp.dst_port

Can be set through nv_set_l4_dst_port extern

headers.tcp.seq_no


headers.tcp.ack_no


headers.tcp.data_offset

 

headers.tcp.res

 

headers.tcp.nonce_sum

 

headers.tcp.ecn


headers.tcp.flags


headers.tcp.window

 

headers.tcp.checksum

 

 

headers.tcp.urgent_ptr

 

 

headers.inner_tcp.src_port

Alias with headers.inner_udp.src_port


headers.inner_tcp.dst_port

Alias with headers.inner_udp.dst_port


headers.inner_tcp.seq_no


headers.inner_tcp.ack_no


headers.inner_tcp.data_offset

 

headers.inner_tcp.res

 

headers.inner_tcp.nonce_sum

 

headers.inner_tcp.ecn


headers.inner_tcp.flags


headers.inner_tcp.window

 

headers.inner_tcp.checksum

 

headers.inner_tcp.urgent_ptr

 

headers.udp.length

 

headers.udp.checksum

 

headers.inner_udp.length

 

headers.inner_udp.checksum

 

headers.gre.checksum_present

 

headers.gre.reserved1

 

headers.gre.key_present

 

headers.gre.sequence_present

 

headers.gre.reserved2

 

headers.gre.reserved3

 

headers.gre.version

 

headers.gre.protocol

 

headers.nvgre_vsid.vsid

 

headers.nvgre_vsid.flow_id

 

headers.esp.security_parameters_index

 

headers.esp.sequence_number

 

headers.esp.next_header

Value set by hardware after decryption

headers.psp.next_header

Value set by hardware after decryption

headers.psp.hdr_ext_len

 

headers.psp.crypt_offset

 

headers.psp.needs_sampling

 

headers.psp.drop

 

headers.psp.version

 

headers.psp.has_virtualization_key

 

headers.psp.one_1

 

headers.psp.security_parameters_index

 

headers.psp.initialization_vector

 

headers.psp.virtualization_key_high

 

headers.psp.virtualization_key_low

 

headers.vxlan.reserved1

 

headers.vxlan.vni_valid

 

headers.vxlan.reserved2

 

headers.vxlan.reserved3

 

headers.vxlan.vni


headers.vxlan.reserved4

 

headers.vxlan_gpe.reserved1

 

headers.vxlan_gpe.vni_valid

 

headers.vxlan_gpe.reserved2

 

headers.vxlan_gpe.reserved3

 

headers.vxlan_gpe.next_proto

 

headers.vxlan_gpe.vni


headers.vxlan_gpe.reserved4

 

headers.geneve.ver

 

headers.geneve.opt_len

 

headers.geneve.o

 

headers.geneve.c

 

headers.geneve.reserved1

 

headers.geneve.protocol_type

 

headers.geneve.vni


headers.geneve.reserved2

 

 


All the fields of BlueField standard metadata are read only. The following table outlines the current support for using a standard metadata field as an R-value in an expression.

Standard Metadata Fields

Copyable

Notes

ingress_port

 

eth_to_fcs_packet_len

 

is_l2_ok

 

l2_type

 

last_l2_ether_type

Last extracted value of etherType within ethernet header or VLAN tags

vlan_type

 

is_l3_ok

 

l3_type

 

is_ip_fragmented

 

is_ipv4_checksum_ok

 

is_l4_ok

 

l4_type

 

l4_type_ext

 

is_l4_checksum_ok

 

l4_src_port

 

l4_dst_port

 

encap_type

ROCE not currently supported

ipsec_layer

 

ipsec_syndrome

Valid only after hardware encrypt/decrypt 

psp_syndrome

Valid only after hardware encrypt/decrypt 

is_inner_l2_ok

 

inner_l2_type

 

inner_last_l2_ether_type

Last extracted value of etherType within inner ethernet header or VLAN tags

inner_vlan_type

 

is_inner_l3_ok

 

inner_l3_type

✘ 

 

is_inner_ipv4_checksum_ok

✘ 

 

is_inner_l4_ok

 

inner_l4_type

 

inner_l4_type_ext

 

random_value

 

ut_clock

 

fr_clock

 

source_qp

 

Operators

The P4-16 language specification lists a wide variety of operations that the language accepts for the supported data types (see Section 8). The table below lists the operators that are officially supported by the NVIDIA P4 compiler:

Operator

Compile-time value

P4Runtime value

Runtime value

Spec section

Bool && Bool

8.5

Bool || Bool

8.5

Bool == Bool

8.5

Bool != Bool

8.5

Bit<W> == Bit<W>

8.6

Bit<W> != Bit<W>

8.6

Bit<W> << integer



8.6

Bit<W> >> integer



8.6

Bit<W>[H:L]

8.6

All explicit casts between supported types

8.11.1

All implicit casts between supported types

8.11.2

Bit<W>..Bit<W>

 8.15.4

Assignment to user struct fields

8.16

Assignment to packet-in struct fields

8.16

All operations on header fields

8.17

Method calls

8.20

Function calls with positional args

✔ 

✔ 

8.20

Extern constructor invocations

8.21

Parser constructor invocations

8.21

Control constructor invocations

8.21

Package constructor invocations

8.21

Decrement (-=)

 ✔

-

Increment (+=)

 ✔

 

 

 -

We don't have a way to export this macro.

Variables

Variables are supported in accordance with the following spec items:

  • Constants (spec 11.1)

    • "Compile-time known values" are evaluated on a best-effort basis. It is possible that a compile-time known value may not be recognized by the compiler as such.

  • Variables (spec 11.2)

  • Instantiations (spec 11.3)

    • Instantiations with abstract methods (spec 11.3.1) are allowed in BlueField Target Architecture

    • Named arguments are not supported

Variables may be declared in any of the locations described in (spec 11.2) and follow the scope rules described there.

The compiler will emit errors for uninitialized values. In some cases where a struct is partially initialized, only a warning may be produced. In some cases there may be no error emitted when an uninitialized struct field is accessed. The accessed field will then contain an undefined value.

Control Apply Block

The following statements are supported in a control's apply block:

  • table.apply() calls

  • if statement

  • switch statement

  • extern function and method calls

  • assignment statements with the supported operators

  • the empty statement

  • return statements

The exit statement is not supported. The for loop is not supported.

All supported expressions are allowed within these statements, where applicable.

Table Apply

Calling the apply method on a table results in a return value two options:

  • bool hit

  • bool miss

Currently the field action_run is not supported.

Actions

Actions support the same statements as controls except for the following:

  • table.apply() calls

  • Conditional statements - if and switch

Actions support the same expressions as controls except for the following:

  • Boolean logical operators - &&, ||, ternary operator

  • Comparisons (==, !=, etc.)

Last updated: