blob: a5bd1d15e4afd78cfa4dec918301d5cd95ca6eed [file] [log] [blame]
Don Newtone0d34a82019-11-14 10:58:06 -05001/*
David K. Bainbridge157bdab2020-01-16 14:38:05 -08002 Copyright 2020 the original author or authors.
Don Newtone0d34a82019-11-14 10:58:06 -05003
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*/
16package openflow
17
18import (
19 "encoding/json"
Don Newtonb437c6f2019-12-18 11:51:57 -050020 "github.com/donNewtonAlpha/goloxi"
21 ofp "github.com/donNewtonAlpha/goloxi/of13"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080022 "github.com/opencord/voltha-lib-go/v3/pkg/log"
23 "github.com/opencord/voltha-protos/v3/go/openflow_13"
24 "github.com/opencord/voltha-protos/v3/go/voltha"
Don Newtone0d34a82019-11-14 10:58:06 -050025)
26
Don Newton7577f072020-01-06 12:41:11 -050027func parseOxm(ofbField *openflow_13.OfpOxmOfbField, DeviceID string) (goloxi.IOxm, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080028 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -050029 js, _ := json.Marshal(ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080030 logger.Debugw("parseOxm called",
31 log.Fields{
32 "device-id": DeviceID,
33 "ofbField": js})
Don Newton7577f072020-01-06 12:41:11 -050034 }
35
Don Newtone0d34a82019-11-14 10:58:06 -050036 switch ofbField.Type {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080037 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050038 ofpInPort := ofp.NewOxmInPort()
39 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
40 ofpInPort.Value = ofp.Port(val.Port)
41 return ofpInPort, 4
David K. Bainbridge157bdab2020-01-16 14:38:05 -080042 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
Don Newtone0d34a82019-11-14 10:58:06 -050043 ofpEthType := ofp.NewOxmEthType()
44 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
45 ofpEthType.Value = ofp.EthernetType(val.EthType)
46 return ofpEthType, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080047 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050048 ofpInPhyPort := ofp.NewOxmInPhyPort()
49 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
50 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
51 return ofpInPhyPort, 4
David K. Bainbridge157bdab2020-01-16 14:38:05 -080052 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
Don Newtone0d34a82019-11-14 10:58:06 -050053 ofpIpProto := ofp.NewOxmIpProto()
54 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
55 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
56 return ofpIpProto, 1
David K. Bainbridge157bdab2020-01-16 14:38:05 -080057 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
Don Newtone0d34a82019-11-14 10:58:06 -050058 ofpUdpSrc := ofp.NewOxmUdpSrc()
59 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
60 ofpUdpSrc.Value = uint16(val.UdpSrc)
61 return ofpUdpSrc, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080062 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
Don Newtone0d34a82019-11-14 10:58:06 -050063 ofpUdpDst := ofp.NewOxmUdpDst()
64 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
65 ofpUdpDst.Value = uint16(val.UdpDst)
66 return ofpUdpDst, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080067 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtone0d34a82019-11-14 10:58:06 -050068 ofpVlanVid := ofp.NewOxmVlanVid()
69 val := ofbField.GetValue()
Don Newton7fe70f72020-02-21 13:54:11 -050070 if val == nil {
Don Newtone0d34a82019-11-14 10:58:06 -050071 ofpVlanVid.Value = uint16(0)
Don Newton7fe70f72020-02-21 13:54:11 -050072 return ofpVlanVid, 2
Don Newtone0d34a82019-11-14 10:58:06 -050073 }
Don Newton7fe70f72020-02-21 13:54:11 -050074 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
75 if ofbField.HasMask {
76 ofpVlanVidMasked := ofp.NewOxmVlanVidMasked()
77 valMask := ofbField.GetMask()
78 vlanMask := valMask.(*openflow_13.OfpOxmOfbField_VlanVidMask)
79 if vlanId.VlanVid == 4096 && vlanMask.VlanVidMask == 4096 {
80 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid)
81 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
82 } else {
83 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid) | 0x1000
84 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
85
86 }
87 return ofpVlanVidMasked, 4
88 }
89 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Don Newtone0d34a82019-11-14 10:58:06 -050090 return ofpVlanVid, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080091 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
Don Newtone0d34a82019-11-14 10:58:06 -050092 ofpMetadata := ofp.NewOxmMetadata()
93 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_TableMetadata)
94 ofpMetadata.Value = val.TableMetadata
95 return ofpMetadata, 8
96 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080097 if logger.V(log.WarnLevel) {
98 js, _ := json.Marshal(ofbField)
99 logger.Warnw("ParseOXM Unhandled OxmField",
100 log.Fields{
101 "device-id": DeviceID,
102 "OfbField": js})
103 }
Don Newtone0d34a82019-11-14 10:58:06 -0500104 }
105 return nil, 0
106}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800107
Don Newton7577f072020-01-06 12:41:11 -0500108func parseInstructions(ofpInstruction *openflow_13.OfpInstruction, DeviceID string) (ofp.IInstruction, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800109 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500110 js, _ := json.Marshal(ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800111 logger.Debugw("parseInstructions called",
112 log.Fields{
113 "device-id": DeviceID,
114 "Instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500115 }
Don Newtone0d34a82019-11-14 10:58:06 -0500116 instType := ofpInstruction.Type
117 data := ofpInstruction.GetData()
118 switch instType {
119 case ofp.OFPITWriteMetadata:
120 instruction := ofp.NewInstructionWriteMetadata()
121 instruction.Len = 24
122 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
123 instruction.Metadata = uint64(metadata.Metadata)
124 return instruction, 24
125 case ofp.OFPITMeter:
126 instruction := ofp.NewInstructionMeter()
127 instruction.Len = 8
128 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
129 instruction.MeterId = meter.MeterId
130 return instruction, 8
131 case ofp.OFPITGotoTable:
132 instruction := ofp.NewInstructionGotoTable()
133 instruction.Len = 8
134 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
135 instruction.TableId = uint8(gotoTable.TableId)
136 return instruction, 8
137 case ofp.OFPITApplyActions:
138 instruction := ofp.NewInstructionApplyActions()
139 var instructionSize uint16
140 instructionSize = 8
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800141 //ofpActions := ofpInstruction.GetActions().Actions
Don Newtone0d34a82019-11-14 10:58:06 -0500142 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800143 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Don Newton7577f072020-01-06 12:41:11 -0500144 action, actionSize := parseAction(ofpAction, DeviceID)
Don Newtone0d34a82019-11-14 10:58:06 -0500145 actions = append(actions, action)
146 instructionSize += actionSize
Don Newtone0d34a82019-11-14 10:58:06 -0500147
148 }
149 instruction.Actions = actions
150 instruction.SetLen(instructionSize)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800151 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500152 js, _ := json.Marshal(instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800153 logger.Debugw("parseInstructions returning",
154 log.Fields{
155 "device-id": DeviceID,
156 "size": instructionSize,
157 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500158 }
Don Newtone0d34a82019-11-14 10:58:06 -0500159 return instruction, instructionSize
160 }
161 //shouldn't have reached here :<
Don Newtone0d34a82019-11-14 10:58:06 -0500162 return nil, 0
163}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800164
Don Newton7577f072020-01-06 12:41:11 -0500165func parseAction(ofpAction *openflow_13.OfpAction, DeviceID string) (goloxi.IAction, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800166 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500167 js, _ := json.Marshal(ofpAction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800168 logger.Debugw("parseAction called",
169 log.Fields{
170 "device-id": DeviceID,
171 "action": js})
Don Newton7577f072020-01-06 12:41:11 -0500172 }
Don Newtone0d34a82019-11-14 10:58:06 -0500173 switch ofpAction.Type {
174 case openflow_13.OfpActionType_OFPAT_OUTPUT:
175 ofpOutputAction := ofpAction.GetOutput()
176 outputAction := ofp.NewActionOutput()
177 outputAction.Port = ofp.Port(ofpOutputAction.Port)
178 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
179 outputAction.Len = 16
180 return outputAction, 16
181 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
182 ofpPushVlanAction := ofp.NewActionPushVlan()
183 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
184 ofpPushVlanAction.Len = 8
185 return ofpPushVlanAction, 8
186 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
187 ofpPopVlanAction := ofp.NewActionPopVlan()
188 ofpPopVlanAction.Len = 8
189 return ofpPopVlanAction, 8
190 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
191 ofpActionSetField := ofpAction.GetSetField()
192 setFieldAction := ofp.NewActionSetField()
193
Don Newton7577f072020-01-06 12:41:11 -0500194 iOxm, _ := parseOxm(ofpActionSetField.GetField().GetOfbField(), DeviceID)
Don Newtone0d34a82019-11-14 10:58:06 -0500195 setFieldAction.Field = iOxm
Don Newtonb437c6f2019-12-18 11:51:57 -0500196 setFieldAction.Len = 16
197 return setFieldAction, 16
Don Newtone0d34a82019-11-14 10:58:06 -0500198 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800199 if logger.V(log.WarnLevel) {
200 js, _ := json.Marshal(ofpAction)
201 logger.Warnw("parseAction unknow action",
202 log.Fields{
203 "device-id": DeviceID,
204 "action": js})
205 }
Don Newtone0d34a82019-11-14 10:58:06 -0500206 }
207 return nil, 0
208}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800209
210func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500211 stats := port.OfpPortStats
212 port.OfpPort.GetPortNo()
213 var entry ofp.PortStatsEntry
214 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
215 entry.SetRxPackets(stats.GetRxPackets())
216 entry.SetTxPackets(stats.GetTxPackets())
217 entry.SetRxBytes(stats.GetRxBytes())
218 entry.SetTxBytes(stats.GetTxBytes())
219 entry.SetRxDropped(stats.GetRxDropped())
220 entry.SetTxDropped(stats.GetTxDropped())
221 entry.SetRxErrors(stats.GetRxErrors())
222 entry.SetTxErrors(stats.GetTxErrors())
223 entry.SetRxFrameErr(stats.GetRxFrameErr())
224 entry.SetRxOverErr(stats.GetRxOverErr())
225 entry.SetRxCrcErr(stats.GetRxCrcErr())
226 entry.SetCollisions(stats.GetCollisions())
227 entry.SetDurationSec(stats.GetDurationSec())
228 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800229 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500230}