blob: d0c315af962bce4cb795294f62b0cba1c50cbbdc [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"
Rohan Agrawalc32d9932020-06-15 11:01:47 +000020 "context"
Jonathan Hart60c5d772020-03-30 18:28:40 -070021 "encoding/binary"
Don Newtone0d34a82019-11-14 10:58:06 -050022 "encoding/json"
Jonathan Hart828908c2020-04-15 14:23:45 -070023 "github.com/opencord/goloxi"
24 ofp "github.com/opencord/goloxi/of13"
Maninder12b909f2020-10-23 14:23:36 +053025 "github.com/opencord/voltha-lib-go/v4/pkg/log"
26 "github.com/opencord/voltha-protos/v4/go/openflow_13"
27 "github.com/opencord/voltha-protos/v4/go/voltha"
Don Newtone0d34a82019-11-14 10:58:06 -050028)
29
Rohan Agrawalc32d9932020-06-15 11:01:47 +000030func parseOxm(ctx context.Context, ofbField *openflow_13.OfpOxmOfbField) goloxi.IOxm {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080031 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -050032 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000033 logger.Debugw(ctx, "parseOxm called",
Jonathan Hart60c5d772020-03-30 18:28:40 -070034 log.Fields{"ofbField": js})
Don Newton7577f072020-01-06 12:41:11 -050035 }
36
Don Newtone0d34a82019-11-14 10:58:06 -050037 switch ofbField.Type {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080038 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050039 ofpInPort := ofp.NewOxmInPort()
40 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
41 ofpInPort.Value = ofp.Port(val.Port)
Jonathan Hart828908c2020-04-15 14:23:45 -070042 return ofpInPort
David K. Bainbridge157bdab2020-01-16 14:38:05 -080043 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
Don Newtone0d34a82019-11-14 10:58:06 -050044 ofpEthType := ofp.NewOxmEthType()
45 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
46 ofpEthType.Value = ofp.EthernetType(val.EthType)
Jonathan Hart828908c2020-04-15 14:23:45 -070047 return ofpEthType
David K. Bainbridge157bdab2020-01-16 14:38:05 -080048 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050049 ofpInPhyPort := ofp.NewOxmInPhyPort()
50 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
51 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
Jonathan Hart828908c2020-04-15 14:23:45 -070052 return ofpInPhyPort
David K. Bainbridge157bdab2020-01-16 14:38:05 -080053 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
Don Newtone0d34a82019-11-14 10:58:06 -050054 ofpIpProto := ofp.NewOxmIpProto()
55 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
56 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
Jonathan Hart828908c2020-04-15 14:23:45 -070057 return ofpIpProto
Jonathan Hart60c5d772020-03-30 18:28:40 -070058 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
59 ofpIpv4Dst := ofp.NewOxmIpv4Dst()
60 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Ipv4Dst)
61 buf := new(bytes.Buffer)
62 err := binary.Write(buf, binary.BigEndian, val.Ipv4Dst)
63 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000064 logger.Errorw(ctx, "error writing ipv4 address %v",
Jonathan Hart60c5d772020-03-30 18:28:40 -070065 log.Fields{"error": err})
66 }
67 ofpIpv4Dst.Value = buf.Bytes()
Jonathan Hart828908c2020-04-15 14:23:45 -070068 return ofpIpv4Dst
David K. Bainbridge157bdab2020-01-16 14:38:05 -080069 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
Don Newtone0d34a82019-11-14 10:58:06 -050070 ofpUdpSrc := ofp.NewOxmUdpSrc()
71 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
72 ofpUdpSrc.Value = uint16(val.UdpSrc)
Jonathan Hart828908c2020-04-15 14:23:45 -070073 return ofpUdpSrc
David K. Bainbridge157bdab2020-01-16 14:38:05 -080074 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
Don Newtone0d34a82019-11-14 10:58:06 -050075 ofpUdpDst := ofp.NewOxmUdpDst()
76 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
77 ofpUdpDst.Value = uint16(val.UdpDst)
Jonathan Hart828908c2020-04-15 14:23:45 -070078 return ofpUdpDst
David K. Bainbridge157bdab2020-01-16 14:38:05 -080079 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtone0d34a82019-11-14 10:58:06 -050080 ofpVlanVid := ofp.NewOxmVlanVid()
81 val := ofbField.GetValue()
Don Newton7fe70f72020-02-21 13:54:11 -050082 if val == nil {
Don Newtone0d34a82019-11-14 10:58:06 -050083 ofpVlanVid.Value = uint16(0)
Jonathan Hart828908c2020-04-15 14:23:45 -070084 return ofpVlanVid
Don Newtone0d34a82019-11-14 10:58:06 -050085 }
Don Newton7fe70f72020-02-21 13:54:11 -050086 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
87 if ofbField.HasMask {
88 ofpVlanVidMasked := ofp.NewOxmVlanVidMasked()
89 valMask := ofbField.GetMask()
90 vlanMask := valMask.(*openflow_13.OfpOxmOfbField_VlanVidMask)
91 if vlanId.VlanVid == 4096 && vlanMask.VlanVidMask == 4096 {
92 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid)
93 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
94 } else {
95 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid) | 0x1000
96 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
97
98 }
Jonathan Hart828908c2020-04-15 14:23:45 -070099 return ofpVlanVidMasked
Don Newton7fe70f72020-02-21 13:54:11 -0500100 }
101 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Jonathan Hart828908c2020-04-15 14:23:45 -0700102 return ofpVlanVid
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800103 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
Don Newtone0d34a82019-11-14 10:58:06 -0500104 ofpMetadata := ofp.NewOxmMetadata()
105 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_TableMetadata)
106 ofpMetadata.Value = val.TableMetadata
Jonathan Hart828908c2020-04-15 14:23:45 -0700107 return ofpMetadata
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000108 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
109 ofpVlanPcp := ofp.NewOxmVlanPcp()
110 val := ofbField.GetValue()
111 vlanPcp := val.(*openflow_13.OfpOxmOfbField_VlanPcp)
112 ofpVlanPcp.Value = uint8(vlanPcp.VlanPcp)
113 return ofpVlanPcp
114 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
115 ofpEthDst := ofp.NewOxmEthDst()
116 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthDst)
117 ofpEthDst.Value = val.EthDst
118 return ofpEthDst
Don Newtone0d34a82019-11-14 10:58:06 -0500119 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 if logger.V(log.WarnLevel) {
121 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000122 logger.Warnw(ctx, "ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700123 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800124 }
Don Newtone0d34a82019-11-14 10:58:06 -0500125 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700126 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500127}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800128
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000129func parseInstructions(ctx context.Context, ofpInstruction *openflow_13.OfpInstruction) ofp.IInstruction {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800130 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500131 js, _ := json.Marshal(ofpInstruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000132 logger.Debugw(ctx, "parseInstructions called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700133 log.Fields{"Instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500134 }
Don Newtone0d34a82019-11-14 10:58:06 -0500135 instType := ofpInstruction.Type
136 data := ofpInstruction.GetData()
137 switch instType {
138 case ofp.OFPITWriteMetadata:
139 instruction := ofp.NewInstructionWriteMetadata()
Don Newtone0d34a82019-11-14 10:58:06 -0500140 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
141 instruction.Metadata = uint64(metadata.Metadata)
Jonathan Hart828908c2020-04-15 14:23:45 -0700142 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500143 case ofp.OFPITMeter:
144 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500145 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
146 instruction.MeterId = meter.MeterId
Jonathan Hart828908c2020-04-15 14:23:45 -0700147 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500148 case ofp.OFPITGotoTable:
149 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500150 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
151 instruction.TableId = uint8(gotoTable.TableId)
Jonathan Hart828908c2020-04-15 14:23:45 -0700152 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500153 case ofp.OFPITApplyActions:
154 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700155
Don Newtone0d34a82019-11-14 10:58:06 -0500156 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800157 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000158 action := parseAction(ctx, ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500159 actions = append(actions, action)
Don Newtone0d34a82019-11-14 10:58:06 -0500160 }
161 instruction.Actions = actions
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800162 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500163 js, _ := json.Marshal(instruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000164 logger.Debugw(ctx, "parseInstructions returning",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800166 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500167 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700168 return instruction
Don Newtone0d34a82019-11-14 10:58:06 -0500169 }
170 //shouldn't have reached here :<
Jonathan Hart828908c2020-04-15 14:23:45 -0700171 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500172}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800173
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000174func parseAction(ctx context.Context, ofpAction *openflow_13.OfpAction) goloxi.IAction {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800175 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500176 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000177 logger.Debugw(ctx, "parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700178 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500179 }
Don Newtone0d34a82019-11-14 10:58:06 -0500180 switch ofpAction.Type {
181 case openflow_13.OfpActionType_OFPAT_OUTPUT:
182 ofpOutputAction := ofpAction.GetOutput()
183 outputAction := ofp.NewActionOutput()
184 outputAction.Port = ofp.Port(ofpOutputAction.Port)
185 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Jonathan Hart828908c2020-04-15 14:23:45 -0700186 return outputAction
Don Newtone0d34a82019-11-14 10:58:06 -0500187 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
188 ofpPushVlanAction := ofp.NewActionPushVlan()
189 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Jonathan Hart828908c2020-04-15 14:23:45 -0700190 return ofpPushVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500191 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
192 ofpPopVlanAction := ofp.NewActionPopVlan()
Jonathan Hart828908c2020-04-15 14:23:45 -0700193 return ofpPopVlanAction
Don Newtone0d34a82019-11-14 10:58:06 -0500194 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
195 ofpActionSetField := ofpAction.GetSetField()
196 setFieldAction := ofp.NewActionSetField()
197
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000198 iOxm := parseOxm(ctx, ofpActionSetField.GetField().GetOfbField())
Don Newtone0d34a82019-11-14 10:58:06 -0500199 setFieldAction.Field = iOxm
Jonathan Hart828908c2020-04-15 14:23:45 -0700200 return setFieldAction
Jonathan Hart60c5d772020-03-30 18:28:40 -0700201 case openflow_13.OfpActionType_OFPAT_GROUP:
202 ofpGroupAction := ofpAction.GetGroup()
203 groupAction := ofp.NewActionGroup()
204 groupAction.GroupId = ofpGroupAction.GroupId
Jonathan Hart828908c2020-04-15 14:23:45 -0700205 return groupAction
Don Newtone0d34a82019-11-14 10:58:06 -0500206 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800207 if logger.V(log.WarnLevel) {
208 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000209 logger.Warnw(ctx, "parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700210 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800211 }
Don Newtone0d34a82019-11-14 10:58:06 -0500212 }
Jonathan Hart828908c2020-04-15 14:23:45 -0700213 return nil
Don Newtone0d34a82019-11-14 10:58:06 -0500214}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800215
216func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500217 stats := port.OfpPortStats
218 port.OfpPort.GetPortNo()
219 var entry ofp.PortStatsEntry
220 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
221 entry.SetRxPackets(stats.GetRxPackets())
222 entry.SetTxPackets(stats.GetTxPackets())
223 entry.SetRxBytes(stats.GetRxBytes())
224 entry.SetTxBytes(stats.GetTxBytes())
225 entry.SetRxDropped(stats.GetRxDropped())
226 entry.SetTxDropped(stats.GetTxDropped())
227 entry.SetRxErrors(stats.GetRxErrors())
228 entry.SetTxErrors(stats.GetTxErrors())
229 entry.SetRxFrameErr(stats.GetRxFrameErr())
230 entry.SetRxOverErr(stats.GetRxOverErr())
231 entry.SetRxCrcErr(stats.GetRxCrcErr())
232 entry.SetCollisions(stats.GetCollisions())
233 entry.SetDurationSec(stats.GetDurationSec())
234 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800235 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500236}