← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1949059] [NEW] ovn-octavia-provider: incorrect router association in NB when network is linked to more than 1 router

 

Public bug reported:

LB does not work when creating an Octavia LB with OVN provider in a
network containing multiple router interfaces.

When creating a loadbalancer using ovn provider, the OVN octavia driver agent creates a Load_Balancer entry and add several external ids, one of those being the Logical Router ID (lr_ref) to have the OVN LB properly work with an associated floating IP. This lr_ref association is repeated multiple times during the lifecycle of a LB : at create time (helper.py:lb_create) or when adding a listener,pool or pool member.
During LB creation, the driver agent tries to find the associated LR of every LS linked with the LB with helper.py:_find_lr_of_ls to add the LR IDs to the lr_ref external id field in OVN. The linked LS are the vip_network or the LS in which the pool members are.

The problem is the function _find_lr_of_ls incorrectly assumes that
there is only one router port, by returning the LR associated with the
FIRST port of type 'router' in the whole LS. This causes an unexpected
behavior as the first port can be either the router port of the default
gateway router, but it can also be any other router port having an
interface in that LS.

The use case of having multiple router interfaces in one LS in to be able to route between other internal networks without NAT, using static routes installed in the neutron default router.
This is a standard way of routing between internal networks in neutron and it works perfectly with OVN.
For a quick example, say we have a LS "ls1" containing the 192.168.1.0/24 network attached to its "lr1" router. We want all the traffic to go to the default gateway (192.168.1.1), SNATted by going through the public interface of the router lr1. For traffic going to 192.168.2.0/24, we want it to go to router "lr2". For this to happen, we add an interface from lr2 (192.168.1.2) in the ls1 network, and add a static route in lr1 (route: 192.168.2.0/24 next-hop 192.168.1.2). The network ls1 now has two routers attached.
We cannot do the same by interconnecting directly multiple routers (neutron does not supports router-to-router links), and we cannot use a dedicated interconnect neutron network to do that, because all the flows routed by lr1 to lr2 through a dedicated network cannot be then SNATted by lr2. But this behavior is out of the present topic, it's just a way of demonstrating that there is no workaround to route traffic the way neutron allows us to without having two routers having both an interface in the initial LS.

The correct logic for helper.py:_find_lr_of_ls would be to first gather
all ports with type=router, then check if the port IP matches the
default gateway specified in neutron subnet definition. If it matches,
then return the associated LR. Another way to make sure that the LB can
work through all the attached routers in a LS would be to add all the
lr_refs of all routers found in a LS (and have an event listening for
all router ports added to the LS after LB creation).

Tested on latest Xena build.

** Affects: neutron
     Importance: Undecided
         Status: New


** Tags: ovn-octavia-provider

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to neutron.
https://bugs.launchpad.net/bugs/1949059

Title:
  ovn-octavia-provider: incorrect router association in NB when network
  is linked to more than 1 router

Status in neutron:
  New

Bug description:
  LB does not work when creating an Octavia LB with OVN provider in a
  network containing multiple router interfaces.

  When creating a loadbalancer using ovn provider, the OVN octavia driver agent creates a Load_Balancer entry and add several external ids, one of those being the Logical Router ID (lr_ref) to have the OVN LB properly work with an associated floating IP. This lr_ref association is repeated multiple times during the lifecycle of a LB : at create time (helper.py:lb_create) or when adding a listener,pool or pool member.
  During LB creation, the driver agent tries to find the associated LR of every LS linked with the LB with helper.py:_find_lr_of_ls to add the LR IDs to the lr_ref external id field in OVN. The linked LS are the vip_network or the LS in which the pool members are.

  The problem is the function _find_lr_of_ls incorrectly assumes that
  there is only one router port, by returning the LR associated with the
  FIRST port of type 'router' in the whole LS. This causes an unexpected
  behavior as the first port can be either the router port of the
  default gateway router, but it can also be any other router port
  having an interface in that LS.

  The use case of having multiple router interfaces in one LS in to be able to route between other internal networks without NAT, using static routes installed in the neutron default router.
  This is a standard way of routing between internal networks in neutron and it works perfectly with OVN.
  For a quick example, say we have a LS "ls1" containing the 192.168.1.0/24 network attached to its "lr1" router. We want all the traffic to go to the default gateway (192.168.1.1), SNATted by going through the public interface of the router lr1. For traffic going to 192.168.2.0/24, we want it to go to router "lr2". For this to happen, we add an interface from lr2 (192.168.1.2) in the ls1 network, and add a static route in lr1 (route: 192.168.2.0/24 next-hop 192.168.1.2). The network ls1 now has two routers attached.
  We cannot do the same by interconnecting directly multiple routers (neutron does not supports router-to-router links), and we cannot use a dedicated interconnect neutron network to do that, because all the flows routed by lr1 to lr2 through a dedicated network cannot be then SNATted by lr2. But this behavior is out of the present topic, it's just a way of demonstrating that there is no workaround to route traffic the way neutron allows us to without having two routers having both an interface in the initial LS.

  The correct logic for helper.py:_find_lr_of_ls would be to first
  gather all ports with type=router, then check if the port IP matches
  the default gateway specified in neutron subnet definition. If it
  matches, then return the associated LR. Another way to make sure that
  the LB can work through all the attached routers in a LS would be to
  add all the lr_refs of all routers found in a LS (and have an event
  listening for all router ports added to the LS after LB creation).

  Tested on latest Xena build.

To manage notifications about this bug go to:
https://bugs.launchpad.net/neutron/+bug/1949059/+subscriptions



Follow ups