Commit d17e65a5 authored by Marek Vavrusa's avatar Marek Vavrusa

Reworked networking to share threads between interfaces.

This reduces number of used threads for I/O to constant:
 CPU_COUNT * 3 instead of IF_COUNT * (CPU_COUNT * 3 + 1)
parent 9bc85457
......@@ -54,7 +54,7 @@ static int acl_compare(void *k1, void *k2)
}
/* Compare integers if IPv4. */
if (a1->family == AF_INET) {
if (sockaddr_family(a1) == AF_INET) {
/* Compute mask .*/
uint32_t mask = acl_fill_mask32(a1->prefix);
......@@ -69,7 +69,7 @@ static int acl_compare(void *k1, void *k2)
/* IPv6 matching. */
#ifndef DISABLE_IPV6
if (a1->family == AF_INET6) {
if (sockaddr_family(a1) == AF_INET6) {
/* Get mask .*/
short chunk = a1->prefix;
......@@ -174,7 +174,6 @@ int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val,
}
memcpy(&key->addr, addr, sizeof(sockaddr_t));
sockaddr_update(&key->addr);
key->rule = rule;
key->val = val;
......
......@@ -27,7 +27,6 @@ int sockaddr_init(sockaddr_t *addr, int af)
{
/* Reset pointer. */
memset(addr, 0, sizeof(sockaddr_t));
addr->family = -1;
/* Initialize address size. */
switch(af) {
......@@ -45,44 +44,23 @@ int sockaddr_init(sockaddr_t *addr, int af)
return -1;
}
/* Update pointer. */
addr->family = af;
return sockaddr_update(addr);
return 0;
}
int sockaddr_isvalid(sockaddr_t *addr)
{
return addr && addr->family > -1;
return addr && (addr->len > 0);
}
int sockaddr_copy(sockaddr_t *dst, const sockaddr_t *src)
{
if (memcpy(dst, src, sizeof(sockaddr_t)) != NULL) {
return sockaddr_update(dst);
return 0;
}
return -1;
}
int sockaddr_update(sockaddr_t *addr)
{
/* Update internal pointer. */
switch(addr->len) {
case sizeof(struct sockaddr_in):
addr->ptr = (struct sockaddr*)&addr->addr4;
break;
#ifndef DISABLE_IPV6
case sizeof(struct sockaddr_in6):
addr->ptr = (struct sockaddr*)&addr->addr6;
break;
#endif
default:
return -1;
}
return 0;
}
int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
{
if (!dst || !addr || port < 0) {
......@@ -90,8 +68,6 @@ int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
}
/* Initialize. */
dst->family = -1;
dst->ptr = 0;
dst->len = 0;
sockaddr_init(dst, family);
......@@ -142,11 +118,7 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size)
size_t minlen = INET_ADDRSTRLEN;
/* Check unsupported IPv6. */
#ifdef DISABLE_IPV6
if (addr->family == AF_INET6) {
return -1;
}
#else
#ifndef DISABLE_IPV6
minlen = INET6_ADDRSTRLEN;
#endif
......@@ -160,15 +132,13 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size)
dst[0] = '\0';
#else
/* Load IPv6 addr if default. */
if (addr->family == AF_INET6) {
inet_ntop(addr->family, &addr->addr6.sin6_addr,
dst, size);
if (addr->len == sizeof(struct sockaddr_in6)) {
inet_ntop(AF_INET6, &addr->addr6.sin6_addr, dst, size);
}
#endif
/* Load IPv4 if set. */
if (addr->family == AF_INET) {
inet_ntop(addr->family, &addr->addr4.sin_addr,
dst, size);
if (addr->len == sizeof(struct sockaddr_in)) {
inet_ntop(AF_INET, &addr->addr4.sin_addr, dst, size);
}
return 0;
......@@ -180,16 +150,16 @@ int sockaddr_portnum(const sockaddr_t *addr)
return -1;
}
switch(addr->family) {
switch(addr->len) {
/* IPv4 */
case AF_INET:
case sizeof(struct sockaddr_in):
return ntohs(addr->addr4.sin_port);
break;
/* IPv6 */
#ifndef DISABLE_IPV6
case AF_INET6:
case sizeof(struct sockaddr_in6):
return ntohs(addr->addr6.sin6_port);
break;
#endif
......@@ -200,3 +170,23 @@ int sockaddr_portnum(const sockaddr_t *addr)
break;
}
}
int sockaddr_family(const sockaddr_t *addr)
{
switch(addr->len) {
case sizeof(struct sockaddr_in): return AF_INET; break;
#ifndef DISABLE_IPV6
case sizeof(struct sockaddr_in6): return AF_INET6; break;
#endif
default: return 0; break;
}
}
void sockaddr_prep(sockaddr_t *addr)
{
#ifndef DISABLE_IPV6
addr->len = sizeof(struct sockaddr_in6);
#else
addr->len = sizeof(struct sockaddr_in);
#endif
}
......@@ -37,16 +37,14 @@
/*! \brief Universal socket address. */
typedef struct sockaddr_t {
int family; /*!< Address family. */
short prefix; /*!< Address prefix. */
struct sockaddr* ptr; /*!< Pointer to used sockaddr. */
socklen_t len; /*!< Length of used sockaddr. */
union {
struct sockaddr_in addr4; /*!< IPv4 sockaddr. */
#ifndef DISABLE_IPV6
struct sockaddr_in6 addr6; /*!< IPv6 sockaddr. */
#endif
};
socklen_t len; /*!< Length of used sockaddr. */
short prefix; /*!< Address prefix. */
} sockaddr_t;
/* Subnet maximum prefix length. */
......@@ -83,16 +81,6 @@ int sockaddr_init(sockaddr_t *addr, int af);
*/
int sockaddr_isvalid(sockaddr_t *addr);
/*!
* \brief Update internal pointers according to length.
*
* \param addr Socket address structure.
*
* \retval 0 on success.
* \retval -1 on invalid size.
*/
int sockaddr_update(sockaddr_t *addr);
/*!
* \brief Copy socket address structure.
*
......@@ -152,6 +140,19 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size);
*/
int sockaddr_portnum(const sockaddr_t *addr);
/*!
* \brief Return socket address family.
* \param addr Socket address structure.
* \return address family
*/
int sockaddr_family(const sockaddr_t *addr);
/*!
* \brief Prepare to maximum largest size.
* \return KNOT_EOK
*/
void sockaddr_prep(sockaddr_t *addr);
#endif /* _KNOTD_SOCKADDR_H_ */
/*! @} */
......@@ -53,7 +53,7 @@ typedef unsigned int uint; /*!< \brief Unsigned. */
#define DEFAULT_PORT 53531 /*!< \brief Default interface port. */
#define TCP_BACKLOG_SIZE 5 /*!< \brief TCP listen backlog size. */
#define XFR_THREADS_COUNT 3 /*!< \brief Number of threads for XFR handler. */
#define RECVMMSG_BATCHLEN 32 /*!< \brief Define for recvmmsg() batch size. */
#define RECVMMSG_BATCHLEN 16 /*!< \brief Define for recvmmsg() batch size. */
///*! \brief If defined, zone structures will use hash table for lookup. */
//#define COMPRESSION_PEDANTIC
......
......@@ -177,7 +177,7 @@ static int rrl_classify(char *dst, size_t maxlen, const sockaddr_t *a,
/* Address (in network byteorder, adjust masks). */
uint64_t nb = 0;
if (a->family == AF_INET6) { /* Take the /56 prefix. */
if (sockaddr_family(a) == AF_INET6) { /* Take the /56 prefix. */
nb = *((uint64_t*)&a->addr6.sin6_addr) & RRL_V6_PREFIX;
} else { /* Take the /24 prefix */
nb = (uint32_t)a->addr4.sin_addr.s_addr & RRL_V4_PREFIX;
......@@ -354,7 +354,7 @@ int rrl_setlocks(rrl_table_t *rrl, unsigned granularity)
return KNOT_ERROR;
}
dbg_rrl("%s: set granularity to '%zu'\n", __func__, granularity);
dbg_rrl("%s: set granularity to '%u'\n", __func__, granularity);
return KNOT_EOK;
}
......
This diff is collapsed.
......@@ -48,23 +48,23 @@
/* Forwad declarations. */
struct iface_t;
struct iohandler_t;
struct server_t;
struct conf_t;
typedef struct iostate {
volatile unsigned s;
struct iohandler* h;
} iostate_t;
/*! \brief I/O handler structure.
*/
typedef struct iohandler_t {
struct node *next, *prev;
int fd; /*!< I/O filedescriptor */
int type; /*!< Descriptor type/family. */
unsigned state; /*!< Handler state */
typedef struct iohandler {
struct node n;
dt_unit_t *unit; /*!< Threading unit */
struct iface_t *iface; /*!< Reference to associated interface. */
struct server_t *server; /*!< Reference to server */
void *data; /*!< Persistent data for I/O handler. */
void (*interrupt)(struct iohandler_t *h); /*!< Interrupt handler. */
iostate_t *state;
void (*interrupt)(struct iohandler *h); /*!< Interrupt handler. */
} iohandler_t;
/*! \brief Round-robin mechanism of switching.
......@@ -76,24 +76,33 @@ typedef struct iohandler_t {
*/
typedef enum {
ServerIdle = 0 << 0, /*!< Server is idle. */
ServerRunning = 1 << 0 /*!< Server is running. */
ServerRunning = 1 << 0, /*!< Server is running. */
ServerReload = 1 << 1 /*!< Server reload requested. */
} server_state;
/*!
* \brief Server interface structure.
*/
typedef struct iface_t {
struct node *next, *prev;
int fd[2]; /*!< \brief Socket filedescriptors (UDP, TCP). */
int type[2]; /*!< \brief Socket type. */
struct node n;
int fd[2];
int type;
int port; /*!< \brief Socket port. */
char* addr; /*!< \brief Socket address. */
iohandler_t* handler[2]; /*!< \brief Associated I/O handlers. */
} iface_t;
/* Interface indexes. */
#define UDP_ID 0
#define TCP_ID 1
/* Handler types. */
#define IO_COUNT 2
enum {
IO_UDP = 0,
IO_TCP = 1
};
typedef struct ifacelist {
ref_t ref;
list l;
list u;
} ifacelist_t;
/*!
* \brief Main server structure.
......@@ -108,17 +117,17 @@ typedef struct server_t {
/*! \brief Reference to the name server structure. */
knot_nameserver_t *nameserver;
/*! \brief XFR handler. */
xfrhandler_t *xfr_h;
/*! \brief I/O handlers. */
unsigned tu_size;
xfrhandler_t *xfr;
iohandler_t h[IO_COUNT];
/*! \brief Event scheduler. */
dt_unit_t *iosched;
evsched_t *sched;
/*! \brief I/O handlers list. */
list handlers;
/*! \brief List of interfaces. */
list* ifaces;
ifacelist_t* ifaces;
/*! \brief Rate limiting. */
rrl_table_t *rrl;
......@@ -136,30 +145,27 @@ typedef struct server_t {
server_t *server_create();
/*!
* \brief Create and bind handler to given filedescriptor.
* \brief Create I/O handler.
*
* Pointer to handler instance is used as native unique identifier.
* This requests instance not to be reallocated.
*
* \param server Server structure to be used for operation.
* \param fd I/O filedescriptor.
* \param unit Threading unit to serve given filedescriptor.
* \param h Initialized handler.
* \param s Server structure to be used for operation.
* \param u Threading unit to serve given filedescriptor.
* \param d Handler data.
*
* \retval Handler instance if successful.
* \retval NULL If an error occured.
*/
iohandler_t *server_create_handler(server_t *server, int fd, dt_unit_t *unit);
int server_init_handler(iohandler_t * h, server_t *s, dt_unit_t *u, void *d);
/*!
* \brief Delete handler.
*
* \param server Server structure to be used for operation.
* \param ref I/O handler instance.
* \param ref I/O handler instance.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EINVAL on invalid parameters.
*/
int server_remove_handler(server_t *server, iohandler_t *ref);
int server_free_handler(iohandler_t *h);
/*!
* \brief Starts the server.
......
......@@ -156,12 +156,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
/* Check address type. */
sockaddr_t addr;
if (sockaddr_init(&addr, w->ioh->type) != KNOT_EOK) {
log_server_error("Socket type %d is not supported, "
"IPv6 support is probably disabled.\n",
w->ioh->type);
return KNOT_EINVAL;
}
sockaddr_prep(&addr);
/* Receive data. */
int n = tcp_recv(fd, qbuf, qbuf_maxlen, &addr);
......@@ -457,7 +452,7 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
/* Get peer name. */
if (addr) {
socklen_t alen = addr->len;
if (getpeername(fd, addr->ptr, &alen) < 0) {
if (getpeername(fd, (struct sockaddr *)addr, &alen) < 0) {
return KNOT_EMALF;
}
}
......@@ -479,45 +474,81 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
int tcp_loop_master(dthread_t *thread)
{
iohandler_t *handler = (iohandler_t *)thread->data;
dt_unit_t *unit = thread->unit;
/* Check socket. */
if (!handler || handler->fd < 0 || handler->data == NULL) {
dbg_net("tcp: failed to initialize master thread\n");
if (!thread || !thread->data) {
return KNOT_EINVAL;
}
tcp_worker_t **workers = handler->data;
iostate_t *st = (iostate_t *)thread->data;
iohandler_t *h = st->h;
dt_unit_t *unit = thread->unit;
tcp_worker_t **workers = h->data;
/* Prepare structures for bound sockets. */
fdset_it_t it;
fdset_t *fds = NULL;
iface_t *i = NULL;
ifacelist_t *ifaces = NULL;
/* Accept connections. */
int id = 0;
dbg_net("tcp: created 1 master with %d workers, backend is '%s' \n",
unit->size - 1, fdset_method());
while(1) {
for(;;) {
/* Check handler state. */
if (knot_unlikely(st->s & ServerReload)) {
st->s &= ~ServerReload;
rcu_read_lock();
fdset_destroy(fds);
fds = fdset_new();
ref_release((ref_t *)ifaces);
ifaces = h->server->ifaces;
if (ifaces) {
WALK_LIST(i, ifaces->l) {
fdset_add(fds, i->fd[IO_TCP], OS_EV_READ);
}
}
rcu_read_unlock();
}
/* Check for cancellation. */
if (dt_is_cancelled(thread)) {
break;
}
/* Accept client. */
int client = tcp_accept(handler->fd);
if (client < 0) {
continue;
/* Wait for events. */
int nfds = fdset_wait(fds, OS_EV_FOREVER);
if (nfds <= 0) {
if (nfds == EINTR) continue;
break;
}
/* Add to worker in RR fashion. */
if (write(workers[id]->pipe[1], &client, sizeof(int)) < 0) {
dbg_net("tcp: failed to register fd=%d to worker=%d\n",
client, id);
close(client);
continue;
fdset_begin(fds, &it);
while(nfds > 0) {
/* Accept client. */
int client = tcp_accept(it.fd);
if (client > -1) {
/* Add to worker in RR fashion. */
if (write(workers[id]->pipe[1], &client, sizeof(int)) < 0) {
dbg_net("tcp: failed to register fd=%d to worker=%d\n",
client, id);
close(client);
continue;
}
id = get_next_rr(id, unit->size - 1);
}
if (fdset_next(fds, &it) != 0) {
break;
}
}
id = get_next_rr(id, unit->size - 1);
}
dbg_net("tcp: master thread finished\n");
free(workers);
fdset_destroy(fds);
ref_release((ref_t *)ifaces);
return KNOT_EOK;
}
......@@ -681,7 +712,7 @@ int tcp_loop_unit(iohandler_t *ioh, dt_unit_t *unit)
}
/* Repurpose first thread as master (unit controller). */
dt_repurpose(unit->threads[0], tcp_loop_master, ioh);
dt_repurpose(unit->threads[0], tcp_loop_master, ioh->state + 0);
return KNOT_EOK;
}
This diff is collapsed.
......@@ -260,7 +260,7 @@ static int xfr_process_udp_resp(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
n = tcp_recv(data->session, data->wire, resp_len, &data->addr);
} else {
n = recvfrom(data->session, data->wire, resp_len,
0, data->addr.ptr, &data->addr.len);
0, (struct sockaddr *)&data->addr, &data->addr.len);
}
if (n <= 0) {
......@@ -400,8 +400,6 @@ static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, const knot_ns_xfr_t *req
}
memcpy(t, req, sizeof(knot_ns_xfr_t));
sockaddr_update(&t->addr);
sockaddr_update(&t->saddr);
/* Update request. */
t->wire = 0; /* Invalidate shared buffer. */
......@@ -834,19 +832,22 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* Connect to remote. */
if (data->session <= 0) {
int fd = socket_create(data->addr.family, SOCK_STREAM);
int fd = socket_create(sockaddr_family(&data->addr), SOCK_STREAM);
if (fd >= 0) {
/* Bind to specific address - if set. */
sockaddr_update(&data->saddr);
if (data->saddr.len > 0) {
/* Presume port is already preset. */
ret = bind(fd, data->saddr.ptr, data->saddr.len);
ret = bind(fd,
(struct sockaddr *)&data->saddr,
data->saddr.len);
}
if (ret < 0) {
log_server_warning("%s Failed to create socket.\n",
data->msgpref);
} else {
ret = connect(fd, data->addr.ptr, data->addr.len);
ret = connect(fd,
(struct sockaddr *)&data->addr,
data->addr.len);
if (ret < 0) {
dbg_xfr("%s: couldn't connect to "
"remote host\n", data->msgpref);
......
......@@ -60,7 +60,7 @@ static int zones_send_cb(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
static int zones_send_udp(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
{
return sendto(fd, msg, msglen, 0, addr->ptr, addr->len);
return sendto(fd, msg, msglen, 0, (struct sockaddr *)addr, addr->len);
}
/*----------------------------------------------------------------------------*/
......@@ -461,7 +461,7 @@ static int zones_refresh_ev(event_t *e)
/* Mark as finished to prevent stalling. */
evsched_event_finished(e->parent);
int ret = xfr_request(zd->server->xfr_h, &xfr_req);
int ret = xfr_request(zd->server->xfr, &xfr_req);
dbg_zones("zones: issued request, ret = %d\n", ret);
if (ret != KNOT_EOK) {
knot_zone_release(xfr_req.zone); /* Discard */
......@@ -535,12 +535,12 @@ static int zones_refresh_ev(event_t *e)
if (ret == KNOT_EOK) {
/* Create socket on random port. */
sock = socket_create(master->family, SOCK_DGRAM);
sock = socket_create(sockaddr_family(master), SOCK_DGRAM);
/* Check requested source. */
sockaddr_t *via = &zd->xfr_in.via;
if (via->len > 0) {
if (bind(sock, via->ptr, via->len) < 0) {
if (bind(sock, (struct sockaddr *)via, via->len) < 0) {
socket_close(sock);
sock = -1;
char r_addr[SOCKADDR_STRLEN];
......@@ -554,7 +554,7 @@ static int zones_refresh_ev(event_t *e)
ret = KNOT_ERROR;
if (sock > -1) {
int sent = sendto(sock, qbuf, buflen, 0,
master->ptr, master->len);
(struct sockaddr *)master, master->len);
/* Store ID of the awaited response. */
if (sent == buflen) {
......@@ -591,13 +591,11 @@ static int zones_refresh_ev(event_t *e)
req.wire = NULL;
memcpy(&req.addr, master, sizeof(sockaddr_t));
memcpy(&req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
sockaddr_update(&req.addr);
sockaddr_update(&req.saddr);
/* Retain pointer to zone and issue. */
knot_zone_retain(req.zone);
if (ret == KNOT_EOK) {
ret = xfr_request(zd->server->xfr_h, &req);
ret = xfr_request(zd->server->xfr, &req);
}
if (ret != KNOT_EOK) {
free(req.digest);
......@@ -687,11 +685,13 @@ static int zones_notify_send(event_t *e)
if (ret == KNOT_EOK && zd->server) {
/* Create socket on random port. */
int sock = socket_create(ev->addr.family, SOCK_DGRAM);
int sock = socket_create(sockaddr_family(&ev->addr), SOCK_DGRAM);
/* Check requested source. */
if (ev->saddr.len > 0) {
if (bind(sock, ev->saddr.ptr, ev->saddr.len) < 0) {
if (bind(sock,
(struct sockaddr *)&ev->saddr,
ev->saddr.len) < 0) {
socket_close(sock);
sock = -1;
}
......@@ -701,7 +701,8 @@ static int zones_notify_send(event_t *e)
ret = -1;
if (sock > -1) {
ret = sendto(sock, qbuf, buflen, 0,
ev->addr.ptr, ev->addr.len);
(struct sockaddr *)&ev->addr,
ev->addr.len);
}
/* Store ID of the awaited response. */
......@@ -725,7 +726,7 @@ static int zones_notify_send(event_t *e)
/* Retain pointer to zone and issue request. */
knot_zone_retain(req.zone);
ret = xfr_request(zd->server->xfr_h, &req);
ret = xfr_request(zd->server->xfr, &req);
if (ret != KNOT_EOK) {
knot_zone_release(req.zone); /* Discard */
}
......@@ -1863,13 +1864,13 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype,
if (ttype == NS_TRANSPORT_TCP) {
stype = SOCK_STREAM;
}
int nfd = socket_create(master->family, stype);
int nfd = socket_create(sockaddr_family(master), stype);
/* Check requested source. */
char strbuf[256] = "Generic error.";
sockaddr_t *via = &zd->xfr_in.via;
if (via->len > 0) {
if (bind(nfd, via->ptr, via->len) < 0) {
if (bind(nfd, (struct sockaddr *)via, via->len) < 0) {
socket_close(nfd);
nfd = -1;
char r_addr[SOCKADDR_STRLEN];
......@@ -1904,7 +1905,9 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype,
if (nfd > -1) {
/* Connect on TCP. */
if (ttype == NS_TRANSPORT_TCP) {
if (connect(nfd, master->ptr, master->len) < 0) {
if (connect(nfd,
(struct sockaddr *)master,
master->len) < 0) {
ret = KNOT_ECONNREFUSED;
}
}
......@@ -1937,13 +1940,11 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype,
req.packet_nr = orig_id;
memcpy(&req.addr, master, sizeof(sockaddr_t));
memcpy(&req.saddr, from, sizeof(sockaddr_t));
sockaddr_update(&req.addr);
sockaddr_update(&req.saddr);
/* Retain pointer to zone and issue. */
knot_zone_retain(req.zone);
if (ret == KNOT_EOK) {
ret = xfr_request(zd->server->xfr_h, &req);
ret = xfr_request(zd->server->xfr, &req);
}
if (ret != KNOT_EOK) {
knot_zone_release(req.zone); /* Discard */
......@@ -2962,7 +2963,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
/* Retain pointer to zone for processing. */
knot_zone_retain(xfr_req.zone);
ret = xfr_request(((server_t *)knot_ns_get_data(
nameserver))->xfr_h, &xfr_req);
nameserver))->xfr, &xfr_req);
if (ret != KNOT_EOK) {
knot_zone_release(xfr_req.zone); /* Discard */
}
......
......@@ -84,7 +84,8 @@ void* thr_action(void *arg)
/* Write pattern. */
char pattern = WRITE_PATTERN;
/* If removes compile warning. */
if (write(*fd, &pattern, WRITE_PATTERN_LEN));
if (write(*fd, &pattern, WRITE_PATTERN_LEN))
;
return NULL;
}
......
......@@ -56,7 +56,6 @@ static void* rrl_runnable(void *arg)
struct runnable_data* d = (struct runnable_data*)arg;
sockaddr_t addr;
memcpy(&addr, d->addr, sizeof(sockaddr_t));
sockaddr_update(&addr);
int lock = -1;
uint32_t now = time(NULL);
struct bucketmap_t *m = malloc(RRL_INSERTS * sizeof(struct bucketmap_t));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment