-
Notifications
You must be signed in to change notification settings - Fork 709
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the new tcx link type. This supersedes netlink based attachment to TC ingress and egress hooks. It is the first user of the bpf_mprog API in the kernel, which allows attaching multiple programs to the same interface. Semantically programs are put into a list and then executed in order. Earlier programs may prevent the execution of later programs. The most interesting part is a way to express where a new program should be inserted in the list. By default, a program attached via a new link will be appended to the list, which is equivalent to passing the BPF_F_AFTER flag. Passing the BPF_F_BEFORE flag prepends instead. BEFORE and AFTER can be combined with a reference to a program or a link to specify any position in the list. The BPF_F_LINK and BPF_F_ID flags indicate whether the reference is to a link or a program and whether it is in the form of an FD or a ID. The default is to refer to a program by FD. The other combinations are as follows: - ..._ID: Refer to a program by ID. - ..._LINK: Refer to a link by FD. - ..._LINK | ..._ID: Refer to a link by ID. There is a special case which allows replacing a program with another program by specifying BPF_F_REPLACE. It's not possible to replace a link. The flag behaviour is pretty subtle, so the Go API doesn't expose it directly. Instead a new concept called an Anchor is introduced, which bundles a position with a reference to a program or link. A couple of constructors are used to create only valid combinations. bpf_mprog also introduces the concept of a revision which changes with each modification of the list of attached programs. User space can pass an expected revision when creating a new link. The kernel then rejects the update if the revision has changed. Breaking change: this commit removes RawAttachProgramOptions.Replace. The fix is to set RawAttachProgramOptions.Anchor to ReplaceProgram(...). Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
- Loading branch information
Showing
12 changed files
with
469 additions
and
31 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,135 @@ | ||
package link | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cilium/ebpf" | ||
"github.com/cilium/ebpf/internal/sys" | ||
) | ||
|
||
const anchorFlags = sys.BPF_F_REPLACE | | ||
sys.BPF_F_BEFORE | | ||
sys.BPF_F_AFTER | | ||
sys.BPF_F_ID | | ||
sys.BPF_F_LINK_MPROG | ||
|
||
// Anchor is a reference to a link or program. | ||
// | ||
// It is used to describe where an attachment or detachment should take place | ||
// for link types which support multiple attachment. | ||
type Anchor interface { | ||
// anchor returns an fd or ID and a set of flags. | ||
// | ||
// By default fdOrID is taken to reference a program, but BPF_F_LINK_MPROG | ||
// changes this to refer to a link instead. | ||
// | ||
// BPF_F_BEFORE, BPF_F_AFTER, BPF_F_REPLACE modify where a link or program | ||
// is attached. The default behaviour if none of these flags is specified | ||
// matches BPF_F_AFTER. | ||
anchor() (fdOrID, flags uint32, _ error) | ||
} | ||
|
||
type firstAnchor struct{} | ||
|
||
func (firstAnchor) anchor() (fdOrID, flags uint32, _ error) { | ||
return 0, sys.BPF_F_BEFORE, nil | ||
} | ||
|
||
func First() Anchor { | ||
return firstAnchor{} | ||
} | ||
|
||
type lastAnchor struct{} | ||
|
||
func (lastAnchor) anchor() (fdOrID, flags uint32, _ error) { | ||
return 0, sys.BPF_F_AFTER, nil | ||
} | ||
|
||
func Last() Anchor { | ||
return lastAnchor{} | ||
} | ||
|
||
// Before is the position just in front of target. | ||
func BeforeLink(target Link) Anchor { | ||
return anchor{target, sys.BPF_F_BEFORE} | ||
} | ||
|
||
// After is the position just after target. | ||
func AfterLink(target Link) Anchor { | ||
return anchor{target, sys.BPF_F_AFTER} | ||
} | ||
|
||
// Before is the position just in front of target. | ||
func BeforeLinkByID(target ID) Anchor { | ||
return anchor{target, sys.BPF_F_BEFORE} | ||
} | ||
|
||
// After is the position just after target. | ||
func AfterLinkByID(target ID) Anchor { | ||
return anchor{target, sys.BPF_F_AFTER} | ||
} | ||
|
||
// Before is the position just in front of target. | ||
func BeforeProgram(target *ebpf.Program) Anchor { | ||
return anchor{target, sys.BPF_F_BEFORE} | ||
} | ||
|
||
// After is the position just after target. | ||
func AfterProgram(target *ebpf.Program) Anchor { | ||
return anchor{target, sys.BPF_F_AFTER} | ||
} | ||
|
||
// Replace the target itself. | ||
func ReplaceProgram(target *ebpf.Program) Anchor { | ||
return anchor{target, sys.BPF_F_REPLACE} | ||
} | ||
|
||
// Before is the position just in front of target. | ||
func BeforeProgramByID(target ebpf.ProgramID) Anchor { | ||
return anchor{target, sys.BPF_F_BEFORE} | ||
} | ||
|
||
// After is the position just after target. | ||
func AfterProgramByID(target ebpf.ProgramID) Anchor { | ||
return anchor{target, sys.BPF_F_AFTER} | ||
} | ||
|
||
// Replace the target itself. | ||
func ReplaceProgramByID(target ebpf.ProgramID) Anchor { | ||
return anchor{target, sys.BPF_F_REPLACE} | ||
} | ||
|
||
type anchor struct { | ||
target any | ||
position uint32 | ||
} | ||
|
||
func (ap anchor) anchor() (fdOrID, flags uint32, _ error) { | ||
var typeFlag uint32 | ||
switch target := ap.target.(type) { | ||
case *ebpf.Program: | ||
fd := target.FD() | ||
if fd < 0 { | ||
return 0, 0, sys.ErrClosedFd | ||
} | ||
fdOrID = uint32(fd) | ||
typeFlag = 0 | ||
case ebpf.ProgramID: | ||
fdOrID = uint32(target) | ||
typeFlag = sys.BPF_F_ID | ||
case interface{ FD() int }: | ||
fd := target.FD() | ||
if fd < 0 { | ||
return 0, 0, sys.ErrClosedFd | ||
} | ||
fdOrID = uint32(fd) | ||
typeFlag = sys.BPF_F_LINK_MPROG | ||
case ID: | ||
fdOrID = uint32(target) | ||
typeFlag = sys.BPF_F_LINK_MPROG | sys.BPF_F_ID | ||
default: | ||
return 0, 0, fmt.Errorf("invalid target %T", ap.target) | ||
} | ||
|
||
return fdOrID, ap.position | typeFlag, 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
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
Oops, something went wrong.