blob: beff0be79d7e43a6ee9ad4467f02bf2e149a183b [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 (
Jonathan Hart60c5d772020-03-30 18:28:40 -070019 "bytes"
20 "encoding/binary"
Don Newtone0d34a82019-11-14 10:58:06 -050021 "encoding/json"
Don Newtonb437c6f2019-12-18 11:51:57 -050022 "github.com/donNewtonAlpha/goloxi"
23 ofp "github.com/donNewtonAlpha/goloxi/of13"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080024 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "github.com/opencord/voltha-protos/v3/go/openflow_13"
26 "github.com/opencord/voltha-protos/v3/go/voltha"
Don Newtone0d34a82019-11-14 10:58:06 -050027)
28
Jonathan Hart60c5d772020-03-30 18:28:40 -070029func parseOxm(ofbField *openflow_13.OfpOxmOfbField) (goloxi.IOxm, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080030 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -050031 js, _ := json.Marshal(ofbField)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080032 logger.Debugw("parseOxm called",
Jonathan Hart60c5d772020-03-30 18:28:40 -070033 log.Fields{"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
Jonathan Hart60c5d772020-03-30 18:28:40 -070057 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
58 ofpIpv4Dst := ofp.NewOxmIpv4Dst()
59 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Ipv4Dst)
60 buf := new(bytes.Buffer)
61 err := binary.Write(buf, binary.BigEndian, val.Ipv4Dst)
62 if err != nil {
63 logger.Errorw("error writing ipv4 address %v",
64 log.Fields{"error": err})
65 }
66 ofpIpv4Dst.Value = buf.Bytes()
67 return ofpIpv4Dst, 4
David K. Bainbridge157bdab2020-01-16 14:38:05 -080068 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
Don Newtone0d34a82019-11-14 10:58:06 -050069 ofpUdpSrc := ofp.NewOxmUdpSrc()
70 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
71 ofpUdpSrc.Value = uint16(val.UdpSrc)
72 return ofpUdpSrc, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080073 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
Don Newtone0d34a82019-11-14 10:58:06 -050074 ofpUdpDst := ofp.NewOxmUdpDst()
75 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
76 ofpUdpDst.Value = uint16(val.UdpDst)
77 return ofpUdpDst, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -080078 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtone0d34a82019-11-14 10:58:06 -050079 ofpVlanVid := ofp.NewOxmVlanVid()
80 val := ofbField.GetValue()
Don Newton7fe70f72020-02-21 13:54:11 -050081 if val == nil {
Don Newtone0d34a82019-11-14 10:58:06 -050082 ofpVlanVid.Value = uint16(0)
Don Newton7fe70f72020-02-21 13:54:11 -050083 return ofpVlanVid, 2
Don Newtone0d34a82019-11-14 10:58:06 -050084 }
Don Newton7fe70f72020-02-21 13:54:11 -050085 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
86 if ofbField.HasMask {
87 ofpVlanVidMasked := ofp.NewOxmVlanVidMasked()
88 valMask := ofbField.GetMask()
89 vlanMask := valMask.(*openflow_13.OfpOxmOfbField_VlanVidMask)
90 if vlanId.VlanVid == 4096 && vlanMask.VlanVidMask == 4096 {
91 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid)
92 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
93 } else {
94 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid) | 0x1000
95 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
96
97 }
98 return ofpVlanVidMasked, 4
99 }
100 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Don Newtone0d34a82019-11-14 10:58:06 -0500101 return ofpVlanVid, 2
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800102 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
Don Newtone0d34a82019-11-14 10:58:06 -0500103 ofpMetadata := ofp.NewOxmMetadata()
104 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_TableMetadata)
105 ofpMetadata.Value = val.TableMetadata
106 return ofpMetadata, 8
107 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800108 if logger.V(log.WarnLevel) {
109 js, _ := json.Marshal(ofbField)
110 logger.Warnw("ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700111 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800112 }
Don Newtone0d34a82019-11-14 10:58:06 -0500113 }
114 return nil, 0
115}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800116
Jonathan Hart60c5d772020-03-30 18:28:40 -0700117func parseInstructions(ofpInstruction *openflow_13.OfpInstruction) (ofp.IInstruction, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800118 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500119 js, _ := json.Marshal(ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 logger.Debugw("parseInstructions called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700121 log.Fields{"Instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500122 }
Don Newtone0d34a82019-11-14 10:58:06 -0500123 instType := ofpInstruction.Type
124 data := ofpInstruction.GetData()
125 switch instType {
126 case ofp.OFPITWriteMetadata:
127 instruction := ofp.NewInstructionWriteMetadata()
128 instruction.Len = 24
129 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
130 instruction.Metadata = uint64(metadata.Metadata)
131 return instruction, 24
132 case ofp.OFPITMeter:
133 instruction := ofp.NewInstructionMeter()
134 instruction.Len = 8
135 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
136 instruction.MeterId = meter.MeterId
137 return instruction, 8
138 case ofp.OFPITGotoTable:
139 instruction := ofp.NewInstructionGotoTable()
140 instruction.Len = 8
141 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
142 instruction.TableId = uint8(gotoTable.TableId)
143 return instruction, 8
144 case ofp.OFPITApplyActions:
145 instruction := ofp.NewInstructionApplyActions()
146 var instructionSize uint16
147 instructionSize = 8
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800148 //ofpActions := ofpInstruction.GetActions().Actions
Don Newtone0d34a82019-11-14 10:58:06 -0500149 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800150 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Jonathan Hart60c5d772020-03-30 18:28:40 -0700151 action, actionSize := parseAction(ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500152 actions = append(actions, action)
153 instructionSize += actionSize
Don Newtone0d34a82019-11-14 10:58:06 -0500154
155 }
156 instruction.Actions = actions
157 instruction.SetLen(instructionSize)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800158 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500159 js, _ := json.Marshal(instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800160 logger.Debugw("parseInstructions returning",
161 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800162 "size": instructionSize,
163 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500164 }
Don Newtone0d34a82019-11-14 10:58:06 -0500165 return instruction, instructionSize
166 }
167 //shouldn't have reached here :<
Don Newtone0d34a82019-11-14 10:58:06 -0500168 return nil, 0
169}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800170
Jonathan Hart60c5d772020-03-30 18:28:40 -0700171func parseAction(ofpAction *openflow_13.OfpAction) (goloxi.IAction, uint16) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800172 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500173 js, _ := json.Marshal(ofpAction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800174 logger.Debugw("parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700175 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500176 }
Don Newtone0d34a82019-11-14 10:58:06 -0500177 switch ofpAction.Type {
178 case openflow_13.OfpActionType_OFPAT_OUTPUT:
179 ofpOutputAction := ofpAction.GetOutput()
180 outputAction := ofp.NewActionOutput()
181 outputAction.Port = ofp.Port(ofpOutputAction.Port)
182 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
183 outputAction.Len = 16
184 return outputAction, 16
185 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
186 ofpPushVlanAction := ofp.NewActionPushVlan()
187 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
188 ofpPushVlanAction.Len = 8
189 return ofpPushVlanAction, 8
190 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
191 ofpPopVlanAction := ofp.NewActionPopVlan()
192 ofpPopVlanAction.Len = 8
193 return ofpPopVlanAction, 8
194 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
195 ofpActionSetField := ofpAction.GetSetField()
196 setFieldAction := ofp.NewActionSetField()
197
Jonathan Hart60c5d772020-03-30 18:28:40 -0700198 iOxm, _ := parseOxm(ofpActionSetField.GetField().GetOfbField())
Don Newtone0d34a82019-11-14 10:58:06 -0500199 setFieldAction.Field = iOxm
Don Newtonb437c6f2019-12-18 11:51:57 -0500200 setFieldAction.Len = 16
201 return setFieldAction, 16
Jonathan Hart60c5d772020-03-30 18:28:40 -0700202 case openflow_13.OfpActionType_OFPAT_GROUP:
203 ofpGroupAction := ofpAction.GetGroup()
204 groupAction := ofp.NewActionGroup()
205 groupAction.GroupId = ofpGroupAction.GroupId
206 groupAction.Len = 8
207 return groupAction, 8
Don Newtone0d34a82019-11-14 10:58:06 -0500208 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800209 if logger.V(log.WarnLevel) {
210 js, _ := json.Marshal(ofpAction)
211 logger.Warnw("parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700212 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800213 }
Don Newtone0d34a82019-11-14 10:58:06 -0500214 }
215 return nil, 0
216}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800217
218func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500219 stats := port.OfpPortStats
220 port.OfpPort.GetPortNo()
221 var entry ofp.PortStatsEntry
222 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
223 entry.SetRxPackets(stats.GetRxPackets())
224 entry.SetTxPackets(stats.GetTxPackets())
225 entry.SetRxBytes(stats.GetRxBytes())
226 entry.SetTxBytes(stats.GetTxBytes())
227 entry.SetRxDropped(stats.GetRxDropped())
228 entry.SetTxDropped(stats.GetTxDropped())
229 entry.SetRxErrors(stats.GetRxErrors())
230 entry.SetTxErrors(stats.GetTxErrors())
231 entry.SetRxFrameErr(stats.GetRxFrameErr())
232 entry.SetRxOverErr(stats.GetRxOverErr())
233 entry.SetRxCrcErr(stats.GetRxCrcErr())
234 entry.SetCollisions(stats.GetCollisions())
235 entry.SetDurationSec(stats.GetDurationSec())
236 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800237 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500238}