From: Shawn Routhier Date: Thu, 19 Nov 2009 23:49:57 +0000 (+0000) Subject: Ticket 20540 - clean ups for DHCP-DDNS work, add an change dropped in the X-Git-Tag: v4_2_0a1~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8fa0112dd11ee301046b42fe463074b067e61a35;p=thirdparty%2Fdhcp.git Ticket 20540 - clean ups for DHCP-DDNS work, add an change dropped in the merge, arrange to handle callbacks from the socket code after we've deleted the socket and deal with the quantum issue in the tasks. This last will be removed shortly as a better fix is now available. --- diff --git a/RELNOTES b/RELNOTES index 91cd5cbbb..fb919172c 100644 --- a/RELNOTES +++ b/RELNOTES @@ -13,6 +13,19 @@ Processing the DHCP to DNS server transactions in an asyncrhonous fashion. The DHCP server or client can now continue with it's processing while awaiting replies from the DNS server. +As part of the changes to support asynchronous DNS the DHCP code was +modified to use the current BIND libraries and a small number of changes +were made to the BIND libraries to support DHCP. There is a bug in one +of these changes that can cause an exception in a DHCP server. This bug +requires either failover or omapi to be in use and a number of events +(timeouts, packet reception, packet transmision) to happen within the same +scheduling interval. As a work around the number of events required to +trigger this issue has been increased though this may affect the responsivness +of the DNS code under load. A fix is being developed but needs +to go into a BIND release. Note that the bug is in a part of the BIND +libraries that is only used by the DHCP code and does NOT affect any +other part of the BIND code. + There are a number of DHCPv6 limitations and features missing in this release, which will be addressed in the future: diff --git a/includes/omapip/omapip_p.h b/includes/omapip/omapip_p.h index 465f8fd3f..f94644ac1 100644 --- a/includes/omapip/omapip_p.h +++ b/includes/omapip/omapip_p.h @@ -214,6 +214,7 @@ typedef struct __omapi_io_object { isc_result_t (*writer) (omapi_object_t *); isc_result_t (*reaper) (omapi_object_t *); isc_socket_t *fd; + isc_boolean_t closed; /* ISC_TRUE = closed, do not use */ } omapi_io_object_t; typedef struct __omapi_generic_object { diff --git a/omapip/connection.c b/omapip/connection.c index b32ee7481..1149c520b 100644 --- a/omapip/connection.c +++ b/omapip/connection.c @@ -587,6 +587,15 @@ isc_result_t omapi_connection_connect (omapi_object_t *h) status = omapi_connection_connect_internal (h); if (status != ISC_R_SUCCESS) omapi_signal (h, "status", status); + + /* + * Currently we use the INPROGRESS error to indicate that + * we want more from the socket. In this case we have now connected + * and are trying to write to the socket for the first time. + */ + if (status == ISC_R_INPROGRESS) + return ISC_R_INPROGRESS; + return ISC_R_SUCCESS; } @@ -699,7 +708,7 @@ static isc_result_t omapi_connection_connect_internal (omapi_object_t *h) omapi_signal_in (h, "connect"); omapi_addr_list_dereference (&c -> connect_list, MDL); - return ISC_R_SUCCESS; + return ISC_R_INPROGRESS; } /* Reaper function for connection - if the connection is completely closed, diff --git a/omapip/dispatch.c b/omapip/dispatch.c index 887a337b1..8ee274327 100644 --- a/omapip/dispatch.c +++ b/omapip/dispatch.c @@ -116,6 +116,12 @@ trigger_event(struct eventqueue **queue) * we can write more. If we indicate we don't have more to write we need * to poke the library via isc_socket_fdwatchpoke. */ + +/* + * sockdelete indicates if we are deleting the socket or leaving it in place + * 1 is delete, 0 is leave in place + */ +#define SOCKDELETE 1 int omapi_iscsock_cb(isc_task_t *task, isc_socket_t *socket, @@ -128,12 +134,40 @@ omapi_iscsock_cb(isc_task_t *task, /* Get the current time... */ gettimeofday (&cur_tv, (struct timezone *)0); + /* isc socket stuff */ +#if SOCKDELETE + /* + * walk through the io states list, if our object is on there + * service it. if not ignore it. + */ + for (obj = omapi_io_states.next; + (obj != NULL) && (obj->next != NULL); + obj = obj->next) { + if (obj == cbarg) + break; + } + if (obj == NULL) { + return(0); + } +#else /* Not much to be done if we have the wrong type of object. */ if (((omapi_object_t *)cbarg) -> type != omapi_type_io_object) { log_fatal ("Incorrect object type, must be of type io_object"); } obj = (omapi_io_object_t *)cbarg; + /* + * If the object is marked as closed don't try and process + * anything just indicate that we don't want any more. + * + * This should be a temporary fix until we arrange to properly + * close the socket. + */ + if (obj->closed == ISC_TRUE) { + return(0); + } +#endif + if ((flags == ISC_SOCKFDWATCH_READ) && (obj->reader != NULL) && (obj->inner != NULL)) { @@ -189,6 +223,7 @@ isc_result_t omapi_register_io_object (omapi_object_t *h, status = omapi_io_allocate (&obj, MDL); if (status != ISC_R_SUCCESS) return status; + obj->closed = ISC_FALSE; /* mark as open */ status = omapi_object_reference (&obj -> inner, h, MDL); if (status != ISC_R_SUCCESS) { @@ -259,11 +294,13 @@ isc_result_t omapi_register_io_object (omapi_object_t *h, return ISC_R_SUCCESS; } -/* ReRegister an I/O handle so that we can do asynchronous I/O on it. +/* + * ReRegister an I/O handle so that we can do asynchronous I/O on it. * If the handle doesn't exist we call the register routine to build it. - * if it does exist we change the functions associated with it, and + * If it does exist we change the functions associated with it, and * repoke the fd code to make it happy. Neither the objects nor the - * fd are allowed to have changed. */ + * fd are allowed to have changed. + */ isc_result_t omapi_reregister_io_object (omapi_object_t *h, int (*readfd) (omapi_object_t *), @@ -276,9 +313,11 @@ isc_result_t omapi_reregister_io_object (omapi_object_t *h, (omapi_object_t *)) { omapi_io_object_t *obj; + int fd_flags = 0; if ((!h -> outer) || (h -> outer -> type != omapi_type_io_object)) { - /* If we don't have an object or if the type isn't what + /* + * If we don't have an object or if the type isn't what * we expect do the normal registration (which will overwrite * an incorrect type, that's what we did historically, may * want to change that) @@ -294,18 +333,31 @@ isc_result_t omapi_reregister_io_object (omapi_object_t *h, obj = (omapi_io_object_t *)h->outer; - obj -> readfd = readfd; - obj -> writefd = writefd; - obj -> reader = reader; - obj -> writer = writer; - obj -> reaper = reaper; + obj->readfd = readfd; + obj->writefd = writefd; + obj->reader = reader; + obj->writer = writer; + obj->reaper = reaper; + + if (readfd) { + fd_flags |= ISC_SOCKFDWATCH_READ; + } + + if (writefd) { + fd_flags |= ISC_SOCKFDWATCH_WRITE; + } + + isc_socket_fdwatchpoke(obj->fd, fd_flags); return (ISC_R_SUCCESS); } isc_result_t omapi_unregister_io_object (omapi_object_t *h) { - omapi_io_object_t *p, *obj, *last, *ph; + omapi_io_object_t *obj, *ph; +#if SOCKDELETE + omapi_io_object_t *p, *last; +#endif if (!h -> outer || h -> outer -> type != omapi_type_io_object) return DHCP_R_INVALIDARG; @@ -313,6 +365,14 @@ isc_result_t omapi_unregister_io_object (omapi_object_t *h) ph = (omapi_io_object_t *)0; omapi_io_reference (&ph, obj, MDL); +#if SOCKDELETE + /* + * For now we leave this out. We can't clean up the isc socket + * structure cleanly yet so we need to leave the io object in place. + * By leaving it on the io states list we avoid it being freed. + * We also mark it as closed to avoid using it. + */ + /* remove from the list of I/O states */ last = &omapi_io_states; for (p = omapi_io_states.next; p; p = p -> next) { @@ -325,6 +385,7 @@ isc_result_t omapi_unregister_io_object (omapi_object_t *h) } if (obj -> next) omapi_io_dereference (&obj -> next, MDL); +#endif if (obj -> outer) { if (obj -> outer -> inner == (omapi_object_t *)obj) @@ -335,10 +396,16 @@ isc_result_t omapi_unregister_io_object (omapi_object_t *h) omapi_object_dereference (&obj -> inner, MDL); omapi_object_dereference (&h -> outer, MDL); +#if SOCKDELETE /* remove isc socket associations */ if (obj->fd != NULL) { + isc_socket_cancel(obj->fd, dhcp_gbl_ctx.task, + ISC_SOCKCANCEL_ALL); isc_socket_detach(&obj->fd); } +#else + obj->closed = ISC_TRUE; +#endif omapi_io_dereference (&ph, MDL); return ISC_R_SUCCESS; diff --git a/omapip/isclib.c b/omapip/isclib.c index 3225096d2..59bba1ffd 100644 --- a/omapip/isclib.c +++ b/omapip/isclib.c @@ -127,7 +127,16 @@ dhcp_context_create(void) { if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_task_create(dhcp_gbl_ctx.taskmgr, 0, &dhcp_gbl_ctx.task); + /*sar*/ + /* + * We currently use a large number for quantum to get around + * an issue in the fdwatchpoke code that allows us to re-check + * a socket for reading or writing even if it already has a pending + * read or write. This event causes an exception and stops the + * program. When that code is fixed the quantum can be reduced. + */ + result = isc_task_create(dhcp_gbl_ctx.taskmgr, 100, + &dhcp_gbl_ctx.task); if (result != ISC_R_SUCCESS) goto cleanup; diff --git a/util/bindlib.sh b/util/bindlib.sh index 482b13b32..23cafef7f 100644 --- a/util/bindlib.sh +++ b/util/bindlib.sh @@ -14,7 +14,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: bindlib.sh,v 1.4 2009/11/03 02:57:22 marka Exp $ +# $Id: bindlib.sh,v 1.5 2009/11/19 23:49:57 sar Exp $ # Configure, build and install the bind export libraries for use by DHCP # @@ -45,10 +45,12 @@ if test -z "$gmake"; then fi # Configure the export libraries +# Currently disable the epoll and devpoll options as they don't interact +# well with the DHCP code. cd $bindsrcdir -./configure --without-openssl --without-libxml2 --enable-exportlib --enable-threads=no --with-export-includedir=$binddir/include --with-export-libdir=$binddir/lib > $binddir/configure.log +./configure --disable-epoll --disable-devpoll --without-openssl --without-libxml2 --enable-exportlib --enable-threads=no --with-export-includedir=$binddir/include --with-export-libdir=$binddir/lib > $binddir/configure.log -# Build the export librares +# Build the export libraries cd lib/export MAKE=$gmake $gmake > $binddir/build.log