The `RangeAssigner` is a `NetworkAssigner` implementation that provides automatic IP address assignment using the `RangeStore` for efficient bitmap-based tracking.
## Overview
The `RangeAssigner` integrates with the network management system to provide:
- Automatic IP range initialization based on network CIDR blocks
- Sequential IP address assignment within network ranges
- Assignment tracking with custom identifiers
- IP address unassignment and reuse capabilities
- Integration with the `NetworkStore` lifecycle
+- Unified IP assignment querying through `Network.get_assignment()`
## Basic Usage
### Creating a Network with RangeAssigner
```rust
use store::network::{RangeAssigner, NetRange, BasicProvider, NetworkStore};
| `reserve_gateway` | Reserve first IP for gateway | `"true"`, `"false"` |
| `pool_size` | Maximum IPs to manage | `"100"`, `"1000"` |
| `start_offset` | Skip first N addresses | `"1"`, `"10"` |
## Range Initialization
-When a network is created with a `RangeAssigner`, the range is automatically initialized based on the network's CIDR block:
+When a network is created with a `RangeAssigner`, the range is automatically initialized within the same transaction based on the network's CIDR block:
- **IPv4**: Range size = 2^(32 - prefix_length)
- **IPv6**: Range size = min(2^(128 - prefix_length), 2^32) (capped for practicality)
+- **Range Name**: Defaults to the network name unless overridden with `with_range_name()`
+
+This ensures atomicity - either both the network and its range are created, or neither is created if the transaction fails.
### Examples
| CIDR | Usable IPs | Range Size |
|------|------------|------------|
| `192.168.1.0/24` | 254 | 256 |
| `10.0.0.0/16` | 65,534 | 65,536 |
| `172.16.0.0/12` | 1,048,574 | 1,048,576 |
| `2001:db8::/64` | Large | 2^32 (capped) |
-## Converting Bit Positions to IP Addresses
+## IP Address Assignment and Retrieval
+
+### Using Network.get_assignment() (Recommended)
-The `assign_ip()` method returns a bit position within the range. To convert this to an actual IP address:
+The easiest way to get IP assignments is through the `Network.get_assignment()` method:
+- **Assigner-agnostic**: Works with any `NetworkAssigner` implementation
+- **Type safety**: Returns `IpAddr` (IPv4 or IPv6) instead of raw bit positions
+- **Unified interface**: Same API regardless of underlying assigner type
+- **Error handling**: Returns `None` for networks without assigners
+- **Performance**: Efficient lookup using range scanning
## Best Practices
### Range Naming
-- Use descriptive, unique names for ranges
+- By default, ranges use the network name (recommended for simplicity)
+- Use `with_range_name()` only when you need multiple ranges per network
- Consider including network name: `"production-web-tier-range"`
- Avoid special characters that might cause issues
### IP Management
+- Use `Network.get_assignment()` for unified IP querying
- Always check return values from assignment operations
- Implement proper cleanup when devices are removed
- Monitor range utilization to prevent exhaustion
+- Use `get_assignment_by_bit_position()` for direct bit-to-IP conversion
### Configuration
- Set appropriate `pool_size` limits for large networks
- Use `reserve_gateway` for networks needing gateway addresses
- Document configuration choices for operational clarity
## Thread Safety
-The `RangeAssigner` uses the underlying `RangeStore` which provides thread-safe operations through `sled`'s transactional system. Multiple `RangeAssigner` instances can safely operate on the same range concurrently.
+The `RangeAssigner` uses the underlying `RangeStore` which provides thread-safe operations through `sled`'s transactional system. Multiple `RangeAssigner` instances can safely operate on the same range concurrently. Range initialization is atomic with network creation, preventing phantom ranges.
## Performance Considerations
- Assignment operations are O(n) in worst case, where n is the range size
- Consider smaller subnet allocations for very large networks
- Range lookups and unassignments are generally fast O(1) operations
-- Bitmap storage is memory-efficient even for large ranges
\ No newline at end of file
+- Bitmap storage is memory-efficient even for large ranges
+- `Network.get_assignment()` uses range scanning - O(n) for identifier lookups
+- `get_assignment_by_bit_position()` is O(1) for direct bit-to-IP conversion
+- Consider caching frequently accessed assignments for better performance