Beispiel #1
0
int netem_set_params(const char *iface, struct netem_params *params)
{
	struct rtnl_link *link;
	struct rtnl_qdisc *qdisc;
	int err;

	pthread_mutex_lock(&nl_sock_mutex);

	/* filter link by name */
	if ((link = rtnl_link_get_by_name(link_cache, iface)) == NULL) {
		fprintf(stderr, "unknown interface/link name.\n");
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	if (!(qdisc = rtnl_qdisc_alloc())) {
		/* OOM error */
		fprintf(stderr, "couldn't alloc qdisc\n");
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	rtnl_tc_set_link(TC_CAST(qdisc), link);
	rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
	rtnl_tc_set_kind(TC_CAST(qdisc), "netem");

	rtnl_netem_set_delay(qdisc,
	                     params->delay * 1000); /* expects microseconds */
	rtnl_netem_set_jitter(qdisc, params->jitter * 1000);
	/* params->loss is given in 10ths of a percent */
	rtnl_netem_set_loss(qdisc, (params->loss * (UINT_MAX / 1000)));

	/* Submit request to kernel and wait for response */
	err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE | NLM_F_REPLACE);

	/* Return the qdisc object to free memory resources */
	rtnl_qdisc_put(qdisc);

	if (err < 0) {
		fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err));
		pthread_mutex_unlock(&nl_sock_mutex);
		return err;
	}

	if ((err = nl_cache_refill(sock, link_cache)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n",
		        nl_geterror(err));
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	pthread_mutex_unlock(&nl_sock_mutex);
	return 0;
}
Beispiel #2
0
static int dist_load(int argc, char *argv[])
{
	FILE *fp;
	double mu, sigma, rho;

	if (argc == 1) {
		if (!(fp = fopen(argv[0], "r")))
			error(-1, errno, "Failed to open file: %s", argv[0]);
	}
	else
		fp = stdin;

	short *inverse = dist_make(fp, &mu, &sigma, &rho);
	if (!inverse)
		error(-1, 0, "Failed to generate distribution");
	
	int ret;

	struct nl_sock *sock;
	
	struct rtnl_link *link;
	struct rtnl_tc *qdisc_prio = NULL;
	struct rtnl_tc *qdisc_netem = NULL;
	struct rtnl_tc *cls_fw = NULL;

	/* Create connection to netlink */
	sock = nl_socket_alloc();
	nl_connect(sock, NETLINK_ROUTE);
	
	/* Get interface */
	link = tc_get_link(sock, cfg.dev);
	if (!link)
		error(-1, 0, "Interface does not exist: %s", cfg.dev);
	
	/* Reset TC subsystem */
	ret = tc_reset(sock, link);
	if (ret && ret != -NLE_OBJ_NOTFOUND)
		error(-1, 0, "Failed to reset TC: %s", nl_geterror(ret));
	
	/* Setup TC subsystem */
	if ((ret = tc_prio(sock, link, &qdisc_prio)))
		error(-1, 0, "Failed to setup TC: prio qdisc: %s", nl_geterror(ret));

	if ((ret = tc_classifier(sock, link, &cls_fw, cfg.mark, cfg.mask)))
		error(-1, 0, "Failed to setup TC: fw filter: %s", nl_geterror(ret));
	
	if ((ret = tc_netem(sock, link, &qdisc_netem)))
		error(-1, 0, "Failed to setup TC: netem qdisc: %s", nl_geterror(ret));
	
	/* We will use the default normal distribution for now */
	if (rtnl_netem_set_delay_distribution_data((struct rtnl_qdisc *) qdisc_netem, inverse, TABLESIZE))
		error(-1, 0, "Failed to set netem delay distrubtion: %s", nl_geterror(ret));
	
	rtnl_netem_set_delay((struct rtnl_qdisc *) qdisc_netem, mu);
	rtnl_netem_set_jitter((struct rtnl_qdisc *) qdisc_netem, sigma);	

	nl_close(sock);
	nl_socket_free(sock);

	return 0;
}