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

From: JINMEI Tatuya / 神明達哉<[email-masked]>
Date: Tue, 11 Oct 2005 08:03:12 +0900

Hello,

Sorry for the long delay in response...I've been clearly a
show-stopper of this document.

>>>>> On Mon, 29 Aug 2005 11:18:27 -0700, 
>>>>> Erik Nordmark <[email-masked]> said:

>> This looks like a reasonable idea.  And I see the need for the new
>> AI_PREFERENCES flag (i.e., the hint structure is built by the
>> application, and the added field passed by an old application can be
>> garbage).
>> 
>> One may want to make the new field more generic, rather than the
>> specific purpose of preferences, but I don't have a strong opinion on
>> this.

> Yes, we could call the new field ai_extended_flags or something like 
> that (ai_eflags?).
> Taking your concern about address family specific flags, we could also 
> explicitly label this (ai_ipv6_flags?).

> I don't know how to decide which way to go on this, since I currently 
> can't imagine what other things might be added to getaddrinfo() over time.

After thinking about it again, I now tend to feel AI_PREFERENCE does
not sound so ad-hoc.  Sine getaddrinfo() is typically expected to
return multiple addresses (of multiple families), ordering among them
is its inherent concern.  So, I think I can live with AI_PREFERENCE
(and the corresponding additional field(s) of addrinfo{}).

> Also, if we change it to only define a single AI flag, are you still 
> concerned about having one flag per "feature" (both a PUBLIC and TMP 
> flag for instance)?

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).

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).
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
   (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).

I speculate one of the reasons why we've been adhering to the use of
"flags" is because we need to do the similar thing for getaddrinfo()
and the only available field to pass this information was a "flag"
field at that time.  If my understanding is correct, and if we agree
on some (more flexible) extensions to the addrinfo structure, we may
be able to take a different approach.

For example, we'd be able to specify each policy as an integer
encoding a type-value pair, and specify the set of policies as an
array of the pairs.  The following describes one possible
implementation of this idea.

typedef struct {
	u_int32_t policyname : 30;
	u_int32_t policyvalue : 2;
} ai_selection_t;

struct addrinfo {
  int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME,
                           AI_NUMERICHOST, .. */
  (snip)
  ai_selection_t *ai_selection; /* examined only when AI_PREFERENCE is
                                   set and ai_selection is non NULL */
};

An application that prefers care-of-address over home-address would
do:

	struct addrinfo hints;
	ai_selection_t ai_selections[2];

	ai_selections[0].policyname = AI_SELECTION_MIP;
	ai_selections[0].policyvalue = AI_SELECTION_PREFER_COA;

	/* AI_SELECTION_NULL is a terminating marker */
	ai_selections[1].policyname = AI_SELECTION_NULL;
	ai_selections[1].policyvalue = 0;

	hints.ai_flags |= AI_PREFERENCE;
	hints.ai_selection = ai_selections;

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.

					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: Tue, 11 Oct 2005 09:38:35 +0900

>>>>> On Mon, 29 Aug 2005 12:29:33 -0700, 

>> First of all, I must say I'm not particularly fascinated by this API.
>> As (I think) I said before, I believe this can be useful in very
>> limited situations only (especially because applications need to be
>> modified - I generally agree with Francis on this point), and most
>> applications (and application writers) wouldn't be bothered with using
>> the additional feature.  In fact, the only people I've ever seen who
>> expressed interest in this API are mobile IP(v6) implementors,
>> expecting this API can be used in their mobile IP(v6) specific
>> implementations (e.g., ones that negotiate with the home agent).  I
>> respect that the draft provides one section showing usage examples,
>> but these are not convincing enough to me.

> FWIW To me, the public/temporary address knob is just as important, if 
> not more important than the home/coa knob.

I'm not saying the public/temporary knob (itself) is not important.  I
simply suspect application programmers don't bother to use that knob
in their implementations, and privacy-conscious users would simply use
per-system default (if the system supports that).

But anyway, I won't fight on this point to decide whether or not this
API should be published, so you don't have to try convince me on this.

>> 3. I suspect the necessity of IPV6_PREFER_SRC_{LARGE,SMALL}SCOPE.
>> Those might actually be even harmful.  The API draft says these
>> correspond to Rule 2 of the source address selection defined in
>> RFC3484.  But the RFC says:

(snip)

>> At the very least, I'm not even sure how the logic of Rule 2 is
>> modified if we specify IPV6_PREFER_SRC_SCOPE.  The rule defined in
>> RFC3484 is:
>> 
>> Rule 2:  Prefer appropriate scope.
>> If Scope(SA) < Scope(SB): If Scope(SA) < Scope(D), then prefer SB
>> and otherwise prefer SA.  Similarly, if Scope(SB) < Scope(SA): If
>> Scope(SB) < Scope(D), then prefer SA and otherwise prefer SB.
>> 
>> How would this look like with IPV6_PREFER_SRC_SCOPE?

> FWIW the semantics of IPV6_PREFER_SRC_SMALLSCOPE would be to invert rule 
> 2, so that the algorithm instead of prefering the smallest scoped source 
> which has a scope of at least the destination address, it would prefer 
> the largest scoped source which has a scope which is at most the same as 
> the destination address.

I'm not sure if this answers my question.  Please describe what would
happen if IPV6_PREFER_SRC_SMALLSCOPE is specified using the
pseudo-algorithm like "If Scope(SA) < Scope(SB)...".  But in any event,

> But, like you, I question the utility of this.

then my primary suggestion is to remove this knob.  And, if we can
agree on that, I don't need the "pseudo-algorithm".

>> SEMI SUBSTANTIAL COMMENTS
>> 
>> 4. Considering the background motivation of the advanced API, I think
>> we should also provide an ancillary-data object corresponding to
>> the proposed socket option in order to control the address
>> selection policy per-packet basis with a single system call (i.e.,
>> sendmsg()).

> We can definitely add that.
> Although I sometimes wonder how useful ancillary data options are on the 
> send side (they are critical on the receive side, so that the 
> application can see what was "part of" each received datagram).

Whether the use of ancillary data makes sense hingly depends on the
usage.  In general, if a single socket is shared for multiple
purposes/destinations with possibly different parameters and switching
the parameters per packet using setsockopt is expensive, using
ancillary data make sense.  For example, BIND9 name server uses the
IPV6_PKTINFO option for specifying a particular source address per DNS
response.

>> 5. (AFAICS) This document does not explicitly define the return value
>> of getsockopt(IPV6_ADDR_PREFERENCES).  Even though it's pretty
>> trivial, I believe an API specification should generally provide
>> such 'trivial' things very clearly and explicitly.

> Do you mean the actual return value (which is 0/-1 according to the Open 
> Group standard for getsockopt), or what value is returned in the *optval?

The latter (sorry, perhaps I was not clear enough).

>> 6. [1st line of page 4 (continued from page 3)]
>> 
>> [...]  Since source address selection and destination address
>> ordering need to be partially implemented in getaddrinfo() [3] the
>> corresponding set of flags are also defined for that routine.
>> 
>> I think this is too strong.  Although destination address ordering
>> (selection) would typically be implemented through getaddrinfo(),
>> the selection rules themselves are quite general and could be
>> realized in some other way.

> Yes, the point is that the API shouldn't constrain or assume which parts 
> of address selection is implemented in getaddrinfo() or in the kernel. 
> We'll make this more clear.
> Something along the lines of "should not assume that implementations 
> implementa particular aspect of RFC 3484 in getaddrinfo"

Okay.

>> 7. [3rd paragraph of Section 5]
>> [...] Thus when
>> AI_PREFER_SRC_TMP is set , getaddrinfo() returns DA before DB and SA
>> before SB likewise.
>> 
>> I don't understand this sentence.  What does 'and SA before SB
>> likewise' mean?

> Oops. I should say
> "Then SA is used when communication to DA, thus the temporary
> address gets preferred."

Okay.

>> 8. [page 12 (Section 5), just after the flag list]
>> 
>> The above flags are ignored for the AF_INET address family as the
>> address selection algorithm defined in section 5 of [1] only applies
>> to the IPv6 addresses.
>> 
>> This is not really true.  RFC3484's destination address selection
>> considers both IPv4 and IPv6 addresses (See Section 3.2 of
>> RFC3484).

> The statement was try when there was no DST flags.
> So we can correct it to say "the above SRC flags ... as the source 
> address selection ..."

Okay.

>> 9. [first paragraph of Section 6]
>> 
>> An application only needs to call getsockopt() prior calling
>> setsockopt() if the application needs to be able to restore the
>> socket back to the system default preferences.
>> 
>> This seems odd.  Shouldn't the application just be able to reset
>> the rules to the default by specifying the all-0 flags?  If not,
>> why do we need the sets of two flags to begin with?

> We need two flags per feature in order handle getaddrinfo() without 
> casting the default flags in concrete and not introducing some new
> getaddrinfo_default_preferences() function.
> To me it makes sense to have setsockopt work the same way conceptually 
> as getaddrinfo, so as long as getaddrinfo has two flags per feature, 
> then setsockopt should have the same.

> With two flags then for any X/not-X pair, the semantics of setting 
> neither X or not-X is a no-op.
> This implies that setting no flag at all must also be a no-op.

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.

>> 11. [second to last paragraph of Section 6]
>> 
>> In order to allow different implementations to do different parts of
>> address selection in getaddrinfo() and in the protocol stack, this
>> specification requires that applications set the same flags when
>> calling getaddrinfo() and when calling setsockopt().  For example,if
>> the application sets IPV6_PREFER_SRC_COA flag, it must use
>> AI_PREFER_SRC_COA flag when calling getaddrinfo().  If applications
>> are not setting the same flags the behavior of the implementation is
>> undefined.
>> 
>> The phrase of "the same flags" (there are two occurrences) is not
>> very accurate, since these are actually different, at least as macro
>> names.

> Correct.
> The same flag at the semantic level, which correspond to different flags 
> for the two API parts.

Okay.

> But if we do a ai_preferences type field, then we can actually use the 
> same flag constants in both places (IPV6_PREFER_...) if we want to. This 
> would make the document shorter, and might be a simplication for the users.

This is a different issue from the original point of comment #11.  We
may have to revisit that part when we reach a consensus on the
ai_preferences (or whatever) thing.

>> 12. [second bullet of Section 7]
>> 
>> What would getsockopt() return for preference flags that are not
>> supported in the system? (see also comment #5)

> I think it makes sense to return the defaults per RFC 3484 and its 
> future updates. Thus IPV6_PREFER_SRC_PUBLIC would be set even if 
> temporary addresses are not implemented, and IPV6_PREFER_SRC_HOME set 
> even if mobile IPv6 is not implemented.
> But this is more from a consistency reason than by necessity; returning 
> 0 for those flags would be ok as well assuming the application just 
> turns flags on and off.

I'm happy as long as the spec is clear on this.

>> 13. [third bullet of Section 7]
>> 
>> If an implementation supports both stream and datagram sockets, it
>> should implement the address preference mechanism API described in
>> this document on types of sockets.
>> 
>> I simply don't understand what this means...could you elaborate?
>> (BTW: perhaps 'on types of sockets' should be 'based on types of
>> sockets'?  Even if so, I still don't understand what this means,
>> though)

> Oops - should say "on both types of sockets."

Okay.

>> 14. [second to last paragraph of Section 8]
>> 
>> Other destination rules (#4-prefer home address; #7-prefer native
>> interfaces) could have been applicable.  But the problem is that the
>> local system does not know whether a destination address is a tunnel-
>> address for destination rule #7.  It can only know for sure if the
>> destination address is one of its own.

(snip)

>> Second, the
>> implementation can syntacatically identify 'non-native' destinations
>> in some cases (e.g., for 6to4 addresses). 

> Yes, but we have the preference table to handle that, without any 
> explicit rules on the nativeness of the transport.
> (It might be a defect in 3484 that it has both the "prefer native 
> transport" and the 6to4 addresses in the table. What happens when they 
> conflict?)

>> Third, at least in
>> theory, the local implementation (even an application) could
>> identify the outgoing interface for a given destination, and might
>> be able to identify it's a tunneling interface.  I do not
>> necessarily require this API consider destination rule #7, but the
>> "excuse" for not doing so should be accurate and convincing.

> Sure, at the local end.
> But the text in RFC 3484 can be interpreted to mean that by magic the 
> host can determine whether there is some IPv6 in IPv4 tunnel somewhere 
> between the host and a particular destination address. It can only do 
> that if 1) the destination syntactically indicates it does tunneling as 
> in the case of 6to4, or 2) the tunnel starts on the host itself.

That's right.

> What do you suggest we clarify to make this more accurate?

Maybe we can simply say the sending host cannot *always* detect
whether the destination is reached via tunnel.  Additional explanation
you mentioned above may also help, but I don't have a particular
opinion on how much of the details we should provide here.

>> 15. [Section 10]
>> Do we really need (standardize) a separate function like
>> inet6_is_srcaddr()?  Perhaps I'm pretty dubious about this
>> just because I'm dubious about the usefulness of the entire API in
>> the first place, but I'd suggest confirming this point with other
>> implementers, particularly with those who are interested in this
>> API.

> I guess the feedback we've gotten doesn't capture whether or not it is 
> necessary; only whether or not it is accurately described.
> I don't recall anybody else arguing against this function. So I'm 
> interested in the opinion of others.

> And since you're dubious about the entire API, I guess you could argue 
> we should remove all the other aspects of the API as well ;-)

True.  Anyway, if others believe this function is useful, then, again,
I won't oppose to introducing the feature.

>> 16. [last paragraph of page 20]
>> The function returns true when srcaddr corresponds to a valid address
>> in the node and that address type satisfies the preference flag(s).
>> 
>> I don't think 'that address type satisfies the preference flag' is
>> well-defined, although it is intuitively understandable.  Please be
>> more precise (c.f. comment #5).  There may actually be subtle cases:
>> e.g., what does it mean if I specify IPV6_PREFER_SRC_SMALLSCOPE as
>> 'flags'?  That is, 'small' is only meaningful when we are comparing
>> multiple things, while this function takes only one address.  I
>> suspect this indicates we should reconsider the function design.

> We tried to make it clear which flags can and can not be tested, but I 
> see the text is still not clear on this. The SCOPE aspects can not be 
> tested with inet6_is_srcaddr(), but can be tested with 
> INET6_IS_LINKLOCAL etc.

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()

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

Then the following point will also be solved naturally:

>> 17. [regarding inet6_is_srcaddr() in general]
>> 
>> If we really need this function (see comment #15), I believe we
>> should clearly separate error cases, i.e., we should not overload
>> the 'false' return value.  This might sound a matter of taste, but I
>> believe it's a common and well-known practice.

> OK.

> There are two different ways to do this and I'd appreciate your opinion 
> on which one to choose.
> 1. A function which returns 3 values: true, false, failure. E.g
> 	int inet6_is_srcaddr(struct sockaddr_in6 *srcaddr,
> 		uint32_t flags);
>     with 3 defined constans for the 3 possible return values.
>     A special case is true=1, false=0, fail=-1.
> 2. A function which returns 0/-1 for ok/fail (like most library calls), 
> and has an extra result parameter for the true/false response. For example,
> 	int inet6_is_srcaddr(struct sockaddr_in6 *srcaddr,
> 		uint32_t flags, int *resultp);

					JINMEI, Tatuya

---

From: JINMEI Tatuya / 神明達哉<[email-masked]>
Date: Fri, 21 Oct 2005 04:07:31 +0900

>>>>> On Fri, 12 Aug 2005 00:38:21 +0900, 
>>>>> JINMEI Tatuya <[email-masked]> said:

> As requested, here are my comments about the addrselect-api draft.

One additional comment (I think this has not been pointed out by
anyone.  sorry if not):

Using new flags for ai_flags of getaddrinfo() may have a compatibility
issue.  RFC3493 says:

   The ai_flags field to which hints parameter points shall be set to
   zero or be the bitwise-inclusive OR of one or more of the values
   AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV,
   AI_V4MAPPED, AI_ALL, and AI_ADDRCONFIG.

I personally don't think this prohibits the use of other flags, but
some existing implementations seem to interpret this part in the
strictest way.  Those return an error of EAI_BADFLAGS if an unknown
flag is specified in hints.ai_flags.  getaddrinfo contained in BSD
variants and in the "libbind" library of ISC BIND behave this way.
For those implementations, applications that use this API extensions
will simply not be working, which is probably what we want to avoid.

However, I cannot think of any other solutions than having these
implementations change the behavior.  So, we should probably first
agree on what the implementation should do for unknown flags and
describe the clarification in this document.

					JINMEI, Tatuya