Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4525740
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
29 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rK kronosnet
Attached
Detach File
Event Timeline
Log In to Comment