Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maps: switch maglev to cilium/ebpf package #15546

Merged
merged 1 commit into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 15 additions & 18 deletions cilium/cmd/bpf_lb_maglev_get.go
Expand Up @@ -18,13 +18,12 @@ import (
"errors"
"strconv"

"github.com/cilium/cilium/pkg/bpf"
"github.com/cilium/cilium/pkg/command"
"github.com/cilium/cilium/pkg/common"
"github.com/cilium/cilium/pkg/ebpf"
"github.com/cilium/cilium/pkg/maps/lbmap"

"github.com/spf13/cobra"
"golang.org/x/sys/unix"
)

var bpfMaglevGetCmd = &cobra.Command{
Expand All @@ -47,24 +46,22 @@ var bpfMaglevGetCmd = &cobra.Command{
lookupTables := map[string][]string{}
found := false

for _, name := range []string{lbmap.MaglevOuter4MapName, lbmap.MaglevOuter6MapName} {
// See bpf_lb_maglev_list.go comment for why we use low-level routines
// to open and access the maps
if m, err := bpf.OpenMap(name); err != nil {
continue
} else {
err := bpf.LookupElement(m.GetFd(), key.GetKeyPtr(), val.GetValuePtr())
if err != nil {
if errors.Is(err, unix.ENOENT) {
continue
}
Fatalf("Unable to retrieve entry from %s with key %s: %s",
name, key, err)
} else {
found = true
parseMaglevEntry(key, val, lookupTables)
tableSize, err := lbmap.OpenMaglevMaps()
if err != nil {
Fatalf("Cannot initialize maglev maps: %s", err)
}

for name, m := range lbmap.GetOpenMaglevMaps() {
if err := m.Lookup(key, val); err != nil {
if errors.Is(err, ebpf.ErrKeyNotExist) {
continue
}
Fatalf("Unable to retrieve entry from %s with key %v: %s",
name, key, err)
}

found = true
parseMaglevEntry(key, val, tableSize, lookupTables)
}

if !found {
Expand Down
65 changes: 21 additions & 44 deletions cilium/cmd/bpf_lb_maglev_list.go
Expand Up @@ -16,11 +16,9 @@ package cmd

import (
"fmt"
"unsafe"

"github.com/spf13/cobra"

"github.com/cilium/cilium/pkg/bpf"
"github.com/cilium/cilium/pkg/command"
"github.com/cilium/cilium/pkg/common"
"github.com/cilium/cilium/pkg/maps/lbmap"
Expand Down Expand Up @@ -48,57 +46,36 @@ var bpfMaglevListCmd = &cobra.Command{
},
}

var lookupTableSize = 0

func parseMaglevEntry(key bpf.MapKey, value bpf.MapValue, tables map[string][]string) {
k := key.(*lbmap.MaglevOuterKey)
v := value.(*lbmap.MaglevOuterVal)

// Determine lookup table size by inspecting the first inner map
if lookupTableSize == 0 {
fd, err := bpf.MapFdFromID(int(v.FD))
if err != nil {
Fatalf("Unable to get map fd by id %d: %s", v.FD, err)
}
m, err := bpf.GetMapInfoByFd(uint32(fd))
if err != nil {
Fatalf("Unable to get map info by fd %d: %s", fd, err)
}
lookupTableSize = int(m.ValueSize) / 2
func parseMaglevEntry(key *lbmap.MaglevOuterKey, value *lbmap.MaglevOuterVal, tableSize uint32, tables map[string][]string) {
innerMap, err := lbmap.MaglevInnerMapFromID(int(value.FD), tableSize)
if err != nil {
Fatalf("Unable to get map fd by id %d: %s", value.FD, err)
}

table := make([]uint16, lookupTableSize)
zero := uint32(0)
fd, err := bpf.MapFdFromID(int(v.FD))
if err != nil {
Fatalf("Unable to get map fd by id %d: %s", v.FD, err)
innerKey := lbmap.MaglevInnerKey{
Zero: 0,
}
if err := bpf.LookupElement(int(fd), unsafe.Pointer(&zero), unsafe.Pointer(&table[0])); err != nil {
Fatalf("Unable to lookup element in map by fd %d: %s", fd, err)
innerValue, err := innerMap.Lookup(&innerKey)
if err != nil {
Fatalf("Unable to lookup element in map by fd %d: %s", value.FD, err)
}
tables[k.ToNetwork().String()] = []string{fmt.Sprintf("%v", table)}

tables[fmt.Sprintf("%d", key.ToNetwork().RevNatID)] = []string{fmt.Sprintf("%v", innerValue.BackendIDs)}
jibi marked this conversation as resolved.
Show resolved Hide resolved
}

func dumpMaglevTables(tables map[string][]string) {
parse := func(key bpf.MapKey, value bpf.MapValue) {
parseMaglevEntry(key, value, tables)
tableSize, err := lbmap.OpenMaglevMaps()
if err != nil {
Fatalf("Cannot initialize maglev maps: %s", err)
}

for _, name := range []string{lbmap.MaglevOuter4MapName, lbmap.MaglevOuter6MapName} {
// We cannot directly access the maps via lbmap.MaglevOuter{4,6}Map, as
// both are not initialized, and they cannot be initialized due to
// option.Config.MaglevTableSize not set in the cilium cli. Thus, we need
// to open map with the lower-level helper and set the fields required
// for the maps traversal.
if m, err := bpf.OpenMap(name); err != nil {
continue
} else {
m.MapKey = &lbmap.MaglevOuterKey{}
m.MapValue = &lbmap.MaglevOuterVal{}
m.DumpParser = bpf.ConvertKeyValue
if err := m.DumpWithCallbackIfExists(parse); err != nil {
Fatalf("Unable to dump %s: %s", name, err)
}
parse := func(key *lbmap.MaglevOuterKey, value *lbmap.MaglevOuterVal) {
parseMaglevEntry(key, value, tableSize, tables)
}

for name, m := range lbmap.GetOpenMaglevMaps() {
if err := m.IterateWithCallback(parse); err != nil {
Fatalf("Unable to dump %s: %v", name, err)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion daemon/cmd/datapath.go
Expand Up @@ -457,7 +457,7 @@ func (d *Daemon) initMaps() error {
}

if option.Config.NodePortAlg == option.NodePortAlgMaglev {
if err := lbmap.InitMaglevMaps(option.Config.EnableIPv4, option.Config.EnableIPv6); err != nil {
if err := lbmap.InitMaglevMaps(option.Config.EnableIPv4, option.Config.EnableIPv6, uint32(option.Config.MaglevTableSize)); err != nil {
return err
}
}
Expand Down
42 changes: 42 additions & 0 deletions pkg/ebpf/map.go
Expand Up @@ -31,10 +31,17 @@ type MapSpec = ciliumebpf.MapSpec

const (
PerCPUHash = ciliumebpf.PerCPUHash
Array = ciliumebpf.Array
HashOfMaps = ciliumebpf.HashOfMaps

PinByName = ciliumebpf.PinByName
)

var (
ErrKeyNotExist = ciliumebpf.ErrKeyNotExist
LoadPinnedMap = ciliumebpf.LoadPinnedMap
)

// IterateCallback represents the signature of the callback function expected by
// the IterateWithCallback method, which in turn is used to iterate all the
// keys/values of a map.
Expand All @@ -56,6 +63,37 @@ func NewMap(spec *MapSpec) *Map {
}
}

// OpenMap opens the given bpf map and generates the Map object based on the
// information stored in the bpf map.
func OpenMap(mapName string) (*Map, error) {
path := bpf.MapPath(mapName)

newMap, err := LoadPinnedMap(path, nil)
if err != nil {
return nil, err
}

m := &Map{
Map: newMap,
path: path,
}

registerMap(m)

return m, nil
}

func MapFromID(id int) (*Map, error) {
newMap, err := ciliumebpf.NewMapFromID(ciliumebpf.MapID(id))
if err != nil {
return nil, err
}

return &Map{
Map: newMap,
}, nil
}

// OpenOrCreate tries to open or create the eBPF map identified by the spec in
// the Map object.
func (m *Map) OpenOrCreate() error {
Expand All @@ -66,6 +104,10 @@ func (m *Map) OpenOrCreate() error {
return nil
}

if m.spec == nil {
return fmt.Errorf("cannot create map: nil map spec")
}

opts := ciliumebpf.MapOptions{
PinPath: bpf.MapPrefixPath(),
}
Expand Down