libnl icon indicating copy to clipboard operation
libnl copied to clipboard

rtnl_flower_set_vlan_id - not work

Open lIkesimba9 opened this issue 1 year ago • 5 comments

I call rtnl_flower_set_vlan_id , but it doesn't have any effect I should get the following output

filter parent ffff: protocol 802.1Q pref 4 flower chain 0 
filter parent ffff: protocol 802.1Q pref 4 flower chain 0 handle 0x1 
  vlan_id 101
  not_in_hw
	action order 1: skbedit  mark 11 pipe
	 index 1 ref 1 bind 1

but I get this output

filter parent ffff: protocol 802.1Q pref 1 flower chain 0 
filter parent ffff: protocol 802.1Q pref 1 flower chain 0 handle 0x1 
  not_in_hw
	action order 1: skbedit  mark 11 pipe
	 index 1 ref 1 bind 1
void add_flower_filter(struct rtnl_link *link, uint32_t parent_handle, struct nl_sock* sock, int prio, struct rtnl_act* act, uint16_t vlan_id) {
    struct rtnl_cls *filter;
    int err;
    filter = rtnl_cls_alloc();
    rtnl_tc_set_link(TC_CAST(filter), link);

    rtnl_tc_set_parent(TC_CAST(filter), parent_handle);
    err = rtnl_tc_set_kind(TC_CAST(filter), "flower");
    throw_err(err);

    rtnl_cls_set_prio(filter, prio);
    rtnl_cls_set_protocol(filter, ETH_P_8021Q);
    err = rtnl_flower_set_vlan_id(filter, vlan_id);

    throw_err(err);

    err = rtnl_flower_append_action(filter, act);
    throw_err(err);

    err = rtnl_cls_add(sock, filter, NLM_F_CREATE);
    throw_err(err);
    rtnl_cls_put(filter);
}

lIkesimba9 avatar Oct 06 '24 15:10 lIkesimba9

hi. I don't know the answer to this, but since you are able to reproduce, you seem well positioned to find out what's wrong.

Note that kernel sources seem to indicate that this should be a big-endian u16 number. libnl doesn't seem to be aware of that, and just passes on whatever it has. Does it work if you pass 0x6500u instead of 0x65u (101)?

thom311 avatar Oct 08 '24 11:10 thom311

Note that kernel sources seem to indicate that this should be a big-endian u16 number. libnl doesn't seem to be aware of that, and just passes on whatever it has. Does it work if you pass 0x6500u instead of 0x65u (101)?

Hm, no from the kernel sources it seems it's native endianness, although there are comments like TCA_FLOWER_KEY_VLAN_ID, /* be16 */ ... dunno.

thom311 avatar Oct 08 '24 11:10 thom311

it didn't help. didn't help. Do you have any other ideas? full code for testing

#include <iostream>
#include <netlink/netlink.h>
#include <netlink/route/link.h>
#include <netlink/route/tc.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/classifier.h>
#include <linux/if_ether.h>
#include <linux/pkt_cls.h>
#include <linux/netlink.h>
#include <netlink/route/cls/flower.h>
#include <netlink/route/cls/u32.h>
#include <netlink/route/act/skbedit.h>




void throw_err(int err) {
    if (err) {
        std::string error_str = "!!ERROR " + std::string(nl_geterror(err));
        throw std::runtime_error(error_str);
    }
}


void add_qdisc_ingress(struct rtnl_link *link, uint32_t parent_handle, uint32_t handle, struct nl_sock* sock) {
    int err;
    struct rtnl_qdisc *qdisc;
    qdisc = rtnl_qdisc_alloc();
    rtnl_tc_set_link(TC_CAST(qdisc), link);

    rtnl_tc_set_parent(TC_CAST(qdisc), parent_handle);
    rtnl_tc_set_handle(TC_CAST(qdisc), handle);
    err = rtnl_tc_set_kind(TC_CAST(qdisc), "ingress");
    throw_err(err);


    err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE);
    throw_err(err);
    rtnl_qdisc_put(qdisc);
}

void add_flower_filter(struct rtnl_link *link, uint32_t parent_handle, struct nl_sock* sock, int prio, struct rtnl_act* act, uint16_t vlan_id) {
    struct rtnl_cls *filter;
    int err;
    filter = rtnl_cls_alloc();
    rtnl_tc_set_link(TC_CAST(filter), link);

    rtnl_tc_set_parent(TC_CAST(filter), parent_handle);
    err = rtnl_tc_set_kind(TC_CAST(filter), "flower");
    throw_err(err);

    rtnl_cls_set_prio(filter, prio);
    rtnl_cls_set_protocol(filter, ETH_P_8021Q);
    err = rtnl_flower_set_vlan_id(filter, vlan_id);

    throw_err(err);

    err = rtnl_flower_append_action(filter, act);
    throw_err(err);

    err = rtnl_cls_add(sock, filter, NLM_F_CREATE);
    throw_err(err);
    rtnl_cls_put(filter);
}



int main() {

    struct nl_cache *cache;
    struct rtnl_link *link;
    struct nl_sock *sock;
    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, "lo");


    struct rtnl_qdisc *qdisc;
    if (!(qdisc = rtnl_qdisc_alloc())) {
        std::runtime_error("Can not allocate Qdisc");
    }
    rtnl_tc_set_link(TC_CAST(qdisc), link);
    rtnl_tc_set_parent(TC_CAST(qdisc), TC_HANDLE(0xffff, 0));

    //tc qdisc del dev lo ingress
    rtnl_qdisc_delete(sock, qdisc);
    free(qdisc);



    //tc qdisc add dev lo ingress
    add_qdisc_ingress(link, TC_H_INGRESS, TC_HANDLE(0xffff, 0), sock);



    struct rtnl_act *act = rtnl_act_alloc();
    if (!act) {
        printf("rtnl_act_alloc() returns %p\n", act);
        return -1;
    }
    rtnl_tc_set_kind(TC_CAST(act), "skbedit");

    rtnl_skbedit_set_action(act, TC_ACT_PIPE);
    rtnl_skbedit_set_mark(act, 11);


   add_flower_filter(link, TC_HANDLE(0xffff, 0), sock, 1, act, 0x6500u);
    return 0;
}

lIkesimba9 avatar Oct 09 '24 10:10 lIkesimba9

  • check with a non-libnl3 tool whether the vlan-id is set. I am not familiar with this, but some tc command line should show it, when it's set. If you can see it there, then libnl fails to parse the data from kernel. If it's not there, libnl fails to configure it in kernel.

  • run with strace -v -s 1000 ./my-command (or something like that), and try to see what netlink messages are exchanged.

  • from looking at the libnl code, it would seem that libnl should try to set the value in the netlink message. If not, investigate why not. If yes, investigate why kernel ignores it (maybe the value makes no sense for the object you are configuring).

  • can you create the desired configuration with other tools, e.g. some tc command line? If yes, check which netlink messages are exchanged, and how they differ from what libnl does.

thom311 avatar Oct 09 '24 11:10 thom311

I run command tc filter add dev veth1 protocol 802.1Q parent ffff: prio 4 flower vlan_id 101 action skbedit mark 11 and i get follow output in strace and in ltrace , what should i do next?

lIkesimba9 avatar Oct 09 '24 16:10 lIkesimba9