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

elf: don't clamp PerfEventArray.MaxEntries at parse time #1094

Merged
merged 3 commits into from
Jul 24, 2023

Conversation

lmb
Copy link
Collaborator

@lmb lmb commented Jul 13, 2023

elf: don't clamp PerfEventArray.MaxEntries at parse time

One key idea of the ELF reader is that it is deterministic: it should always
produce the same output regardless of which system it runs on. The
PerfEventArray clamping logic violates this since it substitutes the number
of possible CPUs.

Move the logic into map creation and adjust MapSpec.Compatible to do the
same fixup.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>

map: fix MapSpec.Compatible for PerfEventArray with zero key or value size

MapSpec.Compatible currently returns an error when comparing a
PerfEventArray created from a MapSpec without explicit key or value sizes.
This is because we only do the fixup just before executing the
BPF_MAP_CREATE syscall.

Move the fixup logic into a separate function so that we can invoke it from 
MapSpec.Compatible.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>

map: fix buggy TestMapLoadReusePinned

The test calls t.Fatal on the wrong (parent) t since it reuses qt.New from
the parent scope. Remove qt.New.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>

@lmb lmb requested review from ti-mo and rgo3 July 13, 2023 09:32
@lmb lmb force-pushed the elf-no-fixup branch 3 times, most recently from 4bd7fd1 to b3cc0d1 Compare July 13, 2023 10:10
Copy link
Contributor

@rgo3 rgo3 left a comment

Choose a reason for hiding this comment

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

Just a question on my part to better understand why we are fixing up the size of a PerfEventArray at all.

map.go Outdated Show resolved Hide resolved
map.go Outdated
var err error
maxEntries, err = fixupPerfEventArraySize(maxEntries)
if err != nil {
return err
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we wrap this? Otherwise, the caller will receive the raw error from internal.PossibleCPUs without any context.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Wrapped in fixupPerfEventArraySize instead.

@@ -376,12 +384,9 @@ func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions) (_ *Map, err erro
spec.KeySize = 4
spec.ValueSize = 4

if spec.MaxEntries == 0 {
Copy link
Collaborator

@ti-mo ti-mo Jul 19, 2023

Choose a reason for hiding this comment

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

This will leave a 0 in spec.MaxEntries if getting possible CPUs fails. I know it's annoying, but we shouldn't do this. (also the Go tenet of not using the other value(s) if err != nil, etc..)

In the spirit of this PR, I'm also not sure if we should mutate spec at all. Could we delay this even further and write this value into the bpf attr instead of the spec?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I know it's annoying, but we shouldn't do this. (also the Go tenet of not using the other value(s) if err != nil, etc..)

I don't understand, sorry.

I'm also not sure if we should mutate spec at all.

That's why we do spec.Copy above.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't remember what the proposed change looked like before, not sure how I missed the copy. I guess it would've been fine.

My point was: if a function returns a non-nil error, all other return values (other than the error itself, of course) should be ignored. IIRC this said something like spec.MaxEntries, err = ..., so I was just pointing out the obvious.

Copy link
Collaborator

@ti-mo ti-mo left a comment

Choose a reason for hiding this comment

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

Left a few nits, thanks!

map.go Outdated
case !(ms.Type == PerfEventArray && ms.MaxEntries == 0) &&
m.maxEntries != ms.MaxEntries:
return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.maxEntries, ErrMapIncompatible)
case maxEntries != ms.MaxEntries:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is supposed to be m.maxEntries != maxEntries? Comparing spec to itself otherwise.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! I added a test.

ti-mo
ti-mo previously requested changes Jul 19, 2023
Copy link
Collaborator

@ti-mo ti-mo left a comment

Choose a reason for hiding this comment

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

Changing my review, think I found a bug.

lmb added 3 commits July 19, 2023 14:14
One key idea of the ELF reader is that it is deterministic: it
should always produce the same output regardless of which system
it runs on. The PerfEventArray clamping logic violates this since
it substitutes the number of possible CPUs.

Move the logic into map creation and adjust MapSpec.Compatible
to do the same fixup.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
… size

MapSpec.Compatible currently returns an error when comparing a PerfEventArray
created from a MapSpec without explicit key or value sizes. This is because
we only do the fixup just before executing the BPF_MAP_CREATE syscall.

Move the fixup logic into a separate function so that we can invoke it from
MapSpec.Compatible.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
The test calls t.Fatal on the wrong (parent) t since it reuses
qt.New from the parent scope. Remove qt.New.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
Copy link
Collaborator Author

@lmb lmb left a comment

Choose a reason for hiding this comment

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

Updated, should be OK now I hope. Found another bug with MapSpec compatibility which I've fixed in a separate commit.

@lmb lmb requested a review from ti-mo July 19, 2023 12:27
@lmb lmb dismissed ti-mo’s stale review July 24, 2023 12:05

Changes were made

@lmb lmb merged commit b4b25b3 into cilium:main Jul 24, 2023
2 checks passed
@lmb lmb deleted the elf-no-fixup branch July 24, 2023 12:05
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.

None yet

3 participants