blob: 46fe2f244ada17c6a0d13b955fdaad3cbc4ec679 [file] [log] [blame]
Don Newton98fd8812019-09-23 15:15:02 -04001/*
2 Copyright 2017 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/opencord/voltha-protos/go/openflow_13"
23 "github.com/skydive-project/goloxi"
24 "log"
25 "net"
26 "unsafe"
27
28 "github.com/opencord/voltha-protos/go/common"
29 pb "github.com/opencord/voltha-protos/go/voltha"
30 ofp "github.com/skydive-project/goloxi/of13"
31)
32
33func handleStatsRequest(request ofp.IHeader, statType uint16, deviceId string, client *Client) error {
34 message, _ := json.Marshal(request)
35 log.Printf("handleStatsRequest called with %s\n ", message)
36 var id = common.ID{Id: deviceId}
37
38 switch statType {
39 case 0:
40 statsReq := request.(*ofp.DescStatsRequest)
41 response, err := handleDescStatsRequest(statsReq, id)
42 if err != nil {
43 return err
44 }
45 client.SendMessage(response)
46
47 case 1:
48 statsReq := request.(*ofp.FlowStatsRequest)
49 response, _ := handleFlowStatsRequest(statsReq, id)
50 err := client.SendMessage(response)
51 if err != nil {
52 return err
53 }
54
55 case 2:
56 statsReq := request.(*ofp.AggregateStatsRequest)
57 aggregateStatsReply, err := handleAggregateStatsRequest(statsReq, id)
58 if err != nil {
59 return err
60 }
61 client.SendMessage(aggregateStatsReply)
62 case 3:
63 statsReq := request.(*ofp.TableStatsRequest)
64 tableStatsReply, e := handleTableStatsRequest(statsReq, id)
65 if e != nil {
66 return e
67 }
68 client.SendMessage(tableStatsReply)
69 case 4:
70 statsReq := request.(*ofp.PortStatsRequest)
71 response, err := handlePortStatsRequest(statsReq, id)
72 if err != nil {
73 return err
74 }
75 client.SendMessage(response)
76
77 case 5:
78 statsReq := request.(*ofp.QueueStatsRequest)
79 response, err := handleQueueStatsRequest(statsReq, id)
80 if err != nil {
81 return err
82 }
83 client.SendMessage(response)
84 case 6:
85 statsReq := request.(*ofp.GroupStatsRequest)
86 response, err := handleGroupStatsRequest(statsReq, id)
87 if err != nil {
88 return err
89 }
90 client.SendMessage(response)
91 case 7:
92 statsReq := request.(*ofp.GroupDescStatsRequest)
93 response, err := handleGroupStatsDescRequest(statsReq, id)
94 if err != nil {
95 return err
96 }
97 client.SendMessage(response)
98 case 8:
99 statsReq := request.(*ofp.GroupFeaturesStatsRequest)
100 response, err := handleGroupFeatureStatsRequest(statsReq, id)
101 if err != nil {
102 return err
103 }
104 client.SendMessage(response)
105 case 9:
106 statsReq := request.(*ofp.MeterStatsRequest)
107 response, err := handleMeterStatsRequest(statsReq, id)
108 if err != nil {
109 return err
110 }
111 client.SendMessage(response)
112 case 10:
113 statsReq := request.(*ofp.MeterConfigStatsRequest)
114 response, err := handleMeterConfigStatsRequest(statsReq, id)
115 if err != nil {
116 return err
117 }
118 client.SendMessage(response)
119 case 11:
120 statsReq := request.(*ofp.MeterFeaturesStatsRequest)
121 response, err := handleMeterFeatureStatsRequest(statsReq)
122 if err != nil {
123 return err
124 }
125 client.SendMessage(response)
126 case 12:
127 statsReq := request.(*ofp.TableFeaturesStatsRequest)
128 response, err := handleTableFeaturesStatsRequest(statsReq, id)
129 if err != nil {
130 return err
131 }
132 client.SendMessage(response)
133 case 13:
134 statsReq := request.(*ofp.PortDescStatsRequest)
135 response, err := handlePortDescStatsRequest(statsReq, deviceId)
136 if err != nil {
137 return err
138 }
139 client.SendMessage(response)
140
141 case 65535:
142 statsReq := request.(*ofp.ExperimenterStatsRequest)
143 response, err := handleExperimenterStatsRequest(statsReq, id)
144 if err != nil {
145 return err
146 }
147 client.SendMessage(response)
148 }
149 return nil
150}
151
152func handleDescStatsRequest(request *ofp.DescStatsRequest, id common.ID) (*ofp.DescStatsReply, error) {
153 response := ofp.NewDescStatsReply()
154 response.SetXid(request.GetXid())
155 response.SetVersion(request.GetVersion())
156 client := *getGrpcClient()
157 resp, err := client.GetLogicalDevice(context.Background(), &id)
158 if err != nil {
159 return nil, err
160 }
161 desc := resp.GetDesc()
162
163 response.SetMfrDesc(PadString(desc.GetMfrDesc(), 256))
164 response.SetHwDesc(PadString(desc.GetHwDesc(), 256))
165 response.SetSwDesc(PadString(desc.GetSwDesc(), 256))
166 response.SetSerialNum(PadString(desc.GetSerialNum(), 32))
167 response.SetDpDesc(PadString(desc.GetDpDesc(), 256))
168 //jsonRes,_ := json.Marshal(response)
169 //log.Printf("handleDescStatsRequest response : %s",jsonRes)
170 return response, nil
171}
172func handleFlowStatsRequest(request *ofp.FlowStatsRequest, id common.ID) (*ofp.FlowStatsReply, error) {
173 log.Println("****************************************\n***********************************")
174 response := ofp.NewFlowStatsReply()
175 response.SetXid(request.GetXid())
176 response.SetVersion(request.GetVersion())
177 client := *getGrpcClient()
178 resp, err := client.ListLogicalDeviceFlows(context.Background(), &id)
179 if err != nil {
180 log.Println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
181 log.Printf("err in handleFlowStatsRequest calling ListLogicalDeviceFlows %v", err)
182 return nil, err
183 }
184 log.Println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
185 js, _ := json.Marshal(resp.GetItems())
186 log.Printf("||||||||||||||||||||||||||||||||||||HandFlowStat %s|||||||||||||||||||||||||||||||||||||||||", js)
187 var flow []*ofp.FlowStatsEntry
188 items := resp.GetItems()
189
190 for i := 0; i < len(items); i++ {
191 item := items[1]
192 var entry ofp.FlowStatsEntry
193
194 entry.SetTableId(uint8(item.GetId()))
195 entry.SetDurationSec(item.GetDurationSec())
196 entry.SetDurationNsec(item.GetDurationNsec())
197 entry.SetPriority(uint16(item.GetPriority()))
198 entry.SetIdleTimeout(uint16(item.GetIdleTimeout()))
199 entry.SetHardTimeout(uint16(item.GetHardTimeout()))
200 entry.SetFlags(ofp.FlowModFlags(item.GetFlags()))
201 entry.SetCookie(item.GetCookie())
202 entry.SetPacketCount(item.GetPacketCount())
203 entry.SetByteCount(item.GetByteCount())
204 var match ofp.Match
205 pbMatch := item.GetMatch()
206
207 var fields []goloxi.IOxm
208 match.SetType(uint16(pbMatch.GetType()))
209 oxFields := pbMatch.GetOxmFields()
210 for i := 0; i < len(oxFields); i++ {
211 js, _ := json.Marshal(oxFields[i])
212 log.Printf("oxfields %s", js)
213 oxmField := oxFields[i]
214 field := oxmField.GetField()
215 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
216 switch ofbField.Type {
217 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
218 ofpInPort := ofp.NewOxmInPort()
219 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
220 ofpInPort.Value = ofp.Port(val.Port)
221 fields = append(fields, ofpInPort)
222 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
223 ofpInPhyPort := ofp.NewOxmInPhyPort()
224 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
225 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
226 fields = append(fields, ofpInPhyPort)
227 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
228 ofpIpProto := ofp.NewOxmIpProto()
229 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
230 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
231 fields = append(fields, ofpIpProto)
232 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
233 ofpUdpSrc := ofp.NewOxmUdpSrc()
234 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
235 ofpUdpSrc.Value = uint16(val.UdpSrc)
236 fields = append(fields, ofpUdpSrc)
237 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
238 ofpUdpDst := ofp.NewOxmUdpSrc()
239 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
240 ofpUdpDst.Value = uint16(val.UdpDst)
241 fields = append(fields, ofpUdpDst)
242 case pb.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
243 ofpVlanVid := ofp.NewOxmVlanVid()
244 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_VlanVid)
245 ofpVlanVid.Value = uint16(val.VlanVid)
246 fields = append(fields, ofpVlanVid)
247 default:
248 log.Printf("handleFlowStatsRequest Unhandled OxmField %v", ofbField.Type)
249 }
250
251 }
252 match.OxmList = fields
253 match.Length = uint16(unsafe.Sizeof(match))
254 entry.SetMatch(match)
255 var instructions []ofp.IInstruction
256 ofpInstructions := item.Instructions
257 for i := 0; i < len(ofpInstructions); i++ {
258 ofpInstruction := ofpInstructions[i]
259 instType := ofpInstruction.Type
260 switch instType {
261 case uint32(openflow_13.OfpInstructionType_OFPIT_APPLY_ACTIONS):
262 ofpActions := ofpInstruction.GetActions().Actions
263 for i := 0; i < len(ofpActions); i++ {
264 ofpAction := ofpActions[i]
265 var actions []*ofp.Action
266 switch ofpAction.Type {
267 case openflow_13.OfpActionType_OFPAT_OUTPUT:
268 ofpOutputAction := ofpAction.GetOutput()
269 outputAction := ofp.NewActionOutput()
270 outputAction.Port = ofp.Port(ofpOutputAction.Port)
271 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
272 actions = append(actions, outputAction.Action)
273 }
274 }
275 instruction := ofp.NewInstruction(uint16(instType))
276 instructions = append(instructions, instruction)
277 }
278
279 }
280 entry.Instructions = instructions
281 entry.Length = uint16(unsafe.Sizeof(entry))
282 flow = append(flow, &entry)
283
284 }
285 response.SetEntries(flow)
286 return response, nil
287}
288func handleAggregateStatsRequest(request *ofp.AggregateStatsRequest, id common.ID) (*ofp.AggregateStatsReply, error) {
289 response := ofp.NewAggregateStatsReply()
290 response.SetVersion(request.GetVersion())
291 response.SetXid(request.GetXid())
292 response.SetFlowCount(0)
293 //TODO wire this to voltha core when it implements
294 return response, nil
295}
296func handleGroupStatsRequest(request *ofp.GroupStatsRequest, id common.ID) (*ofp.GroupStatsReply, error) {
297 response := ofp.NewGroupStatsReply()
298 response.SetVersion(request.GetVersion())
299 response.SetXid(request.GetXid())
300 client := *getGrpcClient()
301 reply, err := client.ListLogicalDeviceFlowGroups(context.Background(), &id)
302 if err != nil {
303 return nil, err
304 }
305
306 var groupStatsEntries []*ofp.GroupStatsEntry
307 items := reply.GetItems()
308 for i := 0; i < len(items); i++ {
309 item := items[i].GetStats()
310 var entry ofp.GroupStatsEntry
311 entry.SetByteCount(item.GetByteCount())
312 entry.SetPacketCount(item.GetPacketCount())
313 entry.SetDurationNsec(item.GetDurationNsec())
314 entry.SetDurationSec(item.GetDurationSec())
315 entry.SetRefCount(item.GetRefCount())
316 entry.SetGroupId(item.GetGroupId())
317 bucketStats := item.GetBucketStats()
318 var bucketStatsList []*ofp.BucketCounter
319 for j := 0; j < len(bucketStats); j++ {
320 bucketStat := bucketStats[i]
321 var bucketCounter ofp.BucketCounter
322 bucketCounter.SetPacketCount(bucketStat.GetPacketCount())
323 bucketCounter.SetByteCount(bucketStat.GetByteCount())
324 bucketStatsList = append(bucketStatsList, &bucketCounter)
325 }
326 entry.SetBucketStats(bucketStatsList)
327 groupStatsEntries = append(groupStatsEntries, &entry)
328 }
329 response.SetEntries(groupStatsEntries)
330 return response, nil
331}
332func handleGroupStatsDescRequest(request *ofp.GroupDescStatsRequest, id common.ID) (*ofp.GroupDescStatsReply, error) {
333 response := ofp.NewGroupDescStatsReply()
334 response.SetVersion(request.GetVersion())
335 response.SetXid(request.GetXid())
336 client := *getGrpcClient()
337 reply, err := client.ListLogicalDeviceFlowGroups(context.Background(), &id)
338 if err != nil {
339 return nil, err
340 }
341 entries := reply.GetItems()
342 var groupDescStatsEntries []*ofp.GroupDescStatsEntry
343 for i := 0; i < len(entries); i++ {
344 item := entries[i].GetStats()
345 var groupDesc ofp.GroupDescStatsEntry
346 groupDesc.SetGroupId(item.GetGroupId())
347 /*
348 buckets := item.g
349 var bucketList []*ofp.Bucket
350 for j:=0;j<len(buckets);j++{
351
352 }
353
354 groupDesc.SetBuckets(bucketList)
355 */
356 groupDescStatsEntries = append(groupDescStatsEntries, &groupDesc)
357 }
358 response.SetEntries(groupDescStatsEntries)
359 return response, nil
360}
361func handleGroupFeatureStatsRequest(request *ofp.GroupFeaturesStatsRequest, id common.ID) (*ofp.GroupFeaturesStatsReply, error) {
362 response := ofp.NewGroupFeaturesStatsReply()
363 response.SetVersion(request.GetVersion())
364 response.SetXid(request.GetXid())
365 //TODO wire this to voltha core when it implements
366 return response, nil
367}
368func handleMeterStatsRequest(request *ofp.MeterStatsRequest, id common.ID) (*ofp.MeterStatsReply, error) {
369 response := ofp.NewMeterStatsReply()
370 response.SetVersion(request.GetVersion())
371 response.SetXid(request.GetXid())
372 //TODO wire this to voltha core when it implements
373 return response, nil
374}
375
376//statsReq := request.(*ofp.MeterConfigStatsRequest)
377func handleMeterConfigStatsRequest(request *ofp.MeterConfigStatsRequest, id common.ID) (*ofp.MeterConfigStatsReply, error) {
378 response := ofp.NewMeterConfigStatsReply()
379 response.SetVersion(request.GetVersion())
380 response.SetXid(request.GetXid())
381 //TODO wire this to voltha core when it implements
382 return response, nil
383}
384
385//statsReq := request.(*ofp.TableFeaturesStatsRequest)
386func handleTableFeaturesStatsRequest(request *ofp.TableFeaturesStatsRequest, id common.ID) (*ofp.TableFeaturesStatsReply, error) {
387 response := ofp.NewTableFeaturesStatsReply()
388 response.SetVersion(request.GetVersion())
389 response.SetXid(request.GetXid())
390 //TODO wire this to voltha core when it implements
391 return response, nil
392}
393func handleTableStatsRequest(request *ofp.TableStatsRequest, id common.ID) (*ofp.TableStatsReply, error) {
394 var tableStatsReply = ofp.NewTableStatsReply()
395 tableStatsReply.SetFlags(ofp.StatsReplyFlags(request.GetFlags()))
396 tableStatsReply.SetVersion(request.GetVersion())
397 tableStatsReply.SetXid(request.GetXid())
398 return tableStatsReply, nil
399}
400func handleQueueStatsRequest(request *ofp.QueueStatsRequest, id common.ID) (*ofp.QueueStatsReply, error) {
401 response := ofp.NewQueueStatsReply()
402 response.SetVersion(request.GetVersion())
403 response.SetXid(request.GetXid())
404 //TODO wire this to voltha core when it implements
405 return response, nil
406}
407func handlePortStatsRequest(request *ofp.PortStatsRequest, id common.ID) (*ofp.PortStatsReply, error) {
408 log.Println("HERE")
409 response := ofp.NewPortStatsReply()
410 response.SetXid(request.GetXid())
411 response.SetVersion(request.GetVersion())
412 //response.SetFlags(ofp.flagsrequest.GetFlags())
413 client := *getGrpcClient()
414 reply, err := client.ListLogicalDevicePorts(context.Background(), &id)
415 //reply,err := client.GetLogicalDevicePort(context.Background(),&id)
416 if err != nil {
417 log.Printf("error calling ListDevicePorts %v", err)
418 return nil, err
419 }
420 js, _ := json.Marshal(reply)
421 log.Printf("PORT STATS REPLY %s", js)
422 ports := reply.GetItems()
423 var entries []*ofp.PortStatsEntry
424 if request.GetPortNo() == 0xffffffff { //all ports
425 for i := 0; i < len(ports); i++ {
426 port := ports[i]
427 entry := parsePortStats(port)
428 entries = append(entries, &entry)
429 }
430 } else { //find right port that is requested
431 for i := 0; i < len(ports); i++ {
432 if ports[i].GetOfpPortStats().GetPortNo() == uint32(request.GetPortNo()) {
433 entry := parsePortStats(ports[i])
434 entries = append(entries, &entry)
435 }
436 }
437 }
438 response.SetEntries(entries)
439 js, _ = json.Marshal(response)
440 log.Printf("handlePortStatsResponse %s", js)
441 return response, nil
442
443}
444func parsePortStats(port *pb.LogicalPort) ofp.PortStatsEntry {
445 stats := port.OfpPortStats
446 var entry ofp.PortStatsEntry
447 entry.SetPortNo(ofp.Port(stats.GetPortNo()))
448 entry.SetRxPackets(stats.GetRxPackets())
449 entry.SetTxPackets(stats.GetTxPackets())
450 entry.SetRxBytes(stats.GetRxBytes())
451 entry.SetTxBytes(stats.GetTxBytes())
452 entry.SetRxDropped(stats.GetRxDropped())
453 entry.SetTxDropped(stats.GetTxDropped())
454 entry.SetRxErrors(stats.GetRxErrors())
455 entry.SetTxErrors(stats.GetTxErrors())
456 entry.SetRxFrameErr(stats.GetRxFrameErr())
457 entry.SetRxOverErr(stats.GetRxOverErr())
458 entry.SetRxCrcErr(stats.GetRxCrcErr())
459 entry.SetCollisions(stats.GetCollisions())
460 entry.SetDurationSec(stats.GetDurationSec())
461 entry.SetDurationNsec(stats.GetDurationNsec())
462 return entry
463}
464func handlePortDescStatsRequest(request *ofp.PortDescStatsRequest, deviceId string) (*ofp.PortDescStatsReply, error) {
465 response := ofp.NewPortDescStatsReply()
466 response.SetVersion(request.GetVersion())
467 response.SetXid(request.GetXid())
468 var grpcClient = *getGrpcClient()
469 var id = common.ID{Id: deviceId}
470 logicalDevice, err := grpcClient.GetLogicalDevice(context.Background(), &id)
471 if err != nil {
472 return nil, err
473 }
474 ports := logicalDevice.GetPorts()
475 var entries []*ofp.PortDesc
476 for i := 0; i < len(ports); i++ {
477 var entry ofp.PortDesc
478 port := ports[i].GetOfpPort()
479 entry.SetPortNo(ofp.Port(port.GetPortNo()))
480
481 intArray := port.GetHwAddr()
482 var octets []byte
483 for i := 0; i < len(intArray); i++ {
484 octets = append(octets, byte(intArray[i]))
485 }
486 hwAddr := net.HardwareAddr(octets)
487 entry.SetHwAddr(hwAddr)
488 entry.SetName(PadString(port.GetName(), 16))
489 entry.SetConfig(ofp.PortConfig(port.GetConfig()))
490 entry.SetState(ofp.PortState(port.GetState()))
491 entry.SetCurr(ofp.PortFeatures(port.GetCurr()))
492 entry.SetAdvertised(ofp.PortFeatures(port.GetAdvertised()))
493 entry.SetSupported(ofp.PortFeatures(port.GetSupported()))
494 entry.SetPeer(ofp.PortFeatures(port.GetPeer()))
495 entry.SetCurrSpeed(port.GetCurrSpeed())
496 entry.SetMaxSpeed(port.GetMaxSpeed())
497
498 entries = append(entries, &entry)
499 }
500
501 response.SetEntries(entries)
502 //TODO call voltha and get port descriptions etc
503 return response, nil
504
505}
506func handleMeterFeatureStatsRequest(request *ofp.MeterFeaturesStatsRequest) (*ofp.MeterFeaturesStatsReply, error) {
507 response := ofp.NewMeterFeaturesStatsReply()
508 response.SetXid(request.GetXid())
509 response.SetVersion(request.GetVersion())
510 return response, nil
511}
512func handleExperimenterStatsRequest(request *ofp.ExperimenterStatsRequest, id common.ID) (*ofp.ExperimenterStatsReply, error) {
513 response := ofp.NewExperimenterStatsReply(request.GetExperimenter())
514 response.SetVersion(request.GetVersion())
515 response.SetXid(request.GetXid())
516 //TODO wire this to voltha core when it implements
517 return response, nil
518}