Skip to content

Commit

Permalink
Merge pull request #7621 from tomastigera/tomas-bpf-log-filter-single…
Browse files Browse the repository at this point in the history
…-jump-map-no-reload

Do not reload log-filters on policy update
  • Loading branch information
tomastigera authored May 25, 2023
2 parents dd927b0 + 8242ad2 commit 03b7805
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 186 deletions.
4 changes: 4 additions & 0 deletions felix/bpf/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ func (ap *AttachPoint) PolicyIdx(family int) int {
return -1
}

type AttachResult interface {
ProgID() int
}

// AlreadyAttachedProg checks that the program we are going to attach has the
// same parameters as what we remembered about the currently attached.
func AlreadyAttachedProg(a AttachPointInfo, object string, id int) (bool, error) {
Expand Down
4 changes: 4 additions & 0 deletions felix/bpf/bpf_defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func (f ProgFD) Close() error {
return unix.Close(int(f))
}

func (f ProgFD) FD() uint32 {
return uint32(f)
}

type ProgResult struct {
RC int32
Duration time.Duration
Expand Down
5 changes: 2 additions & 3 deletions felix/bpf/jump/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package jump
import (
"encoding/binary"

"github.com/projectcalico/calico/felix/bpf"
"github.com/projectcalico/calico/felix/bpf/maps"
)

Expand Down Expand Up @@ -58,8 +57,8 @@ func Key(idx int) []byte {
return k[:]
}

func Value(fd bpf.ProgFD) []byte {
func Value(fd uint32) []byte {
var v [4]byte
binary.LittleEndian.PutUint32(v[:], uint32(fd))
binary.LittleEndian.PutUint32(v[:], fd)
return v[:]
}
21 changes: 17 additions & 4 deletions felix/bpf/libbpf/libbpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,35 @@ func (o *Obj) ProgramFD(secname string) (int, error) {
return int(ret), nil
}

func (o *Obj) AttachClassifier(secName, ifName string, ingress bool) (int, error) {
func QueryClassifier(ifindex, handle, pref int, ingress bool) (int, error) {
opts, err := C.bpf_tc_program_query(C.int(ifindex), C.int(handle), C.int(pref), C.bool(ingress))

return int(opts.prog_id), err
}

func DetachClassifier(ifindex, handle, pref int, ingress bool) error {
_, err := C.bpf_tc_program_detach(C.int(ifindex), C.int(handle), C.int(pref), C.bool(ingress))

return err
}

// AttachClassifier return the program id and pref and handle of the qdisc
func (o *Obj) AttachClassifier(secName, ifName string, ingress bool) (int, int, int, error) {
cSecName := C.CString(secName)
cIfName := C.CString(ifName)
defer C.free(unsafe.Pointer(cSecName))
defer C.free(unsafe.Pointer(cIfName))
ifIndex, err := C.if_nametoindex(cIfName)
if err != nil {
return -1, err
return -1, -1, -1, err
}

ret, err := C.bpf_tc_program_attach(o.obj, cSecName, C.int(ifIndex), C.bool(ingress))
if err != nil {
return -1, fmt.Errorf("error attaching tc program %w", err)
return -1, -1, -1, fmt.Errorf("error attaching tc program %w", err)
}

return int(ret.prog_id), nil
return int(ret.prog_id), int(ret.priority), int(ret.handle), nil
}

func (o *Obj) AttachXDP(ifName, progName string, oldID int, mode uint) (int, error) {
Expand Down
48 changes: 35 additions & 13 deletions felix/bpf/libbpf/libbpf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,51 @@ struct bpf_tc_opts bpf_tc_program_attach(struct bpf_object *obj, char *secName,
return attach;
}

int bpf_tc_query_iface (int ifIndex, struct bpf_tc_opts opts, int isIngress) {
void bpf_tc_program_detach(int ifindex, int handle, int pref, bool ingress)
{
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook,
.ifindex = ifindex,
.attach_point = ingress ? BPF_TC_INGRESS : BPF_TC_EGRESS,
);
DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts,
.handle = handle,
.priority = pref,
);

set_errno(bpf_tc_detach(&hook, &opts));
}

struct bpf_tc_opts bpf_tc_program_query(int ifindex, int handle, int pref, bool ingress)
{
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook,
.ifindex = ifindex,
.attach_point = ingress ? BPF_TC_INGRESS : BPF_TC_EGRESS,
);
DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts,
.handle = handle,
.priority = pref,
);

DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .attach_point = BPF_TC_EGRESS);
if (isIngress) {
hook.attach_point = BPF_TC_INGRESS;
}
hook.ifindex = ifIndex;
opts.prog_fd = opts.prog_id = opts.flags = 0;
set_errno(bpf_tc_query(&hook, &opts));
return opts.prog_id;

return opts;
}

void bpf_tc_create_qdisc (int ifIndex) {
void bpf_tc_create_qdisc(int ifIndex)
{
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .attach_point = BPF_TC_INGRESS);
hook.ifindex = ifIndex;
set_errno(bpf_tc_hook_create(&hook));
}

void bpf_tc_remove_qdisc (int ifIndex) {
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .attach_point = BPF_TC_EGRESS | BPF_TC_INGRESS);
hook.ifindex = ifIndex;
void bpf_tc_remove_qdisc(int ifindex)
{
DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook,
.attach_point = BPF_TC_EGRESS | BPF_TC_INGRESS,
.ifindex = ifindex,
);

set_errno(bpf_tc_hook_destroy(&hook));
return;
}

int bpf_update_jump_map(struct bpf_object *obj, char* mapName, char *progName, int progIndex) {
Expand Down
10 changes: 9 additions & 1 deletion felix/bpf/libbpf/libbpf_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@ func (m *Map) NextMap() (*Map, error) {
panic("LIBBPF syscall stub")
}

func (o *Obj) AttachClassifier(secName, ifName string, ingress bool) (int, error) {
func QueryClassifier(ifindex, handle, pref int, ingress bool) (int, error) {
panic("LIBBPF syscall stub")
}

func DetachClassifier(ifindex, handle, pref int, ingress bool) error {
panic("LIBBPF syscall stub")
}

func (o *Obj) AttachClassifier(secName, ifName string, ingress bool) (int, int, int, error) {
panic("LIBBPF syscall stub")
}

Expand Down
42 changes: 31 additions & 11 deletions felix/bpf/tc/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,41 +104,61 @@ func (ap *AttachPoint) loadObject(ipVer int, file string) (*libbpf.Obj, error) {
return obj, nil
}

type AttachResult struct {
progId int
prio int
handle int
}

func (ar AttachResult) ProgID() int {
return ar.progId
}

func (ar AttachResult) Prio() int {
return ar.prio
}

func (ar AttachResult) Handle() int {
return ar.handle
}

// AttachProgram attaches a BPF program from a file to the TC attach point
func (ap *AttachPoint) AttachProgram() (int, error) {
func (ap *AttachPoint) AttachProgram() (bpf.AttachResult, error) {
logCxt := log.WithField("attachPoint", ap)

// By now the attach type specific generic set of programs is loaded and we
// only need to load and configure the preamble that will pass the
// configuration further to the selected set of programs.
binaryToLoad := path.Join(bpfdefs.ObjectDir, "tc_preamble.o")

var res AttachResult

/* XXX we should remember the tag of the program and skip the rest if the tag is
* still the same */
progsToClean, err := ap.listAttachedPrograms(true)
if err != nil {
return -1, err
return nil, err
}

obj, err := ap.loadObject(4, binaryToLoad)
if err != nil {
logCxt.Warn("Failed to load program")
return -1, fmt.Errorf("object v4: %w", err)
return nil, fmt.Errorf("object v4: %w", err)
}
defer obj.Close()

progId, err := obj.AttachClassifier("cali_tc_preamble", ap.Iface, ap.Hook == hook.Ingress)
res.progId, res.prio, res.handle, err = obj.AttachClassifier("cali_tc_preamble", ap.Iface, ap.Hook == hook.Ingress)
if err != nil {
logCxt.Warnf("Failed to attach to TC section cali_tc_preamble")
return -1, err
return nil, err
}
logCxt.Info("Program attached to TC.")

if err := ap.detachPrograms(progsToClean); err != nil {
return -1, err
return nil, err
}

return progId, nil
return res, nil
}

func (ap *AttachPoint) DetachProgram() error {
Expand Down Expand Up @@ -305,16 +325,16 @@ func (ap *AttachPoint) IsAttached() (bool, error) {
}

// EnsureQdisc makes sure that qdisc is attached to the given interface
func EnsureQdisc(ifaceName string) error {
func EnsureQdisc(ifaceName string) (bool, error) {
hasQdisc, err := HasQdisc(ifaceName)
if err != nil {
return err
return false, err
}
if hasQdisc {
log.WithField("iface", ifaceName).Debug("Already have a clsact qdisc on this interface")
return nil
return true, nil
}
return libbpf.CreateQDisc(ifaceName)
return false, libbpf.CreateQDisc(ifaceName)
}

func HasQdisc(ifaceName string) (bool, error) {
Expand Down
2 changes: 1 addition & 1 deletion felix/bpf/ut/attach_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ func BenchmarkAttachProgram(b *testing.B) {
vethName, veth := createVeth()
defer deleteLink(veth)

err := tc.EnsureQdisc(vethName)
_, err := tc.EnsureQdisc(vethName)
Expect(err).NotTo(HaveOccurred())

ap := tc.AttachPoint{
Expand Down
24 changes: 15 additions & 9 deletions felix/bpf/xdp/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,21 @@ func ConfigureProgram(m *libbpf.Map, iface string, globalData *libbpf.XDPGlobalD
return nil
}

func (ap *AttachPoint) AttachProgram() (int, error) {
type AttachResult int

func (ar AttachResult) ProgID() int {
return int(ar)
}

func (ap *AttachPoint) AttachProgram() (bpf.AttachResult, error) {
// By now the attach type specific generic set of programs is loaded and we
// only need to load and configure the preamble that will pass the
// configuration further to the selected set of programs.
binaryToLoad := path.Join(bpfdefs.ObjectDir, "xdp_preamble.o")

obj, err := libbpf.OpenObject(binaryToLoad)
if err != nil {
return -1, err
return nil, err
}
defer obj.Close()

Expand All @@ -137,33 +143,33 @@ func (ap *AttachPoint) AttachProgram() (int, error) {
globals.Jumps[tcdefs.ProgIndexPolicy] = uint32(ap.PolicyIdx(4))

if err := ConfigureProgram(m, ap.Iface, &globals); err != nil {
return -1, err
return nil, err
}
continue
}
// TODO: We need to set map size here like tc.
pinDir := bpf.MapPinDir(m.Type(), m.Name(), ap.Iface, hook.XDP)
if err := m.SetPinPath(path.Join(pinDir, m.Name())); err != nil {
return -1, fmt.Errorf("error pinning map %s: %w", m.Name(), err)
return nil, fmt.Errorf("error pinning map %s: %w", m.Name(), err)
}
}

// Check if the bpf object is already attached, and we should skip re-attaching it
progID, isAttached := ap.AlreadyAttached(binaryToLoad)
if isAttached {
ap.Log().Infof("Programs already attached, skip reattaching %s", binaryToLoad)
return progID, nil
return AttachResult(progID), nil
}
ap.Log().Infof("Continue with attaching BPF program %s", binaryToLoad)

if err := obj.Load(); err != nil {
ap.Log().Warn("Failed to load program")
return -1, fmt.Errorf("error loading program: %w", err)
return nil, fmt.Errorf("error loading program: %w", err)
}

oldID, err := ap.ProgramID()
if err != nil {
return -1, fmt.Errorf("failed to get the attached XDP program ID: %w", err)
return nil, fmt.Errorf("failed to get the attached XDP program ID: %w", err)
}

attachmentSucceeded := false
Expand All @@ -182,11 +188,11 @@ func (ap *AttachPoint) AttachProgram() (int, error) {
}

if !attachmentSucceeded {
return -1, fmt.Errorf("failed to attach XDP program with program name %v to interface %v",
return nil, fmt.Errorf("failed to attach XDP program with program name %v to interface %v",
ap.ProgramName(), ap.Iface)
}

return progID, nil
return AttachResult(progID), nil
}

func (ap *AttachPoint) DetachProgram() error {
Expand Down
Loading

0 comments on commit 03b7805

Please sign in to comment.