blob: 69337437714c97da96bcd1ec114fc2221354835d [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"
Andrea Campanella18448bc2021-07-08 18:47:22 +020026 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninder12b909f2020-10-23 14:23:36 +053027 "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 }
khenaidoo47f99de2021-05-20 13:22:49 -0400346 logger.Debugw(ctx, "logicalDeviceFlows", log.Fields{"logical-device-id": ofc.DeviceID, "num-flows": len(resp.Items)})
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
khenaidoo47f99de2021-05-20 13:22:49 -0400390
Matteo Scandolo256266d2020-06-01 13:44:07 -0700391 chunkSize := ofc.flowsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700392 total := len(flows) / chunkSize
393 n := 0
394 for n <= total {
khenaidoo47f99de2021-05-20 13:22:49 -0400395 response := ofp.NewFlowStatsReply()
396 response.SetXid(request.GetXid())
397 response.SetVersion(request.GetVersion())
398 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700399
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200400 limit := (n * chunkSize) + chunkSize
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200401 chunk := flows[n*chunkSize : min(limit, len(flows))]
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700402
403 if len(chunk) == 0 {
khenaidoo47f99de2021-05-20 13:22:49 -0400404 // Special case - no flows
405 if len(flows) == 0 {
406 logger.Debugw(ctx, "no-flows-present", log.Fields{"logical-device-id": ofc.DeviceID})
407 response.SetEntries(chunk)
408 responses = append(responses, response)
409 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700410 break
411 }
412
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200413 if limit < len(flows) {
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700414 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
415 }
416 response.SetEntries(chunk)
417 responses = append(responses, response)
418 n++
419 }
420 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800421}
422
Jonathan Hart4b110f62020-03-13 17:36:19 -0700423func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800424 response := ofp.NewAggregateStatsReply()
425 response.SetVersion(request.GetVersion())
426 response.SetXid(request.GetXid())
427 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
428 response.SetFlowCount(0)
429 //TODO wire this to voltha core when it implements
430 return response, nil
431}
432
Girish Kumar01e0c632020-08-10 16:48:56 +0000433func (ofc *OFConnection) handleGroupStatsRequest(ctx context.Context, request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700434 volthaClient := ofc.VolthaClient.Get()
435 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800436 return nil, NoVolthaConnectionError
437 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800438 response := ofp.NewGroupStatsReply()
439 response.SetVersion(request.GetVersion())
440 response.SetXid(request.GetXid())
441 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000442 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800443 &common.ID{Id: ofc.DeviceID})
444 if err != nil {
445 return nil, err
446 }
447
448 var groupStatsEntries []*ofp.GroupStatsEntry
449 for _, item := range reply.GetItems() {
450 stats := item.GetStats()
451 var entry ofp.GroupStatsEntry
452 entry.SetByteCount(stats.GetByteCount())
453 entry.SetPacketCount(stats.GetPacketCount())
454 entry.SetDurationNsec(stats.GetDurationNsec())
455 entry.SetDurationSec(stats.GetDurationSec())
456 entry.SetRefCount(stats.GetRefCount())
457 entry.SetGroupId(stats.GetGroupId())
458 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700459 // TODO fix this when API handler is fixed in the core
460 // Core doesn't return any buckets in the Stats object, so just
461 // fill out an empty BucketCounter for each bucket in the group Desc for now.
462 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800463 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700464 bucketCounter.SetPacketCount(0)
465 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800466 bucketStatsList = append(bucketStatsList, &bucketCounter)
467 }
468 entry.SetBucketStats(bucketStatsList)
469 groupStatsEntries = append(groupStatsEntries, &entry)
470 }
471 response.SetEntries(groupStatsEntries)
472 return response, nil
473}
474
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000475func (ofc *OFConnection) handleGroupStatsDescRequest(ctx context.Context, request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700476 volthaClient := ofc.VolthaClient.Get()
477 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800478 return nil, NoVolthaConnectionError
479 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800480 response := ofp.NewGroupDescStatsReply()
481 response.SetVersion(request.GetVersion())
482 response.SetXid(request.GetXid())
483 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000484 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800485 &common.ID{Id: ofc.DeviceID})
486 if err != nil {
487 return nil, err
488 }
489 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
490 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700491 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800492
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100493 buckets, err := volthaBucketsToOpenflow(ctx, desc.Buckets)
494 if err != nil {
495 return nil, err
496 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800497
Jonathan Hart60c5d772020-03-30 18:28:40 -0700498 groupDesc := &ofp.GroupDescStatsEntry{
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000499 GroupType: volthaGroupTypeToOpenflow(ctx, desc.Type),
Jonathan Hart60c5d772020-03-30 18:28:40 -0700500 GroupId: desc.GroupId,
501 Buckets: buckets,
502 }
503 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800504 }
505 response.SetEntries(groupDescStatsEntries)
506 return response, nil
507}
508
Jonathan Hart4b110f62020-03-13 17:36:19 -0700509func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800510 response := ofp.NewGroupFeaturesStatsReply()
511 response.SetVersion(request.GetVersion())
512 response.SetXid(request.GetXid())
513 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
514 //TODO wire this to voltha core when it implements
515 return response, nil
516}
517
Girish Kumar01e0c632020-08-10 16:48:56 +0000518func (ofc *OFConnection) handleMeterStatsRequest(ctx context.Context, request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700519 volthaClient := ofc.VolthaClient.Get()
520 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800521 return nil, NoVolthaConnectionError
522 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800523 response := ofp.NewMeterStatsReply()
524 response.SetVersion(request.GetVersion())
525 response.SetXid(request.GetXid())
526 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000527 resp, err := volthaClient.ListLogicalDeviceMeters(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800528 &common.ID{Id: ofc.DeviceID})
529 if err != nil {
530 return nil, err
531 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800532 var meterStats []*ofp.MeterStats
533 for _, item := range resp.Items {
534 meterStat := ofp.NewMeterStats()
535 stats := item.Stats
536 meterStat.DurationNsec = stats.DurationNsec
537 meterStat.DurationSec = stats.DurationSec
538 meterStat.ByteInCount = stats.ByteInCount
539 meterStat.FlowCount = stats.FlowCount
540 meterStat.MeterId = stats.MeterId
541 var bandStats []*ofp.MeterBandStats
542 for _, bStat := range stats.BandStats {
543 bandStat := ofp.NewMeterBandStats()
544 bandStat.ByteBandCount = bStat.ByteBandCount
545 bandStat.PacketBandCount = bStat.PacketBandCount
546 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800547 }
548 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800549 meterStats = append(meterStats, meterStat)
550 }
551 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800552 return response, nil
553}
554
Jonathan Hart4b110f62020-03-13 17:36:19 -0700555func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800556 response := ofp.NewMeterConfigStatsReply()
557 response.SetVersion(request.GetVersion())
558 response.SetXid(request.GetXid())
559 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
560 //TODO wire this to voltha core when it implements
561 return response, nil
562}
563
Jonathan Hart4b110f62020-03-13 17:36:19 -0700564func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800565 response := ofp.NewTableFeaturesStatsReply()
566 response.SetVersion(request.GetVersion())
567 response.SetXid(request.GetXid())
568 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
569 //TODO wire this to voltha core when it implements
570 return response, nil
571}
572
Jonathan Hart4b110f62020-03-13 17:36:19 -0700573func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800574 var response = ofp.NewTableStatsReply()
575 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
576 response.SetVersion(request.GetVersion())
577 response.SetXid(request.GetXid())
578 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
579 return response, nil
580}
581
Jonathan Hart4b110f62020-03-13 17:36:19 -0700582func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800583 response := ofp.NewQueueStatsReply()
584 response.SetVersion(request.GetVersion())
585 response.SetXid(request.GetXid())
586 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
587 //TODO wire this to voltha core when it implements
588 return response, nil
589}
590
Girish Kumar01e0c632020-08-10 16:48:56 +0000591func (ofc *OFConnection) handlePortStatsRequest(ctx context.Context, request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700592 volthaClient := ofc.VolthaClient.Get()
593 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800594 return nil, NoVolthaConnectionError
595 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700596
Girish Kumar01e0c632020-08-10 16:48:56 +0000597 reply, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800598 &common.ID{Id: ofc.DeviceID})
599 if err != nil {
600 return nil, err
601 }
602 var entries []*ofp.PortStatsEntry
603 if request.GetPortNo() == 0xffffffff { //all ports
604 for _, port := range reply.GetItems() {
605 entries = append(entries, parsePortStats(port))
606 }
607 } else { //find right port that is requested
608 for _, port := range reply.GetItems() {
609 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
610 entries = append(entries, parsePortStats(port))
611 }
612 }
613 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700614
615 var responses []*ofp.PortStatsReply
khenaidoo47f99de2021-05-20 13:22:49 -0400616
Matteo Scandolo256266d2020-06-01 13:44:07 -0700617 chunkSize := ofc.portsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700618 total := len(entries) / chunkSize
619 n := 0
620 for n <= total {
khenaidoo47f99de2021-05-20 13:22:49 -0400621 response := ofp.NewPortStatsReply()
622 response.SetXid(request.GetXid())
623 response.SetVersion(request.GetVersion())
624 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700625
626 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
627
628 if len(chunk) == 0 {
khenaidoo47f99de2021-05-20 13:22:49 -0400629 // handle the case of no ports
630 if len(entries) == 0 {
631 logger.Debugw(ctx, "no-ports-present", log.Fields{"logical-device-id": ofc.DeviceID})
632 response.SetEntries(chunk)
633 responses = append(responses, response)
634 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700635 break
636 }
637
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700638 if total != n {
639 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
640 }
khenaidoo47f99de2021-05-20 13:22:49 -0400641 response.SetEntries(chunk)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700642 responses = append(responses, response)
643 n++
644 }
645 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800646}
647
Girish Kumar01e0c632020-08-10 16:48:56 +0000648func (ofc *OFConnection) handlePortDescStatsRequest(ctx context.Context, request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700649 volthaClient := ofc.VolthaClient.Get()
650 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800651 return nil, NoVolthaConnectionError
652 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700653
Girish Kumar01e0c632020-08-10 16:48:56 +0000654 ports, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx), &common.ID{Id: ofc.DeviceID})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800655 if err != nil {
656 return nil, err
657 }
658 var entries []*ofp.PortDesc
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400659 for _, port := range ports.Items {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800660 ofpPort := port.GetOfpPort()
661 var entry ofp.PortDesc
662 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
663
664 var octets []byte
665 for _, val := range ofpPort.GetHwAddr() {
666 octets = append(octets, byte(val))
667 }
668 hwAddr := net.HardwareAddr(octets)
669 entry.SetHwAddr(hwAddr)
670 entry.SetName(PadString(ofpPort.GetName(), 16))
671 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
672 entry.SetState(ofp.PortState(ofpPort.GetState()))
673 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
674 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
675 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
676 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
677 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
678 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
679
680 entries = append(entries, &entry)
681 }
682
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700683 var responses []*ofp.PortDescStatsReply
khenaidoo47f99de2021-05-20 13:22:49 -0400684
Matteo Scandolo256266d2020-06-01 13:44:07 -0700685 chunkSize := ofc.portsDescChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700686 total := len(entries) / chunkSize
687 n := 0
688 for n <= total {
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700689 response := ofp.NewPortDescStatsReply()
690 response.SetVersion(request.GetVersion())
691 response.SetXid(request.GetXid())
692 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
khenaidoo47f99de2021-05-20 13:22:49 -0400693
694 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
695
696 if len(chunk) == 0 {
697 if len(entries) == 0 {
698 logger.Debugw(ctx, "no-ports-desc-present", log.Fields{"logical-device-id": ofc.DeviceID})
699 response.SetEntries(chunk)
700 responses = append(responses, response)
701 }
702 break
703 }
704
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700705 if total != n {
706 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
707 }
708 response.SetEntries(chunk)
709 responses = append(responses, response)
710 n++
711 }
712 return responses, nil
713
714}
715
716// Interestingly enough there is no min function fot two integers
717func min(a, b int) int {
718 if a < b {
719 return a
720 }
721 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800722}
723
Jonathan Hart4b110f62020-03-13 17:36:19 -0700724func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800725 response := ofp.NewMeterFeaturesStatsReply()
726 response.SetXid(request.GetXid())
727 response.SetVersion(request.GetVersion())
728 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
729 meterFeatures := ofp.NewMeterFeatures()
730 meterFeatures.Capabilities = ofp.OFPMFKbps
731 meterFeatures.BandTypes = ofp.OFPMBTDrop
732 meterFeatures.MaxMeter = 0xffffffff
733 meterFeatures.MaxBands = 0xff
734 meterFeatures.MaxColor = 0xff
735 response.Features = *meterFeatures
736 return response, nil
737}
738
Jonathan Hart4b110f62020-03-13 17:36:19 -0700739func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800740 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
741 response.SetVersion(request.GetVersion())
742 response.SetXid(request.GetXid())
743 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
744 //TODO wire this to voltha core when it implements
745 return response, nil
746}