blob: 67de283a699429c498c2fb18b0944c7d46610d6d [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"
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010023 "fmt"
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +000024
Jonathan Hart828908c2020-04-15 14:23:45 -070025 "github.com/opencord/goloxi"
26 ofp "github.com/opencord/goloxi/of13"
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +000027 "github.com/opencord/voltha-lib-go/v7/pkg/log"
28 "github.com/opencord/voltha-protos/v5/go/openflow_13"
29 "github.com/opencord/voltha-protos/v5/go/voltha"
Don Newtone0d34a82019-11-14 10:58:06 -050030)
31
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010032func parseOxm(ctx context.Context, ofbField *openflow_13.OfpOxmOfbField) (goloxi.IOxm, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080033 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -050034 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000035 logger.Debugw(ctx, "parseOxm called",
Jonathan Hart60c5d772020-03-30 18:28:40 -070036 log.Fields{"ofbField": js})
Don Newton7577f072020-01-06 12:41:11 -050037 }
38
Don Newtone0d34a82019-11-14 10:58:06 -050039 switch ofbField.Type {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080040 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050041 ofpInPort := ofp.NewOxmInPort()
42 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
43 ofpInPort.Value = ofp.Port(val.Port)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010044 return ofpInPort, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080045 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
Don Newtone0d34a82019-11-14 10:58:06 -050046 ofpEthType := ofp.NewOxmEthType()
47 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
48 ofpEthType.Value = ofp.EthernetType(val.EthType)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010049 return ofpEthType, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080050 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050051 ofpInPhyPort := ofp.NewOxmInPhyPort()
52 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
53 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010054 return ofpInPhyPort, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080055 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
Don Newtone0d34a82019-11-14 10:58:06 -050056 ofpIpProto := ofp.NewOxmIpProto()
57 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
58 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010059 return ofpIpProto, nil
Jonathan Hart60c5d772020-03-30 18:28:40 -070060 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
61 ofpIpv4Dst := ofp.NewOxmIpv4Dst()
62 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Ipv4Dst)
63 buf := new(bytes.Buffer)
64 err := binary.Write(buf, binary.BigEndian, val.Ipv4Dst)
65 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000066 logger.Errorw(ctx, "error writing ipv4 address %v",
Jonathan Hart60c5d772020-03-30 18:28:40 -070067 log.Fields{"error": err})
68 }
69 ofpIpv4Dst.Value = buf.Bytes()
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010070 return ofpIpv4Dst, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080071 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
Don Newtone0d34a82019-11-14 10:58:06 -050072 ofpUdpSrc := ofp.NewOxmUdpSrc()
73 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
74 ofpUdpSrc.Value = uint16(val.UdpSrc)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010075 return ofpUdpSrc, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080076 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
Don Newtone0d34a82019-11-14 10:58:06 -050077 ofpUdpDst := ofp.NewOxmUdpDst()
78 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
79 ofpUdpDst.Value = uint16(val.UdpDst)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010080 return ofpUdpDst, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080081 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtone0d34a82019-11-14 10:58:06 -050082 ofpVlanVid := ofp.NewOxmVlanVid()
83 val := ofbField.GetValue()
Don Newton7fe70f72020-02-21 13:54:11 -050084 if val == nil {
Don Newtone0d34a82019-11-14 10:58:06 -050085 ofpVlanVid.Value = uint16(0)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010086 return ofpVlanVid, nil
Don Newtone0d34a82019-11-14 10:58:06 -050087 }
Don Newton7fe70f72020-02-21 13:54:11 -050088 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
89 if ofbField.HasMask {
90 ofpVlanVidMasked := ofp.NewOxmVlanVidMasked()
91 valMask := ofbField.GetMask()
92 vlanMask := valMask.(*openflow_13.OfpOxmOfbField_VlanVidMask)
93 if vlanId.VlanVid == 4096 && vlanMask.VlanVidMask == 4096 {
94 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid)
95 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
96 } else {
97 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid) | 0x1000
98 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
99
100 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100101 return ofpVlanVidMasked, nil
Don Newton7fe70f72020-02-21 13:54:11 -0500102 }
103 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100104 return ofpVlanVid, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800105 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
Don Newtone0d34a82019-11-14 10:58:06 -0500106 ofpMetadata := ofp.NewOxmMetadata()
107 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_TableMetadata)
108 ofpMetadata.Value = val.TableMetadata
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100109 return ofpMetadata, nil
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000110 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
111 ofpVlanPcp := ofp.NewOxmVlanPcp()
112 val := ofbField.GetValue()
113 vlanPcp := val.(*openflow_13.OfpOxmOfbField_VlanPcp)
114 ofpVlanPcp.Value = uint8(vlanPcp.VlanPcp)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100115 return ofpVlanPcp, nil
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000116 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
117 ofpEthDst := ofp.NewOxmEthDst()
118 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthDst)
119 ofpEthDst.Value = val.EthDst
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100120 return ofpEthDst, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500121 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800122 if logger.V(log.WarnLevel) {
123 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000124 logger.Warnw(ctx, "ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700125 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800126 }
Don Newtone0d34a82019-11-14 10:58:06 -0500127 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100128 return nil, fmt.Errorf("can't-parse-oxm %+v", ofbField)
Don Newtone0d34a82019-11-14 10:58:06 -0500129}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800130
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100131func parseInstructions(ctx context.Context, ofpInstruction *openflow_13.OfpInstruction) (ofp.IInstruction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800132 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500133 js, _ := json.Marshal(ofpInstruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000134 logger.Debugw(ctx, "parseInstructions called",
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100135 log.Fields{"Instruction": js,
136 "ofp-Instruction": ofpInstruction})
Don Newton7577f072020-01-06 12:41:11 -0500137 }
Don Newtone0d34a82019-11-14 10:58:06 -0500138 instType := ofpInstruction.Type
139 data := ofpInstruction.GetData()
140 switch instType {
141 case ofp.OFPITWriteMetadata:
142 instruction := ofp.NewInstructionWriteMetadata()
Don Newtone0d34a82019-11-14 10:58:06 -0500143 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
144 instruction.Metadata = uint64(metadata.Metadata)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100145 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500146 case ofp.OFPITMeter:
147 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500148 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
149 instruction.MeterId = meter.MeterId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100150 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500151 case ofp.OFPITGotoTable:
152 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500153 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
154 instruction.TableId = uint8(gotoTable.TableId)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100155 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500156 case ofp.OFPITApplyActions:
157 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700158
Don Newtone0d34a82019-11-14 10:58:06 -0500159 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800160 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100161 action, err := parseAction(ctx, ofpAction)
162 if err == nil {
163 actions = append(actions, action)
164 } else {
165 return nil, fmt.Errorf("can't-parse-action %v", err)
166 }
Don Newtone0d34a82019-11-14 10:58:06 -0500167 }
168 instruction.Actions = actions
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800169 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500170 js, _ := json.Marshal(instruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000171 logger.Debugw(ctx, "parseInstructions returning",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800172 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800173 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500174 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100175 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500176 }
177 //shouldn't have reached here :<
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100178 return nil, fmt.Errorf("can't-parse-instruction %+v", ofpInstruction)
Don Newtone0d34a82019-11-14 10:58:06 -0500179}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800180
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100181func parseAction(ctx context.Context, ofpAction *openflow_13.OfpAction) (goloxi.IAction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800182 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500183 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000184 logger.Debugw(ctx, "parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700185 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500186 }
Don Newtone0d34a82019-11-14 10:58:06 -0500187 switch ofpAction.Type {
188 case openflow_13.OfpActionType_OFPAT_OUTPUT:
189 ofpOutputAction := ofpAction.GetOutput()
190 outputAction := ofp.NewActionOutput()
191 outputAction.Port = ofp.Port(ofpOutputAction.Port)
192 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100193 return outputAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500194 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
195 ofpPushVlanAction := ofp.NewActionPushVlan()
196 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100197 return ofpPushVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500198 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
199 ofpPopVlanAction := ofp.NewActionPopVlan()
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100200 return ofpPopVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500201 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
202 ofpActionSetField := ofpAction.GetSetField()
203 setFieldAction := ofp.NewActionSetField()
204
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100205 iOxm, err := parseOxm(ctx, ofpActionSetField.GetField().GetOfbField())
206 if err == nil {
207 setFieldAction.Field = iOxm
208 } else {
209 return nil, fmt.Errorf("can't-parse-oxm %v", err)
210 }
211 return setFieldAction, nil
Jonathan Hart60c5d772020-03-30 18:28:40 -0700212 case openflow_13.OfpActionType_OFPAT_GROUP:
213 ofpGroupAction := ofpAction.GetGroup()
214 groupAction := ofp.NewActionGroup()
215 groupAction.GroupId = ofpGroupAction.GroupId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100216 return groupAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500217 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800218 if logger.V(log.WarnLevel) {
219 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000220 logger.Warnw(ctx, "parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700221 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800222 }
Don Newtone0d34a82019-11-14 10:58:06 -0500223 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100224 return nil, fmt.Errorf("can't-parse-action %+v", ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500225}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800226
227func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500228 stats := port.OfpPortStats
229 port.OfpPort.GetPortNo()
230 var entry ofp.PortStatsEntry
231 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
232 entry.SetRxPackets(stats.GetRxPackets())
233 entry.SetTxPackets(stats.GetTxPackets())
234 entry.SetRxBytes(stats.GetRxBytes())
235 entry.SetTxBytes(stats.GetTxBytes())
236 entry.SetRxDropped(stats.GetRxDropped())
237 entry.SetTxDropped(stats.GetTxDropped())
238 entry.SetRxErrors(stats.GetRxErrors())
239 entry.SetTxErrors(stats.GetTxErrors())
240 entry.SetRxFrameErr(stats.GetRxFrameErr())
241 entry.SetRxOverErr(stats.GetRxOverErr())
242 entry.SetRxCrcErr(stats.GetRxCrcErr())
243 entry.SetCollisions(stats.GetCollisions())
244 entry.SetDurationSec(stats.GetDurationSec())
245 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800246 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500247}