Subject: Re: comments about draft-chakrabarti-ipv6-addrselect-api-03

From: JINMEI Tatuya / 神明達哉<[email-masked]>
Date: Fri, 04 Nov 2005 13:57:57 +0900

>>>>> On Mon, 31 Oct 2005 10:27:09 -0800, 
>>>>> Erik Nordmark <[email-masked]> said:

>> I'm not really sure what "to only define a single AI flag", but yes,
>> I'm still concerned about having separate flags for both PUBLIC and
>> TMP (and so on).

> FWIW I don't understand the first part of that sentence. Missing "means"
> before the comma? Or something else?

Oops, sorry.  Yes, a "means" before the comma was missing.

>> I've been thinking over it again, and I guess the main concerns are as
>> follows:
>> 
>> 1. having separate flags cause invalid cases and make sanity checks in
>> implementations more complex (as I mentioned in the comment
>> message).

> But for getaddrinfo I think is an inherent issue. For instance, I don't
> see how your proposed list of preferences below (in ai_selections) makes
> it any easier to detect conflicts; it might actually make it harder for
> all I can tell.

Ah, yes, that's right.  While I'm not sure if it's "inherent", the
argument about the complexity of checks applies to the "array of
rules" approach, too.

>> 2. rephrasing this point differently, these are actually not "flags",
>> but multi(more than 2)-value options.  For example, what we are
>> going to define with IPV6_PREFER_SRC_HOME and IPV6_PREFER_SRC_COA
>> is the source address selection policy from
>> - prefer home address
>> - prefer care-of-address
>> - (perhaps implicitly) use system (or administrator's) default

> The 3rd is actually the semantics of "leave unchanged". In the case of
> getaddrinfo this would always mean the system default. But in the case
> of setsockopt, it would mean to not change the current setting for that
> preference on the socket.

Okay, but this does not change the point that "these are actually
multi-value options".

>> (I admit this might sound just a "philosophical" argument.)
>> 
>> As far as I know, in the traditional API design we have been using a
>> separate socket option type for each optional notion (in this case the
>> address selection policy).  Examples include the IPV6_MULTICAST_LOOP
>> option (while it does not have a specific "use default" value) and the
>> IPV6_{UNICAST,MULTICAST}_HOPS options (while these have more than two
>> possible values).

> Yes, one can produce a functional setsockopt setting of preferences by
> using a separate socket option for each preference.
> Thus
> 	int on = 1;

> 	setsockopt(s, IPPROTO_IPV6, IPV6_PREFER_COA, &on, sizeof(on));
> to prefer CoA over HOA and
> 	int off = 0;

> 	setsockopt(s, IPPROTO_IPV6, IPV6_PREFER_COA, &off, sizeof(off));
> to turn it off, and likewise for the separate socket options for
> IPV6_PREFER_TMP, IPV6_PREFER_CGA, etc.

> That would imply a large number of separate socket options.

Yes, but I don't think it's a problem, since the socket option space
is pretty large.

> But the important thing is that such a change could have no impact on
> how we specify getaddrinfo(), since there we have to be able to specify
> everything in a single call.

??? Sorry, I don't understand the point here.

>> How about something like this?  One may regard this as an
>> overly-generalized solution, but I believe this solves all technical
>> concerns pointed out so far.

> I don't see how this is any simpler. The implementation becomes more
> complex because it needs to handle an array of preferences instead of a
> single value. And the implementation still need to have checks against
> specifying different values for the same preference, doesn't it?

Yes, about the simplicity, you are right.

> The simplest approach for the application programmer would be to define
> a single name space for IPV6_ADDR_PREFER_*, and use that both in
> ai_preferences and with setsockopt. In such a case the application code
> would be along the lines of
> 	int preferences = IPV6_PREFER_COA | IPV6_PREFER_TMP;

> 	hints.ai_flags |= AI_PREFERENCE;
> 	hints.ai_preferences = preferences;
> 	getaddrinfo(...);
> 	/* Loop over all returned addresses */
> 	while (ai != NULL) {
> 		s = socket(ai->ai_family, ...);
> 		setsockopt(s, IPV^_PREFERENCES, &preferences,
> 		    sizeof (preferences));
> 		if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1)
> 			continue;
> 		break;
> 	}

Actually, I'd rather avoid such easy convenience, because it has a
pitfall: the relationship between the source selection flags and
destination selection flags is not a one-to-one mapping.  In fact, as
I already pointed out, there is no (natural) corresponding rule (or
only a dubious one if not nothing) in the source address selection to
AI_PREFER_DST_{SMALL,LARGE}SCOPE.  So, if the application programmer
unconditionally passes ai_preferences to setsockopt(), it may cause an
error or unexpected result.  I'd rather clearly separate the two
similar but actually different interfaces so that the programmer will
be free from the pitfalls by design.

Probably the difference on the opinion is based on my bottom line
impression that ordinary application programmers won't be fascinated
by this API in the first place and won't be bothered to use it.  Since
this API (to me) is very special for special types of programmers
(e.g., MIP6 protocol implementors), I don't care about the convenience
at the programmer side.

On the other hand, for those who believe this will get wider ordinary
customers, the convenience for programmers will probably be an
important issue.

If my understanding is correct, this is probably more like a matter of
preference.  And since I will not be a customer of this API anyway
(IMO), I'm probably not qualified to insist on my preference.  So, I
don't keep my opinion on this as a blocking issue.  I suggest hearing
from others (particularly those who are interested in this API as a
user), but I don't oppose to moving forward with the current style if
you still prefer it.

One possible compromise is to make it clearer that the "flags" are
actually multi-value options.  The "Default Router Preferences"
mechanism takes a similar approach in the RA header field next to
some "flags" bits.  But again, I don't insist on this idea, either.

> Such code would be more complex for all the other approaches we've
> discussed. And the single preference name space would make it easier to
> provide a
> 	int connect_by_name(char *hostname, int port, int preferences);
> library function (which would help move the complexity of trying
> multiple addresses out of the applications).

For that matter, the same argument applies.

					JINMEI, Tatuya
					Communication Platform Lab.
					Corporate R&D Center, Toshiba Corp.
					[email-masked]

--------------------------------------------------------------------
IETF IPv6 working group mailing list
[email-masked]
Administrative Requests: https://www1.ietf.org/mailman/listinfo/ipv6
--------------------------------------------------------------------

---

From: JINMEI Tatuya / 神明達哉<[email-masked]>
Date: Fri, 04 Nov 2005 14:15:09 +0900

>>>>> On Mon, 31 Oct 2005 10:29:04 -0800, 

>> I'm afraid you misunderstood my point.  (Perhaps the additional
>> question obscured the main point...)  My main question is:
>> 
>> In my understanding, if either of the flags of a particular rule is
>> off, it means the system default should be used for that rule.  For
>> example, if 'flags = IPV6_PREFER_SRC_TMP', then the system default
>> will apply for HOME vs COA, CGA vs NONCGA, etc.  Is that correct?
>> If so, when an application wants to make the rules revert to system
>> default, it should be able to call setsockopt without setting any
>> flag, shouldn't it?  Or in other wise, it does not have to remember
>> the old rule values by calling getsockopt beforehand for this
>> purpose.

> No, it isn't "apply system default", it is "leave unchanged".

> Given that a socket starts with the system default, then subsequent
> setsockopts of IPV6_PREFERENCES can be used to tweak different
> preferences; one setsockopt can specify public vs. tmp preferences, and
> a different setsockopt can specify home vs. coa.

Ah, OK, then it makes sense.  Unless I was missing something,
however, this point was not very clear.  I've not read the 04 version
yet, but I hope this point is clarified there.

>> Yes, and this leads me to think we should rather define other variants
>> of IN6_IS_ADDR_xxx().  That is,
>> 
>> in6_is_addr_home()
>> in6_is_addr_careof()
>> in6_is_addr_temporary()
>> in6_is_addr_cga()

> You mean that each of those would just take an struct sockaddr * as an
> argument?
> And return true/false?

Yes or no, depending on how we should return an error.

> What if the address in question isn't even assigned to the host i.e. the
> host can't determine whether it is of a particular category?

Actually, I wasn't thinking about that level of details, but it will
probably return some error.

But I think these questions equally apply to the inet6_is_srcaddr().

>> etc.  Or, it's probably better not to adhere to recycling the
>> IPV6_PREFER_xxx "flags" for multiple purposes, and consider something
>> like this:
>> 
>> int in6_getaddrattr(struct sockaddr_in6 *addr, uint32_t *attrp);
>> 
>> On success, this function returns 0 and sets the "attributes" of the
>> address as bit-wise flags in '*attrp'.  The flags are, for example,
>> 
>> IN6_ADDRATTR_HOME
>> IN6_ADDRATTR_COA (not sure if we need this in addition to HOME
>> though)
>> IN6_ADDRATTR_TMP
>> IN6_ADDRATTR_CGA

> This seems like more work than definining a handful of specific
> in6_is_addr_*() functions.

> I'm not sure this generality is worth-while.

Frankly, I'm not sure either.  This may be a matter of preference, and
so if no one else has a particular opinion, I don't insist on this
point as a blocking issue.

					JINMEI, Tatuya