void pt_process_instance(const void * node, VISIT visit, int level) { algorithm_instance_t * instance = *((algorithm_instance_t * const *) node); size_t i, num_events; uint64_t ret; ssize_t count; // Save temporarily this algorithm context instance->loop->cur_instance = instance; // Execute algorithm handler for events of each algorithm num_events = dynarray_get_size(instance->events); for (i = 0; i < num_events; i++) { event_t * event; count = read(instance->loop->eventfd_algorithm, &ret, sizeof(ret)); if (count == -1) return; event = dynarray_get_ith_element(instance->events, i); instance->algorithm->handler(instance->loop, event, &instance->data, instance->probe_skel, instance->options); } // Restore the algorithm context instance->loop->cur_instance = NULL; // Flush events queue algorithm_instance_clear_events(instance); }
static void network_flying_probes_dump(network_t * network) { size_t i, num_flying_probes = dynarray_get_size(network->probes); uint16_t tag_probe; probe_t * probe; printf("\n%u flying probe(s) :\n", (unsigned int)num_flying_probes); for (i = 0; i < num_flying_probes; i++) { probe = dynarray_get_ith_element(network->probes, i); probe_extract_tag(probe, &tag_probe) ? printf(" 0x%x", tag_probe): printf(" (invalid tag)"); printf("\n"); } }
bool network_drop_expired_flying_probe(network_t * network) { // Drop every expired probes size_t i, num_flying_probes = dynarray_get_size(network->probes); bool ret = false; probe_t * probe; // Is there flying probe(s) ? if (num_flying_probes > 0) { // Iterate on each expired probes (at least the oldest one has expired) for (i = 0 ;i < num_flying_probes; i++) { probe = dynarray_get_ith_element(network->probes, i); // Some probe may expires very soon and may expire before the next probe timeout // update. If so, the timer will be disarmed and libparistraceroute may freeze. // To avoid this kind of deadlock, we provoke a probe timeout for each probe // expiring in less that EXTRA_DELAY seconds. if (network_get_probe_timeout(network, probe) - EXTRA_DELAY > 0) break; // This probe has expired, raise a PROBE_TIMEOUT event. pt_throw(NULL, probe->caller, event_create(PROBE_TIMEOUT, probe, NULL, NULL)); //(ELEMENT_FREE) probe_free)); } // Delete the i oldest probes, which have expired. if (i != 0) { dynarray_del_n_elements(network->probes, 0, i, NULL); } ret = network_update_next_timeout(network); } else { fprintf(stderr, "network_drop_expired_flying_probe: a probe has expired, but there are no more flying probes!\n"); } return ret; }
static probe_t * network_get_matching_probe(network_t * network, const probe_t * reply) { // Suppose we perform a traceroute measurement thanks to IPv4/UDP packet // We encode in the IPv4 checksum the ID of the probe. // Then, we should sniff an IPv4/ICMP/IPv4/UDP packet. // The ICMP message carries the begining of our probe packet, so we can // retrieve the checksum (= our probe ID) of the second IP layer, which // corresponds to the 3rd checksum field of our probe. uint16_t tag_probe, tag_reply; probe_t * probe; size_t i, num_flying_probes; // XXX // Fetch the tag from the reply. Its the 3rd checksum field. if (!(reply_extract_tag(reply, &tag_reply))) { // This is not an IP / ICMP / IP / * reply :( if (network->is_verbose) fprintf(stderr, "Can't retrieve tag from reply\n"); return NULL; } num_flying_probes = dynarray_get_size(network->probes); for (i = 0; i < num_flying_probes; i++) { probe = dynarray_get_ith_element(network->probes, i); // Reply / probe comparison. In our probe packet, the probe ID // is stored in the checksum of the (first) IP layer. if (probe_extract_tag(probe, &tag_probe)) { if (tag_reply == tag_probe) break; } } /* // XXX BEGIN Harcoded ICMP response (JA 17/07/2014) tag_reply = 0; tag_probe = 0; tag_probe++; tag_reply++; num_flying_probes = dynarray_get_size(network->probes); for (i = 0; i < num_flying_probes; i++) { probe = dynarray_get_ith_element(network->probes, i); // Reply / probe comparison. In our probe packet, the probe ID // is stored in the checksum of the (first) IP layer. if (probe_match((const struct probe_s *)probe, (const struct probe_s *)reply)) break; } // XXX END Hardcoded ICMP response */ // No match found if we reached the end of the array if (i == num_flying_probes) { if (network->is_verbose) { fprintf(stderr, "network_get_matching_probe: This reply has been discarded: tag = 0x%x.\n", tag_reply); network_flying_probes_dump(network); } return NULL; } // We delete the corresponding probe // TODO: ... but it should be kept, for archive purposes, and to match for duplicates... // But we cannot reenable it until we set the probe ID into the // checksum, since probes with same flow_id and different TTL have the // same checksum dynarray_del_ith_element(network->probes, i, NULL); // The matching probe is the oldest one and there are other probes, update // the timer according to the next unexpired probe timeout. if (i == 0) { if (!(network_update_next_timeout(network))) { fprintf(stderr, "Error while updating timeout\n"); } } return probe; }
static probe_t * network_get_oldest_probe(const network_t * network) { return dynarray_get_ith_element(network->probes, 0); }
layer_t * probe_get_layer(const probe_t * probe, size_t i) { return dynarray_get_ith_element(probe->layers, i); }