nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: cilium/ebpf
Pull request #526 (2021-12-14 14:40:08)

cmd/bpf2go: allow to specify native target
This allows to invoke `bpf2go` to build for the native architecture and
have `__TARGET_ARCH_xxx` defined based on `GOARCH` without having to
derive the  architecture e.g. as part of the build system.

For example this would be useful in github.com/cilium/pwru:

    //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -target native KProbePWRU ./bpf/kprobe_pwru.c -- -DOUTPUT_SKB -I./bpf/headers


Patch:
diff --git a/cmd/bpf2go/main.go b/cmd/bpf2go/main.go
index 0e115f0..4ff3c1f 100644
--- a/cmd/bpf2go/main.go
+++ b/cmd/bpf2go/main.go
@@ -10,6 +10,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"runtime"
 	"sort"
 	"strings"
 )
@@ -358,6 +359,10 @@ func collectTargets(targets []string) (map[target][]string, error) {
 			sort.Strings(goarches)
 			result[target{tgt, ""}] = goarches
 
+		case "native":
+			tgt = runtime.GOARCH
+			fallthrough
+
 		default:
 			archTarget, ok := targetByGoArch[tgt]
 			if !ok || archTarget.linux == "" {


Test patch:
diff --git a/cmd/bpf2go/main_test.go b/cmd/bpf2go/main_test.go
index afb59b2..8492b86 100644
--- a/cmd/bpf2go/main_test.go
+++ b/cmd/bpf2go/main_test.go
@@ -7,6 +7,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"runtime"
 	"sort"
 	"strings"
 	"testing"
@@ -142,6 +143,18 @@ func TestCollectTargets(t *testing.T) {
 		sort.Strings(linuxArchesBE[i])
 	}
 
+	nativeTarget := make(map[target][]string)
+	for arch, archTarget := range targetByGoArch {
+		if arch == runtime.GOARCH {
+			if archTarget.clang == "bpfel" {
+				nativeTarget[archTarget] = linuxArchesLE[archTarget.linux]
+			} else {
+				nativeTarget[archTarget] = linuxArchesBE[archTarget.linux]
+			}
+			break
+		}
+	}
+
 	tests := []struct {
 		targets []string
 		want    map[target][]string
@@ -167,6 +180,10 @@ func TestCollectTargets(t *testing.T) {
 				{"bpfel", "x86"}:   linuxArchesLE["x86"],
 			},
 		},
+		{
+			[]string{"native"},
+			nativeTarget,
+		},
 	}
 
 	for _, test := range tests {
Repository: cilium/ebpf
Pull request #584 (2022-02-23 15:27:31)

collection: don't copy btf.Spec in CollectionSpec.Copy()
Copying btf.Spec requires updating Map/Program.BTF.(S,s)pec, which gets complicated due to btf.Map/Program being pointers.

Instead of implementing a full deep-copy, avoid copying btf.Spec for now, since it's considered read-only. Since we're planning to get rid of btf.Program/Map anyway, this would not be worth the investment.

Add a test that loads both a copy and an original CollectionSpec.

lmb: Ci errors are real, you're missing a `testutils.SkipIfNotSupported`. 

Patch:
diff --git a/collection.go b/collection.go
index 9bb0a2d..8d27828 100644
--- a/collection.go
+++ b/collection.go
@@ -28,6 +28,7 @@ type CollectionSpec struct {
 	Programs map[string]*ProgramSpec
 
 	// Types holds type information about Maps and Programs.
+	// Modifications to Types are currently undefined behaviour.
 	Types *btf.Spec
 
 	// ByteOrder specifies whether the ELF was compiled for
@@ -45,7 +46,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
 		Maps:      make(map[string]*MapSpec, len(cs.Maps)),
 		Programs:  make(map[string]*ProgramSpec, len(cs.Programs)),
 		ByteOrder: cs.ByteOrder,
-		Types:     cs.Types.Copy(),
+		Types:     cs.Types,
 	}
 
 	for name, spec := range cs.Maps {


Test patch:
diff --git a/collection_test.go b/collection_test.go
index 714e74a..e40a749 100644
--- a/collection_test.go
+++ b/collection_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/cilium/ebpf/asm"
+	"github.com/cilium/ebpf/internal"
 	"github.com/cilium/ebpf/internal/btf"
 	"github.com/cilium/ebpf/internal/testutils"
 )
@@ -83,8 +84,32 @@ func TestCollectionSpecCopy(t *testing.T) {
 		t.Error("Copy returned same Programs")
 	}
 
-	if cpy.Types == cs.Types {
-		t.Error("Copy returned same Types")
+	if cpy.Types != cs.Types {
+		t.Error("Copy returned different Types")
+	}
+}
+
+func TestCollectionSpecLoadCopy(t *testing.T) {
+	file := fmt.Sprintf("testdata/loader-%s.elf", internal.ClangEndian)
+	spec, err := LoadCollectionSpec(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	spec2 := spec.Copy()
+
+	var objs struct {
+		Prog *Program `ebpf:"xdp_prog"`
+	}
+
+	err = spec.LoadAndAssign(&objs, nil)
+	testutils.SkipIfNotSupported(t, err)
+	if err != nil {
+		t.Fatal("Loading original spec:", err)
+	}
+
+	if err := spec2.LoadAndAssign(&objs, nil); err != nil {
+		t.Fatal("Loading copied spec:", err)
 	}
 }
Repository: cilium/ebpf
Pull request #1232 (2023-11-23 15:40:41)

link: rename First, Last to Head, Tail
Timo suggested renaming First and Last to make it less likely that users assume that the position is guaranteed for the lifetime of the link.

lmb: I tried looking for that as well, not much luck so far.

Patch:
diff --git a/.github/workflows/apidiff.yml b/.github/workflows/apidiff.yml
index c4bca90..ac86eb1 100644
--- a/.github/workflows/apidiff.yml
+++ b/.github/workflows/apidiff.yml
@@ -21,15 +21,14 @@ jobs:
 
       - name: Run go-apidiff
         id: apidiff
+        continue-on-error: true
         uses: joelanford/go-apidiff@main
 
       - name: Create apidiff.json
-        if: always()
         run: |
           echo '{"id": ${{ github.event.pull_request.number }}, "semver-type": "${{ steps.apidiff.outputs.semver-type }}"}' > apidiff.json
 
       - name: Upload apidiff.json
-        if: always()
         uses: actions/upload-artifact@v3
         with:
           name: apidiff
diff --git a/link/anchor.go b/link/anchor.go
index 983296d..1a3b5f7 100644
--- a/link/anchor.go
+++ b/link/anchor.go
@@ -35,7 +35,8 @@ func (firstAnchor) anchor() (fdOrID, flags uint32, _ error) {
 	return 0, sys.BPF_F_BEFORE, nil
 }
 
-func First() Anchor {
+// Head is the position before all other programs or links.
+func Head() Anchor {
 	return firstAnchor{}
 }
 
@@ -45,7 +46,8 @@ func (lastAnchor) anchor() (fdOrID, flags uint32, _ error) {
 	return 0, sys.BPF_F_AFTER, nil
 }
 
-func Last() Anchor {
+// Tail is the position after all other programs or links.
+func Tail() Anchor {
 	return lastAnchor{}
 }
 


Test patch:
diff --git a/link/program_test.go b/link/program_test.go
index 2d56212..3fabe3f 100644
--- a/link/program_test.go
+++ b/link/program_test.go
@@ -84,8 +84,8 @@ func TestRawAttachProgramAnchor(t *testing.T) {
 	b := mustLoadProgram(t, ebpf.SchedCLS, 0, "")
 
 	for _, anchor := range []Anchor{
-		First(),
-		Last(),
+		Head(),
+		Tail(),
 		AfterProgram(a),
 		AfterProgramByID(aID),
 		AfterLink(link),
diff --git a/link/tcx_test.go b/link/tcx_test.go
index 77cde74..53ac959 100644
--- a/link/tcx_test.go
+++ b/link/tcx_test.go
@@ -39,8 +39,8 @@ func TestTCXAnchor(t *testing.T) {
 	linkID := linkInfo.ID
 
 	for _, anchor := range []Anchor{
-		First(),
-		Last(),
+		Head(),
+		Tail(),
 		BeforeProgram(a),
 		BeforeProgramByID(programID),
 		AfterLink(linkA),
Repository: cilium/ebpf
Pull request #1267 (2023-12-12 17:49:16)

cmd/bpf2go: rephrase GOPACKAGE error message
The current error message makes people think that bpf2go can only be invoked via go generate. In fact we just expect to find the package name in GOPACKAGE.

Reword the error and add a test to make sure that the error message mentions the variable.

lmb: Based on https://github.com/cilium/ebpf/discussions/1265

Patch:
diff --git a/cmd/bpf2go/main.go b/cmd/bpf2go/main.go
index c96e042..92d7227 100644
--- a/cmd/bpf2go/main.go
+++ b/cmd/bpf2go/main.go
@@ -149,7 +149,7 @@ func newB2G(stdout io.Writer, pkg, outputDir string, args []string) (*bpf2go, er
 	}
 
 	if b2g.pkg == "" {
-		return nil, errors.New("missing package, are you running via go generate?")
+		return nil, errors.New("missing package, have you set GOPACKAGE?")
 	}
 
 	if b2g.cc == "" {
@@ -484,6 +484,8 @@ func collectTargets(targets []string) (map[target][]string, error) {
 	return result, nil
 }
 
+const gopackageEnv = "GOPACKAGE"
+
 func main() {
 	outputDir, err := os.Getwd()
 	if err != nil {
@@ -491,7 +493,7 @@ func main() {
 		os.Exit(1)
 	}
 
-	if err := run(os.Stdout, os.Getenv("GOPACKAGE"), outputDir, os.Args[1:]); err != nil {
+	if err := run(os.Stdout, os.Getenv(gopackageEnv), outputDir, os.Args[1:]); err != nil {
 		fmt.Fprintln(os.Stderr, "Error:", err)
 		os.Exit(1)
 	}


Test patch:
diff --git a/cmd/bpf2go/main_test.go b/cmd/bpf2go/main_test.go
index 8b22433..493cde0 100644
--- a/cmd/bpf2go/main_test.go
+++ b/cmd/bpf2go/main_test.go
@@ -105,6 +105,11 @@ func TestHelp(t *testing.T) {
 	}
 }
 
+func TestErrorMentionsEnvVar(t *testing.T) {
+	err := run(io.Discard, "", "", nil)
+	qt.Assert(t, qt.StringContains(err.Error(), gopackageEnv), qt.Commentf("Error should include name of environment variable"))
+}
+
 func TestDisableStripping(t *testing.T) {
 	dir := mustWriteTempFile(t, "test.c", minimalSocketFilter)
 
diff --git a/link/uprobe_test.go b/link/uprobe_test.go
index 501420b..fdc6125 100644
--- a/link/uprobe_test.go
+++ b/link/uprobe_test.go
@@ -117,9 +117,8 @@ func TestUprobeExtWithOpts(t *testing.T) {
 	// NB: It's not possible to invoke the uprobe since we use an arbitrary
 	// address.
 	up, err := bashEx.Uprobe("open", prog, &UprobeOptions{
-		// arm64 doesn't seem to allow addresses on the first page. Use
-		// the first byte of the second page.
-		Address: uint64(os.Getpagesize()),
+		// arm64 requires the addresses to be aligned (a multiple of 4)
+		Address: 0x4,
 	})
 	if err != nil {
 		t.Fatal(err)
Repository: cilium/ebpf
Pull request #1293 (2024-01-04 21:15:04)

Add link.Info.TCX method
Just like for other link types, this commit adds a method for retrieving TCX link specific extra metadata info.


Patch:
diff --git a/link/link.go b/link/link.go
index 590ea3a..2025b7d 100644
--- a/link/link.go
+++ b/link/link.go
@@ -160,7 +160,7 @@ func (r Info) NetNs() *NetNsInfo {
 	return e
 }
 
-// ExtraNetNs returns XDP type-specific link info.
+// XDP returns XDP type-specific link info.
 //
 // Returns nil if the type-specific link info isn't available.
 func (r Info) XDP() *XDPInfo {
@@ -168,6 +168,14 @@ func (r Info) XDP() *XDPInfo {
 	return e
 }
 
+// TCX returns TCX type-specific link info.
+//
+// Returns nil if the type-specific link info isn't available.
+func (r Info) TCX() *TCXInfo {
+	e, _ := r.extra.(*TCXInfo)
+	return e
+}
+
 // RawLink is the low-level API to bpf_link.
 //
 // You should consider using the higher level interfaces in this


Test patch:
diff --git a/link/link_test.go b/link/link_test.go
index 8bb2863..785c639 100644
--- a/link/link_test.go
+++ b/link/link_test.go
@@ -204,6 +204,11 @@ func testLink(t *testing.T, link Link, prog *ebpf.Program) {
 			if xdp.Ifindex == 0 {
 				t.Fatalf("Failed to get link XDP extra info")
 			}
+		case sys.BPF_LINK_TYPE_TCX:
+			tcx := info.TCX()
+			if tcx.Ifindex == 0 {
+				t.Fatalf("Failed to get link TCX extra info")
+			}
 		}
 	})
Repository: cilium/ebpf
Pull request #1294 (2024-01-05 10:00:25)

link: add feature test for tcx
As with many of the other existing APIs, this adds a feature test for tcx to indicate to the user if the underlying kernel APIs are available in the running kernel.


Patch:
diff --git a/link/syscalls.go b/link/syscalls.go
index 96d6c7b..a74f6af 100644
--- a/link/syscalls.go
+++ b/link/syscalls.go
@@ -125,3 +125,24 @@ var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() err
 	}
 	return errors.New("syscall succeeded unexpectedly")
 })
+
+var haveTCX = internal.NewFeatureTest("tcx", "6.6", func() error {
+	attr := sys.LinkCreateTcxAttr{
+		// We rely on this being checked during the syscall.
+		// With an otherwise correct payload we expect EBADF here
+		// as an indication that the feature is present.
+		ProgFd:        ^uint32(0),
+		TargetIfindex: ^uint32(0),
+		AttachType:    sys.AttachType(ebpf.AttachTCXIngress),
+	}
+
+	_, err := sys.LinkCreateTcx(&attr)
+
+	if errors.Is(err, unix.EBADF) {
+		return nil
+	}
+	if err != nil {
+		return ErrNotSupported
+	}
+	return errors.New("syscall succeeded unexpectedly")
+})
diff --git a/link/tcx.go b/link/tcx.go
index 6989af8..88f2237 100644
--- a/link/tcx.go
+++ b/link/tcx.go
@@ -55,6 +55,9 @@ func AttachTCX(opts TCXOptions) (Link, error) {
 	runtime.KeepAlive(opts.Program)
 	runtime.KeepAlive(opts.Anchor)
 	if err != nil {
+		if haveFeatErr := haveTCX(); haveFeatErr != nil {
+			return nil, haveFeatErr
+		}
 		return nil, fmt.Errorf("attach tcx link: %w", err)
 	}
 


Test patch:
diff --git a/link/syscalls_test.go b/link/syscalls_test.go
index 70fd983..28dfd3b 100644
--- a/link/syscalls_test.go
+++ b/link/syscalls_test.go
@@ -21,3 +21,7 @@ func TestHaveBPFLink(t *testing.T) {
 func TestHaveProgQuery(t *testing.T) {
 	testutils.CheckFeatureTest(t, haveProgQuery)
 }
+
+func TestHaveTCX(t *testing.T) {
+	testutils.CheckFeatureTest(t, haveTCX)
+}
Repository: cilium/ebpf
Pull request #1358 (2024-02-22 15:28:07)

btf: fix race in mutableTypes.copy
We reference mt.copiedTypeIDs during copy to be able to figure out the correct ID for a copied type. This access can currently race with mutableTypes.add since we don't protect mt.copiedTypeIDs.

Take a read lock to prevent modification.


Patch:
diff --git a/btf/btf.go b/btf/btf.go
index 1268a41..74a17a9 100644
--- a/btf/btf.go
+++ b/btf/btf.go
@@ -118,6 +118,10 @@ func (mt *mutableTypes) copy() mutableTypes {
 		make(map[Type]TypeID, len(mt.copiedTypeIDs)),
 	}
 
+	// Prevent concurrent modification of mt.copiedTypeIDs.
+	mt.mu.RLock()
+	defer mt.mu.RUnlock()
+
 	copies := make(map[Type]Type, len(mt.copies))
 	for orig, copy := range mt.copies {
 		// NB: We make a copy of copy, not orig, so that changes to mutable types


Test patch:
diff --git a/btf/btf_test.go b/btf/btf_test.go
index 02e6b5f..d2a043e 100644
--- a/btf/btf_test.go
+++ b/btf/btf_test.go
@@ -542,12 +542,16 @@ func TestSpecConcurrentAccess(t *testing.T) {
 		go func() {
 			defer wg.Done()
 
-			cond.Add(1)
+			n := cond.Add(1)
 			for cond.Load() != int64(maxprocs) {
 				// Spin to increase the chances of a race.
 			}
 
-			_, _ = spec.AnyTypeByName("gov_update_cpu_data")
+			if n%2 == 0 {
+				_, _ = spec.AnyTypeByName("gov_update_cpu_data")
+			} else {
+				_ = spec.Copy()
+			}
 		}()
 
 		// Try to get the Goroutines scheduled and spinning.
Repository: netlify/build
Pull request #1470 (2020-06-08 16:33:55)

Add some comments
This adds some code comments.


Patch:
diff --git a/packages/build/package.json b/packages/build/package.json
index 2c8b6a6ce..b59479dd6 100644
--- a/packages/build/package.json
+++ b/packages/build/package.json
@@ -81,7 +81,6 @@
     "get-node": "^6.6.0",
     "has-ansi": "^4.0.0",
     "nock": "^11.9.1",
-    "path-key": "^3.1.1",
     "yarn": "^1.22.4"
   },
   "engines": {


Test patch:
diff --git a/packages/build/tests/helpers/main.js b/packages/build/tests/helpers/main.js
index 05015e893..69b77a696 100644
--- a/packages/build/tests/helpers/main.js
+++ b/packages/build/tests/helpers/main.js
@@ -1,13 +1,8 @@
-const { delimiter } = require('path')
-const { env } = require('process')
-
 const { getBinPath } = require('get-bin-path')
-const pathKey = require('path-key')
 
 const { runFixtureCommon, FIXTURES_DIR } = require('./common')
 
 const ROOT_DIR = `${__dirname}/../..`
-const BUILD_BIN_DIR = `${ROOT_DIR}/node_modules/.bin`
 
 const runFixture = async function(t, fixtureName, { env: envOption, flags = '', ...opts } = {}) {
   return runFixtureCommon(t, fixtureName, {
@@ -18,13 +13,12 @@ const runFixture = async function(t, fixtureName, { env: envOption, flags = '',
       BUILD_TELEMETRY_DISABLED: '',
       // Ensure local tokens aren't used during development
       NETLIFY_AUTH_TOKEN: '',
-      // Allows executing any locally installed Node modules inside tests,
-      // regardless of the current directory
-      [pathKey()]: `${env[pathKey()]}${delimiter}${BUILD_BIN_DIR}`,
       ...envOption,
     },
   })
 }
+
+// Use a top-level promise so it's only performed once at load time
 const BINARY_PATH = getBinPath({ cwd: ROOT_DIR })
 
 module.exports = { runFixture, FIXTURES_DIR }
diff --git a/packages/config/tests/helpers/main.js b/packages/config/tests/helpers/main.js
index 934862fb5..3a8e09ed2 100644
--- a/packages/config/tests/helpers/main.js
+++ b/packages/config/tests/helpers/main.js
@@ -17,6 +17,8 @@ const runFixture = async function(t, fixtureName, { env, flags = '', ...opts } =
     flags: flagsB,
   })
 }
+
+// Use a top-level promise so it's only performed once at load time
 const BINARY_PATH = getBinPath({ cwd: ROOT_DIR })
 
 module.exports = { runFixture, FIXTURES_DIR, escapeExecaOpt, startServer }