Skip to content

Commit

Permalink
Add storage
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Popov <[email protected]>
  • Loading branch information
Vladimir Popov committed Oct 28, 2020
1 parent 68f46a3 commit 0cfd526
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 25 deletions.
35 changes: 25 additions & 10 deletions pkg/sriov/pci/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/config"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/pcifunction"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/sriovtest"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/storage"
)

const (
Expand All @@ -49,29 +50,36 @@ type function struct {
}

// NewPool returns a new PCI Pool
func NewPool(pciDevicesPath, pciDriversPath string, conf *config.Config) (*Pool, error) {
func NewPool(pciDevicesPath, pciDriversPath string, store storage.Storage, conf *config.Config) (*Pool, error) {
p := &Pool{
functions: map[string]*function{},
functionsByIOMMUGroup: map[uint][]*function{},
}

pciStore := &pciStorage{
storage: store,
}

kernelDrivers := pciStore.load()
for pfPCIAddr := range conf.PhysicalFunctions {
pf, err := pcifunction.NewPhysicalFunction(pfPCIAddr, pciDevicesPath, pciDriversPath)
if err != nil {
return nil, err
}

if err := p.addFunction(&pf.Function); err != nil {
if err := p.addFunction(&pf.Function, kernelDrivers); err != nil {
return nil, err
}

for _, vf := range pf.GetVirtualFunctions() {
if err := p.addFunction(vf); err != nil {
if err := p.addFunction(vf, kernelDrivers); err != nil {
return nil, err
}
}
}

pciStore.store(kernelDrivers)

return p, nil
}

Expand All @@ -82,32 +90,39 @@ func NewTestPool(physicalFunctions map[string]*sriovtest.PCIPhysicalFunction, co
functionsByIOMMUGroup: map[uint][]*function{},
}

kernelDrivers := map[string]string{}
for pfPCIAddr := range conf.PhysicalFunctions {
pf, ok := physicalFunctions[pfPCIAddr]
if !ok {
return nil, errors.Errorf("PF doesn't exist: %v", pfPCIAddr)
}

_ = p.addFunction(&pf.PCIFunction)
_ = p.addFunction(&pf.PCIFunction, kernelDrivers)

for _, vf := range pf.Vfs {
_ = p.addFunction(vf)
_ = p.addFunction(vf, kernelDrivers)
}
}

return p, nil
}

func (p *Pool) addFunction(pcif pciFunction) (err error) {
func (p *Pool) addFunction(pcif pciFunction, kernelDrivers map[string]string) (err error) {
f := &function{
function: pcif,
}

f.kernelDriver, err = pcif.GetBoundDriver()
if err != nil {
return err
pciAddr := pcif.GetPCIAddress()

var ok bool
if f.kernelDriver, ok = kernelDrivers[pciAddr]; !ok {
f.kernelDriver, err = pcif.GetBoundDriver()
if err != nil {
return err
}
kernelDrivers[pciAddr] = f.kernelDriver
}
p.functions[pcif.GetPCIAddress()] = f
p.functions[pciAddr] = f

iommuGroup, err := pcif.GetIOMMUGroup()
if err != nil {
Expand Down
31 changes: 31 additions & 0 deletions pkg/sriov/pci/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 pci

import "github.com/networkservicemesh/sdk-sriov/pkg/sriov/storage"

type pciStorage struct {
storage storage.Storage
}

func (s *pciStorage) store(kernelDrivers map[string]string) {
s.storage.Store(kernelDrivers)
}

func (s *pciStorage) load() map[string]string {
return s.storage.Load()
}
1 change: 0 additions & 1 deletion pkg/sriov/resource/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,3 @@ physicalFunctions:
iommuGroup: 1
- address: 0000:03:00.3
iommuGroup: 1

24 changes: 24 additions & 0 deletions pkg/sriov/storage/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 storage provides interface for key-value storage
package storage

// Storage is a state storage interface
type Storage interface {
Store(state map[string]string)
Load() map[string]string
}
39 changes: 39 additions & 0 deletions pkg/sriov/storage/test_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 storage

// TestStorage is a simple map-based Storage for testing
type TestStorage struct {
state map[string]string
}

// NewTestStorage returns a new TestStorage
func NewTestStorage() *TestStorage {
return &TestStorage{
state: map[string]string{},
}
}

// Store stores state
func (s *TestStorage) Store(state map[string]string) {
s.state = state
}

// Load loads state
func (s *TestStorage) Load() map[string]string {
return s.state
}
41 changes: 29 additions & 12 deletions pkg/sriov/token/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/pkg/errors"

"github.com/networkservicemesh/sdk-sriov/pkg/sriov/config"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/storage"
)

const (
Expand Down Expand Up @@ -64,30 +65,46 @@ type token struct {
}

// NewPool returns a new Pool
func NewPool(cfg *config.Config) *Pool {
func NewPool(store storage.Storage, cfg *config.Config) *Pool {
p := &Pool{
tokens: map[string]*token{},
tokensByNames: map[string][]*token{},
closedTokens: map[string][]*token{},
}

for _, pFun := range cfg.PhysicalFunctions {
for _, serviceDomain := range pFun.ServiceDomains {
for _, capability := range pFun.Capabilities {
name := path.Join(serviceDomain, capability)
for i := 0; i < len(pFun.VirtualFunctions); i++ {
tok := &token{
id: uuid.New().String(),
name: name,
state: free,
tokenStore := &tokenStorage{
storage: store,
}

tokens := tokenStore.load()
if len(tokens) > 0 {
// restore tokens from storage
p.tokens = tokens
for _, tok := range tokens {
p.tokensByNames[tok.name] = append(p.tokensByNames[tok.name], tok)
}
} else {
// create new tokens
for _, pFun := range cfg.PhysicalFunctions {
for _, serviceDomain := range pFun.ServiceDomains {
for _, capability := range pFun.Capabilities {
name := path.Join(serviceDomain, capability)
for i := 0; i < len(pFun.VirtualFunctions); i++ {
tok := &token{
id: uuid.New().String(),
name: name,
state: free,
}
p.tokens[tok.id] = tok
p.tokensByNames[tok.name] = append(p.tokensByNames[tok.name], tok)
}
p.tokens[tok.id] = tok
p.tokensByNames[tok.name] = append(p.tokensByNames[tok.name], tok)
}
}
}
}

tokenStore.store(p.tokens)

return p
}

Expand Down
18 changes: 16 additions & 2 deletions pkg/sriov/token/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/networkservicemesh/sdk-sriov/pkg/sriov/config"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/storage"
"github.com/networkservicemesh/sdk-sriov/pkg/sriov/token"
)

Expand All @@ -40,7 +41,7 @@ func TestPool_Tokens(t *testing.T) {
cfg, err := config.ReadConfig(context.TODO(), configFileName)
require.NoError(t, err)

p := token.NewPool(cfg)
p := token.NewPool(storage.NewTestStorage(), cfg)

tokens := p.Tokens()
require.Equal(t, 5, len(tokens))
Expand All @@ -55,7 +56,7 @@ func TestPool_Use(t *testing.T) {
cfg, err := config.ReadConfig(context.TODO(), configFileName)
require.NoError(t, err)

p := token.NewPool(cfg)
p := token.NewPool(storage.NewTestStorage(), cfg)

var tokenID string
for id := range p.Tokens()[path.Join(serviceDomain2, capability20G)] {
Expand Down Expand Up @@ -89,6 +90,19 @@ func TestPool_Use(t *testing.T) {
require.Equal(t, 3, countTrue(tokens[path.Join(serviceDomain2, capability20G)]))
}

func TestPool_Restore(t *testing.T) {
cfg, err := config.ReadConfig(context.TODO(), configFileName)
require.NoError(t, err)

store := storage.NewTestStorage()

p := token.NewPool(store, cfg)
tokens := p.Tokens()

p = token.NewPool(store, cfg)
require.Equal(t, tokens, p.Tokens())
}

func countTrue(m map[string]bool) (count int) {
for _, v := range m {
if v {
Expand Down
68 changes: 68 additions & 0 deletions pkg/sriov/token/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2020 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 token

import (
"encoding/json"

"github.com/networkservicemesh/sdk-sriov/pkg/sriov/storage"
)

type tokenStorage struct {
storage storage.Storage
}

type storedToken struct {
ID string `json:"id"`
Name string `json:"name"`
}

func (s *tokenStorage) store(tokens map[string]*token) {
state := map[string]string{}
for id, tok := range tokens {
state[id] = marshallToken(tok)
}
s.storage.Store(state)
}

func marshallToken(tok *token) string {
data, _ := json.Marshal(&storedToken{
ID: tok.id,
Name: tok.name,
})
return string(data)
}

func (s *tokenStorage) load() map[string]*token {
tokens := map[string]*token{}
state := s.storage.Load()
for id, s := range state {
tokens[id] = unmarshallToken(s)
}
return tokens
}

func unmarshallToken(s string) (tok *token) {
storedTok := storedToken{}
_ = json.Unmarshal([]byte(s), &storedTok)

return &token{
id: storedTok.ID,
name: storedTok.Name,
state: free,
}
}

0 comments on commit 0cfd526

Please sign in to comment.