blob: 9b642ce02999033bf31cc815fc7d66e2088b0bd9 [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"
David Bainbridgef8ce7d22020-04-08 12:49:41 -070022 "net"
23 "unsafe"
24
David K. Bainbridge157bdab2020-01-16 14:38:05 -080025 "github.com/donNewtonAlpha/goloxi"
26 ofp "github.com/donNewtonAlpha/goloxi/of13"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080027 "github.com/opencord/voltha-lib-go/v3/pkg/log"
28 "github.com/opencord/voltha-protos/v3/go/common"
29 "github.com/opencord/voltha-protos/v3/go/openflow_13"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080030)
31
Jonathan Hart4b110f62020-03-13 17:36:19 -070032func (ofc *OFConnection) handleStatsRequest(request ofp.IHeader, statType uint16) error {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080033 if logger.V(log.DebugLevel) {
34 js, _ := json.Marshal(request)
35 logger.Debugw("handleStatsRequest called",
36 log.Fields{
37 "device-id": ofc.DeviceID,
38 "stat-type": statType,
39 "request": js})
40 }
41
42 switch statType {
43 case ofp.OFPSTDesc:
44 statsReq := request.(*ofp.DescStatsRequest)
45 response, err := ofc.handleDescStatsRequest(statsReq)
46 if err != nil {
47 return err
48 }
49 if logger.V(log.DebugLevel) {
50 reqJs, _ := json.Marshal(statsReq)
51 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -080052 logger.Debugw("handle-stats-request-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080053 log.Fields{
54 "device-id": ofc.DeviceID,
55 "request": reqJs,
56 "response": resJs})
57 }
58 return ofc.SendMessage(response)
59 case ofp.OFPSTFlow:
60 statsReq := request.(*ofp.FlowStatsRequest)
61 response, err := ofc.handleFlowStatsRequest(statsReq)
62 if err != nil {
63 return err
64 }
65 response.Length = uint16(unsafe.Sizeof(*response))
66 if logger.V(log.DebugLevel) {
67 reqJs, _ := json.Marshal(statsReq)
68 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -080069 logger.Debugw("handle-stats-request-flow",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080070 log.Fields{
Don Newton7fe70f72020-02-21 13:54:11 -050071 "device-id": ofc.DeviceID,
72 "request": reqJs,
73 "response-object": response,
74 "response": resJs})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080075 }
76 return ofc.SendMessage(response)
77
78 case ofp.OFPSTAggregate:
79 statsReq := request.(*ofp.AggregateStatsRequest)
80 response, err := ofc.handleAggregateStatsRequest(statsReq)
81 if err != nil {
82 return err
83 }
84 if logger.V(log.DebugLevel) {
85 reqJs, _ := json.Marshal(statsReq)
86 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -080087 logger.Debugw("handle-stats-request-aggregate",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080088 log.Fields{
89 "device-id": ofc.DeviceID,
90 "request": reqJs,
91 "response": resJs})
92 }
93 return ofc.SendMessage(response)
94 case ofp.OFPSTTable:
95 statsReq := request.(*ofp.TableStatsRequest)
96 response, e := ofc.handleTableStatsRequest(statsReq)
97 if logger.V(log.DebugLevel) {
98 reqJs, _ := json.Marshal(statsReq)
99 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800100 logger.Debugw("handle-stats-request-table",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800101 log.Fields{
102 "device-id": ofc.DeviceID,
103 "request": reqJs,
104 "response": resJs})
105 }
106 if e != nil {
107 return e
108 }
109 return ofc.SendMessage(response)
110 case ofp.OFPSTPort:
111 statsReq := request.(*ofp.PortStatsRequest)
112 response, err := ofc.handlePortStatsRequest(statsReq)
113 if err != nil {
114 return err
115 }
116 if logger.V(log.DebugLevel) {
117 reqJs, _ := json.Marshal(statsReq)
118 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800119 logger.Debugw("handle-stats-request-port",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 log.Fields{
121 "device-id": ofc.DeviceID,
122 "request": reqJs,
123 "response": resJs})
124 }
125 return ofc.SendMessage(response)
126 case ofp.OFPSTQueue:
127 statsReq := request.(*ofp.QueueStatsRequest)
128 response, err := ofc.handleQueueStatsRequest(statsReq)
129 if err != nil {
130 return err
131 }
132 if logger.V(log.DebugLevel) {
133 reqJs, _ := json.Marshal(statsReq)
134 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800135 logger.Debugw("handle-stats-request-queue",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800136 log.Fields{
137 "device-id": ofc.DeviceID,
138 "request": reqJs,
139 "response": resJs})
140 }
141 return ofc.SendMessage(response)
142 case ofp.OFPSTGroup:
143 statsReq := request.(*ofp.GroupStatsRequest)
144 response, err := ofc.handleGroupStatsRequest(statsReq)
145 if err != nil {
146 return err
147 }
148 if logger.V(log.DebugLevel) {
149 reqJs, _ := json.Marshal(statsReq)
150 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800151 logger.Debugw("handle-stats-request-group",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800152 log.Fields{
153 "device-id": ofc.DeviceID,
154 "request": reqJs,
155 "response": resJs})
156 }
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800157 return ofc.SendMessage(response)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800158 case ofp.OFPSTGroupDesc:
159 statsReq := request.(*ofp.GroupDescStatsRequest)
160 response, err := ofc.handleGroupStatsDescRequest(statsReq)
161 if err != nil {
162 return err
163 }
164 if logger.V(log.DebugLevel) {
165 reqJs, _ := json.Marshal(statsReq)
166 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800167 logger.Debugw("handle-stats-request-group-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800168 log.Fields{
169 "device-id": ofc.DeviceID,
170 "request": reqJs,
171 "response": resJs})
172 }
173 return ofc.SendMessage(response)
174
175 case ofp.OFPSTGroupFeatures:
176 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
177 response, err := ofc.handleGroupFeatureStatsRequest(statsReq)
178 if err != nil {
179 return err
180 }
181 if logger.V(log.DebugLevel) {
182 reqJs, _ := json.Marshal(statsReq)
183 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800184 logger.Debugw("handle-stats-request-group-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800185 log.Fields{
186 "device-id": ofc.DeviceID,
187 "request": reqJs,
188 "response": resJs})
189 }
190 return ofc.SendMessage(response)
191 case ofp.OFPSTMeter:
192 statsReq := request.(*ofp.MeterStatsRequest)
193 response, err := ofc.handleMeterStatsRequest(statsReq)
194 if err != nil {
195 return err
196 }
197 if logger.V(log.DebugLevel) {
198 reqJs, _ := json.Marshal(statsReq)
199 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800200 logger.Debugw("handle-stats-request-meter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800201 log.Fields{
202 "device-id": ofc.DeviceID,
203 "request": reqJs,
204 "response": resJs})
205 }
206 return ofc.SendMessage(response)
207 case ofp.OFPSTMeterConfig:
208 statsReq := request.(*ofp.MeterConfigStatsRequest)
209 response, err := ofc.handleMeterConfigStatsRequest(statsReq)
210 if err != nil {
211 return err
212 }
213 if logger.V(log.DebugLevel) {
214 reqJs, _ := json.Marshal(statsReq)
215 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800216 logger.Debugw("handle-stats-request-meter-config",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800217 log.Fields{
218 "device-id": ofc.DeviceID,
219 "request": reqJs,
220 "response": resJs})
221 }
222 return ofc.SendMessage(response)
223 case ofp.OFPSTMeterFeatures:
224 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
225 response, err := ofc.handleMeterFeatureStatsRequest(statsReq)
226 if err != nil {
227 return err
228 }
229 if logger.V(log.DebugLevel) {
230 reqJs, _ := json.Marshal(statsReq)
231 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800232 logger.Debugw("handle-stats-request-meter-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800233 log.Fields{
234 "device-id": ofc.DeviceID,
235 "request": reqJs,
236 "response": resJs})
237 }
238 return ofc.SendMessage(response)
239 case ofp.OFPSTTableFeatures:
240 statsReq := request.(*ofp.TableFeaturesStatsRequest)
241 response, err := ofc.handleTableFeaturesStatsRequest(statsReq)
242 if err != nil {
243 return err
244 }
245 if logger.V(log.DebugLevel) {
246 reqJs, _ := json.Marshal(statsReq)
247 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800248 logger.Debugw("handle-stats-request-table-features",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800249 log.Fields{
250 "device-id": ofc.DeviceID,
251 "request": reqJs,
252 "response": resJs})
253 }
254 return ofc.SendMessage(response)
255 case ofp.OFPSTPortDesc:
256 statsReq := request.(*ofp.PortDescStatsRequest)
257 response, err := ofc.handlePortDescStatsRequest(statsReq)
258 if err != nil {
259 return err
260 }
261 if logger.V(log.DebugLevel) {
262 reqJs, _ := json.Marshal(statsReq)
263 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800264 logger.Debugw("handle-stats-request-port-desc",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800265 log.Fields{
266 "device-id": ofc.DeviceID,
267 "request": reqJs,
268 "response": resJs})
269 }
270 return ofc.SendMessage(response)
271
272 case ofp.OFPSTExperimenter:
273 statsReq := request.(*ofp.ExperimenterStatsRequest)
274 response, err := ofc.handleExperimenterStatsRequest(statsReq)
275 if err != nil {
276 return err
277 }
278 if logger.V(log.DebugLevel) {
279 reqJs, _ := json.Marshal(statsReq)
280 resJs, _ := json.Marshal(response)
David K. Bainbridge55376262020-01-22 23:28:27 -0800281 logger.Debugw("handle-stats-request-experimenter",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800282 log.Fields{
283 "device-id": ofc.DeviceID,
284 "request": reqJs,
285 "response": resJs})
286 }
287 return ofc.SendMessage(response)
288 }
289 return nil
290}
291
Jonathan Hart4b110f62020-03-13 17:36:19 -0700292func (ofc *OFConnection) handleDescStatsRequest(request *ofp.DescStatsRequest) (*ofp.DescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700293 volthaClient := ofc.VolthaClient.Get()
294 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800295 return nil, NoVolthaConnectionError
296 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800297 response := ofp.NewDescStatsReply()
298 response.SetXid(request.GetXid())
299 response.SetVersion(request.GetVersion())
300 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
301
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700302 resp, err := volthaClient.GetLogicalDevice(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800303 &common.ID{Id: ofc.DeviceID})
304 if err != nil {
305 return nil, err
306 }
307 desc := resp.GetDesc()
308
309 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
310 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
311 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
312 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
313 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
314 return response, nil
315}
316
Jonathan Hart4b110f62020-03-13 17:36:19 -0700317func (ofc *OFConnection) handleFlowStatsRequest(request *ofp.FlowStatsRequest) (*ofp.FlowStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700318 volthaClient := ofc.VolthaClient.Get()
319 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800320 return nil, NoVolthaConnectionError
321 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800322 response := ofp.NewFlowStatsReply()
323 response.SetXid(request.GetXid())
324 response.SetVersion(4)
325 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700326 resp, err := volthaClient.ListLogicalDeviceFlows(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800327 &common.ID{Id: ofc.DeviceID})
328 if err != nil {
329 return nil, err
330 }
331 var flow []*ofp.FlowStatsEntry
332 for _, item := range resp.GetItems() {
333 entry := ofp.NewFlowStatsEntry()
334 entry.SetTableId(uint8(item.GetTableId()))
335 entry.SetDurationSec(item.GetDurationSec())
336 entry.SetDurationNsec(item.GetDurationNsec())
337 entry.SetPriority(uint16(item.GetPriority()))
338 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
339 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
340 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
341 entry.SetCookie(item.GetCookie())
342 entry.SetPacketCount(item.GetPacketCount())
343 entry.SetByteCount(item.GetByteCount())
344 entrySize := uint16(48)
345 match := ofp.NewMatchV3()
346 pbMatch := item.GetMatch()
347 match.SetType(uint16(pbMatch.GetType()))
348 size := uint16(4)
349 var fields []goloxi.IOxm
350 for _, oxmField := range pbMatch.GetOxmFields() {
351 field := oxmField.GetField()
352 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
Jonathan Hart60c5d772020-03-30 18:28:40 -0700353 iOxm, oxmSize := parseOxm(ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800354 fields = append(fields, iOxm)
355 if oxmSize > 0 {
356 size += 4 //header for oxm
357 }
358 size += oxmSize
359 }
360
361 match.OxmList = fields
362 match.Length = uint16(size)
363 //account for 8 byte alignment
364 if size%8 != 0 {
365 size = ((size / 8) + 1) * 8
366 }
367 entrySize += size
368 entry.SetMatch(*match)
369 var instructions []ofp.IInstruction
370 for _, ofpInstruction := range item.Instructions {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700371 instruction, size := parseInstructions(ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800372 instructions = append(instructions, instruction)
373 entrySize += size
374 }
375 entry.Instructions = instructions
376 entry.Length = entrySize
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800377 flow = append(flow, entry)
378 }
379 response.SetEntries(flow)
380 return response, nil
381}
382
Jonathan Hart4b110f62020-03-13 17:36:19 -0700383func (ofc *OFConnection) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800384 response := ofp.NewAggregateStatsReply()
385 response.SetVersion(request.GetVersion())
386 response.SetXid(request.GetXid())
387 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
388 response.SetFlowCount(0)
389 //TODO wire this to voltha core when it implements
390 return response, nil
391}
392
Jonathan Hart4b110f62020-03-13 17:36:19 -0700393func (ofc *OFConnection) handleGroupStatsRequest(request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700394 volthaClient := ofc.VolthaClient.Get()
395 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800396 return nil, NoVolthaConnectionError
397 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800398 response := ofp.NewGroupStatsReply()
399 response.SetVersion(request.GetVersion())
400 response.SetXid(request.GetXid())
401 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700402 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800403 &common.ID{Id: ofc.DeviceID})
404 if err != nil {
405 return nil, err
406 }
407
408 var groupStatsEntries []*ofp.GroupStatsEntry
409 for _, item := range reply.GetItems() {
410 stats := item.GetStats()
411 var entry ofp.GroupStatsEntry
412 entry.SetByteCount(stats.GetByteCount())
413 entry.SetPacketCount(stats.GetPacketCount())
414 entry.SetDurationNsec(stats.GetDurationNsec())
415 entry.SetDurationSec(stats.GetDurationSec())
416 entry.SetRefCount(stats.GetRefCount())
417 entry.SetGroupId(stats.GetGroupId())
418 var bucketStatsList []*ofp.BucketCounter
Jonathan Hart60c5d772020-03-30 18:28:40 -0700419 // TODO fix this when API handler is fixed in the core
420 // Core doesn't return any buckets in the Stats object, so just
421 // fill out an empty BucketCounter for each bucket in the group Desc for now.
422 for range item.GetDesc().GetBuckets() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800423 bucketCounter := ofp.BucketCounter{}
Jonathan Hart60c5d772020-03-30 18:28:40 -0700424 bucketCounter.SetPacketCount(0)
425 bucketCounter.SetByteCount(0)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800426 bucketStatsList = append(bucketStatsList, &bucketCounter)
427 }
428 entry.SetBucketStats(bucketStatsList)
Jonathan Hart60c5d772020-03-30 18:28:40 -0700429 // TODO loxi should set lengths automatically
430 // last 2 + 4 are padding
431 length := 2 + 4 + 4 + 8 + 8 + 4 + 4 + len(bucketStatsList)*16 + 2 + 4
432 entry.SetLength(uint16(length))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800433 groupStatsEntries = append(groupStatsEntries, &entry)
434 }
435 response.SetEntries(groupStatsEntries)
436 return response, nil
437}
438
Jonathan Hart4b110f62020-03-13 17:36:19 -0700439func (ofc *OFConnection) handleGroupStatsDescRequest(request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700440 volthaClient := ofc.VolthaClient.Get()
441 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800442 return nil, NoVolthaConnectionError
443 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800444 response := ofp.NewGroupDescStatsReply()
445 response.SetVersion(request.GetVersion())
446 response.SetXid(request.GetXid())
447 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700448 reply, err := volthaClient.ListLogicalDeviceFlowGroups(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800449 &common.ID{Id: ofc.DeviceID})
450 if err != nil {
451 return nil, err
452 }
453 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
454 for _, item := range reply.GetItems() {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700455 desc := item.GetDesc()
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800456
Jonathan Hart60c5d772020-03-30 18:28:40 -0700457 buckets := volthaBucketsToOpenflow(desc.Buckets)
458 var bucketsLength uint16
459 for _, b := range buckets {
460 bucketsLength += b.Len
461 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800462
Jonathan Hart60c5d772020-03-30 18:28:40 -0700463 groupDesc := &ofp.GroupDescStatsEntry{
464 // TODO loxi should set lengths automatically
465 // last 1 is padding
466 Length: 2 + 1 + 4 + bucketsLength + 1, // length field + groupType + groupId + buckets
467 GroupType: volthaGroupTypeToOpenflow(desc.Type),
468 GroupId: desc.GroupId,
469 Buckets: buckets,
470 }
471 groupDescStatsEntries = append(groupDescStatsEntries, groupDesc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800472 }
473 response.SetEntries(groupDescStatsEntries)
474 return response, nil
475}
476
Jonathan Hart4b110f62020-03-13 17:36:19 -0700477func (ofc *OFConnection) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800478 response := ofp.NewGroupFeaturesStatsReply()
479 response.SetVersion(request.GetVersion())
480 response.SetXid(request.GetXid())
481 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
482 //TODO wire this to voltha core when it implements
483 return response, nil
484}
485
Jonathan Hart4b110f62020-03-13 17:36:19 -0700486func (ofc *OFConnection) handleMeterStatsRequest(request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700487 volthaClient := ofc.VolthaClient.Get()
488 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800489 return nil, NoVolthaConnectionError
490 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800491 response := ofp.NewMeterStatsReply()
492 response.SetVersion(request.GetVersion())
493 response.SetXid(request.GetXid())
494 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700495 resp, err := volthaClient.ListLogicalDeviceMeters(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800496 &common.ID{Id: ofc.DeviceID})
497 if err != nil {
498 return nil, err
499 }
David K. Bainbridge55376262020-01-22 23:28:27 -0800500 size := uint16(5) // size of stats header
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800501 var meterStats []*ofp.MeterStats
502 for _, item := range resp.Items {
David K. Bainbridge55376262020-01-22 23:28:27 -0800503 entrySize := uint16(40) // size of entry header
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800504 meterStat := ofp.NewMeterStats()
505 stats := item.Stats
506 meterStat.DurationNsec = stats.DurationNsec
507 meterStat.DurationSec = stats.DurationSec
508 meterStat.ByteInCount = stats.ByteInCount
509 meterStat.FlowCount = stats.FlowCount
510 meterStat.MeterId = stats.MeterId
511 var bandStats []*ofp.MeterBandStats
512 for _, bStat := range stats.BandStats {
513 bandStat := ofp.NewMeterBandStats()
514 bandStat.ByteBandCount = bStat.ByteBandCount
515 bandStat.PacketBandCount = bStat.PacketBandCount
516 bandStats = append(bandStats, bandStat)
David K. Bainbridge55376262020-01-22 23:28:27 -0800517 entrySize += uint16(16) // size of each band stat
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800518 }
519 meterStat.SetBandStats(bandStats)
David K. Bainbridge55376262020-01-22 23:28:27 -0800520 meterStat.Len = entrySize
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800521 meterStats = append(meterStats, meterStat)
David K. Bainbridge55376262020-01-22 23:28:27 -0800522 size += entrySize
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800523 }
524 response.SetEntries(meterStats)
David K. Bainbridge55376262020-01-22 23:28:27 -0800525 response.SetLength(size)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800526 return response, nil
527}
528
Jonathan Hart4b110f62020-03-13 17:36:19 -0700529func (ofc *OFConnection) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800530 response := ofp.NewMeterConfigStatsReply()
531 response.SetVersion(request.GetVersion())
532 response.SetXid(request.GetXid())
533 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
534 //TODO wire this to voltha core when it implements
535 return response, nil
536}
537
Jonathan Hart4b110f62020-03-13 17:36:19 -0700538func (ofc *OFConnection) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800539 response := ofp.NewTableFeaturesStatsReply()
540 response.SetVersion(request.GetVersion())
541 response.SetXid(request.GetXid())
542 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
543 //TODO wire this to voltha core when it implements
544 return response, nil
545}
546
Jonathan Hart4b110f62020-03-13 17:36:19 -0700547func (ofc *OFConnection) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800548 var response = ofp.NewTableStatsReply()
549 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
550 response.SetVersion(request.GetVersion())
551 response.SetXid(request.GetXid())
552 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
553 return response, nil
554}
555
Jonathan Hart4b110f62020-03-13 17:36:19 -0700556func (ofc *OFConnection) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800557 response := ofp.NewQueueStatsReply()
558 response.SetVersion(request.GetVersion())
559 response.SetXid(request.GetXid())
560 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
561 //TODO wire this to voltha core when it implements
562 return response, nil
563}
564
Jonathan Hart4b110f62020-03-13 17:36:19 -0700565func (ofc *OFConnection) handlePortStatsRequest(request *ofp.PortStatsRequest) (*ofp.PortStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700566 volthaClient := ofc.VolthaClient.Get()
567 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800568 return nil, NoVolthaConnectionError
569 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800570 response := ofp.NewPortStatsReply()
571 response.SetXid(request.GetXid())
572 response.SetVersion(request.GetVersion())
573 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
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 }
591 response.SetEntries(entries)
592 return response, nil
593}
594
Jonathan Hart4b110f62020-03-13 17:36:19 -0700595func (ofc *OFConnection) handlePortDescStatsRequest(request *ofp.PortDescStatsRequest) (*ofp.PortDescStatsReply, error) {
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700596 volthaClient := ofc.VolthaClient.Get()
597 if volthaClient == nil {
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800598 return nil, NoVolthaConnectionError
599 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800600 response := ofp.NewPortDescStatsReply()
601 response.SetVersion(request.GetVersion())
602 response.SetXid(request.GetXid())
603 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700604 logicalDevice, err := volthaClient.GetLogicalDevice(context.Background(),
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800605 &common.ID{Id: ofc.DeviceID})
606 if err != nil {
607 return nil, err
608 }
609 var entries []*ofp.PortDesc
610 for _, port := range logicalDevice.GetPorts() {
611 ofpPort := port.GetOfpPort()
612 var entry ofp.PortDesc
613 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
614
615 var octets []byte
616 for _, val := range ofpPort.GetHwAddr() {
617 octets = append(octets, byte(val))
618 }
619 hwAddr := net.HardwareAddr(octets)
620 entry.SetHwAddr(hwAddr)
621 entry.SetName(PadString(ofpPort.GetName(), 16))
622 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
623 entry.SetState(ofp.PortState(ofpPort.GetState()))
624 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
625 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
626 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
627 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
628 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
629 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
630
631 entries = append(entries, &entry)
632 }
633
634 response.SetEntries(entries)
635 //TODO call voltha and get port descriptions etc
636 return response, nil
637
638}
639
Jonathan Hart4b110f62020-03-13 17:36:19 -0700640func (ofc *OFConnection) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800641 response := ofp.NewMeterFeaturesStatsReply()
642 response.SetXid(request.GetXid())
643 response.SetVersion(request.GetVersion())
644 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
645 meterFeatures := ofp.NewMeterFeatures()
646 meterFeatures.Capabilities = ofp.OFPMFKbps
647 meterFeatures.BandTypes = ofp.OFPMBTDrop
648 meterFeatures.MaxMeter = 0xffffffff
649 meterFeatures.MaxBands = 0xff
650 meterFeatures.MaxColor = 0xff
651 response.Features = *meterFeatures
652 return response, nil
653}
654
Jonathan Hart4b110f62020-03-13 17:36:19 -0700655func (ofc *OFConnection) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800656 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
657 response.SetVersion(request.GetVersion())
658 response.SetXid(request.GetXid())
659 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
660 //TODO wire this to voltha core when it implements
661 return response, nil
662}