WL#12715: Support multiple addresses for the --mysqlx-bind-address command option

Affects: Server-8.0   —   Status: Complete

Motivation

  1. Network configuration of a server that run MySQL Server, may consist of multiple network interfaces which may serve different propose, for example

    Host:

    • eth0 - intra-site network (business network)
    • eth1 - inter-site network (business network)
    • eth2 - public network

    While the DBA may configure MySQL Server to listen on one of those interfaces or on all, still if He doesn't have a possibility of listening only on "business network" (two interfaces), where listening on public interface might be unwanted or even be a security issue.

  2. MySQL Server introduced binding to multiple addresses under WL#11652. X Plugin should be aligned to those changes.

    The MySQL server can be configured to listen to one (and only one) IPv4 and one (and only one) IPv6 interface, or all interfaces that are configured on a server. See https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_bind- address

    If at OS level, the server has multiple networks addresses, there is a need to configure the MySQL server to listen to a set of addresses, to also be able to restrict an address the server should not listen to.

Goal

Currently X Plugin accepts single bind address in configuration variable: Mysqlx_bind_address. The default value (which is *) makes X Plugin to listen on all IPv6 and IPv4 interfaces. This worklog must give:

  • Allow user to configure X Plugin bind address with multiple IP address (interfaces) where he can skip unwanted interfaces of his host machine.

  • X Plugin must be in align with MySQL server, thus it must implement feature same as WL#11652.

Functional requirements

Existing Behaviour

SI: Single "hostname", selects specific interface

SI1
User must be able to specify single address to listen on
SI2
User must be able to specify single address with a network-namespace to listen
SI3
User must be able to specify local "hostname" to listen on
SI4
When user specified wrong "hostname" (that can't be bound) the server must start. The server must be accessible through X UNIX socket or classic protocol

MI: Single "hostname", selects multiple interfaces

MI1
User must be able to specify single address to listen on all interfaces
MI2
User must be able to specify single address to listen on all IPv4 interfaces
MI3
User must be able to specify single address to listen on all IPv6 interfaces

OB: Observability

OB1
User should be able to check on which interface X Plugin listens.
OB2
User should be able to check error log on information on ignored addresses (ERROR LEVEL).
OB4
User should be able to check error log on information that X Plugin is inaccessible, because all interfaces addresses were skipped and UNIX socket file name was invalid (ERROR LEVEL).

New requirements

MA: Multiple "hostnames", selects multiple interfaces

MA1
User must be able to specify multiple addresses that fulfill any requirement from 'SI' group.
MA2
User must be able to specify multiple addresses, where all invalid should be ignored.

NOB: Observability

NOB1
User should be able to check on which interfaces X Plugin listens.

Configuration

X Plugin already allows to configure the network interface on which its going to accept incoming connections. Still the value is limited to string describing just one network interfaces or all:

  • hostname, for example:

    • localhost
  • IPv4 interface address, for example:

    • 127.0.0.1
    • 10.0.0.1
  • IPv6 interface address, for example:

    • ::1
    • 2606:b400:840:40::8b2c:141c
    • fe80::1%lo0
  • address/IP interface address with network namespace

    • 127.0.0.1/some_ns1
    • 127.0.0.1/some_ns2
    • 10.0.0.1/some_ns2
    • 2606:b400:840:40::8b2c:141c/some_ns2
  • address selecting all IPv4 interfaces

    • 0.0.0.0
  • address selecting all IPv6 interfaces

    • ::
  • address selecting all interfaces

    • *

The implementation of this worklog must extend Mysqlx_bind_address to accept values with multiple addresses. The new value format must be the same as defined by WL#11652 for bind_address. Multiple addresses must be separated by comma, where when there are more than one address in the value, then "wildcards" are not allowed ("*", "::", "0.0.0.0"). Thus following EBNF syntax, describes possible values for Mysqlx_bind_address:

wildcards      = "::" | "0.0.0.0" | "*"
net_namespace  = "/", name
interface      = (IPv4 | IPv6 | hostname) [net_namespace]
more_interface = "," , interface
interfaces     = interface, [{more_interface}]
bind_address   = wildcards | interfaces

X Plugin must parse the configuration string at startup, and allocate listening socket for each entry. In case when user put an invalid address then it must be skipped and an error information must be sent to error-log.

If all entries were invalid (with UNIX socket), then X Plugin must send an error to error-log, that user won't be able to connect through X Protocol.

Note

Plugin API doesn't allow a plugin to fail startup of the server, this means that in case of invalid configuration of interfaces on which the plugin, it is not able to fail the startup because of that X Plugin must skip invalid configuration and create a note in error-log.

There is other possibility, to change XPlugin to "mandatory" plugin, still in that case, user won't be able to turn off the plugin. This option can be introduced in X Plugin in future still as separate worklog.

Instrumentation

  • Mysqlx_address - this variable already exist, only thing that changes is is that instead a single address on which X Plugin is accepting connection, it will report multiple addresses (only those that X Plugin was able to bind). The list of addresses must be separated with "comma", for example:

    ADDR1, ADDR_WITH_NS_2, ADDR3

Summary:

Property Value
Variable name Mysqlx_address
Variable type string
Allowed values UNDEFINED - all addresses were invalid
"" - Waiting for X Plugin startup
"ADDR([,ADDR...])+" list of addresses

Error and Warnings

Following error-log message already exists and must be reused. It is reported in case when X Plugin doesn't have a interface to accept incoming connections:

ER_XPLUGIN_FAILED_TO_PREPARE_IO_INTERFACES
  eng "Preparation of I/O interfaces failed, X Protocol won't be accessible"

Following error-log message must be logged in case when parsing of one of the addresses failed:

ER_XPLUGIN_FAILED_TO_PARSE_ADDRESS
  eng "Value \"%s\" set to `Mysqlx_bind_address`, can't be parsed. Skipping this value."

Following error-log message must be logged in case when binding of one of the addresses failed:

ER_XPLUGIN_FAILED_TO_BIND_INTERFACE_ADDRESS
  eng "Value \"%s\" set to `Mysqlx_bind_address`, X Plugin can't bind to it. Skipping this value."

Before ER_XPLUGIN_FAILED_TO_BIND_INTERFACE_ADDRESS, the plugin should print an error-log message containing error-number and error description of the failure.

Note

Those error messages are only suggestions, and in the final solution the message might be different, for example having more context or information.

General

Currently Socket_acceptors_task class is responsible for creating both listeners (UNIX socket, TCP) and Server_builder parses the Mysqlx_bind_address string. The dependency between all relevant classes can be represented by following UML diagram:

Server_builder o-- Socket_acceptors_task
Socket_acceptors_task "1" *-- "0..2" Listener

Where Listener class represents an concrete bind address to which server is bound, also potential unix-socket listener.

Goal

Socket_acceptors_task must handle multiple TCP bind addresses, thus it must handle multiple listeners. This "Multiplicity" between Socket_acceptors_task and Listener is going to be changed:

Server_builder o-- Socket_acceptors_task
Socket_acceptors_task "1" *-- "0..*" Listener

Thus Server_builder be able to divide Mysqlx_bind_address to multiple addresses and pass them to Server_acceptors_task to create the sockets.