blob: 68d2625cfbe2fad9fa99acc6d98435260e603418 [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"
22 "github.com/donNewtonAlpha/goloxi"
23 ofp "github.com/donNewtonAlpha/goloxi/of13"
24 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-protos/v2/go/common"
26 "github.com/opencord/voltha-protos/v2/go/openflow_13"
27 "net"
28 "unsafe"
29)
30
31func (ofc *OFClient) handleStatsRequest(request ofp.IHeader, statType uint16) error {
32 if logger.V(log.DebugLevel) {
33 js, _ := json.Marshal(request)
34 logger.Debugw("handleStatsRequest called",
35 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)
51 logger.Debugw("handle-stats-request",
52 log.Fields{
53 "device-id": ofc.DeviceID,
54 "request": reqJs,
55 "response": resJs})
56 }
57 return ofc.SendMessage(response)
58 case ofp.OFPSTFlow:
59 statsReq := request.(*ofp.FlowStatsRequest)
60 response, err := ofc.handleFlowStatsRequest(statsReq)
61 if err != nil {
62 return err
63 }
64 response.Length = uint16(unsafe.Sizeof(*response))
65 if logger.V(log.DebugLevel) {
66 reqJs, _ := json.Marshal(statsReq)
67 resJs, _ := json.Marshal(response)
68 logger.Debugw("handle-stats-request",
69 log.Fields{
70 "device-id": ofc.DeviceID,
71 "request": reqJs,
72 "response": resJs})
73 }
74 return ofc.SendMessage(response)
75
76 case ofp.OFPSTAggregate:
77 statsReq := request.(*ofp.AggregateStatsRequest)
78 response, err := ofc.handleAggregateStatsRequest(statsReq)
79 if err != nil {
80 return err
81 }
82 if logger.V(log.DebugLevel) {
83 reqJs, _ := json.Marshal(statsReq)
84 resJs, _ := json.Marshal(response)
85 logger.Debugw("handle-stats-request",
86 log.Fields{
87 "device-id": ofc.DeviceID,
88 "request": reqJs,
89 "response": resJs})
90 }
91 return ofc.SendMessage(response)
92 case ofp.OFPSTTable:
93 statsReq := request.(*ofp.TableStatsRequest)
94 response, e := ofc.handleTableStatsRequest(statsReq)
95 if logger.V(log.DebugLevel) {
96 reqJs, _ := json.Marshal(statsReq)
97 resJs, _ := json.Marshal(response)
98 logger.Debugw("handle-stats-request",
99 log.Fields{
100 "device-id": ofc.DeviceID,
101 "request": reqJs,
102 "response": resJs})
103 }
104 if e != nil {
105 return e
106 }
107 return ofc.SendMessage(response)
108 case ofp.OFPSTPort:
109 statsReq := request.(*ofp.PortStatsRequest)
110 response, err := ofc.handlePortStatsRequest(statsReq)
111 if err != nil {
112 return err
113 }
114 if logger.V(log.DebugLevel) {
115 reqJs, _ := json.Marshal(statsReq)
116 resJs, _ := json.Marshal(response)
117 logger.Debugw("handle-stats-request",
118 log.Fields{
119 "device-id": ofc.DeviceID,
120 "request": reqJs,
121 "response": resJs})
122 }
123 return ofc.SendMessage(response)
124 case ofp.OFPSTQueue:
125 statsReq := request.(*ofp.QueueStatsRequest)
126 response, err := ofc.handleQueueStatsRequest(statsReq)
127 if err != nil {
128 return err
129 }
130 if logger.V(log.DebugLevel) {
131 reqJs, _ := json.Marshal(statsReq)
132 resJs, _ := json.Marshal(response)
133 logger.Debugw("handle-stats-request",
134 log.Fields{
135 "device-id": ofc.DeviceID,
136 "request": reqJs,
137 "response": resJs})
138 }
139 return ofc.SendMessage(response)
140 case ofp.OFPSTGroup:
141 statsReq := request.(*ofp.GroupStatsRequest)
142 response, err := ofc.handleGroupStatsRequest(statsReq)
143 if err != nil {
144 return err
145 }
146 if logger.V(log.DebugLevel) {
147 reqJs, _ := json.Marshal(statsReq)
148 resJs, _ := json.Marshal(response)
149 logger.Debugw("handle-stats-request",
150 log.Fields{
151 "device-id": ofc.DeviceID,
152 "request": reqJs,
153 "response": resJs})
154 }
155 ofc.SendMessage(response)
156 case ofp.OFPSTGroupDesc:
157 statsReq := request.(*ofp.GroupDescStatsRequest)
158 response, err := ofc.handleGroupStatsDescRequest(statsReq)
159 if err != nil {
160 return err
161 }
162 if logger.V(log.DebugLevel) {
163 reqJs, _ := json.Marshal(statsReq)
164 resJs, _ := json.Marshal(response)
165 logger.Debugw("handle-stats-request",
166 log.Fields{
167 "device-id": ofc.DeviceID,
168 "request": reqJs,
169 "response": resJs})
170 }
171 return ofc.SendMessage(response)
172
173 case ofp.OFPSTGroupFeatures:
174 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
175 response, err := ofc.handleGroupFeatureStatsRequest(statsReq)
176 if err != nil {
177 return err
178 }
179 if logger.V(log.DebugLevel) {
180 reqJs, _ := json.Marshal(statsReq)
181 resJs, _ := json.Marshal(response)
182 logger.Debugw("handle-stats-request",
183 log.Fields{
184 "device-id": ofc.DeviceID,
185 "request": reqJs,
186 "response": resJs})
187 }
188 return ofc.SendMessage(response)
189 case ofp.OFPSTMeter:
190 statsReq := request.(*ofp.MeterStatsRequest)
191 response, err := ofc.handleMeterStatsRequest(statsReq)
192 if err != nil {
193 return err
194 }
195 if logger.V(log.DebugLevel) {
196 reqJs, _ := json.Marshal(statsReq)
197 resJs, _ := json.Marshal(response)
198 logger.Debugw("handle-stats-request",
199 log.Fields{
200 "device-id": ofc.DeviceID,
201 "request": reqJs,
202 "response": resJs})
203 }
204 return ofc.SendMessage(response)
205 case ofp.OFPSTMeterConfig:
206 statsReq := request.(*ofp.MeterConfigStatsRequest)
207 response, err := ofc.handleMeterConfigStatsRequest(statsReq)
208 if err != nil {
209 return err
210 }
211 if logger.V(log.DebugLevel) {
212 reqJs, _ := json.Marshal(statsReq)
213 resJs, _ := json.Marshal(response)
214 logger.Debugw("handle-stats-request",
215 log.Fields{
216 "device-id": ofc.DeviceID,
217 "request": reqJs,
218 "response": resJs})
219 }
220 return ofc.SendMessage(response)
221 case ofp.OFPSTMeterFeatures:
222 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
223 response, err := ofc.handleMeterFeatureStatsRequest(statsReq)
224 if err != nil {
225 return err
226 }
227 if logger.V(log.DebugLevel) {
228 reqJs, _ := json.Marshal(statsReq)
229 resJs, _ := json.Marshal(response)
230 logger.Debugw("handle-stats-request",
231 log.Fields{
232 "device-id": ofc.DeviceID,
233 "request": reqJs,
234 "response": resJs})
235 }
236 return ofc.SendMessage(response)
237 case ofp.OFPSTTableFeatures:
238 statsReq := request.(*ofp.TableFeaturesStatsRequest)
239 response, err := ofc.handleTableFeaturesStatsRequest(statsReq)
240 if err != nil {
241 return err
242 }
243 if logger.V(log.DebugLevel) {
244 reqJs, _ := json.Marshal(statsReq)
245 resJs, _ := json.Marshal(response)
246 logger.Debugw("handle-stats-request",
247 log.Fields{
248 "device-id": ofc.DeviceID,
249 "request": reqJs,
250 "response": resJs})
251 }
252 return ofc.SendMessage(response)
253 case ofp.OFPSTPortDesc:
254 statsReq := request.(*ofp.PortDescStatsRequest)
255 response, err := ofc.handlePortDescStatsRequest(statsReq)
256 if err != nil {
257 return err
258 }
259 if logger.V(log.DebugLevel) {
260 reqJs, _ := json.Marshal(statsReq)
261 resJs, _ := json.Marshal(response)
262 logger.Debugw("handle-stats-request",
263 log.Fields{
264 "device-id": ofc.DeviceID,
265 "request": reqJs,
266 "response": resJs})
267 }
268 return ofc.SendMessage(response)
269
270 case ofp.OFPSTExperimenter:
271 statsReq := request.(*ofp.ExperimenterStatsRequest)
272 response, err := ofc.handleExperimenterStatsRequest(statsReq)
273 if err != nil {
274 return err
275 }
276 if logger.V(log.DebugLevel) {
277 reqJs, _ := json.Marshal(statsReq)
278 resJs, _ := json.Marshal(response)
279 logger.Debugw("handle-stats-request",
280 log.Fields{
281 "device-id": ofc.DeviceID,
282 "request": reqJs,
283 "response": resJs})
284 }
285 return ofc.SendMessage(response)
286 }
287 return nil
288}
289
290func (ofc *OFClient) handleDescStatsRequest(request *ofp.DescStatsRequest) (*ofp.DescStatsReply, error) {
291 response := ofp.NewDescStatsReply()
292 response.SetXid(request.GetXid())
293 response.SetVersion(request.GetVersion())
294 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
295
296 resp, err := ofc.VolthaClient.GetLogicalDevice(context.Background(),
297 &common.ID{Id: ofc.DeviceID})
298 if err != nil {
299 return nil, err
300 }
301 desc := resp.GetDesc()
302
303 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
304 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
305 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
306 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
307 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
308 return response, nil
309}
310
311func (ofc *OFClient) handleFlowStatsRequest(request *ofp.FlowStatsRequest) (*ofp.FlowStatsReply, error) {
312 response := ofp.NewFlowStatsReply()
313 response.SetXid(request.GetXid())
314 response.SetVersion(4)
315 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
316 resp, err := ofc.VolthaClient.ListLogicalDeviceFlows(context.Background(),
317 &common.ID{Id: ofc.DeviceID})
318 if err != nil {
319 return nil, err
320 }
321 var flow []*ofp.FlowStatsEntry
322 for _, item := range resp.GetItems() {
323 entry := ofp.NewFlowStatsEntry()
324 entry.SetTableId(uint8(item.GetTableId()))
325 entry.SetDurationSec(item.GetDurationSec())
326 entry.SetDurationNsec(item.GetDurationNsec())
327 entry.SetPriority(uint16(item.GetPriority()))
328 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
329 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
330 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
331 entry.SetCookie(item.GetCookie())
332 entry.SetPacketCount(item.GetPacketCount())
333 entry.SetByteCount(item.GetByteCount())
334 entrySize := uint16(48)
335 match := ofp.NewMatchV3()
336 pbMatch := item.GetMatch()
337 match.SetType(uint16(pbMatch.GetType()))
338 size := uint16(4)
339 var fields []goloxi.IOxm
340 for _, oxmField := range pbMatch.GetOxmFields() {
341 field := oxmField.GetField()
342 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
343 iOxm, oxmSize := parseOxm(ofbField, ofc.DeviceID)
344 fields = append(fields, iOxm)
345 if oxmSize > 0 {
346 size += 4 //header for oxm
347 }
348 size += oxmSize
349 }
350
351 match.OxmList = fields
352 match.Length = uint16(size)
353 //account for 8 byte alignment
354 if size%8 != 0 {
355 size = ((size / 8) + 1) * 8
356 }
357 entrySize += size
358 entry.SetMatch(*match)
359 var instructions []ofp.IInstruction
360 for _, ofpInstruction := range item.Instructions {
361 instruction, size := parseInstructions(ofpInstruction, ofc.DeviceID)
362 instructions = append(instructions, instruction)
363 entrySize += size
364 }
365 entry.Instructions = instructions
366 entry.Length = entrySize
367 entrySize = 0
368 flow = append(flow, entry)
369 }
370 response.SetEntries(flow)
371 return response, nil
372}
373
374func (ofc *OFClient) handleAggregateStatsRequest(request *ofp.AggregateStatsRequest) (*ofp.AggregateStatsReply, error) {
375 response := ofp.NewAggregateStatsReply()
376 response.SetVersion(request.GetVersion())
377 response.SetXid(request.GetXid())
378 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
379 response.SetFlowCount(0)
380 //TODO wire this to voltha core when it implements
381 return response, nil
382}
383
384func (ofc *OFClient) handleGroupStatsRequest(request *ofp.GroupStatsRequest) (*ofp.GroupStatsReply, error) {
385 response := ofp.NewGroupStatsReply()
386 response.SetVersion(request.GetVersion())
387 response.SetXid(request.GetXid())
388 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
389 reply, err := ofc.VolthaClient.ListLogicalDeviceFlowGroups(context.Background(),
390 &common.ID{Id: ofc.DeviceID})
391 if err != nil {
392 return nil, err
393 }
394
395 var groupStatsEntries []*ofp.GroupStatsEntry
396 for _, item := range reply.GetItems() {
397 stats := item.GetStats()
398 var entry ofp.GroupStatsEntry
399 entry.SetByteCount(stats.GetByteCount())
400 entry.SetPacketCount(stats.GetPacketCount())
401 entry.SetDurationNsec(stats.GetDurationNsec())
402 entry.SetDurationSec(stats.GetDurationSec())
403 entry.SetRefCount(stats.GetRefCount())
404 entry.SetGroupId(stats.GetGroupId())
405 var bucketStatsList []*ofp.BucketCounter
406 for _, bucketStat := range stats.GetBucketStats() {
407 bucketCounter := ofp.BucketCounter{}
408 bucketCounter.SetPacketCount(bucketStat.GetPacketCount())
409 bucketCounter.SetByteCount(bucketStat.GetByteCount())
410 bucketStatsList = append(bucketStatsList, &bucketCounter)
411 }
412 entry.SetBucketStats(bucketStatsList)
413 groupStatsEntries = append(groupStatsEntries, &entry)
414 }
415 response.SetEntries(groupStatsEntries)
416 return response, nil
417}
418
419func (ofc *OFClient) handleGroupStatsDescRequest(request *ofp.GroupDescStatsRequest) (*ofp.GroupDescStatsReply, error) {
420 response := ofp.NewGroupDescStatsReply()
421 response.SetVersion(request.GetVersion())
422 response.SetXid(request.GetXid())
423 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
424 reply, err := ofc.VolthaClient.ListLogicalDeviceFlowGroups(context.Background(),
425 &common.ID{Id: ofc.DeviceID})
426 if err != nil {
427 return nil, err
428 }
429 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
430 for _, item := range reply.GetItems() {
431 stats := item.GetStats()
432 var groupDesc ofp.GroupDescStatsEntry
433 groupDesc.SetGroupId(stats.GetGroupId())
434 /*
435 buckets := item.g
436 var bucketList []*ofp.Bucket
437 for j:=0;j<len(buckets);j++{
438
439 }
440
441 groupDesc.SetBuckets(bucketList)
442 */
443 groupDescStatsEntries = append(groupDescStatsEntries, &groupDesc)
444 }
445 response.SetEntries(groupDescStatsEntries)
446 return response, nil
447}
448
449func (ofc *OFClient) handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest) (*ofp.GroupFeaturesStatsReply, error) {
450 response := ofp.NewGroupFeaturesStatsReply()
451 response.SetVersion(request.GetVersion())
452 response.SetXid(request.GetXid())
453 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
454 //TODO wire this to voltha core when it implements
455 return response, nil
456}
457
458func (ofc *OFClient) handleMeterStatsRequest(request *ofp.MeterStatsRequest) (*ofp.MeterStatsReply, error) {
459 response := ofp.NewMeterStatsReply()
460 response.SetVersion(request.GetVersion())
461 response.SetXid(request.GetXid())
462 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
463 resp, err := ofc.VolthaClient.ListLogicalDeviceMeters(context.Background(),
464 &common.ID{Id: ofc.DeviceID})
465 if err != nil {
466 return nil, err
467 }
468 size := uint16(40)
469 var meterStats []*ofp.MeterStats
470 for _, item := range resp.Items {
471 meterStat := ofp.NewMeterStats()
472 stats := item.Stats
473 meterStat.DurationNsec = stats.DurationNsec
474 meterStat.DurationSec = stats.DurationSec
475 meterStat.ByteInCount = stats.ByteInCount
476 meterStat.FlowCount = stats.FlowCount
477 meterStat.MeterId = stats.MeterId
478 var bandStats []*ofp.MeterBandStats
479 for _, bStat := range stats.BandStats {
480 bandStat := ofp.NewMeterBandStats()
481 bandStat.ByteBandCount = bStat.ByteBandCount
482 bandStat.PacketBandCount = bStat.PacketBandCount
483 bandStats = append(bandStats, bandStat)
484 size += 16
485 }
486 meterStat.SetBandStats(bandStats)
487 meterStat.Len = size
488 meterStats = append(meterStats, meterStat)
489 }
490 response.SetEntries(meterStats)
491 return response, nil
492}
493
494func (ofc *OFClient) handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest) (*ofp.MeterConfigStatsReply, error) {
495 response := ofp.NewMeterConfigStatsReply()
496 response.SetVersion(request.GetVersion())
497 response.SetXid(request.GetXid())
498 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
499 //TODO wire this to voltha core when it implements
500 return response, nil
501}
502
503func (ofc *OFClient) handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest) (*ofp.TableFeaturesStatsReply, error) {
504 response := ofp.NewTableFeaturesStatsReply()
505 response.SetVersion(request.GetVersion())
506 response.SetXid(request.GetXid())
507 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
508 //TODO wire this to voltha core when it implements
509 return response, nil
510}
511
512func (ofc *OFClient) handleTableStatsRequest(request *ofp.TableStatsRequest) (*ofp.TableStatsReply, error) {
513 var response = ofp.NewTableStatsReply()
514 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
515 response.SetVersion(request.GetVersion())
516 response.SetXid(request.GetXid())
517 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
518 return response, nil
519}
520
521func (ofc *OFClient) handleQueueStatsRequest(request *ofp.QueueStatsRequest) (*ofp.QueueStatsReply, error) {
522 response := ofp.NewQueueStatsReply()
523 response.SetVersion(request.GetVersion())
524 response.SetXid(request.GetXid())
525 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
526 //TODO wire this to voltha core when it implements
527 return response, nil
528}
529
530func (ofc *OFClient) handlePortStatsRequest(request *ofp.PortStatsRequest) (*ofp.PortStatsReply, error) {
531 response := ofp.NewPortStatsReply()
532 response.SetXid(request.GetXid())
533 response.SetVersion(request.GetVersion())
534 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
535 reply, err := ofc.VolthaClient.ListLogicalDevicePorts(context.Background(),
536 &common.ID{Id: ofc.DeviceID})
537 if err != nil {
538 return nil, err
539 }
540 var entries []*ofp.PortStatsEntry
541 if request.GetPortNo() == 0xffffffff { //all ports
542 for _, port := range reply.GetItems() {
543 entries = append(entries, parsePortStats(port))
544 }
545 } else { //find right port that is requested
546 for _, port := range reply.GetItems() {
547 if port.GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
548 entries = append(entries, parsePortStats(port))
549 }
550 }
551 }
552 response.SetEntries(entries)
553 return response, nil
554}
555
556func (ofc *OFClient) handlePortDescStatsRequest(request *ofp.PortDescStatsRequest) (*ofp.PortDescStatsReply, error) {
557 response := ofp.NewPortDescStatsReply()
558 response.SetVersion(request.GetVersion())
559 response.SetXid(request.GetXid())
560 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
561 logicalDevice, err := ofc.VolthaClient.GetLogicalDevice(context.Background(),
562 &common.ID{Id: ofc.DeviceID})
563 if err != nil {
564 return nil, err
565 }
566 var entries []*ofp.PortDesc
567 for _, port := range logicalDevice.GetPorts() {
568 ofpPort := port.GetOfpPort()
569 var entry ofp.PortDesc
570 entry.SetPortNo(ofp.Port(ofpPort.GetPortNo()))
571
572 var octets []byte
573 for _, val := range ofpPort.GetHwAddr() {
574 octets = append(octets, byte(val))
575 }
576 hwAddr := net.HardwareAddr(octets)
577 entry.SetHwAddr(hwAddr)
578 entry.SetName(PadString(ofpPort.GetName(), 16))
579 entry.SetConfig(ofp.PortConfig(ofpPort.GetConfig()))
580 entry.SetState(ofp.PortState(ofpPort.GetState()))
581 entry.SetCurr(ofp.PortFeatures(ofpPort.GetCurr()))
582 entry.SetAdvertised(ofp.PortFeatures(ofpPort.GetAdvertised()))
583 entry.SetSupported(ofp.PortFeatures(ofpPort.GetSupported()))
584 entry.SetPeer(ofp.PortFeatures(ofpPort.GetPeer()))
585 entry.SetCurrSpeed(ofpPort.GetCurrSpeed())
586 entry.SetMaxSpeed(ofpPort.GetMaxSpeed())
587
588 entries = append(entries, &entry)
589 }
590
591 response.SetEntries(entries)
592 //TODO call voltha and get port descriptions etc
593 return response, nil
594
595}
596
597func (ofc *OFClient) handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
598 response := ofp.NewMeterFeaturesStatsReply()
599 response.SetXid(request.GetXid())
600 response.SetVersion(request.GetVersion())
601 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
602 meterFeatures := ofp.NewMeterFeatures()
603 meterFeatures.Capabilities = ofp.OFPMFKbps
604 meterFeatures.BandTypes = ofp.OFPMBTDrop
605 meterFeatures.MaxMeter = 0xffffffff
606 meterFeatures.MaxBands = 0xff
607 meterFeatures.MaxColor = 0xff
608 response.Features = *meterFeatures
609 return response, nil
610}
611
612func (ofc *OFClient) handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest) (*ofp.ExperimenterStatsReply, error) {
613 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
614 response.SetVersion(request.GetVersion())
615 response.SetXid(request.GetXid())
616 response.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
617 //TODO wire this to voltha core when it implements
618 return response, nil
619}