Ensure that address familly proto is given with IPv6 address on the memcache_pool backend

Bug #1871372 reported by Herve Beraud
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
oslo.cache
New
Undecided
Herve Beraud

Bug Description

Hello,

Description
===========

To setup a memcached based backend we need to pass the `memcache_servers` parameter to oslo.config [1].

This parameter can be consumed by the following backends:
- dogpile.cache.memcached
- oslo_cache.memcache_pool

The memcache_pool backend is based on python-memcached, this one is waiting for the `servers` [2] as a list of servers addresses at format <url|ip>:<port>.

The `memcache_servers` parameter [1] in oslo.cache's config will be passed to the memcache_pool backend as the `urls` argument.

This param (url) will be passed to the python-memcached library to create a client as a positional argument [3] which correspond to the `servers` param [2].

However python-memcached to create the client socket with given servers expect to get the address familly (the `proto`) given in the passed urls (the servers param) [5].

It could be an issue if an url at IPv6 format is given without the `proto` specified inside her [4], then the socket will be initialized with a wrong address familly and the connection with the server will be not established. In this case the socket will be intialized with an IPv6 format and an `AF_INET` [7] address familly, which correspond to an IPv4 familly address where normally it should use an `AF_INET6` [6][8] which is designed for IPv6 addresses.

python-memcached wait for this proto in the given servers to initialize the socket with the right address familly [6][7].

Working examples:
-----------------

memcache_servers=inet6:[fd00:fd00:fd00:2000::18]:11211,inet6:[fd00:fd00:fd00:2000::19]:11211,inet6:[fd00:fd00:fd00:2000::1c]:11211

memcache_servers=inet6:[controller-2.internalapi]:11211,inet6:[controller-1.internalapi]:11211,inet6:[controller-0.internalapi]:11211

*Not* working examples:
-----------------------

memcache_servers=controller-2.internalapi:11211,controller-1.internalapi:11211,controller-0.internalapi:11211

memcache_servers=inet6:controller-2.internalapi:11211,inet6:controller-1.internalapi:11211,inet6:controller-0.internalapi:11211

memcache_servers=[controller-2.internalapi]:11211,[controller-1.internalapi]:11211,[controller-0.internalapi]:11211

To summarize, the python-memcached library waiting for of proto inet6 to intialize the socket with the `AF_INET6` constant for the address familly.
If the `proto` is not passed then the socket will be intialized with the `AF_INET` constant [6] for the address familly.

Real examples
=============

Without the proto given
-----------------------

memcache_servers=controller-2.internalapi:11211,controller-1.internalapi:11211,controller-0.internalapi:11211

```
[root@controller-1 keystone]# netstat -natp |grep 11211 |grep keys
[root@controller-1 keystone]#
```

With the proto given
-----------------------

memcache_servers=inet6:[fd00:fd00:fd00:2000::18]:11211,inet6:[fd00:fd00:fd00:2000::19]:11211,inet6:[fd00:fd00:fd00:2000::1c]:11211

```
[root@controller-1 keystone]# netstat -natp |grep 11211 |grep key
tcp6 0 0 fd00:fd00:fd00:20:43420 fd00:fd00:fd00:20:11211 ESTABLISHED 242085/keystone-adm
tcp6 0 0 fd00:fd00:fd00:20:43408 fd00:fd00:fd00:20:11211 ESTABLISHED 242085/keystone-adm
tcp6 0 0 fd00:fd00:fd00:20:43224 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44010 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44746 fd00:fd00:fd00:20:11211 ESTABLISHED 242085/keystone-adm
tcp6 0 0 fd00:fd00:fd00:20:44008 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44000 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:43222 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44600 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44002 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44606 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
tcp6 0 0 fd00:fd00:fd00:20:44608 fd00:fd00:fd00:20:11211 ESTABLISHED 242086/keystone-mai
```

Workaround
==========

As you can observe above this is not an issue if the `proto` is given in the memcache_servers:

```
memcache_servers=inet6:[fd00:fd00:fd00:2000::18]:11211,inet6:[fd00:fd00:fd00:2000::19]:11211,inet6:[fd00:fd00:fd00:2000::1c]:11211
```

So if you faced similar issue you could easily fix that by simply put the proto in your urls.

Solutions & improvements
========================

Warning: the solution need to take care to be only focused on the `memcache_pool` backend to avoid side effects on the `dogpile.cache` backend which is based on pylibmc and bmemcached and which surely handle given urls in a different way.

First, it could be worth to put some examples in the oslo.cache's doc with details on how to pass proper `memcache_servers` for the `memcache_pool` backend and to speak about address familly and proto.

Second, also it could be worth on the oslo.cache side to test some IPv6 regexes on the given urls to looking for the proto and to be aware if it isn't given. Some sort of regexes which will surround the case where an IPv6 is given without the proto part and to improve the python-memcached regexes [1]. We can easily force the proto if it's was not given by users when we detect IPv6 addresses format.

It could avoid the previous example where connection between the client and the memcache server is not established.

Third, some new regexes could be added to python-memcached too to take care of this case and directly handle these case at the root position.

Also I think a couple of unit tests and functional tests could help us to surround this kind of issue.

Thoughts?

[1] https://docs.openstack.org/oslo.cache/latest/configuration/index.html#cache.memcache_servers
[2] https://github.com/linsomniac/python-memcached/blob/master/memcache.py#L169
[3] https://github.com/openstack/oslo.cache/blob/master/oslo_cache/_memcache_pool.py#L234
[4] https://github.com/linsomniac/python-memcached/blob/bad41222379102e3f18f6f2f7be3ee608de6fbff/memcache.py#L1353,L1357
[5] https://github.com/linsomniac/python-memcached/blob/bad41222379102e3f18f6f2f7be3ee608de6fbff/memcache.py#L1337,L1345
[6] https://docs.python.org/3/library/socket.html#socket.AF_INET6
[7] https://docs.python.org/3/library/socket.html#socket.AF_INET
[8] https://tools.ietf.org/html/rfc3493.html#section-3.1

Changed in oslo.cache:
assignee: nobody → Herve Beraud (herveberaud)
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.