blob: 18390d16e83f510b51d479850cc06fa4414297ac [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
80 // Construct the match
81 var oxmList []*voltha.OfpOxmField
82 for _, oxmField := range flowAdd.Match.GetOxmList() {
83 name := oxmMap[oxmField.GetOXMName()]
84 val := oxmField.GetOXMValue()
85 field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
86 ofpOxmField := voltha.OfpOxmField{
87 OxmClass: ofp.OFPXMCOpenflowBasic,
88 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
89 }
90 switch voltha.OxmOfbFieldTypes(name) {
91 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
92 field.Value = &voltha.OfpOxmOfbField_Port{
93 Port: uint32(val.(ofp.Port)),
94 }
95 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
96 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
97 PhysicalPort: val.(uint32),
98 }
99 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
100 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
101 TableMetadata: val.(uint64),
102 }
103 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
104 field.Value = &voltha.OfpOxmOfbField_EthType{
105 EthType: uint32(val.(ofp.EthernetType)),
106 }
107 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
108 field.Value = &voltha.OfpOxmOfbField_IpProto{
109 IpProto: uint32(val.(ofp.IpPrototype)),
110 }
111 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
112 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
113 UdpSrc: uint32(val.(uint16)),
114 }
115 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
116 field.Value = &voltha.OfpOxmOfbField_UdpDst{
117 UdpDst: uint32(val.(uint16)),
118 }
119 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
120 field.Value = &voltha.OfpOxmOfbField_VlanVid{
121 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
122 }
123 }
124 oxmList = append(oxmList, &ofpOxmField)
125 }
126
127 // Construct the instructions
128 var instructions []*voltha.OfpInstruction
129 for _, ofpInstruction := range flowAdd.GetInstructions() {
130 instructionType := ofpInstruction.GetType()
131 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
132 switch instructionType {
133 case ofp.OFPITGotoTable:
134 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
135 GotoTable: &openflow_13.OfpInstructionGotoTable{
136 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
137 },
138 }
139 case ofp.OFPITWriteMetadata:
140 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
141 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
142 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
143 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
144 },
145 }
146 case ofp.OFPITWriteActions:
147 var ofpActions []*openflow_13.OfpAction
148 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
149 ofpActions = append(ofpActions, extractAction(action))
150 }
151 instruction.Data = &openflow_13.OfpInstruction_Actions{
152 Actions: &openflow_13.OfpInstructionActions{
153 Actions: ofpActions,
154 },
155 }
156 case ofp.OFPITApplyActions:
157 var ofpActions []*openflow_13.OfpAction
158 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
159 ofpActions = append(ofpActions, extractAction(action))
160 }
161 instruction.Data = &openflow_13.OfpInstruction_Actions{
162 Actions: &openflow_13.OfpInstructionActions{
163 Actions: ofpActions,
164 },
165 }
166 case ofp.OFPITMeter:
167 instruction.Data = &openflow_13.OfpInstruction_Meter{
168 Meter: &openflow_13.OfpInstructionMeter{
169 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
170 },
171 }
172 }
173 instructions = append(instructions, &instruction)
174 }
175
176 // Construct the request
177 flowUpdate := openflow_13.FlowTableUpdate{
178 Id: ofc.DeviceID,
179 FlowMod: &voltha.OfpFlowMod{
180 Cookie: flowAdd.Cookie,
181 CookieMask: flowAdd.CookieMask,
182 TableId: uint32(flowAdd.TableId),
183 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
184 IdleTimeout: uint32(flowAdd.IdleTimeout),
185 HardTimeout: uint32(flowAdd.HardTimeout),
186 Priority: uint32(flowAdd.Priority),
187 BufferId: flowAdd.BufferId,
188 OutPort: uint32(flowAdd.OutPort),
189 OutGroup: uint32(flowAdd.OutGroup),
190 Flags: uint32(flowAdd.Flags),
191 Match: &voltha.OfpMatch{
192 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
193 OxmFields: oxmList,
194 },
195
196 Instructions: instructions,
197 },
198 }
199 if logger.V(log.DebugLevel) {
200 flowUpdateJs, _ := json.Marshal(flowUpdate)
201 logger.Debugf("FlowUpdate being sent to Voltha",
202 log.Fields{
203 "device-id": ofc.DeviceID,
204 "flow-mod-request": flowUpdateJs})
205 }
206 if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
207 logger.Errorw("Error calling FlowUpdate ",
208 log.Fields{
209 "device-id": ofc.DeviceID,
210 "error": err})
211 }
212}
213
214func (ofc *OFClient) handleFlowMod(flowMod *ofp.FlowMod) {
215 if logger.V(log.DebugLevel) {
216 js, _ := json.Marshal(flowMod)
217 logger.Debugw("handleMod called",
218 log.Fields{
219 "device-id": ofc.DeviceID,
220 "flow-mod": js})
221 }
222 logger.Errorw("handleFlowMod not implemented",
223 log.Fields{"device-id": ofc.DeviceID})
224}
225
226func (ofc *OFClient) handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict) {
227 if logger.V(log.DebugLevel) {
228 js, _ := json.Marshal(flowModStrict)
229 logger.Debugw("handleFlowModStrict called",
230 log.Fields{
231 "device-id": ofc.DeviceID,
232 "flow-mod-strict": js})
233 }
234 logger.Error("handleFlowModStrict not implemented",
235 log.Fields{"device-id": ofc.DeviceID})
236}
237
238func (ofc *OFClient) handleFlowDelete(flowDelete *ofp.FlowDelete) {
239 if logger.V(log.DebugLevel) {
240 js, _ := json.Marshal(flowDelete)
241 logger.Debugw("handleFlowDelete called",
242 log.Fields{
243 "device-id": ofc.DeviceID,
244 "flow-delete": js})
245 }
246 logger.Error("handleFlowDelete not implemented",
247 log.Fields{"device-id": ofc.DeviceID})
248
249}
250
251func (ofc *OFClient) handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict) {
252 if logger.V(log.DebugLevel) {
253 js, _ := json.Marshal(flowDeleteStrict)
254 logger.Debugw("handleFlowAdd called",
255 log.Fields{
256 "device-id": ofc.DeviceID,
257 "flow-delete-strict": js})
258 }
259
260 // Construct match
261 var oxmList []*voltha.OfpOxmField
262 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
263 name := oxmMap[oxmField.GetOXMName()]
264 val := oxmField.GetOXMValue()
265 var ofpOxmField voltha.OfpOxmField
266 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
267 var field voltha.OfpOxmOfbField
268 field.Type = voltha.OxmOfbFieldTypes(name)
269
270 var x openflow_13.OfpOxmField_OfbField
271 x.OfbField = &field
272 ofpOxmField.Field = &x
273
274 switch voltha.OxmOfbFieldTypes(name) {
275 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
276 field.Value = &voltha.OfpOxmOfbField_Port{
277 Port: uint32(val.(ofp.Port)),
278 }
279 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
280 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
281 PhysicalPort: val.(uint32),
282 }
283 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
284 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
285 TableMetadata: val.(uint64),
286 }
287 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
288 field.Value = &voltha.OfpOxmOfbField_EthType{
289 EthType: uint32(val.(ofp.EthernetType)),
290 }
291 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
292 field.Value = &voltha.OfpOxmOfbField_IpProto{
293 IpProto: uint32(val.(ofp.IpPrototype)),
294 }
295 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
296 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
297 UdpSrc: uint32(val.(uint16)),
298 }
299 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
300 field.Value = &voltha.OfpOxmOfbField_UdpDst{
301 UdpDst: uint32(val.(uint16)),
302 }
303 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
304 field.Value = &voltha.OfpOxmOfbField_VlanVid{
305 VlanVid: uint32(val.(uint16)),
306 }
307 }
308 oxmList = append(oxmList, &ofpOxmField)
309 }
310
311 // Construct request
312 flowUpdate := openflow_13.FlowTableUpdate{
313 Id: ofc.DeviceID,
314 FlowMod: &voltha.OfpFlowMod{
315 Cookie: flowDeleteStrict.Cookie,
316 CookieMask: flowDeleteStrict.CookieMask,
317 TableId: uint32(flowDeleteStrict.TableId),
318 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
319 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
320 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
321 Priority: uint32(flowDeleteStrict.Priority),
322 BufferId: flowDeleteStrict.BufferId,
323 OutPort: uint32(flowDeleteStrict.OutPort),
324 OutGroup: uint32(flowDeleteStrict.OutGroup),
325 Flags: uint32(flowDeleteStrict.Flags),
326 Match: &voltha.OfpMatch{
327 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
328 OxmFields: oxmList,
329 },
330 },
331 }
332
333 if logger.V(log.DebugLevel) {
334 flowUpdateJs, _ := json.Marshal(flowUpdate)
335 logger.Debugf("FlowUpdate being sent to Voltha",
336 log.Fields{
337 "device-id": ofc.DeviceID,
338 "flow-update": flowUpdateJs})
339 }
340 if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
341 logger.Errorw("Error calling FlowUpdate ",
342 log.Fields{
343 "device-id": ofc.DeviceID,
344 "error": err})
345 }
346}