# neutron-0002 — CWE-407: O(n) list() conversion for set membership test in DVR scheduler

**Severity:** MEDIUM
**File:** `neutron/db/l3_dvrscheduler_db.py`
**Line:** 258
**Status:** PATCHED

## Description

`_get_dvr_routers_to_remove()` builds `router_ids` as a set (returned
from `get_dvr_routers_by_subnet_ids`), then constructs `related_router_ids`
by filtering out routers already in `router_ids`:

```python
router_ids = self.get_dvr_routers_by_subnet_ids(admin_context, subnet_ids)
# ...
related_router_ids = [r_id for r_id in related_router_ids
                      if r_id not in list(router_ids)]   # BUG
```

The expression `list(router_ids)` converts the existing set to a list
just for the `not in` check.  The list conversion discards O(1) set
lookup semantics, turning each membership test into O(|router_ids|)
instead of O(1).  For R related routers and S subnet routers the
comprehension costs O(R × S) instead of O(R).

## Fix

Remove the `list()` call — sets already support `not in` with O(1) cost:

```python
related_router_ids = [r_id for r_id in related_router_ids
                      if r_id not in router_ids]
```

## Patch

See `patch/neutron-0002.patch`

## Test

See `unit/NeutronDvrRouterFilterAlgorithm.java`

## Speedup

At R=S=500: ~500× fewer comparisons.
