Skip to content

Commit

Permalink
Add support to disable BPF programs.
Browse files Browse the repository at this point in the history
If the page size for an enhanced event is 0, then don't attempt to load
that BPF program. This is helpful for BPF programs that generate massive
amounts of events (like disk events).
  • Loading branch information
russjones committed Jan 17, 2020
1 parent a87c1a3 commit d80f666
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 17 deletions.
10 changes: 5 additions & 5 deletions lib/bpf/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,23 @@ func New(config *Config) (BPF, error) {
start := time.Now()
log.Debugf("Starting enhanced session recording.")

// Compile and start BPF programs.
s.exec, err = startExec(closeContext, config.CommandBufferSize)
// Compile and start BPF programs if they are enabled (buffer size given).
s.exec, err = startExec(closeContext, *config.CommandBufferSize)
if err != nil {
return nil, trace.Wrap(err)
}
s.open, err = startOpen(closeContext, config.DiskBufferSize)
s.open, err = startOpen(closeContext, *config.DiskBufferSize)
if err != nil {
return nil, trace.Wrap(err)
}
s.conn, err = startConn(closeContext, config.NetworkBufferSize)
s.conn, err = startConn(closeContext, *config.NetworkBufferSize)
if err != nil {
return nil, trace.Wrap(err)
}

log.Debugf("Started enhanced session recording with buffer sizes (command=%v, "+
"disk=%v, network=%v) and cgroup mount path: %v. Took %v.",
s.CommandBufferSize, s.DiskBufferSize, s.NetworkBufferSize, s.CgroupPath,
*s.CommandBufferSize, *s.DiskBufferSize, *s.NetworkBufferSize, s.CgroupPath,
time.Since(start))

// Start pulling events off the perf buffers and emitting them to the
Expand Down
5 changes: 5 additions & 0 deletions lib/bpf/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ func startExec(closeContext context.Context, pageCount int) (*exec, error) {
closeContext: closeContext,
}

// If the page count is zero, don't start any BPF module.
if pageCount == 0 {
return e, nil
}

// Compile the BPF program.
e.module = bcc.NewModule(execveSource, []string{})
if e.module == nil {
Expand Down
21 changes: 12 additions & 9 deletions lib/bpf/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,31 @@ type Config struct {
Enabled bool

// CommandBufferSize is the size of the perf buffer for command events.
CommandBufferSize int
CommandBufferSize *int

// DiskBufferSize is the size of the perf buffer for disk events.
DiskBufferSize int
DiskBufferSize *int

// NetworkBufferSize is the size of the perf buffer for network events.
NetworkBufferSize int
NetworkBufferSize *int

// CgroupPath is where the cgroupv2 hierarchy is mounted.
CgroupPath string
}

// CheckAndSetDefaults checks BPF configuration.
func (c *Config) CheckAndSetDefaults() error {
if c.CommandBufferSize == 0 {
c.CommandBufferSize = defaults.PerfBufferPageCount
var perfBufferPageCount = defaults.PerfBufferPageCount
var openPerfBufferPageCount = defaults.OpenPerfBufferPageCount

if c.CommandBufferSize == nil {
c.CommandBufferSize = &perfBufferPageCount
}
if c.DiskBufferSize == 0 {
c.DiskBufferSize = defaults.OpenPerfBufferPageCount
if c.DiskBufferSize == nil {
c.DiskBufferSize = &openPerfBufferPageCount
}
if c.NetworkBufferSize == 0 {
c.NetworkBufferSize = defaults.PerfBufferPageCount
if c.NetworkBufferSize == nil {
c.NetworkBufferSize = &perfBufferPageCount
}
if c.CgroupPath == "" {
c.CgroupPath = defaults.CgroupPath
Expand Down
87 changes: 87 additions & 0 deletions lib/bpf/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package bpf

import (
"fmt"

"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"

"gopkg.in/check.v1"
)

type CommonSuite struct{}

var _ = fmt.Printf
var _ = check.Suite(&CommonSuite{})

func (s *CommonSuite) SetUpSuite(c *check.C) {
utils.InitLoggerForTests()
}
func (s *CommonSuite) TearDownSuite(c *check.C) {}
func (s *CommonSuite) SetUpTest(c *check.C) {}
func (s *CommonSuite) TearDownTest(c *check.C) {}

// TestCheckAndSetDefaults makes sure defaults are set when the user does not
// provide values for the page sizes and hard coded values (like zero or a
// specific page size) are respected when given.
func (s *CommonSuite) TestCheckAndSetDefaults(c *check.C) {
var perfBufferPageCount = defaults.PerfBufferPageCount
var openPerfBufferPageCount = defaults.OpenPerfBufferPageCount
var zeroPageCount = 0

var tests = []struct {
inConfig *Config
outConfig *Config
}{
// Empty values get defaults.
{
inConfig: &Config{
CommandBufferSize: nil,
DiskBufferSize: nil,
NetworkBufferSize: nil,
},
outConfig: &Config{
CommandBufferSize: &perfBufferPageCount,
DiskBufferSize: &openPerfBufferPageCount,
NetworkBufferSize: &perfBufferPageCount,
},
},
// Values are not wiped out with defaults.
{
inConfig: &Config{
CommandBufferSize: &zeroPageCount,
DiskBufferSize: &zeroPageCount,
NetworkBufferSize: &perfBufferPageCount,
},
outConfig: &Config{
CommandBufferSize: &zeroPageCount,
DiskBufferSize: &zeroPageCount,
NetworkBufferSize: &perfBufferPageCount,
},
},
}

for _, tt := range tests {
err := tt.inConfig.CheckAndSetDefaults()
c.Assert(err, check.IsNil)
c.Assert(*tt.inConfig.CommandBufferSize, check.Equals, *tt.outConfig.CommandBufferSize)
c.Assert(*tt.inConfig.DiskBufferSize, check.Equals, *tt.outConfig.DiskBufferSize)
c.Assert(*tt.inConfig.NetworkBufferSize, check.Equals, *tt.outConfig.NetworkBufferSize)
}
}
5 changes: 5 additions & 0 deletions lib/bpf/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ func startOpen(closeContext context.Context, pageCount int) (*open, error) {
closeContext: closeContext,
}

// If the page count is zero, don't start any BPF module.
if pageCount == 0 {
return e, nil
}

// Compile the BPF program.
e.module = bcc.NewModule(openSource, []string{})
if e.module == nil {
Expand Down
5 changes: 5 additions & 0 deletions lib/bpf/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func startConn(closeContext context.Context, pageCount int) (*conn, error) {
closeContext: closeContext,
}

// If the page count is zero, don't start any BPF module.
if pageCount == 0 {
return e, nil
}

e.module = bcc.NewModule(connSource, []string{})
if e.module == nil {
return nil, trace.BadParameter("failed to load libbcc")
Expand Down
6 changes: 3 additions & 3 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,13 +725,13 @@ type BPF struct {
Enabled string `yaml:"enabled"`

// CommandBufferSize is the size of the perf buffer for command events.
CommandBufferSize int `yaml:"command_buffer_size"`
CommandBufferSize *int `yaml:"command_buffer_size,omitempty"`

// DiskBufferSize is the size of the perf buffer for disk events.
DiskBufferSize int `yaml:"disk_buffer_size"`
DiskBufferSize *int `yaml:"disk_buffer_size,omitempty"`

// NetworkBufferSize is the size of the perf buffer for network events.
NetworkBufferSize int `yaml:"network_buffer_size"`
NetworkBufferSize *int `yaml:"network_buffer_size,omitempty"`

// CgroupPath controls where cgroupv2 hierarchy is mounted.
CgroupPath string `yaml:"cgroup_path"`
Expand Down

0 comments on commit d80f666

Please sign in to comment.