blob: 4ab1afc00d61a42cdd7ccccc771fdbf7831917a9 [file] [log] [blame]
David K. Bainbridge157bdab2020-01-16 14:38:05 -08001/*
2 Copyright 2020 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"
22 ofp "github.com/donNewtonAlpha/goloxi/of13"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080023 "github.com/opencord/voltha-lib-go/v3/pkg/log"
24 "github.com/opencord/voltha-protos/v3/go/openflow_13"
25 "github.com/opencord/voltha-protos/v3/go/voltha"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080026)
27
28var oxmMap = map[string]int32{
29 "in_port": 0,
30 "in_phy_port": 1,
31 "metadata": 2,
32 "eth_dst": 3,
33 "eth_src": 4,
34 "eth_type": 5,
35 "vlan_vid": 6,
36 "vlan_pcp": 7,
37 "ip_dscp": 8,
38 "ip_ecn": 9,
39 "ip_proto": 10,
40 "ipv4_src": 11,
41 "ipv4_dst": 12,
42 "tcp_src": 13,
43 "tcp_dst": 14,
44 "udp_src": 15,
45 "udp_dst": 16,
46 "sctp_src": 17,
47 "sctp_dst": 18,
48 "icmpv4_type": 19,
49 "icmpv4_code": 20,
50 "arp_op": 21,
51 "arp_spa": 22,
52 "arp_tpa": 23,
53 "arp_sha": 24,
54 "arp_tha": 25,
55 "ipv6_src": 26,
56 "ipv6_dst": 27,
57 "ipv6_flabel": 28,
58 "icmpv6_type": 29,
59 "icmpv6_code": 30,
60 "ipv6_nd_target": 31,
61 "ipv6_nd_sll": 32,
62 "ipv6_nd_tll": 33,
63 "mpls_label": 34,
64 "mpls_tc": 35,
65 "mpls_bos": 36,
66 "pbb_isid": 37,
67 "tunnel_id": 38,
68 "ipv6_exthdr": 39,
69}
70
71func (ofc *OFClient) handleFlowAdd(flowAdd *ofp.FlowAdd) {
72 if logger.V(log.DebugLevel) {
73 js, _ := json.Marshal(flowAdd)
74 logger.Debugw("handleFlowAdd called",
75 log.Fields{
76 "device-id": ofc.DeviceID,
77 "params": js})
78 }
79
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080080 if ofc.VolthaClient == nil {
81 logger.Errorw("no-voltha-connection",
82 log.Fields{"device-id": ofc.DeviceID})
83 return
84 }
85
David K. Bainbridge157bdab2020-01-16 14:38:05 -080086 // Construct the match
87 var oxmList []*voltha.OfpOxmField
88 for _, oxmField := range flowAdd.Match.GetOxmList() {
89 name := oxmMap[oxmField.GetOXMName()]
90 val := oxmField.GetOXMValue()
91 field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
92 ofpOxmField := voltha.OfpOxmField{
93 OxmClass: ofp.OFPXMCOpenflowBasic,
94 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
95 }
96 switch voltha.OxmOfbFieldTypes(name) {
97 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
98 field.Value = &voltha.OfpOxmOfbField_Port{
99 Port: uint32(val.(ofp.Port)),
100 }
101 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
102 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
103 PhysicalPort: val.(uint32),
104 }
105 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
106 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
107 TableMetadata: val.(uint64),
108 }
109 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
110 field.Value = &voltha.OfpOxmOfbField_EthType{
111 EthType: uint32(val.(ofp.EthernetType)),
112 }
113 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
114 field.Value = &voltha.OfpOxmOfbField_IpProto{
115 IpProto: uint32(val.(ofp.IpPrototype)),
116 }
117 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
118 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
119 UdpSrc: uint32(val.(uint16)),
120 }
121 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
122 field.Value = &voltha.OfpOxmOfbField_UdpDst{
123 UdpDst: uint32(val.(uint16)),
124 }
125 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
126 field.Value = &voltha.OfpOxmOfbField_VlanVid{
127 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
128 }
129 }
130 oxmList = append(oxmList, &ofpOxmField)
131 }
132
133 // Construct the instructions
134 var instructions []*voltha.OfpInstruction
135 for _, ofpInstruction := range flowAdd.GetInstructions() {
136 instructionType := ofpInstruction.GetType()
137 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
138 switch instructionType {
139 case ofp.OFPITGotoTable:
140 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
141 GotoTable: &openflow_13.OfpInstructionGotoTable{
142 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
143 },
144 }
145 case ofp.OFPITWriteMetadata:
146 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
147 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
148 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
149 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
150 },
151 }
152 case ofp.OFPITWriteActions:
153 var ofpActions []*openflow_13.OfpAction
154 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
155 ofpActions = append(ofpActions, extractAction(action))
156 }
157 instruction.Data = &openflow_13.OfpInstruction_Actions{
158 Actions: &openflow_13.OfpInstructionActions{
159 Actions: ofpActions,
160 },
161 }
162 case ofp.OFPITApplyActions:
163 var ofpActions []*openflow_13.OfpAction
164 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
165 ofpActions = append(ofpActions, extractAction(action))
166 }
167 instruction.Data = &openflow_13.OfpInstruction_Actions{
168 Actions: &openflow_13.OfpInstructionActions{
169 Actions: ofpActions,
170 },
171 }
172 case ofp.OFPITMeter:
173 instruction.Data = &openflow_13.OfpInstruction_Meter{
174 Meter: &openflow_13.OfpInstructionMeter{
175 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
176 },
177 }
178 }
179 instructions = append(instructions, &instruction)
180 }
181
182 // Construct the request
183 flowUpdate := openflow_13.FlowTableUpdate{
184 Id: ofc.DeviceID,
185 FlowMod: &voltha.OfpFlowMod{
186 Cookie: flowAdd.Cookie,
187 CookieMask: flowAdd.CookieMask,
188 TableId: uint32(flowAdd.TableId),
189 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
190 IdleTimeout: uint32(flowAdd.IdleTimeout),
191 HardTimeout: uint32(flowAdd.HardTimeout),
192 Priority: uint32(flowAdd.Priority),
193 BufferId: flowAdd.BufferId,
194 OutPort: uint32(flowAdd.OutPort),
195 OutGroup: uint32(flowAdd.OutGroup),
196 Flags: uint32(flowAdd.Flags),
197 Match: &voltha.OfpMatch{
198 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
199 OxmFields: oxmList,
200 },
201
202 Instructions: instructions,
203 },
204 }
205 if logger.V(log.DebugLevel) {
206 flowUpdateJs, _ := json.Marshal(flowUpdate)
207 logger.Debugf("FlowUpdate being sent to Voltha",
208 log.Fields{
209 "device-id": ofc.DeviceID,
210 "flow-mod-request": flowUpdateJs})
211 }
212 if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
213 logger.Errorw("Error calling FlowUpdate ",
214 log.Fields{
215 "device-id": ofc.DeviceID,
216 "error": err})
217 }
218}
219
220func (ofc *OFClient) handleFlowMod(flowMod *ofp.FlowMod) {
221 if logger.V(log.DebugLevel) {
222 js, _ := json.Marshal(flowMod)
223 logger.Debugw("handleMod called",
224 log.Fields{
225 "device-id": ofc.DeviceID,
226 "flow-mod": js})
227 }
228 logger.Errorw("handleFlowMod not implemented",
229 log.Fields{"device-id": ofc.DeviceID})
230}
231
232func (ofc *OFClient) handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict) {
233 if logger.V(log.DebugLevel) {
234 js, _ := json.Marshal(flowModStrict)
235 logger.Debugw("handleFlowModStrict called",
236 log.Fields{
237 "device-id": ofc.DeviceID,
238 "flow-mod-strict": js})
239 }
240 logger.Error("handleFlowModStrict not implemented",
241 log.Fields{"device-id": ofc.DeviceID})
242}
243
244func (ofc *OFClient) handleFlowDelete(flowDelete *ofp.FlowDelete) {
245 if logger.V(log.DebugLevel) {
246 js, _ := json.Marshal(flowDelete)
247 logger.Debugw("handleFlowDelete called",
248 log.Fields{
249 "device-id": ofc.DeviceID,
250 "flow-delete": js})
251 }
252 logger.Error("handleFlowDelete not implemented",
253 log.Fields{"device-id": ofc.DeviceID})
254
255}
256
257func (ofc *OFClient) handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict) {
258 if logger.V(log.DebugLevel) {
259 js, _ := json.Marshal(flowDeleteStrict)
260 logger.Debugw("handleFlowAdd called",
261 log.Fields{
262 "device-id": ofc.DeviceID,
263 "flow-delete-strict": js})
264 }
265
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800266 if ofc.VolthaClient == nil {
267 logger.Errorw("no-voltha-connection",
268 log.Fields{"device-id": ofc.DeviceID})
269 return
270 }
271
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800272 // Construct match
273 var oxmList []*voltha.OfpOxmField
274 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
275 name := oxmMap[oxmField.GetOXMName()]
276 val := oxmField.GetOXMValue()
277 var ofpOxmField voltha.OfpOxmField
278 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
279 var field voltha.OfpOxmOfbField
280 field.Type = voltha.OxmOfbFieldTypes(name)
281
282 var x openflow_13.OfpOxmField_OfbField
283 x.OfbField = &field
284 ofpOxmField.Field = &x
285
286 switch voltha.OxmOfbFieldTypes(name) {
287 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
288 field.Value = &voltha.OfpOxmOfbField_Port{
289 Port: uint32(val.(ofp.Port)),
290 }
291 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
292 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
293 PhysicalPort: val.(uint32),
294 }
295 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
296 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
297 TableMetadata: val.(uint64),
298 }
299 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
300 field.Value = &voltha.OfpOxmOfbField_EthType{
301 EthType: uint32(val.(ofp.EthernetType)),
302 }
303 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
304 field.Value = &voltha.OfpOxmOfbField_IpProto{
305 IpProto: uint32(val.(ofp.IpPrototype)),
306 }
307 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
308 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
309 UdpSrc: uint32(val.(uint16)),
310 }
311 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
312 field.Value = &voltha.OfpOxmOfbField_UdpDst{
313 UdpDst: uint32(val.(uint16)),
314 }
315 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
316 field.Value = &voltha.OfpOxmOfbField_VlanVid{
317 VlanVid: uint32(val.(uint16)),
318 }
319 }
320 oxmList = append(oxmList, &ofpOxmField)
321 }
322
323 // Construct request
324 flowUpdate := openflow_13.FlowTableUpdate{
325 Id: ofc.DeviceID,
326 FlowMod: &voltha.OfpFlowMod{
327 Cookie: flowDeleteStrict.Cookie,
328 CookieMask: flowDeleteStrict.CookieMask,
329 TableId: uint32(flowDeleteStrict.TableId),
330 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
331 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
332 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
333 Priority: uint32(flowDeleteStrict.Priority),
334 BufferId: flowDeleteStrict.BufferId,
335 OutPort: uint32(flowDeleteStrict.OutPort),
336 OutGroup: uint32(flowDeleteStrict.OutGroup),
337 Flags: uint32(flowDeleteStrict.Flags),
338 Match: &voltha.OfpMatch{
339 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
340 OxmFields: oxmList,
341 },
342 },
343 }
344
345 if logger.V(log.DebugLevel) {
346 flowUpdateJs, _ := json.Marshal(flowUpdate)
347 logger.Debugf("FlowUpdate being sent to Voltha",
348 log.Fields{
349 "device-id": ofc.DeviceID,
350 "flow-update": flowUpdateJs})
351 }
352 if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
353 logger.Errorw("Error calling FlowUpdate ",
354 log.Fields{
355 "device-id": ofc.DeviceID,
356 "error": err})
357 }
358}