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 2 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
2 changes: 1 addition & 1 deletion .github/workflows/ci-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Prep
run: |
sudo cp -r /home/runner/work/l3afd/l3afd /root
sudo git clone https://github.com/l3af-project/l3af-arch.git /root/l3af-arch
sudo git clone -b sanfern-e2e-add-probes https://github.com/sanfern/l3af-arch.git /root/l3af-arch

Choose a reason for hiding this comment

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

Please revert back once PR113 approved

sudo bash /root/l3af-arch/dev_environment/e2e_test/prep_env.sh
sudo bash /root/l3af-arch/dev_environment/setup_linux_dev_env.sh --ci-build
hm=$(hostname)
Expand Down
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
127 changes: 44 additions & 83 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
}

Choose a reason for hiding this comment

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

Is it suppose to add another check for the ProgType for tracepoints and keep the else for the type not supported?

Choose a reason for hiding this comment

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

I agree, we should have an explicit list of types we support

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This block is for defining the progMapFilePath for pinning, when we were not supporting probe types. We wanted to explicitly throw errors for other than prog types of tc or xdp. Since we are supporting probes, we don't need prog maps and also we are not chaining. We don't want to error out here in case of probes.

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 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
Loading