blob: eb6ba02a49a2d4e128f435cc2110decc8454aef8 [file] [log] [blame]
Don Newton98fd8812019-09-23 15:15:02 -04001/*
2 Copyright 2017 the original author or authors.
3
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*/
16
17package openflow
18
19import (
20 "context"
21 "encoding/json"
Don Newton7577f072020-01-06 12:41:11 -050022
23 "github.com/opencord/ofagent-go/settings"
Don Newtone0d34a82019-11-14 10:58:06 -050024
25 ofp "github.com/donNewtonAlpha/goloxi/of13"
Don Newton7577f072020-01-06 12:41:11 -050026 l "github.com/opencord/voltha-lib-go/v2/pkg/log"
Don Newtonb437c6f2019-12-18 11:51:57 -050027 "github.com/opencord/voltha-protos/v2/go/openflow_13"
28 pb "github.com/opencord/voltha-protos/v2/go/voltha"
Don Newton98fd8812019-09-23 15:15:02 -040029)
30
31var oxmMap = map[string]int32{
32 "in_port": 0,
33 "in_phy_port": 1,
34 "metadata": 2,
35 "eth_dst": 3,
36 "eth_src": 4,
37 "eth_type": 5,
38 "vlan_vid": 6,
39 "vlan_pcp": 7,
40 "ip_dscp": 8,
41 "ip_ecn": 9,
42 "ip_proto": 10,
43 "ipv4_src": 11,
44 "ipv4_dst": 12,
45 "tcp_src": 13,
46 "tcp_dst": 14,
47 "udp_src": 15,
48 "udp_dst": 16,
49 "sctp_src": 17,
50 "sctp_dst": 18,
51 "icmpv4_type": 19,
52 "icmpv4_code": 20,
53 "arp_op": 21,
54 "arp_spa": 22,
55 "arp_tpa": 23,
56 "arp_sha": 24,
57 "arp_tha": 25,
58 "ipv6_src": 26,
59 "ipv6_dst": 27,
60 "ipv6_flabel": 28,
61 "icmpv6_type": 29,
62 "icmpv6_code": 30,
63 "ipv6_nd_target": 31,
64 "ipv6_nd_sll": 32,
65 "ipv6_nd_tll": 33,
66 "mpls_label": 34,
67 "mpls_tc": 35,
68 "mpls_bos": 36,
69 "pbb_isid": 37,
70 "tunnel_id": 38,
71 "ipv6_exthdr": 39,
72}
73
Don Newton7577f072020-01-06 12:41:11 -050074func handleFlowAdd(flowAdd *ofp.FlowAdd, DeviceID string) {
75 if settings.GetDebug(DeviceID) {
76 js, _ := json.Marshal(flowAdd)
77 logger.Debugw("handleFlowAdd called", l.Fields{"DeviceID": DeviceID, "params": js})
78 }
Don Newton98fd8812019-09-23 15:15:02 -040079
80 var flowUpdate openflow_13.FlowTableUpdate
Don Newton7577f072020-01-06 12:41:11 -050081 flowUpdate.Id = DeviceID
Don Newton98fd8812019-09-23 15:15:02 -040082 var flowMod pb.OfpFlowMod
83 flowMod.Cookie = flowAdd.Cookie
84 flowMod.CookieMask = flowAdd.CookieMask
85 flowMod.TableId = uint32(flowAdd.TableId)
Don Newton7577f072020-01-06 12:41:11 -050086 flowMod.Command = pb.OfpFlowModCommand_OFPFC_ADD
Don Newton98fd8812019-09-23 15:15:02 -040087 flowMod.IdleTimeout = uint32(flowAdd.IdleTimeout)
88 flowMod.HardTimeout = uint32(flowAdd.HardTimeout)
89 flowMod.Priority = uint32(flowAdd.Priority)
90 flowMod.BufferId = flowAdd.BufferId
91 flowMod.OutPort = uint32(flowAdd.OutPort)
92 flowMod.OutGroup = uint32(flowAdd.OutGroup)
93 flowMod.Flags = uint32(flowAdd.Flags)
94 inMatch := flowAdd.Match
95 var flowMatch pb.OfpMatch
96 flowMatch.Type = pb.OfpMatchType(inMatch.GetType())
97 var oxmList []*pb.OfpOxmField
98 inOxmList := inMatch.GetOxmList()
99 for i := 0; i < len(inOxmList); i++ {
100 oxmField := inOxmList[i]
Don Newton98fd8812019-09-23 15:15:02 -0400101 name := oxmMap[oxmField.GetOXMName()]
Don Newton98fd8812019-09-23 15:15:02 -0400102 val := oxmField.GetOXMValue()
103 var ofpOxmField pb.OfpOxmField
104 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
105 var field pb.OfpOxmOfbField
Don Newton98fd8812019-09-23 15:15:02 -0400106 field.Type = pb.OxmOfbFieldTypes(name)
Don Newton98fd8812019-09-23 15:15:02 -0400107 var x openflow_13.OfpOxmField_OfbField
108 x.OfbField = &field
109 ofpOxmField.Field = &x
Don Newton98fd8812019-09-23 15:15:02 -0400110 switch pb.OxmOfbFieldTypes(name) {
111 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
112 port := val.(ofp.Port)
113 var value pb.OfpOxmOfbField_Port
114 value.Port = uint32(port)
115 field.Value = &value
116 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
117 phyPort := val.(uint32)
118 var value pb.OfpOxmOfbField_PhysicalPort
119 value.PhysicalPort = phyPort
120 field.Value = &value
121 case pb.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
122 metadata := val.(uint64)
123 var value pb.OfpOxmOfbField_TableMetadata
124 value.TableMetadata = metadata
125 field.Value = &value
126 case pb.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
127 ethType := val.(ofp.EthernetType)
128 var value pb.OfpOxmOfbField_EthType
129 value.EthType = uint32(ethType)
130 field.Value = &value
131 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
132 proto := val.(ofp.IpPrototype)
133 var value pb.OfpOxmOfbField_IpProto
134 value.IpProto = uint32(proto)
135 field.Value = &value
136 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
137 udpSrc := val.(uint16)
138 var value pb.OfpOxmOfbField_UdpSrc
139 value.UdpSrc = uint32(udpSrc)
Don Newton98fd8812019-09-23 15:15:02 -0400140 field.Value = &value
141 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
142 udpDst := val.(uint16)
143 var value pb.OfpOxmOfbField_UdpDst
144 value.UdpDst = uint32(udpDst)
145 field.Value = &value
Don Newtone0d34a82019-11-14 10:58:06 -0500146 case pb.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Don Newtonb437c6f2019-12-18 11:51:57 -0500147 vid := (val.(uint16) & 0xfff) | 0x1000
Don Newtone0d34a82019-11-14 10:58:06 -0500148 var value pb.OfpOxmOfbField_VlanVid
149 value.VlanVid = uint32(vid)
150 field.Value = &value
Don Newton98fd8812019-09-23 15:15:02 -0400151 }
152 oxmList = append(oxmList, &ofpOxmField)
153 }
154 flowMatch.OxmFields = oxmList
155 flowMod.Match = &flowMatch
156 var instructions []*pb.OfpInstruction
157 ofpInstructions := flowAdd.GetInstructions()
158 for i := 0; i < len(ofpInstructions); i++ {
159 var instruction pb.OfpInstruction
160 ofpInstruction := ofpInstructions[i]
161 instructionType := ofpInstruction.GetType()
162 instruction.Type = uint32(instructionType)
163 switch instructionType {
Don Newtone0d34a82019-11-14 10:58:06 -0500164 case ofp.OFPITGotoTable:
Don Newton98fd8812019-09-23 15:15:02 -0400165 goToTable := ofpInstruction.(ofp.IInstructionGotoTable)
166 var ofpGoToTable openflow_13.OfpInstruction_GotoTable
Don Newtone0d34a82019-11-14 10:58:06 -0500167 var oGoToTable openflow_13.OfpInstructionGotoTable
168 ofpGoToTable.GotoTable = &oGoToTable
Don Newton98fd8812019-09-23 15:15:02 -0400169 ofpGoToTable.GotoTable.TableId = uint32(goToTable.GetTableId())
170 instruction.Data = &ofpGoToTable
Don Newtone0d34a82019-11-14 10:58:06 -0500171 case ofp.OFPITWriteMetadata:
Don Newton98fd8812019-09-23 15:15:02 -0400172 writeMetaData := ofpInstruction.(ofp.IInstructionWriteMetadata)
173 var ofpWriteMetadata openflow_13.OfpInstruction_WriteMetadata
Don Newtone0d34a82019-11-14 10:58:06 -0500174 var writeMetadata openflow_13.OfpInstructionWriteMetadata
175 ofpWriteMetadata.WriteMetadata = &writeMetadata
Don Newton98fd8812019-09-23 15:15:02 -0400176 ofpWriteMetadata.WriteMetadata.Metadata = writeMetaData.GetMetadata()
177 ofpWriteMetadata.WriteMetadata.MetadataMask = writeMetaData.GetMetadataMask()
178 instruction.Data = &ofpWriteMetadata
Don Newtone0d34a82019-11-14 10:58:06 -0500179 case ofp.OFPITWriteActions:
Don Newton98fd8812019-09-23 15:15:02 -0400180 writeAction := ofpInstruction.(ofp.IInstructionWriteActions)
181 var ofpInstructionActions openflow_13.OfpInstruction_Actions
182 var ofpActions []*openflow_13.OfpAction
183 actions := writeAction.GetActions()
184 for i := 0; i < len(actions); i++ {
185 action := actions[i]
186 ofpAction := extractAction(action)
187 ofpActions = append(ofpActions, ofpAction)
188 }
189 instruction.Data = &ofpInstructionActions
Don Newtone0d34a82019-11-14 10:58:06 -0500190 case ofp.OFPITApplyActions:
Don Newton98fd8812019-09-23 15:15:02 -0400191 applyAction := ofpInstruction.(ofp.IInstructionApplyActions)
192 var ofpInstructionActions openflow_13.OfpInstruction_Actions
193 var ofpActions []*openflow_13.OfpAction
194 actions := applyAction.GetActions()
195 for i := 0; i < len(actions); i++ {
196 action := actions[i]
197 ofpAction := extractAction(action)
198 ofpActions = append(ofpActions, ofpAction)
199 }
200 var actionsHolder openflow_13.OfpInstructionActions
201 actionsHolder.Actions = ofpActions
202 ofpInstructionActions.Actions = &actionsHolder
203 instruction.Data = &ofpInstructionActions
Don Newtone0d34a82019-11-14 10:58:06 -0500204 case ofp.OFPITMeter:
205 var instructionMeter = ofpInstruction.(ofp.IInstructionMeter)
206 var meterInstruction openflow_13.OfpInstruction_Meter
207 var meter openflow_13.OfpInstructionMeter
Don Newton98fd8812019-09-23 15:15:02 -0400208
Don Newtone0d34a82019-11-14 10:58:06 -0500209 meter.MeterId = instructionMeter.GetMeterId()
210 meterInstruction.Meter = &meter
211 instruction.Data = &meterInstruction
Don Newton98fd8812019-09-23 15:15:02 -0400212 }
213 instructions = append(instructions, &instruction)
214 }
215
216 flowMod.Instructions = instructions
217 flowUpdate.FlowMod = &flowMod
218 grpcClient := *getGrpcClient()
Don Newton7577f072020-01-06 12:41:11 -0500219 if settings.GetDebug(DeviceID) {
220 flowUpdateJs, _ := json.Marshal(flowUpdate)
221 logger.Debugf("FlowUpdate being sent to Voltha", l.Fields{"DeviceID": DeviceID, "FlowModRequest": flowUpdateJs})
Don Newton98fd8812019-09-23 15:15:02 -0400222 }
Don Newton7577f072020-01-06 12:41:11 -0500223 _, err := grpcClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate)
224 if err != nil {
225 logger.Errorw("Error calling FlowUpdate ", l.Fields{"DeviceID": DeviceID, "error": err})
226 }
Don Newton98fd8812019-09-23 15:15:02 -0400227}
228
Don Newton7577f072020-01-06 12:41:11 -0500229func handleFlowMod(flowMod *ofp.FlowMod, DeviceID string) {
230 if settings.GetDebug(DeviceID) {
231 js, _ := json.Marshal(flowMod)
232 logger.Debugw("handleMod called", l.Fields{"DeviceID": DeviceID, "params": js})
233 }
234 logger.Error("handleFlowMod not implemented")
Don Newton98fd8812019-09-23 15:15:02 -0400235}
236
Don Newton7577f072020-01-06 12:41:11 -0500237func handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict, DeviceID string) {
238 if settings.GetDebug(DeviceID) {
239 js, _ := json.Marshal(flowModStrict)
240 logger.Debugw("handleFlowModStrict called", l.Fields{"DeviceID": DeviceID, "params": js})
241 }
242 logger.Error("handleFlowModStrict not implemented")
Don Newton98fd8812019-09-23 15:15:02 -0400243}
Don Newton7577f072020-01-06 12:41:11 -0500244func handleFlowDelete(flowDelete *ofp.FlowDelete, DeviceID string) {
245 if settings.GetDebug(DeviceID) {
246 js, _ := json.Marshal(flowDelete)
247 logger.Debugw("handleFlowDelete called", l.Fields{"DeviceID": DeviceID, "params": js})
248 }
249 logger.Error("handleFlowDelete not implemented")
Don Newton98fd8812019-09-23 15:15:02 -0400250
251}
Don Newton7577f072020-01-06 12:41:11 -0500252func handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict, DeviceID string) {
253 if settings.GetDebug(DeviceID) {
254 js, _ := json.Marshal(flowDeleteStrict)
255 logger.Debugw("handleFlowAdd called", l.Fields{"DeviceID": DeviceID, "params": js})
256 }
Don Newton98fd8812019-09-23 15:15:02 -0400257
Don Newtonb437c6f2019-12-18 11:51:57 -0500258 var flowUpdate openflow_13.FlowTableUpdate
Don Newton7577f072020-01-06 12:41:11 -0500259 flowUpdate.Id = DeviceID
Don Newtonb437c6f2019-12-18 11:51:57 -0500260 var flowMod pb.OfpFlowMod
261 flowMod.Cookie = flowDeleteStrict.Cookie
262 flowMod.CookieMask = flowDeleteStrict.CookieMask
263 flowMod.TableId = uint32(flowDeleteStrict.TableId)
264 flowMod.Command = pb.OfpFlowModCommand_OFPFC_DELETE_STRICT
265 flowMod.IdleTimeout = uint32(flowDeleteStrict.IdleTimeout)
266 flowMod.HardTimeout = uint32(flowDeleteStrict.HardTimeout)
267 flowMod.Priority = uint32(flowDeleteStrict.Priority)
268 flowMod.BufferId = flowDeleteStrict.BufferId
269 flowMod.OutPort = uint32(flowDeleteStrict.OutPort)
270 flowMod.OutGroup = uint32(flowDeleteStrict.OutGroup)
271 flowMod.Flags = uint32(flowDeleteStrict.Flags)
272 inMatch := flowDeleteStrict.Match
273 var flowMatch pb.OfpMatch
274 flowMatch.Type = pb.OfpMatchType(inMatch.GetType())
275 var oxmList []*pb.OfpOxmField
276 inOxmList := inMatch.GetOxmList()
277 for i := 0; i < len(inOxmList); i++ {
278 oxmField := inOxmList[i]
Don Newtonb437c6f2019-12-18 11:51:57 -0500279 name := oxmMap[oxmField.GetOXMName()]
Don Newtonb437c6f2019-12-18 11:51:57 -0500280 val := oxmField.GetOXMValue()
281 var ofpOxmField pb.OfpOxmField
282 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
283 var field pb.OfpOxmOfbField
Don Newtonb437c6f2019-12-18 11:51:57 -0500284 field.Type = pb.OxmOfbFieldTypes(name)
Don Newtonb437c6f2019-12-18 11:51:57 -0500285
286 var x openflow_13.OfpOxmField_OfbField
287 x.OfbField = &field
288 ofpOxmField.Field = &x
289
290 switch pb.OxmOfbFieldTypes(name) {
291 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
292 port := val.(ofp.Port)
293 var value pb.OfpOxmOfbField_Port
294 value.Port = uint32(port)
295 field.Value = &value
296 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
297 phyPort := val.(uint32)
298 var value pb.OfpOxmOfbField_PhysicalPort
299 value.PhysicalPort = phyPort
300 field.Value = &value
301 case pb.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
302 metadata := val.(uint64)
303 var value pb.OfpOxmOfbField_TableMetadata
304 value.TableMetadata = metadata
305 field.Value = &value
306 case pb.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
307 ethType := val.(ofp.EthernetType)
308 var value pb.OfpOxmOfbField_EthType
309 value.EthType = uint32(ethType)
310 field.Value = &value
311 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
312 proto := val.(ofp.IpPrototype)
313 var value pb.OfpOxmOfbField_IpProto
314 value.IpProto = uint32(proto)
315 field.Value = &value
316 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
317 udpSrc := val.(uint16)
318 var value pb.OfpOxmOfbField_UdpSrc
319 value.UdpSrc = uint32(udpSrc)
Don Newtonb437c6f2019-12-18 11:51:57 -0500320 field.Value = &value
321 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
322 udpDst := val.(uint16)
323 var value pb.OfpOxmOfbField_UdpDst
324 value.UdpDst = uint32(udpDst)
325 field.Value = &value
326 case pb.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
327 //vid := (val.(uint16) & 0xfff)|0x1000
328 vid := val.(uint16)
329 //vid := val.(uint16) & 0xfff
330 var value pb.OfpOxmOfbField_VlanVid
331 value.VlanVid = uint32(vid)
332 field.Value = &value
333 }
334 oxmList = append(oxmList, &ofpOxmField)
335 }
336 flowMatch.OxmFields = oxmList
337 flowMod.Match = &flowMatch
Don Newtonb437c6f2019-12-18 11:51:57 -0500338 flowUpdate.FlowMod = &flowMod
339 grpcClient := *getGrpcClient()
Don Newton7577f072020-01-06 12:41:11 -0500340 if settings.GetDebug(DeviceID) {
341 flowUpdateJs, _ := json.Marshal(flowUpdate)
342 logger.Debugf("FlowUpdate being sent to Voltha", l.Fields{"DeviceID": DeviceID, "FlowModRequest": flowUpdateJs})
Don Newtonb437c6f2019-12-18 11:51:57 -0500343 }
Don Newton7577f072020-01-06 12:41:11 -0500344 _, err := grpcClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate)
345 if err != nil {
346 logger.Errorw("Error calling FlowUpdate ", l.Fields{"DeviceID": DeviceID, "error": err})
347 }
Don Newton98fd8812019-09-23 15:15:02 -0400348}