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

example xdp: The IP address output by xdp demo is empty #1175

Closed
BillyChen1 opened this issue Oct 19, 2023 · 5 comments
Closed

example xdp: The IP address output by xdp demo is empty #1175

BillyChen1 opened this issue Oct 19, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@BillyChen1
Copy link
Contributor

BillyChen1 commented Oct 19, 2023

Describe the bug
The IP address output by xdp demo is empty (NIL)

To Reproduce

Env:

~ go version
go version go1.21.1 linux/amd64
~ uname -a
Linux cqm-OptiPlex-7040 5.15.0-83-generic #92~20.04.1-Ubuntu SMP Mon Aug 21 14:00:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
~ cat /etc/issue
Ubuntu 20.04.5 LTS \n \l

Behavior:

xdp git:(main) ✗ sudo ./xdp enp0s31f6
2023/10/19 16:56:15 Attached XDP program to iface "enp0s31f6" (index 2)
2023/10/19 16:56:15 Press Ctrl-C to exit and remove the program
2023/10/19 16:56:16 Map contents:
        <nil> => 1
        <nil> => 1
        <nil> => 61
2023/10/19 16:56:17 Map contents:
        <nil> => 1
        <nil> => 5
        <nil> => 2
        <nil> => 1
        <nil> => 164

Expected behavior
My expectation was to see the IP address string.
I found that if I use the uint32 type in examples/xdp/main.go to accept the val attribute, and use internal.NativeEndian.PutUint32 to convert it to a byte array, I can solve the problem.
The following is my modification to the formatMapContents method in examples/xdp/main.go, which can solve this problem.

func formatMapContents(m *ebpf.Map) (string, error) {
	var (
		sb strings.Builder
		key uint32
		val uint32
	)
	iter := m.Iterate()
	for iter.Next(&key, &val) {
		b := make([]byte, 4)
		internal.NativeEndian.PutUint32(b, key)
		sourceIP := net.IP(b) // IPv4 source address in network byte order.
		packetCount := val
		sb.WriteString(fmt.Sprintf("\t%s => %d\n", sourceIP, packetCount))
	}
	return sb.String(), iter.Err()
}

After modification, the problem was solved.

➜  xdp git:(main) ✗ sudo ./xdp enp0s31f6
2023/10/19 17:08:20 Attached XDP program to iface "enp0s31f6" (index 2)
2023/10/19 17:08:20 Press Ctrl-C to exit and remove the program
2023/10/19 17:08:21 Map contents:
        114.212.81.84 => 16
        100.103.31.185 => 5
        172.27.144.197 => 1
2023/10/19 17:08:22 Map contents:
        114.212.81.84 => 43
        100.103.31.185 => 5
        120.55.98.112 => 2
        172.27.144.197 => 6
2023/10/19 17:08:23 Map contents:
        114.212.81.84 => 43
        100.103.31.185 => 7
        114.212.87.49 => 1
        120.55.98.112 => 2
        172.27.144.197 => 9
@BillyChen1 BillyChen1 added the bug Something isn't working label Oct 19, 2023
@rgo3
Copy link
Contributor

rgo3 commented Oct 19, 2023

I can confirm that this is also broken for me.
@markpash already suggested on the PR for this example, that we could use netip.Addr as the type for the key, which fixed it for me:

func formatMapContents(m *ebpf.Map) (string, error) {
	var (
		sb strings.Builder
		key netip.Addr
		val uint32
	)
	iter := m.Iterate()
	for iter.Next(&key, &val) {
                sourceIP := key
		packetCount := val
		sb.WriteString(fmt.Sprintf("\t%s => %d\n", sourceIP, packetCount))
	}
	return sb.String(), iter.Err()
}

@BillyChen1
Copy link
Contributor Author

I can confirm that this is also broken for me. @markpash already suggested on the PR for this example, that we could use netip.Addr as the type for the key, which fixed it for me:

func formatMapContents(m *ebpf.Map) (string, error) {
	var (
		sb strings.Builder
		key netip.Addr
		val uint32
	)
	iter := m.Iterate()
	for iter.Next(&key, &val) {
                sourceIP := key
		packetCount := val
		sb.WriteString(fmt.Sprintf("\t%s => %d\n", sourceIP, packetCount))
	}
	return sb.String(), iter.Err()
}

cool! It worked for me, too!

@rgo3
Copy link
Contributor

rgo3 commented Oct 19, 2023

Feel free to open a PR with the fix @BillyChen1

@BillyChen1
Copy link
Contributor Author

@rgo3 #1178

@rgo3
Copy link
Contributor

rgo3 commented Oct 19, 2023

@lmb I had some suspicions and this broke with 4609dc7. So my suggested fix fixes the issue described here but there might be some underlying bug with the zero allocation stuff?

lmb added a commit to lmb/ebpf that referenced this issue Oct 20, 2023
The library has somewhat complicated semantics when unmarshaling
map keys and values. It turns out that the following was supported
(but not documented) until the zero-allocation marshaling work
broke it:

    var s []byte
    m.Lookup(key, &s)

The important thing is that the slice here is empty. The current
code treats this as "the key should be zero length" while originally
we'd assign the temporary buffer used by the syscall to s as a way to
reduce allocations. In hindsight this wasn't a great idea, but it is
what it is.

Reintroduce the byte slice special case.

Fixes cilium#1175

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
lmb added a commit to lmb/ebpf that referenced this issue Oct 20, 2023
The library has somewhat complicated semantics when unmarshaling
map keys and values. It turns out that the following was supported
(but not documented) until the zero-allocation marshaling work
broke it:

    var s []byte
    m.Lookup(key, &s)

The important thing is that the slice here is empty. The current
code treats this as "the key should be zero length" while originally
we'd assign the temporary buffer used by the syscall to s as a way to
reduce allocations. In hindsight this wasn't a great idea, but it is
what it is.

Reintroduce the byte slice special case.

Fixes cilium#1175

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
@lmb lmb closed this as completed in e83be32 Oct 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants