Beispiel #1
0
void
do_resend()
{
    struct resend *resend;

    resend = to_resend;
    while(resend) {
        if(!resend_expired(resend) && resend->delay > 0 && resend->max > 0) {
            struct timeval timeout;
            timeval_add_msec(&timeout, &resend->time, resend->delay);
            if(timeval_compare(&now, &timeout) >= 0) {
                switch(resend->kind) {
                case RESEND_REQUEST:
                    send_multihop_request(resend->ifp,
                                          resend->prefix, resend->plen,
                                          resend->src_prefix, resend->src_plen,
                                          resend->seqno, resend->id, 127);
                    break;
                case RESEND_UPDATE:
                    send_update(resend->ifp, 1,
                                resend->prefix, resend->plen,
                                resend->src_prefix, resend->src_plen);
                    break;
                default: abort();
                }
                resend->delay = MIN(0xFFFF, resend->delay * 2);
                resend->max--;
            }
        }
        resend = resend->next;
    }
    recompute_resend_time();
}
Beispiel #2
0
void
recompute_resend_time()
{
    struct resend *request;
    struct timeval resend = {0, 0};

    request = to_resend;
    while(request) {
        if(!resend_expired(request) && request->delay > 0 && request->max > 0) {
            struct timeval timeout;
            timeval_add_msec(&timeout, &request->time, request->delay);
            timeval_min(&resend, &timeout);
        }
        request = request->next;
    }

    resend_time = resend;
}
Beispiel #3
0
/* We got a Hello or IHU from a neighbour, update its entry. */
int
update_neighbour(struct in6_addr *from, struct interface *interface,
                 unsigned int ihu, unsigned short interval_or_rxcost)
{
    int i = find_neighbour(interface, from, !ihu);
    if(i < 0)
        return 0;

    if(ihu) {
        neighbours[i].rxcost = interval_or_rxcost;
    } else {
        struct timeval now;
        int interval = interval_or_rxcost;
        gettime(&now);
        /* We'll expire this neighbour if we miss 3 Hellos in a row. */
        timeval_add_msec(&neighbours[i].timeout, &now,
                         3 * interval * 10 + rand() % (interval * 5));
    }
    return 1;
}
Beispiel #4
0
/* We just got an Update for the default route. */
int
update_selected_route(struct interface *interface, struct in6_addr *nexthop,
                      short interval, int metric)
{
    struct timeval now;
    int n = find_neighbour(interface, nexthop, 0);

    if(n < 0)
        return 0;

    metric += MAX(link_cost, neighbours[n].rxcost);

    gettime(&now);

    if(selected_nexthop_metric >= INFINITY ||
       interface != selected_interface ||
       memcmp(nexthop, &selected_nexthop, sizeof(selected_nexthop)) != 0) {
        int rc;
        if(metric >= INFINITY ||
           (metric >= selected_nexthop_metric + 32 &&
            timeval_compare(&now, &selected_nexthop_timeout) < 0)) {
            /* Our currently selected route is just as good or better. */
            return 0;
        }

        rc = install_default_route(interface->ifindex, nexthop);
        if(rc < 0) {
            perror("install_default_route");
            return -1;
        }
        selected_interface = interface;
        memcpy(&selected_nexthop, nexthop, sizeof(selected_nexthop));
    }

    selected_nexthop_metric = metric;
    /* Expire this route when we lose 3 updates in a row. */
    timeval_add_msec(&selected_nexthop_timeout, &now,
                     3 * interval * 10 + rand() % (interval * 5));

    return 1;
}
Beispiel #5
0
static void *helper_thread_main(void *data)
{
	struct helper_data *hd = data;
	unsigned int msec_to_next_event, next_log;
	struct timeval tv, last_du;
	int ret = 0;

	sk_out_assign(hd->sk_out);

	gettimeofday(&tv, NULL);
	memcpy(&last_du, &tv, sizeof(tv));

	fio_mutex_up(hd->startup_mutex);

	msec_to_next_event = DISK_UTIL_MSEC;
	while (!ret && !hd->exit) {
		struct timespec ts;
		struct timeval now;
		uint64_t since_du;

		timeval_add_msec(&tv, msec_to_next_event);
		ts.tv_sec = tv.tv_sec;
		ts.tv_nsec = tv.tv_usec * 1000;

		pthread_mutex_lock(&hd->lock);
		pthread_cond_timedwait(&hd->cond, &hd->lock, &ts);

		gettimeofday(&now, NULL);

		if (hd->reset) {
			memcpy(&tv, &now, sizeof(tv));
			memcpy(&last_du, &now, sizeof(last_du));
			hd->reset = 0;
		}

		pthread_mutex_unlock(&hd->lock);

		since_du = mtime_since(&last_du, &now);
		if (since_du >= DISK_UTIL_MSEC || DISK_UTIL_MSEC - since_du < 10) {
			ret = update_io_ticks();
			timeval_add_msec(&last_du, DISK_UTIL_MSEC);
			msec_to_next_event = DISK_UTIL_MSEC;
			if (since_du >= DISK_UTIL_MSEC)
				msec_to_next_event -= (since_du - DISK_UTIL_MSEC);
		} else {
			if (since_du >= DISK_UTIL_MSEC)
				msec_to_next_event = DISK_UTIL_MSEC - (DISK_UTIL_MSEC - since_du);
			else
				msec_to_next_event = DISK_UTIL_MSEC;
		}

		if (hd->do_stat) {
			hd->do_stat = 0;
			__show_running_run_stats();
		}

		next_log = calc_log_samples();
		if (!next_log)
			next_log = DISK_UTIL_MSEC;

		msec_to_next_event = min(next_log, msec_to_next_event);

		if (!is_backend)
			print_thread_status();
	}

	fio_writeout_logs(false);

	sk_out_drop();
	return NULL;
}
Beispiel #6
0
int
record_resend(int kind, const unsigned char *prefix, unsigned char plen,
              const unsigned char *src_prefix, unsigned char src_plen,
              unsigned short seqno, const unsigned char *id,
              struct interface *ifp, int delay)
{
    struct resend *resend;
    unsigned int ifindex = ifp ? ifp->ifindex : 0;

    if((kind == RESEND_REQUEST &&
        input_filter(NULL, prefix, plen, src_prefix, src_plen, NULL,
                     ifindex) >=
        INFINITY) ||
       (kind == RESEND_UPDATE &&
        output_filter(NULL, prefix, plen, src_prefix, src_plen, ifindex) >=
        INFINITY))
        return 0;

    if(delay >= 0xFFFF)
        delay = 0xFFFF;

    resend = find_resend(kind, prefix, plen, src_prefix, src_plen, NULL);
    if(resend) {
        if(resend->delay && delay)
            resend->delay = MIN(resend->delay, delay);
        else if(delay)
            resend->delay = delay;
        resend->time = now;
        resend->max = RESEND_MAX;
        if(id && memcmp(resend->id, id, 8) == 0 &&
           seqno_compare(resend->seqno, seqno) > 0) {
            return 0;
        }
        if(id)
            memcpy(resend->id, id, 8);
        else
            memset(resend->id, 0, 8);
        resend->seqno = seqno;
        if(resend->ifp != ifp)
            resend->ifp = NULL;
    } else {
        resend = calloc(1, sizeof(struct resend));
        if(resend == NULL)
            return -1;
        resend->kind = kind;
        resend->max = RESEND_MAX;
        resend->delay = delay;
        memcpy(resend->prefix, prefix, 16);
        resend->plen = plen;
        memcpy(resend->src_prefix, src_prefix, 16);
        resend->src_plen = src_plen;
        resend->seqno = seqno;
        if(id)
            memcpy(resend->id, id, 8);
        resend->ifp = ifp;
        resend->time = now;
        resend->next = to_resend;
        to_resend = resend;
    }

    if(resend->delay) {
        struct timeval timeout;
        timeval_add_msec(&timeout, &resend->time, resend->delay);
        timeval_min(&resend_time, &timeout);
    }
    return 1;
}
Beispiel #7
0
void
set_timeout(struct timeval *timeout, int msecs)
{
    timeval_add_msec(timeout, &now, roughly(msecs));
}
Beispiel #8
0
int
main(int argc, char **argv)
{
    int i, opt, rc;
    int sock;
    struct timeval now;

    gettime(&now);

    inet_pton(AF_INET6, "ff02::1:6", &babel_group);
    babel_port = 6696;

    srand(now.tv_sec ^ now.tv_usec);

    while(1) {
        opt = getopt(argc, argv, "p:u:h:c:");
        if(opt < 0)
            break;

        switch(opt) {
        case 'p':               /* prefix */
            if(have_prefix)
                goto usage;
            rc = inet_pton(AF_INET6, optarg, &myprefix);
            if(rc != 1)
                goto usage;
            have_prefix = 1;
            break;
        case 'u':               /* update interval */
            update_interval = atoi(optarg);
            if(update_interval <= 0)
                goto usage;
            break;
        case 'h':               /* hello interval */
            hello_interval = atoi(optarg);
            if(hello_interval <= 0)
                goto usage;
            break;
        case 'c':               /* link cost */
            link_cost = atoi(optarg);
            if(link_cost <= 0)
                goto usage;
            break;
        default:
            goto usage;
        }
    }

    if(!have_prefix)
        fprintf(stderr, "Warning: you didn't ask me to announce a prefix.\n");

    if(argc - optind > MAXINTERFACES) {
        fprintf(stderr, "Too many interfaces.\n");
        exit(1);
    }

    for(i = 0; i < argc - optind; i++) {
        int index;

        index = if_nametoindex(argv[optind + i]);
        if(index <= 0) {
            fprintf(stderr, "Unknown interface %s\n", argv[i]);
            exit(1);
        }
        memset(&interfaces[i], 0, sizeof(interfaces[i]));
        interfaces[i].ifindex = index;
        interfaces[i].ifname = argv[optind + i];
        rc = get_local_address(interfaces[i].ifindex, &interfaces[i].address);
        if(rc < 0) {
            perror("get_local_address");
            fprintf(stderr, "Continuing anyway -- "
                    "won't perform reachibility detection "
                    "on interface %s.\n", interfaces[i].ifname);
        }
        interfaces[i].seqno = rand() & 0xFFFF;
    }
    numinterfaces = argc - optind;

    random_eui64(my_router_id);
    myseqno = rand() & 0xFFFF;

    sock = babel_socket(babel_port);
    if(sock < 0) {
        perror("babel_socket");
        exit(1);
    }

    for(i = 0; i < numinterfaces; i++) {
        rc = join_group(sock, interfaces[i].ifindex, &babel_group);
        if(rc < 0) {
            perror("setsockopt(IPV6_JOIN_GROUP)");
            exit(1);
        }
    }

    catch_signals(sigexit);

    while(!exiting) {
        struct sockaddr_in6 sin6;
        unsigned char buf[BUF_SIZE];
        struct timeval tv, update, zerotv = {0, 0};
        fd_set readfds;
        int hello_count = 0;

        /* Compute when to wake up. */
        gettime(&now);
        timeval_add_msec(&tv, &last_hello, hello_interval * 700 + rand() % 300);
        timeval_add_msec(&update, &last_update,
                         update_interval * 700 + rand() % 300);
        timeval_min(&tv, &update);

        if(selected_nexthop_metric < INFINITY) {
            int n = find_neighbour(selected_interface, &selected_nexthop, 0);
            assert(n >= 0);
            timeval_min(&tv, &neighbours[n].timeout);
            timeval_min(&tv, &selected_nexthop_timeout);
        }

        if(timeval_compare(&tv, &now) > 0)
            timeval_minus(&tv, &tv, &now);
        else
            tv = zerotv;

        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);

        rc = select(sock + 1, &readfds, NULL, NULL, &tv);
        if(rc < 0 && errno != EINTR) {
            perror("select");
            nap(1000);
            continue;
        }

        if(rc > 0) {
            /* Oh good, a packet. */
            socklen_t sin6len = sizeof(sin6);
            rc = recvfrom(sock, buf, BUF_SIZE, 0,
                          (struct sockaddr*)&sin6, &sin6len);

            if(rc < 0 || rc >= BUF_SIZE) {
                if(rc < 0 && errno != EAGAIN) {
                    perror("recv");
                    nap(100);
                }
                continue;
            }

            if(sin6.sin6_family != PF_INET6) {
                fprintf(stderr, "Received unexpected packet in family %d.\n",
                        sin6.sin6_family);
                nap(100);
                continue;
            }

            i = find_interface(sin6.sin6_scope_id);
            if(i < 0) {
                fprintf(stderr, "Received packet on unknown interface %d.\n",
                        sin6.sin6_scope_id);
                nap(100);
                continue;
            }
            handle_packet(sock, buf, rc, &interfaces[i], &sin6.sin6_addr);
        }

        gettime(&now);

        if(selected_nexthop_metric < INFINITY) {
            int n = find_neighbour(selected_interface, &selected_nexthop, 0);
            assert(n >= 0);

            if(neighbour_expired(n, &now)) {
                /* Expire neighbour. */
                flush_default_route();
                delete_neighbour(n);
            } else if(timeval_compare(&now, &selected_nexthop_timeout) > 0) {
                /* Expire route. */
                flush_default_route();
            }
            /* Send a request? */
        }

        /* Is it time to send hellos? */
        if(timeval_minus_msec(&now, &last_hello) > hello_interval * 700) {
            for(i = 0; i < numinterfaces; i++)
                send_hello(sock, &interfaces[i]);
            last_hello = now;
            hello_count++;
            /* Make an expiry pass every ten hellos. */
            if(hello_count >= 10) {
                expire_neighbours();
                hello_count = 0;
            }
        }

        /* Is it time to send an update? */
        if(timeval_minus_msec(&now, &last_update) > update_interval * 700) {
            for(i = 0; i < numinterfaces; i++)
                send_update(sock, &interfaces[i], 0);
            last_update = now;
        }
    }

    /* Send a bunch of retractions. */
    for(i = 0; i < numinterfaces; i++)
        send_update(sock, &interfaces[i], 1);

    flush_default_route();

    return 0;

 usage:
    fprintf(stderr,
            "Usage: sbabeld "
            "[-p prefix] [-u interval] [-h interval] [-c cost] interface...\n");
    return 1;
}