Skip to content

feat: per-batch scanner lock for concurrent discovery#2

Merged
simonmorley merged 2 commits into
mainfrom
feat/per-batch-scanner-lock
Mar 16, 2026
Merged

feat: per-batch scanner lock for concurrent discovery#2
simonmorley merged 2 commits into
mainfrom
feat/per-batch-scanner-lock

Conversation

@simonmorley
Copy link
Copy Markdown
Member

@simonmorley simonmorley commented Mar 16, 2026

Summary

  • Hold scanner mutex per-batch instead of per-scan in discover_bpf()
  • Build stealth profile per-request (clone) instead of mutating shared state
  • Concurrent scans now interleave batches rather than fully serializing

Part of the limpet concurrent scans work (Layer 3). Requires limpet-timing concurrent dispatch to actually exercise concurrency.

Test plan

  • cargo test --lib — 249 passed, 0 failed
  • Deploy to one scanner, run 2 concurrent limpet campaigns, verify both complete
  • Check BPF map for stale entries (shouldn't happen — LRU eviction)

Previously the scanner mutex was held for the entire batch-send phase,
serializing all concurrent discovery requests. Now each batch acquires
and releases the lock independently, with a per-request stealth profile
clone instead of mutating shared state. Concurrent scans interleave
their batches rather than fully serializing.
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the concurrency of discovery scans by refining how the scanner lock and stealth profiles are managed. By acquiring and releasing the scanner lock for each batch of probes and handling stealth profiles on a per-request, immutable basis, the system can now interleave multiple concurrent scans, leading to more efficient resource utilization and improved performance for parallel operations.

Highlights

  • Concurrency Improvement: The scanner mutex is now held per-batch instead of for the entire scan operation, allowing concurrent discovery requests to interleave their batches.
  • Stealth Profile Handling: The stealth profile is now built per-request and cloned for each batch, eliminating shared state mutation and the need to restore the original profile.
  • Performance: Concurrent scans can now interleave their processing, which is expected to improve overall throughput when multiple scans are active.
Changelog
  • src/engine.rs
    • Refactored the discover_bpf function to acquire and release the scanner lock for each batch of probes, rather than holding it for the entire scan.
    • Modified the stealth profile application to be per-batch using a cloned, per-request profile, removing the need to save and restore the scanner's original profile.
    • Ensured the scanner guard is explicitly dropped after each batch to release the lock promptly, facilitating concurrency.
Activity
  • The author has completed and checked the cargo test --lib step of the test plan, with 249 tests passed.
  • Two test plan items remain pending: deploying to a scanner for concurrent limpet campaigns and checking the BPF map for stale entries.
  • The pull request description indicates it was generated with Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

The changes successfully refactor the discover_bpf method to acquire the scanner mutex per-batch instead of per-scan. This enables concurrent discovery requests to interleave their batches, significantly improving concurrency for the scanning engine. The approach of building a per-request stealth profile and cloning it for each batch ensures that shared state is not mutated, maintaining correctness in a multi-threaded environment. The explicit dropping of the scanner guard within the loop is a crucial detail that ensures the lock is released promptly, allowing other tasks to acquire it between batches.

Comment thread src/engine.rs

// Drain AF_XDP RX ring between batches to prevent overflow
scanner_guard.poll_rx(0);
drop(scanner_guard);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The explicit drop(scanner_guard) here is critical for enabling the intended concurrency. Without it, the scanner_guard would remain in scope and hold the lock until the end of the for loop iteration, preventing other concurrent scans from acquiring the lock between batches of the same scan. This ensures the lock is released as soon as the batch operations are complete, allowing for true interleaving of batches from different requests.

Passthrough mode silently ran with raw socket TX when BPF had issues,
producing discovery results without timing data. Remove the config
option entirely so limpet either starts with full BPF or fails hard.
@simonmorley simonmorley merged commit ff79036 into main Mar 16, 2026
1 check failed
@simonmorley simonmorley deleted the feat/per-batch-scanner-lock branch March 16, 2026 17:00
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