blob: ccf7d7d5943f5f86d8a226febec66f920ad51ae4 [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 }
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
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200386 limit := (n * chunkSize) + chunkSize
387
388 chunk := flows[n*chunkSize : min(limit, len(flows))]
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700389
390 if len(chunk) == 0 {
391 break
392 }
393
394 response := ofp.NewFlowStatsReply()
395 response.SetXid(request.GetXid())
396 response.SetVersion(4)
397 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Andrea Campanellaf2cf13e2020-09-03 16:22:27 +0200398 if limit < len(flows) {
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700399 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
400 }
401 response.SetEntries(chunk)
402 responses = append(responses, response)
403 n++
404 }
405 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800406}
407
Jonathan Hart4b110f62020-03-13 17:36:19 -0700408func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800409 response := ofp.NewAggregateStatsReply()
410 response.SetVersion(request.GetVersion())
411 response.SetXid(request.GetXid())
412 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
413 response.SetFlowCount(0)
414 //TODO wire this to voltha core when it implements
415 return response, nil
416}
417
Girish Kumar01e0c632020-08-10 16:48:56 +0000418func (ofc *OFConnection) handleGroupStatsRequest(ctx context.Context, request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700419 volthaClient := ofc.VolthaClient.Get()
420 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800421 return nil, NoVolthaConnectionError
422 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800423 response := ofp.NewGroupStatsReply()
424 response.SetVersion(request.GetVersion())
425 response.SetXid(request.GetXid())
426 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000427 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800428 &common.ID{Id: ofc.DeviceID})
429 if err != nil {
430 return nil, err
431 }
432
433 var groupStatsEntries []*ofp.GroupStatsEntry
434 for _, item := range reply.GetItems() {
435 stats := item.GetStats()
436 var entry ofp.GroupStatsEntry
437 entry.SetByteCount(stats.GetByteCount())
438 entry.SetPacketCount(stats.GetPacketCount())
439 entry.SetDurationNsec(stats.GetDurationNsec())
440 entry.SetDurationSec(stats.GetDurationSec())
441 entry.SetRefCount(stats.GetRefCount())
442 entry.SetGroupId(stats.GetGroupId())
443 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700444 // TODO fix this when API handler is fixed in the core
445 // Core doesn't return any buckets in the Stats object, so just
446 // fill out an empty BucketCounter for each bucket in the group Desc for now.
447 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800448 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700449 bucketCounter.SetPacketCount(0)
450 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800451 bucketStatsList = append(bucketStatsList, &bucketCounter)
452 }
453 entry.SetBucketStats(bucketStatsList)
454 groupStatsEntries = append(groupStatsEntries, &entry)
455 }
456 response.SetEntries(groupStatsEntries)
457 return response, nil
458}
459
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000460func (ofc *OFConnection) handleGroupStatsDescRequest(ctx context.Context, request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700461 volthaClient := ofc.VolthaClient.Get()
462 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800463 return nil, NoVolthaConnectionError
464 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800465 response := ofp.NewGroupDescStatsReply()
466 response.SetVersion(request.GetVersion())
467 response.SetXid(request.GetXid())
468 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000469 reply, err := volthaClient.ListLogicalDeviceFlowGroups(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800470 &common.ID{Id: ofc.DeviceID})
471 if err != nil {
472 return nil, err
473 }
474 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
475 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700476 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800477
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000478 buckets := volthaBucketsToOpenflow(ctx, desc.Buckets)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800479
Jonathan Hart60c5d772020-03-30 18:28:40 -0700480 groupDesc := &ofp.GroupDescStatsEntry{
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000481 GroupType: volthaGroupTypeToOpenflow(ctx, desc.Type),
Jonathan Hart60c5d772020-03-30 18:28:40 -0700482 GroupId: desc.GroupId,
483 Buckets: buckets,
484 }
485 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800486 }
487 response.SetEntries(groupDescStatsEntries)
488 return response, nil
489}
490
Jonathan Hart4b110f62020-03-13 17:36:19 -0700491func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800492 response := ofp.NewGroupFeaturesStatsReply()
493 response.SetVersion(request.GetVersion())
494 response.SetXid(request.GetXid())
495 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
496 //TODO wire this to voltha core when it implements
497 return response, nil
498}
499
Girish Kumar01e0c632020-08-10 16:48:56 +0000500func (ofc *OFConnection) handleMeterStatsRequest(ctx context.Context, request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700501 volthaClient := ofc.VolthaClient.Get()
502 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800503 return nil, NoVolthaConnectionError
504 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800505 response := ofp.NewMeterStatsReply()
506 response.SetVersion(request.GetVersion())
507 response.SetXid(request.GetXid())
508 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
Girish Kumar01e0c632020-08-10 16:48:56 +0000509 resp, err := volthaClient.ListLogicalDeviceMeters(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800510 &common.ID{Id: ofc.DeviceID})
511 if err != nil {
512 return nil, err
513 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800514 var meterStats []*ofp.MeterStats
515 for _, item := range resp.Items {
516 meterStat := ofp.NewMeterStats()
517 stats := item.Stats
518 meterStat.DurationNsec = stats.DurationNsec
519 meterStat.DurationSec = stats.DurationSec
520 meterStat.ByteInCount = stats.ByteInCount
521 meterStat.FlowCount = stats.FlowCount
522 meterStat.MeterId = stats.MeterId
523 var bandStats []*ofp.MeterBandStats
524 for _, bStat := range stats.BandStats {
525 bandStat := ofp.NewMeterBandStats()
526 bandStat.ByteBandCount = bStat.ByteBandCount
527 bandStat.PacketBandCount = bStat.PacketBandCount
528 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800529 }
530 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800531 meterStats = append(meterStats, meterStat)
532 }
533 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800534 return response, nil
535}
536
Jonathan Hart4b110f62020-03-13 17:36:19 -0700537func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800538 response := ofp.NewMeterConfigStatsReply()
539 response.SetVersion(request.GetVersion())
540 response.SetXid(request.GetXid())
541 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
542 //TODO wire this to voltha core when it implements
543 return response, nil
544}
545
Jonathan Hart4b110f62020-03-13 17:36:19 -0700546func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800547 response := ofp.NewTableFeaturesStatsReply()
548 response.SetVersion(request.GetVersion())
549 response.SetXid(request.GetXid())
550 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
551 //TODO wire this to voltha core when it implements
552 return response, nil
553}
554
Jonathan Hart4b110f62020-03-13 17:36:19 -0700555func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800556 var response = ofp.NewTableStatsReply()
557 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
558 response.SetVersion(request.GetVersion())
559 response.SetXid(request.GetXid())
560 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
561 return response, nil
562}
563
Jonathan Hart4b110f62020-03-13 17:36:19 -0700564func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800565 response := ofp.NewQueueStatsReply()
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
Girish Kumar01e0c632020-08-10 16:48:56 +0000573func (ofc *OFConnection) handlePortStatsRequest(ctx context.Context, request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700574 volthaClient := ofc.VolthaClient.Get()
575 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800576 return nil, NoVolthaConnectionError
577 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700578
Girish Kumar01e0c632020-08-10 16:48:56 +0000579 reply, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800580 &common.ID{Id: ofc.DeviceID})
581 if err != nil {
582 return nil, err
583 }
584 var entries []*ofp.PortStatsEntry
585 if request.GetPortNo() == 0xffffffff { //all ports
586 for _, port := range reply.GetItems() {
587 entries = append(entries, parsePortStats(port))
588 }
589 } else { //find right port that is requested
590 for _, port := range reply.GetItems() {
591 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
592 entries = append(entries, parsePortStats(port))
593 }
594 }
595 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700596
597 var responses []*ofp.PortStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700598 chunkSize := ofc.portsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700599 total := len(entries) / chunkSize
600 n := 0
601 for n <= total {
602
603 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
604
605 if len(chunk) == 0 {
606 break
607 }
608
609 response := ofp.NewPortStatsReply()
610 response.SetXid(request.GetXid())
611 response.SetVersion(request.GetVersion())
612 if total != n {
613 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
614 }
615 response.SetEntries(entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))])
616 responses = append(responses, response)
617 n++
618 }
619 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800620}
621
Girish Kumar01e0c632020-08-10 16:48:56 +0000622func (ofc *OFConnection) handlePortDescStatsRequest(ctx context.Context, request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700623 volthaClient := ofc.VolthaClient.Get()
624 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800625 return nil, NoVolthaConnectionError
626 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700627
Girish Kumar01e0c632020-08-10 16:48:56 +0000628 ports, err := volthaClient.ListLogicalDevicePorts(log.WithSpanFromContext(context.Background(), ctx), &common.ID{Id: ofc.DeviceID})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800629 if err != nil {
630 return nil, err
631 }
632 var entries []*ofp.PortDesc
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400633 for _, port := range ports.Items {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800634 ofpPort := port.GetOfpPort()
635 var entry ofp.PortDesc
636 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
637
638 var octets []byte
639 for _, val := range ofpPort.GetHwAddr() {
640 octets = append(octets, byte(val))
641 }
642 hwAddr := net.HardwareAddr(octets)
643 entry.SetHwAddr(hwAddr)
644 entry.SetName(PadString(ofpPort.GetName(), 16))
645 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
646 entry.SetState(ofp.PortState(ofpPort.GetState()))
647 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
648 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
649 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
650 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
651 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
652 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
653
654 entries = append(entries, &entry)
655 }
656
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700657 var responses []*ofp.PortDescStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700658 chunkSize := ofc.portsDescChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700659 total := len(entries) / chunkSize
660 n := 0
661 for n <= total {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800662
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700663 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
664
665 if len(chunk) == 0 {
666 break
667 }
668
669 response := ofp.NewPortDescStatsReply()
670 response.SetVersion(request.GetVersion())
671 response.SetXid(request.GetXid())
672 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
673 if total != n {
674 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
675 }
676 response.SetEntries(chunk)
677 responses = append(responses, response)
678 n++
679 }
680 return responses, nil
681
682}
683
684// Interestingly enough there is no min function fot two integers
685func min(a, b int) int {
686 if a < b {
687 return a
688 }
689 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800690}
691
Jonathan Hart4b110f62020-03-13 17:36:19 -0700692func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800693 response := ofp.NewMeterFeaturesStatsReply()
694 response.SetXid(request.GetXid())
695 response.SetVersion(request.GetVersion())
696 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
697 meterFeatures := ofp.NewMeterFeatures()
698 meterFeatures.Capabilities = ofp.OFPMFKbps
699 meterFeatures.BandTypes = ofp.OFPMBTDrop
700 meterFeatures.MaxMeter = 0xffffffff
701 meterFeatures.MaxBands = 0xff
702 meterFeatures.MaxColor = 0xff
703 response.Features = *meterFeatures
704 return response, nil
705}
706
Jonathan Hart4b110f62020-03-13 17:36:19 -0700707func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800708 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
709 response.SetVersion(request.GetVersion())
710 response.SetXid(request.GetXid())
711 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
712 //TODO wire this to voltha core when it implements
713 return response, nil
714}