jbaublitz / neli

Rust type safe netlink library
BSD 3-Clause "New" or "Revised" License
180 stars 35 forks source link

Using neli to retrieve `qdisc` information #225

Open mmynk opened 1 year ago

mmynk commented 1 year ago

Is this a question about neli specifically? If so, please describe. I'm trying to use neli to retrieve qdisc information similar to the tc binary, basically receive something similar to the output of this command:

tc -s qdisc show

I used strace to debug the netlink commands and was trying to implement the same using neli. However, I couldn't really get it to work.

strace -s 100 -f -o out -x tc -s qdisc show

Output: https://gist.github.com/mmynk/ca4327d659956405bf1a0302ab7fd182#file-tc-strace-log

Here's what I have so far: https://gist.github.com/mmynk/ca4327d659956405bf1a0302ab7fd182#file-tc_neli-rs

However, it runs into an error:

Application error was returned by netlink: Nlmsgerr { error: -2, nlmsg: NlmsghdrErr { nl_len: 36, nl_type: GenlId(Pmcraid), nl_flags: NlmF(769), nl_seq: 0, nl_pid: 58092, nl_payload: Ifinfomsg { ifi_family: Unspecified, padding: 0, ifi_type: Netrom, ifi_index: 0, ifi_flags: Iff(0), ifi_change: Iff(0), rtattrs: RtBuffer([Rtattr { rta_len: 4, rta_type: ExtMask, rta_payload: Buffer }]) } }, ext_ack: GenlBuffer([]) }
mmynk commented 1 year ago

Looks like I was using the wrong protocol to connect: NETLINK_GENERIC instead of NETLINK_ROUTE. I receive two messages now but I do not know how to parse them.

msg: Nlmsghdr { nl_len: 1404, nl_type: GenlId(Ctrl), nl_flags: NlmF(2), nl_seq: 0, nl_pid: 58517, nl_payload: Payload(Ifinfomsg { ifi_family: Unspecified, padding: 0, ifi_type: Loopback, ifi_index: 1, ifi_flags: Iff(65609), ifi_change: Iff(0), rtattrs: RtBuffer([Rtattr { rta_len: 7, rta_type: Ifname, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Txqlen, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Operstate, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Linkmode, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Mtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: MinMtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: MaxMtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Group, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Promiscuity, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(61), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: NumTxQueues, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: GsoMaxSegs, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: GsoMaxSize, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(58), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(59), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(60), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: NumRxQueues, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Carrier, rta_payload: Buffer }, Rtattr { rta_len: 12, rta_type: Qdisc, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierChanges, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierUpCount, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierDownCount, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: ProtoDown, rta_payload: Buffer }, Rtattr { rta_len: 36, rta_type: Map, rta_payload: Buffer }, Rtattr { rta_len: 10, rta_type: Address, rta_payload: Buffer }, Rtattr { rta_len: 10, rta_type: Broadcast, rta_payload: Buffer }, Rtattr { rta_len: 204, rta_type: Stats64, rta_payload: Buffer }, Rtattr { rta_len: 100, rta_type: Stats, rta_payload: Buffer }, Rtattr { rta_len: 12, rta_type: Xdp, rta_payload: Buffer }, Rtattr { rta_len: 804, rta_type: AfSpec, rta_payload: Buffer }, Rtattr { rta_len: 4, rta_type: UnrecognizedConst(32830), rta_payload: Buffer }]) }) }

msg: Nlmsghdr { nl_len: 1432, nl_type: GenlId(Ctrl), nl_flags: NlmF(2), nl_seq: 0, nl_pid: 58517, nl_payload: Payload(Ifinfomsg { ifi_family: Unspecified, padding: 0, ifi_type: Ether, ifi_index: 2, ifi_flags: Iff(69699), ifi_change: Iff(0), rtattrs: RtBuffer([Rtattr { rta_len: 9, rta_type: Ifname, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Txqlen, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Operstate, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Linkmode, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Mtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: MinMtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: MaxMtu, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Group, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: Promiscuity, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(61), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: NumTxQueues, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: GsoMaxSegs, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: GsoMaxSize, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(58), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(59), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(60), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: NumRxQueues, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: Carrier, rta_payload: Buffer }, Rtattr { rta_len: 7, rta_type: Qdisc, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierChanges, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierUpCount, rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: CarrierDownCount, rta_payload: Buffer }, Rtattr { rta_len: 5, rta_type: ProtoDown, rta_payload: Buffer }, Rtattr { rta_len: 36, rta_type: Map, rta_payload: Buffer }, Rtattr { rta_len: 10, rta_type: Address, rta_payload: Buffer }, Rtattr { rta_len: 10, rta_type: Broadcast, rta_payload: Buffer }, Rtattr { rta_len: 204, rta_type: Stats64, rta_payload: Buffer }, Rtattr { rta_len: 100, rta_type: Stats, rta_payload: Buffer }, Rtattr { rta_len: 12, rta_type: Xdp, rta_payload: Buffer }, Rtattr { rta_len: 10, rta_type: PermAddress, rta_payload: Buffer }, Rtattr { rta_len: 792, rta_type: AfSpec, rta_payload: Buffer }, Rtattr { rta_len: 17, rta_type: UnrecognizedConst(56), rta_payload: Buffer }, Rtattr { rta_len: 8, rta_type: UnrecognizedConst(57), rta_payload: Buffer }, Rtattr { rta_len: 4, rta_type: UnrecognizedConst(32830), rta_payload: Buffer }]) }) }
=====================
mmynk commented 1 year ago

Does neli have decoding support similar to pyroute2:decoder.py?

jbaublitz commented 1 year ago

What information are you looking to get out of the message? Are you looking to parse the route attributes?

mmynk commented 1 year ago

Thanks for the reply. That’s exactly what I’m trying to do, yes.

jbaublitz commented 1 year ago

Please see the examples directory for an example of how to use the API for route netlink. route-list.rs has some pretty involved usage in terms of how to get attributes from a routing message.

mmynk commented 1 year ago

Those examples use IpAddr for parsing the buffer. How do I parse, say Ifla::Stats or Ifla::Stats64?

// for stats64
let mut bytes = [0u8; 200];
buf.read_exact(&mut bytes);
// TODO: ???

Do I need to define the entire data structure of Stats for parsing this?

jbaublitz commented 1 year ago

Yes, you would need to define the data structure, implementing ToBytes and FromBytes to handle the conversion.