blob: bb6a941047264c03c78aa6caa9eddd5a2ad0ebe1 [file] [log] [blame]
David K. Bainbridge157bdab2020-01-16 14:38:05 -08001/*
2 Copyright 2020 the original author or 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
17package openflow
18
19import (
20 "context"
21 "encoding/json"
Jonathan Hart828908c2020-04-15 14:23:45 -070022 "github.com/opencord/goloxi"
23 ofp "github.com/opencord/goloxi/of13"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080024 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "github.com/opencord/voltha-protos/v3/go/common"
26 "github.com/opencord/voltha-protos/v3/go/openflow_13"
Jonathan Hart828908c2020-04-15 14:23:45 -070027 "net"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080028)
29
Jonathan Hart4b110f62020-03-13 17:36:19 -070030func (ofc *OFConnection) handleStatsRequest(request ofp.IHeader, statType uint16) error {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080031 if logger.V(log.DebugLevel) {
32 js, _ := json.Marshal(request)
33 logger.Debugw("handleStatsRequest called",
34 log.Fields{
35 "device-id": ofc.DeviceID,
36 "stat-type": statType,
37 "request": js})
38 }
39
40 switch statType {
41 case ofp.OFPSTDesc:
42 statsReq := request.(*ofp.DescStatsRequest)
43 response, err := ofc.handleDescStatsRequest(statsReq)
44 if err != nil {
45 return err
46 }
47 if logger.V(log.DebugLevel) {
48 reqJs, _ := json.Marshal(statsReq)
49 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -080050 logger.Debugw("handle-stats-request-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080051 log.Fields{
52 "device-id": ofc.DeviceID,
53 "request": reqJs,
54 "response": resJs})
55 }
56 return ofc.SendMessage(response)
57 case ofp.OFPSTFlow:
58 statsReq := request.(*ofp.FlowStatsRequest)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070059 responses, err := ofc.handleFlowStatsRequest(statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080060 if err != nil {
61 return err
62 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080063 if logger.V(log.DebugLevel) {
64 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070065 resJs, _ := json.Marshal(responses)
David K. Bainbridge55376262020-01-22 23:28:27 -080066 logger.Debugw("handle-stats-request-flow",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080067 log.Fields{
Matteo Scandoloe23b7582020-05-21 13:50:02 -070068 "device-id": ofc.DeviceID,
69 "request": reqJs,
70 "responses-object": responses,
71 "response": resJs})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080072 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -070073 for _, response := range responses {
74 err := ofc.SendMessage(response)
75 if err != nil {
76 return err
77 }
78 }
79 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080080
81 case ofp.OFPSTAggregate:
82 statsReq := request.(*ofp.AggregateStatsRequest)
83 response, err := ofc.handleAggregateStatsRequest(statsReq)
84 if err != nil {
85 return err
86 }
87 if logger.V(log.DebugLevel) {
88 reqJs, _ := json.Marshal(statsReq)
89 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -080090 logger.Debugw("handle-stats-request-aggregate",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080091 log.Fields{
92 "device-id": ofc.DeviceID,
93 "request": reqJs,
94 "response": resJs})
95 }
96 return ofc.SendMessage(response)
97 case ofp.OFPSTTable:
98 statsReq := request.(*ofp.TableStatsRequest)
99 response, e := ofc.handleTableStatsRequest(statsReq)
100 if logger.V(log.DebugLevel) {
101 reqJs, _ := json.Marshal(statsReq)
102 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800103 logger.Debugw("handle-stats-request-table",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800104 log.Fields{
105 "device-id": ofc.DeviceID,
106 "request": reqJs,
107 "response": resJs})
108 }
109 if e != nil {
110 return e
111 }
112 return ofc.SendMessage(response)
113 case ofp.OFPSTPort:
114 statsReq := request.(*ofp.PortStatsRequest)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700115 responses, err := ofc.handlePortStatsRequest(statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800116 if err != nil {
117 return err
118 }
119 if logger.V(log.DebugLevel) {
120 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700121 resJs, _ := json.Marshal(responses)
David K. Bainbridge55376262020-01-22 23:28:27 -0800122 logger.Debugw("handle-stats-request-port",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800123 log.Fields{
124 "device-id": ofc.DeviceID,
125 "request": reqJs,
126 "response": resJs})
127 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700128 for _, response := range responses {
129 err := ofc.SendMessage(response)
130 if err != nil {
131 return err
132 }
133 }
134 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800135 case ofp.OFPSTQueue:
136 statsReq := request.(*ofp.QueueStatsRequest)
137 response, err := ofc.handleQueueStatsRequest(statsReq)
138 if err != nil {
139 return err
140 }
141 if logger.V(log.DebugLevel) {
142 reqJs, _ := json.Marshal(statsReq)
143 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800144 logger.Debugw("handle-stats-request-queue",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800145 log.Fields{
146 "device-id": ofc.DeviceID,
147 "request": reqJs,
148 "response": resJs})
149 }
150 return ofc.SendMessage(response)
151 case ofp.OFPSTGroup:
152 statsReq := request.(*ofp.GroupStatsRequest)
153 response, err := ofc.handleGroupStatsRequest(statsReq)
154 if err != nil {
155 return err
156 }
157 if logger.V(log.DebugLevel) {
158 reqJs, _ := json.Marshal(statsReq)
159 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800160 logger.Debugw("handle-stats-request-group",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800161 log.Fields{
162 "device-id": ofc.DeviceID,
163 "request": reqJs,
164 "response": resJs})
165 }
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800166 return ofc.SendMessage(response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800167 case ofp.OFPSTGroupDesc:
168 statsReq := request.(*ofp.GroupDescStatsRequest)
169 response, err := ofc.handleGroupStatsDescRequest(statsReq)
170 if err != nil {
171 return err
172 }
173 if logger.V(log.DebugLevel) {
174 reqJs, _ := json.Marshal(statsReq)
175 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800176 logger.Debugw("handle-stats-request-group-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800177 log.Fields{
178 "device-id": ofc.DeviceID,
179 "request": reqJs,
180 "response": resJs})
181 }
182 return ofc.SendMessage(response)
183
184 case ofp.OFPSTGroupFeatures:
185 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
186 response, err := ofc.handleGroupFeatureStatsRequest(statsReq)
187 if err != nil {
188 return err
189 }
190 if logger.V(log.DebugLevel) {
191 reqJs, _ := json.Marshal(statsReq)
192 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800193 logger.Debugw("handle-stats-request-group-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800194 log.Fields{
195 "device-id": ofc.DeviceID,
196 "request": reqJs,
197 "response": resJs})
198 }
199 return ofc.SendMessage(response)
200 case ofp.OFPSTMeter:
201 statsReq := request.(*ofp.MeterStatsRequest)
202 response, err := ofc.handleMeterStatsRequest(statsReq)
203 if err != nil {
204 return err
205 }
206 if logger.V(log.DebugLevel) {
207 reqJs, _ := json.Marshal(statsReq)
208 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800209 logger.Debugw("handle-stats-request-meter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800210 log.Fields{
211 "device-id": ofc.DeviceID,
212 "request": reqJs,
213 "response": resJs})
214 }
215 return ofc.SendMessage(response)
216 case ofp.OFPSTMeterConfig:
217 statsReq := request.(*ofp.MeterConfigStatsRequest)
218 response, err := ofc.handleMeterConfigStatsRequest(statsReq)
219 if err != nil {
220 return err
221 }
222 if logger.V(log.DebugLevel) {
223 reqJs, _ := json.Marshal(statsReq)
224 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800225 logger.Debugw("handle-stats-request-meter-config",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800226 log.Fields{
227 "device-id": ofc.DeviceID,
228 "request": reqJs,
229 "response": resJs})
230 }
231 return ofc.SendMessage(response)
232 case ofp.OFPSTMeterFeatures:
233 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
234 response, err := ofc.handleMeterFeatureStatsRequest(statsReq)
235 if err != nil {
236 return err
237 }
238 if logger.V(log.DebugLevel) {
239 reqJs, _ := json.Marshal(statsReq)
240 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800241 logger.Debugw("handle-stats-request-meter-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800242 log.Fields{
243 "device-id": ofc.DeviceID,
244 "request": reqJs,
245 "response": resJs})
246 }
247 return ofc.SendMessage(response)
248 case ofp.OFPSTTableFeatures:
249 statsReq := request.(*ofp.TableFeaturesStatsRequest)
250 response, err := ofc.handleTableFeaturesStatsRequest(statsReq)
251 if err != nil {
252 return err
253 }
254 if logger.V(log.DebugLevel) {
255 reqJs, _ := json.Marshal(statsReq)
256 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800257 logger.Debugw("handle-stats-request-table-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800258 log.Fields{
259 "device-id": ofc.DeviceID,
260 "request": reqJs,
261 "response": resJs})
262 }
263 return ofc.SendMessage(response)
264 case ofp.OFPSTPortDesc:
265 statsReq := request.(*ofp.PortDescStatsRequest)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700266 responses, err := ofc.handlePortDescStatsRequest(statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800267 if err != nil {
268 return err
269 }
270 if logger.V(log.DebugLevel) {
271 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700272 resJs, _ := json.Marshal(responses)
David K. Bainbridge55376262020-01-22 23:28:27 -0800273 logger.Debugw("handle-stats-request-port-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800274 log.Fields{
275 "device-id": ofc.DeviceID,
276 "request": reqJs,
277 "response": resJs})
278 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700279 for _, response := range responses {
280 err := ofc.SendMessage(response)
281 if err != nil {
282 return err
283 }
284 }
285 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800286
287 case ofp.OFPSTExperimenter:
288 statsReq := request.(*ofp.ExperimenterStatsRequest)
289 response, err := ofc.handleExperimenterStatsRequest(statsReq)
290 if err != nil {
291 return err
292 }
293 if logger.V(log.DebugLevel) {
294 reqJs, _ := json.Marshal(statsReq)
295 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800296 logger.Debugw("handle-stats-request-experimenter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800297 log.Fields{
298 "device-id": ofc.DeviceID,
299 "request": reqJs,
300 "response": resJs})
301 }
302 return ofc.SendMessage(response)
303 }
304 return nil
305}
306
Jonathan Hart4b110f62020-03-13 17:36:19 -0700307func (ofc *OFConnection) handleDescStatsRequest(request *ofp.DescStatsRequest) (*ofp.DescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700308 volthaClient := ofc.VolthaClient.Get()
309 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800310 return nil, NoVolthaConnectionError
311 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800312 response := ofp.NewDescStatsReply()
313 response.SetXid(request.GetXid())
314 response.SetVersion(request.GetVersion())
315 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
316
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700317 resp, err := volthaClient.GetLogicalDevice(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800318 &common.ID{Id: ofc.DeviceID})
319 if err != nil {
320 return nil, err
321 }
322 desc := resp.GetDesc()
323
324 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
325 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
326 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
327 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
328 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
329 return response, nil
330}
331
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700332func (ofc *OFConnection) handleFlowStatsRequest(request *ofp.FlowStatsRequest) ([]*ofp.FlowStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700333 volthaClient := ofc.VolthaClient.Get()
334 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800335 return nil, NoVolthaConnectionError
336 }
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700337 resp, err := volthaClient.ListLogicalDeviceFlows(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800338 &common.ID{Id: ofc.DeviceID})
339 if err != nil {
340 return nil, err
341 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700342 var flows []*ofp.FlowStatsEntry
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800343 for _, item := range resp.GetItems() {
344 entry := ofp.NewFlowStatsEntry()
345 entry.SetTableId(uint8(item.GetTableId()))
346 entry.SetDurationSec(item.GetDurationSec())
347 entry.SetDurationNsec(item.GetDurationNsec())
348 entry.SetPriority(uint16(item.GetPriority()))
349 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
350 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
351 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
352 entry.SetCookie(item.GetCookie())
353 entry.SetPacketCount(item.GetPacketCount())
354 entry.SetByteCount(item.GetByteCount())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800355 match := ofp.NewMatchV3()
356 pbMatch := item.GetMatch()
357 match.SetType(uint16(pbMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800358 var fields []goloxi.IOxm
359 for _, oxmField := range pbMatch.GetOxmFields() {
360 field := oxmField.GetField()
361 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
Jonathan Hart828908c2020-04-15 14:23:45 -0700362 iOxm := parseOxm(ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800363 fields = append(fields, iOxm)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800364 }
365
366 match.OxmList = fields
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800367 entry.SetMatch(*match)
368 var instructions []ofp.IInstruction
369 for _, ofpInstruction := range item.Instructions {
Jonathan Hart828908c2020-04-15 14:23:45 -0700370 instruction := parseInstructions(ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800371 instructions = append(instructions, instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800372 }
373 entry.Instructions = instructions
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700374 flows = append(flows, entry)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800375 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700376 var responses []*ofp.FlowStatsReply
377 chunkSize := 150
378 total := len(flows) / chunkSize
379 n := 0
380 for n <= total {
381
382 chunk := flows[n*chunkSize : min((n*chunkSize)+chunkSize, len(flows))]
383
384 if len(chunk) == 0 {
385 break
386 }
387
388 response := ofp.NewFlowStatsReply()
389 response.SetXid(request.GetXid())
390 response.SetVersion(4)
391 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
392 if total != n {
393 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
394 }
395 response.SetEntries(chunk)
396 responses = append(responses, response)
397 n++
398 }
399 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800400}
401
Jonathan Hart4b110f62020-03-13 17:36:19 -0700402func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800403 response := ofp.NewAggregateStatsReply()
404 response.SetVersion(request.GetVersion())
405 response.SetXid(request.GetXid())
406 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
407 response.SetFlowCount(0)
408 //TODO wire this to voltha core when it implements
409 return response, nil
410}
411
Jonathan Hart4b110f62020-03-13 17:36:19 -0700412func (ofc *OFConnection) handleGroupStatsRequest(request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700413 volthaClient := ofc.VolthaClient.Get()
414 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800415 return nil, NoVolthaConnectionError
416 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800417 response := ofp.NewGroupStatsReply()
418 response.SetVersion(request.GetVersion())
419 response.SetXid(request.GetXid())
420 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700421 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800422 &common.ID{Id: ofc.DeviceID})
423 if err != nil {
424 return nil, err
425 }
426
427 var groupStatsEntries []*ofp.GroupStatsEntry
428 for _, item := range reply.GetItems() {
429 stats := item.GetStats()
430 var entry ofp.GroupStatsEntry
431 entry.SetByteCount(stats.GetByteCount())
432 entry.SetPacketCount(stats.GetPacketCount())
433 entry.SetDurationNsec(stats.GetDurationNsec())
434 entry.SetDurationSec(stats.GetDurationSec())
435 entry.SetRefCount(stats.GetRefCount())
436 entry.SetGroupId(stats.GetGroupId())
437 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700438 // TODO fix this when API handler is fixed in the core
439 // Core doesn't return any buckets in the Stats object, so just
440 // fill out an empty BucketCounter for each bucket in the group Desc for now.
441 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800442 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700443 bucketCounter.SetPacketCount(0)
444 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800445 bucketStatsList = append(bucketStatsList, &bucketCounter)
446 }
447 entry.SetBucketStats(bucketStatsList)
448 groupStatsEntries = append(groupStatsEntries, &entry)
449 }
450 response.SetEntries(groupStatsEntries)
451 return response, nil
452}
453
Jonathan Hart4b110f62020-03-13 17:36:19 -0700454func (ofc *OFConnection) handleGroupStatsDescRequest(request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700455 volthaClient := ofc.VolthaClient.Get()
456 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800457 return nil, NoVolthaConnectionError
458 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800459 response := ofp.NewGroupDescStatsReply()
460 response.SetVersion(request.GetVersion())
461 response.SetXid(request.GetXid())
462 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700463 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800464 &common.ID{Id: ofc.DeviceID})
465 if err != nil {
466 return nil, err
467 }
468 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
469 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700470 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800471
Jonathan Hart60c5d772020-03-30 18:28:40 -0700472 buckets := volthaBucketsToOpenflow(desc.Buckets)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800473
Jonathan Hart60c5d772020-03-30 18:28:40 -0700474 groupDesc := &ofp.GroupDescStatsEntry{
Jonathan Hart60c5d772020-03-30 18:28:40 -0700475 GroupType: volthaGroupTypeToOpenflow(desc.Type),
476 GroupId: desc.GroupId,
477 Buckets: buckets,
478 }
479 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800480 }
481 response.SetEntries(groupDescStatsEntries)
482 return response, nil
483}
484
Jonathan Hart4b110f62020-03-13 17:36:19 -0700485func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800486 response := ofp.NewGroupFeaturesStatsReply()
487 response.SetVersion(request.GetVersion())
488 response.SetXid(request.GetXid())
489 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
490 //TODO wire this to voltha core when it implements
491 return response, nil
492}
493
Jonathan Hart4b110f62020-03-13 17:36:19 -0700494func (ofc *OFConnection) handleMeterStatsRequest(request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700495 volthaClient := ofc.VolthaClient.Get()
496 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800497 return nil, NoVolthaConnectionError
498 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800499 response := ofp.NewMeterStatsReply()
500 response.SetVersion(request.GetVersion())
501 response.SetXid(request.GetXid())
502 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700503 resp, err := volthaClient.ListLogicalDeviceMeters(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800504 &common.ID{Id: ofc.DeviceID})
505 if err != nil {
506 return nil, err
507 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800508 var meterStats []*ofp.MeterStats
509 for _, item := range resp.Items {
510 meterStat := ofp.NewMeterStats()
511 stats := item.Stats
512 meterStat.DurationNsec = stats.DurationNsec
513 meterStat.DurationSec = stats.DurationSec
514 meterStat.ByteInCount = stats.ByteInCount
515 meterStat.FlowCount = stats.FlowCount
516 meterStat.MeterId = stats.MeterId
517 var bandStats []*ofp.MeterBandStats
518 for _, bStat := range stats.BandStats {
519 bandStat := ofp.NewMeterBandStats()
520 bandStat.ByteBandCount = bStat.ByteBandCount
521 bandStat.PacketBandCount = bStat.PacketBandCount
522 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800523 }
524 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800525 meterStats = append(meterStats, meterStat)
526 }
527 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800528 return response, nil
529}
530
Jonathan Hart4b110f62020-03-13 17:36:19 -0700531func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800532 response := ofp.NewMeterConfigStatsReply()
533 response.SetVersion(request.GetVersion())
534 response.SetXid(request.GetXid())
535 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
536 //TODO wire this to voltha core when it implements
537 return response, nil
538}
539
Jonathan Hart4b110f62020-03-13 17:36:19 -0700540func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800541 response := ofp.NewTableFeaturesStatsReply()
542 response.SetVersion(request.GetVersion())
543 response.SetXid(request.GetXid())
544 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
545 //TODO wire this to voltha core when it implements
546 return response, nil
547}
548
Jonathan Hart4b110f62020-03-13 17:36:19 -0700549func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800550 var response = ofp.NewTableStatsReply()
551 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
552 response.SetVersion(request.GetVersion())
553 response.SetXid(request.GetXid())
554 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
555 return response, nil
556}
557
Jonathan Hart4b110f62020-03-13 17:36:19 -0700558func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800559 response := ofp.NewQueueStatsReply()
560 response.SetVersion(request.GetVersion())
561 response.SetXid(request.GetXid())
562 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
563 //TODO wire this to voltha core when it implements
564 return response, nil
565}
566
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700567func (ofc *OFConnection) handlePortStatsRequest(request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700568 volthaClient := ofc.VolthaClient.Get()
569 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800570 return nil, NoVolthaConnectionError
571 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700572
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700573 reply, err := volthaClient.ListLogicalDevicePorts(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800574 &common.ID{Id: ofc.DeviceID})
575 if err != nil {
576 return nil, err
577 }
578 var entries []*ofp.PortStatsEntry
579 if request.GetPortNo() == 0xffffffff { //all ports
580 for _, port := range reply.GetItems() {
581 entries = append(entries, parsePortStats(port))
582 }
583 } else { //find right port that is requested
584 for _, port := range reply.GetItems() {
585 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
586 entries = append(entries, parsePortStats(port))
587 }
588 }
589 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700590
591 var responses []*ofp.PortStatsReply
592 chunkSize := 500
593 total := len(entries) / chunkSize
594 n := 0
595 for n <= total {
596
597 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
598
599 if len(chunk) == 0 {
600 break
601 }
602
603 response := ofp.NewPortStatsReply()
604 response.SetXid(request.GetXid())
605 response.SetVersion(request.GetVersion())
606 if total != n {
607 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
608 }
609 response.SetEntries(entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))])
610 responses = append(responses, response)
611 n++
612 }
613 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800614}
615
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700616func (ofc *OFConnection) handlePortDescStatsRequest(request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700617 volthaClient := ofc.VolthaClient.Get()
618 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800619 return nil, NoVolthaConnectionError
620 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700621
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700622 logicalDevice, err := volthaClient.GetLogicalDevice(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800623 &common.ID{Id: ofc.DeviceID})
624 if err != nil {
625 return nil, err
626 }
627 var entries []*ofp.PortDesc
628 for _, port := range logicalDevice.GetPorts() {
629 ofpPort := port.GetOfpPort()
630 var entry ofp.PortDesc
631 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
632
633 var octets []byte
634 for _, val := range ofpPort.GetHwAddr() {
635 octets = append(octets, byte(val))
636 }
637 hwAddr := net.HardwareAddr(octets)
638 entry.SetHwAddr(hwAddr)
639 entry.SetName(PadString(ofpPort.GetName(), 16))
640 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
641 entry.SetState(ofp.PortState(ofpPort.GetState()))
642 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
643 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
644 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
645 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
646 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
647 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
648
649 entries = append(entries, &entry)
650 }
651
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700652 var responses []*ofp.PortDescStatsReply
653 chunkSize := 500
654 total := len(entries) / chunkSize
655 n := 0
656 for n <= total {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800657
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700658 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
659
660 if len(chunk) == 0 {
661 break
662 }
663
664 response := ofp.NewPortDescStatsReply()
665 response.SetVersion(request.GetVersion())
666 response.SetXid(request.GetXid())
667 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
668 if total != n {
669 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
670 }
671 response.SetEntries(chunk)
672 responses = append(responses, response)
673 n++
674 }
675 return responses, nil
676
677}
678
679// Interestingly enough there is no min function fot two integers
680func min(a, b int) int {
681 if a < b {
682 return a
683 }
684 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800685}
686
Jonathan Hart4b110f62020-03-13 17:36:19 -0700687func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800688 response := ofp.NewMeterFeaturesStatsReply()
689 response.SetXid(request.GetXid())
690 response.SetVersion(request.GetVersion())
691 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
692 meterFeatures := ofp.NewMeterFeatures()
693 meterFeatures.Capabilities = ofp.OFPMFKbps
694 meterFeatures.BandTypes = ofp.OFPMBTDrop
695 meterFeatures.MaxMeter = 0xffffffff
696 meterFeatures.MaxBands = 0xff
697 meterFeatures.MaxColor = 0xff
698 response.Features = *meterFeatures
699 return response, nil
700}
701
Jonathan Hart4b110f62020-03-13 17:36:19 -0700702func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800703 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
704 response.SetVersion(request.GetVersion())
705 response.SetXid(request.GetXid())
706 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
707 //TODO wire this to voltha core when it implements
708 return response, nil
709}