Skip to content

Commit

Permalink
check the correct size of per cpu maps in bpf syscall (projectcalico#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mazdakn authored Feb 3, 2022
1 parent 462a912 commit 5400f30
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 25 deletions.
45 changes: 24 additions & 21 deletions felix/bpf/bpf_syscall.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019-2021 Tigera, Inc. All rights reserved.
// Copyright (c) 2019-2022 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,14 +18,15 @@ import (
"reflect"
"runtime"
"strings"
"sync"
"syscall"
"time"
"unsafe"

log "github.com/sirupsen/logrus"

"github.com/projectcalico/calico/felix/bpf/asm"
"github.com/projectcalico/calico/felix/bpf/bpfutils"
"github.com/projectcalico/calico/felix/bpf/libbpf"

"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -73,7 +74,7 @@ const maxLogSize = 128 * 1024 * 1024

func LoadBPFProgramFromInsns(insns asm.Insns, license string, progType uint32) (fd ProgFD, err error) {
log.Debugf("LoadBPFProgramFromInsns(%v, %v, %v)", insns, license, progType)
IncreaseLockedMemoryQuota()
bpfutils.IncreaseLockedMemoryQuota()

// Occasionally see retryable errors here, retry silently a few times before going into log-collection mode.
backoff := 1 * time.Millisecond
Expand Down Expand Up @@ -152,17 +153,6 @@ func tryLoadBPFProgramFromInsns(insns asm.Insns, license string, logSize uint, p
return ProgFD(fd), nil
}

var memLockOnce sync.Once

func IncreaseLockedMemoryQuota() {
memLockOnce.Do(func() {
err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY})
if err != nil {
log.WithError(err).Error("Failed to increase RLIMIT_MEMLOCK, loading BPF programs may fail")
}
})
}

func RunBPFProgram(fd ProgFD, dataIn []byte, repeat int) (pr ProgResult, err error) {
log.Debugf("RunBPFProgram(%v, ..., %v)", fd, repeat)
bpfAttr := C.bpf_attr_alloc()
Expand Down Expand Up @@ -259,16 +249,29 @@ func GetMapEntry(mapFD MapFD, k []byte, valueSize int) ([]byte, error) {
}

func checkMapIfDebug(mapFD MapFD, keySize, valueSize int) error {
if log.GetLevel() >= log.DebugLevel {
mapInfo, err := GetMapInfo(mapFD)
if log.GetLevel() < log.DebugLevel {
return nil
}
mapInfo, err := GetMapInfo(mapFD)
if err != nil {
log.WithError(err).Error("Failed to read map information")
return err
}
log.WithField("mapInfo", mapInfo).Debug("Map metadata")
if keySize != mapInfo.KeySize {
log.WithField("mapInfo", mapInfo).WithField("keyLen", keySize).Panic("Incorrect key length")
}
switch mapInfo.Type {
case unix.BPF_MAP_TYPE_PERCPU_HASH, unix.BPF_MAP_TYPE_PERCPU_ARRAY, unix.BPF_MAP_TYPE_LRU_PERCPU_HASH, unix.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
// The actual size of per cpu maps is equal to the value size * number of cpu
ncpus, err := libbpf.NumPossibleCPUs()
if err != nil {
log.WithError(err).Error("Failed to read map information")
return err
log.WithError(err).Panic("Failed to get number of possible cpus")
}
log.WithField("mapInfo", mapInfo).Debug("Map metadata")
if keySize != mapInfo.KeySize {
log.WithField("mapInfo", mapInfo).WithField("keyLen", keySize).Panic("Incorrect key length")
if valueSize >= 0 && valueSize != mapInfo.ValueSize*ncpus {
log.WithField("mapInfo", mapInfo).WithField("valueLen", valueSize).Panic("Incorrect value length for per-CPU map")
}
default:
if valueSize >= 0 && valueSize != mapInfo.ValueSize {
log.WithField("mapInfo", mapInfo).WithField("valueLen", valueSize).Panic("Incorrect value length")
}
Expand Down
33 changes: 33 additions & 0 deletions felix/bpf/bpfutils/bpf_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2022 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bpfutils

import (
"sync"

log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)

var memLockOnce sync.Once

func IncreaseLockedMemoryQuota() {
memLockOnce.Do(func() {
err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY})
if err != nil {
log.WithError(err).Error("Failed to increase RLIMIT_MEMLOCK, loading BPF programs may fail")
}
})
}
14 changes: 11 additions & 3 deletions felix/bpf/libbpf/libbpf.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 Tigera, Inc. All rights reserved.
// Copyright (c) 2021-2022 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,7 @@ import (
"time"
"unsafe"

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

// #include "libbpf_api.h"
Expand Down Expand Up @@ -72,7 +72,7 @@ func (m *Map) IsMapInternal() bool {
}

func OpenObject(filename string) (*Obj, error) {
bpf.IncreaseLockedMemoryQuota()
bpfutils.IncreaseLockedMemoryQuota()
cFilename := C.CString(filename)
defer C.free(unsafe.Pointer(cFilename))
obj, err := C.bpf_obj_open(cFilename)
Expand Down Expand Up @@ -257,3 +257,11 @@ func CTLBSetGlobals(m *Map, udpNotSeen time.Duration) error {

return err
}

func NumPossibleCPUs() (int, error) {
ncpus := int(C.num_possible_cpu())
if ncpus < 0 {
return ncpus, fmt.Errorf("Invalid number of CPUs: %d", ncpus)
}
return ncpus, nil
}
7 changes: 6 additions & 1 deletion felix/bpf/libbpf/libbpf_api.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 Tigera, Inc. All rights reserved.
// Copyright (c) 2021-2022 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -184,3 +184,8 @@ void bpf_ctlb_set_globals(struct bpf_map *map, uint udp_not_seen_timeo)

set_errno(bpf_map__set_initial_value(map, (void*)(&data), sizeof(data)));
}

int num_possible_cpu()
{
return libbpf_num_possible_cpus();
}

0 comments on commit 5400f30

Please sign in to comment.