blob: b9e4e29cc3bc6d45506b10f6fb7780b453a0c79b [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
Don Newtone0d34a82019-11-14 10:58:06 -0500107 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 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700114 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500115}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800116
Jonathan Hart828908c2020-04-15 14:23:45 -0700117func parseInstructions(ofpInstruction *openflow_13.OfpInstruction) ofp.IInstruction {
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()
Don Newtone0d34a82019-11-14 10:58:06 -0500128 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
129 instruction.Metadata = uint64(metadata.Metadata)
Jonathan Hart828908c2020-04-15 14:23:45 -0700130 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500131 case ofp.OFPITMeter:
132 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500133 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
134 instruction.MeterId = meter.MeterId
Jonathan Hart828908c2020-04-15 14:23:45 -0700135 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500136 case ofp.OFPITGotoTable:
137 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500138 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
139 instruction.TableId = uint8(gotoTable.TableId)
Jonathan Hart828908c2020-04-15 14:23:45 -0700140 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500141 case ofp.OFPITApplyActions:
142 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700143
Don Newtone0d34a82019-11-14 10:58:06 -0500144 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800145 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Jonathan Hart828908c2020-04-15 14:23:45 -0700146 action := parseAction(ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500147 actions = append(actions, action)
Don Newtone0d34a82019-11-14 10:58:06 -0500148 }
149 instruction.Actions = actions
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800150 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500151 js, _ := json.Marshal(instruction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800152 logger.Debugw("parseInstructions returning",
153 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800154 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500155 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700156 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500157 }
158 //shouldn't have reached here :<
Jonathan Hart828908c2020-04-15 14:23:45 -0700159 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500160}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800161
Jonathan Hart828908c2020-04-15 14:23:45 -0700162func parseAction(ofpAction *openflow_13.OfpAction) goloxi.IAction {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800163 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500164 js, _ := json.Marshal(ofpAction)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165 logger.Debugw("parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700166 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500167 }
Don Newtone0d34a82019-11-14 10:58:06 -0500168 switch ofpAction.Type {
169 case openflow_13.OfpActionType_OFPAT_OUTPUT:
170 ofpOutputAction := ofpAction.GetOutput()
171 outputAction := ofp.NewActionOutput()
172 outputAction.Port = ofp.Port(ofpOutputAction.Port)
173 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Jonathan Hart828908c2020-04-15 14:23:45 -0700174 return outputAction
Don Newtone0d34a82019-11-14 10:58:06 -0500175 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
176 ofpPushVlanAction := ofp.NewActionPushVlan()
177 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Jonathan Hart828908c2020-04-15 14:23:45 -0700178 return ofpPushVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500179 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
180 ofpPopVlanAction := ofp.NewActionPopVlan()
Jonathan Hart828908c2020-04-15 14:23:45 -0700181 return ofpPopVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500182 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
183 ofpActionSetField := ofpAction.GetSetField()
184 setFieldAction := ofp.NewActionSetField()
185
Jonathan Hart828908c2020-04-15 14:23:45 -0700186 iOxm := parseOxm(ofpActionSetField.GetField().GetOfbField())
Don Newtone0d34a82019-11-14 10:58:06 -0500187 setFieldAction.Field = iOxm
Jonathan Hart828908c2020-04-15 14:23:45 -0700188 return setFieldAction
Jonathan Hart60c5d772020-03-30 18:28:40 -0700189 case openflow_13.OfpActionType_OFPAT_GROUP:
190 ofpGroupAction := ofpAction.GetGroup()
191 groupAction := ofp.NewActionGroup()
192 groupAction.GroupId = ofpGroupAction.GroupId
Jonathan Hart828908c2020-04-15 14:23:45 -0700193 return groupAction
Don Newtone0d34a82019-11-14 10:58:06 -0500194 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800195 if logger.V(log.WarnLevel) {
196 js, _ := json.Marshal(ofpAction)
197 logger.Warnw("parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700198 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800199 }
Don Newtone0d34a82019-11-14 10:58:06 -0500200 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700201 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500202}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800203
204func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500205 stats := port.OfpPortStats
206 port.OfpPort.GetPortNo()
207 var entry ofp.PortStatsEntry
208 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
209 entry.SetRxPackets(stats.GetRxPackets())
210 entry.SetTxPackets(stats.GetTxPackets())
211 entry.SetRxBytes(stats.GetRxBytes())
212 entry.SetTxBytes(stats.GetTxBytes())
213 entry.SetRxDropped(stats.GetRxDropped())
214 entry.SetTxDropped(stats.GetTxDropped())
215 entry.SetRxErrors(stats.GetRxErrors())
216 entry.SetTxErrors(stats.GetTxErrors())
217 entry.SetRxFrameErr(stats.GetRxFrameErr())
218 entry.SetRxOverErr(stats.GetRxOverErr())
219 entry.SetRxCrcErr(stats.GetRxCrcErr())
220 entry.SetCollisions(stats.GetCollisions())
221 entry.SetDurationSec(stats.GetDurationSec())
222 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800223 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500224}