We run multiple teams on the same OpenStack platform, one project per team. Traffic between two projects always hairpins through the gateway nodes, even with DVR enabled. This is expected behavior, not a misconfiguration. Below is the technical summary of why.
What DVR distributes East-west between networks on the same router: routed locally on the ingress chassis, tunneled to the destination chassis. Fully distributed. North-south with a floating IP: the chassis hosting the VM performs the 1:1 NAT and answers ARP for the FIP on the external network. Distributed, but requires the provider network to be attached to every compute node and distributed FIP to be enabled. North-south with SNAT: centralized. The router’s external address is shared by all VMs behind it; it can be ARP-owned at only one point of the external segment, and the NAT state must live in a single conntrack table. It is pinned to a gateway chassis by design. DVR distributes only what it can bind 1:1 to a single chassis. Everything based on a shared, stateful address is centralized.
...