Skip to contentSkip to conversation

RFC 3484 support

DISCUSSION Ulrich Drepper 3 participants 8 messages Nov 12, 2003 – Nov 18, 2003

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I want to implement RFC 3484 support in getaddrinfo for glibc but there is the tiny little problem with the source address selection which has to be solved as part of the destination address selection.

To sort the destination addresses the source address for each of the addresses returned by getaddrinfo must be determined. This can be done in two ways:

1. use the existing kernel functionality and provide an interface to it which userlevel can use

2. re-implement routing at userlevel

#2 above has serious problems. To accurately re-implement the kernels routing decision making a huge amount of data is needed. Not only the routing information, but also transient errors, all the kernel parameters and flags influencing routines etc. This is, I'd say, virtually impossible which would mean an implementation with the source address selection happening at userlevel would do a bad job in some cases.

So my question is: is there interest in adding support for method #1 to the kernel? Could we get a syscall or whatever to pass down to the kernel a set of addresses (and whatever else is needed) and the kernel passing back information about the sorted list (either the sorting list or a transformation description of some sort)?

[I'm not on this list, so please cc: me. DaveM made me post here.]

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/sYdY2ijCOnn/RHQRAppvAJ9MuBPXJM5tH93mXwRu2prifwo+GACfSjzg tuMC3yIgcqugevSYvuJpC2g=
=yEdb
-----END PGP SIGNATURE-----

#1 lore raw

Hello!

Quoted 6 lines

To sort the destination addresses the source address for each of the addresses returned by getaddrinfo must be determined. This can be done in two ways:

1. use the existing kernel functionality and provide an interface to it which userlevel can use

This interface is connect() for example. Essentially, connect() on datagram socket with subsequent getsockname() makes exactly this.

Quoted 1 line

#2 above has serious problems.

This is just impossible.

Quoted 4 lines

the kernel? Could we get a syscall or whatever to pass down to the kernel a set of addresses (and whatever else is needed) and the kernel passing back information about the sorted list (either the sorting list or a transformation description of some sort)?

Do you really need this?

Right now the kernel is able to to determine a valid source address derived from some known destination address and nothing more. It is just connect().

I do not understand rfc3484, actually. Does it involve some policies made inside libc, which could contradict to policies used by kernel? If so, it is definitely unimplementable without surgery in the kernel.

Alexey

#2 lore raw
Quoted 9 lines · On Thu, 13 Nov 2003 [email protected] wrote:

Do you really need this?

Right now the kernel is able to to determine a valid source address derived from some known destination address and nothing more. It is just connect().

I do not understand rfc3484, actually. Does it involve some policies made inside libc, which could contradict to policies used by kernel? If so, it is definitely unimplementable without surgery in the kernel.

I'm not sure what you refer by policies. The policies of "matching label" and "higher precedence" could include manually configured policies which might subsequently be different in kernel and in libc (at least).

But, I think you what you're really asking is whether we need destination address selection at all, because we already have policy control in the kernel for source address. The short answer is "yes", the longer answer is below.

The destination address selection as specified by RFC 3484 is pretty much necessary for the "proper" address selection. Just having source address selection is not enough, because if we get multiple inputs as destination addresses, there has to be some way of selecting the best of them (combined with a best source address), as a trivial example:

DNS lookup gives you 2002::1 and 2001::1 addresses (6to4 and native).

The node has 2002:f00::1 address configured, but no "native" address.

Currently getaddrinfo picks the destination address in a round-robin fashion. However, the best (s,d) -pair is (2002:f00::1, 2002::1), and you currently get that only one half of the time.

This is a very simplistic example, but there are actually real failure modes and problems if the destination address selection is missing.

HTH

Signature · 3 lines
Pekka Savola                 "You each name yourselves king, yet the
Netcore Oy                    kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings
#3 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 2 lines · Pekka Savola

Currently getaddrinfo picks the destination address in a round-robin fashion.

That's what could be done but isn't since I see little value. We currently return IPv6 address, if there are any and if they are wanted, first, then the IPv4 addresses. The order in which multiple IPv6 and/or IPv4 addresses are returned depends on the order the server returns it and eventually on artificial round-robin selection.

But the rest of your argumentation I fully support. I'm no expert at this, but all these possible IPv6 address uses can lead to big problems if the wrong address is chosen at any one time. Support for destination address selection is needed. And I really would like to avoid to implement something which will inevitably fall short of the real solution at userlevel.

I could image something like this: a syscall with

int destination_addr_sort (size_t n, struct addrinfo addr[], size_t
reorder[])

n and addr are input parameters. reorder is an output parameter, a pointer to an array describing the transformation. I.e., it is not necessary for the kernel to shuffle the data around. It's not needed for getaddrinfo anyway. It means less data has to be transported.

An alternative would be to pass something other than struct addrinfo elements down. That struct contains data the kernel doesn't need. I'd be fine with that, too.

I'm open to any reasonable solution. If we cannot come to an agreement I'll have to try a user-level solution. But this will be slow[¹], and suck big time.

[¹] BTW, it will be slow, among other things, because there is no way to cache and netlink-provided data at userlevel. For every name lookup we have to re-read the data. This already happens today to implement AI_ADDRCONFIG. I've mentioned to DaveM sometime back that I would love to get a netlink command which allows me to query a timestamp for the last interface configuration change. Then I could perform this one quick test and read the other data only if the timestamp changed.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/tBEJ2ijCOnn/RHQRAsbMAKCcQzX+GRBqA0O/nZzLfqw1Qko5ZACfe+P5 ODlgrjK3BcPqzjEWrSc6hIY=
=8/PO
-----END PGP SIGNATURE-----

#4 lore raw
Quoted 8 lines · Ulrich Drepper
Quoted 2 lines

Currently getaddrinfo picks the destination address in a round-robin fashion.

That's what could be done but isn't since I see little value. We currently return IPv6 address, if there are any and if they are wanted, first, then the IPv4 addresses. The order in which multiple IPv6 and/or IPv4 addresses are returned depends on the order the server returns it and eventually on artificial round-robin selection.

Oops, sorry. That's what I meant. The current behaviour is good. Putting v6 first is regular practice and good.

Signature · 3 lines
Pekka Savola                 "You each name yourselves king, yet the
Netcore Oy                    kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings
#5 lore raw
In reply to [email protected]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 6 lines · [email protected] wrote:
Quoted 2 lines

1. use the existing kernel functionality and provide an interface to it which userlevel can use

This interface is connect() for example. Essentially, connect() on datagram socket with subsequent getsockname() makes exactly this.

Wouldn't this require to set up a socket and connect it to each target address? The point of the whole source and destination address selection is it to avoid making connections with addresses/via interfaces which might have problems. getaddrinfo returns a list of addresses which a client program then tries in the order they are provided. The address which has the highest rate of success and the highest quality for the connection should be tried first. And all this is subject to all the customization and configuration going in the kernel.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/tA/l2ijCOnn/RHQRAiYcAKCjgzJXwd/zV7KaWBUnaIqNEUdHrgCeKq5g pQm7ViT1UChv0DtqKaxkdiY=
=/Jay
-----END PGP SIGNATURE-----

#6 lore raw

Hello!

Quoted 3 lines

Wouldn't this require to set up a socket and connect it to each target address? The point of the whole source and destination address selection is it to avoid making connections

Datagram connect() is exactly selection of the addresses, nothing more.

I do not mind against specialized interface, but I still see plain connect() as a reasonable and, the most important, universal solution.

Quoted 2 lines

provided. The address which has the highest rate of success and the highest quality for the connection should be tried first.

Hmm... We do not account for this. Do you really propose to gather this kind of statistics in the kernel? I am afraid this is really difficult.

Alexey

#7 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 1 line · [email protected] wrote:

Datagram connect() is exactly selection of the addresses, nothing more.

I've now implemented a userlevel-only version of the destination address selection algorithm in glibc's getaddrinfo. The cost is 4 additional system calls per returned address plus potentially more (see below).

The code has also limitation I don't think a userlevel implementation can overcome:

~ rules 3, 4, and 7 are not implemented. This info is, afaik, only
available inside the kernel (if at all)

~ the source address selection also needs the label and precedence
information. Therefore the kernel would have to share this information.

~ to read the label/preference data more syscalls are needed. And
there is the question when to read that info. Once per program run? What about changes to the policies and programs which run for a long time?

I'm OK with having this code I wrote as a backup solution. But I still would like to see the kernel supporting it directly. There are programs which do a lot name lookups and speed is important.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/ud+O2ijCOnn/RHQRAu23AKDNzNfum+OQFwt2aJ5IgI87yEJTPACgoikN TKRhY6Kuu56b22mlh+Cguvs=
=Q9dl
-----END PGP SIGNATURE-----