blob: 3beb3c9cb427db6d80659159c155b1600faae27d [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 {
khenaidoofcf0b8d2021-10-19 17:57:30 -040040 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040045 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040050 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040055 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040060 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
Jonathan Hart60c5d772020-03-30 18:28:40 -070061 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
khenaidoofcf0b8d2021-10-19 17:57:30 -040071 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040076 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -040081 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -0400105 case openflow_13.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
khenaidoofcf0b8d2021-10-19 17:57:30 -0400110 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000111 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
khenaidoofcf0b8d2021-10-19 17:57:30 -0400116 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000117 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
Abhilash Laxmeshwar4f990a02022-03-03 18:52:32 +0530121 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC:
122 ofpEthSrc := ofp.NewOxmEthSrc()
123 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthSrc)
124 ofpEthSrc.Value = val.EthSrc
125 return ofpEthSrc, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500126 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800127 if logger.V(log.WarnLevel) {
128 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000129 logger.Warnw(ctx, "ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700130 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800131 }
Don Newtone0d34a82019-11-14 10:58:06 -0500132 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100133 return nil, fmt.Errorf("can't-parse-oxm %+v", ofbField)
Don Newtone0d34a82019-11-14 10:58:06 -0500134}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800135
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100136func parseInstructions(ctx context.Context, ofpInstruction *openflow_13.OfpInstruction) (ofp.IInstruction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800137 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500138 js, _ := json.Marshal(ofpInstruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000139 logger.Debugw(ctx, "parseInstructions called",
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100140 log.Fields{"Instruction": js,
141 "ofp-Instruction": ofpInstruction})
Don Newton7577f072020-01-06 12:41:11 -0500142 }
Don Newtone0d34a82019-11-14 10:58:06 -0500143 instType := ofpInstruction.Type
144 data := ofpInstruction.GetData()
145 switch instType {
146 case ofp.OFPITWriteMetadata:
147 instruction := ofp.NewInstructionWriteMetadata()
Don Newtone0d34a82019-11-14 10:58:06 -0500148 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
149 instruction.Metadata = uint64(metadata.Metadata)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100150 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500151 case ofp.OFPITMeter:
152 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500153 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
154 instruction.MeterId = meter.MeterId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100155 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500156 case ofp.OFPITGotoTable:
157 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500158 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
159 instruction.TableId = uint8(gotoTable.TableId)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100160 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500161 case ofp.OFPITApplyActions:
162 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700163
Don Newtone0d34a82019-11-14 10:58:06 -0500164 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100166 action, err := parseAction(ctx, ofpAction)
167 if err == nil {
168 actions = append(actions, action)
169 } else {
170 return nil, fmt.Errorf("can't-parse-action %v", err)
171 }
Don Newtone0d34a82019-11-14 10:58:06 -0500172 }
173 instruction.Actions = actions
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(instruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000176 logger.Debugw(ctx, "parseInstructions returning",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800177 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800178 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500179 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100180 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500181 }
182 //shouldn't have reached here :<
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100183 return nil, fmt.Errorf("can't-parse-instruction %+v", ofpInstruction)
Don Newtone0d34a82019-11-14 10:58:06 -0500184}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800185
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100186func parseAction(ctx context.Context, ofpAction *openflow_13.OfpAction) (goloxi.IAction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800187 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500188 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000189 logger.Debugw(ctx, "parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700190 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500191 }
Don Newtone0d34a82019-11-14 10:58:06 -0500192 switch ofpAction.Type {
193 case openflow_13.OfpActionType_OFPAT_OUTPUT:
194 ofpOutputAction := ofpAction.GetOutput()
195 outputAction := ofp.NewActionOutput()
196 outputAction.Port = ofp.Port(ofpOutputAction.Port)
197 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100198 return outputAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500199 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
200 ofpPushVlanAction := ofp.NewActionPushVlan()
201 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100202 return ofpPushVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500203 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
204 ofpPopVlanAction := ofp.NewActionPopVlan()
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100205 return ofpPopVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500206 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
207 ofpActionSetField := ofpAction.GetSetField()
208 setFieldAction := ofp.NewActionSetField()
209
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100210 iOxm, err := parseOxm(ctx, ofpActionSetField.GetField().GetOfbField())
211 if err == nil {
212 setFieldAction.Field = iOxm
213 } else {
214 return nil, fmt.Errorf("can't-parse-oxm %v", err)
215 }
216 return setFieldAction, nil
Jonathan Hart60c5d772020-03-30 18:28:40 -0700217 case openflow_13.OfpActionType_OFPAT_GROUP:
218 ofpGroupAction := ofpAction.GetGroup()
219 groupAction := ofp.NewActionGroup()
220 groupAction.GroupId = ofpGroupAction.GroupId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100221 return groupAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500222 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800223 if logger.V(log.WarnLevel) {
224 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000225 logger.Warnw(ctx, "parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700226 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800227 }
Don Newtone0d34a82019-11-14 10:58:06 -0500228 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100229 return nil, fmt.Errorf("can't-parse-action %+v", ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500230}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800231
232func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500233 stats := port.OfpPortStats
234 port.OfpPort.GetPortNo()
235 var entry ofp.PortStatsEntry
236 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
237 entry.SetRxPackets(stats.GetRxPackets())
238 entry.SetTxPackets(stats.GetTxPackets())
239 entry.SetRxBytes(stats.GetRxBytes())
240 entry.SetTxBytes(stats.GetTxBytes())
241 entry.SetRxDropped(stats.GetRxDropped())
242 entry.SetTxDropped(stats.GetTxDropped())
243 entry.SetRxErrors(stats.GetRxErrors())
244 entry.SetTxErrors(stats.GetTxErrors())
245 entry.SetRxFrameErr(stats.GetRxFrameErr())
246 entry.SetRxOverErr(stats.GetRxOverErr())
247 entry.SetRxCrcErr(stats.GetRxCrcErr())
248 entry.SetCollisions(stats.GetCollisions())
249 entry.SetDurationSec(stats.GetDurationSec())
250 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800251 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500252}