Skip to content

Commit

Permalink
Enable support for ebpf program type Probes
Browse files Browse the repository at this point in the history
Signed-off-by: Santhosh Fernandes <[email protected]>
  • Loading branch information
sanfern committed Jun 5, 2024
1 parent 76e980c commit 668f371
Show file tree
Hide file tree
Showing 11 changed files with 344 additions and 81 deletions.
14 changes: 14 additions & 0 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,13 @@ const docTemplate = `{
"models.BPFProgramNames": {
"type": "object",
"properties": {
"probes": {
"description": "names of the probe eBPF programs",
"type": "array",
"items": {
"type": "string"
}
},
"tc_egress": {
"description": "names of the TC egress eBPF programs",
"type": "array",
Expand All @@ -338,6 +345,13 @@ const docTemplate = `{
"models.BPFPrograms": {
"type": "object",
"properties": {
"probes": {
"description": "list of probe bpf programs",
"type": "array",
"items": {
"$ref": "#/definitions/models.BPFProgram"
}
},
"tc_egress": {
"description": "list of tc egress bpf programs",
"type": "array",
Expand Down
14 changes: 14 additions & 0 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,13 @@
"models.BPFProgramNames": {
"type": "object",
"properties": {
"probes": {
"description": "names of the probe eBPF programs",
"type": "array",
"items": {
"type": "string"
}
},
"tc_egress": {
"description": "names of the TC egress eBPF programs",
"type": "array",
Expand All @@ -331,6 +338,13 @@
"models.BPFPrograms": {
"type": "object",
"properties": {
"probes": {
"description": "list of probe bpf programs",
"type": "array",
"items": {
"$ref": "#/definitions/models.BPFProgram"
}
},
"tc_egress": {
"description": "list of tc egress bpf programs",
"type": "array",
Expand Down
10 changes: 10 additions & 0 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ definitions:
type: object
models.BPFProgramNames:
properties:
probes:
description: names of the probe eBPF programs
items:
type: string
type: array
tc_egress:
description: names of the TC egress eBPF programs
items:
Expand All @@ -124,6 +129,11 @@ definitions:
type: object
models.BPFPrograms:
properties:
probes:
description: list of probe bpf programs
items:
$ref: '#/definitions/models.BPFProgram'
type: array
tc_egress:
description: list of tc egress bpf programs
items:
Expand Down
114 changes: 44 additions & 70 deletions kf/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 @@ -1063,12 +1063,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 @@ -1198,7 +1192,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 @@ -1220,31 +1214,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 @@ -1366,8 +1362,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 @@ -1429,12 +1429,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 @@ -1534,35 +1537,6 @@ func (b *BPF) LoadBPFProgramChain(ifaceName, direction string) error {
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
Expand Down
29 changes: 24 additions & 5 deletions kf/kfmetrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ func NewpKFMetrics(chain bool, interval int) *kfMetrics {
return m
}

func (c *kfMetrics) kfMetricsStart(xdpProgs, ingressTCProgs, egressTCProgs map[string]*list.List) {
go c.kfMetricsWorker(xdpProgs, models.XDPIngressType)
go c.kfMetricsWorker(ingressTCProgs, models.IngressType)
go c.kfMetricsWorker(egressTCProgs, models.EgressType)
func (c *kfMetrics) kfMetricsStart(xdpProgs, ingressTCProgs, egressTCProgs map[string]*list.List, probes *list.List) {
go c.kfMetricsWorker(xdpProgs)
go c.kfMetricsWorker(ingressTCProgs)
go c.kfMetricsWorker(egressTCProgs)
go c.kfMetricsProbeWorker(probes)
}

func (c *kfMetrics) kfMetricsWorker(bpfProgs map[string]*list.List, direction string) {
func (c *kfMetrics) kfMetricsWorker(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 *kfMetrics) kfMetricsWorker(bpfProgs map[string]*list.List, direction st
}
}
}

func (c *kfMetrics) kfMetricsProbeWorker(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)
}
}
}
}
3 changes: 2 additions & 1 deletion kf/kfmetrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func Test_KFMetrics_Start(t *testing.T) {
IngressXDPbpfProgs map[string]*list.List
IngressTCbpfProgs map[string]*list.List
EgressTCbpfProgs map[string]*list.List
Probebpfs list.List
}
tests := []struct {
name string
Expand All @@ -75,7 +76,7 @@ func Test_KFMetrics_Start(t *testing.T) {
Chain: tt.fields.Chain,
Intervals: tt.fields.Interval,
}
c.kfMetricsStart(tt.args.IngressXDPbpfProgs, tt.args.IngressTCbpfProgs, tt.args.EgressTCbpfProgs)
c.kfMetricsStart(tt.args.IngressXDPbpfProgs, tt.args.IngressTCbpfProgs, tt.args.EgressTCbpfProgs, &tt.args.Probebpfs)
})
}
}
Loading

0 comments on commit 668f371

Please sign in to comment.