Tracing neutron-l3-agent via rbdb clears the issue out a bit.
For the case where a tenant network is added before an external network ext_port_addr_scopes is an empty set:
https://paste.ubuntu.com/p/Byjp6fNpdd/
--Call-- > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(590)_check_if_address_scopes_match() -> def _check_if_address_scopes_match(self, int_port, ex_gw_port): ... (Pdb) n > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(592)_check_if_address_scopes_match() -> int_port_addr_scopes = int_port.get('address_scopes', {}) (Pdb) n > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(593)_check_if_address_scopes_match() -> ext_port_addr_scopes = ex_gw_port.get('address_scopes', {}) (Pdb) n > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(595)_check_if_address_scopes_match() -> lib_constants.IP_VERSION_6 if self._port_has_ipv6_subnet(int_port) (Pdb) int_port_addr_scopes {u'4': u'd5d483bd-b1a1-4d11-8b98-a9697707321e', u'6': None} (Pdb) ext_port_addr_scopes {}
For the case where an external network is added first, then a tenant network both int_port_addr_scopes and ext_port_addr_scopes have the same content:
(Pdb) n > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(593)_check_if_address_scopes_match() -> ext_port_addr_scopes = ex_gw_port.get('address_scopes', {}) (Pdb) n > /usr/lib/python2.7/dist-packages/neutron/agent/l3/dvr_local_router.py(595)_check_if_address_scopes_match() -> lib_constants.IP_VERSION_6 if self._port_has_ipv6_subnet(int_port)
-> lib_constants.IP_VERSION_6 if self._port_has_ipv6_subnet(int_port) (Pdb) int_port_addr_scopes {u'4': u'd5d483bd-b1a1-4d11-8b98-a9697707321e', u'6': None} (Pdb) ext_port_addr_scopes {u'4': u'd5d483bd-b1a1-4d11-8b98-a9697707321e', u'6': None}
Tracing neutron-l3-agent via rbdb clears the issue out a bit.
For the case where a tenant network is added before an external network ext_port_ addr_scopes is an empty set:
https:/ /paste. ubuntu. com/p/Byjp6fNpd d/
--Call-- python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(590) _check_ if_address_ scopes_ match() if_address_ scopes_ match(self, int_port, ex_gw_port): python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(592) _check_ if_address_ scopes_ match() addr_scopes = int_port. get('address_ scopes' , {}) python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(593) _check_ if_address_ scopes_ match() addr_scopes = ex_gw_port. get('address_ scopes' , {}) python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(595) _check_ if_address_ scopes_ match() IP_VERSION_ 6 if self._port_ has_ipv6_ subnet( int_port) addr_scopes b1a1-4d11- 8b98-a969770732 1e', u'6': None} addr_scopes
> /usr/lib/
-> def _check_
...
(Pdb) n
> /usr/lib/
-> int_port_
(Pdb) n
> /usr/lib/
-> ext_port_
(Pdb) n
> /usr/lib/
-> lib_constants.
(Pdb) int_port_
{u'4': u'd5d483bd-
(Pdb) ext_port_
{}
For the case where an external network is added first, then a tenant network both int_port_ addr_scopes and ext_port_ addr_scopes have the same content:
(Pdb) n python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(593) _check_ if_address_ scopes_ match() addr_scopes = ex_gw_port. get('address_ scopes' , {}) python2. 7/dist- packages/ neutron/ agent/l3/ dvr_local_ router. py(595) _check_ if_address_ scopes_ match() IP_VERSION_ 6 if self._port_ has_ipv6_ subnet( int_port)
> /usr/lib/
-> ext_port_
(Pdb) n
> /usr/lib/
-> lib_constants.
-> lib_constants. IP_VERSION_ 6 if self._port_ has_ipv6_ subnet( int_port) addr_scopes b1a1-4d11- 8b98-a969770732 1e', u'6': None} addr_scopes b1a1-4d11- 8b98-a969770732 1e', u'6': None}
(Pdb) int_port_
{u'4': u'd5d483bd-
(Pdb) ext_port_
{u'4': u'd5d483bd-