Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rtnl_flower_set_vlan_id - not work #408

Open
lIkesimba9 opened this issue Oct 6, 2024 · 5 comments
Open

rtnl_flower_set_vlan_id - not work #408

lIkesimba9 opened this issue Oct 6, 2024 · 5 comments

Comments

@lIkesimba9
Copy link

lIkesimba9 commented Oct 6, 2024

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);
}
@thom311
Copy link
Owner

thom311 commented Oct 8, 2024

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
Copy link
Owner

thom311 commented Oct 8, 2024

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.

@lIkesimba9
Copy link
Author

lIkesimba9 commented Oct 9, 2024

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;
}

@thom311
Copy link
Owner

thom311 commented Oct 9, 2024

  • 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.

@lIkesimba9
Copy link
Author

lIkesimba9 commented Oct 9, 2024

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants