Rewrite pack — neutron-fwaas — branch stable/2026.2
Branch
stable/2026.2@5303a4deed1e— repository https://opendev.org/openstack/neutron-fwaas — analysed on 2026-10-28. Other repositories:neutron-lib:@1ee72052251a,neutron:@eef1a0f7ee36,openstacksdk:@fbdc403819e0,python-openstackclient:@8bb083b83829,skyline-console:@806d200392ee,heat:@5872396e548c(allstable/2026.2clones in the OpenKeel workspace).
For OpenKeel, the target is an FWaaS v2 API served by the Go Neutron replacement, programming OVN Northbound ACLs (Kube-OVN or OVN). The agent path (iptables and OVS flows) is documented in files 01–05 for completeness. A Kubernetes-native rewrite does not need it.
1. Contents of _rewrite/
| File | Use in a rewrite |
|---|---|
[routes_stable-2026.2.json](_rewrite/routes_stable-2026.2.json) | route table extracted from the running Neutron pipeline (ML2/OVN + firewall_v2 + OVN driver): 17 real operations plus 6 Routes artifacts (/new, /{id}/edit), plugin method and file:line, policy, status, and the run-time attribute map of the three collections |
[openapi_stable-2026.2.json](_rewrite/openapi_stable-2026.2.json) | OpenAPI 3.0.3 built from the route table and the observed response schemas. x-neutron-validate and x-neutron-convert-to carry Neutron's validators; x-response-unwrapped marks insert_rule/remove_rule. Types and stubs only, not the authority on behaviour |
[api-ref_stable-2026.2.json](_rewrite/api-ref_stable-2026.2.json) | the 17 operations documented in neutron-lib:api-ref/source/v2/fwaas-v2.inc, with parameters and samples (paths prefixed neutron-lib:) |
[policies_stable-2026.2.json](_rewrite/policies_stable-2026.2.json), [policies_stable-2026.2.yaml](_rewrite/policies_stable-2026.2.yaml) | the 26 default oslo.policy rules with their deprecated forms |
[config_stable-2026.2.conf](_rewrite/config_stable-2026.2.conf) | server options of neutron-fwaas: [default_fwg_rules], [quotas], [service_providers] |
[config-agent_stable-2026.2.conf](_rewrite/config-agent_stable-2026.2.conf) | agent options [fwaas] (driver, enabled, conntrack_driver, firewall_l2_driver); not needed on OVN |
[schema-mysql-migrated_stable-2026.2.sql](_rewrite/schema-mysql-migrated_stable-2026.2.sql) | authoritative schema: the six FWaaS tables as created by neutron-db-manage upgrade heads on MariaDB 11.4 |
[schema-mysql_stable-2026.2.sql](_rewrite/schema-mysql_stable-2026.2.sql), [schema-postgresql_stable-2026.2.sql](_rewrite/schema-postgresql_stable-2026.2.sql) | DDL generated from the ORM models (tool _rewrite/tools/fwaas_model_ddl.py) |
[cases-ovn-acl_stable-2026.2.json](_rewrite/cases-ovn-acl_stable-2026.2.json) | 67 vectors of the OVN ACL translation recorded from the OVN driver unit tests (rule dict + direction → ACL row); replay 67/67 |
[cases-ovn-acl-matrix_stable-2026.2.json](_rewrite/cases-ovn-acl-matrix_stable-2026.2.json) | 868 generated vectors (every action × tcp/udp/sctp/icmp/ipv6-icmp/gre/any × IPv4/IPv6 × port forms × addresses × directions × positions 0 and 3, plus the 4 default ACLs), computed by the original function; replay 868/868 |
[cases-iptables-rule_stable-2026.2.json](_rewrite/cases-iptables-rule_stable-2026.2.json) | 8 vectors of the iptables rule conversion (agent path); replay 8/8 |
[replay-report_stable-2026.2.json](_rewrite/replay-report_stable-2026.2.json) | replay results of the three case sets |
[exchanges_stable-2026.2.json](_rewrite/exchanges_stable-2026.2.json) | 691 HTTP exchanges of the API unit tests (135 tests, 0 failures), paths normalised to /v2.0/fwaas/…. Evidence and examples for differential testing, not replayable: no seed |
[response-schemas_stable-2026.2.json](_rewrite/response-schemas_stable-2026.2.json), [.md](_rewrite/response-schemas_stable-2026.2.md) | response JSON schemas inferred per operation and status |
[observed-errors_stable-2026.2.md](_rewrite/observed-errors_stable-2026.2.md) | 43 (operation, status, type, message) combinations seen in the test run |
tools/ | fwaas_routes.py + neutron-fwaas-ovn.conf (route table), fwaas_model_ddl.py, fwaas_openapi.py, fwaas_http_infer.py, fwaas_vectors.py, and adapters/neutron_fwaas.py (conformance_capture adapter) |
Library versions used for the extraction: neutron 29.0.1.dev29 and neutron-lib 5.0.2.dev16 (local clones above), ovsdbapp 2.19.0, oslo.db 18.1.1, oslo.messaging 18.3.1, oslo.policy 6.0.1, SQLAlchemy 2.0.52, alembic 1.19.1, netaddr 1.3.0, Python 3.12.7.
2. HTTP behaviour that the contracts do not show
2.1 Pipeline
FWaaS requests go through Neutron's paste pipeline (neutron:etc/neutron/api-paste.ini:10), outermost first: cors, http_proxy_to_wsgi, request_id, catch_errors, osprofiler, authtoken (keystonemiddleware), keystonecontext, then extensions. That last one is Neutron's Routes ExtensionMiddleware, which matches /fwaas/... and hands the request to Controller (neutron:neutron/api/v2/base.py:445). So:
- 401 (token) wins over everything;
- then routing: an unknown path returns 404;
- then body preparation (400), policy (403/404), quota (409), and finally the plugin.
2.2 Error body
Always {"NeutronError": {"type": "<ExceptionClass>", "message": "<text>", "detail": ""}} (neutron:neutron/api/api_common.py:520). The type values to reproduce exactly are listed in 02 and _rewrite/observed-errors_stable-2026.2.md. Clients display message (openstacksdk openstacksdk:openstack/network/v2/firewall_policy.py:104).
2.3 Other cross-cutting rules
- Resource wrapper:
{"firewall_group": {...}}for create, update and show;{"firewall_groups": [...]}for list. **Exception:insert_ruleandremove_rulereturn the bare policy object** (neutron:neutron/api/v2/base.py:262). - **
fields=projection**,limit/marker/page_reversepagination withfirewall_groups_links,sort_key/sort_dir(emulated), and filters onis_filterattributes. These are Neutron generic behaviours, to take from the Neutron rewrite. - Hidden resources return 404, not 403 (01 § Cross-cutting).
tenant_idandproject_idare both returned. Standard attributes (created_at,updated_at,revision_number,tags) are returned although thestandard-attr-fwaas-v2extension is not advertised (§ 8).GET /v2.0/extensionslistsfwaas_v2(alias), "FWaaS v2", updated "2016-10-06T10:00:00-00:00" (neutron-lib:neutron_lib/api/definitions/firewall_v2.py:25).
3. Core algorithm: firewall group → OVN Port_Group and ACLs
The behaviour a rewrite must reproduce bit for bit, so that an existing OVN NB DB stays consistent after switching implementations.
3.1 Input model and validation
- Rule (DB row → dict):
id,action∈ {allow, deny, reject},protocol(iptables protocol name or null),ip_version∈ {4, 6},source_ip_address/destination_ip_address(string as entered:1.1.1.1stays1.1.1.1, not/32,neutron_fwaas/db/firewall/v2/firewall_db_v2.py:37),source_port/destination_port("N" or "a:b", rebuilt from the min/max columns,neutron_fwaas/objects/firewall_v2.py:105),enabled. - Validation (400 cases, all before any OVN write):
- ports only with tcp/udp (
neutron_fwaas/common/utils.py:21); - addresses of the rule's IP version (
neutron_fwaas/common/utils.py:36); - min ≤ max (
neutron_fwaas/common/utils.py:51); - protocol in the iptables protocol name list (
neutron-lib:neutron_lib/api/definitions/constants.py:29).
- ports only with tcp/udp (
- Group:
id,ports(router interface port ids),ingress_firewall_policy_id,egress_firewall_policy_id. Each policy gives an ordered rule list (firewall_policy_rule_associations_v2.positionascending,neutron_fwaas/db/firewall/v2/firewall_db_v2.py:77).
3.2 Names and constants
pg_name = "pg_" + group_id.replace("-", "_")(neutron:neutron/common/ovn/utils.py:367).Port_Group.external_ids = {"neutron:firewall_group_id": group_id}(neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:223).ACL.external_ids = {"neutron:firewall_rule_id": rule_id}, or"default_rule"for the four default drops (neutron_fwaas/services/firewall/service_drivers/ovn/constants.py:19,neutron_fwaas/services/firewall/service_drivers/ovn/constants.py:31).- Priorities: user rules
2000 - position, default drops1001(neutron_fwaas/services/firewall/service_drivers/ovn/constants.py:24). - Actions: allow →
allow-stateless, deny →drop, reject →reject(neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:99). - Direction: ingress →
from-lport+inport == @pg; egress →to-lport+outport == @pg(neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:27,neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:127). log = false,name = [],severity = [](neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:131).
3.3 ACL of one rule (pure function)
acl(pg, rule, dir): # neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:143
match = (dir == ingress ? "inport" : "outport") + " == @" + pg
if rule.ip_version == 4: v="ip4"; icmp="icmp4"; match += " && ip4"
elif == 6: v="ip6"; icmp="icmp6"; match += " && ip6"
if rule.source_ip_address: match += " && " + v + ".src == " + rule.source_ip_address
if rule.destination_ip_address: match += " && " + v + ".dst == " + rule.destination_ip_address
p = rule.protocol
if p in (tcp, udp, sctp): # neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:89
match += " && " + p
for (port, side) in ((source_port, "src"), (destination_port, "dst")):
if port: (a, b) = split(port, ":") (b = a if absent)
if a == b: match += " && p.side == a"
else: match += " && p.side >= a && p.side <= b"
elif p in (icmp, ipv6-icmp): match += " && " + icmp # chosen by ip_version, not by p
# any other p (gre, ah, esp, vrrp, numbers…) adds NOTHING: the ACL matches all traffic of ip_version
if rule.action == deny and rule.is_default: (action, prio) = (drop, 1001)
else: prio = 2000 - rule.position; action = {allow: allow-stateless, deny: drop, reject: reject}
return {port_group: pg, priority: prio, action, log: false, name: [], severity: [],
direction: (ingress ? from-lport : to-lport), match, "neutron:firewall_rule_id": rule.id}
The 935 vectors of § 1 fix every branch, including ipv6-icmp with ip_version 4 (gives icmp4) and icmp with ip_version 6 (gives icmp6).
3.4 Group programming
- Position numbering: per direction, the rules of the policy in order get positions 0, 1, 2…; disabled rules consume a position but produce no ACL (
neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:102). - Create (
neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:199):pg_add(name, acls=[], external_ids, may_exist)in its own transaction;- the 4 default ACLs (egress then ingress, v4 then v6,
neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:228) withpg_acl_add(may_exist=True); - in one transaction, the rule ACLs of both policies, then
pg_add_portsfor each port; - status
ACTIVEwith ports,INACTIVEwithout.
- Update: if the Port_Group is missing, recreate it as in create. Otherwise apply the port delta (
pg_add_ports/pg_del_ports if_exists). On any policy change, resetPort_Group.aclsto the 4 default ACL uuids (or re-add them if they are not exactly 4), then re-add all rule ACLs (neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:126). - Policy rule list changed / insert_rule: same reset and re-add for every group that uses the policy (
neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:157). - remove_rule / rule disabled: find, in
pg_acl_list(pg), the ACL whoseexternal_idsrule id and direction match, andpg_acl_del(pg, direction, its priority, recomputed match)(neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:198). - Rule enabled:
pg_acl_addof that rule only, at its current position (neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:108). - Rule changed:
db_set ACL match, actionon the matching ACL; the priority is unchanged (neutron_fwaas/services/firewall/service_drivers/ovn/acl.py:206). - Delete group:
pg_del(if_exists)(neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:305). - **
admin_state_upis ignored.** Ports of any kind other than router interfaces are refused upstream.
3.5 Ordering and determinism
- The ACL set of a Port_Group is fully determined by the policies, their rule order and
enabled. The order of ACL creation inside a transaction does not matter (OVN evaluates by priority). - Priority collisions: ingress and egress rules both start at 2000, but different directions never collide. A policy with more than 999 rules reaches the 1001 of the default drops, and positions ≥ 2000 give invalid priorities. The default quota of 100 rules per project prevents this in practice [inferred]. A rewrite should reproduce the formula, or refuse more than 999 rules per policy explicitly.
- Stateless allow: replies are not implicitly allowed. A rewrite that switched to
allow-relatedwould change the security semantics of existing deployments.
3.6 Test cases of the algorithm
- Format: conformance_capture
callscases,{"kind": "ovn-acl", "input": {"port_group", "rule", "direction"}, "expected": <ACL dict>}. Theiptables-rulekind has{"input": {"rule"}, "expected": "<iptables args>"}. - Coverage:
- recorded vectors (67): tcp/icmp IPv4, the three actions, both directions, and the 40 default-rule calls;
- generated vectors (868): udp, sctp, ipv6-icmp, protocols without mapping, IPv6, single ports and ranges, addresses on either side, positions 0 and 3.
- Replay (adapter
_rewrite/tools/adapters/neutron_fwaas.py,replay_casecalls the original function): 67/67, 868/868, 8/8 pass (_rewrite/replay-report_stable-2026.2.json). - Not encoded: the OVSDB transaction sequence (number and grouping of transactions), the
pg_acl_list-based lookups for delete and modify, and the Port_Group port changes. Test those against a real NB DB (§ 7). - The iptables vectors embed the action chain name
conformance_capt-accepted:neutron-l3-agentderives the prefix from the process name (neutron-l3-agent-acceptedin production) (neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py:420).
3.7 Performance
Each API write costs at most a few OVSDB transactions per affected group (03 § "Operations per API call"). A policy change rewrites every ACL of every group using it: O(groups × rules) ACL rows per request.
4. What the clients expect
| Expectation | Where the client relies on it |
|---|---|
Paths /fwaas/firewall_groups, /fwaas/firewall_policies, /fwaas/firewall_rules under the network endpoint, keys firewall_group(s) etc. | openstacksdk:openstack/network/v2/firewall_group.py:20, skyline-console:src/client/neutron/index.js:118 |
insert_rule/remove_rule return the unwrapped policy: the SDK merges the JSON straight into the resource | openstacksdk:openstack/network/v2/firewall_policy.py:97 |
on error, NeutronError.message is the displayed text | openstacksdk:openstack/network/v2/firewall_policy.py:104 |
insert_rule accepts firewall_rule_id, insert_before, insert_after | openstacksdk:openstack/network/v2/_proxy.py:6240, skyline-console:src/client/neutron/index.js:128 |
PUT ports replaces the list; OSC firewall group set --port / unset --port read the current ports and send the full new list | python-openstackclient:openstackclient/network/v2/fwaas/group.py:171, python-openstackclient:openstackclient/network/v2/fwaas/group.py:479 |
PUT firewall_rules replaces the ordered list | python-openstackclient:openstackclient/network/v2/fwaas/policy.py:61 |
list filters sent by the SDK include source_port, destination_port and firewall_policy_id, which the server does not declare as filters (is_filter false). The FWaaS plugin does not declare filter-validation support, so Neutron does not reject them (neutron:neutron/api/v2/base.py:156). What the DB layer then does with them is not verified [inferred, not tested] | openstacksdk:openstack/network/v2/firewall_rule.py:33 |
Heat's OS::Neutron::Firewall* resources require the extension alias fwaas (FWaaS v1) and call the v1 API, so they are unavailable against v2: no expectation to keep | heat:heat/engine/resources/openstack/neutron/firewall.py:31 |
5. Database strategy
- Reuse the migrated schema (
_rewrite/schema-mysql-migrated_stable-2026.2.sql, alembic branchneutron-fwaas, heads1007f519ea46+2a0d33e9ef63). It matches the models for columns, keys and foreign keys. Differences:- the migration names its unique keys (
uniq_firewall_rules_v20standard_attr_id,uniq_firewallgroupportassociation0port_id…) where the model DDL leaves them unnamed; - MariaDB adds implicit indexes on the FK columns (
ingress_firewall_policy_id,egress_firewall_policy_id,firewall_rule_id,firewall_group_id); - column order differs.
- the migration names its unique keys (
- Shared Neutron tables: each rule, policy and group owns a
standardattributesrow (resource_type=firewall_rules_v2,firewall_policies_v2orfirewall_groups_v2[inferred from the Neutron standard-attribute convention],revision_number, timestamps,description). Tags live in Neutron'stagstable.firewall_group_port_associations_v2.port_idreferences Neutron'sportswith ON DELETE CASCADE, so deleting a port silently removes it from its group without touching OVN. The router LSP disappears too, so OVN stays consistent. - Integrity kept by code:
- "one group per port" is also a DB unique key;
- policy in use (FKs without cascade on
firewall_groups_v2would raise an IntegrityError if the code check were skipped); - rule in use (cascade FK; the code refuses first);
- default resources (by name).
- No optimistic locking: no revision check on PUT, and the read-modify-write of the policy rule list and of the default group's ports has no lock (03 § Notable transactions).
- Dead column:
firewall_policies_v2.rule_count(never written). - Startup data: none. The default group is created lazily per project (01 § Default firewall group).
6. Authentication, policies, configuration and CLI
- Auth: keystonemiddleware in Neutron's pipeline; project-scoped tokens.
- Policies: the 26 rules of
_rewrite/policies_stable-2026.2.json, with oslo.policy semantics:role:member and project_id:%(project_id)s,role:reader…,rule:admin_only;field:firewall_groups:shared=Truefor read access to shared objects;:sharedsub-rules checked by Neutron when the body setsshared(attribute enforcement,enforce_policy: Truein the attribute map). The deprecated rules (rule:admin_or_owner,rule:regular_user) are still loaded whileenforce_new_defaultsis false.
- Configuration a drop-in must accept:
[service_providers] service_provider = FIREWALL_V2:<name>:<driver class>:default;[default_fwg_rules] *(15 options: action, addresses, ports, protocol, shared, enabled for the four default rules);[quotas] quota_firewall_group/policy/rule;service_pluginsmust includefirewall_v2.
- CLI:
neutron-db-manage --subproject neutron-fwaas upgrade(migrations, entry pointpyproject.toml:53);neutron-status upgrade check(fails if FWaaS v1 is still configured,neutron_fwaas/cmd/upgrade_checks/checks.py:30);neutron-ovn-db-sync-util --sync_plugin neutron_fwaas_nb_sync. For a Go rewrite, the sync function belongs in the controller's reconcile loop (§ 10).
7. Conformance strategy
- Pure translation: run the 935 OVN vectors and 8 iptables vectors against the Go ACL builder. They must produce identical dicts (
matchstring byte for byte, priority, action, direction, external_ids). - API:
- replay
_rewrite/exchanges_stable-2026.2.jsonas differential evidence: same requests, compare status,NeutronError.typeand body shape, ignoring ids and timestamps; - validate bodies against
_rewrite/response-schemas_stable-2026.2.json. The exchanges come from the original unit tests, which useDummyDriverDB(no back end,neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin_v2.py:73), so their statuses are those of the DB layer (CREATED/INACTIVE), not of the OVN driver.
- replay
- Black-box suite: the neutron-tempest-plugin clone of the workspace has an
fwaastest package (API and scenario tests; contents not inspected in this pack). Run it against the rewrite with OVN. - OVN end-to-end (not covered by any captured data): spin up an NB DB (ovsdb-server in a container) and compare, for a scripted sequence (create, update ports, insert, remove, disable, enable, delete), the Port_Group/ACL rows written by the original (neutron-server with the OVN driver) and by the rewrite.
- Original fixtures, for reference:
neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin_v2.py:54(API test base),neutron_fwaas/tests/unit/services/firewall/service_drivers/ovn/test_firewall_l3_driver.py(OVN driver with a mocked NB IDL).
8. Gaps found while building the pack
- **
standard-attr-fwaas-v2never loads**: the class inneutron_fwaas/extensions/firewall_v2_stdattrs.py:19is namedStandard_attr_fwaas, while Neutron's file-based loader expectsFirewall_v2_stdattrs(neutron:neutron/api/extensions.py:459). Seen at run time while building the route table: "Did not find expected name". A rewrite can advertise it (the attributes are there) or keep it hidden for strict compatibility. - No route table or api-ref inside the repository: the routes came from the running pipeline and the api-ref from neutron-lib.
- Exchanges without seeds: the HTTP tests build their data through the API itself, so the exchanges are not independently replayable.
- Test-harness workarounds (adapter
setup(), never in the repository): run in isolation, the OVN driver tests need Neutron's core options registered (setproctitle), and the iptables tests need the[fwaas]options registered. - Dead code:
FWaaSPluginApiMixin.set_firewall_status/firewall_deleted(v1 RPC);FirewallAgentApi.delete_firewall_group;process_services_sync;- the
neutron_service_pluginscheck; ProtocolNotSupported,FirewallGroupPortInvalidProject;rule_count,position.
- Misleading statuses and messages: 404 for
FirewallPolicyConflict,FirewallRuleSharingConflictandMechanismDriverNotFound; "of type Firewall Group" on default policies; "protocol is set to ICMP" for any non-tcp/udp protocol. - **The internal callback after a policy deletion is
AFTER_UPDATE** (neutron_fwaas/services/firewall/service_drivers/driver_api.py:272). - Protocols without OVN mapping produce an ACL that matches all IP traffic (§ 3.3). This is a security trap: a deny rule for
gredrops everything, and an allow rule forgreallows everything, of that IP version, at its priority.
9. Non-functional requirements
- Every API write is synchronous with the OVN NB DB. The NB connection must be up for any FWaaS write; reads only need the database.
- Expected scale (default quotas): ≤ 10 groups, 10 policies and 100 rules per project.
- Consistency with OVN must be restorable: provide a reconcile loop (the original only has the manual
neutron-ovn-db-sync-util, which does not remove stale ACLs). - List calls have a write side effect (default group creation) that must stay idempotent under concurrency (unique key on
default_firewall_groups.project_id).
10. Rewrite checklist
- [ ] Serve the 17 operations of
_rewrite/routes_stable-2026.2.jsonunder/v2.0/fwaas/, with Neutron's generic list, filter, field, pagination and sort semantics and theNeutronErrorbody. - [ ] Reproduce the attribute map (defaults, conversions such as case-insensitive
action, port range strings, IP strings kept as entered) fromneutron-lib:neutron_lib/api/definitions/firewall_v2.py:51. - [ ] Reproduce every business check of 01, with the statuses and
typenames of 02, including the "wrong" 404s. - [ ] Keep
insert_rule/remove_ruleresponses unwrapped. - [ ] Implement the default firewall group: lazy creation on list and group create, the
[default_fwg_rules]options, the reserved names, the restrictions on updating and deleting it. - [ ] Implement
auditedreset rules. - [ ] Implement the OVN translation of § 3.3 and pass the 935 vectors.
- [ ] Implement the Port_Group lifecycle of § 3.4 with identical names and
external_ids, so that an NB DB written by the original keeps working. - [ ] Refuse non-router ports (
FirewallGroupPortNotSupported), as the OVN driver does; or decide explicitly to support VM ports (new behaviour). - [ ] Use the migrated schema; create the
standardattributesrows; keep the unique key onport_id. - [ ] Load the 26 policy rules, including the
:sharedattribute rules andshared_firewall_*. - [ ] Emit
firewall_*.create/update/delete.start/.endnotifications if the Neutron rewrite emits them for other resources. - [ ] Add a reconcile loop that also removes stale ACLs and ports (improvement over the original sync).
- [ ] Decide on the stateless-allow semantics (keep
allow-statelessfor compatibility) and on the priority overflow above 999 rules. - [ ] Not needed on OVN: RPC topics
q-firewall-plugin/firewall_agent, L3/L2 agent extensions, iptables, conntrack, NFLOG logging.
Source: reverse-spec-neutron-fwaas/07-rewrite-pack_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.