Example #1
0
static void print_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct rtnl_qdisc *qdisc;

	ifindex = rtnl_link_get_ifindex(link);
	dump_params.dp_prefix = 0;
	nl_object_dump(obj, &dump_params);

	class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
	if (!class_cache)
		return;

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
	if (qdisc) {
		print_qdisc((struct nl_object *) qdisc, (void *) 2);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
	if (qdisc) {
		print_qdisc((struct nl_object *) qdisc, (void *) 2);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
	if (qdisc) {
		print_qdisc((struct nl_object *) qdisc, (void *) 2);
		rtnl_qdisc_put(qdisc);
	}

	nl_cache_free(class_cache);
}
Example #2
0
TError TNlHtb::Create(const TNlLink &link, uint32_t defaultClass) {
    TError error = TError::Success();
    int ret;
    struct rtnl_qdisc *qdisc;

    qdisc = rtnl_qdisc_alloc();
    if (!qdisc)
        return TError(EError::Unknown, std::string("Unable to allocate qdisc object"));

    rtnl_tc_set_ifindex(TC_CAST(qdisc), link.GetIndex());
    rtnl_tc_set_parent(TC_CAST(qdisc), Parent);
    rtnl_tc_set_handle(TC_CAST(qdisc), Handle);

    ret = rtnl_tc_set_kind(TC_CAST(qdisc), "htb");
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to set qdisc type: ") + nl_geterror(ret));
        goto free_qdisc;
    }

    rtnl_htb_set_defcls(qdisc, TC_H_MIN(defaultClass));
    rtnl_htb_set_rate2quantum(qdisc, 10);

    link.Dump("add", qdisc);

    ret = rtnl_qdisc_add(link.GetSock(), qdisc, NLM_F_CREATE);
    if (ret < 0)
        error = TError(EError::Unknown, std::string("Unable to add qdisc: ") + nl_geterror(ret));

free_qdisc:
    rtnl_qdisc_put(qdisc);

    return error;
}
Example #3
0
bool TNlHtb::Valid(const TNlLink &link, uint32_t defaultClass) {
    int ret;
    struct nl_cache *qdiscCache;
    bool valid = true;

    ret = rtnl_qdisc_alloc_cache(link.GetSock(), &qdiscCache);
    if (ret < 0) {
        L_ERR() << "can't alloc qdisc cache" << std::endl;
        return false;
    }

    struct rtnl_qdisc *qdisc = rtnl_qdisc_get(qdiscCache, link.GetIndex(), Handle);
    if (qdisc) {
        link.Dump("found", qdisc);
        if (rtnl_tc_get_ifindex(TC_CAST(qdisc)) != link.GetIndex())
            valid = false;
        else if (rtnl_tc_get_parent(TC_CAST(qdisc)) != Parent)
            valid = false;
        else if (rtnl_tc_get_handle(TC_CAST(qdisc)) != Handle)
            valid = false;
        else if (rtnl_tc_get_kind(TC_CAST(qdisc)) != std::string("htb"))
            valid = false;
        else if (rtnl_htb_get_defcls(qdisc) != TC_H_MIN(defaultClass))
            valid = false;
    } else {
        valid = false;
    }

    rtnl_qdisc_put(qdisc);
    nl_cache_free(qdiscCache);

    return valid;
}
Example #4
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;
}
Example #5
0
static void list_qdiscs(int ifindex, uint32_t parent)
{
	struct nl_cache *qdisc_cache;
	struct rtnl_qdisc *filter = nl_cli_qdisc_alloc();

	qdisc_cache = nl_cli_qdisc_alloc_cache(sock);

	rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex);
	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
	params.dp_prefix += NUM_INDENT;
	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), list_qdisc, NULL);
	params.dp_prefix -= NUM_INDENT;

	rtnl_qdisc_put(filter);
	nl_cache_free(qdisc_cache);
}
Example #6
0
TError TNlHtb::Remove(const TNlLink &link) {
    struct rtnl_qdisc *qdisc;

    qdisc = rtnl_qdisc_alloc();
    if (!qdisc)
        return TError(EError::Unknown, std::string("Unable to allocate qdisc object"));

    rtnl_tc_set_ifindex(TC_CAST(qdisc), link.GetIndex());
    rtnl_tc_set_parent(TC_CAST(qdisc), Parent);

    link.Dump("remove", qdisc);

    rtnl_qdisc_delete(link.GetSock(), qdisc);
    rtnl_qdisc_put(qdisc);

    return TError::Success();
}
Example #7
0
bool TNlHtb::Exists(const TNlLink &link) {
    int ret;
    struct nl_cache *qdiscCache;
    bool exists;

    ret = rtnl_qdisc_alloc_cache(link.GetSock(), &qdiscCache);
    if (ret < 0)
        return false;

    link.LogCache(qdiscCache);

    struct rtnl_qdisc *qdisc = rtnl_qdisc_get(qdiscCache, link.GetIndex(), Handle);
    exists = qdisc != nullptr;
    rtnl_qdisc_put(qdisc);
    nl_cache_free(qdiscCache);

    return exists;
}
Example #8
0
static int qdisc_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
			    struct nlmsghdr *n, struct nl_parser_param *pp)
{
	struct rtnl_qdisc *qdisc;
	int err;

	if (!(qdisc = rtnl_qdisc_alloc()))
		return -NLE_NOMEM;

	if ((err = rtnl_tc_msg_parse(n, TC_CAST(qdisc))) < 0)
		goto errout;

	err = pp->pp_cb(OBJ_CAST(qdisc), pp);
errout:
	rtnl_qdisc_put(qdisc);

	return err;
}
Example #9
0
TError TNlQdisc::Delete(const TNl &nl) {
    struct rtnl_qdisc *qdisc;
    int ret;

    qdisc = rtnl_qdisc_alloc();
    if (!qdisc)
        return TError(EError::Unknown, std::string("Unable to allocate qdisc object"));

    rtnl_tc_set_ifindex(TC_CAST(qdisc), Index);
    rtnl_tc_set_parent(TC_CAST(qdisc), Parent);

    nl.Dump("remove", qdisc);
    ret = rtnl_qdisc_delete(nl.GetSock(), qdisc);
    rtnl_qdisc_put(qdisc);
    if (ret < 0)
        return nl.Error(ret, "Cannot remove qdisc");

    return TError::Success();
}
Example #10
0
bool TNlQdisc::Check(const TNl &nl) {
    struct nl_cache *qdiscCache;
    bool result = false;
    int ret;

    ret = rtnl_qdisc_alloc_cache(nl.GetSock(), &qdiscCache);
    if (ret < 0) {
        L_ERR() <<  nl.Error(ret, "cannot alloc qdisc cache") << std::endl;
        return false;
    }

    struct rtnl_qdisc *qdisc = rtnl_qdisc_get(qdiscCache, Index, Handle);
    if (!qdisc) {
        result = Kind == "";
        goto out;
    }

    nl.Dump("found", qdisc);
    if (rtnl_tc_get_ifindex(TC_CAST(qdisc)) != Index)
        goto out;

    if (rtnl_tc_get_parent(TC_CAST(qdisc)) != Parent)
        goto out;

    if (rtnl_tc_get_handle(TC_CAST(qdisc)) != Handle)
        goto out;

    if (rtnl_tc_get_kind(TC_CAST(qdisc)) != Kind)
        goto out;

    if (Kind == "htb") {
        if (rtnl_htb_get_defcls(qdisc) != Default)
            goto out;
    }

    result = true;

out:
    rtnl_qdisc_put(qdisc);
    nl_cache_free(qdiscCache);
    return result;
}
/*
 * function that adds a new ingress qdisc and set the default class for unclassified traffic
 */
static
int qdisc_add_ingress(struct nl_sock *sock, struct rtnl_link *rtnlLink)
{
    
    struct rtnl_qdisc *qdisc;
    int err;
    
    /* Allocation of a qdisc object */
    if (!(qdisc = rtnl_qdisc_alloc())) {
        printf("Can not allocate Qdisc\n");
	return -1;
    }

    //rtnl_tc_set_ifindex(TC_CAST(qdisc), master_index);
    rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink);
    rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);

    //printf("Delete current qdisc\n");
    rtnl_qdisc_delete(sock, qdisc);
    //rtnl_qdisc_put(qdisc);

    rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(0xffff, 0));

    if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "ingress"))) {
        printf("Can not allocate ingress\n");
	return -1;
    }

    /* Submit request to kernel and wait for response */
    if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) {
        printf("Can not allocate ingress Qdisc\n");
	return -1;
    }

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

    return 0;
}
int main(int argc, char *argv[])
{
	struct nl_sock *nlh;
	struct rtnl_qdisc *qdisc;
	uint32_t handle, parent;
	int err = 1;

	if (nltool_init(argc, argv) < 0)
		return -1;

	if (argc < 5 || !strcmp(argv[1], "-h"))
		print_usage();

	nlh = nltool_alloc_handle();
	if (!nlh)
		goto errout;

	qdisc = rtnl_qdisc_alloc();
	if (!qdisc)
		goto errout_free_handle;

	rtnl_qdisc_set_ifindex(qdisc, strtoul(argv[1], NULL, 0));

	if (rtnl_tc_str2handle(argv[2], &handle) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout_free_qdisc;
	}

	if (rtnl_tc_str2handle(argv[3], &parent) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout_free_qdisc;
	}

	rtnl_qdisc_set_handle(qdisc, handle);
	rtnl_qdisc_set_parent(qdisc, parent);
	rtnl_qdisc_set_kind(qdisc, argv[4]);

	if (!strcasecmp(argv[4], "blackhole"))
		err = parse_blackhole_opts(qdisc, &argv[5], argc-5);
	else if (!strcasecmp(argv[4], "pfifo"))
		err = parse_pfifo_opts(qdisc, &argv[5], argc-5);
	else if (!strcasecmp(argv[4], "bfifo"))
		err = parse_bfifo_opts(qdisc, &argv[5], argc-5);
	else if (!strcasecmp(argv[4], "prio"))
		err = parse_prio_opts(qdisc, &argv[5], argc-5);
	else {
		fprintf(stderr, "Unknown qdisc \"%s\"\n", argv[4]);
		goto errout_free_qdisc;
	}

	if (err < 0)
		goto errout_free_qdisc;

	if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
		goto errout_free_qdisc;

	if (rtnl_qdisc_add(nlh, qdisc, NLM_F_REPLACE) < 0) {
		fprintf(stderr, "Unable to add Qdisc: %s\n", nl_geterror());
		goto errout_close;
	}

	err = 0;
errout_close:
	nl_close(nlh);
errout_free_qdisc:
	rtnl_qdisc_put(qdisc);
errout_free_handle:
	nl_handle_destroy(nlh);
errout:
	return err;
}
Example #13
0
inline void cleanup(struct rtnl_qdisc* qdisc) { rtnl_qdisc_put(qdisc); }
Example #14
0
int netem_get_params(char *iface, struct netem_params *params)
{
	struct rtnl_link *link;
	struct rtnl_qdisc *filter_qdisc;
	struct rtnl_qdisc *found_qdisc = NULL;
	int err;
	int delay, jitter, loss;

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

	if ((err = nl_cache_refill(sock, qdisc_cache)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n",
		        nl_geterror(err));
		goto cleanup;
	}

	/* filter link by name */
	if ((link = rtnl_link_get_by_name(link_cache, iface)) == NULL) {
		fprintf(stderr, "unknown interface/link name.\n");
		goto cleanup;
	}

	if (!(filter_qdisc = rtnl_qdisc_alloc())) {
		/* OOM error */
		fprintf(stderr, "couldn't alloc qdisc\n");
		goto cleanup_link;
	}

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

	found_qdisc = (struct rtnl_qdisc *)nl_cache_find(
	    qdisc_cache, OBJ_CAST(filter_qdisc));
	if (!found_qdisc) {
		/* The iface probably doesn't have a netem qdisc at startup. */
		goto cleanup_filter_qdisc;
	}

	if (0 > (delay = rtnl_netem_get_delay(found_qdisc))) {
		fprintf(stderr, "couldn't get delay for iface: %s\n", iface);
		goto cleanup_qdisc;
	}
	params->delay = (double)delay / 1000;

	if (0 > (jitter = rtnl_netem_get_jitter(found_qdisc))) {
		fprintf(stderr, "couldn't get jitter for iface: %s\n", iface);
		goto cleanup_qdisc;
	}
	params->jitter = (double)jitter / 1000;

	if (0 > (loss = rtnl_netem_get_loss(found_qdisc))) {
		fprintf(stderr, "couldn't get loss for iface: %s\n", iface);
		goto cleanup_qdisc;
	}
	/* loss is specified in 10ths of a percent, ie. 1 ==> 0.1% */
	params->loss = (int)(loss / (UINT_MAX / 1000));

	rtnl_qdisc_put(found_qdisc);
	rtnl_qdisc_put(filter_qdisc);
	rtnl_link_put(link);
	pthread_mutex_unlock(&nl_sock_mutex);
	return 0;

cleanup_qdisc:
	rtnl_qdisc_put(found_qdisc);
cleanup_filter_qdisc:
	rtnl_qdisc_put(filter_qdisc);
cleanup_link:
	rtnl_link_put(link);
cleanup:
	pthread_mutex_unlock(&nl_sock_mutex);
	return -1;
}
Example #15
0
static void handle_class(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "class", rdata)))
		return;

	ndata.parent = e;

	if (!strcmp(rtnl_tc_get_kind(tc), "htb"))
		element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));

	find_classes(rtnl_tc_get_handle(tc), &ndata);
	find_qdiscs(rtnl_tc_get_handle(tc), &ndata);
}

static void find_qdiscs(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_qdisc *filter;

	if (!(filter = rtnl_qdisc_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
				handle_qdisc, rdata);

	rtnl_qdisc_put(filter);
}

static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata)
{
	struct nl_cache *cls_cache;

	if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0)
		return;

	nl_cache_foreach(cls_cache, handle_cls, rdata);

	nl_cache_free(cls_cache);
}

static void find_classes(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_class *filter;

	if (!(filter = rtnl_class_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter),
				handle_class, rdata);

	rtnl_class_put(filter);
}

static void handle_qdisc(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "qdisc", rdata)))
		return;

	ndata.parent = e;

	find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);

	if (rtnl_tc_get_parent(tc) == TC_H_ROOT) {
		find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata);
		find_classes(TC_H_ROOT, &ndata);
	}

	find_classes(rtnl_tc_get_handle(tc), &ndata);
}

static void handle_tc(struct element *e, struct rtnl_link *link)
{
	struct rtnl_qdisc *qdisc;
	int ifindex = rtnl_link_get_ifindex(link);
	struct rdata rdata = {
		.level = 1,
		.parent = e,
	};

	if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
		return;

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	nl_cache_free(class_cache);
}

static void update_link_infos(struct element *e, struct rtnl_link *link)
{
	char buf[64];

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link));
	element_update_info(e, "MTU", buf);

	rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf));
	element_update_info(e, "Flags", buf);

	rtnl_link_operstate2str(rtnl_link_get_operstate(link),
				buf, sizeof(buf));
	element_update_info(e, "Operstate", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link));
	element_update_info(e, "IfIndex", buf);

	nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf));
	element_update_info(e, "Address", buf);

	nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf));
	element_update_info(e, "Broadcast", buf);

	rtnl_link_mode2str(rtnl_link_get_linkmode(link),
			   buf, sizeof(buf));
	element_update_info(e, "Mode", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link));
	element_update_info(e, "TXQlen", buf);

	nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf));
	element_update_info(e, "Family", buf);

	element_update_info(e, "Alias",
		rtnl_link_get_ifalias(link) ? : "");

	element_update_info(e, "Qdisc",
		rtnl_link_get_qdisc(link) ? : "");

	if (rtnl_link_get_link(link)) {
		snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link));
		element_update_info(e, "SlaveOfIndex", buf);
	}
}

static void do_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct element *e, *e_parent = NULL;
	int i, master_ifindex;

	if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) {
		/* FIXME: delete element */
		return;
	}

	/* Check if the interface is a slave of another interface */
	if ((master_ifindex = rtnl_link_get_link(link))) {
		char parent[IFNAMSIZ+1];

		rtnl_link_i2name(link_cache, master_ifindex,
				 parent, sizeof(parent));

		e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0);
	}

	if (!(e = element_lookup(grp, rtnl_link_get_name(link),
				 rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT)))
		return;

	if (e->e_flags & ELEMENT_FLAG_CREATED) {
		if (e->e_parent)
			e->e_level = e->e_parent->e_level + 1;

		if (element_set_key_attr(e, "bytes", "packets") ||
		    element_set_usage_attr(e, "bytes"))
			BUG();

		/* FIXME: Update link infos every 1s or so */
		update_link_infos(e, link);

		e->e_flags &= ~ELEMENT_FLAG_CREATED;
	}

	for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
		struct attr_map *m = &link_attrs[i];
		uint64_t c_rx = 0, c_tx = 0;
		int flags = 0;

		if (m->rxid >= 0) {
			c_rx = rtnl_link_get_stat(link, m->rxid);
			flags |= UPDATE_FLAG_RX;
		}

		if (m->txid >= 0) {
			c_tx = rtnl_link_get_stat(link, m->txid);
			flags |= UPDATE_FLAG_TX;
		}

		attr_update(e, m->attrid, c_rx, c_tx, flags);
	}

	if (!c_notc)
		handle_tc(e, link);

	element_notify_update(e, NULL);
	element_lifesign(e, 1);
}

static void netlink_read(void)
{
	int err;

	if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err));
		goto disable;
	}

	if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
		goto disable;
	}

	nl_cache_foreach(link_cache, do_link, NULL);

	return;

disable:
	netlink_ops.m_flags &= ~BMON_MODULE_ENABLED;
}

static void netlink_shutdown(void)
{
	nl_cache_free(link_cache);
	nl_cache_free(qdisc_cache);
	nl_socket_free(sock);
}
Example #16
0
TError TNlQdisc::Create(const TNl &nl) {
    TError error = TError::Success();
    int ret;
    struct rtnl_qdisc *qdisc;

    if (Kind == "")
        return Delete(nl);

    qdisc = rtnl_qdisc_alloc();
    if (!qdisc)
        return TError(EError::Unknown, std::string("Unable to allocate qdisc object"));

    rtnl_tc_set_ifindex(TC_CAST(qdisc), Index);
    rtnl_tc_set_parent(TC_CAST(qdisc), Parent);
    rtnl_tc_set_handle(TC_CAST(qdisc), Handle);

    ret = rtnl_tc_set_kind(TC_CAST(qdisc), Kind.c_str());
    if (ret < 0) {
        error = nl.Error(ret, "Cannot to set qdisc type: " + Kind);
        goto free_qdisc;
    }

    if (Kind == "bfifo" || Kind == "pfifo") {
        if (Limit)
            rtnl_qdisc_fifo_set_limit(qdisc, Limit);
    }

    if (Kind == "htb") {
        if (Default)
            rtnl_htb_set_defcls(qdisc, Default);
        if (Quantum)
            rtnl_htb_set_rate2quantum(qdisc, Quantum);
    }

    if (Kind == "hfsc") {
        if (Default)
            rtnl_qdisc_hfsc_set_defcls(qdisc, Default);
    }

    if (Kind == "sfq") {
        if (Limit)
            rtnl_sfq_set_limit(qdisc, Limit);
        if (Quantum)
            rtnl_sfq_set_quantum(qdisc, Quantum);
    }

    if (Kind == "fq_codel") {
        if (Limit)
            rtnl_qdisc_fq_codel_set_limit(qdisc, Limit);
        if (Quantum)
            rtnl_qdisc_fq_codel_set_quantum(qdisc, Quantum);
    }

    nl.Dump("create", qdisc);

    ret = rtnl_qdisc_add(nl.GetSock(), qdisc, NLM_F_CREATE  | NLM_F_REPLACE);
    if (ret < 0)
        error = nl.Error(ret, "Cannot create qdisc");

free_qdisc:
    rtnl_qdisc_put(qdisc);

    return error;
}