Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/TODO b/TODO
index bb6a02a4..a5c2a41d 100644
--- a/TODO
+++ b/TODO
@@ -1,121 +1,121 @@
0.1
---
link layer:
* add priority/weight to link config struct
host layer:
* add seq num and ring buffer for pckt tracking to struct
knet_frame:
* remove padding to add nodeid (1 char) and linkid (3 bit), flags (1 bit compress, 1 bit encrypted, 3 pad)
ring:
* change from many mallocs to single (per host) malloc in handler_new and map it.
* support 8 listener per node.
* add api to knet_handle_new to define src/dst mapping in data frame.
* index pointer list
libtap:
* remove log_* calls
* add man pages
* improve tests to cover thread safety and more error codes
general:
* logging and what to log
log to file: who logins, config changes and link status changes
log to vty: cmd execution failure
* consider splitting tests/* based on what they test (tap_test -> libtap/) ?
api:
-* knet_{domain}_ are public api's
-* knet_{domain}_ structs are public
-* {domain}_ are private API's
+* {domain}_ are public api's
+* {domain}_ structs are public
+* _{function} are private functions
vty:
* split cmd_files
* basic show info
* fix check_param for ip/prefix
0.2
---
* packet inspector
0.3
---
link layer:
* add active/active to link config struct
* change link->enabled to something more meaningfull (ping enable/admin enable)
host layer:
* add seq num and ring buffer for pckt tracking to struct
* benchmark tests:
- all critical paths in ring.c
0.4
---
general:
* add statistics
* add init script / spec file
* /etc/kronosnet/(ca-ssl/)
* v4/v6 (bindv6only check via cli)
vty:
* add optional options
* sorting
* tab completion on options
0.5
---
* pong count
* switch engine
0.6
---
* dynip
0.7
---
* review ring api for libknetring shared lib
* review tap api for libknettap shared lib
* review vty api for libknetvty shared lib
0.9
---
* crypto
* compression
1.0-pre
-------
tests:
* coverity
* unit test:
- test all public APIs
- write ad-doc tests for internal complex functions
- not required to test return codes from external libs directly
(we are not testing glibc)
- test all code paths we write
- no 0.9/1.0 release without max testing coverage for the core
diff --git a/cfg.h b/cfg.h
index 59f1a1ac..8343b05a 100644
--- a/cfg.h
+++ b/cfg.h
@@ -1,40 +1,40 @@
#ifndef __CFG_H__
#define __CFG_H__
#include <stdint.h>
#include <net/if.h>
#include "libtap.h"
-#include "ring.h"
+#include "libknet.h"
struct knet_cfg_eth {
knet_tap_t knet_tap;
uint8_t node_id;
};
struct knet_cfg_ring {
knet_handle_t knet_h;
int base_port;
};
struct knet_cfg {
struct knet_cfg_eth cfg_eth;
struct knet_cfg_ring cfg_ring;
int active;
struct knet_cfg *next;
};
struct knet_cfg_top {
char *conffile;
char *vty_ip;
char *vty_port;
struct knet_cfg *knet_cfg;
};
struct knet_cfg *knet_get_iface(const char *name, const int create);
void knet_destroy_iface(struct knet_cfg *knet_iface);
extern struct knet_cfg_top knet_cfg_head;
#endif
diff --git a/libknet/Makefile.am b/libknet/Makefile.am
index 5e10e205..e1a21f1e 100644
--- a/libknet/Makefile.am
+++ b/libknet/Makefile.am
@@ -1,16 +1,15 @@
MAINTAINERCLEANFILES = Makefile.in
LIBS = -lpthread \
-version-info $(libversion)
sources = ring.c
libversion = 0:0:0
-include_HEADERS = ring.h
-
-noinst_HEADERS = knethandle.h
+include_HEADERS = libknet.h
+noinst_HEADERS = libknet-private.h
lib_LTLIBRARIES = libknet.la
libknet_la_SOURCES = $(sources)
diff --git a/libknet/knethandle.h b/libknet/libknet-private.h
similarity index 96%
rename from libknet/knethandle.h
rename to libknet/libknet-private.h
index 82de16b1..5b49c936 100644
--- a/libknet/knethandle.h
+++ b/libknet/libknet-private.h
@@ -1,25 +1,25 @@
#ifndef __KNETHANDLE_H__
#define __KNETHANDLE_H__
/* NOTE: you shouldn't need to include this header normally, it is provided for
* testing purpose only.
*/
-#include "ring.h"
+#include "libknet.h"
struct knet_handle {
int sockfd;
int epollfd;
uint16_t node_id;
unsigned int enabled:1;
struct knet_host *host_head;
struct knet_host *host_index[KNET_MAX_HOST];
struct knet_listener *listener_head;
struct knet_frame *databuf;
struct knet_frame *pingbuf;
pthread_t control_thread;
pthread_t heartbt_thread;
pthread_rwlock_t list_rwlock;
};
#endif
diff --git a/libknet/ring.h b/libknet/libknet.h
similarity index 100%
rename from libknet/ring.h
rename to libknet/libknet.h
diff --git a/libknet/ring.c b/libknet/ring.c
index 39a88e89..114a0f9e 100644
--- a/libknet/ring.c
+++ b/libknet/ring.c
@@ -1,617 +1,617 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
-#include "knethandle.h"
+#include "libknet-private.h"
#include "netutils.h"
#include "utils.h"
#define KNET_MAX_EVENTS 8
#define KNET_PING_TIMERES 200000
#define KNET_DATABUFSIZE 131072 /* 128k */
#define KNET_PINGBUFSIZE sizeof(struct knet_frame)
static void *knet_control_thread(void *data);
static void *knet_heartbt_thread(void *data);
knet_handle_t knet_handle_new(int fd, uint16_t node_id)
{
knet_handle_t knet_h;
struct epoll_event ev;
if ((knet_h = malloc(sizeof(struct knet_handle))) == NULL)
return NULL;
memset(knet_h, 0, sizeof(struct knet_handle));
if ((knet_h->databuf = malloc(KNET_DATABUFSIZE))== NULL)
goto exit_fail1;
memset(knet_h->databuf, 0, KNET_DATABUFSIZE);
if ((knet_h->pingbuf = malloc(KNET_PINGBUFSIZE))== NULL)
goto exit_fail2;
memset(knet_h->pingbuf, 0, KNET_PINGBUFSIZE);
if (pthread_rwlock_init(&knet_h->list_rwlock, NULL) != 0)
goto exit_fail3;
knet_h->sockfd = fd;
knet_h->epollfd = epoll_create(KNET_MAX_EVENTS);
knet_h->node_id = node_id;
if (knet_h->epollfd < 0)
goto exit_fail4;
if (knet_fdset_cloexec(knet_h->epollfd) != 0)
goto exit_fail5;
memset(&ev, 0, sizeof(struct epoll_event));
ev.events = EPOLLIN;
ev.data.fd = knet_h->sockfd;
if (epoll_ctl(knet_h->epollfd,
EPOLL_CTL_ADD, knet_h->sockfd, &ev) != 0)
goto exit_fail5;
if (pthread_create(&knet_h->control_thread, 0,
knet_control_thread, (void *) knet_h) != 0)
goto exit_fail5;
if (pthread_create(&knet_h->heartbt_thread, 0,
knet_heartbt_thread, (void *) knet_h) != 0)
goto exit_fail6;
return knet_h;
exit_fail6:
pthread_cancel(knet_h->control_thread);
exit_fail5:
close(knet_h->epollfd);
exit_fail4:
pthread_rwlock_destroy(&knet_h->list_rwlock);
exit_fail3:
free(knet_h->databuf);
exit_fail2:
free(knet_h->pingbuf);
exit_fail1:
free(knet_h);
return NULL;
}
int knet_handle_free(knet_handle_t knet_h)
{
void *retval;
if ((knet_h->host_head != NULL) || (knet_h->listener_head != NULL))
goto exit_busy;
pthread_cancel(knet_h->heartbt_thread);
pthread_join(knet_h->heartbt_thread, &retval);
if (retval != PTHREAD_CANCELED)
goto exit_busy;
pthread_cancel(knet_h->control_thread);
pthread_join(knet_h->control_thread, &retval);
if (retval != PTHREAD_CANCELED)
goto exit_busy;
close(knet_h->epollfd);
pthread_rwlock_destroy(&knet_h->list_rwlock);
free(knet_h->databuf);
free(knet_h->pingbuf);
free(knet_h);
return 0;
exit_busy:
errno = EBUSY;
return -EBUSY;
}
void knet_handle_setfwd(knet_handle_t knet_h, int enabled)
{
knet_h->enabled = (enabled == 1) ? 1 : 0;
}
int knet_host_get(knet_handle_t knet_h, uint16_t node_id, struct knet_host **host)
{
int ret;
if ((ret = pthread_rwlock_rdlock(&knet_h->list_rwlock)) != 0)
return ret;
*host = knet_h->host_index[node_id];
if (*host == NULL) {
pthread_rwlock_unlock(&knet_h->list_rwlock);
errno = ENOENT;
return ENOENT;
}
return 0;
}
int knet_host_acquire(knet_handle_t knet_h, struct knet_host **host)
{
int ret;
if ((ret = pthread_rwlock_rdlock(&knet_h->list_rwlock)) != 0)
return ret;
*host = knet_h->host_head;
return 0;
}
int knet_host_release(knet_handle_t knet_h, struct knet_host **host)
{
int ret;
*host = NULL;
if ((ret = pthread_rwlock_unlock(&knet_h->list_rwlock)) != 0)
return ret;
return 0;
}
int knet_host_foreach(knet_handle_t knet_h, knet_link_fn_t linkfun, struct knet_host_search *data)
{
int lockstatus;
struct knet_host *host;
lockstatus = pthread_rwlock_rdlock(&knet_h->list_rwlock);
if ((lockstatus != 0) && (lockstatus != EDEADLK))
return lockstatus;
for (host = knet_h->host_head; host != NULL; host = host->next) {
if ((linkfun(knet_h, host, data)) != KNET_HOST_FOREACH_NEXT)
break;
}
if (lockstatus == 0)
pthread_rwlock_unlock(&knet_h->list_rwlock);
return 0;
}
int knet_listener_acquire(knet_handle_t knet_h, struct knet_listener **head, int writelock)
{
int ret;
if (writelock != 0)
ret = pthread_rwlock_wrlock(&knet_h->list_rwlock);
else
ret = pthread_rwlock_rdlock(&knet_h->list_rwlock);
if (head)
*head = (ret == 0) ? knet_h->listener_head : NULL;
return ret;
}
int knet_listener_release(knet_handle_t knet_h)
{
return pthread_rwlock_unlock(&knet_h->list_rwlock);
}
int knet_host_add(knet_handle_t knet_h, uint16_t node_id)
{
int i, ret = 0; /* success */
struct knet_host *host;
if ((ret = pthread_rwlock_wrlock(&knet_h->list_rwlock)) != 0)
goto exit_clean;
if (knet_h->host_index[node_id] != NULL) {
errno = ret = EEXIST;
goto exit_unlock;
}
if ((host = malloc(sizeof(struct knet_host))) == NULL)
goto exit_unlock;
memset(host, 0, sizeof(struct knet_host));
host->node_id = node_id;
for (i = 0; i < KNET_MAX_LINK; i++)
host->link[i].link_id = i;
/* adding new host to the index */
knet_h->host_index[node_id] = host;
/* TODO: keep hosts ordered */
/* pushing new host to the front */
host->next = knet_h->host_head;
knet_h->host_head = host;
exit_unlock:
pthread_rwlock_unlock(&knet_h->list_rwlock);
exit_clean:
return ret;
}
int knet_host_remove(knet_handle_t knet_h, uint16_t node_id)
{
int ret = 0; /* success */
struct knet_host *i, *removed;
if ((ret = pthread_rwlock_wrlock(&knet_h->list_rwlock)) != 0)
goto exit_clean;
if (knet_h->host_index[node_id] == NULL) {
errno = ret = EINVAL;
goto exit_unlock;
}
removed = NULL;
/* removing host from list */
if (knet_h->host_head->node_id == node_id) {
removed = knet_h->host_head;
knet_h->host_head = removed->next;
} else {
for (i = knet_h->host_head; i->next != NULL; i = i->next) {
if (i->next->node_id == node_id) {
removed = i->next;
i->next = removed->next;
break;
}
}
}
if (removed != NULL) {
knet_h->host_index[node_id] = NULL;
free(removed);
}
exit_unlock:
pthread_rwlock_unlock(&knet_h->list_rwlock);
exit_clean:
return ret;
}
int knet_listener_add(knet_handle_t knet_h, struct knet_listener *listener)
{
int value;
struct epoll_event ev;
listener->sock = socket(listener->address.ss_family, SOCK_DGRAM, 0);
if (listener->sock < 0)
return listener->sock;
value = KNET_RING_RCVBUFF;
setsockopt(listener->sock, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value));
if (knet_fdset_cloexec(listener->sock) != 0)
goto exit_fail1;
if (bind(listener->sock, (struct sockaddr *) &listener->address,
sizeof(struct sockaddr_storage)) != 0)
goto exit_fail1;
memset(&ev, 0, sizeof(struct epoll_event));
ev.events = EPOLLIN;
ev.data.fd = listener->sock;
if (epoll_ctl(knet_h->epollfd, EPOLL_CTL_ADD, listener->sock, &ev) != 0)
goto exit_fail1;
if (pthread_rwlock_wrlock(&knet_h->list_rwlock) != 0)
goto exit_fail2;
/* pushing new host to the front */
listener->next = knet_h->listener_head;
knet_h->listener_head = listener;
pthread_rwlock_unlock(&knet_h->list_rwlock);
return 0;
exit_fail2:
epoll_ctl(knet_h->epollfd, EPOLL_CTL_DEL, listener->sock, &ev);
exit_fail1:
close(listener->sock);
return -1;
}
int knet_listener_remove(knet_handle_t knet_h, struct knet_listener *listener)
{
int i, ret;
struct epoll_event ev; /* kernel < 2.6.9 bug (see epoll_ctl man) */
struct knet_host *host;
struct knet_listener *l;
if (pthread_rwlock_wrlock(&knet_h->list_rwlock) != 0)
return -EINVAL;
ret = 0;
/* checking if listener is in use */
for (host = knet_h->host_head; host != NULL; host = host->next) {
for (i = 0; i < KNET_MAX_LINK; i++) {
if (host->link[i].ready != 1) continue;
if (host->link[i].sock == listener->sock) {
ret = -EBUSY;
goto exit_fail1;
}
}
}
/* TODO: use a doubly-linked list? */
if (listener == knet_h->listener_head) {
knet_h->listener_head = knet_h->listener_head->next;
} else {
for (l = knet_h->listener_head; l != NULL; l = l->next) {
if (listener == l->next) {
l->next = l->next->next;
break;
}
}
}
epoll_ctl(knet_h->epollfd, EPOLL_CTL_DEL, listener->sock, &ev);
close(listener->sock);
exit_fail1:
pthread_rwlock_unlock(&knet_h->list_rwlock);
if (ret < 0) errno = -ret;
return ret;
}
void knet_link_timeout(struct knet_link *lnk,
time_t interval, time_t timeout, int precision)
{
lnk->ping_interval = interval * 1000; /* microseconds */
lnk->pong_timeout = timeout * 1000; /* microseconds */
lnk->latency_fix = precision;
lnk->latency_exp = precision - \
((lnk->ping_interval * precision) / 8000000);
}
static void knet_send_data(knet_handle_t knet_h)
{
int j;
ssize_t len, snt;
struct knet_host *i;
len = read(knet_h->sockfd, knet_h->databuf->kf_data,
KNET_DATABUFSIZE - KNET_FRAME_SIZE);
if (len == 0) {
/* TODO: disconnection, should never happen! */
return;
}
len += KNET_FRAME_SIZE;
if (knet_h->enabled != 1) /* data forward is disabled */
return;
/* TODO: packet inspection */
knet_h->databuf->kf_type = KNET_FRAME_DATA;
if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0)
return;
for (i = knet_h->host_head; i != NULL; i = i->next) {
for (j = 0; j < KNET_MAX_LINK; j++) {
if (i->link[j].enabled != 1) /* link is disabled */
continue;
snt = sendto(i->link[j].sock,
knet_h->databuf, len, MSG_DONTWAIT,
(struct sockaddr *) &i->link[j].address,
sizeof(struct sockaddr_storage));
if ((i->active == 0) && (snt == len))
break;
}
}
pthread_rwlock_unlock(&knet_h->list_rwlock);
}
static void knet_recv_frame(knet_handle_t knet_h, int sockfd)
{
ssize_t len;
struct sockaddr_storage address;
socklen_t addrlen;
struct knet_host *src_host;
struct knet_link *src_link;
unsigned long long latency_last;
if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0)
return;
addrlen = sizeof(struct sockaddr_storage);
len = recvfrom(sockfd, knet_h->databuf, KNET_DATABUFSIZE,
MSG_DONTWAIT, (struct sockaddr *) &address, &addrlen);
if (len < (KNET_FRAME_SIZE + 1))
goto exit_unlock;
if (ntohl(knet_h->databuf->kf_magic) != KNET_FRAME_MAGIC)
goto exit_unlock;
if (knet_h->databuf->kf_version != KNET_FRAME_VERSION)
goto exit_unlock;
src_host = NULL;
src_link = NULL;
if ((knet_h->databuf->kf_type & KNET_FRAME_PMSK) != 0) {
knet_h->databuf->kf_node = ntohs(knet_h->databuf->kf_node);
src_host = knet_h->host_index[knet_h->databuf->kf_node];
if (src_host == NULL) /* host not found */
goto exit_unlock;
src_link = src_host->link +
(knet_h->databuf->kf_link % KNET_MAX_LINK);
}
switch (knet_h->databuf->kf_type) {
case KNET_FRAME_DATA:
if (knet_h->enabled != 1) /* data forward is disabled */
break;
write(knet_h->sockfd,
knet_h->databuf->kf_data, len - KNET_FRAME_SIZE);
break;
case KNET_FRAME_PING:
knet_h->databuf->kf_type = KNET_FRAME_PONG;
knet_h->databuf->kf_node = htons(knet_h->node_id);
sendto(src_link->sock, knet_h->databuf, len, MSG_DONTWAIT,
(struct sockaddr *) &src_link->address,
sizeof(struct sockaddr_storage));
break;
case KNET_FRAME_PONG:
clock_gettime(CLOCK_MONOTONIC, &src_link->pong_last);
timespec_diff(knet_h->databuf->kf_time,
src_link->pong_last, &latency_last);
src_link->latency =
((src_link->latency * src_link->latency_exp) +
((latency_last / 1000llu) *
(src_link->latency_fix - src_link->latency_exp))) /
src_link->latency_fix;
if (src_link->latency < src_link->pong_timeout)
src_link->enabled = 1;
break;
default:
goto exit_unlock;
}
exit_unlock:
pthread_rwlock_unlock(&knet_h->list_rwlock);
}
static void heartbeat_check_each(knet_handle_t knet_h, struct knet_link *dst_link)
{
int len;
struct timespec clock_now, pong_last;
unsigned long long diff_ping;
/* caching last pong to avoid race conditions */
pong_last = dst_link->pong_last;
if (clock_gettime(CLOCK_MONOTONIC, &clock_now) != 0)
return;
timespec_diff(dst_link->ping_last, clock_now, &diff_ping);
if (diff_ping >= (dst_link->ping_interval * 1000llu)) {
knet_h->pingbuf->kf_time = clock_now;
knet_h->pingbuf->kf_link = dst_link->link_id;
len = sendto(dst_link->sock, knet_h->pingbuf, KNET_PINGBUFSIZE,
MSG_DONTWAIT, (struct sockaddr *) &dst_link->address,
sizeof(struct sockaddr_storage));
if (len == KNET_PINGBUFSIZE)
dst_link->ping_last = clock_now;
}
if (dst_link->enabled == 1) {
timespec_diff(pong_last, clock_now, &diff_ping);
if (diff_ping >= (dst_link->pong_timeout * 1000llu))
dst_link->enabled = 0; /* TODO: might need write lock */
}
}
static void *knet_heartbt_thread(void *data)
{
int j;
knet_handle_t knet_h;
struct knet_host *i;
knet_h = (knet_handle_t) data;
/* preparing ping buffer */
knet_h->pingbuf->kf_magic = htonl(KNET_FRAME_MAGIC);
knet_h->pingbuf->kf_version = KNET_FRAME_VERSION;
knet_h->pingbuf->kf_type = KNET_FRAME_PING;
knet_h->pingbuf->kf_node = htons(knet_h->node_id);
while (1) {
usleep(KNET_PING_TIMERES);
if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0)
continue;
for (i = knet_h->host_head; i != NULL; i = i->next) {
for (j = 0; j < KNET_MAX_LINK; j++) {
if (i->link[j].ready != 1) continue;
heartbeat_check_each(knet_h, &i->link[j]);
}
}
pthread_rwlock_unlock(&knet_h->list_rwlock);
}
return NULL;
}
static void *knet_control_thread(void *data)
{
int i, nev;
knet_handle_t knet_h;
struct epoll_event events[KNET_MAX_EVENTS];
knet_h = (knet_handle_t) data;
/* preparing data buffer */
knet_h->databuf->kf_magic = htonl(KNET_FRAME_MAGIC);
knet_h->databuf->kf_version = KNET_FRAME_VERSION;
while (1) {
nev = epoll_wait(knet_h->epollfd, events, KNET_MAX_EVENTS, -1);
for (i = 0; i < nev; i++) {
if (events[i].data.fd == knet_h->sockfd) {
knet_send_data(knet_h);
} else {
knet_recv_frame(knet_h, events[i].data.fd);
}
}
}
return NULL;
}
diff --git a/tests/khandle_test.c b/tests/khandle_test.c
index e56a66aa..9323803e 100644
--- a/tests/khandle_test.c
+++ b/tests/khandle_test.c
@@ -1,56 +1,56 @@
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
-#include "ring.h"
+#include "libknet.h"
#include "utils.h"
#define HOST_LIST_SIZE 8192
#define HOST_LIST_LOOP 64
static int host_loop(knet_handle_t knet_h, struct knet_host *host, struct knet_host_search *search)
{
host->active = 1;
search->param1++;
return KNET_HOST_FOREACH_NEXT;
}
int main(int argc, char *argv[])
{
int sock, i, j;
knet_handle_t knet_h;
struct knet_host_search search;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_error("Unable to create new socket");
exit(EXIT_FAILURE);
}
knet_h = knet_handle_new(sock, 1);
for (i = 0; i < HOST_LIST_SIZE; i++)
knet_host_add(knet_h, i);
search.param1 = 0;
for (i = 0; i < HOST_LIST_SIZE; i++) {
for (j = 0; j < HOST_LIST_LOOP; j++) {
knet_host_foreach(knet_h, host_loop, &search);
}
knet_host_remove(knet_h, i);
}
printf("Loop count: %u times\n", (unsigned int) search.param1);
if (knet_handle_free(knet_h) != 0) {
log_error("Unable to free knet_handle");
exit(EXIT_FAILURE);
}
return 0;
}
diff --git a/tests/listener_test.c b/tests/listener_test.c
index 7b00e028..394de773 100644
--- a/tests/listener_test.c
+++ b/tests/listener_test.c
@@ -1,132 +1,132 @@
#include "config.h"
#include <stdlib.h>
#include <sys/epoll.h>
-#include "knethandle.h"
+#include "libknet-private.h"
#include "utils.h"
#define KNET_TEST_PORT 50000
static knet_handle_t knet_h;
struct knet_listener *listener;
static void test_add_listener(void)
{
struct sockaddr_in *address;
listener = malloc(sizeof(struct knet_listener));
if (listener == NULL) {
log_error("Unable to create listener");
exit(EXIT_FAILURE);
}
memset(listener, 0, sizeof(struct knet_listener));
address = (struct sockaddr_in *) &listener->address;
address->sin_family = AF_INET;
address->sin_port = htons(KNET_TEST_PORT);
address->sin_addr.s_addr = INADDR_ANY;
if (knet_listener_add(knet_h, listener) != 0) {
log_error("Unable to add listener");
exit(EXIT_FAILURE);
}
}
static void test_add_host(void)
{
struct knet_host *host;
if (knet_host_add(knet_h, 1) != 0) {
log_error("Unable to add host to knet_handle");
exit(EXIT_FAILURE);
}
knet_host_get(knet_h, 1, &host);
host->link[0].sock = listener->sock;
host->link[0].ready = 1;
knet_host_release(knet_h, &host);
}
int main(int argc, char *argv[])
{
int err, sock;
struct epoll_event ev;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
log_error("Unable to create new socket");
exit(EXIT_FAILURE);
}
if ((knet_h = knet_handle_new(sock, 1)) == NULL) {
log_error("Unable to create new knet_handle_t");
exit(EXIT_FAILURE);
}
log_info("Adding listener to handle");
test_add_listener();
memset(&ev, 0, sizeof(struct epoll_event));
/* don't try this at home :) */
err = epoll_ctl(knet_h->epollfd, EPOLL_CTL_ADD, listener->sock, &ev);
if (err != -1) {
log_error("Listener file descriptor not found in epollfd");
exit(EXIT_FAILURE);
}
log_error("Listener file descriptor was added to epollfd");
log_info("Adding host to handle");
test_add_host();
err = knet_listener_remove(knet_h, listener);
if (err != -EBUSY) {
log_error("Listener socket should be in use");
exit(EXIT_FAILURE);
}
log_error("Unable to remove listener with active links");
log_info("Removing host from handle");
err = knet_host_remove(knet_h, 1);
if (err != 0) {
log_error("Unable to remove host from knet_handle");
exit(EXIT_FAILURE);
}
log_info("Removing listener");
err = knet_listener_remove(knet_h, listener);
if (err != 0) {
log_error("Unable to remove listener from knet_handle");
exit(EXIT_FAILURE);
}
/* don't try this at home :) */
err = epoll_ctl(knet_h->epollfd, EPOLL_CTL_DEL, listener->sock, &ev);
if (err != -1) {
log_error("Listener file was present in epollfd");
exit(EXIT_FAILURE);
}
log_error("Listener file descriptor was removed from epollfd");
if (knet_handle_free(knet_h) != 0) {
log_error("Unable to free knet_handle");
exit(EXIT_FAILURE);
}
return 0;
}
diff --git a/tests/lookup_bench.c b/tests/lookup_bench.c
index 647de9be..879624f7 100644
--- a/tests/lookup_bench.c
+++ b/tests/lookup_bench.c
@@ -1,54 +1,54 @@
#include "config.h"
#include <stdlib.h>
#include <time.h>
-#include "ring.h"
+#include "libknet.h"
#include "netutils.h"
#include "utils.h"
#define KNET_PORT 50000
#define KNET_BENCH_LOOPNUM 100000000
int main(int argc, char *argv[])
{
struct knet_link *head;
struct sockaddr_in address;
struct timespec bench_start, bench_end;
unsigned long long i, bench_diff;
head = malloc(sizeof(struct knet_link));
if (head == NULL) {
log_error("Unable to create knet_link");
exit(EXIT_FAILURE);
}
memset(head, 0, sizeof(struct knet_link));
address.sin_family = AF_INET;
address.sin_port = htons(KNET_PORT);
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
memmove(&head->address, &address, sizeof(address));
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &bench_start);
for (i = 0; i < KNET_BENCH_LOOPNUM; i++) {
cmpaddr((struct sockaddr_storage *) &address, sizeof(address),
(struct sockaddr_storage *) &head->address,
sizeof(head->address));
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &bench_end);
printf("start sec: %3lu, nsec: %9lu\n end sec: %3lu, nsec: %9lu\n",
bench_start.tv_sec, bench_start.tv_nsec,
bench_end.tv_sec, bench_end.tv_nsec);
timespec_diff(bench_start, bench_end, &bench_diff);
printf("end - start = %llums\n", bench_diff);
return 0;
}
diff --git a/tests/ping_test.c b/tests/ping_test.c
index d3b68fae..eb3992be 100644
--- a/tests/ping_test.c
+++ b/tests/ping_test.c
@@ -1,211 +1,211 @@
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <alloca.h>
#include <signal.h>
#include <arpa/inet.h>
-#include "ring.h"
+#include "libknet.h"
#include "utils.h"
static int knet_sock[2];
static knet_handle_t knet_h;
static in_port_t tok_inport(char *str)
{
int value = atoi(str);
if ((value < 0) || (value > UINT16_MAX))
return 0;
return (in_port_t) value;
}
static int tok_inaddrport(char *str, struct sockaddr_in *addr)
{
char *strhost, *strport, *tmp = NULL;
strhost = strtok_r(str, ":", &tmp);
strport = strtok_r(NULL, ":", &tmp);
if (strport == NULL)
addr->sin_port = htons(KNET_RING_DEFPORT);
else
addr->sin_port = htons(tok_inport(strport));
return inet_aton(strhost, &addr->sin_addr);
}
static void print_usage(char *name)
{
printf("usage: %s <localip>[:<port>] <remoteip>[:port] [...]\n", name);
printf("example: %s 0.0.0.0 192.168.0.2\n", name);
}
static void argv_to_hosts(int argc, char *argv[])
{
int err, i;
struct sockaddr_in *address;
struct knet_host *host;
struct knet_listener *listener;
listener = malloc(sizeof(struct knet_listener));
if (listener == NULL) {
log_error("Unable to create listener");
exit(EXIT_FAILURE);
}
memset(listener, 0, sizeof(struct knet_listener));
address = (struct sockaddr_in *) &listener->address;
address->sin_family = AF_INET;
err = tok_inaddrport(argv[1], address);
if (err < 0) {
log_error("Unable to convert ip address: %s", argv[1]);
exit(EXIT_FAILURE);
}
err = knet_listener_add(knet_h, listener);
if (err != 0) {
log_error("Unable to start knet listener");
exit(EXIT_FAILURE);
}
for (i = 2; i < argc; i++) {
if (knet_host_add(knet_h, i - 1) != 0) {
log_error("Unable to add new knet_host");
exit(EXIT_FAILURE);
}
knet_host_get(knet_h, i - 1, &host);
host->link[0].sock = listener->sock;
host->link[0].address.ss_family = AF_INET;
knet_link_timeout(&host->link[0], 1000, 5000, 2048);
host->link[0].ready = 1;
err = tok_inaddrport(argv[i],
(struct sockaddr_in *) &host->link[0].address);
if (err < 0) {
log_error("Unable to convert ip address: %s", argv[i]);
exit(EXIT_FAILURE);
}
knet_host_release(knet_h, &host);
}
}
/* Testing the latency/timeout:
* # tc qdisc add dev lo root handle 1:0 netem delay 1s limit 1000
* # tc -d qdisc show dev lo
* # tc qdisc del dev lo root
*/
static int print_link(knet_handle_t khandle, struct knet_host *host, struct knet_host_search *data)
{
int i;
for (i = 0; i < KNET_MAX_LINK; i++) {
if (host->link[i].ready != 1) continue;
printf("host %p, link %p latency is %llums, status: %s\n",
host, &host->link[i], host->link[i].latency,
(host->link[i].enabled == 0) ? "disabled" : "enabled");
}
return KNET_HOST_FOREACH_NEXT;
}
static void sigint_handler(int signum)
{
int err;
printf("Cleaning up...\n");
if (knet_h != NULL) {
err = knet_handle_free(knet_h);
if (err != 0) {
log_error("Unable to cleanup before exit");
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
char buff[1024];
size_t len;
fd_set rfds;
struct timeval tv;
struct knet_host_search print_search;
if (argc < 3) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (socketpair(AF_UNIX, SOCK_STREAM, IPPROTO_IP, knet_sock) != 0) {
log_error("Unable to create socket");
exit(EXIT_FAILURE);
}
knet_h = NULL;
if (signal(SIGINT, sigint_handler) == SIG_ERR) {
log_error("Unable to configure SIGINT handler");
exit(EXIT_FAILURE);
}
if ((knet_h = knet_handle_new(knet_sock[0], 1)) == NULL) {
log_error("Unable to create new knet_handle_t");
exit(EXIT_FAILURE);
}
argv_to_hosts(argc, argv);
knet_handle_setfwd(knet_h, 1);
while (1) {
knet_host_foreach(knet_h, print_link, &print_search);
log_info("Sending 'Hello World!' frame");
write(knet_sock[1], "Hello World!", 13);
tv.tv_sec = 5;
tv.tv_usec = 0;
select_loop:
FD_ZERO(&rfds);
FD_SET(knet_sock[1], &rfds);
len = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
/* uncomment this to replicate the one-message problem */
/* usleep(500000); */
if (len < 0) {
log_error("Unable select over knet_handle_t");
exit(EXIT_FAILURE);
} else if (FD_ISSET(knet_sock[1], &rfds)) {
len = read(knet_sock[1], buff, sizeof(buff));
printf("Received data (%zu bytes): '%s'\n", len, buff);
}
if ((tv.tv_sec > 0) || (tv.tv_usec > 0))
goto select_loop;
}
/* FIXME: allocated hosts should be free'd */
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 26, 8:00 PM (1 d, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1959628
Default Alt Text
(29 KB)

Event Timeline