gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

rdma.go (3693B)


      1 /*
      2    Copyright The containerd Authors.
      3 
      4    Licensed under the Apache License, Version 2.0 (the "License");
      5    you may not use this file except in compliance with the License.
      6    You may obtain a copy of the License at
      7 
      8        http://www.apache.org/licenses/LICENSE-2.0
      9 
     10    Unless required by applicable law or agreed to in writing, software
     11    distributed under the License is distributed on an "AS IS" BASIS,
     12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13    See the License for the specific language governing permissions and
     14    limitations under the License.
     15 */
     16 
     17 package cgroup1
     18 
     19 import (
     20 	"math"
     21 	"os"
     22 	"path/filepath"
     23 	"strconv"
     24 	"strings"
     25 
     26 	v1 "github.com/containerd/cgroups/v3/cgroup1/stats"
     27 	specs "github.com/opencontainers/runtime-spec/specs-go"
     28 )
     29 
     30 type rdmaController struct {
     31 	root string
     32 }
     33 
     34 func (p *rdmaController) Name() Name {
     35 	return Rdma
     36 }
     37 
     38 func (p *rdmaController) Path(path string) string {
     39 	return filepath.Join(p.root, path)
     40 }
     41 
     42 func NewRdma(root string) *rdmaController {
     43 	return &rdmaController{
     44 		root: filepath.Join(root, string(Rdma)),
     45 	}
     46 }
     47 
     48 func createCmdString(device string, limits *specs.LinuxRdma) string {
     49 	var cmdString string
     50 
     51 	cmdString = device
     52 	if limits.HcaHandles != nil {
     53 		cmdString = cmdString + " " + "hca_handle=" + strconv.FormatUint(uint64(*limits.HcaHandles), 10)
     54 	}
     55 
     56 	if limits.HcaObjects != nil {
     57 		cmdString = cmdString + " " + "hca_object=" + strconv.FormatUint(uint64(*limits.HcaObjects), 10)
     58 	}
     59 	return cmdString
     60 }
     61 
     62 func (p *rdmaController) Create(path string, resources *specs.LinuxResources) error {
     63 	if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil {
     64 		return err
     65 	}
     66 
     67 	for device, limit := range resources.Rdma {
     68 		if device != "" && (limit.HcaHandles != nil || limit.HcaObjects != nil) {
     69 			limit := limit
     70 			return os.WriteFile(
     71 				filepath.Join(p.Path(path), "rdma.max"),
     72 				[]byte(createCmdString(device, &limit)),
     73 				defaultFilePerm,
     74 			)
     75 		}
     76 	}
     77 	return nil
     78 }
     79 
     80 func (p *rdmaController) Update(path string, resources *specs.LinuxResources) error {
     81 	return p.Create(path, resources)
     82 }
     83 
     84 func parseRdmaKV(raw string, entry *v1.RdmaEntry) {
     85 	var value uint64
     86 	var err error
     87 
     88 	parts := strings.Split(raw, "=")
     89 	switch len(parts) {
     90 	case 2:
     91 		if parts[1] == "max" {
     92 			value = math.MaxUint32
     93 		} else {
     94 			value, err = parseUint(parts[1], 10, 32)
     95 			if err != nil {
     96 				return
     97 			}
     98 		}
     99 		if parts[0] == "hca_handle" {
    100 			entry.HcaHandles = uint32(value)
    101 		} else if parts[0] == "hca_object" {
    102 			entry.HcaObjects = uint32(value)
    103 		}
    104 	}
    105 }
    106 
    107 func toRdmaEntry(strEntries []string) []*v1.RdmaEntry {
    108 	var rdmaEntries []*v1.RdmaEntry
    109 	for i := range strEntries {
    110 		parts := strings.Fields(strEntries[i])
    111 		switch len(parts) {
    112 		case 3:
    113 			entry := new(v1.RdmaEntry)
    114 			entry.Device = parts[0]
    115 			parseRdmaKV(parts[1], entry)
    116 			parseRdmaKV(parts[2], entry)
    117 
    118 			rdmaEntries = append(rdmaEntries, entry)
    119 		default:
    120 			continue
    121 		}
    122 	}
    123 	return rdmaEntries
    124 }
    125 
    126 func (p *rdmaController) Stat(path string, stats *v1.Metrics) error {
    127 
    128 	currentData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
    129 	if err != nil {
    130 		return err
    131 	}
    132 	currentPerDevices := strings.Split(string(currentData), "\n")
    133 
    134 	maxData, err := os.ReadFile(filepath.Join(p.Path(path), "rdma.max"))
    135 	if err != nil {
    136 		return err
    137 	}
    138 	maxPerDevices := strings.Split(string(maxData), "\n")
    139 
    140 	// If device got removed between reading two files, ignore returning
    141 	// stats.
    142 	if len(currentPerDevices) != len(maxPerDevices) {
    143 		return nil
    144 	}
    145 
    146 	currentEntries := toRdmaEntry(currentPerDevices)
    147 	maxEntries := toRdmaEntry(maxPerDevices)
    148 
    149 	stats.Rdma = &v1.RdmaStat{
    150 		Current: currentEntries,
    151 		Limit:   maxEntries,
    152 	}
    153 	return nil
    154 }