diff --git a/specs/xena/vpnaas-ovn.rst b/specs/xena/vpnaas-ovn.rst new file mode 100644 index 000000000..6c7e9e8d2 --- /dev/null +++ b/specs/xena/vpnaas-ovn.rst @@ -0,0 +1,224 @@ +.. + This work is licensed under a Creative Commons Attribution 3.0 Unported + License. + + http://creativecommons.org/licenses/by/3.0/legalcode + +========================= +VPNaaS for OVN Networking +========================= + +This specification covers the support for VPNaaS with OVN networking by adding +a stand-alone VPN agent. This new agent will create a namespace on the node, +connect it with the OVN distributed logical router and run the Swan process in +the namespace. + +Problem Description +=================== + +The existing VPNaaS service plugin only supports the reference Neutron software +routers, such as neutron L3 router using the L3 agent. This approach does not +work if there is no L3 agent. For OVN a different solution is required. + +Proposed Change +=============== + +Add a new stand-alone VPN agent to support OVN+VPN. Add OVN-specific service +and device drivers that support this new VPN agent. This will have no impact +on the existing VPN solution, the existing L3 agent and its VPN extension will +still work. + +Changes on neutron server +------------------------- + +VPN service driver and Agent scheduler +++++++++++++++++++++++++++++++++++++++ + +The VPN service driver has different implementations for different VPNaaS +solutions. The existing implementation relies on the Neutron L3 router +scheduler to decide where the VPN service process is hosted and the VPN device +driver is part of the L3 agent. In OVN the L3 router scheduler and L3 agents +are not used anymore, so a replacement is required. + +For the newly-introduced agent type "VPN agent" +we also add a corresponding VPN agent scheduler. Using the OVN-related +scheduler for the router gateway port was ruled out because the VPN agent +scheduler should also keep track whether the VPN agent(s) are still alive. + +The new VPN agent scheduler will work on a per-router basis to have all IPSec +site connections of a router processed by the same agent. + +VPN gateway and transit network ++++++++++++++++++++++++++++++++ + +In the existing implementation for ML2/OVS the VPNaaS shares the router gateway +IP address with router SNAT, but for OVN the gateway public IP address (SNAT) +can't be shared with the VPN because SNAT is not in the namespace context. +A new public IP address is needed for the VPNaaS namespace, so a VPN gateway +port is created in the external network of the router. This address will be +visible as the external_v4_ip/external_v6_ip of the VPN service. + +To connect the router with the namespace a "Transit network" (169.254.0.0/30) +is created and attached to the router. It is used to route traffic between +virtual machine network(s) and the VPN process namespace. The respective routes +added to the router are (per peer CIDR): + +- destination CIDR: peer CIDR +- next hop: IP address of a port in the transit network (169.254.0.2) + +The new ports and the transit network and subnet are managed using the API of +the Neutron core plugin and OVN L3 router service plugin, not "under the hood" +with OVN functions, to avoid inconsistencies between the Neutron database and +OVN Northbound. This makes sure that scripts that sync Neutron DB and OVN +Northbound (like neutron-ovn-db-sync-util) don't delete lswitches that +were created for the VPNaaS transit network but have no corresponding Neutron +DB entries. + +The IDs of the newly added ports, transit network and subnet are stored in a +new database table "vpn_ext_gws" (for VPN external gateways). +The gateway port and transit network are created automatically when the first +VPN service of a router is created and are deleted after the last VPN service +of the router is removed. + +Naming of Neutron objects ++++++++++++++++++++++++++ + +- External gateway port for VPN: "vpn-gw-{router_id}" (with device owner + "network:vpn_router_gateway", device ID is the router ID) + +- VPN transit network: "vpn-transit-network-{router_id}" + +- VPN transit subnet: "vpn-transit-subnet-{router_id}" + +- Port in the VPN transit network, to be plugged by the agent in the VPN + namespace: "vpn-ns-{router_id}" (with device owner "network:vpn_namespace", + device ID is the transit subnet ID) + +Changes on VPN agent +-------------------- + +For OVN the VPN functionality is implemented in a new dedicated VPN agent using +new OVN specific device drivers. + +Configuration synchronization ++++++++++++++++++++++++++++++ + +The existing VPNaaS implementation uses rabbitmq RPCs to synchronize the VPN +configuration between the database and the IKE daemon (strongswan etc) +controlled by the agent. + +Ideally a VPNaaS solution for OVN would avoid rabbitmq. But currently there +is no support for configuring VPNs in OVN (via north/southbound databases). +While it is possible to configure IPSec for tunnel ports, it's not possible +to set up and configure IPSec site connections to external peers. + +To still be able to offer VPNaaS some other means than configuration via +OVN north/southbound tables is necessary. Possible solutions could be: + +1. Use rabbitmq RPCs as in the existing VPNaaS plugin. +2. Instead of rabbitmq, implement REST APIs on both ends (neutron server and + VPN agent). This includes API endpoints that let the agent know about + configuration changes (server -> agent), that allow agents to fetch the + current configuration (agent -> server) and that allow agents to report + state changes (agent -> server) + +The least complex implementation approach is (1) to rely on existing code +even if it is still using rabbitmq instead of rewriting the server/agent +communication with new REST APIs. + +VPN namespace management +++++++++++++++++++++++++ + +The agent creates a VPN namespace and plugs two ports: + +- the external gateway port +- a port in the transit network bound to 169.254.0.2 + +There will be one VPN namespace per router and it's scheduled on exactly one +VPN agent. The VPN agent shall make sure that only those VPN namespaces exist +on the node which are scheduled there. I.e. when the agent starts it will +synchronize with the controller and potentially delete superfluous VPN +namespaces and/or create missing ones. + +VPN namespaces are created by the VPN agent / device driver when the first +IPSec site connection of a router is created and are deleted if all IPSec site +connections of the router were deleted. + +Routes are configured in the namespace to route incoming traffic to the local +subnets (destination: local CIDR, next hop: router port of the transit network, +i.e. 169.254.0.1). These routes are updated whenever the IPSec site connection +configuration changes. + +The agent will + +1. create a namespace called "qvpn-{router_id}" +2. create two interfaces in the namespace: + + - vgxxxxxxxx-xxx, where xxxxxxxx-xxx is the prefix of the port UUID of the + VPN external gateway port (IP address in the external network) + - vrxxxxxxxx-xxx, where xxxxxxxx-xxx is the prefix of the port UUID of the + VPN transit network port (169.254.0.2) + +3. plug the two interfaces +4. add routes + +Liveness of the VPN agent ++++++++++++++++++++++++++ + +There are two ways how liveness checks could be implemented: + +1. Traditional way using rabbitmq. The VPN agent periodically reports its state + ("report_state" RPC). The server side plugin utilizes the + AgentSchedulerDbMixin functionality to keep track of alive agents and will + potentially reschedule VPN services if an agent is down. +2. Liveness check using OVN similar to OVN Metadata agent. The server sets + a new value of the "neutron:liveness_check_at" external_id in NB_Global, + the agent monitors SB_Global and will set an external_id in its chassis row + (external_id "neutron:ovn-vpnagent-sb-cfg") + +The second approach is more in line with the management of agents in the Neutron +OVN mech driver. + +VPN plugin configuration for OVN +-------------------------------- + +The OVN VPN plugin is an extension of the existing one in order to add the VPN +agent scheduler and status checks. + +The service plugin to be added to neutron.conf is +neutron_vpnaas.services.vpn.ovn_plugin.VPNOVNDriverPlugin + +For OVN there is a new dedicated service driver, so the service_provider +setting in neutron_vpnaas.conf will be: +VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ovn_ipsec.IPsecOvnVPNDriver:default + +There is a new agent type "VPN agent" + +- The agent binary is neutron-vpn-agent +- The agent configuration file is /etc/neutron/vpn_agent.ini +- The agent uses the VPN device driver configured in vpnagent/vpn_device_driver. + An example device driver entry is + vpn_device_driver = neutron_vpnaas.services.vpn.device_drivers.ovn_ipsec.OvnStrongSwanDriver + +Database impact +--------------- + +Two new tables are added to the neutron database: + +- vpn_ext_gws: keeps the IDs of the additional network items needed for VPN + services of a router (gateway port, transit network, subnet, port) +- routervpnagentbindings: keeps the VPN agent ID per router + +REST API and CLI impact +----------------------- + +There are no changes to the REST API or CLI of VPNaaS or Neutron. + +The external IP address of the VPN service is visible in its +external_v4_ip/external_v6_ip and will be different than the one of +the router. + +References +========== + +* https://bugs.launchpad.net/neutron/+bug/1905391