mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-24 07:16:43 +00:00
Add network coding test app to the build
This commit is contained in:
parent
c1a7abdaa9
commit
d67dfa22b2
@ -111,9 +111,6 @@ fakeradio: fakeradio.o
|
|||||||
@echo LINK $@
|
@echo LINK $@
|
||||||
@$(CC) $(CFLAGS) -Wall -o $@ fakeradio.o
|
@$(CC) $(CFLAGS) -Wall -o $@ fakeradio.o
|
||||||
|
|
||||||
network_coding: network_coding.c
|
|
||||||
@$(CC) -DRUNTESTS -Wall -o $@ network_coding.c
|
|
||||||
|
|
||||||
# This does not build on 64 bit elf platforms as NaCL isn't built with -fPIC
|
# This does not build on 64 bit elf platforms as NaCL isn't built with -fPIC
|
||||||
# DOC 20120615
|
# DOC 20120615
|
||||||
libservald.so: $(OBJS) version.o
|
libservald.so: $(OBJS) version.o
|
||||||
|
@ -16,6 +16,7 @@ HDRS= fifo.h \
|
|||||||
strbuf.h \
|
strbuf.h \
|
||||||
strbuf_helpers.h \
|
strbuf_helpers.h \
|
||||||
sha2.h \
|
sha2.h \
|
||||||
|
network_coding.h \
|
||||||
conf.h \
|
conf.h \
|
||||||
conf_schema.h \
|
conf_schema.h \
|
||||||
crypto.h \
|
crypto.h \
|
||||||
|
@ -24,9 +24,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include "network_coding.h"
|
||||||
|
#include "dataformats.h"
|
||||||
|
|
||||||
#define FLAG_NEW 1
|
#define FLAG_NEW 1
|
||||||
#define HEADER_LEN 7
|
|
||||||
|
|
||||||
struct nc_packet{
|
struct nc_packet{
|
||||||
uint8_t sequence;
|
uint8_t sequence;
|
||||||
@ -56,21 +58,6 @@ struct nc{
|
|||||||
struct nc_half rx;
|
struct nc_half rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
void write_uint32(unsigned char *o,uint32_t v)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0;i<4;i++)
|
|
||||||
{ *(o++)=v&0xff; v=v>>8; }
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read_uint32(unsigned char *o)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t v=0;
|
|
||||||
for(i=0;i<4;i++) v=(v<<8)|o[4-1-i];
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _nc_free_half(struct nc_half *n)
|
static void _nc_free_half(struct nc_half *n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -265,7 +252,7 @@ static int _nc_tx_combine_random_payloads(struct nc_half *n, struct nc_packet *p
|
|||||||
int nc_tx_produce_packet(struct nc *n, uint8_t *datagram, uint32_t buffer_size)
|
int nc_tx_produce_packet(struct nc *n, uint8_t *datagram, uint32_t buffer_size)
|
||||||
{
|
{
|
||||||
// TODO: Don't waste more bytes than we need to on the bitmap and sequence number
|
// TODO: Don't waste more bytes than we need to on the bitmap and sequence number
|
||||||
if (buffer_size < n->tx.datagram_size+HEADER_LEN)
|
if (buffer_size < n->tx.datagram_size+NC_HEADER_LEN)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (_nc_get_ack(&n->rx, &datagram[0], &datagram[1]))
|
if (_nc_get_ack(&n->rx, &datagram[0], &datagram[1]))
|
||||||
@ -281,7 +268,7 @@ int nc_tx_produce_packet(struct nc *n, uint8_t *datagram, uint32_t buffer_size)
|
|||||||
struct nc_packet packet={
|
struct nc_packet packet={
|
||||||
.sequence = n->tx.window_start,
|
.sequence = n->tx.window_start,
|
||||||
.combination = 0,
|
.combination = 0,
|
||||||
.payload = &datagram[HEADER_LEN],
|
.payload = &datagram[NC_HEADER_LEN],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_nc_tx_combine_random_payloads(&n->tx, &packet))
|
if (_nc_tx_combine_random_payloads(&n->tx, &packet))
|
||||||
@ -291,7 +278,7 @@ int nc_tx_produce_packet(struct nc *n, uint8_t *datagram, uint32_t buffer_size)
|
|||||||
// Write out bitmap of actual combinations involved
|
// Write out bitmap of actual combinations involved
|
||||||
datagram[2] = packet.sequence;
|
datagram[2] = packet.sequence;
|
||||||
write_uint32(&datagram[3], packet.combination);
|
write_uint32(&datagram[3], packet.combination);
|
||||||
return HEADER_LEN+n->tx.datagram_size;
|
return NC_HEADER_LEN+n->tx.datagram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nc_rx_combine_packet(struct nc_half *n, struct nc_packet *packet)
|
static int _nc_rx_combine_packet(struct nc_half *n, struct nc_packet *packet)
|
||||||
@ -372,14 +359,14 @@ static void _nc_rx_advance_window(struct nc_half *n, uint8_t new_window_start)
|
|||||||
|
|
||||||
int nc_rx_packet(struct nc *n, uint8_t *payload, size_t len)
|
int nc_rx_packet(struct nc *n, uint8_t *payload, size_t len)
|
||||||
{
|
{
|
||||||
if (len!=2 && len != HEADER_LEN+n->rx.datagram_size){
|
if (len!=2 && len != NC_HEADER_LEN+n->rx.datagram_size){
|
||||||
fprintf(stderr, "len=%zd\n",len);
|
fprintf(stderr, "len=%zd\n",len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_nc_ack(&n->tx, payload[0], payload[1]);
|
_nc_ack(&n->tx, payload[0], payload[1]);
|
||||||
|
|
||||||
if (len < HEADER_LEN+n->rx.datagram_size)
|
if (len < NC_HEADER_LEN+n->rx.datagram_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint8_t new_window_start = payload[2];
|
uint8_t new_window_start = payload[2];
|
||||||
@ -387,7 +374,7 @@ int nc_rx_packet(struct nc *n, uint8_t *payload, size_t len)
|
|||||||
struct nc_packet packet={
|
struct nc_packet packet={
|
||||||
.sequence = new_window_start,
|
.sequence = new_window_start,
|
||||||
.combination = read_uint32(&payload[3]),
|
.combination = read_uint32(&payload[3]),
|
||||||
.payload = &payload[HEADER_LEN],
|
.payload = &payload[NC_HEADER_LEN],
|
||||||
};
|
};
|
||||||
|
|
||||||
int r = _nc_rx_combine_packet(&n->rx, &packet);
|
int r = _nc_rx_combine_packet(&n->rx, &packet);
|
||||||
@ -419,12 +406,19 @@ int nc_rx_next_delivered(struct nc *n, uint8_t *payload, int buffer_size)
|
|||||||
return n->rx.datagram_size;
|
return n->rx.datagram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _hexdump(uint8_t *bytes, size_t len)
|
#ifdef RUNTESTS
|
||||||
{
|
/* TODO: Tests that should be written.
|
||||||
size_t i;
|
1. nc_new() works, and rejects bad input.
|
||||||
for (i=0;i<len;i++)
|
2. nc_free() works, including on partially initialised structures.
|
||||||
fprintf(stderr, "%02x ", bytes[i]);
|
3. nc_tx_enqueue_datagram() works, including failing on bad input and when the
|
||||||
}
|
queue is full.
|
||||||
|
4. nc_tx_ack_dof() works, rejects bad input, and correctly releases buffers.
|
||||||
|
5. nc_tx_random_linear_combination() works, rejects bad input, and produces valid
|
||||||
|
linear combinations of the enqueued datagrams, and never produces all zeroes.
|
||||||
|
6. nc_rx_linear_combination() works, rejects bad input
|
||||||
|
7. nc_rx_linear_combination() rejects when RX queue full, when combination starts
|
||||||
|
before current window.
|
||||||
|
*/
|
||||||
|
|
||||||
static int _nc_dump_half(struct nc_half *n)
|
static int _nc_dump_half(struct nc_half *n)
|
||||||
{
|
{
|
||||||
@ -440,8 +434,6 @@ static int _nc_dump_half(struct nc_half *n)
|
|||||||
int j;
|
int j;
|
||||||
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
||||||
fprintf(stderr, "%0d",(n->packets[i].combination>>(31-j))&1);
|
fprintf(stderr, "%0d",(n->packets[i].combination>>(31-j))&1);
|
||||||
fprintf(stderr, " ");
|
|
||||||
_hexdump(n->packets[i].payload, 16);
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -456,20 +448,6 @@ static void _nc_dump(struct nc *n)
|
|||||||
_nc_dump_half(&n->rx);
|
_nc_dump_half(&n->rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RUNTESTS
|
|
||||||
/* TODO: Tests that should be written.
|
|
||||||
1. nc_new() works, and rejects bad input.
|
|
||||||
2. nc_free() works, including on partially initialised structures.
|
|
||||||
3. nc_tx_enqueue_datagram() works, including failing on bad input and when the
|
|
||||||
queue is full.
|
|
||||||
4. nc_tx_ack_dof() works, rejects bad input, and correctly releases buffers.
|
|
||||||
5. nc_tx_random_linear_combination() works, rejects bad input, and produces valid
|
|
||||||
linear combinations of the enqueued datagrams, and never produces all zeroes.
|
|
||||||
6. nc_rx_linear_combination() works, rejects bad input
|
|
||||||
7. nc_rx_linear_combination() rejects when RX queue full, when combination starts
|
|
||||||
before current window.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void FAIL(const char *fmt,...){
|
void FAIL(const char *fmt,...){
|
||||||
va_list ap;
|
va_list ap;
|
||||||
fprintf(stderr, "FAIL: ");
|
fprintf(stderr, "FAIL: ");
|
||||||
@ -530,7 +508,7 @@ int nc_test()
|
|||||||
|
|
||||||
int j=0;
|
int j=0;
|
||||||
for(i=0;i<10;i++) {
|
for(i=0;i<10;i++) {
|
||||||
uint8_t outbuffer[HEADER_LEN+200];
|
uint8_t outbuffer[NC_HEADER_LEN+200];
|
||||||
int len=sizeof(outbuffer);
|
int len=sizeof(outbuffer);
|
||||||
int written = nc_tx_produce_packet(tx, outbuffer, len);
|
int written = nc_tx_produce_packet(tx, outbuffer, len);
|
||||||
if (written==-1)
|
if (written==-1)
|
||||||
@ -543,7 +521,7 @@ int nc_test()
|
|||||||
if (i==9)
|
if (i==9)
|
||||||
PASS("Should not produce empty linear combination bitmap");
|
PASS("Should not produce empty linear combination bitmap");
|
||||||
|
|
||||||
if (memcmp(&outbuffer[HEADER_LEN], datagrams[0], 200)!=0)
|
if (memcmp(&outbuffer[NC_HEADER_LEN], datagrams[0], 200)!=0)
|
||||||
FAIL("Output identity datagram when only one in queue");
|
FAIL("Output identity datagram when only one in queue");
|
||||||
if (i==9)
|
if (i==9)
|
||||||
PASS("Output identity datagram when only one in queue");
|
PASS("Output identity datagram when only one in queue");
|
||||||
@ -583,7 +561,7 @@ int nc_test()
|
|||||||
|
|
||||||
// now can we receive this first packet?
|
// now can we receive this first packet?
|
||||||
{
|
{
|
||||||
uint8_t outbuffer[HEADER_LEN+200];
|
uint8_t outbuffer[NC_HEADER_LEN+200];
|
||||||
int written = nc_tx_produce_packet(tx, outbuffer, sizeof(outbuffer));
|
int written = nc_tx_produce_packet(tx, outbuffer, sizeof(outbuffer));
|
||||||
ASSERT(written!=-1, "Produce packet");
|
ASSERT(written!=-1, "Produce packet");
|
||||||
int r=nc_rx_packet(rx, outbuffer, written);
|
int r=nc_rx_packet(rx, outbuffer, written);
|
||||||
@ -602,7 +580,7 @@ int nc_test()
|
|||||||
|
|
||||||
// acknowledging this first packet advances the window
|
// acknowledging this first packet advances the window
|
||||||
{
|
{
|
||||||
uint8_t outbuffer[HEADER_LEN+200];
|
uint8_t outbuffer[NC_HEADER_LEN+200];
|
||||||
int written = nc_tx_produce_packet(rx, outbuffer, sizeof(outbuffer));
|
int written = nc_tx_produce_packet(rx, outbuffer, sizeof(outbuffer));
|
||||||
ASSERT(written!=-1, "Produce ACK");
|
ASSERT(written!=-1, "Produce ACK");
|
||||||
int r=nc_rx_packet(tx, outbuffer, written);
|
int r=nc_rx_packet(tx, outbuffer, written);
|
||||||
@ -621,7 +599,7 @@ int nc_test()
|
|||||||
|
|
||||||
int decoded=0;
|
int decoded=0;
|
||||||
for(i=0;i<100;i++) {
|
for(i=0;i<100;i++) {
|
||||||
uint8_t outbuffer[HEADER_LEN+200];
|
uint8_t outbuffer[NC_HEADER_LEN+200];
|
||||||
int len=sizeof(outbuffer);
|
int len=sizeof(outbuffer);
|
||||||
int written = nc_tx_produce_packet(tx, outbuffer, len);
|
int written = nc_tx_produce_packet(tx, outbuffer, len);
|
||||||
if (written==-1)
|
if (written==-1)
|
||||||
@ -636,7 +614,7 @@ int nc_test()
|
|||||||
|
|
||||||
for(j=0;j<200;j++) {
|
for(j=0;j<200;j++) {
|
||||||
int k;
|
int k;
|
||||||
uint8_t x = outbuffer[HEADER_LEN+j];
|
uint8_t x = outbuffer[NC_HEADER_LEN+j];
|
||||||
for (k=0;k<8;k++){
|
for (k=0;k<8;k++){
|
||||||
if (combination&(0x80000000>>k))
|
if (combination&(0x80000000>>k))
|
||||||
x^=datagrams[k+1][j];
|
x^=datagrams[k+1][j];
|
||||||
@ -668,7 +646,7 @@ int nc_test()
|
|||||||
|
|
||||||
// acknowledging first 8 packets advances the tx window
|
// acknowledging first 8 packets advances the tx window
|
||||||
{
|
{
|
||||||
uint8_t outbuffer[HEADER_LEN+200];
|
uint8_t outbuffer[NC_HEADER_LEN+200];
|
||||||
int written = nc_tx_produce_packet(rx, outbuffer, sizeof(outbuffer));
|
int written = nc_tx_produce_packet(rx, outbuffer, sizeof(outbuffer));
|
||||||
ASSERT(written!=-1, "Produce ACK");
|
ASSERT(written!=-1, "Produce ACK");
|
||||||
int r=nc_rx_packet(tx, outbuffer, written);
|
int r=nc_rx_packet(tx, outbuffer, written);
|
||||||
@ -682,7 +660,7 @@ int nc_test()
|
|||||||
int dropped=0;
|
int dropped=0;
|
||||||
bzero(histogram, sizeof(histogram));
|
bzero(histogram, sizeof(histogram));
|
||||||
|
|
||||||
uint8_t packets[8][HEADER_LEN+200];
|
uint8_t packets[8][NC_HEADER_LEN+200];
|
||||||
|
|
||||||
while(decoded < 10000 && sent <=1000000){
|
while(decoded < 10000 && sent <=1000000){
|
||||||
// fill the transmit window whenever there is space
|
// fill the transmit window whenever there is space
|
||||||
@ -693,8 +671,8 @@ int nc_test()
|
|||||||
|
|
||||||
// generate a packet in each direction
|
// generate a packet in each direction
|
||||||
sent++;
|
sent++;
|
||||||
int wone = nc_tx_produce_packet(tx, packets[sent&7], HEADER_LEN+200);
|
int wone = nc_tx_produce_packet(tx, packets[sent&7], NC_HEADER_LEN+200);
|
||||||
int wtwo = nc_tx_produce_packet(rx, packets[(sent+4)&7], HEADER_LEN+200);
|
int wtwo = nc_tx_produce_packet(rx, packets[(sent+4)&7], NC_HEADER_LEN+200);
|
||||||
if (sent <13)
|
if (sent <13)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
6
network_coding.h
Normal file
6
network_coding.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __SERVALD_NETWORK_CODING_H
|
||||||
|
#define __SERVALD_NETWORK_CODING_H
|
||||||
|
|
||||||
|
#define NC_HEADER_LEN 7
|
||||||
|
|
||||||
|
#endif
|
@ -30,6 +30,7 @@ SERVAL_SOURCES = \
|
|||||||
$(SERVAL_BASE)monitor-client.c \
|
$(SERVAL_BASE)monitor-client.c \
|
||||||
$(SERVAL_BASE)monitor-cli.c \
|
$(SERVAL_BASE)monitor-cli.c \
|
||||||
$(SERVAL_BASE)net.c \
|
$(SERVAL_BASE)net.c \
|
||||||
|
$(SERVAL_BASE)network_coding.c \
|
||||||
$(SERVAL_BASE)nonce.c \
|
$(SERVAL_BASE)nonce.c \
|
||||||
$(SERVAL_BASE)overlay.c \
|
$(SERVAL_BASE)overlay.c \
|
||||||
$(SERVAL_BASE)overlay_address.c \
|
$(SERVAL_BASE)overlay_address.c \
|
||||||
|
Loading…
Reference in New Issue
Block a user