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

Add --filter-ifname #257

Merged
merged 4 commits into from
Sep 28, 2023
Merged

Add --filter-ifname #257

merged 4 commits into from
Sep 28, 2023

Conversation

jschwinger233
Copy link
Member

Set this flag to filter skb from/to the specific interface under the specific netns. If flag --filter-netns is not set, pwru uses current netns.

Signed-off-by: Zhichuan Liang [email protected]

@jschwinger233 jschwinger233 marked this pull request as ready for review September 26, 2023 05:50
@brb
Copy link
Member

brb commented Sep 26, 2023

@jschwinger233 Maybe let's resolve ifname to ifindex from the user space, and then use ifindex in the kprobe?

@jschwinger233
Copy link
Member Author

@brb That was my idea, but I ended up giving it up because I didn't know how to switch netns using ID.

I know how to switch netns: https://www.weave.works/blog/linux-namespaces-golang-followup, I don't know how to get NsHandle from ID.

I looked up vishvananda/netns, there are 5 functions to get a NsHandle: GetFromDocker, GetFromName, GetFromPath, GetFromPid, GetFromThread, but none accepts a netns ID.

@brb
Copy link
Member

brb commented Sep 26, 2023

I didn't know how to switch netns using ID

A netns ID is just an inode number. Have you tried passing it to https://github.com/vishvananda/netns/blob/master/netns_linux.go#L29, i.e. netns.Set(netns.NsHandle($INODE_NUM))?

@jschwinger233
Copy link
Member Author

I think NsHandle is a wrapper of fd:
https://github.com/vishvananda/netns/blob/16c2fa0b2f57726d0e9e4acd228a63c322954f31/netns_linux.go#L101-L106

The value should be a small integer like 5, 6, 7, instead of something like 4026531834

@brb
Copy link
Member

brb commented Sep 26, 2023

Hmm, you are right. And on Linux getting FD by inode is not possible :-/ Maybe we should change the semantics of filter-netns, and require it to point to a netns path? That would also improve the UX.

@jschwinger233
Copy link
Member Author

I agree that netnsPath improves UX, but netns field in output of pwru --output-meta shows inode. If someone wants to filter a specific netns based on previous pwru output, it would be inconvenient.

(For me, I can use lsns to search pid by inode, but it's still an extra burden for users.)

Speaking of output fields, one more thing is ifindex field in output of pwru --output-meta, I'd love to convert that ifindex to ifname and show something like if=3(eth0), still it's hard to parse ifindex in userspace. We can achieve it in bpf program by fetching skb->dev->name, not sure if we want to do so.

@brb
Copy link
Member

brb commented Sep 26, 2023

I agree that netnsPath improves UX, but netns field in output of pwru --output-meta shows inode. If someone wants to filter a specific netns based on previous pwru output, it would be inconvenient.

My main worry with the current ifname approach is that in the critical path we have a slow operation (string vs int cmp).

WDYT about having --filter-netns (by path) and --filter-netns-by-inode, and then making --filter-netns-by-inode mutual exclusive with --filter-ifname (which we convert to ifindex in the user space)?

@brb
Copy link
Member

brb commented Sep 26, 2023

I'd love to convert that ifindex to ifname and show something like if=3(eth0), still it's hard to parse ifindex in userspace.

It's been on my list since forever 😅 When the prog starts, we could fetch ifindices from all netns, and then build a cache (prone to races, but it's fine) - key=[netns_inode, ifindex] => val=iface_name.

@jschwinger233
Copy link
Member Author

WDYT about having --filter-netns (by path) and --filter-netns-by-inode, and then making --filter-netns-by-inode mutual exclusive with --filter-ifname (which we convert to ifindex in the user space)?

That will do.

Another option is like docker run --network, to adapt different network types, docker run --network accepts:

  • bridge as type
  • container:<name|id> to attach a container netns
  • <network-id>

So how about letting --filter-netns accept multiple forms of arguments:

  • path:/proc/1/ns/net
  • <inode>

@brb
Copy link
Member

brb commented Sep 26, 2023

So how about letting --filter-netns accept multiple forms of arguments:

SGTM! Just maybe let's make path as a default.

@jschwinger233 jschwinger233 force-pushed the gray/filter-ifname branch 3 times, most recently from ee1667c to a10a79d Compare September 27, 2023 15:05
@jschwinger233 jschwinger233 marked this pull request as draft September 27, 2023 16:43
@jschwinger233 jschwinger233 marked this pull request as ready for review September 27, 2023 17:06
@@ -53,15 +54,16 @@ func (f *Flags) SetFlags() {
flag.StringSliceVar(&f.KMods, "kmods", nil, "list of kernel modules names to attach to")
flag.BoolVar(&f.AllKMods, "all-kmods", false, "attach to all available kernel modules")
flag.StringVar(&f.FilterFunc, "filter-func", "", "filter kernel functions to be probed by name (exact match, supports RE2 regular expression)")
flag.Uint32Var(&f.FilterNetns, "filter-netns", 0, "filter netns inode")
flag.StringVar(&f.FilterNetns, "filter-netns", "", "filter netns (\"proc/<pid>/ns/net\", \"inode:<inode>\")")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: s/proc//proc/

@brb
Copy link
Member

brb commented Sep 28, 2023

@jschwinger233 Very nice! One nit, and then we can :shipit:

@brb
Copy link
Member

brb commented Sep 28, 2023

@jschwinger233 Could you rebase to resolve the conflict?

Set this flag to filter skbs whose dev->ifindex equals to user specified
one, under the netns set by --filter-netns.

If --filter-netns is not set, pwru automatically detects current netns.

Pwru has to switch netns in order to parse ifindex from ifname. To
achieve that, --filer-netns accepts multi-forms arguments:
1. By path: --filter-netns /proc/<pid>/ns/net
2. By inode: --filter-netns inode:4026533332

--filter-ifname can only work with --filter-netns by path, otherwise
pwru cannot switch to target netns by inode.

Signed-off-by: Zhichuan Liang <[email protected]>
Signed-off-by: Zhichuan Liang <[email protected]>
Signed-off-by: Zhichuan Liang <[email protected]>
Signed-off-by: Zhichuan Liang <[email protected]>
Copy link
Member

@brb brb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@brb brb merged commit 0ea4a67 into main Sep 28, 2023
@jschwinger233 jschwinger233 deleted the gray/filter-ifname branch September 28, 2023 08:07
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

Successfully merging this pull request may close these issues.

2 participants