blob: 1cd656ea9d508143912ae26e151b87d378650435 [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"
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -040022 "net"
23
Jonathan Hart828908c2020-04-15 14:23:45 -070024 "github.com/opencord/goloxi"
25 ofp "github.com/opencord/goloxi/of13"
Maninder12b909f2020-10-23 14:23:36 +053026 "github.com/opencord/voltha-lib-go/v4/pkg/log"
27 "github.com/opencord/voltha-protos/v4/go/common"
28 "github.com/opencord/voltha-protos/v4/go/openflow_13"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080029)
30
Rohan Agrawalc32d9932020-06-15 11:01:47 +000031func (ofc *OFConnection) handleStatsRequest(ctx context.Context, request ofp.IHeader, statType uint16) error {
Girish Kumar01e0c632020-08-10 16:48:56 +000032 span, ctx := log.CreateChildSpan(ctx, "openflow-stats")
33 defer span.Finish()
34
David K. Bainbridge157bdab2020-01-16 14:38:05 -080035 if logger.V(log.DebugLevel) {
36 js, _ := json.Marshal(request)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000037 logger.Debugw(ctx, "handleStatsRequest called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080038 log.Fields{
39 "device-id": ofc.DeviceID,
40 "stat-type": statType,
41 "request": js})
42 }
43
44 switch statType {
45 case ofp.OFPSTDesc:
46 statsReq := request.(*ofp.DescStatsRequest)
Girish Kumar01e0c632020-08-10 16:48:56 +000047 response, err := ofc.handleDescStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080048 if err != nil {
49 return err
50 }
51 if logger.V(log.DebugLevel) {
52 reqJs, _ := json.Marshal(statsReq)
53 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000054 logger.Debugw(ctx, "handle-stats-request-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080055 log.Fields{
56 "device-id": ofc.DeviceID,
57 "request": reqJs,
58 "response": resJs})
59 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +000060 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080061 case ofp.OFPSTFlow:
62 statsReq := request.(*ofp.FlowStatsRequest)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000063 responses, err := ofc.handleFlowStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080064 if err != nil {
65 return err
66 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080067 if logger.V(log.DebugLevel) {
68 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070069 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000070 logger.Debugw(ctx, "handle-stats-request-flow",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080071 log.Fields{
Matteo Scandoloe23b7582020-05-21 13:50:02 -070072 "device-id": ofc.DeviceID,
73 "request": reqJs,
74 "responses-object": responses,
75 "response": resJs})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080076 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -070077 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000078 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070079 if err != nil {
80 return err
81 }
82 }
83 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080084
85 case ofp.OFPSTAggregate:
86 statsReq := request.(*ofp.AggregateStatsRequest)
87 response, err := ofc.handleAggregateStatsRequest(statsReq)
88 if err != nil {
89 return err
90 }
91 if logger.V(log.DebugLevel) {
92 reqJs, _ := json.Marshal(statsReq)
93 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000094 logger.Debugw(ctx, "handle-stats-request-aggregate",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080095 log.Fields{
96 "device-id": ofc.DeviceID,
97 "request": reqJs,
98 "response": resJs})
99 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000100 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800101 case ofp.OFPSTTable:
102 statsReq := request.(*ofp.TableStatsRequest)
103 response, e := ofc.handleTableStatsRequest(statsReq)
104 if logger.V(log.DebugLevel) {
105 reqJs, _ := json.Marshal(statsReq)
106 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000107 logger.Debugw(ctx, "handle-stats-request-table",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800108 log.Fields{
109 "device-id": ofc.DeviceID,
110 "request": reqJs,
111 "response": resJs})
112 }
113 if e != nil {
114 return e
115 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000116 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800117 case ofp.OFPSTPort:
118 statsReq := request.(*ofp.PortStatsRequest)
Girish Kumar01e0c632020-08-10 16:48:56 +0000119 responses, err := ofc.handlePortStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 if err != nil {
121 return err
122 }
123 if logger.V(log.DebugLevel) {
124 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700125 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000126 logger.Debugw(ctx, "handle-stats-request-port",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800127 log.Fields{
128 "device-id": ofc.DeviceID,
129 "request": reqJs,
130 "response": resJs})
131 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700132 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000133 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700134 if err != nil {
135 return err
136 }
137 }
138 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800139 case ofp.OFPSTQueue:
140 statsReq := request.(*ofp.QueueStatsRequest)
141 response, err := ofc.handleQueueStatsRequest(statsReq)
142 if err != nil {
143 return err
144 }
145 if logger.V(log.DebugLevel) {
146 reqJs, _ := json.Marshal(statsReq)
147 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000148 logger.Debugw(ctx, "handle-stats-request-queue",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800149 log.Fields{
150 "device-id": ofc.DeviceID,
151 "request": reqJs,
152 "response": resJs})
153 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000154 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800155 case ofp.OFPSTGroup:
156 statsReq := request.(*ofp.GroupStatsRequest)
Girish Kumar01e0c632020-08-10 16:48:56 +0000157 response, err := ofc.handleGroupStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800158 if err != nil {
159 return err
160 }
161 if logger.V(log.DebugLevel) {
162 reqJs, _ := json.Marshal(statsReq)
163 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000164 logger.Debugw(ctx, "handle-stats-request-group",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165 log.Fields{
166 "device-id": ofc.DeviceID,
167 "request": reqJs,
168 "response": resJs})
169 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000170 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800171 case ofp.OFPSTGroupDesc:
172 statsReq := request.(*ofp.GroupDescStatsRequest)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000173 response, err := ofc.handleGroupStatsDescRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800174 if err != nil {
175 return err
176 }
177 if logger.V(log.DebugLevel) {
178 reqJs, _ := json.Marshal(statsReq)
179 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000180 logger.Debugw(ctx, "handle-stats-request-group-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800181 log.Fields{
182 "device-id": ofc.DeviceID,
183 "request": reqJs,
184 "response": resJs})
185 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000186 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800187
188 case ofp.OFPSTGroupFeatures:
189 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
190 response, err := ofc.handleGroupFeatureStatsRequest(statsReq)
191 if err != nil {
192 return err
193 }
194 if logger.V(log.DebugLevel) {
195 reqJs, _ := json.Marshal(statsReq)
196 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000197 logger.Debugw(ctx, "handle-stats-request-group-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800198 log.Fields{
199 "device-id": ofc.DeviceID,
200 "request": reqJs,
201 "response": resJs})
202 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000203 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800204 case ofp.OFPSTMeter:
205 statsReq := request.(*ofp.MeterStatsRequest)
Girish Kumar01e0c632020-08-10 16:48:56 +0000206 response, err := ofc.handleMeterStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800207 if err != nil {
208 return err
209 }
210 if logger.V(log.DebugLevel) {
211 reqJs, _ := json.Marshal(statsReq)
212 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000213 logger.Debugw(ctx, "handle-stats-request-meter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800214 log.Fields{
215 "device-id": ofc.DeviceID,
216 "request": reqJs,
217 "response": resJs})
218 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000219 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800220 case ofp.OFPSTMeterConfig:
221 statsReq := request.(*ofp.MeterConfigStatsRequest)
222 response, err := ofc.handleMeterConfigStatsRequest(statsReq)
223 if err != nil {
224 return err
225 }
226 if logger.V(log.DebugLevel) {
227 reqJs, _ := json.Marshal(statsReq)
228 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000229 logger.Debugw(ctx, "handle-stats-request-meter-config",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800230 log.Fields{
231 "device-id": ofc.DeviceID,
232 "request": reqJs,
233 "response": resJs})
234 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000235 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800236 case ofp.OFPSTMeterFeatures:
237 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
238 response, err := ofc.handleMeterFeatureStatsRequest(statsReq)
239 if err != nil {
240 return err
241 }
242 if logger.V(log.DebugLevel) {
243 reqJs, _ := json.Marshal(statsReq)
244 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000245 logger.Debugw(ctx, "handle-stats-request-meter-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800246 log.Fields{
247 "device-id": ofc.DeviceID,
248 "request": reqJs,
249 "response": resJs})
250 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000251 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800252 case ofp.OFPSTTableFeatures:
253 statsReq := request.(*ofp.TableFeaturesStatsRequest)
254 response, err := ofc.handleTableFeaturesStatsRequest(statsReq)
255 if err != nil {
256 return err
257 }
258 if logger.V(log.DebugLevel) {
259 reqJs, _ := json.Marshal(statsReq)
260 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000261 logger.Debugw(ctx, "handle-stats-request-table-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800262 log.Fields{
263 "device-id": ofc.DeviceID,
264 "request": reqJs,
265 "response": resJs})
266 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000267 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800268 case ofp.OFPSTPortDesc:
269 statsReq := request.(*ofp.PortDescStatsRequest)
Girish Kumar01e0c632020-08-10 16:48:56 +0000270 responses, err := ofc.handlePortDescStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800271 if err != nil {
272 return err
273 }
274 if logger.V(log.DebugLevel) {
275 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700276 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000277 logger.Debugw(ctx, "handle-stats-request-port-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800278 log.Fields{
279 "device-id": ofc.DeviceID,
280 "request": reqJs,
281 "response": resJs})
282 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700283 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000284 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700285 if err != nil {
286 return err
287 }
288 }
289 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800290
291 case ofp.OFPSTExperimenter:
292 statsReq := request.(*ofp.ExperimenterStatsRequest)
293 response, err := ofc.handleExperimenterStatsRequest(statsReq)
294 if err != nil {
295 return err
296 }
297 if logger.V(log.DebugLevel) {
298 reqJs, _ := json.Marshal(statsReq)
299 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000300 logger.Debugw(ctx, "handle-stats-request-experimenter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800301 log.Fields{
302 "device-id": ofc.DeviceID,
303 "request": reqJs,
304 "response": resJs})
305 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000306 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800307 }
308 return nil
309}
310
Girish Kumar01e0c632020-08-10 16:48:56 +0000311func (ofc *OFConnection) handleDescStatsRequest(ctx context.Context, request *ofp.DescStatsRequest) (*ofp.DescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700312 volthaClient := ofc.VolthaClient.Get()
313 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800314 return nil, NoVolthaConnectionError
315 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800316 response := ofp.NewDescStatsReply()
317 response.SetXid(request.GetXid())
318 response.SetVersion(request.GetVersion())
319 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
320
Girish Kumar01e0c632020-08-10 16:48:56 +0000321 resp, err := volthaClient.GetLogicalDevice(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800322 &common.ID{Id: ofc.DeviceID})
323 if err != nil {
324 return nil, err
325 }
326 desc := resp.GetDesc()
327
328 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
329 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
330 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
331 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
332 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
333 return response, nil
334}
335
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000336func (ofc *OFConnection) handleFlowStatsRequest(ctx context.Context, request *ofp.FlowStatsRequest) ([]*ofp.FlowStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700337 volthaClient := ofc.VolthaClient.Get()
338 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800339 return nil, NoVolthaConnectionError
340 }
Girish Kumar01e0c632020-08-10 16:48:56 +0000341 resp, err := volthaClient.ListLogicalDeviceFlows(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800342 &common.ID{Id: ofc.DeviceID})
343 if err != nil {
344 return nil, err
345 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100346 logger.Debugw(ctx, "logicalDeviceFlows", log.Fields{"flows": resp})
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700347 var flows []*ofp.FlowStatsEntry
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800348 for _, item := range resp.GetItems() {
349 entry := ofp.NewFlowStatsEntry()
350 entry.SetTableId(uint8(item.GetTableId()))
351 entry.SetDurationSec(item.GetDurationSec())
352 entry.SetDurationNsec(item.GetDurationNsec())
353 entry.SetPriority(uint16(item.GetPriority()))
354 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
355 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
356 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
357 entry.SetCookie(item.GetCookie())
358 entry.SetPacketCount(item.GetPacketCount())
359 entry.SetByteCount(item.GetByteCount())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800360 match := ofp.NewMatchV3()
361 pbMatch := item.GetMatch()
362 match.SetType(uint16(pbMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800363 var fields []goloxi.IOxm
364 for _, oxmField := range pbMatch.GetOxmFields() {
365 field := oxmField.GetField()
366 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100367 iOxm, err := parseOxm(ctx, ofbField)
368 if err == nil {
369 fields = append(fields, iOxm)
370 } else {
371 logger.Errorw(ctx, "error-parsing-oxm", log.Fields{"err": err})
372 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800373 }
374
375 match.OxmList = fields
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800376 entry.SetMatch(*match)
377 var instructions []ofp.IInstruction
378 for _, ofpInstruction := range item.Instructions {
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100379 instruction, err := parseInstructions(ctx, ofpInstruction)
380 if err == nil {
381 instructions = append(instructions, instruction)
382 } else {
383 logger.Errorw(ctx, "error-parsing-instruction", log.Fields{"err": err})
384 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800385 }
386 entry.Instructions = instructions
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700387 flows = append(flows, entry)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800388 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700389 var responses []*ofp.FlowStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700390 chunkSize := ofc.flowsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700391 total := len(flows) / chunkSize
392 n := 0
393 for n <= total {
394
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200395 limit := (n * chunkSize) + chunkSize
396
397 chunk := flows[n*chunkSize : min(limit, len(flows))]
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700398
399 if len(chunk) == 0 {
400 break
401 }
402
403 response := ofp.NewFlowStatsReply()
404 response.SetXid(request.GetXid())
405 response.SetVersion(4)
406 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200407 if limit < len(flows) {
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700408 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
409 }
410 response.SetEntries(chunk)
411 responses = append(responses, response)
412 n++
413 }
414 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800415}
416
Jonathan Hart4b110f62020-03-13 17:36:19 -0700417func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800418 response := ofp.NewAggregateStatsReply()
419 response.SetVersion(request.GetVersion())
420 response.SetXid(request.GetXid())
421 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
422 response.SetFlowCount(0)
423 //TODO wire this to voltha core when it implements
424 return response, nil
425}
426
Girish Kumar01e0c632020-08-10 16:48:56 +0000427func (ofc *OFConnection) handleGroupStatsRequest(ctx context.Context, request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700428 volthaClient := ofc.VolthaClient.Get()
429 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800430 return nil, NoVolthaConnectionError
431 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800432 response := ofp.NewGroupStatsReply()
433 response.SetVersion(request.GetVersion())
434 response.SetXid(request.GetXid())
435 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000436 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800437 &common.ID{Id: ofc.DeviceID})
438 if err != nil {
439 return nil, err
440 }
441
442 var groupStatsEntries []*ofp.GroupStatsEntry
443 for _, item := range reply.GetItems() {
444 stats := item.GetStats()
445 var entry ofp.GroupStatsEntry
446 entry.SetByteCount(stats.GetByteCount())
447 entry.SetPacketCount(stats.GetPacketCount())
448 entry.SetDurationNsec(stats.GetDurationNsec())
449 entry.SetDurationSec(stats.GetDurationSec())
450 entry.SetRefCount(stats.GetRefCount())
451 entry.SetGroupId(stats.GetGroupId())
452 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700453 // TODO fix this when API handler is fixed in the core
454 // Core doesn't return any buckets in the Stats object, so just
455 // fill out an empty BucketCounter for each bucket in the group Desc for now.
456 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800457 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700458 bucketCounter.SetPacketCount(0)
459 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800460 bucketStatsList = append(bucketStatsList, &bucketCounter)
461 }
462 entry.SetBucketStats(bucketStatsList)
463 groupStatsEntries = append(groupStatsEntries, &entry)
464 }
465 response.SetEntries(groupStatsEntries)
466 return response, nil
467}
468
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000469func (ofc *OFConnection) handleGroupStatsDescRequest(ctx context.Context, request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700470 volthaClient := ofc.VolthaClient.Get()
471 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800472 return nil, NoVolthaConnectionError
473 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800474 response := ofp.NewGroupDescStatsReply()
475 response.SetVersion(request.GetVersion())
476 response.SetXid(request.GetXid())
477 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000478 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800479 &common.ID{Id: ofc.DeviceID})
480 if err != nil {
481 return nil, err
482 }
483 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
484 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700485 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800486
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100487 buckets, err := volthaBucketsToOpenflow(ctx, desc.Buckets)
488 if err != nil {
489 return nil, err
490 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800491
Jonathan Hart60c5d772020-03-30 18:28:40 -0700492 groupDesc := &ofp.GroupDescStatsEntry{
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000493 GroupType: volthaGroupTypeToOpenflow(ctx, desc.Type),
Jonathan Hart60c5d772020-03-30 18:28:40 -0700494 GroupId: desc.GroupId,
495 Buckets: buckets,
496 }
497 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800498 }
499 response.SetEntries(groupDescStatsEntries)
500 return response, nil
501}
502
Jonathan Hart4b110f62020-03-13 17:36:19 -0700503func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800504 response := ofp.NewGroupFeaturesStatsReply()
505 response.SetVersion(request.GetVersion())
506 response.SetXid(request.GetXid())
507 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
508 //TODO wire this to voltha core when it implements
509 return response, nil
510}
511
Girish Kumar01e0c632020-08-10 16:48:56 +0000512func (ofc *OFConnection) handleMeterStatsRequest(ctx context.Context, request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700513 volthaClient := ofc.VolthaClient.Get()
514 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800515 return nil, NoVolthaConnectionError
516 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800517 response := ofp.NewMeterStatsReply()
518 response.SetVersion(request.GetVersion())
519 response.SetXid(request.GetXid())
520 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000521 resp, err := volthaClient.ListLogicalDeviceMeters(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800522 &common.ID{Id: ofc.DeviceID})
523 if err != nil {
524 return nil, err
525 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800526 var meterStats []*ofp.MeterStats
527 for _, item := range resp.Items {
528 meterStat := ofp.NewMeterStats()
529 stats := item.Stats
530 meterStat.DurationNsec = stats.DurationNsec
531 meterStat.DurationSec = stats.DurationSec
532 meterStat.ByteInCount = stats.ByteInCount
533 meterStat.FlowCount = stats.FlowCount
534 meterStat.MeterId = stats.MeterId
535 var bandStats []*ofp.MeterBandStats
536 for _, bStat := range stats.BandStats {
537 bandStat := ofp.NewMeterBandStats()
538 bandStat.ByteBandCount = bStat.ByteBandCount
539 bandStat.PacketBandCount = bStat.PacketBandCount
540 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800541 }
542 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800543 meterStats = append(meterStats, meterStat)
544 }
545 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800546 return response, nil
547}
548
Jonathan Hart4b110f62020-03-13 17:36:19 -0700549func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800550 response := ofp.NewMeterConfigStatsReply()
551 response.SetVersion(request.GetVersion())
552 response.SetXid(request.GetXid())
553 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
554 //TODO wire this to voltha core when it implements
555 return response, nil
556}
557
Jonathan Hart4b110f62020-03-13 17:36:19 -0700558func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800559 response := ofp.NewTableFeaturesStatsReply()
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
Jonathan Hart4b110f62020-03-13 17:36:19 -0700567func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800568 var response = ofp.NewTableStatsReply()
569 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
570 response.SetVersion(request.GetVersion())
571 response.SetXid(request.GetXid())
572 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
573 return response, nil
574}
575
Jonathan Hart4b110f62020-03-13 17:36:19 -0700576func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800577 response := ofp.NewQueueStatsReply()
578 response.SetVersion(request.GetVersion())
579 response.SetXid(request.GetXid())
580 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
581 //TODO wire this to voltha core when it implements
582 return response, nil
583}
584
Girish Kumar01e0c632020-08-10 16:48:56 +0000585func (ofc *OFConnection) handlePortStatsRequest(ctx context.Context, request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700586 volthaClient := ofc.VolthaClient.Get()
587 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800588 return nil, NoVolthaConnectionError
589 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700590
Girish Kumar01e0c632020-08-10 16:48:56 +0000591 reply, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800592 &common.ID{Id: ofc.DeviceID})
593 if err != nil {
594 return nil, err
595 }
596 var entries []*ofp.PortStatsEntry
597 if request.GetPortNo() == 0xffffffff { //all ports
598 for _, port := range reply.GetItems() {
599 entries = append(entries, parsePortStats(port))
600 }
601 } else { //find right port that is requested
602 for _, port := range reply.GetItems() {
603 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
604 entries = append(entries, parsePortStats(port))
605 }
606 }
607 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700608
609 var responses []*ofp.PortStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700610 chunkSize := ofc.portsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700611 total := len(entries) / chunkSize
612 n := 0
613 for n <= total {
614
615 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
616
617 if len(chunk) == 0 {
618 break
619 }
620
621 response := ofp.NewPortStatsReply()
622 response.SetXid(request.GetXid())
623 response.SetVersion(request.GetVersion())
624 if total != n {
625 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
626 }
627 response.SetEntries(entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))])
628 responses = append(responses, response)
629 n++
630 }
631 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800632}
633
Girish Kumar01e0c632020-08-10 16:48:56 +0000634func (ofc *OFConnection) handlePortDescStatsRequest(ctx context.Context, request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700635 volthaClient := ofc.VolthaClient.Get()
636 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800637 return nil, NoVolthaConnectionError
638 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700639
Girish Kumar01e0c632020-08-10 16:48:56 +0000640 ports, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx), &common.ID{Id: ofc.DeviceID})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800641 if err != nil {
642 return nil, err
643 }
644 var entries []*ofp.PortDesc
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400645 for _, port := range ports.Items {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800646 ofpPort := port.GetOfpPort()
647 var entry ofp.PortDesc
648 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
649
650 var octets []byte
651 for _, val := range ofpPort.GetHwAddr() {
652 octets = append(octets, byte(val))
653 }
654 hwAddr := net.HardwareAddr(octets)
655 entry.SetHwAddr(hwAddr)
656 entry.SetName(PadString(ofpPort.GetName(), 16))
657 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
658 entry.SetState(ofp.PortState(ofpPort.GetState()))
659 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
660 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
661 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
662 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
663 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
664 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
665
666 entries = append(entries, &entry)
667 }
668
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700669 var responses []*ofp.PortDescStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700670 chunkSize := ofc.portsDescChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700671 total := len(entries) / chunkSize
672 n := 0
673 for n <= total {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800674
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700675 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
676
677 if len(chunk) == 0 {
678 break
679 }
680
681 response := ofp.NewPortDescStatsReply()
682 response.SetVersion(request.GetVersion())
683 response.SetXid(request.GetXid())
684 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
685 if total != n {
686 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
687 }
688 response.SetEntries(chunk)
689 responses = append(responses, response)
690 n++
691 }
692 return responses, nil
693
694}
695
696// Interestingly enough there is no min function fot two integers
697func min(a, b int) int {
698 if a < b {
699 return a
700 }
701 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800702}
703
Jonathan Hart4b110f62020-03-13 17:36:19 -0700704func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800705 response := ofp.NewMeterFeaturesStatsReply()
706 response.SetXid(request.GetXid())
707 response.SetVersion(request.GetVersion())
708 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
709 meterFeatures := ofp.NewMeterFeatures()
710 meterFeatures.Capabilities = ofp.OFPMFKbps
711 meterFeatures.BandTypes = ofp.OFPMBTDrop
712 meterFeatures.MaxMeter = 0xffffffff
713 meterFeatures.MaxBands = 0xff
714 meterFeatures.MaxColor = 0xff
715 response.Features = *meterFeatures
716 return response, nil
717}
718
Jonathan Hart4b110f62020-03-13 17:36:19 -0700719func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800720 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
721 response.SetVersion(request.GetVersion())
722 response.SetXid(request.GetXid())
723 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
724 //TODO wire this to voltha core when it implements
725 return response, nil
726}