mem_ptr_t *mem_heap_alloc(U8 size) { U8 i; for (i=0; i<MAX_MEM_PTR_POOL; i++) { if (!mem_ptr_pool[i].alloc) { // found a free mem ptr. only mark it used if we can alloc memory to it. if (mmem_alloc(&mem_ptr_pool[i].mmem_ptr, size)) { // memory successfully alloc'd. clear the block, mark this sucker used, and return it. memset(mem_ptr_pool[i].mmem_ptr.ptr, 0, sizeof(mem_ptr_t)); mem_ptr_pool[i].alloc = true; return &mem_ptr_pool[i]; } else { // no more memory. don't touch the ptr and return NULL. return NULL; } } } // couldn't find any free mem pointers. return NULL. return NULL; }
struct mmem * bundle_create_bundle() { int ret; struct bundle_slot_t *bs; struct bundle_t *bundle; bs = bundleslot_get_free(); if( bs == NULL ) { LOG(LOGD_DTN, LOG_BUNDLE, LOGL_ERR, "Could not allocate slot for a bundle"); return NULL; } ret = mmem_alloc(&bs->bundle, sizeof(struct bundle_t)); if (!ret) { bundleslot_free(bs); LOG(LOGD_DTN, LOG_BUNDLE, LOGL_ERR, "Could not allocate memory for a bundle"); return NULL; } bundle = (struct bundle_t *) MMEM_PTR(&bs->bundle); memset(bundle, 0, sizeof(struct bundle_t)); bundle->rec_time = xTaskGetTickCount(); bundle->num_blocks = 0; bundle->source_event_queue = dtn_process_get_event_queue(); configASSERT(bundle->source_event_queue != NULL); /* Bundles are created as singleton and with normal priority */ bundle->flags = BUNDLE_FLAG_SINGLETON | BUNDLE_PRIORITY_NORMAL; return &bs->bundle; }
/** * Return values: * 1 = SUCCESS * -1 = Temporary error * -2 = Permanent error */ int convergence_layer_parse_dataframe(linkaddr_t * source, uint8_t * payload, uint8_t payload_length, uint8_t flags, uint8_t sequence_number, packetbuf_attr_t rssi) { struct mmem * bundlemem = NULL; struct bundle_t * bundle = NULL; struct transmit_ticket_t * ticket = NULL; int n; int length; #if CONVERGENCE_LAYER_SEGMENTATION int ret; #endif /* CONVERGENCE_LAYER_SEGMENTATION */ /* Note down the payload length */ length = payload_length; if( flags != (CONVERGENCE_LAYER_FLAGS_FIRST | CONVERGENCE_LAYER_FLAGS_LAST ) ) { #if CONVERGENCE_LAYER_SEGMENTATION /* We have a multipart bundle here */ if( flags == CONVERGENCE_LAYER_FLAGS_FIRST ) { /* Beginning of a new bundle from a peer, remove old tickets */ for( ticket = list_head(transmission_ticket_list); ticket != NULL; ticket = list_item_next(ticket) ) { if( linkaddr_cmp(&ticket->neighbour, source) && (ticket->flags & CONVERGENCE_LAYER_QUEUE_MULTIPART_RECV) ) { break; } } /* We found a ticket, remove it */ if( ticket != NULL ) { LOG(LOGD_DTN, LOG_CL, LOGL_WRN, "Resynced to peer %u.%u, throwing away old buffer", source->u8[0], source->u8[1]); convergence_layer_free_transmit_ticket(ticket); ticket = NULL; } /* Allocate a new ticket for the incoming bundle */ ticket = convergence_layer_get_transmit_ticket_priority(CONVERGENCE_LAYER_PRIORITY_HIGH); if( ticket == NULL ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Unable to allocate multipart receive ticket"); return -1; } /* Fill the fields of the ticket */ linkaddr_copy(&ticket->neighbour, source); ticket->flags = CONVERGENCE_LAYER_QUEUE_MULTIPART_RECV; ticket->timestamp = clock_time(); ticket->sequence_number = sequence_number; /* Now allocate some memory */ ret = mmem_alloc(&ticket->buffer, length); if( ret < 1 ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Unable to allocate multipart receive buffer of %u bytes", length); convergence_layer_free_transmit_ticket(ticket); ticket = NULL; return -1; } /* Copy the payload into the buffer */ memcpy(MMEM_PTR(&ticket->buffer), payload, length); /* We are waiting for more segments, return now */ return 1; } else { /* Either the middle of the end of a bundle, go look for the ticket */ for( ticket = list_head(transmission_ticket_list); ticket != NULL; ticket = list_item_next(ticket) ) { if( linkaddr_cmp(&ticket->neighbour, source) && (ticket->flags & CONVERGENCE_LAYER_QUEUE_MULTIPART_RECV) ) { break; } } /* Cannot find a ticket, discard segment */ if( ticket == NULL ) { LOG(LOGD_DTN, LOG_CL, LOGL_WRN, "Segment from peer %u.%u does not match any bundles in progress, discarding", source->u8[0], source->u8[1]); return -1; } if( sequence_number != (ticket->sequence_number + 1) % 4 ) { LOG(LOGD_DTN, LOG_CL, LOGL_WRN, "Segment from peer %u.%u is out of sequence. Recv %u, Exp %u", source->u8[0], source->u8[1], sequence_number, (ticket->sequence_number + 1) % 4); return 1; } /* Store the last received and valid sequence number */ ticket->sequence_number = sequence_number; /* Note down the old length to know where to start */ n = ticket->buffer.size; /* Allocate more memory */ ret = mmem_realloc(&ticket->buffer, ticket->buffer.size + length); if( ret < 1 ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Unable to re-allocate multipart receive buffer of %u bytes", ticket->buffer.size + length); convergence_layer_free_transmit_ticket(ticket); return -1; } /* Update timestamp to avoid the ticket from timing out */ ticket->timestamp = clock_time(); /* And append the payload */ memcpy(((uint8_t *) MMEM_PTR(&ticket->buffer)) + n, payload, length); } if( flags & CONVERGENCE_LAYER_FLAGS_LAST ) { /* We have the last segment, change pointer so that the rest of the function works as planned */ payload = (uint8_t *) MMEM_PTR(&ticket->buffer); length = ticket->buffer.size; LOG(LOGD_DTN, LOG_CL, LOGL_DBG, "%u byte multipart bundle received from %u.%u, parsing", length, source->u8[0], source->u8[1]); } else { /* We are waiting for more segments, return now */ return 1; } #else /* CONVERGENCE_LAYER_SEGMENTATION */ /* We will never be able to parse that bundle, signal a permanent error */ return -2; #endif /* CONVERGENCE_LAYER_SEGMENTATION */ } /* Allocate memory, parse the bundle and set reference counter to 1 */ bundlemem = bundle_recover_bundle(payload, length); /* We do not need the ticket anymore if there was one, deallocate it */ if( ticket != NULL ) { convergence_layer_free_transmit_ticket(ticket); ticket = NULL; } if( !bundlemem ) { LOG(LOGD_DTN, LOG_CL, LOGL_WRN, "Error recovering bundle"); /* Possibly not enough memory -> temporary error */ return -1; } bundle = (struct bundle_t *) MMEM_PTR(bundlemem); if( !bundle ) { LOG(LOGD_DTN, LOG_CL, LOGL_WRN, "Invalid bundle pointer"); bundle_decrement(bundlemem); /* Possibly not enough memory -> temporary error */ return -1; } /* Check for bundle expiration */ if( bundle_ageing_is_expired(bundlemem) ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Bundle received from %u.%u with SeqNo %u is expired", source->u8[0], source->u8[1], sequence_number); bundle_decrement(bundlemem); /* Send permanent rejection */ return -2; } /* Mark the bundle as "internal" */ bundle->source_process = &agent_process; LOG(LOGD_DTN, LOG_CL, LOGL_DBG, "Bundle from ipn:%lu.%lu (to ipn:%lu.%lu) received from %u.%u with SeqNo %u", bundle->src_node, bundle->src_srv, bundle->dst_node, bundle->dst_srv, source->u8[0], source->u8[1], sequence_number); /* Store the node from which we received the bundle */ linkaddr_copy(&bundle->msrc, source); /* Store the RSSI for this packet */ bundle->rssi = rssi; /* Hand over the bundle to dispatching */ n = dispatching_dispatch_bundle(bundlemem); bundlemem = NULL; if( n ) { /* Dispatching was successfull! */ return 1; } /* Temporary error */ return -1; }
int convergence_layer_send_bundle(struct transmit_ticket_t * ticket) { struct bundle_t *bundle = NULL; uint16_t length = 0; uint8_t * buffer = NULL; uint8_t buffer_length = 0; #if CONVERGENCE_LAYER_SEGMENTATION int ret; int segments; #endif /* CONVERGENCE_LAYER_SEGMENTATION */ LOG(LOGD_DTN, LOG_CL, LOGL_DBG, "Sending bundle %lu to %u.%u with ticket %p", ticket->bundle_number, ticket->neighbour.u8[0], ticket->neighbour.u8[1], ticket); if( !(ticket->flags & CONVERGENCE_LAYER_QUEUE_MULTIPART) ) { /* Read the bundle from storage, if it is not in memory */ if( ticket->bundle == NULL ) { ticket->bundle = BUNDLE_STORAGE.read_bundle(ticket->bundle_number); if( ticket->bundle == NULL ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Unable to read bundle %lu", ticket->bundle_number); /* FIXME: Notify somebody */ return -1; } } /* Get our bundle struct and check the pointer */ bundle = (struct bundle_t *) MMEM_PTR(ticket->bundle); if( bundle == NULL ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Invalid bundle pointer for bundle %lu", ticket->bundle_number); bundle_decrement(ticket->bundle); ticket->bundle = NULL; return -1; } /* Check if bundle has expired */ if( bundle_ageing_is_expired(ticket->bundle) ) { LOG(LOGD_DTN, LOG_CL, LOGL_INF, "Bundle %lu has expired, not sending it", ticket->bundle_number); /* Bundle is expired */ bundle_decrement(ticket->bundle); /* Tell storage to delete - it will take care of the rest */ BUNDLE_STORAGE.del_bundle(ticket->bundle_number, REASON_LIFETIME_EXPIRED); return -1; } } /* Get the outgoing network buffer */ buffer = dtn_network_get_buffer(); if( buffer == NULL ) { bundle_decrement(ticket->bundle); ticket->bundle = NULL; return -1; } /* Get the buffer length */ buffer_length = dtn_network_get_buffer_length(); #if CONVERGENCE_LAYER_SEGMENTATION /* We have to use a heuristic to estimate if the bundle will be a multipart bundle */ if( ticket->bundle->size > CONVERGENCE_LAYER_MAX_LENGTH && !(ticket->flags & CONVERGENCE_LAYER_QUEUE_MULTIPART) ) { /* This is a bundle for multiple segments and we have our first look at it */ ticket->flags |= CONVERGENCE_LAYER_QUEUE_MULTIPART; LOG(LOGD_DTN, LOG_CL, LOGL_DBG, "Encoding multipart bundle %lu", ticket->bundle_number); /* Now allocate a buffer to serialize the bundle * The size is a rough estimation here and will be reallocated later on */ ret = mmem_alloc(&ticket->buffer, ticket->bundle->size); if( ret < 1 ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Multipart bundle %lu could not be encoded, not enough memory for %u bytes", ticket->bundle_number, ticket->bundle->size); ticket->flags &= ~CONVERGENCE_LAYER_QUEUE_MULTIPART; return -1; } /* Encode the bundle into our temporary buffer */ length = bundle_encode_bundle(ticket->bundle, (uint8_t *) MMEM_PTR(&ticket->buffer), ticket->buffer.size); if( length < 0 ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Multipart bundle %lu could not be encoded, error occured", ticket->bundle_number); mmem_free(&ticket->buffer); ticket->buffer.ptr = NULL; ticket->flags &= ~CONVERGENCE_LAYER_QUEUE_MULTIPART; return -1; } /* Decrease memory size to what is actually needed */ ret = mmem_realloc(&ticket->buffer, length); if( ret < 1 ) { LOG(LOGD_DTN, LOG_CL, LOGL_ERR, "Multipart bundle %lu could not be encoded, realloc failed", ticket->bundle_number); mmem_free(&ticket->buffer); ticket->buffer.ptr = NULL; ticket->flags &= ~CONVERGENCE_LAYER_QUEUE_MULTIPART; return -1; } /* We do not need the original bundle anymore */ bundle_decrement(ticket->bundle); ticket->bundle = NULL; /* Initialize the state for this bundle */ ticket->offset_sent = 0; ticket->offset_acked = 0; ticket->sequence_number = outgoing_sequence_number; /* Calculate the number of segments we will need */ segments = (length + 0.5 * CONVERGENCE_LAYER_MAX_LENGTH) / CONVERGENCE_LAYER_MAX_LENGTH; /* And reserve the sequence number space for this bundle to allow for consequtive numbers */ outgoing_sequence_number = (outgoing_sequence_number + segments) % 4; } /* Initialize the header field */ buffer[0] = CONVERGENCE_LAYER_TYPE_DATA & CONVERGENCE_LAYER_MASK_TYPE; /* Check if this is a multipart bundle */ if( ticket->flags & CONVERGENCE_LAYER_QUEUE_MULTIPART ) { /* Calculate the remaining length */ length = ticket->buffer.size - ticket->offset_acked; /* Is it possible, that we send a single-part bundle here because the heuristic * from above failed. So be it. */ if( length <= CONVERGENCE_LAYER_MAX_LENGTH && ticket->offset_acked == 0 ) { /* One bundle per segment, standard flags */ buffer[0] |= (CONVERGENCE_LAYER_FLAGS_FIRST | CONVERGENCE_LAYER_FLAGS_LAST) & CONVERGENCE_LAYER_MASK_FLAGS; } else if( ticket->offset_acked == 0 ) { /* First segment of a bundle */ buffer[0] |= CONVERGENCE_LAYER_FLAGS_FIRST & CONVERGENCE_LAYER_MASK_FLAGS; } else if( length <= CONVERGENCE_LAYER_MAX_LENGTH ) { /* Last segment of a bundle */ buffer[0] |= CONVERGENCE_LAYER_FLAGS_LAST & CONVERGENCE_LAYER_MASK_FLAGS; } else if( length > CONVERGENCE_LAYER_MAX_LENGTH) { /* A segment in the middle of a bundle */ buffer[0] &= ~CONVERGENCE_LAYER_MASK_FLAGS; } /* one byte for the CL header */ length += 1; if( length > CONVERGENCE_LAYER_MAX_LENGTH ) { length = CONVERGENCE_LAYER_MAX_LENGTH; } if( length > buffer_length ) { length = buffer_length; } /* Copy the subset of the bundle into the buffer */ memcpy(buffer + 1, ((uint8_t *) MMEM_PTR(&ticket->buffer)) + ticket->offset_acked, length - 1); /* Every segment so far has been acked */ if( ticket->offset_sent == ticket->offset_acked ) { /* It is the first time that we are sending this segment */ ticket->offset_sent += length - 1; /* Increment the sequence number for the new segment, except for the first segment */ if( ticket->offset_sent != 0 ) { ticket->sequence_number = (ticket->sequence_number + 1) % 4; } } } else { #endif /* CONVERGENCE_LAYER_SEGMENTATION */ /* one byte for the CL header */ length = 1; /* Initialize the header field */ buffer[0] = CONVERGENCE_LAYER_TYPE_DATA & CONVERGENCE_LAYER_MASK_TYPE; /* One bundle per segment, standard flags */ buffer[0] |= (CONVERGENCE_LAYER_FLAGS_FIRST | CONVERGENCE_LAYER_FLAGS_LAST) & CONVERGENCE_LAYER_MASK_FLAGS; /* Encode the bundle into the buffer */ length += bundle_encode_bundle(ticket->bundle, buffer + 1, buffer_length - 1); /* Initialize the sequence number */ ticket->sequence_number = outgoing_sequence_number; outgoing_sequence_number = (outgoing_sequence_number + 1) % 4; #if CONVERGENCE_LAYER_SEGMENTATION } #endif /* CONVERGENCE_LAYER_SEGMENTATION */ /* Put the sequence number for this bundle into the outgoing header */ buffer[0] |= (ticket->sequence_number << 2) & CONVERGENCE_LAYER_MASK_SEQNO; /* Flag the bundle as being in transit now */ ticket->flags |= CONVERGENCE_LAYER_QUEUE_IN_TRANSIT; /* Now we are transmitting */ convergence_layer_transmitting = 1; /* This neighbour is blocked, until we have received the App Layer ACK or NACK */ convergence_layer_set_blocked(&ticket->neighbour); /* And send it out */ dtn_network_send(&ticket->neighbour, length, (void *) ticket); return 1; }
/** * \brief Adds a new bundle to the list of bundles * \param bundle_number bundle number of the bundle * \return >0 on success, <0 on error */ int routing_chain_new_bundle(uint32_t * bundle_number) { struct routing_list_entry_t * n = NULL; struct routing_entry_t * entry = NULL; struct mmem * bundlemem = NULL; struct bundle_t * bundle = NULL; LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "agent announces bundle %lu", *bundle_number); // Let us see, if we know this bundle already for( n = list_head(routing_list); n != NULL; n = list_item_next(n) ) { entry = (struct routing_entry_t *) MMEM_PTR(&n->entry); if( entry->bundle_number == *bundle_number ) { LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "agent announces bundle %lu that is already known", *bundle_number); return -1; } } // Notify statistics statistics_bundle_incoming(1); // Now allocate new memory for the list entry n = memb_alloc(&routing_mem); if( n == NULL ) { LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "cannot allocate list entry for bundle, please increase BUNDLE_STORAGE_SIZE"); return -1; } memset(n, 0, sizeof(struct routing_list_entry_t)); // Now allocate new MMEM memory for the struct in the list if( !mmem_alloc(&n->entry, sizeof(struct routing_entry_t)) ) { LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "cannot allocate routing struct for bundle, MMEM is full"); memb_free(&routing_mem, n); return -1; } // Now go and request the bundle from storage bundlemem = BUNDLE_STORAGE.read_bundle(*bundle_number); if( bundlemem == NULL ) { LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "unable to read bundle %lu", *bundle_number); mmem_free(&n->entry); memb_free(&routing_mem, n); return -1; } // Get our bundle struct and check the pointer bundle = (struct bundle_t *) MMEM_PTR(bundlemem); if( bundle == NULL ) { LOG(LOGD_DTN, LOG_ROUTE, LOGL_ERR, "invalid bundle pointer for bundle %lu", *bundle_number); mmem_free(&n->entry); memb_free(&routing_mem, n); bundle_decrement(bundlemem); return -1; } // Now we have our entry // We have to get the pointer AFTER getting the bundle from storage, because accessing the // storage may change the MMEM structure and thus the pointers! entry = (struct routing_entry_t *) MMEM_PTR(&n->entry); memset(entry, 0, sizeof(struct routing_entry_t)); // Nothing can go wrong anymore, add the (surrounding) struct to the list list_add(routing_list, n); /* Here we decide if a bundle is to be delivered locally and/or forwarded */ if( bundle->dst_node == dtn_node_id ) { /* This bundle is for our node_id, deliver locally */ LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for local"); entry->flags |= ROUTING_FLAG_LOCAL; } else { /* This bundle is not (directly) for us and will be forwarded */ LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for forward"); entry->flags |= ROUTING_FLAG_FORWARD; } if( !(bundle->flags & BUNDLE_FLAG_SINGLETON) ) { /* Bundle is not Singleton, so forward it in any case */ LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for forward"); entry->flags |= ROUTING_FLAG_FORWARD; } if( registration_is_local(bundle->dst_srv, bundle->dst_node) && bundle->dst_node != dtn_node_id) { /* Bundle is for a local registration, so deliver it locally */ LOG(LOGD_DTN, LOG_ROUTE, LOGL_DBG, "bundle is for local and forward"); entry->flags |= ROUTING_FLAG_LOCAL; entry->flags |= ROUTING_FLAG_FORWARD; } // Now copy the necessary attributes from the bundle entry->bundle_number = *bundle_number; bundle_get_attr(bundlemem, DEST_NODE, &entry->destination_node); bundle_get_attr(bundlemem, SRC_NODE, &entry->source_node); linkaddr_copy(&entry->received_from_node, &bundle->msrc); // Now that we have the bundle, we do not need the allocated memory anymore bundle_decrement(bundlemem); bundlemem = NULL; bundle = NULL; // Schedule to deliver and forward the bundle routing_chain_schedule_resubmission(); // We do not have a failure here, so it must be a success return 1; }
PROCESS_THREAD(test_process, ev, data) { static int n; static int i; static int errors = 0; static struct etimer timer; static uint32_t time_start, time_stop; uint8_t buffer[128]; int bundle_length; struct mmem * bundle_original = NULL; struct mmem * bundle_restored = NULL; struct mmem * bundle_spare = NULL; uint32_t bundle_number; uint32_t bundle_number_spare; PROCESS_BEGIN(); PROCESS_PAUSE(); profiling_init(); profiling_start(); // Wait again etimer_set(&timer, CLOCK_SECOND); PROCESS_WAIT_UNTIL(etimer_expired(&timer)); /* Profile initialization separately */ profiling_stop(); watchdog_stop(); profiling_report("init", 0); watchdog_start(); printf("Init done, starting test using %s storage\n", BUNDLE_STORAGE.name); profiling_init(); profiling_start(); // Measure the current time time_start = test_precise_timestamp(); for(i=0; i<=1; i++) { struct mmem bla; if( i > 0 ) { mmem_alloc(&bla, 1); } printf("Serializing and deserializing bundle...\n"); if( my_create_bundle(0, &bundle_number, 3600) ) { printf("\tBundle created successfully \n"); } else { printf("\tBundle could not be created \n"); errors ++; } printf("Serializing and deserializing bundle...\n"); if( my_create_bundle(1, &bundle_number_spare, 3600) ) { printf("\tSpare Bundle created successfully \n"); } else { printf("\tSpare Bundle could not be created \n"); errors ++; } bundle_original = BUNDLE_STORAGE.read_bundle(bundle_number); if( bundle_original == NULL ) { printf("VERIFY: MMEM ptr is invalid\n"); errors ++; } bundle_spare = BUNDLE_STORAGE.read_bundle(bundle_number_spare); if( bundle_spare == NULL ) { printf("VERIFY: MMEM ptr is invalid\n"); errors ++; } // Fake timing information in the bundle to make verify successful struct bundle_t * bundle_original_bundle = (struct bundle_t *) MMEM_PTR(bundle_original); bundle_original_bundle->aeb_value_ms = 54; bundle_original_bundle->rec_time = clock_time(); // Serialize the bundle memset(buffer, 0, 128); bundle_length = bundle_encode_bundle(bundle_original, buffer, 128); if( bundle_length < 0 ) { printf("SERIALIZE: fail\n"); errors ++; } n = my_static_compare(buffer, bundle_length); if( n > 0 ) { printf("COMPARE: fail\n"); errors += n; } // Deserialize it bundle_restored = bundle_recover_bundle(buffer, bundle_length); if( bundle_restored == NULL ) { printf("DESERIALIZE: unable to recover\n"); errors ++; } n = my_compare_bundles(bundle_original, bundle_restored); if( n == 0 ) { printf("\tBundle serialized and deserialized successfully\n"); } else { printf("COMPARE: differences\n"); errors ++; } // Dellocate memory bundle_decrement(bundle_restored); bundle_restored = NULL; bundle_decrement(bundle_original); bundle_original = NULL; bundle_decrement(bundle_spare); bundle_spare = NULL; memset(buffer, 0, 128); // Delete bundle from storage n = BUNDLE_STORAGE.del_bundle(bundle_number, REASON_DELIVERED); if( n ) { printf("\tBundle deleted successfully\n"); } else { printf("\tBundle could not be deleted\n"); errors++; } printf("Comparing static bundle...\n"); if( my_create_bundle(0, &bundle_number, 3600) ) { printf("\tReference Bundle created successfully \n"); } else { printf("\ttReference Bundle could not be created \n"); errors ++; } bundle_original = BUNDLE_STORAGE.read_bundle(bundle_number); if( bundle_original == NULL ) { printf("VERIFY: MMEM ptr is invalid\n"); errors ++; } // Deserialize it bundle_restored = bundle_recover_bundle(static_compare_bundle, sizeof(static_compare_bundle)); if( bundle_restored == NULL ) { printf("DESERIALIZE: unable to recover static bundle\n"); errors ++; } // Deserialize it one more time bundle_spare = bundle_recover_bundle(static_compare_bundle, sizeof(static_compare_bundle)); if( bundle_spare == NULL ) { printf("DESERIALIZE: unable to recover static bundle\n"); errors ++; } n = my_compare_bundles(bundle_original, bundle_restored); if( n == 0 ) { printf("\tStatic Bundle verified successfully\n"); } else { printf("COMPARE: differences\n"); errors ++; } n = my_compare_bundles(bundle_original, bundle_spare); if( n == 0 ) { printf("\tStatic Bundle verified successfully\n"); } else { printf("COMPARE: differences\n"); errors ++; } // Dellocate memory bundle_decrement(bundle_restored); bundle_restored = NULL; bundle_decrement(bundle_original); bundle_original = NULL; bundle_decrement(bundle_spare); bundle_spare = NULL; } time_stop = test_precise_timestamp(); watchdog_stop(); profiling_report("serializer", 0); TEST_REPORT("No of errors", errors, 1, "errors"); TEST_REPORT("Duration", time_stop-time_start, CLOCK_SECOND, "s"); if( errors > 0 ) { TEST_FAIL("More than 0 errors occured"); } else { TEST_PASS(); } PROCESS_END(); }