OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

neutron-fwaas — Scenarios

End-to-end scenarios — neutron-fwaas — branch stable/2026.2

Branch stable/2026.2 @ 5303a4deed1e — repository https://opendev.org/openstack/neutron-fwaas — analysed on 2026-10-28. neutron: = neutron @ eef1a0f7ee36.

1. Protect a router interface with the OVN driver

A project member creates a rule and a policy, then a group that applies the policy as the ingress policy of a router interface. Everything happens inside the API request (neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:199, neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:210).

sequenceDiagram
  autonumber
  actor U as Project member
  participant API as neutron-server (FirewallPluginV2 + OVNFwaasDriver)
  participant DB as MariaDB
  participant NB as OVN NB DB
  U->>API: POST /v2.0/fwaas/firewall_rules {tcp, dst port 22, allow}
  API->>DB: SELECT default fwg of project (create default rules/policies/group if missing)
  API->>DB: INSERT standardattributes, firewall_rules_v2
  API-->>U: 201 firewall_rule
  U->>API: POST /v2.0/fwaas/firewall_policies {firewall_rules:[r1]}
  API->>DB: INSERT firewall_policies_v2, firewall_policy_rule_associations_v2(position=1)
  API-->>U: 201 firewall_policy
  U->>API: POST /v2.0/fwaas/firewall_groups {ingress_firewall_policy_id, ports:[qr port]}
  API->>DB: SELECT policy (owner/shared), core get_port (device_owner router_interface)
  API->>DB: SELECT groups holding the port
  API->>DB: INSERT firewall_groups_v2 (CREATED), firewall_group_port_associations_v2
  API->>NB: OVSDB txn: insert Port_Group pg_<id> {external_ids neutron:firewall_group_id}
  API->>NB: OVSDB txn: 4 ACLs drop prio 1001 (ip4/ip6 × from-lport/to-lport)
  alt rule ACLs + ports OK
    API->>NB: OVSDB txn: ACL allow-stateless prio 2000 "inport == @pg && ip4 && tcp && tcp.dst == 22"; Port_Group.ports += LSP(qr port)
    API->>DB: UPDATE firewall_groups_v2 SET status='ACTIVE'; COMMIT
    API-->>U: 201 firewall_group (status ACTIVE)
  else OVSDB error
    API->>NB: OVSDB txn: delete Port_Group pg_<id>
    API->>DB: ROLLBACK
    API-->>U: 500 NeutronError
  end

Diagnostics:

  • 409 FirewallGroupPortNotSupported means a VM port was given: OVN supports router interface ports only.
  • 404 MechanismDriverNotFound means ML2 is not using the ovn mechanism driver.
  • 500: check the neutron-server log for "Failed to create_firewall_group_postcommit." and the NB connectivity.

Check the result with ovn-nbctl --columns=name,external_ids,ports,acls list Port_Group pg_<id with _> and ovn-nbctl acl-list pg_<…>.

Behavioural note: the allow ACL is stateless. Replies to the allowed SSH flow, which travel in the egress direction, are only allowed if the egress policy has a matching rule; otherwise the egress default drop (priority 1001) applies. Operators used to the iptables driver (RELATED,ESTABLISHED accepted, neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py:501) must write symmetric rules on OVN.

2. Change a rule used by several groups (OVN driver)

sequenceDiagram
  autonumber
  actor U as Project member
  participant API as neutron-server
  participant DB as MariaDB
  participant NB as OVN NB DB
  U->>API: PUT /v2.0/fwaas/firewall_rules/{id} {destination_port: "22:23"}
  API->>DB: SELECT policies with rule (same project) → groups using them
  alt a group is PENDING_*
    API-->>U: 409 FirewallGroupInPendingState
  else
    API->>DB: UPDATE firewall_rules_v2 (port range), policies.audited=false
    loop each policy of the old rule × each direction × each group
      API->>NB: pg_acl_list(pg) (IDL cache)
      API->>NB: OVSDB txn: db_set ACL <uuid> match="… tcp.dst >= 22 && tcp.dst <= 23" action=…
    end
    API->>DB: COMMIT
    API-->>U: 200 firewall_rule
  end

Disabling the rule (enabled: false) deletes the ACL instead (pg_acl_del), and re-enabling adds it back with its current position (neutron_fwaas/services/firewall/service_drivers/ovn/firewall_l3_driver.py:336).

Diagnostics: if the ACL is unchanged, look for "Cannot find Port_Group with name" in the server log (the group has no Port_Group, typically the default group). Check whether the rule was in a policy when it was changed: the update uses the old rule's firewall_policy_id list.

3. Reorder a policy with insert_rule (OVN driver)

sequenceDiagram
  autonumber
  actor U as Project member
  participant API as neutron-server
  participant DB as MariaDB
  participant NB as OVN NB DB
  U->>API: PUT /v2.0/fwaas/firewall_policies/{p}/insert_rule {firewall_rule_id: r3, insert_before: r1}
  API->>DB: groups using p not PENDING_*; r3 not already in p; r3 shared or same project
  API->>DB: DELETE associations of p; INSERT (r3,1),(r1,2),(r2,3); policy.audited=false
  loop each group using p
    API->>NB: OVSDB txn: Port_Group.acls = 4 default ACLs
    API->>NB: same txn: pg_acl_add for every enabled rule of the ingress and egress policies (prio 2000-pos)
  end
  API->>DB: COMMIT
  API-->>U: 200 {policy fields, not wrapped}

Diagnostics: during the transaction, the old rule ACLs are removed and the new ones added in one OVSDB transaction, so there is no window in which only the default drops apply [inferred from ovsdbapp transaction semantics]. A 400 FirewallRuleNotAssociatedWithPolicy means insert_before/insert_after names a rule that is not in the policy.

4. Protect a router interface with the agent driver (iptables)

sequenceDiagram
  autonumber
  actor U as Project member
  participant API as neutron-server
  participant DB as MariaDB
  participant MQ as RabbitMQ
  participant L3 as neutron-l3-agent (fwaas_v2) hosting the router
  participant L3b as other L3 agents
  U->>API: POST /v2.0/fwaas/firewall_groups {ingress policy, ports:[qr port]}
  API->>DB: INSERT group (PENDING_CREATE), port association
  API->>MQ: cast fanout create_firewall_group v1.0 (topic firewall_agent)
  API->>DB: COMMIT
  API-->>U: 201 (status PENDING_CREATE)
  MQ->>L3b: create_firewall_group
  L3b->>L3b: no local namespace hosts the ports → ignore (no reply)
  MQ->>L3: create_firewall_group
  L3->>L3: iptables-restore in qrouter-<id>: chains iv4/ov4/iv6/ov6<fwg>, FORWARD jumps -o/-i qr-xxx, fwaas-default-policy
  L3->>L3: conntrack -D in the namespace
  alt driver OK
    L3->>API: call set_firewall_group_status(ACTIVE) (topic q-firewall-plugin)
  else FirewallInternalDriverError
    L3->>API: call set_firewall_group_status(ERROR)
  end
  API->>DB: UPDATE firewall_groups_v2 SET status=? WHERE id=? AND status<>'PENDING_DELETE'
  U->>API: GET /v2.0/fwaas/firewall_groups/{id}
  API-->>U: 200 status ACTIVE / ERROR

Diagnostics:

  • The group stays PENDING_CREATE when no L3 agent hosts the router port, or when the agent's status call failed. Check the agent log for "FWaaS RPC failure in create_firewall_group", and remember that nothing resyncs it (05 § process_services_sync).
  • ERROR: check the agent log for "FWaaS driver error in create_firewall_group" and the iptables-restore output.
  • While the group is pending, every update of the group, its policies or its rules returns 409.

5. New VM port joins the default group (agent driver, OVS L2 extension)

sequenceDiagram
  autonumber
  participant Nova as nova-compute
  participant API as neutron-server
  participant DB as MariaDB
  participant MQ as RabbitMQ
  participant OVS as neutron-openvswitch-agent (fwaas_v2 L2)
  Nova->>API: PUT /v2.0/ports/{id} binding:host_id (vif_type unbound → ovs)
  API->>API: callback port AFTER_UPDATE → FirewallPluginV2.handle_update_port
  API->>DB: SELECT group 'default' of project
  API->>DB: UPDATE association (default fwg ports += port)
  Note over API: port not ACTIVE yet → no cast (default-group special case of the agent driver)
  OVS->>OVS: port appears on br-int → ext_manager.handle_port
  OVS->>API: call get_firewall_group_for_port(port_id)
  API-->>OVS: default group + rules (v1.1 OVO)
  OVS->>OVS: install flows tables 64-69 for the port
  OVS->>API: call set_firewall_group_status(ACTIVE)

Defined at neutron_fwaas/services/firewall/fwaas_plugin_v2.py:257, neutron_fwaas/services/firewall/service_drivers/agents/agents.py:327 and neutron_fwaas/services/firewall/service_drivers/agents/l2/fwaas_v2.py:354. Not applicable to OVN: the OVN driver refuses L2 ports, so VM ports are never attached to firewall groups on OVN.

6. Repair OVN after drift (neutron-ovn-db-sync-util)

sequenceDiagram
  autonumber
  actor Op as Operator
  participant CLI as neutron-ovn-db-sync-util
  participant DB as MariaDB
  participant NB as OVN NB DB
  Op->>CLI: --sync_mode repair --sync_plugin neutron_fwaas_nb_sync
  CLI->>DB: SELECT all firewall groups (except name 'default')
  CLI->>NB: list Port_Group with external_ids:neutron:firewall_group_id
  CLI->>CLI: WARNING counts and lists
  loop each Neutron group
    CLI->>NB: txn: Port_Group may_exist, 4 default ACLs may_exist, rule ACLs may_exist, add ports
  end
  loop each Port_Group without group
    CLI->>NB: txn: delete Port_Group
  end

Defined at neutron_fwaas/services/firewall/service_drivers/ovn/ovn_db_sync.py:129. Diagnostics: run --sync_mode log first and read the WARNING lines. Repair does not remove stale ACLs or extra ports inside an existing Port_Group. For a full rebuild, delete the Port_Group by hand and run repair again.

Source: reverse-spec-neutron-fwaas/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.