Skip to content

Commit

Permalink
Add IB GUID Pool interface and implementation
Browse files Browse the repository at this point in the history
The package is fully incapsulated and provides
a single interface with one function.
The package handles all the validation of the json config.
If there are any errors when processing the config, return a nil object.

Signed-off-by: amaslennikov <[email protected]>

Integrate IB GUID Pool into the sriov VF configuration flow

Signed-off-by: amaslennikov <[email protected]>
  • Loading branch information
almaslennikov committed Mar 20, 2024
1 parent f1a522a commit bcbd96d
Show file tree
Hide file tree
Showing 11 changed files with 639 additions and 21 deletions.
2 changes: 2 additions & 0 deletions pkg/consts/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ const (
KernelArgIommuPt = "iommu=pt"

ParallelNicConfigFeatureGate = "parallelNicConfig"

InfinibandGUIDConfigFilePath = "/host/var/opt/infiniband_guids"
)

const (
Expand Down
9 changes: 5 additions & 4 deletions pkg/helper/mock/mock_helper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 133 additions & 0 deletions pkg/host/internal/infiniband/ib_guid_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package infiniband

import (
"encoding/json"
"fmt"
"net"
"os"

"github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink"
"github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
)

type ibPfGUIDJSONConfig struct {
PciAddress string `json:"pciAddress,omitempty"`
PfGUID string `json:"pfGuid,omitempty"`
GUIDs []string `json:"guids,omitempty"`
RangeStart string `json:"rangeStart,omitempty"`
RangeEnd string `json:"rangeEnd,omitempty"`
}

type ibPfGUIDConfig struct {
GUIDs []net.HardwareAddr
RangeStart utils.GUID
RangeEnd utils.GUID
NextGUIDIndex int
}

func getIbGUIDConfig(configPath string, netlinkLib netlink.NetlinkLib) (map[string]ibPfGUIDConfig, error) {
if configPath == "" {
return nil, fmt.Errorf("configPath should not be empty")
}
if netlinkLib == nil {
return nil, fmt.Errorf("netlinkLib should not be nil")
}
links, err := netlinkLib.LinkList()
if err != nil {
return nil, err
}

rawConfigs, err := readJSONConfig(configPath)
if err != nil {
return nil, err
}

resultConfigs := map[string]ibPfGUIDConfig{}

// Parse JSON config into an internal struct
for _, rawConfig := range rawConfigs {
pciAddress, err := getPfPciAddressFromRawConfig(rawConfig, links)
if err != nil {
return nil, fmt.Errorf("failed to extract pci address from ib guid config: %w", err)
}

// GUID list and GUID range can't be set at the same time
if len(rawConfig.GUIDs) != 0 && (rawConfig.RangeStart != "" || rawConfig.RangeEnd != "") {
return nil, fmt.Errorf("either guid list or guid range should be provided, got both")
} else if (rawConfig.RangeStart != "" && rawConfig.RangeEnd == "") || (rawConfig.RangeStart == "" && rawConfig.RangeEnd != "") {
return nil, fmt.Errorf("both guid rangeStart and rangeEnd should be provided, got one")
} else if len(rawConfig.GUIDs) != 0 {
var guids []net.HardwareAddr

for _, guidStr := range rawConfig.GUIDs {
guid, err := net.ParseMAC(guidStr)
if err != nil {
return nil, fmt.Errorf("failed to parse ib guid %s: %w", guidStr, err)
}
guids = append(guids, guid)
}
resultConfigs[pciAddress] = ibPfGUIDConfig{
GUIDs: guids,
}
} else if rawConfig.RangeStart != "" && rawConfig.RangeEnd != "" { // use guid range
rangeStart, err := utils.ParseGUID(rawConfig.RangeStart)
if err != nil {
return nil, fmt.Errorf("failed to parse ib guid range start: %w", err)
}

rangeEnd, err := utils.ParseGUID(rawConfig.RangeEnd)
if err != nil {
return nil, fmt.Errorf("failed to parse ib guid range end: %w", err)
}

if rangeEnd <= rangeStart {
return nil, fmt.Errorf("range end cannot be less then or equal to range start")
}

resultConfigs[pciAddress] = ibPfGUIDConfig{
RangeStart: rangeStart,
RangeEnd: rangeEnd,
}
} else {
return nil, fmt.Errorf("either guid list or guid range should be provided, got none")
}
}

return resultConfigs, nil
}

// readJSONConfig reads the file at the given path and unmarshals the contents into an array of ibPfGUIDJSONConfig structs
func readJSONConfig(configPath string) ([]ibPfGUIDJSONConfig, error) {
file, err := os.Open(configPath)
if err != nil {
return nil, fmt.Errorf("failed to open ib guid config file: %w", err)
}
defer file.Close()

var configs []ibPfGUIDJSONConfig
decoder := json.NewDecoder(file)
if err := decoder.Decode(&configs); err != nil {
fmt.Println("Error decoding JSON:", err)
return nil, fmt.Errorf("failed to decode ib guid config from json: %w", err)
}

return configs, nil
}

func getPfPciAddressFromRawConfig(pfRawConfig ibPfGUIDJSONConfig, links []netlink.Link) (string, error) {
if pfRawConfig.PciAddress != "" && pfRawConfig.PfGUID != "" {
return "", fmt.Errorf("either PCI address or PF GUID required to describe an interface, both provided")
} else if pfRawConfig.PciAddress != "" {
return pfRawConfig.PciAddress, nil
} else if pfRawConfig.PfGUID != "" { // If PF GUID is given, match the existing link and retrieve its pci address
for _, link := range links {
if link.Attrs().HardwareAddr.String() == pfRawConfig.PfGUID {
return utils.GetPciAddressFromInterfaceName(link.Attrs().Name)
}
}

return "", fmt.Errorf("no matching link found for pf guid: %s", pfRawConfig.PfGUID)
} else {
return "", fmt.Errorf("either PCI address or PF GUID required to describe an interface, none provided")
}
}
Loading

0 comments on commit bcbd96d

Please sign in to comment.