Skip to content

Set Geneve encap source port using flow hash - #398

Merged
FelixMcFelix merged 8 commits into
mainfrom
felixmcfelix/fix-324
Oct 20, 2026
Merged

FelixMcFelix merged 8 commits into
mainfrom
felixmcfelix/fix-324

Conversation

@FelixMcFelix

Copy link
Copy Markdown
Contributor

This PR moves computation of any packet's flow hash (previously used for ECMP in the Router4/Router6 controls) to the head of packet processing. This allows us to use one flow hash to fill out the UDP source port for Geneve packets, and for ECMP as before.

This is slightly different to what we had before in two ways. The first is that this hash includes the IpProtocol value, and the second is that we will use the outer flow hash rather than the inner when decapping and forwarding. Part of why this is still valid is that OPTE already sets the encap source port to the flow hash, so hashing early still includes the entropy from the inner flow hash. This ended up needing to be done because I couldn't convince p4c to let me place an extra two Hashes into NatIngress.

This also fixes some of the external subnets & NAT unit ingress tests, which weren't actually generating the packet types we would have expected for each (we got all UDP, apparently!).

Fixes #324.

This PR moves computation of any packet's flow hash (previously used for
ECMP in the Router4/Router6 controls) to the head of packet processing.
This allows us to use one flow hash to fill out the UDP source port for
Geneve packets, and for ECMP as before.

This is slightly different to what we had before in two ways. The first
is that this hash includes the IpProtocol value, and the second is that
we will use the outer flow hash rather than the inner when decapping and
forwarding. Part of why this is still valid is that OPTE already sets
the encap source port to the flow hash, so hashing early still includes
the entropy from the inner flow hash. This ended up needing to be done
because I couldn't convince p4c to let me place an extra two `Hash`es
into `NatIngress`.

This also fixes some of the external subnets & NAT unit ingress tests,
which weren't *actually* generating the packet types we would have
expected for each (we got all UDP, apparently!).

Fixes #324.
Comment thread dpd/p4/sidecar.p4
}) & 0x3f;
// bits of the 16-bit hash calculated earlier to complete the
// 11-bit index.
fwd.ecmp_hash = 2w0 ++ meta.flow_hash[5:0];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a bit odd to be getting a bit<8> here with 6 bits occupied for select_route, but moving it from operating on a (bit<8>, bit<8>) to a (bit<6>, bit<5>) seemed like it'd be out of scope for this PR, particularly since res.slots is numbered 1--32 rather than 0--31.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting the former argument was actually painless, done so in a59506b.

@FelixMcFelix FelixMcFelix Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...or not. I'm getting a test failure in route_ipv6::fill_until_ipv6_filler_alloc_unavailable that I can't make sense of right now. I'm going to say there's not much value to get out of this change worth debugging that, at the minute.

Comment thread dpd/p4/sidecar.p4 Outdated
Comment on lines +9 to +13
if [ "$MULTICAST" == "" ]; then
TOFINO_STAGES=17
else
TOFINO_STAGES=19
fi

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the limits on main were 18 for non-multicast, and 20 for multicast. I kinda wish there were a way to be alerted when we go down in stage count. Do we know when things improved here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the framing here, going back: main's limit was 20 for both builds since #201 split multicast out as a separate feature but kept the one TOFINO_STAGES argument (a hard cap, as --stages becomes p4c's --num-stages-override).

The 18/20 has been what each build actually used, respectively. #208 (closed) had gotten these down to 16/19 with its refactoring of the pipeline, but none of that landed. Moving us to 17/19 here is great! It'll be awesome to combine this with #371, which also keeps the routing tables at full occupancy with @ways(8) (the table-size being finicky here is the same issue). With that work, multicast is always "on", as the feature flag goes away there.

@FelixMcFelix
FelixMcFelix marked this pull request as ready for review October 7, 2026 17:25
@FelixMcFelix FelixMcFelix self-assigned this Oct 7, 2026
Comment on lines +9 to +13
if [ "$MULTICAST" == "" ]; then
TOFINO_STAGES=17
else
TOFINO_STAGES=19
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the framing here, going back: main's limit was 20 for both builds since #201 split multicast out as a separate feature but kept the one TOFINO_STAGES argument (a hard cap, as --stages becomes p4c's --num-stages-override).

The 18/20 has been what each build actually used, respectively. #208 (closed) had gotten these down to 16/19 with its refactoring of the pipeline, but none of that landed. Moving us to 17/19 here is great! It'll be awesome to combine this with #371, which also keeps the routing tables at full occupancy with @ways(8) (the table-size being finicky here is the same issue). With that work, multicast is always "on", as the feature flag goes away there.

Comment thread dpd/p4/sidecar.p4 Outdated
Comment thread packet/src/lib.rs
Comment thread dpd-client/tests/integration_tests/common.rs
Comment thread packet/src/lib.rs Outdated
@FelixMcFelix
FelixMcFelix added this pull request to stack #407 October 16, 2026 11:35

@rcgoodfellow rcgoodfellow left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. one question on multicast level hashes below.

Comment thread dpd/p4/sidecar.p4
// Set L3/ECMP and L2/LAG multicast hashes using the packet's
// flow hash. This will include entropy from the inner flow, see
// the commentary on FlowHash.
ig_tm_md.level1_mcast_hash = meta.flow_hash[12:0];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not a question for this PR. @zeeshanlakhani are we using ECMP level 1 node types or LAG level 2 node types? Put differently, are level1_mcast_hash and level2_mcast_hash being used for anything? ref: section 5.7.3.1 in the TNA.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the review. I don't believe we are, from my read on #398 (comment). They're filled out pre-emptively I think.

I'm going to merge this just now, setting these fields (or not) seems like a #371 question.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, taking this on.

@FelixMcFelix
FelixMcFelix merged commit 9ffd5a1 into main Oct 20, 2026
6 checks passed
@FelixMcFelix
FelixMcFelix deleted the felixmcfelix/fix-324 branch October 20, 2026 12:59
zeeshanlakhani added a commit that referenced this pull request Oct 21, 2026
When merging forward the `main` branch's/bookmark's flow hash (#398)
work, two components broke in the combination:

- `level2_mcast_hash`: With `flow_hash[15:3]` being a shifted copy, this
  pushes `flow_hash` into a 32b container, and the egress decap bitmap
  no longer fits in PHV.
  - *fix*: level2 is now a `Hash<bit<13>>` over `{flow_hash, ingress_port}`
  - Note: Neither level has an ECMP/LAG node to incorporate at the moment
    per the #398 thread.
- With the changes upstream, p4c mistakenly reused the match register
  holding `dst_mac[39:32]` for the IPv4 protocol byte, causing IPv4
  multicast packets to be dropped due to "invalid MACs".
  - This existing IPv6 MAC check is also in the `Filter` control.
  - *fix*: the IPv4 mcast OUI (Organizationally Unique Identifier) check
    has been moved from the parser to the `Filter` control.

Includes:

- `TOFINO_STAGES=19` remains the same as `main` and is unconditional.
- Usable IPv4 route capacity doesn't change here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NAT encapsulated flows have one 5-tuple per sled

3 participants