118 lines
3 KiB
C
118 lines
3 KiB
C
#include <libnl3/netlink/route/qdisc/netem.h>
|
|
#include <libnl3/netlink/route/qdisc/prio.h>
|
|
#include <libnl3/netlink/route/cls/fw.h>
|
|
|
|
#include "tc.h"
|
|
|
|
struct rtnl_link * tc_get_link(struct nl_sock *sock, const char *dev)
|
|
{
|
|
struct nl_cache *cache;
|
|
struct rtnl_link *link;
|
|
|
|
rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
|
|
link = rtnl_link_get_by_name(cache, "eth0");
|
|
nl_cache_put(cache);
|
|
|
|
return link;
|
|
}
|
|
|
|
int tc_init_prio(struct nl_sock *sock)
|
|
{
|
|
q = rtnl_qdisc_alloc();
|
|
|
|
rtnl_tc_set_ifindex(TC_CAST(q), if_index);
|
|
rtnl_tc_set_parent(TC_CAST(q), TC_H_ROOT);
|
|
rtnl_tc_set_handle(TC_CAST(q), TC_HANDLE(1, 0));
|
|
rtnl_tc_set_kind(TC_CAST(q), "prio");
|
|
|
|
rtnl_qdisc_prio_set_bands (struct rtnl_qdisc *qdisc, int bands);
|
|
rtnl_qdisc_prio_set_priomap (struct rtnl_qdisc *qdisc, uint8_t priomap[], int len);
|
|
|
|
rtnl_qdisc_add(sock, q, NLM_F_CREATE);
|
|
rtnl_qdisc_put(q);
|
|
}
|
|
|
|
int tc_init_netem(struct nl_sock *sock, struct tc_netem *ne)
|
|
{
|
|
q = rtnl_qdisc_alloc();
|
|
|
|
rtnl_tc_set_ifindex(TC_CAST(q), if_index);
|
|
rtnl_tc_set_parent(TC_CAST(q), TC_H_ROOT);
|
|
rtnl_tc_set_handle(TC_CAST(q), TC_HANDLE(1, 0));
|
|
rtnl_tc_set_kind(TC_CAST(q), "netem");
|
|
|
|
rtnl_netem_set_gap(q, int);
|
|
rtnl_netem_set_reorder_probability(q, int);
|
|
rtnl_netem_set_reorder_correlation(q, int);
|
|
rtnl_netem_set_corruption_probability(q, int);
|
|
rtnl_netem_set_corruption_correlation(q, int);
|
|
rtnl_netem_set_loss(q, int);
|
|
rtnl_netem_set_loss_correlation(q, int);
|
|
rtnl_netem_set_duplicate(q, int);
|
|
rtnl_netem_set_duplicate_correlation(q, int);
|
|
rtnl_netem_set_delay(q, int);
|
|
rtnl_netem_set_jitter(q, int);
|
|
rtnl_netem_set_delay_correlation(q, int);
|
|
rtnl_netem_set_delay_distribution(q, const char *);
|
|
|
|
rtnl_qdisc_add(sock, q, NLM_F_CREATE);
|
|
rtnl_qdisc_put(q);
|
|
}
|
|
|
|
int tc_init_classifier(struct nl_sock *sock, int mark)
|
|
{
|
|
struct rtnl_cls *c = rtnl_cls_alloc();
|
|
|
|
rtnl_tc_set_link(TC_CAST(c), if_index);
|
|
rtnl_tc_set_parent(TC_CAST(c), TC_H_ROOT);
|
|
rtnl_tc_set_handle(TC_CAST(c), TC_HANDLE(1, 0));
|
|
rtnl_tc_set_kind(TC_CAST(c), "netem");
|
|
|
|
rtnl_fw_set_classid(c, uint32_t classid);
|
|
rtnl_fw_set_mask(c, uint32_t mask);
|
|
|
|
rtnl_cls_add(sock, cls, int flags);
|
|
rtnl_cls_put(cls);
|
|
}
|
|
|
|
struct nl_sock * tc_init(int mark)
|
|
{
|
|
struct nl_sock *sock;
|
|
struct rtnl_link *link;
|
|
struct rtnl_qdisc *q;
|
|
|
|
/* Create connection to netlink */
|
|
sock = nl_socket_alloc();
|
|
nl_connect(sock, NETLINK_ROUTE);
|
|
|
|
if (tc_init_prio(sock))
|
|
error(0, -1, "Failed to setup TC: prio qdisc");
|
|
if (tc_init_classifier(sock, mark))
|
|
error(0, -1, "Failed to setup TC: fw filter");
|
|
|
|
/* Get interface index */
|
|
int ifindex = tc_get_ifindex;
|
|
|
|
/* Setup classifier */
|
|
rtnl_fw_set_classid (struct rtnl_cls *cls, uint32_t classid);
|
|
rtnl_fw_set_mask (struct rtnl_cls *cls, uint32_t mask);
|
|
rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags);
|
|
|
|
return sock;
|
|
}
|
|
|
|
int tc_reset(struct nl_sock *)
|
|
{
|
|
struct rtnl_qdisc *q;
|
|
|
|
/* Restore default qdisc by deleting the root qdisc (see tc-pfifo_fast(8)) */
|
|
q = rtnl_qdisc_alloc();
|
|
rtnl_tc_set_link(TC_CAST(q), link);
|
|
rtnl_qdisc_delete(sock, q);
|
|
rtnl_qdisc_put(q);
|
|
|
|
/* Shutdown */
|
|
nl_close(sock);
|
|
nl_socket_free(sock);
|
|
}
|
|
|