Nate Foster: Verifying Programmable Network Data Planes

How p4v applies program verification to packet-processing code, and why its conclusions depend on control-plane assumptions.

NFNate FosterSpeaker · ProfessorRoRonSpeaker · Jane Street
Channel
Jane Street
Published
Nov 27, 2017
Video
1:13:25
Read
10 min
Slides
6
Original
English
Open on YouTube
Scroll to read and the video shrinks to the bottom-right corner. Captions follow your reading language.
Reading languageAvailable in 2 languages
You're reading the original English.
SUMMARY

In 30 seconds

Cornell researcher Nate Foster explains programmable data planes and P4, then demonstrates p4v, a verifier developed with collaborators at Barefoot and Yale. He shows how validity checks and counterexamples reveal bugs, and how ghost state expresses assumptions about control-plane table entries. He emphasizes that verification is exhaustive only within the model and stated assumptions.

  1. 1Proofs depend on modelsA correct proof can miss real-world behavior if its model or assumptions do not match the implementation.
  2. 2Match-action tablesP4 specifies a table’s schema, while the control plane supplies entries and actions.
  3. 3Counterexamples expose bugsThe verifier traces invalid header accesses and undefined output metadata in a router example.
  4. 4Control-plane assumptionsThe verifier records ghost state to express how table entries and actions must relate.
  5. 5Exhaustive within assumptionsThe tool analyzes all modeled executions for a stateless device, subject to any stated control-plane assumptions.

Takeaways

  1. Programmable data planes expose network behavior to software techniques but also introduce new classes of bugs.
  2. P4’s bounded state and restricted control flow make exhaustive symbolic analysis more tractable.
  3. Counterexamples can pinpoint paths that access invalid headers or leave forwarding metadata undefined.
  4. A proof of a data-plane property depends on the model and assumptions about control-plane table entries.
  5. Ghost state can record table behavior so assumptions are explicit and checkable.
  6. Multi-device state, queueing and usable tools for non-experts remain open challenges.
FULL TEXT

Read the edited text by chapter

Transcript only
01

Why verify networks?

Foster connects the internet’s origins to the operational challenge of modern networks. He argues for verification while warning that proofs depend on realistic models.

I have been an OCaml programmer for a long time, and I appreciate the tools and the work supported by Jane Street. I want to begin with the original ARPANET topology from the late 1960s and the design choices behind the internet.

Early architects faced a shift from circuit-switched telephone networks to packet switching. They also had to connect networks with different hardware and packet formats. The protocols they designed made this possible with decentralization and robustness as organizing principles.

Modern data-center networks are much larger and more complex. Operators manage thousands of switches running multiple protocols while facing demands for performance and sophisticated processing. An outage can cascade through a data center and affect services that depend on a public cloud.

Operators use practical techniques: high-level policy languages generate device configurations, monitoring and analysis examine those configurations, and tools such as ping and traceroute probe behavior. These methods work well much of the time, but high-profile failures still occur.

Could we bring software verification techniques to networking? We might automatically check connectivity, redundancy, isolation, forwarding loops and traffic balancing. An audience member observes that modern infrastructure is less decentralized; I distinguish the global internet from huge networks owned by individual organizations, which have different management needs.

Software-defined networking has created a new opportunity. Abstractions, APIs and languages now have reasonably precise semantics, so we can consider automatically checking network properties. I will describe a tool for verifying programmable data planes.

A caution: a proof is only as useful as its model and assumptions. A recently disclosed wireless protocol weakness illustrates how a correct formal proof can coexist with an end-to-end attack when the verification model does not match reality. We want practical tools connected to actual implementations rather than merely idealized models.

Our tool, developed with colleagues at Barefoot, checks properties of P4 programs. I will first explain software-defined networks and P4, then review program verification, and finally describe the tool.

02

SDN and programmable data planes

Control and data planes have different responsibilities. SDN separates them, and P4 provides a language for programming packet-processing pipelines.

Traditional network devices have two parts. The control plane runs software and protocols such as BGP and OSPF to discover topology, compute paths and manage policies. The data plane uses specialized hardware to apply those decisions and forward packets at high speed.

Software-defined networking tries to generalize packet-processing primitives and separate control from the devices. A controller can run on ordinary servers and direct many data planes; centralization of the controller is common but not essential. This makes it possible to express some network algorithms as ordinary programs rather than a separate distributed protocol on every device.

The early vision had a problem: common standards such as OpenFlow did not expose enough data-plane functionality in practice, and sophisticated switch support was difficult to obtain. Hardware designers pursued a more programmable data plane, resulting in fast chips programmable in the domain-specific P4 language.

The RMT architecture has two pipelines around a traffic manager. A parser extracts fields from arriving packets; ingress stages use memory, arithmetic units and state to process them. The traffic manager schedules traffic, an egress pipeline can modify headers after scheduling, and a deparser reconstructs the outgoing packet.

Programmable packet-processing pipeline
SLIDE 1 / 6Programmable packet-processing pipelineThe RMT diagram shows parsing, ingress, the traffic manager, egress and deparsing.

P4 provides a higher-level way to program such devices and can also target software switches and other architectures. It has familiar types and control flow as well as packet parsers and match-action tables. The design aims for predictable work and time per packet: state is bounded, pointers and complex data structures are absent, and ordinary program loops are excluded.

A program can exceed hardware resources and fail to compile, but on the chip I describe, a successfully compiled program runs at line rate. This predictability is central to the architecture. It also makes the programs especially interesting for verification.

03

Match-action tables and P4 programs

Tables specify matching and available actions while the control plane fills in entries. Programmable switches can implement conventional processing and new services.

A match-action table specifies which fields to read, how to match them, and which actions can run. For an Ethernet source address, a table might use exact matching and select either a learn action, which sends a digest to the control plane, or a no-op. It can also specify a default action and table size.

P4 and match-action tables
SLIDE 2 / 6P4 and match-action tablesThe slide connects P4 language restrictions to a table schema and example entries.

The P4 program defines the table schema, not the actual entries. The control plane fills in the matching rules and action choices at runtime. This division will matter when we try to verify a program without knowing how its tables will be populated.

A small Ethernet switch program declares headers and metadata, defines a parser and actions, and connects its tables in ingress and egress controls. A standard language and semantics make the packet-processing behavior explicit, rather than hiding it in device-specific configuration.

Programmability can enable more than conventional switching. One project placed a key-value cache on a switch in front of Memcached servers. The P4 program parses requests and uses switch memory for cached values, returning a hit immediately without contacting a server.

04

Errors and a verifier demonstration

P4 programs can access invalid headers or produce incorrect metadata. Foster uses counterexamples to find and repair errors in a small IPv4 router.

Programmability also opens up new errors. To reason about network-wide behavior we need to understand each device, and P4 programs can have subtle bugs. A header may be invalid, much as an object reference can be null; accessing an invalid header can produce an undefined value.

Dynamic validity checks can cost performance, which motivated this unsafe language design, though I dislike undefined values. Other problems include unhandled exceptions, incorrect metadata, inconsistent parsing and deparsing that creates malformed packets, and paths that bypass an access-control table.

The open-source switch.p4 parser illustrates the complexity: its state machine has roughly 50 states to handle Ethernet, VLAN stacks, IPv4, IPv6 and tunnels. A packet without a VLAN tag leaves that header invalid; reading it later may produce undefined behavior. The type system does not precisely document all such validity conditions.

Header validity and parser complexity
SLIDE 3 / 6Header validity and parser complexityThe switch.p4 parser illustrates how many paths determine whether a header is valid.

In the demo I use a smaller IPv4 router. Its parser extracts an Ethernet header and branches on its type field: IPv4 packets get an additional IP header, while other Ethernet packets proceed without one. The controls apply tables for routing and rewriting addresses.

Running our verifier without requesting a property succeeds trivially. Enabling the header-validity check instead fails and produces a counterexample: a trace of parser states, packet fields, tables and actions leading to an invalid access. The first failure involves the IPv4 checksum on an Ethernet-only packet.

I add a condition so checksum processing runs only when the IPv4 header is valid. A second counterexample reveals another unguarded IPv4 table access. Adding a validity guard there makes the check succeed: all analyzed paths now access valid headers.

Another property concerns standard metadata specifying the output port or a drop decision. That field is initially undefined, so a program must set it before the traffic manager needs it. The tool finds a path to the end of ingress on which the field has not been defined.

I add a table that drops the relevant non-IPv4 packets and invoke it in an else branch. The verification then succeeds. The example shows how automatically inserted safety assertions and readable counterexamples can help harden even a small working router.

05

Program logic and weakest preconditions

Guarded commands, assertions and assumptions provide a model for verification. Weakest-precondition formulas and an SMT solver establish properties or produce counterexamples.

The verification method builds on Hoare and Dijkstra’s work on reasoning about programs with logic. We translate P4 into guarded commands, an idealized imperative language, and generate a first-order formula. If the formula is valid, the assertions and other encoded properties cannot fail under the modeled conditions.

A Hoare-style triple relates a precondition, a command and a postcondition. It says that if execution starts in a state satisfying the precondition and the command terminates, the resulting state satisfies the postcondition. The precondition captures the assumptions under which the claim is made.

The guarded-command language includes expressions and logical formulas, assertions, assumptions, assignments, sequencing and nondeterministic choice. An assertion must hold when reached; an assumption discards executions that do not satisfy it. Assuming false discards everything, which is why assumptions must be treated carefully.

A normal conditional can be represented as nondeterministic choice between two branches, one assuming the condition and the other assuming its negation. Only the branch whose assumption holds contributes an execution. This small language is enough to represent the control flow we need.

Weakest-precondition reasoning starts with a command and a desired postcondition and computes a formula describing sufficient starting states. If the starting state satisfies that formula and the command terminates, the postcondition holds. The calculation is a syntactic translation over the program.

Weakest preconditions
SLIDE 4 / 6Weakest preconditionsThe predicate transformer computes a precondition sufficient for a desired postcondition.

Assertions contribute conjunctions, assumptions contribute implications, assignments substitute expressions, sequencing composes the transformations, and choice requires both branches to satisfy the property. A straightforward translation can create exponentially large formulas, so the tool uses a more efficient equivalent construction.

We use the Z3 SMT solver to check the resulting formula. Validity can be reduced to satisfiability by negating the formula: if the negation is unsatisfiable, verification succeeds; if it is satisfiable, its model supplies a counterexample from which we can construct a trace.

06

Modeling the control plane

P4 code does not specify the contents of its tables. Ghost state makes assumptions about those contents explicit, as illustrated by VLAN decapsulation.

A P4 program is only part of the overall behavior: it defines the processing pipeline and table schemas, but the control plane supplies table entries. Checking every possible table configuration can fail for real programs that depend on unstated control-plane assumptions. We need a way to describe those assumptions explicitly.

Consider VLAN decapsulation from switch.p4. Actions remove zero, one or two tags, and a table reads header-validity bits to choose among them. We want the packet to have no valid VLAN headers after the table runs.

VLAN decapsulation property
SLIDE 5 / 6VLAN decapsulation propertyThe example shows actions and a table whose correctness depends on control-plane choices.

Without assumptions the property fails: the control plane could install a rule that selects no-op for a packet with two tags. The intended behavior depends on the control plane pairing each pattern of validity bits with the right action. That relationship must be captured for the proof to mean what we intend.

We instrument the program with additional ghost state, which we call zombie state. It records table applications, hits, actions and data read. We can then state assumptions such as a particular table hitting or a double-tagged packet receiving the double-tag-removal action, and verify the data plane under those assumptions.

Ghost state for control-plane assumptions
SLIDE 6 / 6Ghost state for control-plane assumptionsInstrumentation records table behavior so assumptions can be expressed in the verification.
07

Implementation and future work

Foster describes the OCaml implementation, checks and optimizations. He outlines work on assumption synthesis, testing and harder network-wide properties.

The implementation uses OCaml and libraries including Core and Async; its front end handles the full language. The tool produces human-readable counterexamples and includes optimizations needed for scale. A design goal is to minimize annotations so non-experts can use it.

Built-in flags check standard properties such as valid header access and arithmetic overflow. With the optimizations, Foster reports that a large real program can be checked in well under a minute. The occasional annotations that remain express assumptions about the driver and control plane.

Ongoing work includes synthesizing control-plane assumptions from counterexamples, automatically generating test cases, and checking equivalence or differences between P4 program versions. Restricting the assumption language may make it possible to propose useful assumptions to programmers.

More broadly, networking is beginning to adopt techniques from programming languages: precise abstractions, compilers and runtimes. Important open problems include reasoning across multiple devices and shared state, quantitative properties such as congestion and load balancing, and tools usable by network engineers who are not formal-methods experts.

08

Questions on scope and usability

The discussion addresses exhaustive analysis, control-plane assumptions, queueing, type systems and restrictions on loops. Foster also explains how the tool inserts checks.

An audience member asks whether the demonstration verifies only specific inputs. I clarify that, for a single stateless device, the tool symbolically considers every possible execution within its model. The counterexample is a concrete witness to failure, not the only input examined.

The qualification is the control-plane assumptions. We exclude traces that violate stated assumptions, for example assumptions about table hits or action choices. A proposed runtime monitor could check those assumptions at the boundary between control and data planes, but we have not built it; alternatively, a verified control plane could establish them.

Asked about queuing and state, I explain that the traffic manager handles queues and that P4 communicates with it through metadata. Our tool can reason about those metadata bits, but it does not directly prove distributional claims such as weighted fair queuing or the absence of hot spots.

More detailed analysis would need an encoding of input packet distributions and their effect on outputs. At the time of the talk, most targets use fixed-function scheduling; programmable packet scheduler research could make verification of scheduling algorithms an interesting future direction.

An audience member asks why these checks are not expressed as a type system. I initially tried a type-based approach, inspired by work on typed assembly language. Existing P4 programs rely on invariants not captured by a simple compositional type system, so program-logic verification seemed more practical for current users.

With a fresh language design, a type-safe and memory-safe packet-processing language might deliver many standard safety properties while remaining efficient. It might require more annotations or runtime checks when programmers step outside the type system. That would be an appealing direction.

P4 generally excludes loops; parsers are an exception, but implementations typically unroll parser loops statically and reject programs that cannot be bounded appropriately. This restriction is one reason the data-plane analysis is tractable.

Could similar restrictions make control planes easy to verify? I am skeptical about push-button verification of existing control planes. Their software stacks are much larger than P4 data planes and are commonly written in general-purpose languages such as C and Java. A clean-slate design might provide better abstractions, but verifying existing stacks remains difficult.

Finally, an audience member asks how the checked properties are expressed. We work with Barefoot engineers to identify recurring bugs, then traverse the program’s abstract syntax tree and insert assertions—for example, before each header access. At present these visitors are ad hoc rather than a general domain-specific language for properties.

More from this channel

1:48:29EN
JSJane Street· Oct 16, 2026How AI Is Changing Programming: John Krazit and Ron MinskyRon Minsky, John Krazit · Jane StreetJane Street’s AI tooling lead and the Signals and Threads host examine agent infrastructure, security, code review and the changing experience of writing software.Coding agentsDeveloper productivityEvals+2
1:36:37EN
JSJane Street· Sep 23, 2026Aaron Bauer on Teaching Software Engineering in the Age of AIRon Minsky, Aaron Bauer · Jane StreetHow learning goals, active practice and editor design shape engineering education when models can generate the code.AI in EducationSoftware engineeringEducation+2
9 slides1:05:45EN
JSJane Street· Sep 11, 2026Cyrus Omar on Live Programming and a Computational Commons for Humans and AICyrus OmarA demonstration of Hazel shows how immediate feedback, structured collaboration and carefully scoped permissions could support people and AI agents working together.Programming LanguagesHuman-AI CollaborationDeveloper workflows & testing+2
1:25:00EN
JSJane Street· Sep 2, 2026Eric Mannes on Turning Messy External Data Into Trading ResearchRon, Eric Mannes · Jane StreetFrom commodity futures and an Excel risk system to point-in-time datasets and AI, Eric Mannes explains the domain knowledge behind data engineering at Jane Street.Data quality & curationDeveloper workflows & testingInvesting+2
7 slides1:16:29EN
JSJane Street· Aug 26, 2026Grant Sanderson and Alok Puranik: Positional Encodings Through Group TheoryGrant Sanderson, Alok Puranik · 3Blue1BrownStarting with assumptions about attention, they derive matrix exponentials and connect rotations, decay and Jordan blocks to RoPE and ALiBi.Transformers & attentionMathematicsML fundamentals+1
27:39EN
JSJane Street· Aug 21, 20263Blue1Brown and Jane Street on Trading, Machine Learning and CultureGrant Sanderson, Nitya, In Young, Craig, Alok · 3Blue1BrownGrant Sanderson talks with Jane Street colleagues about market making, shared compute, research and the paths that brought them to the firm.Machine LearningFintechCompany Culture+2