blob: 78a9b9333f5e8ea103f5c183f5b8ccb366d27d90 [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 {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080032 if logger.V(log.DebugLevel) {
33 js, _ := json.Marshal(request)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000034 logger.Debugw(ctx, "handleStatsRequest called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080035 log.Fields{
36 "device-id": ofc.DeviceID,
37 "stat-type": statType,
38 "request": js})
39 }
40
41 switch statType {
42 case ofp.OFPSTDesc:
43 statsReq := request.(*ofp.DescStatsRequest)
44 response, err := ofc.handleDescStatsRequest(statsReq)
45 if err != nil {
46 return err
47 }
48 if logger.V(log.DebugLevel) {
49 reqJs, _ := json.Marshal(statsReq)
50 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000051 logger.Debugw(ctx, "handle-stats-request-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080052 log.Fields{
53 "device-id": ofc.DeviceID,
54 "request": reqJs,
55 "response": resJs})
56 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +000057 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080058 case ofp.OFPSTFlow:
59 statsReq := request.(*ofp.FlowStatsRequest)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000060 responses, err := ofc.handleFlowStatsRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080061 if err != nil {
62 return err
63 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080064 if logger.V(log.DebugLevel) {
65 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070066 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000067 logger.Debugw(ctx, "handle-stats-request-flow",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080068 log.Fields{
Matteo Scandoloe23b7582020-05-21 13:50:02 -070069 "device-id": ofc.DeviceID,
70 "request": reqJs,
71 "responses-object": responses,
72 "response": resJs})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080073 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -070074 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000075 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -070076 if err != nil {
77 return err
78 }
79 }
80 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080081
82 case ofp.OFPSTAggregate:
83 statsReq := request.(*ofp.AggregateStatsRequest)
84 response, err := ofc.handleAggregateStatsRequest(statsReq)
85 if err != nil {
86 return err
87 }
88 if logger.V(log.DebugLevel) {
89 reqJs, _ := json.Marshal(statsReq)
90 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000091 logger.Debugw(ctx, "handle-stats-request-aggregate",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080092 log.Fields{
93 "device-id": ofc.DeviceID,
94 "request": reqJs,
95 "response": resJs})
96 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +000097 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080098 case ofp.OFPSTTable:
99 statsReq := request.(*ofp.TableStatsRequest)
100 response, e := ofc.handleTableStatsRequest(statsReq)
101 if logger.V(log.DebugLevel) {
102 reqJs, _ := json.Marshal(statsReq)
103 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000104 logger.Debugw(ctx, "handle-stats-request-table",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800105 log.Fields{
106 "device-id": ofc.DeviceID,
107 "request": reqJs,
108 "response": resJs})
109 }
110 if e != nil {
111 return e
112 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000113 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800114 case ofp.OFPSTPort:
115 statsReq := request.(*ofp.PortStatsRequest)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700116 responses, err := ofc.handlePortStatsRequest(statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800117 if err != nil {
118 return err
119 }
120 if logger.V(log.DebugLevel) {
121 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700122 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000123 logger.Debugw(ctx, "handle-stats-request-port",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800124 log.Fields{
125 "device-id": ofc.DeviceID,
126 "request": reqJs,
127 "response": resJs})
128 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700129 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000130 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700131 if err != nil {
132 return err
133 }
134 }
135 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800136 case ofp.OFPSTQueue:
137 statsReq := request.(*ofp.QueueStatsRequest)
138 response, err := ofc.handleQueueStatsRequest(statsReq)
139 if err != nil {
140 return err
141 }
142 if logger.V(log.DebugLevel) {
143 reqJs, _ := json.Marshal(statsReq)
144 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000145 logger.Debugw(ctx, "handle-stats-request-queue",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800146 log.Fields{
147 "device-id": ofc.DeviceID,
148 "request": reqJs,
149 "response": resJs})
150 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000151 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800152 case ofp.OFPSTGroup:
153 statsReq := request.(*ofp.GroupStatsRequest)
154 response, err := ofc.handleGroupStatsRequest(statsReq)
155 if err != nil {
156 return err
157 }
158 if logger.V(log.DebugLevel) {
159 reqJs, _ := json.Marshal(statsReq)
160 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000161 logger.Debugw(ctx, "handle-stats-request-group",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800162 log.Fields{
163 "device-id": ofc.DeviceID,
164 "request": reqJs,
165 "response": resJs})
166 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000167 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800168 case ofp.OFPSTGroupDesc:
169 statsReq := request.(*ofp.GroupDescStatsRequest)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000170 response, err := ofc.handleGroupStatsDescRequest(ctx, statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800171 if err != nil {
172 return err
173 }
174 if logger.V(log.DebugLevel) {
175 reqJs, _ := json.Marshal(statsReq)
176 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000177 logger.Debugw(ctx, "handle-stats-request-group-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800178 log.Fields{
179 "device-id": ofc.DeviceID,
180 "request": reqJs,
181 "response": resJs})
182 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000183 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800184
185 case ofp.OFPSTGroupFeatures:
186 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
187 response, err := ofc.handleGroupFeatureStatsRequest(statsReq)
188 if err != nil {
189 return err
190 }
191 if logger.V(log.DebugLevel) {
192 reqJs, _ := json.Marshal(statsReq)
193 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000194 logger.Debugw(ctx, "handle-stats-request-group-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800195 log.Fields{
196 "device-id": ofc.DeviceID,
197 "request": reqJs,
198 "response": resJs})
199 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000200 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800201 case ofp.OFPSTMeter:
202 statsReq := request.(*ofp.MeterStatsRequest)
203 response, err := ofc.handleMeterStatsRequest(statsReq)
204 if err != nil {
205 return err
206 }
207 if logger.V(log.DebugLevel) {
208 reqJs, _ := json.Marshal(statsReq)
209 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000210 logger.Debugw(ctx, "handle-stats-request-meter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800211 log.Fields{
212 "device-id": ofc.DeviceID,
213 "request": reqJs,
214 "response": resJs})
215 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000216 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800217 case ofp.OFPSTMeterConfig:
218 statsReq := request.(*ofp.MeterConfigStatsRequest)
219 response, err := ofc.handleMeterConfigStatsRequest(statsReq)
220 if err != nil {
221 return err
222 }
223 if logger.V(log.DebugLevel) {
224 reqJs, _ := json.Marshal(statsReq)
225 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000226 logger.Debugw(ctx, "handle-stats-request-meter-config",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800227 log.Fields{
228 "device-id": ofc.DeviceID,
229 "request": reqJs,
230 "response": resJs})
231 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000232 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800233 case ofp.OFPSTMeterFeatures:
234 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
235 response, err := ofc.handleMeterFeatureStatsRequest(statsReq)
236 if err != nil {
237 return err
238 }
239 if logger.V(log.DebugLevel) {
240 reqJs, _ := json.Marshal(statsReq)
241 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000242 logger.Debugw(ctx, "handle-stats-request-meter-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800243 log.Fields{
244 "device-id": ofc.DeviceID,
245 "request": reqJs,
246 "response": resJs})
247 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000248 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800249 case ofp.OFPSTTableFeatures:
250 statsReq := request.(*ofp.TableFeaturesStatsRequest)
251 response, err := ofc.handleTableFeaturesStatsRequest(statsReq)
252 if err != nil {
253 return err
254 }
255 if logger.V(log.DebugLevel) {
256 reqJs, _ := json.Marshal(statsReq)
257 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000258 logger.Debugw(ctx, "handle-stats-request-table-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800259 log.Fields{
260 "device-id": ofc.DeviceID,
261 "request": reqJs,
262 "response": resJs})
263 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000264 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800265 case ofp.OFPSTPortDesc:
266 statsReq := request.(*ofp.PortDescStatsRequest)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700267 responses, err := ofc.handlePortDescStatsRequest(statsReq)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800268 if err != nil {
269 return err
270 }
271 if logger.V(log.DebugLevel) {
272 reqJs, _ := json.Marshal(statsReq)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700273 resJs, _ := json.Marshal(responses)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000274 logger.Debugw(ctx, "handle-stats-request-port-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800275 log.Fields{
276 "device-id": ofc.DeviceID,
277 "request": reqJs,
278 "response": resJs})
279 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700280 for _, response := range responses {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000281 err := ofc.SendMessage(ctx, response)
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700282 if err != nil {
283 return err
284 }
285 }
286 return nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800287
288 case ofp.OFPSTExperimenter:
289 statsReq := request.(*ofp.ExperimenterStatsRequest)
290 response, err := ofc.handleExperimenterStatsRequest(statsReq)
291 if err != nil {
292 return err
293 }
294 if logger.V(log.DebugLevel) {
295 reqJs, _ := json.Marshal(statsReq)
296 resJs, _ := json.Marshal(response)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000297 logger.Debugw(ctx, "handle-stats-request-experimenter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800298 log.Fields{
299 "device-id": ofc.DeviceID,
300 "request": reqJs,
301 "response": resJs})
302 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000303 return ofc.SendMessage(ctx, response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800304 }
305 return nil
306}
307
Jonathan Hart4b110f62020-03-13 17:36:19 -0700308func (ofc *OFConnection) handleDescStatsRequest(request *ofp.DescStatsRequest) (*ofp.DescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700309 volthaClient := ofc.VolthaClient.Get()
310 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800311 return nil, NoVolthaConnectionError
312 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800313 response := ofp.NewDescStatsReply()
314 response.SetXid(request.GetXid())
315 response.SetVersion(request.GetVersion())
316 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
317
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700318 resp, err := volthaClient.GetLogicalDevice(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800319 &common.ID{Id: ofc.DeviceID})
320 if err != nil {
321 return nil, err
322 }
323 desc := resp.GetDesc()
324
325 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
326 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
327 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
328 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
329 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
330 return response, nil
331}
332
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000333func (ofc *OFConnection) handleFlowStatsRequest(ctx context.Context, request *ofp.FlowStatsRequest) ([]*ofp.FlowStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700334 volthaClient := ofc.VolthaClient.Get()
335 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800336 return nil, NoVolthaConnectionError
337 }
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700338 resp, err := volthaClient.ListLogicalDeviceFlows(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800339 &common.ID{Id: ofc.DeviceID})
340 if err != nil {
341 return nil, err
342 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700343 var flows []*ofp.FlowStatsEntry
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800344 for _, item := range resp.GetItems() {
345 entry := ofp.NewFlowStatsEntry()
346 entry.SetTableId(uint8(item.GetTableId()))
347 entry.SetDurationSec(item.GetDurationSec())
348 entry.SetDurationNsec(item.GetDurationNsec())
349 entry.SetPriority(uint16(item.GetPriority()))
350 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
351 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
352 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
353 entry.SetCookie(item.GetCookie())
354 entry.SetPacketCount(item.GetPacketCount())
355 entry.SetByteCount(item.GetByteCount())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800356 match := ofp.NewMatchV3()
357 pbMatch := item.GetMatch()
358 match.SetType(uint16(pbMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800359 var fields []goloxi.IOxm
360 for _, oxmField := range pbMatch.GetOxmFields() {
361 field := oxmField.GetField()
362 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000363 iOxm := parseOxm(ctx, ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800364 fields = append(fields, iOxm)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800365 }
366
367 match.OxmList = fields
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800368 entry.SetMatch(*match)
369 var instructions []ofp.IInstruction
370 for _, ofpInstruction := range item.Instructions {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000371 instruction := parseInstructions(ctx, ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800372 instructions = append(instructions, instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800373 }
374 entry.Instructions = instructions
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700375 flows = append(flows, entry)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800376 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700377 var responses []*ofp.FlowStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700378 chunkSize := ofc.flowsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700379 total := len(flows) / chunkSize
380 n := 0
381 for n <= total {
382
383 chunk := flows[n*chunkSize : min((n*chunkSize)+chunkSize, len(flows))]
384
385 if len(chunk) == 0 {
386 break
387 }
388
389 response := ofp.NewFlowStatsReply()
390 response.SetXid(request.GetXid())
391 response.SetVersion(4)
392 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
393 if total != n {
394 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
395 }
396 response.SetEntries(chunk)
397 responses = append(responses, response)
398 n++
399 }
400 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800401}
402
Jonathan Hart4b110f62020-03-13 17:36:19 -0700403func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800404 response := ofp.NewAggregateStatsReply()
405 response.SetVersion(request.GetVersion())
406 response.SetXid(request.GetXid())
407 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
408 response.SetFlowCount(0)
409 //TODO wire this to voltha core when it implements
410 return response, nil
411}
412
Jonathan Hart4b110f62020-03-13 17:36:19 -0700413func (ofc *OFConnection) handleGroupStatsRequest(request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700414 volthaClient := ofc.VolthaClient.Get()
415 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800416 return nil, NoVolthaConnectionError
417 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800418 response := ofp.NewGroupStatsReply()
419 response.SetVersion(request.GetVersion())
420 response.SetXid(request.GetXid())
421 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700422 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800423 &common.ID{Id: ofc.DeviceID})
424 if err != nil {
425 return nil, err
426 }
427
428 var groupStatsEntries []*ofp.GroupStatsEntry
429 for _, item := range reply.GetItems() {
430 stats := item.GetStats()
431 var entry ofp.GroupStatsEntry
432 entry.SetByteCount(stats.GetByteCount())
433 entry.SetPacketCount(stats.GetPacketCount())
434 entry.SetDurationNsec(stats.GetDurationNsec())
435 entry.SetDurationSec(stats.GetDurationSec())
436 entry.SetRefCount(stats.GetRefCount())
437 entry.SetGroupId(stats.GetGroupId())
438 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700439 // TODO fix this when API handler is fixed in the core
440 // Core doesn't return any buckets in the Stats object, so just
441 // fill out an empty BucketCounter for each bucket in the group Desc for now.
442 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800443 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700444 bucketCounter.SetPacketCount(0)
445 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800446 bucketStatsList = append(bucketStatsList, &bucketCounter)
447 }
448 entry.SetBucketStats(bucketStatsList)
449 groupStatsEntries = append(groupStatsEntries, &entry)
450 }
451 response.SetEntries(groupStatsEntries)
452 return response, nil
453}
454
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000455func (ofc *OFConnection) handleGroupStatsDescRequest(ctx context.Context, request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700456 volthaClient := ofc.VolthaClient.Get()
457 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800458 return nil, NoVolthaConnectionError
459 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800460 response := ofp.NewGroupDescStatsReply()
461 response.SetVersion(request.GetVersion())
462 response.SetXid(request.GetXid())
463 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700464 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800465 &common.ID{Id: ofc.DeviceID})
466 if err != nil {
467 return nil, err
468 }
469 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
470 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700471 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800472
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000473 buckets := volthaBucketsToOpenflow(ctx, desc.Buckets)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800474
Jonathan Hart60c5d772020-03-30 18:28:40 -0700475 groupDesc := &ofp.GroupDescStatsEntry{
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000476 GroupType: volthaGroupTypeToOpenflow(ctx, desc.Type),
Jonathan Hart60c5d772020-03-30 18:28:40 -0700477 GroupId: desc.GroupId,
478 Buckets: buckets,
479 }
480 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800481 }
482 response.SetEntries(groupDescStatsEntries)
483 return response, nil
484}
485
Jonathan Hart4b110f62020-03-13 17:36:19 -0700486func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800487 response := ofp.NewGroupFeaturesStatsReply()
488 response.SetVersion(request.GetVersion())
489 response.SetXid(request.GetXid())
490 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
491 //TODO wire this to voltha core when it implements
492 return response, nil
493}
494
Jonathan Hart4b110f62020-03-13 17:36:19 -0700495func (ofc *OFConnection) handleMeterStatsRequest(request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700496 volthaClient := ofc.VolthaClient.Get()
497 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800498 return nil, NoVolthaConnectionError
499 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800500 response := ofp.NewMeterStatsReply()
501 response.SetVersion(request.GetVersion())
502 response.SetXid(request.GetXid())
503 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700504 resp, err := volthaClient.ListLogicalDeviceMeters(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800505 &common.ID{Id: ofc.DeviceID})
506 if err != nil {
507 return nil, err
508 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800509 var meterStats []*ofp.MeterStats
510 for _, item := range resp.Items {
511 meterStat := ofp.NewMeterStats()
512 stats := item.Stats
513 meterStat.DurationNsec = stats.DurationNsec
514 meterStat.DurationSec = stats.DurationSec
515 meterStat.ByteInCount = stats.ByteInCount
516 meterStat.FlowCount = stats.FlowCount
517 meterStat.MeterId = stats.MeterId
518 var bandStats []*ofp.MeterBandStats
519 for _, bStat := range stats.BandStats {
520 bandStat := ofp.NewMeterBandStats()
521 bandStat.ByteBandCount = bStat.ByteBandCount
522 bandStat.PacketBandCount = bStat.PacketBandCount
523 bandStats = append(bandStats, bandStat)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800524 }
525 meterStat.SetBandStats(bandStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800526 meterStats = append(meterStats, meterStat)
527 }
528 response.SetEntries(meterStats)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800529 return response, nil
530}
531
Jonathan Hart4b110f62020-03-13 17:36:19 -0700532func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800533 response := ofp.NewMeterConfigStatsReply()
534 response.SetVersion(request.GetVersion())
535 response.SetXid(request.GetXid())
536 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
537 //TODO wire this to voltha core when it implements
538 return response, nil
539}
540
Jonathan Hart4b110f62020-03-13 17:36:19 -0700541func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800542 response := ofp.NewTableFeaturesStatsReply()
543 response.SetVersion(request.GetVersion())
544 response.SetXid(request.GetXid())
545 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
546 //TODO wire this to voltha core when it implements
547 return response, nil
548}
549
Jonathan Hart4b110f62020-03-13 17:36:19 -0700550func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800551 var response = ofp.NewTableStatsReply()
552 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
553 response.SetVersion(request.GetVersion())
554 response.SetXid(request.GetXid())
555 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
556 return response, nil
557}
558
Jonathan Hart4b110f62020-03-13 17:36:19 -0700559func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800560 response := ofp.NewQueueStatsReply()
561 response.SetVersion(request.GetVersion())
562 response.SetXid(request.GetXid())
563 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
564 //TODO wire this to voltha core when it implements
565 return response, nil
566}
567
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700568func (ofc *OFConnection) handlePortStatsRequest(request *ofp.PortStatsRequest) ([]*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700569 volthaClient := ofc.VolthaClient.Get()
570 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800571 return nil, NoVolthaConnectionError
572 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700573
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700574 reply, err := volthaClient.ListLogicalDevicePorts(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800575 &common.ID{Id: ofc.DeviceID})
576 if err != nil {
577 return nil, err
578 }
579 var entries []*ofp.PortStatsEntry
580 if request.GetPortNo() == 0xffffffff { //all ports
581 for _, port := range reply.GetItems() {
582 entries = append(entries, parsePortStats(port))
583 }
584 } else { //find right port that is requested
585 for _, port := range reply.GetItems() {
586 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
587 entries = append(entries, parsePortStats(port))
588 }
589 }
590 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700591
592 var responses []*ofp.PortStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700593 chunkSize := ofc.portsChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700594 total := len(entries) / chunkSize
595 n := 0
596 for n <= total {
597
598 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
599
600 if len(chunk) == 0 {
601 break
602 }
603
604 response := ofp.NewPortStatsReply()
605 response.SetXid(request.GetXid())
606 response.SetVersion(request.GetVersion())
607 if total != n {
608 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
609 }
610 response.SetEntries(entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))])
611 responses = append(responses, response)
612 n++
613 }
614 return responses, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800615}
616
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700617func (ofc *OFConnection) handlePortDescStatsRequest(request *ofp.PortDescStatsRequest) ([]*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700618 volthaClient := ofc.VolthaClient.Get()
619 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800620 return nil, NoVolthaConnectionError
621 }
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700622
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400623 ports, err := volthaClient.ListLogicalDevicePorts(context.Background(), &common.ID{Id: ofc.DeviceID})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800624 if err != nil {
625 return nil, err
626 }
627 var entries []*ofp.PortDesc
Kent Hagerman9b0ac0a2020-06-08 11:48:16 -0400628 for _, port := range ports.Items {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800629 ofpPort := port.GetOfpPort()
630 var entry ofp.PortDesc
631 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
632
633 var octets []byte
634 for _, val := range ofpPort.GetHwAddr() {
635 octets = append(octets, byte(val))
636 }
637 hwAddr := net.HardwareAddr(octets)
638 entry.SetHwAddr(hwAddr)
639 entry.SetName(PadString(ofpPort.GetName(), 16))
640 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
641 entry.SetState(ofp.PortState(ofpPort.GetState()))
642 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
643 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
644 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
645 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
646 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
647 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
648
649 entries = append(entries, &entry)
650 }
651
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700652 var responses []*ofp.PortDescStatsReply
Matteo Scandolo256266d2020-06-01 13:44:07 -0700653 chunkSize := ofc.portsDescChunkSize
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700654 total := len(entries) / chunkSize
655 n := 0
656 for n <= total {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800657
Matteo Scandoloe23b7582020-05-21 13:50:02 -0700658 chunk := entries[n*chunkSize : min((n*chunkSize)+chunkSize, len(entries))]
659
660 if len(chunk) == 0 {
661 break
662 }
663
664 response := ofp.NewPortDescStatsReply()
665 response.SetVersion(request.GetVersion())
666 response.SetXid(request.GetXid())
667 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
668 if total != n {
669 response.SetFlags(ofp.StatsReplyFlags(ofp.OFPSFReplyMore))
670 }
671 response.SetEntries(chunk)
672 responses = append(responses, response)
673 n++
674 }
675 return responses, nil
676
677}
678
679// Interestingly enough there is no min function fot two integers
680func min(a, b int) int {
681 if a < b {
682 return a
683 }
684 return b
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800685}
686
Jonathan Hart4b110f62020-03-13 17:36:19 -0700687func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800688 response := ofp.NewMeterFeaturesStatsReply()
689 response.SetXid(request.GetXid())
690 response.SetVersion(request.GetVersion())
691 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
692 meterFeatures := ofp.NewMeterFeatures()
693 meterFeatures.Capabilities = ofp.OFPMFKbps
694 meterFeatures.BandTypes = ofp.OFPMBTDrop
695 meterFeatures.MaxMeter = 0xffffffff
696 meterFeatures.MaxBands = 0xff
697 meterFeatures.MaxColor = 0xff
698 response.Features = *meterFeatures
699 return response, nil
700}
701
Jonathan Hart4b110f62020-03-13 17:36:19 -0700702func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800703 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
704 response.SetVersion(request.GetVersion())
705 response.SetXid(request.GetXid())
706 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
707 //TODO wire this to voltha core when it implements
708 return response, nil
709}