blob: c434674bba5ed0e2c93b3d847fb17198019d480f [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"
Jonathan Hart828908c2020-04-15 14:23:45 -070024 "github.com/opencord/goloxi"
25 ofp "github.com/opencord/goloxi/of13"
Andrea Campanella18448bc2021-07-08 18:47:22 +020026 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninder12b909f2020-10-23 14:23:36 +053027 "github.com/opencord/voltha-protos/v4/go/openflow_13"
28 "github.com/opencord/voltha-protos/v4/go/voltha"
Don Newtone0d34a82019-11-14 10:58:06 -050029)
30
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010031func parseOxm(ctx context.Context, ofbField *openflow_13.OfpOxmOfbField) (goloxi.IOxm, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080032 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -050033 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000034 logger.Debugw(ctx, "parseOxm called",
Jonathan Hart60c5d772020-03-30 18:28:40 -070035 log.Fields{"ofbField": js})
Don Newton7577f072020-01-06 12:41:11 -050036 }
37
Don Newtone0d34a82019-11-14 10:58:06 -050038 switch ofbField.Type {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080039 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050040 ofpInPort := ofp.NewOxmInPort()
41 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
42 ofpInPort.Value = ofp.Port(val.Port)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010043 return ofpInPort, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080044 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
Don Newtone0d34a82019-11-14 10:58:06 -050045 ofpEthType := ofp.NewOxmEthType()
46 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
47 ofpEthType.Value = ofp.EthernetType(val.EthType)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010048 return ofpEthType, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080049 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
Don Newtone0d34a82019-11-14 10:58:06 -050050 ofpInPhyPort := ofp.NewOxmInPhyPort()
51 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
52 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010053 return ofpInPhyPort, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080054 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
Don Newtone0d34a82019-11-14 10:58:06 -050055 ofpIpProto := ofp.NewOxmIpProto()
56 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
57 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010058 return ofpIpProto, nil
Jonathan Hart60c5d772020-03-30 18:28:40 -070059 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
60 ofpIpv4Dst := ofp.NewOxmIpv4Dst()
61 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Ipv4Dst)
62 buf := new(bytes.Buffer)
63 err := binary.Write(buf, binary.BigEndian, val.Ipv4Dst)
64 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000065 logger.Errorw(ctx, "error writing ipv4 address %v",
Jonathan Hart60c5d772020-03-30 18:28:40 -070066 log.Fields{"error": err})
67 }
68 ofpIpv4Dst.Value = buf.Bytes()
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010069 return ofpIpv4Dst, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080070 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
Don Newtone0d34a82019-11-14 10:58:06 -050071 ofpUdpSrc := ofp.NewOxmUdpSrc()
72 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
73 ofpUdpSrc.Value = uint16(val.UdpSrc)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010074 return ofpUdpSrc, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080075 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
Don Newtone0d34a82019-11-14 10:58:06 -050076 ofpUdpDst := ofp.NewOxmUdpDst()
77 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
78 ofpUdpDst.Value = uint16(val.UdpDst)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010079 return ofpUdpDst, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -080080 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtone0d34a82019-11-14 10:58:06 -050081 ofpVlanVid := ofp.NewOxmVlanVid()
82 val := ofbField.GetValue()
Don Newton7fe70f72020-02-21 13:54:11 -050083 if val == nil {
Don Newtone0d34a82019-11-14 10:58:06 -050084 ofpVlanVid.Value = uint16(0)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +010085 return ofpVlanVid, nil
Don Newtone0d34a82019-11-14 10:58:06 -050086 }
Don Newton7fe70f72020-02-21 13:54:11 -050087 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
88 if ofbField.HasMask {
89 ofpVlanVidMasked := ofp.NewOxmVlanVidMasked()
90 valMask := ofbField.GetMask()
91 vlanMask := valMask.(*openflow_13.OfpOxmOfbField_VlanVidMask)
92 if vlanId.VlanVid == 4096 && vlanMask.VlanVidMask == 4096 {
93 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid)
94 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
95 } else {
96 ofpVlanVidMasked.Value = uint16(vlanId.VlanVid) | 0x1000
97 ofpVlanVidMasked.ValueMask = uint16(vlanMask.VlanVidMask)
98
99 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100100 return ofpVlanVidMasked, nil
Don Newton7fe70f72020-02-21 13:54:11 -0500101 }
102 ofpVlanVid.Value = uint16(vlanId.VlanVid) | 0x1000
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100103 return ofpVlanVid, nil
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800104 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
Don Newtone0d34a82019-11-14 10:58:06 -0500105 ofpMetadata := ofp.NewOxmMetadata()
106 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_TableMetadata)
107 ofpMetadata.Value = val.TableMetadata
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100108 return ofpMetadata, nil
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000109 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
110 ofpVlanPcp := ofp.NewOxmVlanPcp()
111 val := ofbField.GetValue()
112 vlanPcp := val.(*openflow_13.OfpOxmOfbField_VlanPcp)
113 ofpVlanPcp.Value = uint8(vlanPcp.VlanPcp)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100114 return ofpVlanPcp, nil
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000115 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
116 ofpEthDst := ofp.NewOxmEthDst()
117 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthDst)
118 ofpEthDst.Value = val.EthDst
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100119 return ofpEthDst, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500120 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800121 if logger.V(log.WarnLevel) {
122 js, _ := json.Marshal(ofbField)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000123 logger.Warnw(ctx, "ParseOXM Unhandled OxmField",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700124 log.Fields{"OfbField": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800125 }
Don Newtone0d34a82019-11-14 10:58:06 -0500126 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100127 return nil, fmt.Errorf("can't-parse-oxm %+v", ofbField)
Don Newtone0d34a82019-11-14 10:58:06 -0500128}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800129
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100130func parseInstructions(ctx context.Context, ofpInstruction *openflow_13.OfpInstruction) (ofp.IInstruction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800131 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500132 js, _ := json.Marshal(ofpInstruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000133 logger.Debugw(ctx, "parseInstructions called",
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100134 log.Fields{"Instruction": js,
135 "ofp-Instruction": ofpInstruction})
Don Newton7577f072020-01-06 12:41:11 -0500136 }
Don Newtone0d34a82019-11-14 10:58:06 -0500137 instType := ofpInstruction.Type
138 data := ofpInstruction.GetData()
139 switch instType {
140 case ofp.OFPITWriteMetadata:
141 instruction := ofp.NewInstructionWriteMetadata()
Don Newtone0d34a82019-11-14 10:58:06 -0500142 metadata := data.(*openflow_13.OfpInstruction_WriteMetadata).WriteMetadata
143 instruction.Metadata = uint64(metadata.Metadata)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100144 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500145 case ofp.OFPITMeter:
146 instruction := ofp.NewInstructionMeter()
Don Newtone0d34a82019-11-14 10:58:06 -0500147 meter := data.(*openflow_13.OfpInstruction_Meter).Meter
148 instruction.MeterId = meter.MeterId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100149 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500150 case ofp.OFPITGotoTable:
151 instruction := ofp.NewInstructionGotoTable()
Don Newtone0d34a82019-11-14 10:58:06 -0500152 gotoTable := data.(*openflow_13.OfpInstruction_GotoTable).GotoTable
153 instruction.TableId = uint8(gotoTable.TableId)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100154 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500155 case ofp.OFPITApplyActions:
156 instruction := ofp.NewInstructionApplyActions()
Jonathan Hart828908c2020-04-15 14:23:45 -0700157
Don Newtone0d34a82019-11-14 10:58:06 -0500158 var actions []goloxi.IAction
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800159 for _, ofpAction := range ofpInstruction.GetActions().Actions {
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100160 action, err := parseAction(ctx, ofpAction)
161 if err == nil {
162 actions = append(actions, action)
163 } else {
164 return nil, fmt.Errorf("can't-parse-action %v", err)
165 }
Don Newtone0d34a82019-11-14 10:58:06 -0500166 }
167 instruction.Actions = actions
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800168 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500169 js, _ := json.Marshal(instruction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000170 logger.Debugw(ctx, "parseInstructions returning",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800171 log.Fields{
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800172 "parsed-instruction": js})
Don Newton7577f072020-01-06 12:41:11 -0500173 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100174 return instruction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500175 }
176 //shouldn't have reached here :<
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100177 return nil, fmt.Errorf("can't-parse-instruction %+v", ofpInstruction)
Don Newtone0d34a82019-11-14 10:58:06 -0500178}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800179
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100180func parseAction(ctx context.Context, ofpAction *openflow_13.OfpAction) (goloxi.IAction, error) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800181 if logger.V(log.DebugLevel) {
Don Newton7577f072020-01-06 12:41:11 -0500182 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000183 logger.Debugw(ctx, "parseAction called",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700184 log.Fields{"action": js})
Don Newton7577f072020-01-06 12:41:11 -0500185 }
Don Newtone0d34a82019-11-14 10:58:06 -0500186 switch ofpAction.Type {
187 case openflow_13.OfpActionType_OFPAT_OUTPUT:
188 ofpOutputAction := ofpAction.GetOutput()
189 outputAction := ofp.NewActionOutput()
190 outputAction.Port = ofp.Port(ofpOutputAction.Port)
191 outputAction.MaxLen = uint16(ofpOutputAction.MaxLen)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100192 return outputAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500193 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
194 ofpPushVlanAction := ofp.NewActionPushVlan()
195 ofpPushVlanAction.Ethertype = uint16(ofpAction.GetPush().Ethertype)
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100196 return ofpPushVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500197 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
198 ofpPopVlanAction := ofp.NewActionPopVlan()
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100199 return ofpPopVlanAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500200 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
201 ofpActionSetField := ofpAction.GetSetField()
202 setFieldAction := ofp.NewActionSetField()
203
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100204 iOxm, err := parseOxm(ctx, ofpActionSetField.GetField().GetOfbField())
205 if err == nil {
206 setFieldAction.Field = iOxm
207 } else {
208 return nil, fmt.Errorf("can't-parse-oxm %v", err)
209 }
210 return setFieldAction, nil
Jonathan Hart60c5d772020-03-30 18:28:40 -0700211 case openflow_13.OfpActionType_OFPAT_GROUP:
212 ofpGroupAction := ofpAction.GetGroup()
213 groupAction := ofp.NewActionGroup()
214 groupAction.GroupId = ofpGroupAction.GroupId
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100215 return groupAction, nil
Don Newtone0d34a82019-11-14 10:58:06 -0500216 default:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800217 if logger.V(log.WarnLevel) {
218 js, _ := json.Marshal(ofpAction)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000219 logger.Warnw(ctx, "parseAction unknow action",
Jonathan Hart60c5d772020-03-30 18:28:40 -0700220 log.Fields{"action": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800221 }
Don Newtone0d34a82019-11-14 10:58:06 -0500222 }
Andrea Campanella22aa3ed2021-03-04 15:58:55 +0100223 return nil, fmt.Errorf("can't-parse-action %+v", ofpAction)
Don Newtone0d34a82019-11-14 10:58:06 -0500224}
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800225
226func parsePortStats(port *voltha.LogicalPort) *ofp.PortStatsEntry {
Don Newtone0d34a82019-11-14 10:58:06 -0500227 stats := port.OfpPortStats
228 port.OfpPort.GetPortNo()
229 var entry ofp.PortStatsEntry
230 entry.SetPortNo(ofp.Port(port.OfpPort.GetPortNo()))
231 entry.SetRxPackets(stats.GetRxPackets())
232 entry.SetTxPackets(stats.GetTxPackets())
233 entry.SetRxBytes(stats.GetRxBytes())
234 entry.SetTxBytes(stats.GetTxBytes())
235 entry.SetRxDropped(stats.GetRxDropped())
236 entry.SetTxDropped(stats.GetTxDropped())
237 entry.SetRxErrors(stats.GetRxErrors())
238 entry.SetTxErrors(stats.GetTxErrors())
239 entry.SetRxFrameErr(stats.GetRxFrameErr())
240 entry.SetRxOverErr(stats.GetRxOverErr())
241 entry.SetRxCrcErr(stats.GetRxCrcErr())
242 entry.SetCollisions(stats.GetCollisions())
243 entry.SetDurationSec(stats.GetDurationSec())
244 entry.SetDurationNsec(stats.GetDurationNsec())
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800245 return &entry
Don Newtone0d34a82019-11-14 10:58:06 -0500246}