Skip to content

[sample #12602] [v2] feat(bpf): implement connection limit enforcement (QoS max connections)#238

Open
stevegaossou wants to merge 1 commit into
coc-sample-12602-v2-basefrom
coc-sample-12602-v2-head
Open

[sample #12602] [v2] feat(bpf): implement connection limit enforcement (QoS max connections)#238
stevegaossou wants to merge 1 commit into
coc-sample-12602-v2-basefrom
coc-sample-12602-v2-head

Conversation

@stevegaossou

Copy link
Copy Markdown
Collaborator

Benchmark sample reproducing the as-first-reviewed state of projectcalico/calico#12602 (by @coutinhop).

This PR's diff equals what the human reviewers first saw: fork point 28ca14a6bd3e → earliest human-reviewed commit c265a80b36e2. The original PR drew 10 human top-level review comments — the ground truth to compare the Council's feedback against.

🤖 Generated for the Council of Claudes benchmark.

Mirrors the diff the human reviewers first saw on projectcalico#12602
('feat(bpf): implement connection limit enforcement (QoS max connections)' by @coutinhop) for the Council of Claudes benchmark.
base(fork)=28ca14a6bd3e2a50aff9c279a8f6e44c85b080f6  head(as-reviewed)=c265a80b36e2fa6a9750b4eafee390918262bf4a
@stevegaossou
stevegaossou requested review from Copilot and removed request for Copilot June 23, 2026 07:32
if ctKey.Proto() != 6 { // TCP only
return ScanVerdictOK, 0
}
if ctVal.Type() == TypeNATForward {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔎 Correctness — The scanner skips TypeNATForward but not TypeNATReverse entries, leading to double counting for service NAT.

Problem:
In Check(), NAT forward entries are skipped:
if ctVal.Type() == TypeNATForward { return ... }
but NAT reverse entries are not. For service traffic, both normal and NAT reverse entries may be present; counting the NAT reverse entry as well as the normal one will overcount.

Suggestion:
Skip NAT reverse too, or conversely only count TypeNormal:
if ctVal.Type() != TypeNormal { return ScanVerdictOK, 0 }
This avoids double counting across NATed paths.

}

for _, ipNet := range wep.Ipv4Nets {
ip, _, err := net.ParseCIDR(ipNet)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔎 Correctness — buildConnLimitPodInfo() uses net.ParseCIDR but the import for “net” isn’t shown in this file.

Problem:
The new function calls net.ParseCIDR; the diff only adds a new bpfconntrack import. If “net” isn’t already imported elsewhere in this file, this will not compile.

Suggestion:
Ensure “net” is imported in felix/dataplane/linux/bpf_ep_mgr.go:
import "net"
If it is already present elsewhere in the file’s import list, please disregard; otherwise, add it.

@github-actions github-actions Bot 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.

🔎 Council of Claudes — Correctness

Note

Correctness lens · bugs · completeness · concurrency · edge cases

3 potential correctness issues

  • The decrement-on-close path in BPF relies on a non-atomic “flag then decrement” sequence guarded only by reading/writing a CT entry flag. Two CPUs handling close packets for the same flow concurrently can both miss the flag and double-decrement the QoS counter before either write becomes visible. This can transiently undercount connections and allow extra connections until the scanner corrects it.
  • The connlimit scanner recounts skip NAT forward entries but not NAT reverse entries. Counting NAT reverse entries will double-count service connections in many paths.
  • In bpf_ep_mgr.go, the new buildConnLimitPodInfo() uses net.ParseCIDR but the diff doesn’t show adding an import for the net package in that file. If net wasn’t already imported, this won’t build.

🤖 Council of Claudes · 2 inline comment(s)

// true count to the cali_qos BPF map. This corrects any drift from LRU
// eviction or connection close without explicit decrement.
//
// The BPF dataplane increments the count on new TCP SYN. This scanner

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — The comment states the scanner “serves as the sole decrement mechanism,” but the code also decrements in the BPF packet path on FIN/RST and in conntrack_cleanup. This is misleading for future maintainers.

  • Reword to something like: “The BPF dataplane increments on SYN and decrements on FIN/RST; the scanner periodically recounts established connections and overwrites current_count to correct drift from silent purges (idle TCPEstablished, half-close, partition, LRU eviction).”

return nil
}

// buildConnLimitPodInfo builds the pod IP → ConnLimitPodInfo mapping from

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — buildConnLimitPodInfo rolls its own net.IP-to-map-key conversion (string(ip.To4()/To16())). The scanner has a similar ipToString helper.

  • Factor this into a small shared helper (e.g., a tiny internal util in felix/bpf/conntrack or qos) to avoid drift, and add a unit test to validate both IPv4 and IPv6 key generation match on both producer and consumer sides.

FlagSetDSCP uint32 = (1 << 15)
FlagMaglev uint32 = (1 << 16)
FlagSendRST uint32 = (1 << 17)
FlagConnLimitIn uint32 = (1 << 18)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — New CT flags (FlagConnLimitIn/Rej/Out/Dec) are added to FlagNames but lack a small unit test. Since FlagNames is used for debug/logging, drift here can silently degrade diagnosability.

  • Add a concise unit test asserting that the string names appear when corresponding bits are set (including a combination containing existing flags to catch future regressions).

Comment thread felix/bpf-gpl/qos.h

// 2*IFACE_STATE_MAP_SIZE because it will potentially have 2 entries for each interface (ingress/egress)
CALI_MAP(cali_qos,,
CALI_MAP(cali_qos, 2,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — The QoS BPF map version was bumped to 2 (good), and new fields were added. The header comment still only mentions “packet rate” and does not call out the new connection-limit fields or the map version.

  • Expand the comment above calico_qos_val and the map definition to describe max_connections/current_count semantics (0=disabled), locking, and to note that this is version 2 of cali_qos to aid future readers syncing userspace/BPF layouts.

return qosKey.AsBytes(), newVal.AsBytes(), true
}

// ipToString converts a net.IP to a string key for map lookup.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — ipToString is critical glue (keys are raw IP bytes in Go string form), but there’s no direct test for the IPv6 branch.

  • Add a unit test passing an IPv6 address to ensure the string key matches what buildConnLimitPodInfo produces for v6 nets; this guards against accidental To16/To4 mismatches.

default:
Expect(true).To(BeFalse(), "hook must be either 'ingress' or 'egress', '%s' is invalid", hook)
}
qosMapName := qos.MapParams.VersionedName()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — getBPFQoSValue and dependent helpers key direction with magic numbers (ingress=1, egress=0) and duplicate parsing logic.

  • Consider using small constants (e.g., qos.DirectionIngress/DirectionEgress) or at least local consts with a single helper to encode the direction. This reduces copy-paste errors and aligns with qos.NewKey’s semantics.

// TestConnLimitScannerBatchesActiveCountUpdates verifies that IterationEnd
// batches updates for entries whose counts changed, preserves the packet-rate
// fields, and leaves unchanged entries alone.
func TestConnLimitScannerBatchesActiveCountUpdates(t *testing.T) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — The batching tests nicely cover active updates/no-op/zeroing. Given the reliance on unix.BPF_F_LOCK, add one small assertion that failed BatchUpdate propagates a warning but doesn’t panic (simulate f.batchUpdateErr != nil and assert behavior). This guards the error path and makes future refactors safer.

}

It("should limit connections correctly", func() {
It("should limit connections correctly (connlimit counter)", func() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧪 Maintainability & Tests — The test mixes iptables/nftables and BPF-mode branches in a single, long scenario. For long-term maintainability and to reduce conditional complexity:

  • Consider moving the BPF-specific connlimit FV into a bpf_*_test.go file (following the existing pattern) so it’s easy to reason about per-dataplane expectations and tailor timeouts/setup independently.

@github-actions github-actions Bot 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.

🧪 Council of Claudes — Maintainability & Tests

Tip

Maintainability & Tests lens · simplicity · tests · docs · idioms

Well-tested with solid UT/FV additions, but missing BPF design/doc updates and a few maintainability nits (dead macro, a misleading comment, and a potentially slow/flaky FV wait).

High-level/architectural

  • BPF design/docs need updating per repo rules. This PR adds new CT flags, expands the QoS map layout, introduces new global flags, and changes the packet path (accepted_entrypoint/new_flow) plus a new CT scanner. Please update the relevant design docs in the same PR:
    • felix/design/bpf-overview.md: summarize the ingress/egress connlimit admission logic at WEP tc ingress/egress; explain fast-path decrement on FIN/RST and cleanup-time decrement; retransmission rejection behavior.
    • felix/design/bpf-conntrack-flowstate.md: document the new CT flags (CALI_CT_FLAG_CONNLIMIT_{INGRESS,EGRESS,REJECTED,DEC}; Go: FlagConnLimit{In,Out,Rej,Dec}) — where they’re set/cleared (first SYN, new_flow egress mark, reject mark, decrement path), and how the scanner treats DEC.
    • felix/design/bpf-maps.md (or the sub-design covering QoS): describe cali_qos v2 layout (max_connections and current_count), locking (spin_lock), reader/writer responsibilities (BPF fast-path increments/decrements; periodic userspace recount), and the version bump rationale.
      Suggested ready-to-paste prompt:
    • @copilot update felix/design/bpf-conntrack-flowstate.md "Flags & state in CT entries" to cover CALI_CT_FLAG_CONNLIMIT_{INGRESS,EGRESS,REJECTED,DEC} — when they are set, how they’re used in admission and decrement paths, and how the scanner skips DEC-marked entries.
    • @copilot update felix/design/bpf-maps.md "cali_qos (QoS & connection limits)" to add the v2 layout (packet-rate fields + max_connections + current_count), BPF spin_lock use, and recount semantics (ConnLimitScanner) with version-bump notes.
    • @copilot update felix/design/bpf-overview.md "Admission at WEP ingress/egress" to include connection-limit checks, fast-path decrement on FIN/RST, cleanup-time decrement, and retransmit rejection via CONNLIMIT_REJECTED.
  • Tests are commendably thorough (new unit tests for the scanner, extended FV including BPF-only scenarios). However, a couple of FV waits rely on long sleeps in Eventually loops; consider exposing a test knob to shorten the scanner sampling (or signal a recount) to reduce runtime and flake risk.
  • Minor duplication: two places convert IPs to raw-byte string map keys. Consider a small shared helper to avoid drift and ease future refactors.
  • Small dead code and a misleading comment add future-reader cost; see line notes.

Line-specific findings

🤖 Council of Claudes · 8 inline comment(s)

Comment thread felix/bpf-gpl/tc.c
* flag), otherwise allow (the connection was already accepted and counted).
* The Go-side CT scanner periodically recounts and corrects drift.
*/
if (CALI_F_TO_WEP && !policy_skipped &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛡️ Security — The ingress connection limit check is gated on “!policy_skipped”:

  • Risk: If policy_skipped is true for traffic to a WEP (e.g., due to a fast-path or a “skip policy” condition), the configured connection limit is not enforced, allowing unlimited new TCP connections despite the QoS limit. This is a policy enforcement bypass that weakens isolation.
  • Mitigation: Ensure that connection limits are enforced independent of policy_skipped (unless there’s a deliberate and documented exception). Either:
    • Remove the policy_skipped clause from this check, or
    • Guarantee that policy_skipped is never set for traffic to workloads with configured conn limits (and document that invariant), and add a unit/FV test to prevent regressions.

Comment thread felix/bpf-gpl/conntrack.h
if (!(cl_flags & (CALI_CT_FLAG_CONNLIMIT_INGRESS | CALI_CT_FLAG_CONNLIMIT_EGRESS))) {
return;
}
ct_value_set_flags(v, CALI_CT_FLAG_CONNLIMIT_DEC);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛡️ Security — qos_connlimit_decrement_for_ct sets CALI_CT_FLAG_CONNLIMIT_DEC then decrements without synchronization:

  • Risk: Two CPUs handling close events for the same flow can race: both read flags without DEC, both set DEC, and both call qos_connlimit_decrement(), resulting in a double-decrement (under-enforcement). Similarly, first‑SYN handling (see below) can race to double-increment. The periodic scanner eventually corrects drift, but within the scan window (~30–60s), limits can be under‑ or over‑enforced (allowing more connections than configured or causing spurious denials).
  • Mitigation:
    • Make DEC setting + decrement atomic per-CT entry. Options include adding a bpf_spin_lock to the conntrack value struct and using it around flag checks/updates, or using an atomic bit test-and-set helper if available. If modifying the CT value is too costly, consider a per-flow dedupe (e.g., a small LRU set keyed by CT key hash) to gate decrements to once-per-flow close.
    • Tighten scanner cadence when connlimits are configured to reduce the correction window.
    • Add FV that stresses concurrent close on the same flow to guard against regressions.

Comment thread felix/bpf-gpl/conntrack.h
* CT_RES_CONNLIMIT_FIRST_SYN is set in the result ONLY on the
* first SYN, so the accepted_entrypoint knows to increment.
*/
if (CALI_F_TO_WEP && INGRESS_CONN_LIMIT_CONFIGURED) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛡️ Security — First‑SYN marking for ingress (sets CALI_CT_FLAG_CONNLIMIT_INGRESS and signals CT_RES_CONNLIMIT_FIRST_SYN):

  • Risk: This write is also unsynchronized. Parallel handling of SYN/SYN-ACK (or rapid retransmits) on multiple CPUs can race before the flag is visible, causing multiple “first‑SYN” observations and therefore multiple increments. The result is transient over‑enforcement (fewer connections allowed) until the scanner corrects the count.
  • Mitigation:
    • As above, add synchronization around the CT flag update (per‑CT spinlock or atomic bit test-and-set) to ensure single‑writer semantics.
    • Alternatively, derive the acceptance-side increment solely from a single well-defined entrypoint (e.g., only from calico_tc_skb_new_flow_entrypoint on the opener side) and avoid relying on unsynchronized shared CT flags to gate first‑time increments.

@github-actions github-actions Bot 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.

🛡️ Council of Claudes — Security

Caution

Security lens · validation · secrets · authz · isolation

2 potential security issues

  • The new connection-limit enforcement in BPF relies on best‑effort flagging in conntrack entries to ensure single increment/decrement. Those flag writes aren’t synchronized, which can race across CPUs. In the worst case, this can either double-decrement (under‑enforcement) or double-increment (over‑enforcement) the QoS counter until the periodic scanner corrects it. That creates a correctness window where limits may be bypassed or cause unintended denial of service.
  • Ingress enforcement is gated on a “policy_skipped” condition. If that flag is ever set for a workload that has a configured connection limit, the check is skipped entirely — a potential enforcement bypass depending on how policy_skipped is set in the call chain. This should be reviewed to ensure that configured QoS limits cannot be disabled by policy fast‑path/skip conditions.

🤖 Council of Claudes · 3 inline comment(s)

Comment thread felix/bpf-gpl/tc.c
* Atomically check the limit and increment the counter in the QoS map.
* The Go-side CT scanner periodically recounts and corrects drift.
*/
if (CALI_F_FROM_WEP && state->ip_proto == IPPROTO_TCP &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nell Nell — Do we want to gate this on the global “egress connlimit configured” flag to avoid a QoS map lookup when the feature is off? Something like:

Suggested change
if (CALI_F_FROM_WEP && state->ip_proto == IPPROTO_TCP &&
if (CALI_F_FROM_WEP && state->ip_proto == IPPROTO_TCP &&
EGRESS_CONN_LIMIT_CONFIGURED &&
!(state->flags & CALI_ST_SUPPRESS_CT_STATE)) {

(We do that for marking the CT ctx a few lines below; feels consistent.)

}
applied, err := s.qosMap.BatchUpdate(batchK, batchV, unix.BPF_F_LOCK)
if err != nil {
log.WithError(err).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nell Nell — We warn then continue if the BatchUpdate fails. Return path doesn’t exist here, but should we at least increment a metric/counter so this is visible in health/metrics? Otherwise persistent failures silently leave stale counts. WDYT?

func (s *ConnLimitScanner) prepareUpdate(ifindex, direction uint32, count int32) (keyBytes, valBytes []byte, changed bool) {
qosKey := qos.NewKey(ifindex, direction)
qosValBytes, err := s.qosMap.Get(qosKey.AsBytes())
if err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nell Nell — On QoS map Get error we log at Debug and drop the update. That’s probably OK for ENOENT (no limit), but for other errors do we want a metric too? (I think best-effort is fine — just checking we intended to swallow non-ENOENT here.)

@github-actions github-actions Bot 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.

Nell Council of Claudes — Nell

Important

Nell lens · simulated reviewer · simplicity · naming · error handling · keep useful comments

2 potential correctness/perf nits; a few polish items and a doc-update ask

Broadly looks solid — flags line up, map version bump matches in-kernel/userspace, and you’ve covered the decrement paths with both packet-path and cleanup. Nice tests, especially exercising FIN vs RST and the cleanup-time decrements.

Two things I’d like us to tighten:

  • For new TCP from a WEP, we unconditionally do a QoS map lookup; suspect we should cheaply gate that on EGRESS_CONN_LIMIT_CONFIGURED to avoid the extra lookup when the feature is off.
  • The connlimit scanner logs-and-continues on QoS map update/get errors. That’s probably OK given the “best-effort drift corrector” role, but can we at least surface a metric/counter so we can spot a broken QoS map?

Doc-update rule: this adds new CT flags and extends cali_qos with max_connections/current_count plus a background recount. Per the repo rule, can we update the BPF design to cover the new mechanics?

  • @copilot update felix/design/bpf-overview.md “Maps & flags” to list the new QoS fields (max_connections/current_count) and the new CT flags (connlimit-in/out/dec/rej) and what sets/clears them.
  • @copilot update felix/design/bpf-qos.md (or the matching QoS/conntrack sub-design) “Connection limit enforcement” to describe: first-SYN marking, increment path(s), decrement on FIN/RST and on cleanup, and the periodic recount (trigger, scope, and downsampling).

Line-specific findings

🤖 Council of Claudes · 3 inline comment(s)

}

// Add connection limit scanner as a low-frequency drift safety net.
// It piggybacks on the CT scan loop but downsamples its recount work

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — I think this comment is inconsistent with the scanner’s own constant? In connlimit_scanner.go the downsample is N=3 with a 10s parent scan → “roughly every 30s”, but here it says “roughly every 60s.” Can we standardize this so the comment matches reality (or reference the constant)?

Suggested change
// It piggybacks on the CT scan loop but downsamples its recount work
// ... it downsamples internally (see connLimitScannerRunEveryN), so the actual recount runs roughly every 30s by default.

Eventually(func() int32 {
tc.Felixes[0].Exec("calico-bpf", "conntrack", "clean")
tc.Felixes[1].Exec("calico-bpf", "conntrack", "clean")
time.Sleep(12 * time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — I am a little bit skeptical of this sleep-inside-Eventually pattern — we try to avoid sleeps since they can sneakily add minutes across the suite. Could we make the scanner cadence configurable for tests (e.g., env var to set N=1 or a “force recount” debug hook) and then poll without an explicit Sleep? Even better if we can observe a concrete condition to drive progress instead of time.

@@ -234,7 +234,12 @@ var _ = infrastructure.DatastoreDescribe(
if _, ok := infra.(*infrastructure.EtcdDatastoreInfra); ok && BPFMode() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — I think this self-skip might fall into the “tests that silently don’t run” bucket we’ve been trying to avoid. If this test genuinely requires a non-etcd datastore in BPF mode, can we fail explicitly with a clear reason (or gate it behind a label that CI selects)? For example:

Fail("This test requires Kubernetes datastore in BPF mode; etcd+BPF is not supported for QoS connlimit FVs.")

If FV is different than e2e here and we do want to skip, fine to leave as-is — just calling out the pattern.

return nil
}

// buildConnLimitPodInfo builds the pod IP → ConnLimitPodInfo mapping from

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — I wonder about the atomic.Pointer-to-map here. Returning a dereferenced pointer to a map header means readers share the same underlying map, which works because you rebuild-and-swap, but it’s easy to accidentally mutate from the reader. Would using atomic.Value with a plain map[string]ConnLimitPodInfo (and returning the map value), or returning a shallow copy, be simpler/safer? No big deal though if we keep it — the current comments do call out the single-writer.

ret; \
})

#define ct_value_clear_flags(v, f) do { \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — Looks like ct_value_clear_flags() is added but not used anywhere in this diff. Can this be removed for now? Dead helpers tend to invite bit-rot — we can add it back when we actually need clears.

}

By("Waiting for cleanup-time decrement after TCPFinsSeen expiry")
// 5s TCPFinsSeen + ~10s scan period + margin.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — This is sort-of a crazy long timeout cascade (5s CT timeout + ~10s scan + 30s Eventually windows). I think the intent is good (exercise cleanup-time decrement), but can we trim this by: (a) lowering the downsample in tests, (b) tightening the CT scan period for FV, or (c) adding a test-only hook to kick the recount? Avoiding 30s Eventuallys would help keep the suite lean.

return
}

log.WithField("counts", s.counts).WithField("numPods", len(s.podInfo)).Debug("ConnLimitScanner: recount done")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — Nit: nice debug log — could we also include the downsample factor or a “skipped” counter somewhere? Not required, but it might help when diagnosing “why hasn’t the count updated yet?” in flakes. Fine to leave as-is, though.

Comment thread felix/bpf/qos/map.go
Name: "cali_qos",
Flags: unix.BPF_F_NO_PREALLOC,
Version: 1,
Version: 2,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Casey Casey — Good call bumping the QoS map version. Do we need to include any migration note in release docs so operators know a dataplane restart will happen (if applicable)? If not, ignore me — just flagging the cross-component implication.

@github-actions github-actions Bot 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.

Casey Council of Claudes — Casey

Warning

Casey lens · simulated reviewer · testing discipline · API design · simplicity · robustness

3 non-blocking issues; 1 documentation/update-rule gap

I think the overall shape looks good — the BPF fast-path plumbing (mark on first SYN, RST/FIN decrement, cleanup-time decrement) plus the low-frequency scanner as a drift safety net makes sense, and you’ve bumped the QoS map version correctly. I am a little bit skeptical of a couple of FV patterns (hard sleeps and long timeouts) that will add up across the suite, and there’s a small comment mismatch. Also, per our doc-update rule, this changes how the BPF dataplane works (new CT flags, new QoS map fields, enforcement points), so I think we need a design doc tweak to record the new bits (which flags, where they’re set, scanner cadence and what it does). WDYT about adding a short section to the relevant sub-design(s) — bpf-overview.md and the conntrack flow-state topic?

  • Tests/time cost: there are a few “sleep inside an Eventually” patterns and 30–60s Eventually windows that seem sort-of a crazy long timeout for FV — they’ll sneakily add minutes over the suite. If we can make the scanner cadence configurable (env var or a test hook to force a recount) and avoid Sleep(), we should do that IMO.
  • Doc-update rule: new CALI_CT_FLAG_CONNLIMIT_* bits, the decrement semantics (fast-path vs cleanup-time), and the cali_qos layout change should be captured under felix/design (bpf-overview + the CT flow-state design). If you drop an “@copilot update …” with the section names, we can iterate there.
  • Minor API shape: storing a pointer-to-map in an atomic and handing it out to other goroutines feels a bit brittle. Returning a fresh map (or using atomic.Value with a plain map value) would avoid accidental mutation and the double indirection — but I could be swayed either way if you prefer the current shape.

Line-specific findings

🤖 Council of Claudes · 8 inline comment(s)

stevegaossou added a commit that referenced this pull request Jun 24, 2026
- Iteration 2 (Lever-2 persona prompts), preliminary single-PR result
  (calico#12602 v2 #238 vs v3 #247): composition shifted as intended —
  Maintainability reflexive test-asks 3->0; Casey voice/focus recalibrated
  (naming appeared, skeptical catchphrase gone, briefer) per casey-report.html;
  no loss of substance. Flagged single-run/preliminary; real Nell/Casey human
  eval next.
- Document the input-required root cause (surfaced by the new poll diagnostics)
  and the planned fix (treat input-required/auth-required as terminal + prompt
  the orchestrator never to ask for input).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant