diff --git a/configure.ac b/configure.ac
index 7c4d6ed19..ca63166ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,7 +44,7 @@ AC_PROG_LIBTOOL
 AC_HEADER_DIRENT
 AC_HEADER_STDC
 AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/file.h sys/socket.h sys/time.h syslog.h unistd.h mntent.h sys/sysinfo.h sys/endian.h endian.h])
+AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/file.h sys/socket.h sys/time.h syslog.h unistd.h mntent.h sys/sysinfo.h sys/endian.h endian.h sys/epoll.h])
 
 # These are *required* headers without option.
 AC_CHECK_HEADERS([inttypes.h], [], AC_MSG_ERROR([unable to locate required header inttypes.h]))
@@ -397,6 +397,22 @@ else
 fi
 AM_CONDITIONAL(enable_posix_winsync,test "$enable_posix_winsync" = "yes")
 
+if test -z "$enable_epoll" ; then
+   enable_epoll=no # if not set on cmdline, set default
+fi
+AC_MSG_CHECKING(for --enable-epoll)
+AC_ARG_ENABLE(epoll,
+        AS_HELP_STRING([--enable-epoll],
+                       [enable support for epoll (default: no)]))
+if test "$enable_epoll" = yes ; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE([ENABLE_EPOLL], [1], [enable support for epoll])
+else
+  AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(enable_epoll,test "$enable_epoll" = "yes")
+
+
 # the default prefix - override with --prefix or --with-fhs
 AC_PREFIX_DEFAULT([/opt/$PACKAGE_NAME])
 
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index fd72a9a43..4d7961b1b 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1851,7 +1851,7 @@ connection_threadmain(void *arg)
 
             /* If we're in turbo mode, we keep our reference to the connection alive */
             /* can't use the more_data var because connection could have changed in another thread */
-            slapi_log_err(SLAPI_LOG_CONNS, "connection_threadmain", "conn %" PRIu64 " check more_data %d thread_turbo_flag %d"
+            slapi_log_err(SLAPI_LOG_CONNS, "connection_threadmain", "conn %" PRIu64 " check more_data %d thread_turbo_flag %d "
                           "repl_conn_bef %d, repl_conn_now %d\n",
                           conn->c_connid, more_data, thread_turbo_flag,
                           replication_connection, conn->c_isreplication_session);
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index feb9c0d75..14592a63e 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -138,6 +138,14 @@ connection_table_new(int table_size)
     ct->conn_next_offset = 1;
     ct->conn_free_offset = 1;
 
+#if defined(ENABLE_EPOLL)
+    ct->epollfd = epoll_create1(0);
+    if (ct->epollfd == -1) {
+        slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "epoll_create1 failed\n");
+        exit(1);
+    }
+#endif /* ENABLE_EPOLL */
+
     pthread_mutexattr_t monitor_attr = {0};
     pthread_mutexattr_init(&monitor_attr);
     pthread_mutexattr_settype(&monitor_attr, PTHREAD_MUTEX_RECURSIVE);
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index ffcf66d22..86169e070 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -96,6 +96,13 @@ typedef struct listener_info
 static size_t listeners = 0;                /* number of listener sockets */
 static listener_info *listener_idxs = NULL; /* array of indexes of listener sockets in the ct->fd array */
 
+#ifdef ENABLE_EPOLL
+static struct epoll_event *epoll_events = NULL;  /* array of epoll events in ct->epollfd array */
+#define EPOLLEVENTS EPOLLIN|EPOLLPRI
+#define EPOLL_PD_DISARM 0
+#define EPOLL_PD_ARM 1
+#endif
+
 #define SLAPD_POLL_LISTEN_READY(xxflagsxx) (xxflagsxx & PR_POLL_READ)
 
 static int get_configured_connection_table_size(void);
@@ -145,6 +152,16 @@ accept_and_configure(int s __attribute__((unused)), PRFileDesc *pr_acceptfd, PRN
  * This is the shiny new re-born daemon function, without all the hair
  */
 static int handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local, Connection **newconn);
+
+#ifdef ENABLE_EPOLL
+static void epoll_pr_idle_pds(Connection_Table *ct);
+static void handle_epoll_pr_read_ready(Connection_Table *ct, Connection *c, struct epoll_event event);
+Connection *setup_epoll_listen_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read);
+void epoll_arm_pd(Connection_Table *ct, Connection *c, int arm, char *string);
+void epoll_arm_listen_pds(Connection_Table *ct, Connection *lt, int arm);
+void free_epoll_listen_table(Connection *lt);
+#endif
+
 static void handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll);
 static int clear_signal(struct POLL_STRUCT *fds);
 static void unfurl_banners(Connection_Table *ct, daemon_ports_t *ports, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix);
@@ -754,6 +771,26 @@ disk_monitoring_thread(void *nothing __attribute__((unused)))
         return;
 }
 
+#ifdef ENABLE_EPOLL
+static void
+handle_epoll_listener(Connection_Table *ct, Connection *c)
+{
+
+    PRFileDesc *listenfd = listener_idxs[c->c_fdi].listenfd;
+    int secure = listener_idxs[c->c_fdi].secure;
+    int local = listener_idxs[c->c_fdi].local;
+
+    slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_listener", "Handle new connection listenfd=%d (secure=%d, local=%d)\n",
+                  PR_FileDesc2NativeHandle(listenfd), secure, local);
+    int rc = handle_new_connection(ct, SLAPD_INVALID_SOCKET, listenfd, secure, local, NULL);
+    if (rc) {
+        slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_listener", "Error accepting new connection listenfd=%d\n",
+                      PR_FileDesc2NativeHandle(listenfd));
+    }
+    return;
+}
+#endif /* ENABLE_EPOLL */
+
 static void
 handle_listeners(Connection_Table *ct)
 {
@@ -981,6 +1018,18 @@ slapd_daemon(daemon_ports_t *ports)
     int in_referral_mode = config_check_referral_mode();
     int connection_table_size = get_configured_connection_table_size();
     the_connection_table = connection_table_new(connection_table_size);
+    int epoll_fds;
+
+#ifdef ENABLE_EPOLL
+    slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+    int accept_new_connections;
+    static int last_accept_new_connections = -1;
+    struct epoll_event ev;
+    if (the_connection_table->epollfd != -1) {
+        epoll_events = (struct epoll_event *)slapi_ch_calloc(connection_table_size, sizeof(*epoll_events));
+    }
+    static time_t epoll_idle_timer = 0;
+#endif
 
     /*
      * Log a warning if we detect nunc-stans
@@ -1154,11 +1203,68 @@ slapd_daemon(daemon_ports_t *ports)
                (unsigned long)getpid());
 #endif
 
+#ifdef ENABLE_EPOLL
+    Connection *the_listen_table = NULL;
+    if (!g_get_shutdown()) {
+        the_listen_table = setup_epoll_listen_pds(the_connection_table, n_tcps, s_tcps, i_unix, &num_poll);
+    }
+#endif /* ENABLE_EPOLL */
+
     /* The meat of the operation is in a loop on a call to select */
     while (!g_get_shutdown()) {
         int select_return = 0;
         PRErrorCode prerr;
 
+#ifdef ENABLE_EPOLL
+        accept_new_connections = ((the_connection_table->size - g_get_current_conn_count()) > slapdFrontendConfig->reservedescriptors);
+
+        if (accept_new_connections != last_accept_new_connections) {
+            slapi_log_err(SLAPI_LOG_ERR, "slapd_daemon",
+                          "%s for new connections%s\n",
+                          accept_new_connections ? "Listening for" : "Not listening",
+                          accept_new_connections ? "" : " - too many fds open");
+            epoll_arm_listen_pds(the_connection_table, the_listen_table, accept_new_connections);
+        }
+        last_accept_new_connections = accept_new_connections;
+
+        int i;
+        Connection *c;
+        epoll_fds = epoll_wait(the_connection_table->epollfd, epoll_events, sizeof(epoll_events), slapd_wakeup_timer);
+        switch (epoll_fds) {
+        case 0: /* Timeout */
+            /* XXX Sweep idle connections, but not too aggresively - should be configurable */
+            if (epoll_idle_timer + 10 < slapi_current_rel_time_t()) {
+                epoll_pr_idle_pds(the_connection_table);
+                epoll_idle_timer = slapi_current_rel_time_t();
+            }
+            break;
+        case -1: /* Error */
+            slapi_log_err(SLAPI_LOG_TRACE, "slapd_daemon", "epoll_wait() failed, error %d (%s)\n",
+                          errno, slapd_system_strerror(errno));
+            break;
+        default: /* either a new connection or data ready */
+            slapi_log_err(SLAPI_LOG_TRACE, "slapd_daemon", "epoll_ctl: %d fds ready.\n", epoll_fds);
+            for (i = 0; i < epoll_fds; i++) {
+                c = epoll_events[i].data.ptr;
+                /* handle new connections from the listeners */
+                /* XXX  Occasionally getting crushed by accepts, should there be a limit
+                 * on how many accepts per loop? Alternately, this should just be an accept thread.*/
+                if (c->c_state == CONN_STATE_LISTEN) {
+                    handle_epoll_listener(the_connection_table, c);
+                /* handle new data ready */
+                } else {
+                    handle_epoll_pr_read_ready(the_connection_table, c, epoll_events[i]);
+                }
+            }
+            clear_signal(the_connection_table->fd);
+            break;
+        }
+        /* XXX Sweep idle connections, but not too aggresively - should be configurable */
+        if (epoll_idle_timer + 10 < slapi_current_rel_time_t()) {
+            epoll_pr_idle_pds(the_connection_table);
+            epoll_idle_timer = slapi_current_rel_time_t();
+        }
+#else
         setup_pr_read_pds(the_connection_table, n_tcps, s_tcps, i_unix, &num_poll);
         select_return = POLL_FN(the_connection_table->fd, num_poll, pr_timeout);
         switch (select_return) {
@@ -1177,6 +1283,7 @@ slapd_daemon(daemon_ports_t *ports)
             clear_signal(the_connection_table->fd);
             break;
         }
+#endif
     }
     /* We get here when the server is shutting down */
     /* Do what we have to do before death */
@@ -1185,6 +1292,16 @@ slapd_daemon(daemon_ports_t *ports)
     sd_notify(0, "STOPPING=1");
 #endif
 
+#ifdef ENABLE_EPOLL
+    epoll_arm_listen_pds(the_connection_table, the_listen_table, EPOLL_PD_DISARM);
+    free_epoll_listen_table(the_listen_table);
+
+    /* free the epoll event array */
+    if (the_connection_table->epollfd != -1) {
+        slapi_ch_free((void **)&epoll_events);
+    }
+#endif
+
     connection_table_abandon_all_operations(the_connection_table); /* abandon all operations in progress */
 
     if (!in_referral_mode) {
@@ -1387,7 +1504,6 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
     }
     last_accept_new_connections = accept_new_connections;
 
-
     /* initialize the mapping from connection table entries to fds entries */
     if (first_time_setup_pr_read_pds) {
         int i;
@@ -1563,6 +1679,361 @@ daemon_register_reslimits(void)
                                     &idletimeout_reslimit_handle));
 }
 
+#ifdef ENABLE_EPOLL
+static void
+epoll_pr_idle_pds(Connection_Table *ct)
+{
+    /* XXX
+     * For discussion:
+     * This function should only be cleaning up connections from the table
+     * that have reached some terminal state such as an I/O timeout or some limit
+     * exeception.
+     *
+     * Can or should active connection removals be completed in handle_epoll_pr_read_ready?
+     */
+    Connection *c = NULL;
+    Connection *next = NULL;
+
+    /* XXX This is just for debugging and should be removed START */
+    slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection count %d/%d\n",
+                  g_get_current_conn_count(), ct->size);
+    /* XXX This is just for debugging and should be removed END */
+
+    /* Walk down the list of active connections to find idle connections. */
+    c = connection_table_get_first_active_connection(ct);
+    while (c) {
+        next = connection_table_get_next_active_connection(ct, c);
+        if (c->c_state == CONN_STATE_FREE) {
+            epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "epoll_pr_idle_pds 1");
+            slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection_table_move_connection_out_of_active_list conn=%" PRIu64 " fd=%d (c = %p) 1\n", c->c_connid, c->c_sd, c); // XXX
+            connection_table_move_connection_out_of_active_list(ct, c);
+        } else {
+            /* we try to acquire the connection mutex, if it is already
+             * acquired by another thread, don't wait
+             */
+            if (pthread_mutex_trylock(&(c->c_mutex)) == EBUSY) {
+                c = next;
+                continue;
+            }
+            if (c->c_flags & CONN_FLAG_CLOSING) {
+                /* A worker thread has marked that this connection
+                 * should be closed by calling disconnect_server.
+                 * move this connection out of the active list
+                 * the last thread to use the connection will close it
+                 */
+                /* XXX Get a lot of errno 2 here, but not always */
+                epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "epoll_pr_idle_pds 2");
+                slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection_table_move_connection_out_of_active_list conn=%" PRIu64 " fd=%d (c = %p) 2\n", c->c_connid, c->c_sd, c); // XXX
+                connection_table_move_connection_out_of_active_list(ct, c);
+            } else if (c->c_sd == SLAPD_INVALID_SOCKET) {
+                slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "SLAPD_INVALID_SOCKET calling epoll_arm_pd\n");
+                epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "epoll_pr_idle_pds 3");
+                slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection_table_move_connection_out_of_active_list conn=%" PRIu64 " fd=%d (c = %p) 3\n", c->c_connid, c->c_sd, c); // XXX
+                connection_table_move_connection_out_of_active_list(ct, c);
+            } else if (c->c_prfd != NULL) {
+                if ((!c->c_gettingber) && (c->c_threadnumber < c->c_max_threads_per_conn)) {
+                    /* check timeout for PAGED RESULTS */
+                    if (pagedresults_is_timedout_nolock(c)) {
+                        /* Exceeded the timelimit; disconnect the client */
+                        slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "PAGED RESULT timeout calling epoll_arm_pd\n");
+                        epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "epoll_pr_idle_pds 4");
+                        slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection_table_move_connection_out_of_active_list conn=%" PRIu64 " fd=%d (c = %p) 4\n", c->c_connid, c->c_sd, c); // XXX
+                        disconnect_server_nomutex(c, c->c_connid, -1,
+                                                  SLAPD_DISCONNECT_IO_TIMEOUT,
+                                                  0);
+                        connection_table_move_connection_out_of_active_list(ct, c);
+                    }
+                } else {
+                    /* XXX
+                     * What to do here, shouldn't we just disconnect this client?
+                     * Is there a state where we should re-arm this client?
+                     */
+                    if (c->c_threadnumber >= c->c_max_threads_per_conn) {
+                        c->c_maxthreadsblocked++;
+                        if (c->c_maxthreadsblocked == 1 && connection_has_psearch(c)) {
+                            slapi_log_err(SLAPI_LOG_NOTICE, "connection_threadmain",
+                                    "Connection (conn=%" PRIu64 ") has a running persistent search "
+                                    "that has exceeded the maximum allowed threads per connection. "
+                                    "New operations will be blocked.\n",
+                                    c->c_connid);
+                        }
+                    }
+                    epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "idle pds 5");
+                    slapi_log_err(SLAPI_LOG_CONNS, "epoll_pr_idle_pds", "connection_table_move_connection_out_of_active_list conn=%" PRIu64 " fd=%d (c = %p) 5\n", c->c_connid, c->c_sd, c); // XXX
+                    disconnect_server_nomutex(c, c->c_connid, -1,
+                                              SLAPD_DISCONNECT_IO_TIMEOUT,
+                                              0);
+                }
+            }
+            pthread_mutex_unlock(&(c->c_mutex));
+        }
+        c = next;
+    }
+}
+
+void
+epoll_arm_pd(Connection_Table *ct, Connection *c, int arm, char *locater)
+{
+    struct epoll_event ev;
+    int epoll_ctl_cmd = EPOLL_CTL_ADD;
+
+    ev.events = EPOLLEVENTS;
+    ev.data.ptr = c;
+
+    if (arm != EPOLL_PD_ARM) {
+        epoll_ctl_cmd = EPOLL_CTL_DEL;
+    }
+
+    slapi_log_err(SLAPI_LOG_CONNS, "epoll_arm_pd", "epoll_ctl_cmd %s conn=%" PRIu64 " fd=%d %p. (%s)\n",
+                  arm == EPOLL_PD_ARM ? "EPOLL_CTL_ADD" : "EPOLL_CTL_DEL",
+                  c->c_connid, c->c_sd, ev.data.ptr, locater);
+    if (epoll_ctl(ct->epollfd, epoll_ctl_cmd, c->c_sd, &ev) == -1) {
+        slapi_log_err(SLAPI_LOG_CONNS, "epoll_arm_pd", "epoll_ctl_cmd %s conn=%" PRIu64 " fd=%d %p: failed %d %s. (%s)\n",
+                      arm == EPOLL_PD_ARM ? "EPOLL_CTL_ADD" : "EPOLL_CTL_DEL",
+                      c->c_connid, c->c_sd, ev.data.ptr,
+                      errno, slapd_system_strerror(errno), locater);
+    }
+}
+
+void
+epoll_arm_listen_pds(Connection_Table *ct, Connection *lt, int arm)
+{
+    Connection *c = NULL;
+    Connection *next = NULL;
+
+    slapi_log_err(SLAPI_LOG_CONNS, "epoll_arm_listen_pds", "%s listen pds.\n",
+                  arm == EPOLL_PD_ARM ? "arming" : "disarming");
+    for (c = lt; c; c = c->c_next) {
+        epoll_arm_pd(ct, c, arm, "listen pds");
+    }
+
+}
+
+void
+free_epoll_listen_table(Connection *lt)
+{
+    Connection *c = lt;
+    Connection *next = NULL;
+
+    while(c) {
+        next = c->c_next;
+        slapi_log_err(SLAPI_LOG_WARNING, "free_epoll_listen table", "conn=%" PRIu64 " fd=%d pd %p.\n", c->c_connid, c->c_sd, c);
+        slapi_ch_free((void **)&c);
+	c = next;
+    }
+}
+
+Connection *
+epoll_listen_queue_add_pd(Connection *lt, Connection *l)
+{
+    Connection *c = NULL;
+
+    if (lt == NULL)
+    {
+        lt = l;
+        l->c_prev = NULL;
+        l->c_next = NULL;
+    } else {
+        c = lt;
+        while (c && c->c_next) {
+            c = c->c_next;
+        }
+        c->c_next = l;
+        l->c_next = NULL;
+        l->c_prev = c;
+    }
+
+    return lt;
+}
+
+Connection *
+setup_epoll_listen_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read)
+{
+    Connection *listen_table = NULL;
+    Connection *c = NULL;
+    Connection *next = NULL;
+    LBER_SOCKET socketdesc = SLAPD_INVALID_SOCKET;
+    PRFileDesc **fdesc = NULL;
+    slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+    size_t n_listeners = 0;
+    int i;
+
+    /* The fds entry for n_tcps starts with n_tcps and less than n_tcpe */
+    ct->n_tcps = n_listeners;
+
+    fdesc = NULL;
+    for (fdesc = n_tcps; fdesc && *fdesc; fdesc++, n_listeners++) {
+        listener_idxs[n_listeners].listenfd = *fdesc;
+        listener_idxs[n_listeners].idx = n_listeners;
+
+        next = (Connection *)slapi_ch_calloc(1, sizeof(Connection));
+        next->c_state = CONN_STATE_LISTEN;
+        next->c_fdi = n_listeners;
+        next->c_prfd = *fdesc;
+        next->c_sd = PR_FileDesc2NativeHandle(*fdesc);
+
+        listen_table = epoll_listen_queue_add_pd(listen_table, next);
+    }
+    ct->n_tcpe = n_listeners;
+
+    ct->s_tcps = n_listeners;
+    /* The fds entry for s_tcps starts with s_tcps and less than s_tcpe */
+    fdesc = NULL;
+    for (fdesc = s_tcps; fdesc && *fdesc; fdesc++, n_listeners++) {
+        listener_idxs[n_listeners].listenfd = *fdesc;
+        listener_idxs[n_listeners].idx = n_listeners;
+        listener_idxs[n_listeners].secure = 1;
+
+        next = (Connection *)slapi_ch_calloc(1, sizeof(Connection));
+        next->c_state = CONN_STATE_LISTEN;
+        next->c_fdi = n_listeners;
+        next->c_prfd = *fdesc;
+        next->c_sd = PR_FileDesc2NativeHandle(*fdesc);
+
+        listen_table = epoll_listen_queue_add_pd(listen_table, next);
+
+        slapi_log_err(SLAPI_LOG_HOUSE,
+                      "setup_epoll_listen_pds", "Listening for SSL connections on %d\n", socketdesc);
+    }
+    ct->s_tcpe = n_listeners;
+
+#if defined(ENABLE_LDAPI)
+    ct->i_unixs = n_listeners;
+    /* The fds entry for i_unix starts with i_unixs and less than i_unixe */
+    fdesc = NULL;
+    for (fdesc = i_unix; fdesc && *fdesc; fdesc++, n_listeners++) {
+        listener_idxs[n_listeners].listenfd = *fdesc;
+        listener_idxs[n_listeners].idx = n_listeners;
+        listener_idxs[n_listeners].local = 1;
+
+        next = (Connection *)slapi_ch_calloc(1, sizeof(Connection));
+        next->c_state = CONN_STATE_LISTEN;
+        next->c_fdi = n_listeners;
+        next->c_prfd = *fdesc;
+        next->c_sd = PR_FileDesc2NativeHandle(*fdesc);
+
+        listen_table = epoll_listen_queue_add_pd(listen_table, next);
+
+        slapi_log_err(SLAPI_LOG_HOUSE,
+                      "setup_epoll_listen_pds", "Listening for LDAPI connections on %d\n", socketdesc);
+    }
+#endif
+    ct->i_unixe = n_listeners;
+
+    if (n_listeners < listeners) {
+        listener_idxs[n_listeners].idx = 0;
+        listener_idxs[n_listeners].listenfd = NULL;
+    }
+    listen_addr_count = n_listeners;
+
+    return(listen_table);
+}
+
+/* XXX This struct is just for debugging and should be removed,
+ * see below in handle_epoll_pr_read_ready */
+typedef struct epoll_flags {
+    int flag;
+    char *name;
+} epoll_flags;
+
+static void
+handle_epoll_pr_read_ready(Connection_Table *ct, Connection *c, struct epoll_event event)
+{
+    /* XXX This is just for debugging and should be removed START */
+    epoll_flags flags[] = { { EPOLLIN, "|EPOLLIN" }, { EPOLLOUT, "|EPOLLOUT" },
+                            { EPOLLRDHUP, "|EPOLLRDHUP" }, { EPOLLPRI, "|EPOLLPRI" },
+                            { EPOLLERR, "|EPOLLERR" }, { EPOLLHUP, "|EPOLLHUP" },
+                            { EPOLLET, "|EPOLLET" }, { EPOLLONESHOT, "|EPOLLONESHOT" },
+                            { EPOLLWAKEUP, "|EPOLLWAKEUP" }, { EPOLLEXCLUSIVE, "|EPOLLEXCLUSIVE" },
+                            { 0, NULL } };
+    char eventstring[256] = "";
+
+    if (event.events & ~EPOLLIN) {
+        int i;
+        int offset = 1;
+        for (i = 0; flags[i].name != NULL; i++) {
+            if (event.events & flags[i].flag) {
+                strcpy(eventstring + strlen(eventstring), flags[i].name + offset);
+                offset = 0;
+            }
+        }
+        slapi_log_err(SLAPI_LOG_WARNING, "handle_epoll_pr_read_ready", "epoll events conn=%" PRIu64 " fd=%d %p: %s\n",
+                  c->c_connid, c->c_sd, event.data.ptr, eventstring);
+    }
+    /* XXX This is just for debugging and should be removed END */
+
+    time_t curtime = slapi_current_rel_time_t();
+
+    pthread_mutex_lock(&(c->c_mutex));
+    //if (connection_is_active_nolock(c) && c->c_gettingber == 0) { / XXX
+    if (!(c->c_flags & CONN_FLAG_CLOSING) && c->c_gettingber == 0) {
+        PRInt16 out_flags, err_flags;
+        short readready;
+
+        slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_pr_read_ready", "!CONN_FLAG_CLOSING && c->c_gettingber==0 conn=%" PRIu64 " fd=%d %p: %s\n",
+                  c->c_connid, c->c_sd, event.data.ptr, eventstring);
+
+        out_flags = event.events;
+        err_flags = event.events & (EPOLLRDHUP|EPOLLERR|EPOLLHUP);
+
+	/* XXX See if we can kick these faster */
+/*        if (c->c_flags & CONN_FLAG_CLOSING) {
+            slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_pr_read_ready", "c = %p CONN_FLAG_CLOSING\n", c);
+            epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "handle_epoll_pr_read_ready 1");
+            connection_table_move_connection_out_of_active_list(ct, c);
+            out_flags = 0;
+        }
+*/
+
+        readready = (out_flags & EPOLLIN);
+
+        if (event.events & ~EPOLLIN) {
+            /* some error occured */
+            slapi_log_err(SLAPI_LOG_CONNS,
+                          "handle_epoll_pr_read_ready", "POLL_FN() says connection on sd %d is bad "
+                                                  "(closing)\n",
+                          c->c_sd);
+            epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "handle_epoll_pr_read_ready 2");
+            slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_pr_read_ready", "disconnect_server_nomutex conn=%" PRIu64 " fd=%d (%p) 2\n", c->c_connid, c->c_sd, c); // XXX
+            disconnect_server_nomutex(c, c->c_connid, -1,
+                                      SLAPD_DISCONNECT_POLL, EPIPE);
+        } else if (readready) {
+            /* read activity */
+            slapi_log_err(SLAPI_LOG_CONNS,
+                          "handle_epoll_pr_read_ready", "read activity on conn%d fd=%d %p\n", c->c_connid, c->c_sd, c);
+            c->c_idlesince = curtime;
+
+            /* This is where the work happens ! */
+            /* MAB: 25 jan 01, error handling added */
+            if ((connection_activity(c, c->c_max_threads_per_conn)) == -1) {
+                /* This might happen as a result of
+                 * trying to acquire a closing connection
+                 */
+                slapi_log_err(SLAPI_LOG_ERR,
+                              "handle_epoll_pr_read_ready", "connection_activity: abandoning conn %" PRIu64 " as "
+                                                      "fd=%d is already closing\n",
+                              c->c_connid, c->c_sd);
+                /* The call disconnect_server should do nothing,
+                 * as the connection c should be already set to CLOSING */
+                slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_pr_read_ready", "disconnect_server_nomutex conn=%" PRIu64 " fd=%d %p 3\n", c, c->c_connid, c->c_sd); // XXX
+                epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "pr read ready 3");
+                disconnect_server_nomutex(c, c->c_connid, -1,
+                                          SLAPD_DISCONNECT_POLL, EPIPE);
+            }
+        } else if (c->c_idletimeout > 0 &&
+                   (curtime - c->c_idlesince) >= c->c_idletimeout &&
+                   NULL == c->c_ops) {
+            /* idle timeout */
+            epoll_arm_pd(the_connection_table, c, EPOLL_PD_DISARM, "pr read ready 4");
+            slapi_log_err(SLAPI_LOG_CONNS, "handle_epoll_pr_read_ready", "disconnect_server_nomutex conn=%" PRIu64 " fd=%d %p 4\n", c, c->c_connid, c->c_sd); // XXX
+            disconnect_server_nomutex(c, c->c_connid, -1,
+                                      SLAPD_DISCONNECT_IDLE_TIMEOUT, ETIMEDOUT);
+        }
+    }
+    pthread_mutex_unlock(&(c->c_mutex));
+}
+#endif /* ENABLE_EPOLL */
+
 static void
 handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll __attribute__((unused)))
 {
@@ -1845,6 +2316,9 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
     PRFileDesc *pr_clonefd = NULL;
     slapdFrontendConfig_t *fecfg = getFrontendConfig();
     ber_len_t maxbersize;
+#ifdef ENABLE_EPOLL
+    struct epoll_event ev;
+#endif
 
     if (newconn) {
         *newconn = NULL;
@@ -1872,6 +2346,10 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
     conn->c_prfd = pr_clonefd;
     conn->c_flags &= ~CONN_FLAG_CLOSING;
 
+#ifdef ENABLE_EPOLL
+    epoll_arm_pd(the_connection_table, conn, EPOLL_PD_ARM, "handle_new_connection");
+#endif
+
     /* Set per connection static config */
     conn->c_maxbersize = config_get_maxbersize();
     conn->c_ioblocktimeout = config_get_ioblocktimeout();
diff --git a/ldap/servers/slapd/fe.h b/ldap/servers/slapd/fe.h
index 9cd122881..f195a7bfc 100644
--- a/ldap/servers/slapd/fe.h
+++ b/ldap/servers/slapd/fe.h
@@ -14,6 +14,10 @@
 #ifndef _SLAPD_FE_H_
 #define _SLAPD_FE_H_
 
+#if defined(HAVE_SYS_EPOLL_H)
+#include <sys/epoll.h>
+#endif
+
 #include <prio.h>
 #include "slap.h"
 
@@ -87,6 +91,12 @@ struct connection_table
     size_t conn_next_offset;
     size_t conn_free_offset;
     struct POLL_STRUCT *fd;
+#ifdef ENABLE_EPOLL
+    int epollfd;
+#else
+    int listen_count;  /* XXX replaced by epoll listen table */
+    int fd_count;      /* XXX really a part of epollfd */
+#endif /* ENABLE_EPOLL */
     int n_tcps; /* standard socket start index in fd */
     int n_tcpe; /* standard socket last ( +1 ) index in fd */
     int s_tcps; /* ssl socket start index in fd */
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 613359859..f4e7dfa12 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1624,6 +1624,19 @@ FrontendConfig_init(void)
         }
     }
 
+#ifdef ENABLE_EPOLL
+    /* XXX maxdescriptors must be smaller that max_user_watches
+     * fs.epoll.max_user_watches.
+     */
+    /* max_watches = (rlim_t)fs_sysctl(XXX INOTIFY_MAX_USER_WATCHES); */
+    /*int64_t max_user_watches = SLAPD_DEFAULT_MAXDESCRIPTORS;
+    if (max_user_watches=sysctl(XXX) == 0) {
+        if ((int64_t)max_user_watches < maxdescriptors) {
+            maxdescriptors = (int64_t)rlp.max_user_watches;
+        }
+    }*/
+#endif /* ENABLE_EPOLL */
+
     /* Take the lock to make sure we barrier correctly. */
     CFG_LOCK_WRITE(cfg);
 
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 8399be247..be0185e9d 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1636,6 +1636,7 @@ typedef struct Conn_private Conn_private;
 typedef enum _conn_state {
     CONN_STATE_FREE = 0,
     CONN_STATE_INIT = 1,
+    CONN_STATE_LISTEN = 2,
 } conn_state;
 
 typedef struct conn
