Skip to content

fix(configapi): widen only a zero-length prefix of 0.0.0.0 to any - #604

Merged
gab-arrobo merged 1 commit into
omec-project:mainfrom
midwell:fix/zero-prefix-endpoint
Oct 22, 2026
Merged

gab-arrobo merged 1 commit into
omec-project:mainfrom
midwell:fix/zero-prefix-endpoint

Conversation

@midwell

@midwell midwell commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Summary

BuildSDFFilter writes every endpoint beginning 0.0.0.0 as any. A rule for 0.0.0.0/1, half the address space, is therefore installed as matching every address, and so is any other prefix of 0.0.0.0. The slice check from #593 accepts such an endpoint, since it is a valid prefix. ruleShapeOf uses the same test, so the shape count matched what was installed; the widening itself is the defect.

After this change:

  • A prefix of length 0 (0.0.0.0/0) is still written as any.
  • So is anything beginning 0.0.0.0 that does not parse as a single prefix: a bare 0.0.0.0, or an endpoint of several fields such as 0.0.0.0/1 80. Those are unchanged and still written as any. fix(configapi): refuse slices whose rules a UPF has no room to match #593's endpoint check refuses them, so only slices stored before it can hold them.
  • A bare 0.0.0.0 stays any because that is what was installed for it before, and it names no narrower set. Only a parsed prefix longer than 0 bits is now honoured.
  • A narrower prefix of 0.0.0.0, such as 0.0.0.0/1 or 0.0.0.0/30, is written as given, and ruleShapeOf counts it as its own prefix length.

Why /0 stays any:

  • SMF: it turns this filter into the packet filter it sends the UE. It treats a filter as match-all only when the endpoint is literally any (qos.IsMatchAllIPFilter). A prefix it encodes as a remote address and mask (buildPFCompAddr), which is right for 0.0.0.0/1.
  • PCF: it marks a rule's QoS as the default QoS flow when the filter ends any to assigned (hasDefaultQosFlow in polling/pcc_policy_config.go).
  • pfcpiface: it reads any as 0.0.0.0/0, so it parses either form.

Behaviour change:

  • The filter: a stored slice holding a prefix such as 0.0.0.0/1 pushes the narrower filter after an upgrade. Its rule then matches what it names, not every address.
  • The PCF: the rule is no longer flagged as the default QoS flow.
  • The shape count: the rule now counts as a shape of its own in validateUpfRuleShapes. A UPF that was within the shape limit only because the rule counted as the any-traffic shape can now be over it. The next post of a slice on that UPF is then refused until it is brought back under.

Testing

  • TestBuildSDFFilterWritesOnlyAZeroPrefixAsAny: 0.0.0.0/0, bare 0.0.0.0 and stored 0.0.0.0/0 80 and 0.0.0.0/1 80 are written as any, and 0.0.0.0/1, /30 and /32 as given.
  • TestValidateUpfRuleShapes:
    • New case: 0.0.0.0/1 is a ninth shape beside the seven prefixes and match-any.
    • Changed case: "rules that differ only in what does not change a mask" used 0.0.0.0/30 as a rule sharing the any-endpoint shape. That held only because of the widening, so it now uses 198.18.0.0/24, a second /24 address.
  • Before this change: both new tests fail on ffa24ba. The shape case answers 200, not 400, and /1, /30 and /32 are written as any.
  • Mutation check:
    • The old prefix test restored in both places fails both tests.
    • Restored in ruleShapeOf only, it fails the shape case.
    • Restored in BuildSDFFilter only, it fails the filter test.
  • Pre-commit: pre-commit run --all-files passes on macOS (darwin/arm64) on ebc71b5. That includes go test -race ./... -count=20 and golangci-lint v2.13.2.

🤖 Generated with Claude Code

@midwell
midwell requested a review from a team October 22, 2026 18:33
@gab-arrobo
gab-arrobo requested a balanced review from Copilot October 22, 2026 18:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused change keeps filter rendering and shape counting aligned, with regression coverage for corrected and preserved behavior and no unresolved findings.

No open issues 🎉

What changed in this PR

This PR prevents valid, nonzero-length prefixes beginning with 0.0.0.0 from being widened to any, keeping SDF filter generation and UPF rule-shape validation consistent.

Changes:

  • Shares the endpoint-widening check between filter rendering and shape counting.
  • Preserves existing behavior for 0.0.0.0/0 and legacy non-prefix endpoints.
  • Adds regression coverage for narrower prefixes and their effect on shape limits.
File Description
configapi/​slice_operations_test.go Adds filter and shape-limit regression cases and corrects an existing test fixture.
configapi/​slice_helpers.go Introduces a shared check that preserves valid narrower prefixes in filters and shape counts.

Review effort: Balanced

BuildSDFFilter wrote every endpoint beginning 0.0.0.0 as "any", so a
rule for 0.0.0.0/1, half the address space, was installed as matching
every address. ruleShapeOf mirrored the same test, so the shape count
was exact; the widening itself was the defect.

Only a prefix of length 0, or an endpoint beginning 0.0.0.0 that does
not parse as one prefix (a bare 0.0.0.0, or an endpoint of several
fields stored before the endpoint check), is still written as "any":
the SMF reads only "any" as a match-all packet filter, and the PCF only
a filter ending "any to assigned" as the default QoS flow. A narrower
prefix of 0.0.0.0 is written as given, and counts as its own shape.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
@gab-arrobo
gab-arrobo force-pushed the fix/zero-prefix-endpoint branch from ebc71b5 to e1e739c Compare October 22, 2026 19:27
@gab-arrobo
gab-arrobo merged commit 73282fd into omec-project:main Oct 22, 2026
13 checks passed
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.

3 participants