...
1
16
17 package cgroups
18
19 import (
20 "math"
21 "os"
22 "path/filepath"
23 "strconv"
24 "strings"
25
26 v1 "github.com/containerd/cgroups/stats/v1"
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 retryingWriteFile(
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
141
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 }
155
View as plain text