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

Enable support for ebpf program type tracepoints #389

Merged
merged 4 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 44 additions & 83 deletions bpfprogs/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ func NewBpfProgram(ctx context.Context, program models.BPFProgram, conf *config.
progMapFilePath = filepath.Join(conf.BpfMapDefaultPath, ifaceName, program.MapName)
} else if program.ProgType == models.TCType {
progMapFilePath = filepath.Join(conf.BpfMapDefaultPath, models.TCMapPinPath, ifaceName, program.MapName)
} else {
log.Error().Msgf("unsupported program type - %s", program.ProgType)
return nil
}
if strings.Contains(progMapFilePath, "..") {
log.Error().Msgf("program map file contains relative path %s", progMapFilePath)
Expand Down Expand Up @@ -292,9 +289,12 @@ func (b *BPF) Stop(ifaceName, direction string, chain bool) error {
}

args := make([]string, 0, len(b.Program.StopArgs)<<1)
args = append(args, "--iface="+ifaceName) // detaching from iface
args = append(args, "--direction="+direction) // xdpingress or ingress or egress

if len(ifaceName) > 0 {
args = append(args, "--iface="+ifaceName) // detaching from iface
}
if len(direction) > 0 {
args = append(args, "--direction="+direction) // xdpingress or ingress or egress
}
for k, val := range b.Program.StopArgs {
if v, ok := val.(string); !ok {
err := fmt.Errorf("stop args is not a string for the bpf program %s", b.Program.Name)
Expand Down Expand Up @@ -1077,12 +1077,6 @@ func (b *BPF) LoadXDPAttachProgram(ifaceName string) error {

// UnloadProgram - Unload or detach the program from the interface and close all the program resources
func (b *BPF) UnloadProgram(ifaceName, direction string) error {
_, err := net.InterfaceByName(ifaceName)
if err != nil {
log.Error().Err(err).Msgf("UnloadProgram - look up network iface %q", ifaceName)
return err
}

// Verifying program attached to the interface.
// SeqID will be 0 for root program or any other program without chaining
if b.Program.SeqID == 0 || !b.hostConfig.BpfChainingEnabled {
Expand Down Expand Up @@ -1214,7 +1208,7 @@ func (b *BPF) LoadBPFProgram(ifaceName string) error {
var mapPinPath string
if b.Program.ProgType == models.TCType {
mapPinPath = filepath.Join(b.hostConfig.BpfMapDefaultPath, models.TCMapPinPath, ifaceName)
} else {
} else if b.Program.ProgType == models.XDPType {
mapPinPath = filepath.Join(b.hostConfig.BpfMapDefaultPath, ifaceName)
}
collOptions := ebpf.CollectionOptions{
Expand All @@ -1236,31 +1230,33 @@ func (b *BPF) LoadBPFProgram(ifaceName string) error {
return fmt.Errorf("LoadBPFProgramProbeTypes failed with error %v ", err)
}

bpfProg := prg.Programs[b.Program.EntryFunctionName]
if bpfProg == nil {
return fmt.Errorf("%s entry function is not found in the loaded object file of the program %s", b.Program.EntryFunctionName, b.Program.Name)
}
//var bpfProg *ebpf.Program
if len(b.Program.EntryFunctionName) > 0 {
bpfProg := prg.Programs[b.Program.EntryFunctionName]
if bpfProg == nil {
return fmt.Errorf("%s entry function is not found in the loaded object file of the program %s", b.Program.EntryFunctionName, b.Program.Name)
}

progInfo, err := bpfProg.Info()
if err != nil {
return fmt.Errorf("%s: information of bpf program failed : %w", b.Program.Name, err)
}
progInfo, err := bpfProg.Info()
if err != nil {
return fmt.Errorf("%s: information of bpf program failed : %w", b.Program.Name, err)
}

ok := false
b.ProgID, ok = progInfo.ID()
if !ok {
log.Warn().Msgf("Program ID fetch failed: %s", b.Program.Name)
}
ok := false
b.ProgID, ok = progInfo.ID()
if !ok {
log.Warn().Msgf("Program ID fetch failed: %s", b.Program.Name)
}

// Initialise metric maps
if err := b.InitialiseMetricMaps(); err != nil {
return fmt.Errorf("initialising metric maps failed %w", err)
}
// Initialise metric maps
if err := b.InitialiseMetricMaps(); err != nil {
return fmt.Errorf("initialising metric maps failed %w", err)
}

if err := b.PinBpfMaps(ifaceName); err != nil {
return err
if err := b.PinBpfMaps(ifaceName); err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -1382,8 +1378,12 @@ func (b *BPF) StartUserProgram(ifaceName, direction string, chain bool) error {
}

args := make([]string, 0, len(b.Program.StartArgs)<<1)
args = append(args, "--iface="+ifaceName) // attaching to interface
args = append(args, "--direction="+direction) // direction xdpingress or ingress or egress
if len(ifaceName) > 0 {
args = append(args, "--iface="+ifaceName) // attaching to interface
}
if len(direction) > 0 {
args = append(args, "--direction="+direction) // direction xdpingress or ingress or egress
}

if chain && b.ProgMapCollection == nil {
// chaining from user program
Expand Down Expand Up @@ -1445,12 +1445,15 @@ func (b *BPF) CreateMapPinDirectory(ifaceName string) error {
} else if b.Program.ProgType == models.TCType {
mapPathDir = filepath.Join(b.hostConfig.BpfMapDefaultPath, models.TCMapPinPath, ifaceName)
}
// codeQL Check
if strings.Contains(mapPathDir, "..") {
return fmt.Errorf("%s contains relative path is not supported - %s", mapPathDir, b.Program.Name)
}
if err := os.MkdirAll(mapPathDir, 0750); err != nil {
return fmt.Errorf("%s failed to create map dir path of %s program %s with err : %w", mapPathDir, b.Program.ProgType, b.Program.Name, err)
// Create map dir for XDP and TC programs only
if len(mapPathDir) > 0 {
// codeQL Check
if strings.Contains(mapPathDir, "..") {
return fmt.Errorf("%s contains relative path is not supported - %s", mapPathDir, b.Program.Name)
}
if err := os.MkdirAll(mapPathDir, 0750); err != nil {
return fmt.Errorf("%s failed to create map dir path of %s program %s with err : %w", mapPathDir, b.Program.ProgType, b.Program.Name, err)
}
}
return nil
}
Expand Down Expand Up @@ -1549,45 +1552,3 @@ func (b *BPF) LoadBPFProgramChain(ifaceName, direction string) error {
log.Info().Msgf("eBPF program %s loaded on interface %s direction %s successfully", b.Program.Name, ifaceName, direction)
return nil
}

// LoadBPFProgramProbeTypes - Load the BPF programs of probe types - TracePoint
func (b *BPF) LoadBPFProgramProbeTypes(objSpec *ebpf.CollectionSpec) error {
for i, prog := range b.ProgMapCollection.Programs {
if i == b.Program.EntryFunctionName {
// skipping XDP/TC programs
continue
}
if err := b.LoadBPFProgramProbeType(prog, objSpec.Programs[i].SectionName); err != nil {
return err
}
}
return nil
}

func (b *BPF) LoadBPFProgramProbeType(prog *ebpf.Program, sectionName string) error {
switch prog.Type() {
case ebpf.TracePoint:
group, probeName := GetProgramSectionDetails(sectionName)
tp, err := link.Tracepoint(group, probeName, prog, nil)
if err != nil {
return fmt.Errorf("failed to link tracepoint sec name %s error %v", sectionName, err)
}
b.ProbeLinks = append(b.ProbeLinks, &tp)
default:
return fmt.Errorf("un-supported probe type %s ", prog.Type())
}
return nil
}

// GetProgramSectionDetails returns group and name details
// Section name format /prob type/group/name
// e.g.: tracepoint/sock/inet_sock_set_state
// e.g.: kprobe/sys_execve
func GetProgramSectionDetails(sectionName string) (string, string) {
sections := strings.Split(sectionName, "/")
length := len(sections)
if length > 1 {
return sections[length-2], sections[length-1]
}
return "", ""
}
29 changes: 24 additions & 5 deletions bpfprogs/bpfmetrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ func NewpBPFMetrics(chain bool, interval int) *bpfMetrics {
return m
}

func (c *bpfMetrics) bpfMetricsStart(xdpProgs, ingressTCProgs, egressTCProgs map[string]*list.List) {
go c.bpfMetricsWorker(xdpProgs, models.XDPIngressType)
go c.bpfMetricsWorker(ingressTCProgs, models.IngressType)
go c.bpfMetricsWorker(egressTCProgs, models.EgressType)
func (c *bpfMetrics) bpfMetricsStart(xdpProgs, ingressTCProgs, egressTCProgs map[string]*list.List, probes *list.List) {
go c.bpfMetricsWorker(xdpProgs)
go c.bpfMetricsWorker(ingressTCProgs)
go c.bpfMetricsWorker(egressTCProgs)
go c.BPFMetricsProbeWorker(probes)
}

func (c *bpfMetrics) bpfMetricsWorker(bpfProgs map[string]*list.List, direction string) {
func (c *bpfMetrics) bpfMetricsWorker(bpfProgs map[string]*list.List) {
for range time.NewTicker(1 * time.Second).C {
for ifaceName, bpfList := range bpfProgs {
if bpfList == nil { // no bpf programs are running
Expand All @@ -53,3 +54,21 @@ func (c *bpfMetrics) bpfMetricsWorker(bpfProgs map[string]*list.List, direction
}
}
}

func (c *bpfMetrics) BPFMetricsProbeWorker(bpfProgs *list.List) {
for range time.NewTicker(1 * time.Second).C {
if bpfProgs == nil {
time.Sleep(time.Second)
continue
}
for e := bpfProgs.Front(); e != nil; e = e.Next() {
bpf := e.Value.(*BPF)
if bpf.Program.AdminStatus == models.Disabled {
continue
}
if err := bpf.MonitorMaps("", c.Intervals); err != nil {
log.Error().Err(err).Msgf("pMonitor probe monitor maps failed - %s", bpf.Program.Name)
}
}
}
}
7 changes: 4 additions & 3 deletions bpfprogs/bpfmetrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"
)

func TestNewpBPFMetrics(t *testing.T) {
func TestNewpKFMetrics(t *testing.T) {
type args struct {
chain bool
interval int
Expand Down Expand Up @@ -37,7 +37,7 @@ func TestNewpBPFMetrics(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := NewpBPFMetrics(tt.args.chain, tt.args.interval)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewBPFMetrics() = %v, want %v", got, tt.want)
t.Errorf("NewKFMetrics() = %v, want %v", got, tt.want)
}
})
}
Expand All @@ -52,6 +52,7 @@ func Test_BPFMetrics_Start(t *testing.T) {
IngressXDPbpfProgs map[string]*list.List
IngressTCbpfProgs map[string]*list.List
EgressTCbpfProgs map[string]*list.List
Probes *list.List
}
tests := []struct {
name string
Expand All @@ -75,7 +76,7 @@ func Test_BPFMetrics_Start(t *testing.T) {
Chain: tt.fields.Chain,
Intervals: tt.fields.Interval,
}
c.bpfMetricsStart(tt.args.IngressXDPbpfProgs, tt.args.IngressTCbpfProgs, tt.args.EgressTCbpfProgs)
c.bpfMetricsStart(tt.args.IngressXDPbpfProgs, tt.args.IngressTCbpfProgs, tt.args.EgressTCbpfProgs, tt.args.Probes)
})
}
}
Loading
Loading