blob: d50fc14f938693907b1cc625cc97a9b39ef1a90d [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"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080026 "github.com/opencord/voltha-lib-go/v3/pkg/log"
27 "github.com/opencord/voltha-protos/v3/go/common"
28 "github.com/opencord/voltha-protos/v3/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 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700346 var flows []*ofp.FlowStatsEntry
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800347 for _, item := range resp.GetItems() {
348 entry := ofp.NewFlowStatsEntry()
349 entry.SetTableId(uint8(item.GetTableId()))
350 entry.SetDurationSec(item.GetDurationSec())
351 entry.SetDurationNsec(item.GetDurationNsec())
352 entry.SetPriority(uint16(item.GetPriority()))
353 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
354 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
355 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
356 entry.SetCookie(item.GetCookie())
357 entry.SetPacketCount(item.GetPacketCount())
358 entry.SetByteCount(item.GetByteCount())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800359 match := ofp.NewMatchV3()
360 pbMatch := item.GetMatch()
361 match.SetType(uint16(pbMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800362 var fields []goloxi.IOxm
363 for _, oxmField := range pbMatch.GetOxmFields() {
364 field := oxmField.GetField()
365 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000366 iOxm := parseOxm(ctx, ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800367 fields = append(fields, iOxm)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800368 }
369
370 match.OxmList = fields
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800371 entry.SetMatch(*match)
372 var instructions []ofp.IInstruction
373 for _, ofpInstruction := range item.Instructions {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000374 instruction := parseInstructions(ctx, ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800375 instructions = append(instructions, instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800376 }
377 entry.Instructions = instructions
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700378 flows = append(flows, entry)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800379 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700380 var responses []*ofp.FlowStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700381 chunkSize := ofc.flowsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700382 total := len(flows) / chunkSize
383 n := 0
384 for n <= total {
385
386 chunk := flows[n*chunkSize : min((n*chunkSize)+chunkSize, len(flows))]
387
388 if len(chunk) == 0 {
389 break
390 }
391
392 response := ofp.NewFlowStatsReply()
393 response.SetXid(request.GetXid())
394 response.SetVersion(4)
395 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
396 if total != n {
397 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
398 }
399 response.SetEntries(chunk)
400 responses = append(responses, response)
401 n++
402 }
403 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800404}
405
Jonathan Hart4b110f62020-03-13 17:36:19 -0700406func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800407 response := ofp.NewAggregateStatsReply()
408 response.SetVersion(request.GetVersion())
409 response.SetXid(request.GetXid())
410 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
411 response.SetFlowCount(0)
412 //TODO wire this to voltha core when it implements
413 return response, nil
414}
415
Girish Kumar01e0c632020-08-10 16:48:56 +0000416func (ofc *OFConnection) handleGroupStatsRequest(ctx context.Context, request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700417 volthaClient := ofc.VolthaClient.Get()
418 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800419 return nil, NoVolthaConnectionError
420 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800421 response := ofp.NewGroupStatsReply()
422 response.SetVersion(request.GetVersion())
423 response.SetXid(request.GetXid())
424 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000425 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800426 &common.ID{Id: ofc.DeviceID})
427 if err != nil {
428 return nil, err
429 }
430
431 var groupStatsEntries []*ofp.GroupStatsEntry
432 for _, item := range reply.GetItems() {
433 stats := item.GetStats()
434 var entry ofp.GroupStatsEntry
435 entry.SetByteCount(stats.GetByteCount())
436 entry.SetPacketCount(stats.GetPacketCount())
437 entry.SetDurationNsec(stats.GetDurationNsec())
438 entry.SetDurationSec(stats.GetDurationSec())
439 entry.SetRefCount(stats.GetRefCount())
440 entry.SetGroupId(stats.GetGroupId())
441 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700442 // TODO fix this when API handler is fixed in the core
443 // Core doesn't return any buckets in the Stats object, so just
444 // fill out an empty BucketCounter for each bucket in the group Desc for now.
445 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800446 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700447 bucketCounter.SetPacketCount(0)
448 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800449 bucketStatsList = append(bucketStatsList, &bucketCounter)
450 }
451 entry.SetBucketStats(bucketStatsList)
452 groupStatsEntries = append(groupStatsEntries, &entry)
453 }
454 response.SetEntries(groupStatsEntries)
455 return response, nil
456}
457
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000458func (ofc *OFConnection) handleGroupStatsDescRequest(ctx context.Context, request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700459 volthaClient := ofc.VolthaClient.Get()
460 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800461 return nil, NoVolthaConnectionError
462 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800463 response := ofp.NewGroupDescStatsReply()
464 response.SetVersion(request.GetVersion())
465 response.SetXid(request.GetXid())
466 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000467 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800468 &common.ID{Id: ofc.DeviceID})
469 if err != nil {
470 return nil, err
471 }
472 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
473 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700474 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800475
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000476 buckets := volthaBucketsToOpenflow(ctx, desc.Buckets)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800477
Jonathan Hart60c5d772020-03-30 18:28:40 -0700478 groupDesc := &ofp.GroupDescStatsEntry{
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000479 GroupType: volthaGroupTypeToOpenflow(ctx, desc.Type),
Jonathan Hart60c5d772020-03-30 18:28:40 -0700480 GroupId: desc.GroupId,
481 Buckets: buckets,
482 }
483 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800484 }
485 response.SetEntries(groupDescStatsEntries)
486 return response, nil
487}
488
Jonathan Hart4b110f62020-03-13 17:36:19 -0700489func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800490 response := ofp.NewGroupFeaturesStatsReply()
491 response.SetVersion(request.GetVersion())
492 response.SetXid(request.GetXid())
493 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
494 //TODO wire this to voltha core when it implements
495 return response, nil
496}
497
Girish Kumar01e0c632020-08-10 16:48:56 +0000498func (ofc *OFConnection) handleMeterStatsRequest(ctx context.Context, request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700499 volthaClient := ofc.VolthaClient.Get()
500 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800501 return nil, NoVolthaConnectionError
502 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800503 response := ofp.NewMeterStatsReply()
504 response.SetVersion(request.GetVersion())
505 response.SetXid(request.GetXid())
506 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000507 resp, err := volthaClient.ListLogicalDeviceMeters(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800508 &common.ID{Id: ofc.DeviceID})
509 if err != nil {
510 return nil, err
511 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800512 var meterStats []*ofp.MeterStats
513 for _, item := range resp.Items {
514 meterStat := ofp.NewMeterStats()
515 stats := item.Stats
516 meterStat.DurationNsec = stats.DurationNsec
517 meterStat.DurationSec = stats.DurationSec
518 meterStat.ByteInCount = stats.ByteInCount
519 meterStat.FlowCount = stats.FlowCount
520 meterStat.MeterId = stats.MeterId
521 var bandStats []*ofp.MeterBandStats
522 for _, bStat := range stats.BandStats {
523 bandStat := ofp.NewMeterBandStats()
524 bandStat.ByteBandCount = bStat.ByteBandCount
525 bandStat.PacketBandCount = bStat.PacketBandCount
526 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800527 }
528 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800529 meterStats = append(meterStats, meterStat)
530 }
531 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800532 return response, nil
533}
534
Jonathan Hart4b110f62020-03-13 17:36:19 -0700535func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800536 response := ofp.NewMeterConfigStatsReply()
537 response.SetVersion(request.GetVersion())
538 response.SetXid(request.GetXid())
539 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
540 //TODO wire this to voltha core when it implements
541 return response, nil
542}
543
Jonathan Hart4b110f62020-03-13 17:36:19 -0700544func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800545 response := ofp.NewTableFeaturesStatsReply()
546 response.SetVersion(request.GetVersion())
547 response.SetXid(request.GetXid())
548 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
549 //TODO wire this to voltha core when it implements
550 return response, nil
551}
552
Jonathan Hart4b110f62020-03-13 17:36:19 -0700553func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800554 var response = ofp.NewTableStatsReply()
555 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
556 response.SetVersion(request.GetVersion())
557 response.SetXid(request.GetXid())
558 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
559 return response, nil
560}
561
Jonathan Hart4b110f62020-03-13 17:36:19 -0700562func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800563 response := ofp.NewQueueStatsReply()
564 response.SetVersion(request.GetVersion())
565 response.SetXid(request.GetXid())
566 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
567 //TODO wire this to voltha core when it implements
568 return response, nil
569}
570
Girish Kumar01e0c632020-08-10 16:48:56 +0000571func (ofc *OFConnection) handlePortStatsRequest(ctx context.Context, request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700572 volthaClient := ofc.VolthaClient.Get()
573 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800574 return nil, NoVolthaConnectionError
575 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700576
Girish Kumar01e0c632020-08-10 16:48:56 +0000577 reply, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800578 &common.ID{Id: ofc.DeviceID})
579 if err != nil {
580 return nil, err
581 }
582 var entries []*ofp.PortStatsEntry
583 if request.GetPortNo() == 0xffffffff { //all ports
584 for _, port := range reply.GetItems() {
585 entries = append(entries, parsePortStats(port))
586 }
587 } else { //find right port that is requested
588 for _, port := range reply.GetItems() {
589 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
590 entries = append(entries, parsePortStats(port))
591 }
592 }
593 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700594
595 var responses []*ofp.PortStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700596 chunkSize := ofc.portsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700597 total := len(entries) / chunkSize
598 n := 0
599 for n <= total {
600
601 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
602
603 if len(chunk) == 0 {
604 break
605 }
606
607 response := ofp.NewPortStatsReply()
608 response.SetXid(request.GetXid())
609 response.SetVersion(request.GetVersion())
610 if total != n {
611 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
612 }
613 response.SetEntries(entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))])
614 responses = append(responses, response)
615 n++
616 }
617 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800618}
619
Girish Kumar01e0c632020-08-10 16:48:56 +0000620func (ofc *OFConnection) handlePortDescStatsRequest(ctx context.Context, request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700621 volthaClient := ofc.VolthaClient.Get()
622 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800623 return nil, NoVolthaConnectionError
624 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700625
Girish Kumar01e0c632020-08-10 16:48:56 +0000626 ports, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx), &common.ID{Id: ofc.DeviceID})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800627 if err != nil {
628 return nil, err
629 }
630 var entries []*ofp.PortDesc
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400631 for _, port := range ports.Items {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800632 ofpPort := port.GetOfpPort()
633 var entry ofp.PortDesc
634 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
635
636 var octets []byte
637 for _, val := range ofpPort.GetHwAddr() {
638 octets = append(octets, byte(val))
639 }
640 hwAddr := net.HardwareAddr(octets)
641 entry.SetHwAddr(hwAddr)
642 entry.SetName(PadString(ofpPort.GetName(), 16))
643 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
644 entry.SetState(ofp.PortState(ofpPort.GetState()))
645 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
646 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
647 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
648 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
649 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
650 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
651
652 entries = append(entries, &entry)
653 }
654
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700655 var responses []*ofp.PortDescStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700656 chunkSize := ofc.portsDescChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700657 total := len(entries) / chunkSize
658 n := 0
659 for n <= total {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800660
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700661 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
662
663 if len(chunk) == 0 {
664 break
665 }
666
667 response := ofp.NewPortDescStatsReply()
668 response.SetVersion(request.GetVersion())
669 response.SetXid(request.GetXid())
670 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
671 if total != n {
672 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
673 }
674 response.SetEntries(chunk)
675 responses = append(responses, response)
676 n++
677 }
678 return responses, nil
679
680}
681
682// Interestingly enough there is no min function fot two integers
683func min(a, b int) int {
684 if a < b {
685 return a
686 }
687 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800688}
689
Jonathan Hart4b110f62020-03-13 17:36:19 -0700690func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800691 response := ofp.NewMeterFeaturesStatsReply()
692 response.SetXid(request.GetXid())
693 response.SetVersion(request.GetVersion())
694 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
695 meterFeatures := ofp.NewMeterFeatures()
696 meterFeatures.Capabilities = ofp.OFPMFKbps
697 meterFeatures.BandTypes = ofp.OFPMBTDrop
698 meterFeatures.MaxMeter = 0xffffffff
699 meterFeatures.MaxBands = 0xff
700 meterFeatures.MaxColor = 0xff
701 response.Features = *meterFeatures
702 return response, nil
703}
704
Jonathan Hart4b110f62020-03-13 17:36:19 -0700705func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800706 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
707 response.SetVersion(request.GetVersion())
708 response.SetXid(request.GetXid())
709 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
710 //TODO wire this to voltha core when it implements
711 return response, nil
712}