X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ffragmentation%2Ftest_fragmentation.c;h=cbfb8efe456df8f647eaee1a67fc0e1f4dd4c306;hb=6d754e6c89fda8cb0da00c4152ffc6dcc707e6ce;hp=1aec7bf3607ffa831a893c3420edf55dcd5942a1;hpb=38b29592cf2e8b816cab68579e07e2477153f739;p=oweals%2Fgnunet.git diff --git a/src/fragmentation/test_fragmentation.c b/src/fragmentation/test_fragmentation.c index 1aec7bf36..cbfb8efe4 100644 --- a/src/fragmentation/test_fragmentation.c +++ b/src/fragmentation/test_fragmentation.c @@ -22,418 +22,240 @@ * @brief test for fragmentation.c * @author Christian Grothoff */ - -/** - * Testcase for defragmentation code. - * We have testcases for: - * - 2 fragments, aligned, [0,16),[16,32) - * - n (50) fragments, [i*16,(i+1)*16) - * - n (50) fragments, [0,i*16) + [50*16,51*16) - * - n (100) fragments, inserted in interleaved order (holes in sequence) - * - holes in sequence - * - other overlaps - * - timeouts - * - multiple entries in GNUNET_hash-list - * - id collisions in GNUNET_hash-list - */ - #include "platform.h" #include "gnunet_fragmentation_lib.h" -#if 0 - -/* -- to speed up the testcases -- */ -#define DEFRAGMENTATION_TIMEOUT (1 * GNUNET_CRON_SECONDS) - - -static GNUNET_PeerIdentity mySender; -static char *myMsg; -static unsigned short myMsgLen; +#define VERBOSE GNUNET_EXTRA_LOGGING -/* static buffers to avoid lots of malloc/free */ -static char masterBuffer[65536]; -static char resultBuffer[65536]; - -static void -handleHelper (const GNUNET_PeerIdentity * sender, - const char *msg, - const unsigned int len, int wasEncrypted, GNUNET_TSession * ts) -{ - GNUNET_GE_ASSERT (NULL, - 0 == memcmp (sender, &mySender, - sizeof (GNUNET_PeerIdentity))); - myMsg = resultBuffer; - memcpy (resultBuffer, msg, len); - myMsgLen = len; -} +#define DETAILS GNUNET_NO /** - * Wait long enough to force all fragments to timeout. + * Number of messages to transmit (note: each uses ~32k memory!) */ -static void -makeTimeout () -{ - GNUNET_thread_sleep (DEFRAGMENTATION_TIMEOUT * 2); - defragmentationPurgeCron (NULL); -} +#define NUM_MSGS 5000 /** - * Create a fragment. The data-portion will be filled - * with a sequence of numbers from start+id to start+len-1+id. - * - * @param pep pointer to the ethernet frame/buffer - * @param ip pointer to the ip-header - * @param start starting-offset - * @param length of the data portion - * @param id the identity of the fragment + * MTU to force on fragmentation (must be > 1k + 12) */ -static GNUNET_MessageHeader * -makeFragment (unsigned short start, - unsigned short size, unsigned short tot, int id) -{ - P2P_fragmentation_MESSAGE *frag; - int i; - - frag = (P2P_fragmentation_MESSAGE *) masterBuffer; - frag->id = htonl (id); - frag->off = htons (start); - frag->len = htons (tot); - frag->header.size = htons (sizeof (P2P_fragmentation_MESSAGE) + size); - - for (i = 0; i < size; i++) - ((char *) &frag[1])[i] = (char) i + id + start; - return &frag->header; -} +#define MTU 1111 /** - * Check that the packet received is what we expected to - * get. - * @param id the expected id - * @param len the expected length + * Simulate dropping of 1 out of how many messages? (must be > 1) */ -static void -checkPacket (int id, unsigned int len) -{ - int i; - - GNUNET_GE_ASSERT (NULL, myMsg != NULL); - GNUNET_GE_ASSERT (NULL, myMsgLen == len); - for (i = 0; i < len; i++) - GNUNET_GE_ASSERT (NULL, myMsg[i] == (char) (i + id)); - myMsgLen = 0; - myMsg = NULL; -} +#define DROPRATE 10 +static int ret = 1; -/* **************** actual testcases ***************** */ +static unsigned int dups; -static void -testSimpleFragment () -{ - GNUNET_MessageHeader *pep; - - pep = makeFragment (0, 16, 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - pep = makeFragment (16, 16, 32, 42); - processFragment (&mySender, pep); - checkPacket (42, 32); -} - -static void -testSimpleFragmentTimeout () -{ - GNUNET_MessageHeader *pep; - - pep = makeFragment (0, 16, 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - makeTimeout (); - pep = makeFragment (16, 16, 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - pep = makeFragment (0, 16, 32, 42); - processFragment (&mySender, pep); - checkPacket (42, 32); -} +static unsigned int fragc; -static void -testSimpleFragmentReverse () -{ - GNUNET_MessageHeader *pep; - - pep = makeFragment (16, 16, 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - pep = makeFragment (0, 16, 32, 42); - processFragment (&mySender, pep); - checkPacket (42, 32); -} +static unsigned int frag_drops; -static void -testManyFragments () -{ - GNUNET_MessageHeader *pep; - int i; +static unsigned int acks; - for (i = 0; i < 50; i++) - { - pep = makeFragment (i * 16, 16, 51 * 16, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (50 * 16, 16, 51 * 16, 42); - processFragment (&mySender, pep); - checkPacket (42, 51 * 16); -} +static unsigned int ack_drops; -static void -testManyFragmentsMegaLarge () -{ - GNUNET_MessageHeader *pep; - int i; +static struct GNUNET_DEFRAGMENT_Context *defrag; - for (i = 0; i < 4000; i++) - { - pep = makeFragment (i * 16, 16, 4001 * 16, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (4000 * 16, 16, 4001 * 16, 42); - processFragment (&mySender, pep); - checkPacket (42, 4001 * 16); -} +static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS]; -static void -testLastFragmentEarly () -{ - GNUNET_MessageHeader *pep; - int i; +static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; - for (i = 0; i < 5; i++) - { - pep = makeFragment (i * 16, 8, 6 * 16 + 8, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (5 * 16, 24, 6 * 16 + 8, 42); - processFragment (&mySender, pep); - for (i = 0; i < 5; i++) - { - pep = makeFragment (i * 16 + 8, 8, 6 * 16 + 8, 42); - processFragment (&mySender, pep); - } - checkPacket (42, 6 * 16 + 8); -} +static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static void -testManyInterleavedFragments () +do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - GNUNET_MessageHeader *pep; - int i; - - for (i = 0; i < 50; i++) - { - pep = makeFragment (i * 16, 8, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - for (i = 0; i < 50; i++) - { - pep = makeFragment (i * 16 + 8, 8, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (50 * 16, 24, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - checkPacket (42, 51 * 16 + 8); + unsigned int i; + + ret = 0; + shutdown_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_DEFRAGMENT_context_destroy (defrag); + defrag = NULL; + for (i = 0; i < NUM_MSGS; i++) + { + if (frags[i] == NULL) + continue; + GNUNET_FRAGMENT_context_destroy (frags[i]); + frags[i] = NULL; + } } -static void -testManyInterleavedOverlappingFragments () -{ - GNUNET_MessageHeader *pep; - int i; - - for (i = 0; i < 50; i++) - { - pep = makeFragment (i * 32, 16, 51 * 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - for (i = 0; i < 50; i++) - { - pep = makeFragment (i * 32 + 8, 24, 51 * 32, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (50 * 32, 32, 51 * 32, 42); - processFragment (&mySender, pep); - checkPacket (42, 51 * 32); -} static void -testManyOverlappingFragments () +proc_msgs (void *cls, const struct GNUNET_MessageHeader *hdr) { - GNUNET_MessageHeader *pep; - int i; - - for (i = 0; i < 50; i++) - { - pep = makeFragment (0, i * 16 + 16, 51 * 16, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - pep = makeFragment (50 * 16, 16, 51 * 16, 42); - processFragment (&mySender, pep); - checkPacket (42, 51 * 16); -} + static unsigned int total; + unsigned int i; + const char *buf; -static void -testManyOverlappingFragmentsTimeout () -{ - GNUNET_MessageHeader *pep; - int i; - - for (i = 0; i < 50; i++) - { - pep = makeFragment (0, i * 16 + 16, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - makeTimeout (); - pep = makeFragment (50 * 16, 24, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - for (i = 0; i < 50; i++) - { - pep = makeFragment (0, i * 16 + 16, 51 * 16 + 8, 42); - processFragment (&mySender, pep); - } - checkPacket (42, 51 * 16 + 8); +#if DETAILS + FPRINTF (stderr, "%s", "!"); /* message complete, good! */ +#endif + buf = (const char *) hdr; + for (i = sizeof (struct GNUNET_MessageHeader); i < ntohs (hdr->size); i++) + GNUNET_assert (buf[i] == (char) i); + total++; +#if ! DETAILS + if (0 == (total % (NUM_MSGS / 100))) + FPRINTF (stderr, "%s", "."); +#endif + /* tolerate 10% loss, i.e. due to duplicate fragment IDs */ + if ((total >= NUM_MSGS - (NUM_MSGS / 10)) && (ret != 0)) + { + if (GNUNET_SCHEDULER_NO_TASK == shutdown_task) + shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + } } -static void -testManyFragmentsMultiId () -{ - GNUNET_MessageHeader *pep; - int i; - int id; - - for (i = 0; i < 50; i++) - { - for (id = 0; id < DEFRAG_BUCKET_COUNT; id++) - { - pep = makeFragment (i * 16, 16, 51 * 16, id + 5); - mySender.hashPubKey.bits[0] = id; - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } - } - for (id = 0; id < DEFRAG_BUCKET_COUNT; id++) - { - pep = makeFragment (50 * 16, 16, 51 * 16, id + 5); - mySender.hashPubKey.bits[0] = id; - processFragment (&mySender, pep); - checkPacket (id + 5, 51 * 16); - } -} +/** + * Process ACK (by passing to fragmenter) + */ static void -testManyFragmentsMultiIdCollisions () +proc_acks (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) { - GNUNET_MessageHeader *pep; - int i; - int id; - - for (i = 0; i < 5; i++) + unsigned int i; + int ret; + + if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) + { + ack_drops++; + return; /* random drop */ + } + for (i = 0; i < NUM_MSGS; i++) + { + if (frags[i] == NULL) + continue; + ret = GNUNET_FRAGMENT_process_ack (frags[i], hdr); + if (ret == GNUNET_OK) { - for (id = 0; id < DEFRAG_BUCKET_COUNT * 4; id++) - { - pep = makeFragment (i * 16, 16, 6 * 16, id + 5); - mySender.hashPubKey.bits[0] = id; - processFragment (&mySender, pep); - GNUNET_GE_ASSERT (NULL, myMsg == NULL); - } +#if DETAILS + FPRINTF (stderr, "%s", "@"); /* good ACK */ +#endif + GNUNET_FRAGMENT_context_destroy (frags[i]); + frags[i] = NULL; + acks++; + return; } - for (id = 0; id < DEFRAG_BUCKET_COUNT * 4; id++) + if (ret == GNUNET_NO) { - pep = makeFragment (5 * 16, 16, 6 * 16, id + 5); - mySender.hashPubKey.bits[0] = id; - processFragment (&mySender, pep); - checkPacket (id + 5, 6 * 16); +#if DETAILS + FPRINTF (stderr, "%s", "@"); /* good ACK */ +#endif + acks++; + return; } + } +#if DETAILS + FPRINTF (stderr, "%s", "_"); /* BAD: ack that nobody feels responsible for... */ +#endif } -/* ************* driver ****************** */ - -static int -p2p_register_handler (const unsigned short type, - GNUNET_P2PRequestHandler callback) -{ - return GNUNET_OK; -} -static int -p2p_unregister_handler (const unsigned short type, - GNUNET_P2PRequestHandler callback) +/** + * Process fragment (by passing to defrag). + */ +static void +proc_frac (void *cls, const struct GNUNET_MessageHeader *hdr) { - return GNUNET_OK; + struct GNUNET_FRAGMENT_Context **fc = cls; + int ret; + + GNUNET_FRAGMENT_context_transmission_done (*fc); + if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) + { + frag_drops++; + return; /* random drop */ + } + if (NULL == defrag) + { + FPRINTF (stderr, "%s", "E"); /* Error: frag after shutdown!? */ + return; + } + ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); + if (ret == GNUNET_NO) + { +#if DETAILS + FPRINTF (stderr, "%s", "?"); /* duplicate fragment */ +#endif + dups++; + } + else if (ret == GNUNET_OK) + { +#if DETAILS + FPRINTF (stderr, "%s", "."); /* good fragment */ +#endif + fragc++; + } } -static void * -request_service (const char *name) +/** + * Main function run with scheduler. + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - return NULL; + unsigned int i; + struct GNUNET_MessageHeader *msg; + char buf[MTU + 32 * 1024]; + + defrag = GNUNET_DEFRAGMENT_context_create (NULL, MTU, NUM_MSGS /* enough space for all */ + , NULL, &proc_msgs, &proc_acks); + for (i = 0; i < sizeof (buf); i++) + buf[i] = (char) i; + msg = (struct GNUNET_MessageHeader *) buf; + for (i = 0; i < NUM_MSGS; i++) + { + msg->type = htons ((uint16_t) i); + msg->size = + htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); + frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */ , + MTU, &trackers[i], + GNUNET_TIME_UNIT_SECONDS, msg, + &proc_frac, &frags[i]); + } } -#endif int main (int argc, char *argv[]) { - fprintf (stderr, "WARNING: testcase not yet ported to new API.\n"); -#if 0 - GNUNET_CoreAPIForPlugins capi; - - memset (&capi, 0, sizeof (GNUNET_CoreAPIForPlugins)); - capi.cron = GNUNET_cron_create (NULL); - capi.loopback_send = &handleHelper; - capi.service_request = &request_service; - capi.p2p_ciphertext_handler_register = &p2p_register_handler; - capi.p2p_ciphertext_handler_unregister = &p2p_unregister_handler; - provide_module_fragmentation (&capi); - - fprintf (stderr, "."); - testSimpleFragment (); - fprintf (stderr, "."); - testSimpleFragmentTimeout (); - fprintf (stderr, "."); - testSimpleFragmentReverse (); - fprintf (stderr, "."); - testManyFragments (); - fprintf (stderr, "."); - testManyFragmentsMegaLarge (); - fprintf (stderr, "."); - testManyFragmentsMultiId (); - fprintf (stderr, "."); - - testManyInterleavedFragments (); - fprintf (stderr, "."); - testManyInterleavedOverlappingFragments (); - fprintf (stderr, "."); - testManyOverlappingFragments (); - fprintf (stderr, "."); - testManyOverlappingFragmentsTimeout (); - fprintf (stderr, "."); - testLastFragmentEarly (); - fprintf (stderr, "."); - testManyFragmentsMultiIdCollisions (); - fprintf (stderr, "."); - release_module_fragmentation (); - fprintf (stderr, "\n"); - GNUNET_cron_destroy (capi.cron); + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + char *const argv_prog[] = { + "test-fragmentation", + "-c", + "test_fragmentation_data.conf", + "-L", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL + }; + unsigned int i; + + GNUNET_log_setup ("test-fragmentation", +#if VERBOSE + "DEBUG", +#else + "WARNING", #endif - return 0; /* testcase passed */ + NULL); + for (i = 0; i < NUM_MSGS; i++) + GNUNET_BANDWIDTH_tracker_init (&trackers[i], + GNUNET_BANDWIDTH_value_init ((i + 1) * 1024), + 100); + GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, + &run, NULL); + FPRINTF (stderr, + "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", + fragc, dups, acks, ack_drops); + return ret; }