blob: 9967d9bdde07c9ecd311f4b863d2cc6d52535c17 [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"
Jonathan Hart828908c2020-04-15 14:23:45 -070022 "github.com/opencord/goloxi"
23 ofp "github.com/opencord/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 Hart828908c2020-04-15 14:23:45 -070029func parseOxm(ofbField *openflow_13.OfpOxmOfbField) goloxi.IOxm {
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070041 return ofpInPort
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070046 return ofpEthType
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070051 return ofpInPhyPort
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070056 return ofpIpProto
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()
Jonathan Hart828908c2020-04-15 14:23:45 -070067 return ofpIpv4Dst
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070072 return ofpUdpSrc
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070077 return ofpUdpDst
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)
Jonathan Hart828908c2020-04-15 14:23:45 -070083 return ofpVlanVid
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 }
Jonathan Hart828908c2020-04-15 14:23:45 -070098 return ofpVlanVidMasked
Don Newton7fe70f72020-02-21 13:54:11 -050099 }
100 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Jonathan Hart828908c2020-04-15 14:23:45 -0700101 return ofpVlanVid
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
Jonathan Hart828908c2020-04-15 14:23:45 -0700106 return ofpMetadata
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000107 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
108 ofpVlanPcp := ofp.NewOxmVlanPcp()
109 val := ofbField.GetValue()
110 vlanPcp := val.(*openflow_13.OfpOxmOfbField_VlanPcp)
111 ofpVlanPcp.Value = uint8(vlanPcp.VlanPcp)
112 return ofpVlanPcp
113 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
114 ofpEthDst := ofp.NewOxmEthDst()
115 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthDst)
116 ofpEthDst.Value = val.EthDst
117 return ofpEthDst
Don Newtone0d34a82019-11-14 10:58:06 -0500118 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800119 if logger.V(log.WarnLevel) {
120 js, _ := json.Marshal(ofbField)
121 logger.Warnw("ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700122 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800123 }
Don Newtone0d34a82019-11-14 10:58:06 -0500124 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700125 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500126}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800127
Jonathan Hart828908c2020-04-15 14:23:45 -0700128func parseInstructions(ofpInstruction *openflow_13.OfpInstruction) ofp.IInstruction {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800129 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500130 js, _ := json.Marshal(ofpInstruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800131 logger.Debugw("parseInstructions called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700132 log.Fields{"Instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500133 }
Don Newtone0d34a82019-11-14 10:58:06 -0500134 instType := ofpInstruction.Type
135 data := ofpInstruction.GetData()
136 switch instType {
137 case ofp.OFPITWriteMetadata:
138 instruction := ofp.NewInstructionWriteMetadata()
Don Newtone0d34a82019-11-14 10:58:06 -0500139 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
140 instruction.Metadata = uint64(metadata.Metadata)
Jonathan Hart828908c2020-04-15 14:23:45 -0700141 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500142 case ofp.OFPITMeter:
143 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500144 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
145 instruction.MeterId = meter.MeterId
Jonathan Hart828908c2020-04-15 14:23:45 -0700146 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500147 case ofp.OFPITGotoTable:
148 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500149 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
150 instruction.TableId = uint8(gotoTable.TableId)
Jonathan Hart828908c2020-04-15 14:23:45 -0700151 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500152 case ofp.OFPITApplyActions:
153 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700154
Don Newtone0d34a82019-11-14 10:58:06 -0500155 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800156 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Jonathan Hart828908c2020-04-15 14:23:45 -0700157 action := parseAction(ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500158 actions = append(actions, action)
Don Newtone0d34a82019-11-14 10:58:06 -0500159 }
160 instruction.Actions = actions
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800161 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500162 js, _ := json.Marshal(instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800163 logger.Debugw("parseInstructions returning",
164 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500166 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700167 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500168 }
169 //shouldn't have reached here :<
Jonathan Hart828908c2020-04-15 14:23:45 -0700170 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500171}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800172
Jonathan Hart828908c2020-04-15 14:23:45 -0700173func parseAction(ofpAction *openflow_13.OfpAction) goloxi.IAction {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800174 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500175 js, _ := json.Marshal(ofpAction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800176 logger.Debugw("parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700177 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500178 }
Don Newtone0d34a82019-11-14 10:58:06 -0500179 switch ofpAction.Type {
180 case openflow_13.OfpActionType_OFPAT_OUTPUT:
181 ofpOutputAction := ofpAction.GetOutput()
182 outputAction := ofp.NewActionOutput()
183 outputAction.Port = ofp.Port(ofpOutputAction.Port)
184 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Jonathan Hart828908c2020-04-15 14:23:45 -0700185 return outputAction
Don Newtone0d34a82019-11-14 10:58:06 -0500186 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
187 ofpPushVlanAction := ofp.NewActionPushVlan()
188 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Jonathan Hart828908c2020-04-15 14:23:45 -0700189 return ofpPushVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500190 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
191 ofpPopVlanAction := ofp.NewActionPopVlan()
Jonathan Hart828908c2020-04-15 14:23:45 -0700192 return ofpPopVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500193 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
194 ofpActionSetField := ofpAction.GetSetField()
195 setFieldAction := ofp.NewActionSetField()
196
Jonathan Hart828908c2020-04-15 14:23:45 -0700197 iOxm := parseOxm(ofpActionSetField.GetField().GetOfbField())
Don Newtone0d34a82019-11-14 10:58:06 -0500198 setFieldAction.Field = iOxm
Jonathan Hart828908c2020-04-15 14:23:45 -0700199 return setFieldAction
Jonathan Hart60c5d772020-03-30 18:28:40 -0700200 case openflow_13.OfpActionType_OFPAT_GROUP:
201 ofpGroupAction := ofpAction.GetGroup()
202 groupAction := ofp.NewActionGroup()
203 groupAction.GroupId = ofpGroupAction.GroupId
Jonathan Hart828908c2020-04-15 14:23:45 -0700204 return groupAction
Don Newtone0d34a82019-11-14 10:58:06 -0500205 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800206 if logger.V(log.WarnLevel) {
207 js, _ := json.Marshal(ofpAction)
208 logger.Warnw("parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700209 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800210 }
Don Newtone0d34a82019-11-14 10:58:06 -0500211 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700212 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500213}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800214
215func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500216 stats := port.OfpPortStats
217 port.OfpPort.GetPortNo()
218 var entry ofp.PortStatsEntry
219 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
220 entry.SetRxPackets(stats.GetRxPackets())
221 entry.SetTxPackets(stats.GetTxPackets())
222 entry.SetRxBytes(stats.GetRxBytes())
223 entry.SetTxBytes(stats.GetTxBytes())
224 entry.SetRxDropped(stats.GetRxDropped())
225 entry.SetTxDropped(stats.GetTxDropped())
226 entry.SetRxErrors(stats.GetRxErrors())
227 entry.SetTxErrors(stats.GetTxErrors())
228 entry.SetRxFrameErr(stats.GetRxFrameErr())
229 entry.SetRxOverErr(stats.GetRxOverErr())
230 entry.SetRxCrcErr(stats.GetRxCrcErr())
231 entry.SetCollisions(stats.GetCollisions())
232 entry.SetDurationSec(stats.GetDurationSec())
233 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800234 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500235}