How to configure netem qdisc and tbf qdisc using libnl-route?

I am trying to do network emulation on ubuntu 12.04 while shell commands are working:

tc qdisc add dev eth1 root handle 1:0 tbf rate 200kbit buffer 1600 limit 3000

or

tc qdisc change dev eth0 root netem loss 0.1%

Now I want to do the same in c code, and I found libnl.

I successfully added prio and htb qdisc using doc

http://www.carisma.slowglass.com/~tgr/libnl/doc/route.html#tc_qdisc

but when I made netem qdisc, it returned "Invalid input or parameter" and "Missing attribute" in the case of tbf qdisc. My codes are as follows:

  • netem

    q = rtnl_qdisc_alloc();
    rtnl_tc_set_ifindex(TC_CAST(q), 2);
    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_delay(q, 100);
    rtnl_netem_set_loss(q, 10);
    
    int err = rtnl_qdisc_add(sock, q, NLM_F_CREATE);
    if(err<0){
      printf("netem error: %s\n", nl_geterror(err));
    }
    
  • TBF

    q = rtnl_qdisc_alloc();
    rtnl_tc_set_ifindex(TC_CAST(q), 2);
    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), "tbf");
    
    rtnl_qdisc_tbf_set_limit(q, 1000);
    rtnl_qdisc_tbf_set_rate(q, 1000, 1000, 8);
    
    int err = rtnl_qdisc_add(sock, q, NLM_F_CREATE);
    if(err<0){
      printf("tbf error: %s\n", nl_geterror(err));
    }
    

I tried all the relevant functions referenced by api ref, but always have the same errors "Invalid input or parameter" and "Missing attribute", and googled without help.

I’ve been stuck with the problem for more than a week, I need your help.

+4
1

, . gcc-, . , , /.

3.2.24-1 (debian unstable); :

  • libnl-3-dev
  • libnl-cli-3-dev
  • libnl-genl-3-dev
  • libnl-nf-3-dev
  • libnl-route-3-dev
  • libnl-3-200
  • libnl--3-200
  • libnl-GENL-3-200
  • libnl-NF-3-200
  • libnl -3-200
  • libnl-Utils

. , , "-lnl-genl-3 -lnl-3 -lnl-route-3"

"gcc -lnl-genl-3 -lnl-3 -lnl-route-3 -fpermissive -pedantic-errors -Wall -Wextra -ftabstop = 4 -march = native -fshow-column -ftabstop = 4 -frounding -math -pipe -ggdb3 -O0 main.c -o your_qdisc_app"

#include <libnl3/netlink/route/tc.h>
#include <libnl3/netlink/route/qdisc.h>
#include <libnl3/netlink/route/qdisc/netem.h>
#include <libnl3/netlink/route/qdisc/tbf.h>

int main(int argc, char ** argv)
{
  struct nl_sock *sock;
  struct rtnl_qdisc *q;
  struct nl_cache *cache;
  struct rtnl_link *link;
  int if_index;


  sock = nl_socket_alloc();

  nl_connect(sock, NETLINK_ROUTE);
  rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
  link = rtnl_link_get_by_name(cache, "eth0");
  if_index = rtnl_link_get_ifindex(link);

  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), "tbf"); 

  /*
   * netem okay, htb okay, please comment 
   * and uncomment the special parameters for the qdiscs
  */
  rtnl_qdisc_tbf_set_limit(q, 1000);
  rtnl_qdisc_tbf_set_rate(q, 1000, 1000, 8);
  /*
   * rtnl_netem_set_delay(q, 100);
   * rtnl_netem_set_loss(q, 10);
  */

  rtnl_qdisc_add(sock, q, NLM_F_CREATE);

  rtnl_qdisc_put(q);
  nl_socket_free(sock);
  rtnl_link_put(link);
  nl_cache_put(cache);

  return 0;
}

"if", . . , .

,

+2

All Articles