-
Notifications
You must be signed in to change notification settings - Fork 721
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The sys package is at the core of the library, so make it work on Windows to minimise changes to the rest of the code base. The first important piece is a custom FD abstraction. On Windows, operating system resources are identified by handles. The differences are large enough that the efW runtime decided to wrap them in a file descriptor abstraction, most of which is provided by the Universal C Runtime on Windows. Change our FD type to call into the efW runtime. Second, Windows does not have the equivalent of bpffs. Instead objects are stored in a global table, keyed by a string. This means that we can't use file system APIs to manipulate pinning. Third, the bpf() syscall is emulated by calling into ebpfapi.dll. This is the key piece which allows most code to work unchanged. Signed-off-by: Lorenz Bauer <[email protected]>
- Loading branch information
Showing
18 changed files
with
425 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//go:build !windows | ||
|
||
package sys | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/cilium/ebpf/internal/unix" | ||
) | ||
|
||
type FD struct { | ||
raw int | ||
} | ||
|
||
// NewFD wraps a raw fd with a finalizer. | ||
// | ||
// You must not use the raw fd after calling this function, since the underlying | ||
// file descriptor number may change. This is because the BPF UAPI assumes that | ||
// zero is not a valid fd value. | ||
func NewFD(value int) (*FD, error) { | ||
if value < 0 { | ||
return nil, fmt.Errorf("invalid fd %d", value) | ||
} | ||
|
||
fd := newFD(value) | ||
if value != 0 { | ||
return fd, nil | ||
} | ||
|
||
dup, err := fd.Dup() | ||
_ = fd.Close() | ||
return dup, err | ||
} | ||
|
||
func (fd *FD) Close() error { | ||
if fd.raw < 0 { | ||
return nil | ||
} | ||
|
||
return unix.Close(fd.Disown()) | ||
} | ||
|
||
func (fd *FD) Dup() (*FD, error) { | ||
if fd.raw < 0 { | ||
return nil, ErrClosedFd | ||
} | ||
|
||
// Always require the fd to be larger than zero: the BPF API treats the value | ||
// as "no argument provided". | ||
dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 1) | ||
if err != nil { | ||
return nil, fmt.Errorf("can't dup fd: %v", err) | ||
} | ||
|
||
return newFD(dup), nil | ||
} | ||
|
||
// File takes ownership of FD and turns it into an [*os.File]. | ||
// | ||
// You must not use the FD after the call returns. | ||
// | ||
// Returns nil if the FD is not valid. | ||
func (fd *FD) File(name string) *os.File { | ||
if fd.raw == invalidFd { | ||
return nil | ||
} | ||
|
||
return os.NewFile(uintptr(fd.Disown()), name) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package sys | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/cilium/ebpf/internal/efw" | ||
) | ||
|
||
// FD wraps a handle which is managed by the eBPF for Windows runtime. | ||
// | ||
// It is not equivalent to a real file descriptor or handle. | ||
type FD struct { | ||
raw int | ||
} | ||
|
||
// NewFD wraps a raw fd with a finalizer. | ||
// | ||
// You must not use the raw fd after calling this function. | ||
func NewFD(value int) (*FD, error) { | ||
if value == invalidFd { | ||
return nil, fmt.Errorf("invalid fd %d", value) | ||
} | ||
|
||
if value == 0 { | ||
// The bpf() syscall API can't deal with zero fds but we can't dup because | ||
// the handle is managed by efW. | ||
return nil, fmt.Errorf("invalid zero fd") | ||
} | ||
|
||
return newFD(value), nil | ||
} | ||
|
||
func (fd *FD) Close() error { | ||
if fd.raw == invalidFd { | ||
return nil | ||
} | ||
|
||
return efw.EbpfCloseFd(fd.Disown()) | ||
} | ||
|
||
func (fd *FD) Dup() (*FD, error) { | ||
if fd.raw == invalidFd { | ||
return nil, ErrClosedFd | ||
} | ||
|
||
dup, err := efw.EbpfDuplicateFd(fd.raw) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return NewFD(int(dup)) | ||
} | ||
|
||
// File panics on Windows. | ||
func (fd *FD) File(name string) *os.File { | ||
panic("FD.File is not implementable on Windows") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//go:build !windows | ||
|
||
package sys | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package sys | ||
|
||
import ( | ||
"errors" | ||
"runtime" | ||
|
||
"github.com/cilium/ebpf/internal/efw" | ||
) | ||
|
||
func Pin(currentPath, newPath string, fd *FD) error { | ||
defer runtime.KeepAlive(fd) | ||
|
||
if newPath == "" { | ||
return errors.New("given pinning path cannot be empty") | ||
} | ||
if currentPath == newPath { | ||
return nil | ||
} | ||
|
||
if currentPath == "" { | ||
return ObjPin(&ObjPinAttr{ | ||
Pathname: NewStringPointer(newPath), | ||
BpfFd: fd.Uint(), | ||
}) | ||
} | ||
|
||
// TODO(windows): This should not allow replacing an existing object. | ||
return ObjPin(&ObjPinAttr{ | ||
Pathname: NewStringPointer(newPath), | ||
BpfFd: fd.Uint(), | ||
}) | ||
} | ||
|
||
func Unpin(pinnedPath string) error { | ||
if pinnedPath == "" { | ||
return nil | ||
} | ||
|
||
err := efw.EbpfObjectUnpin(pinnedPath) | ||
if err != nil && !errors.Is(err, efw.EBPF_KEY_NOT_FOUND) { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//go:build !windows | ||
|
||
package sys | ||
|
||
import ( | ||
|
Oops, something went wrong.