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

gadgets/run: Generalize logic #2012

Merged
merged 2 commits into from
Sep 8, 2023

Conversation

mauriciovasquezbernal
Copy link
Member

@mauriciovasquezbernal mauriciovasquezbernal commented Sep 7, 2023

Make logic more generic to support other kind of gadgets later on

Reviewing #1866 will take longer, so I'm opening this PR with some preparation work.

Signed-off-by: Mauricio Vásquez <mauriciov@microsoft.com>
Copy link
Member

@eiffel-fl eiffel-fl left a comment

Choose a reason for hiding this comment

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

I will approve it but the more I read this code the more complex I found it...
Using this printMap only to know which buffer (ring of perf) we need to create is really complex as, in fine, we do not even use this map...
Isn't there an abstraction for these buffers (ring of perf) in cilium/ebpf that we could use?

Comment on lines 130 to 139
if printMap != nil {
var valueStruct *btf.Struct
var ok bool
valueStruct, ok = printMap.Value.(*btf.Struct)
if !ok {
return nil, fmt.Errorf("BPF map %q does not have BTF info for values", printMap.Name)
}

var valueStruct *btf.Struct
var ok bool
valueStruct, ok = m.Value.(*btf.Struct)
if !ok {
return nil, fmt.Errorf("BPF map %q does not have BTF info for values", m.Name)
return valueStruct, nil
}

return valueStruct, nil
return nil, fmt.Errorf("the gadget doesn't provide any compatible way to show information")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if printMap != nil {
var valueStruct *btf.Struct
var ok bool
valueStruct, ok = printMap.Value.(*btf.Struct)
if !ok {
return nil, fmt.Errorf("BPF map %q does not have BTF info for values", printMap.Name)
}
var valueStruct *btf.Struct
var ok bool
valueStruct, ok = m.Value.(*btf.Struct)
if !ok {
return nil, fmt.Errorf("BPF map %q does not have BTF info for values", m.Name)
return valueStruct, nil
}
return valueStruct, nil
return nil, fmt.Errorf("the gadget doesn't provide any compatible way to show information")
if printMap == nil {
return nil, fmt.Errorf("the gadget doesn't provide any compatible way to show information")
}
var valueStruct *btf.Struct
var ok bool
valueStruct, ok = printMap.Value.(*btf.Struct)
if !ok {
return nil, fmt.Errorf("BPF map %q does not have BTF info for values", printMap.Name)
}
return valueStruct, nil

Do you really need to var? Cannot you use :=?

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you really need to var? Cannot you use :=?

Sure, it was a leftover of many reworks before.

Regarding your suggestion, I don't want to use early return on this case, as the logic after will be:

// does the program provide a print map?
printMap := getPrintMap()
if printMap != nil {
 return here
}

// is the program an iterator?
// Logic here

// is the program a topper?
// Logic here

// the program isn't any of the above, error out
return nil, fmt.Errorf("the gadget doesn't provide any compatible way to show information")

Copy link
Member

Choose a reason for hiding this comment

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

Regarding your suggestion, I don't want to use early return on this case, as the logic after will be:

I do not understand.
The above function does not handle iterator or topper and the if; else if is done in a later function.

Copy link
Member Author

Choose a reason for hiding this comment

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

It'll handle iterators in #1866. Please take into consideration this refactoring is mainly preparing for that PR, originally it was part of that PR but I decided to open a new one to merge is quickly.

pkg/gadgets/run/tracer/tracer.go Outdated Show resolved Hide resolved
Make logic more generic to support other kind of gadgets later on.

Signed-off-by: Mauricio Vásquez <mauriciov@microsoft.com>
@mauriciovasquezbernal
Copy link
Member Author

I will approve it but the more I read this code the more complex I found it...

Suggestions are welcome!

Using this printMap only to know which buffer (ring of perf) we need to create is really complex as, in fine, we do not even use this map...

I know that we don't use this map yet, but if the code is already there I don't think it's worth removing it.

Isn't there an abstraction for these buffers (ring of perf) in cilium/ebpf that we could use?

Unfortunately I don't think there is any, both provide a Read method but it doesn't have the same signature:
https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/ringbuf/reader.go#L191
https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/perf/reader.go#L316

Record is different for them:
https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/ringbuf/reader.go#L45
https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/perf/reader.go#L39

Could you take a look after my latest changes?

@eiffel-fl
Copy link
Member

I will approve it but the more I read this code the more complex I found it...

Suggestions are welcome!

This is for the writing part in eBPF code, but I like the API they have in libbpf-tools:

iovisor/bcc@527e2e6

Using this printMap only to know which buffer (ring of perf) we need to create is really complex as, in fine, we do not even use this map...

I know that we don't use this map yet, but if the code is already there I don't think it's worth removing it.

Isn't there an abstraction for these buffers (ring of perf) in cilium/ebpf that we could use?

Unfortunately I don't think there is any, both provide a Read method but it doesn't have the same signature: https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/ringbuf/reader.go#L191 https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/perf/reader.go#L316

Record is different for them: https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/ringbuf/reader.go#L45 https://github.com/cilium/ebpf/blob/01ebd4c1e2b9f8b3dd4fd2382aa1092c3c9bfc9d/perf/reader.go#L39

Maybe we can have a dedicated structure to abstract these two type of buffers.

@mauriciovasquezbernal mauriciovasquezbernal merged commit 94cb9c9 into main Sep 8, 2023
47 checks passed
@mauriciovasquezbernal mauriciovasquezbernal deleted the mauricio/cleanup-run-gadget branch September 8, 2023 10:41
@mauriciovasquezbernal
Copy link
Member Author

This is for the writing part in eBPF code, but I like the API they have in libbpf-tools:

Looks good, I'll keep this in mind.

Maybe we can have a dedicated structure to abstract these two type of buffers.

I think there should be a common interface provided by both, but perhaps better to be done in the cilium/ebpf library?

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

2 participants