BIND 10 #2003: support DDNS/TCP response

BIND 10 Development do-not-reply at isc.org
Fri Jun 8 21:44:52 UTC 2012


#2003: support DDNS/TCP response
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:  jinmei
  jinmei                             |                Status:  reviewing
                       Type:  task   |             Milestone:
                   Priority:  low    |  Sprint-20120612
                  Component:  DDNS   |            Resolution:
                   Keywords:         |             Sensitive:  0
            Defect Severity:  N/A    |           Sub-Project:  DNS
Feature Depending on Ticket:  DDNS   |  Estimated Difficulty:  5
        Add Hours to Ticket:  0      |           Total Hours:  0
                  Internal?:  0      |
-------------------------------------+-------------------------------------

Comment (by jinmei):

 Replying to [comment:7 vorner]:

 Thanks for the review.

 > Replying to [comment:4 jinmei]:
 > > I believe the intent of the former is clear from its documentation.
 > > I've made this as a separate module so it can be eventually used
 > > for revised versions of xfrin/xfrout, too.
 >
 > I thought we would use blocking reads/writes in xfrin/out (such as
 socket.sendall). I thought this is the reason why we wanted separate
 forked processes for them.

 I know, and, I still thought utility class(es) like this would be
 useful for them.  We'll still need to handle the 2-byte length field
 some way, so something like `DNSTCPSendBuffer` will be helpful even if
 we use blocking write.  Also, unless we concatenate the length field
 and the actual data binary, we'll still need to call socket.send()
 variants multiple times.  An imaginary extended version of
 `DNSTCPContext` (which would support a blocking mode) would be
 helpful.  Further, at least xfrin will need to receive incoming
 messages, which will require multiple calls to recv variants even if
 each call is blocking.  Another imaginary extended version of
 `DNSTCPContext` (which would support receiving messages, and it's
 necessary even for ddns if we want to keep the TCP connection for
 multiple requests) will be helpful in that case.

 > Not that it would be a problem for the class, but I think it would be an
 overkill for such purpose.

 So, I thought these utilities will be useful even for blocking-based
 applications.  It might still be an overkill if they are only intended
 for blocking apps, but as long as we have non blocking apps (like
 b10-ddns) we'll still need some code that is implemented in this
 module, and, if the support for the blocking apps can be done with a
 relatively minor extensions to the base implementation, I believe it's
 worth doing.  This is basically why I made it as a separate module and
 placed it under server_common from the beginning.

 That said, I also reckon that it may be possible that we won't need
 such abstraction for other applications in the end.  So I tried to
 make it not too generalized at the moment, restricting the necessary
 features for b10-ddns.  If it becomes clear that b10-ddns is the only
 user of these utilities in the end, we can move it inside ddns.py or
 some ddns specific package.

 > I think you forgot to put the dns_tcp_test.py to git. I hope you still
 have it somewhere. This is what I get (both check and distcheck) and I
 don't think I saw the test in the diff:
 > {{{
 > make[6]: Leaving directory
 `/home/vorner/work/bind10/src/lib/python/isc/server_common/tests'
 > make[6]: *** No rule to make target `dns_tcp_test.py', needed by
 `distdir'.  Stop.
 > make[5]: Leaving directory
 `/home/vorner/work/bind10/src/lib/python/isc/server_common'
 > }}}

 Oops, sorry.  I naively thought I'd added everything by confirming
 distcheck passed.  I've git-added and pushed it.

 > Is dropping the connection silently on the quota the best thing to do?

 I agree that's debatable.  Which options other than this are you
 thinking about?

 - returning SERVFAIL or REFUSED?  but it requires to keep the
   connection at least until the transmission of the response is
   completed.
 - buffering the pending requests?  It will still require the server to
   maintain more resource than it's configured, and, it'll be more
   likely that the client times out the request.
 - killing oldest client to allow a new client?  Maybe, but maybe not;
   if the server is simply busy, it could be possible that the server
   is just killing any TCP client before completing any of the
   requests.

 I checked what other server implementations (BIND 9, NSD and unbound)
 do for TCP clients beyond the configured quota.  All of them are
 basically pending the requests by not doing accept() on the listening
 socket.  So it's closer to the second option, although the resource is
 maintained in the kernel, not in the application.  Also, if it takes
 too long for existing clients to be completed, newer requests will be
 refused at the TCP level anyway.

 So, none of the options looked ideal to me, and I chose the simplest
 solution, which is actually not so different from other
 implementations in the end result.

 We can certainly revisit the behavior, but that will be a topic of a
 separate ticket, maybe starting from a team wide discussion.

 > And, generally speaking, isn't 10 as the quota really low?

 This is also debatable, and I'm not sure.  BIND 9's default of
 tcp-clients (not specific to ddns) is 100, so maybe we should use the
 same value.  In any case, as long as we use select, we cannot increase
 it too much due to its scalability.

 > Should the `PYSERVER_COMMON_DNS_TCP_SEND_ERROR` be logged as an ERROR
 instead of WARN? AFAIK WARN is for things that are possibly correct but
 might be wrong, while I don't see a way this could be correct in any
 situation.

 I changed it to WARN, after thinking about it more, with the rationale
 that socket error can happen for reasons outside of the server itself,
 so ERROR seemed to strong.  Also, WARN is the BIND 9's log level for
 an event that sending a response fails (for an error at the layer of
 socket API or below it).  I do not necessarily insist on it though -
 we can discuss the appropriate level for this type of events.

 > The two of the new log messages include the amount of data sent so far.
 Should it log how much it is total as well? (like „%2 of %3 bytes sent so
 far“)?

 Done at commit 85fcef3.  I considered it in the original
 implementation, but didn't do it at that time because it would require
 a cleaner interface to get the total length of the data including the
 length field.  But now that it was asked explicitly, I added the
 interface and updated the log.

-- 
Ticket URL: <http://bind10.isc.org/ticket/2003#comment:8>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list