使用libnl或netlink在Linux中更新FQ Qdisc

时间:2019-05-31 19:30:03

标签: c linux netlink

我有一个FQ Qdisc,我想以毫秒为单位更新。我当前的方法是直接使用tc命令,但这太慢了:

    char tc_cmd[200];
    snprintf(tc_cmd, 200,"tc qdisc change dev %s root fq maxrate %.3fmbit &", net_dev, tx_rate / 10e5);
    err = system(tc_cmd);
    if (err) {
        perror(stderr,"Problem with tc qdisc change");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;

我想使用libnl或netlink实现此代码片段。不幸的是,尽管libnl-route支持variety的qdiscs,但它尚不支持公平排队的qdiscs。我真正想要做的唯一一件事就是发送一条更新消息,以更改活动FQ qdisc的限制。但是,我对netlink和libnl实现的了解不多,我不确定如何制作这样的消息。

作为参考,这是我使用libnl设置和更改htb qdisc的方式。我想为fq qdisc实现类似的功能:

    struct rtnl_qdisc *tbf_qdisc;
    int if_index;
    int err = 0;
    char *netdev = "eth0"
    uint64_t tx_rate = 10e6;
    uint64_t burst = 12000;
    uint64_t limit = 5000;

    fprintf(stderr, "Kernel Clock Rate: %d\n", nl_get_user_hz());
    qdisc_sock = nl_socket_alloc();
    nl_connect(qdisc_sock, NETLINK_ROUTE);
    if_index = if_nametoindex(netdev);

    // Allocate and configure the qdisc 
    fq_qdisc = rtnl_qdisc_alloc();
    rtnl_tc_set_ifindex(TC_CAST(tbf_qdisc), if_index);
    rtnl_tc_set_parent(TC_CAST(tbf_qdisc), TC_H_ROOT);
    rtnl_tc_set_handle(TC_CAST(tbf_qdisc), TC_HANDLE(1,0));
    err = rtnl_tc_set_kind(TC_CAST(tbf_qdisc), "tbf");
    if (err) {
        fprintf(stderr,"Can not allocate TBF: %s\n", nl_geterror(err));
        return NULL;
    }
    rtnl_qdisc_tbf_set_rate(tbf_qdisc, (uint64_t) tx_rate, burst , 0);
    rtnl_qdisc_tbf_set_limit(tbf_qdisc, limit);
    rtnl_qdisc_tbf_set_peakrate(tbf_qdisc, (uint64_t) tx_rate, burst, 0);

    // Add it to the interface
    err = rtnl_qdisc_add(qdisc_sock, tbf_qdisc, NLM_F_CREATE);
    if (err) {
        fprintf(stderr,"Can not set TBF: %s\n", nl_geterror(err));
        return NULL;

    // Update the rate of the qdisc 
    rate = 1e6;
    rtnl_qdisc_tbf_set_rate(tbf_qdisc, (uint64_t) tx_rate, burst , 0);
    rtnl_qdisc_tbf_set_peakrate(tbf_qdisc, (uint64_t) tx_rate, burst, 0);
    rtnl_qdisc_tbf_set_limit(tbf_qdisc, limit);
    err = rtnl_qdisc_add(qdisc_sock, tbf_qdisc, NLM_F_REPLACE);
    if(err) {
        fprintf(stderr,"Rate %lu qdisc_add: %s\n", tx_rate, nl_geterror(err));
        return NULL;
    }

0 个答案:

没有答案