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 support for filtering events and minor related changes #673

Merged
merged 4 commits into from
May 13, 2017
Merged

Add support for filtering events and minor related changes #673

merged 4 commits into from
May 13, 2017

Conversation

aalemayhu
Copy link
Contributor

@aalemayhu aalemayhu commented May 9, 2017

The new filtering support consists of --type, --to and --from.
The cilium help monitor output now looks like this:

The monitor displays notifications and events omitted by the BPF
programs attached to endpoints and devices. This includes:
  * Dropped packet notifications
  * Captured packet traces
  * Debugging information

Usage:
  cilium monitor [flags]

Flags:
  -d, --dissect             Dissect packet data
      --from uint16         filter by source endpoint id
  -c, --num-cpus int        Number of CPUs (default 2)
  -n, --num-pages int       Number of pages for ring buffer (default 64)
      --related-to uint32   filter by either source or destination endpoint id
      --to uint32           filter by destination endpoint id
  -t, --type string         Filter by event types [drop debug capture]

Global Flags:
      --config string   config file (default is $HOME/.cilium.yaml)
  -D, --debug           Enable debug messages
  -H, --host string     URI to server-side API

Some example usage:

  • cilium monitor --type drop will only show you messages for packets being
    dropped.
  • cilium monitor --type drop --from 173 is same as above but will only match
    when the source has the provided id.
  • cilium monitor --type drop --to 123 should match when we get a drop event
    and the destination has the provided id.
  • cilium monitor --type drop --related-to 749 shows drop notifications where
    the source or destination has the provided id.

Closes: #473 (Feature: Add filtering to cilium monitor)

@aalemayhu aalemayhu requested a review from tgraf May 9, 2017 14:12
Copy link
Member

@tgraf tgraf left a comment

Choose a reason for hiding this comment

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

Overall this is great. It would be even better if we can support a --related-to ID which takes an endpoint ID and then prints everything which has the endpoint ID in either the from to to. This would show everything in and out of a particular endpoint.

// checkFilter does some input validation to give the user feedback if they
// wrote something close that did not match for example 'srop' instead of
// 'drop'.
func checkFilter() {
Copy link
Member

Choose a reason for hiding this comment

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

I would rename this to validateEventTypeFilter

@@ -59,40 +63,97 @@ var (
SampleType: bpf.PERF_SAMPLE_RAW,
WakeupEvents: 1,
}
eventTypeIdx = -1 // for integer comparison
eventType = ""
eventTypes = []string{"drop", "debug", "capture"}
Copy link
Member

Choose a reason for hiding this comment

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

Consider writing this as a map instead:

eventTypes := map[string]int {
   "debug":   bpfdebug.MessageTypeDebug,
   "drop":    bpfdebug.MessageTypeDrop,
   "capture": bpfdebug.MessageTypeCapture,
}

Copy link
Member

Choose a reason for hiding this comment

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

This also makes it clear which names corresponds to which message type without depending on order

func checkFilter() {
for i, e := range eventTypes {
if eventType == e {
eventTypeIdx = i + 1 // 0 == .MessageTypeUnspec, but we only want valid ones.
Copy link
Member

Choose a reason for hiding this comment

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

You can then just check the type against the map:

if eventTypeIdx, ok = eventTypes[eventType]; !ok {
    err := "Unknown type (%s). Please use one of the following ones %s\n"
    [...]
}

// are supplied. If either one of them is less than zero, then it is assumed user did
// use them.
func match(messageType int, src uint16, dst uint32) bool {
if eventTypeIdx > bpfdebug.MessageTypeUnspec && messageType != eventTypeIdx {
Copy link
Member

Choose a reason for hiding this comment

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

The > is misleading, write this as:

if eventTypeIdx != bpfdebug.MessageTypeUnspec && messageType != eventTypeIdx {

Copy link
Member

Choose a reason for hiding this comment

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

@scanf was this addressed?

Copy link
Member

Choose a reason for hiding this comment

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

@aanm meant my comment above which is still not addressed. It's a cosmetic thing though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@aanm ah, must have left this on a different machine. It was marked as outdated so I just assumed it was addressed since Github automatically collapses these. Will follow up. Thanks!

eventTypeIdx = -1 // for integer comparison
eventType = ""
eventTypes = []string{"drop", "debug", "capture"}
fromSource = 0
Copy link
Member

Choose a reason for hiding this comment

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

Initialize them to uint16 so you don't have to cast later on:

fromSource = uint16(0)

@@ -43,11 +43,19 @@ programs attached to endpoints and devices. This includes:
},
}

func listEventTypes() string {
return "[ drop, debug, capture ]"
Copy link
Member

Choose a reason for hiding this comment

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

This is fine, if you want to generate it:

types := []string{}
for _, v := range eventTypes {
  types = append(types, v)
}
return types

Copy link
Member

@aanm aanm left a comment

Choose a reason for hiding this comment

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

Great additions. I've one question. Is it possible do multiple filters at the same time?

func init() {
RootCmd.AddCommand(monitorCmd)
monitorCmd.Flags().IntVarP(&eventConfig.NumCpus, "num-cpus", "c", runtime.NumCPU(), "Number of CPUs")
monitorCmd.Flags().IntVarP(&eventConfig.NumPages, "num-pages", "n", 64, "Number of pages for ring buffer")
monitorCmd.Flags().BoolVarP(&dissect, "dissect", "d", false, "Dissect packet data")
monitorCmd.Flags().StringVarP(&eventType, "type", "t", "", fmt.Sprintf("Filter by event types %v", listEventTypes()))
monitorCmd.Flags().Uint16Var(&fromSource, "from", 0, "filter by source endpoint id")
Copy link
Member

Choose a reason for hiding this comment

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

filter - > Filter

The same goes with the next 2 liness

func init() {
RootCmd.AddCommand(monitorCmd)
monitorCmd.Flags().IntVarP(&eventConfig.NumCpus, "num-cpus", "c", runtime.NumCPU(), "Number of CPUs")
monitorCmd.Flags().IntVarP(&eventConfig.NumPages, "num-pages", "n", 64, "Number of pages for ring buffer")
monitorCmd.Flags().BoolVarP(&dissect, "dissect", "d", false, "Dissect packet data")
monitorCmd.Flags().StringVarP(&eventType, "type", "t", "", fmt.Sprintf("Filter by event types %v", listEventTypes()))
monitorCmd.Flags().Uint16Var(&fromSource, "from", 0, "filter by source endpoint id")
Copy link
Member

Choose a reason for hiding this comment

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

Why Uint16Var and the others have Uint32Var?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

return false
} else if toDst > 0 && toDst != dst {
return false
} else if uint16(related) != src && related > 0 && related != dst {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be related > 0 && uint16(related) != src && related != dst?

@aalemayhu
Copy link
Contributor Author

@aanm yes combining options should work fine, but please try out. If you discover something doesn't work. Let me know, so I can fix and add a test for it. Thanks.

@aanm
Copy link
Member

aanm commented May 10, 2017

@scanf How does the to flag works? I've been using it but I don't see any packets showing up, only if I use the from flag.

@aalemayhu
Copy link
Contributor Author

@aanm --to option uses the .Arg1 or .DstID which is what I thought
destination is supposed to be. Can you show an example of how you are using it?
Did you enable the relevant configuration you are interested in cilium config Debug=true DropNotification=true Policy=true?

@aanm
Copy link
Member

aanm commented May 10, 2017

@scanf why Policy needs to be set to true?

if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dm); err != nil {
fmt.Printf("Error while parsing debug message: %s\n", err)
}
if match(bpfdebug.MessageTypeDebug, dm.Source, dm.Arg1) {
Copy link
Member

Choose a reason for hiding this comment

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

Passing dm.Arg1 as destination ID is wrong. In most cases, that is not the destination. We can't support --to for debug messages. Let's just pass in0 for now.

if err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &dc); err != nil {
fmt.Printf("Error while parsing debug capture message: %s\n", err)
}
if match(bpfdebug.MessageTypeCapture, dc.Source, dc.Arg1) {
Copy link
Member

Choose a reason for hiding this comment

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

Same here, we would need to extend the BPF progs to always specify the destination ID before we can pass that in. dc.Arg1 will mean something different depending on the actual message being sent.

This will be used for testing the new filtering arguments in a follow up
commit.

Related-to: #473 (Feature: Add filtering to cilium monitor)
Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
monitor_resume is useful because it behaves the same as monitor_start()
but instead does not overwrite DUMP_FILE. This will be used in follow up
to test multiple runs of the monitor.

Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
)

func lostEvent(lost *bpf.PerfEventLost, cpu int) {
fmt.Printf("Lost %d events\n", lost.Lost)
fmt.Printf("CPU %02d: Lost %d events\n", lost.Lost, cpu)
Copy link
Member

Choose a reason for hiding this comment

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

The ordering seems incorrect here - it should be:
fmt.Printf("CPU: %02d: Lost %d events\n", cpu, lost.Lost)

return true
}

func dropEvents(prefix string, data []byte) {
Copy link
Member

Choose a reason for hiding this comment

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

Documentation needed for this function.

}
}

func debugEvents(prefix string, data []byte) {
Copy link
Member

Choose a reason for hiding this comment

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

Documentation needed for this function.

}
}

func captureEvents(prefix string, data []byte) {
Copy link
Member

Choose a reason for hiding this comment

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

Documentation needed for this function.

}
}

func receiveEvent(msg *bpf.PerfEventSample, cpu int) {
Copy link
Member

Choose a reason for hiding this comment

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

Documentation needed for this function.

Copy link
Member

@ianvernon ianvernon left a comment

Choose a reason for hiding this comment

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

Mainly nits on my part, but please add the requested documentation.

We are already printing it in func receiveEvent(...). To be consistent
print it here as well, and maybe this will be useful for future
debugging.

Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
The new filtering support consists of `--type`, `--to` and `--from`.
The `cilium help monitor` output now looks like this:

    The monitor displays notifications and events omitted by the BPF
    programs attached to endpoints and devices. This includes:
      * Dropped packet notifications
      * Captured packet traces
      * Debugging information

    Usage:
      cilium monitor [flags]

    Flags:
      -d, --dissect             Dissect packet data
          --from uint16         filter by source endpoint id
      -c, --num-cpus int        Number of CPUs (default 2)
      -n, --num-pages int       Number of pages for ring buffer (default 64)
          --related-to uint32   filter by either source or destination endpoint id
          --to uint32           filter by destination endpoint id
      -t, --type string         Filter by event types [drop debug capture]

    Global Flags:
          --config string   config file (default is $HOME/.cilium.yaml)
      -D, --debug           Enable debug messages
      -H, --host string     URI to server-side API

Some example usage:

- `cilium monitor --type drop` will only show you messages for packets being
dropped.
- `cilium monitor --type drop --from 173` is same as above but will only match
when the source has the provided id.
- `cilium monitor --type drop --to 123` should match when we get a drop event
and the destination has the provided id.
- `cilium monitor --type drop --related-to 749` shows drop notifications where
the source or destination has the provided id.

Closes: #473 (Feature: Add filtering to cilium monitor)
Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
@aalemayhu
Copy link
Contributor Author

@aanm sorry, the policy part can be ignored. Please try again to see if you still have issues.

@aalemayhu
Copy link
Contributor Author

@ianvernon fixed, let me know what to reword. Thanks!

@aalemayhu aalemayhu self-assigned this May 11, 2017
@tgraf tgraf requested review from aanm and ianvernon May 12, 2017 20:25
aanm
aanm previously requested changes May 12, 2017
// are supplied. If either one of them is less than zero, then it is assumed user did
// use them.
func match(messageType int, src uint16, dst uint32) bool {
if eventTypeIdx > bpfdebug.MessageTypeUnspec && messageType != eventTypeIdx {
Copy link
Member

Choose a reason for hiding this comment

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

@scanf was this addressed?

@aalemayhu
Copy link
Contributor Author

@aanm I am not sure what you mean in the last comment. Could you elaborate on what should have been addressed? Thanks.

@tgraf tgraf dismissed aanm’s stale review May 13, 2017 11:28

Let's merge as-is, we can fix stlye afterwards.

@tgraf tgraf merged commit bc0d0e5 into cilium:master May 13, 2017
@aanm
Copy link
Member

aanm commented May 13, 2017

@scanf I was referring this comment #673 (comment)

@aalemayhu aalemayhu deleted the filter-473 branch May 13, 2017 11:44
tgraf pushed a commit that referenced this pull request May 14, 2017
Thomas says:
>The > is misleading

Related-to: #673 (Add support for filtering events and minor related changes)
Suggested-by: Thomas Graf <thomas@cilium.io>
Suggested-by: André Martins <andre@cilium.io>
Signed-off-by: Alexander Alemayhu <alexander@alemayhu.com>
@aalemayhu aalemayhu removed their assignment Jan 16, 2018
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

4 participants