blob: 9e0bdee7ed6fc74fa56b9e258d654c13c084bbaf [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"
Andrea Campanella30342622020-03-05 20:48:26 +010021 "encoding/binary"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080022 "encoding/json"
Jonathan Hart828908c2020-04-15 14:23:45 -070023 ofp "github.com/opencord/goloxi/of13"
Maninder12b909f2020-10-23 14:23:36 +053024 "github.com/opencord/voltha-lib-go/v4/pkg/log"
25 "github.com/opencord/voltha-protos/v4/go/openflow_13"
26 "github.com/opencord/voltha-protos/v4/go/voltha"
Jonathan Hart60c5d772020-03-30 18:28:40 -070027 "net"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080028)
29
30var oxmMap = map[string]int32{
Don Newton7fe70f72020-02-21 13:54:11 -050031 "in_port": 0,
32 "in_phy_port": 1,
33 "metadata": 2,
34 "eth_dst": 3,
35 "eth_src": 4,
36 "eth_type": 5,
37 "vlan_vid": 6,
38 "vlan_pcp": 7,
39 "ip_dscp": 8,
40 "ip_ecn": 9,
41 "ip_proto": 10,
42 "ipv4_src": 11,
43 "ipv4_dst": 12,
44 "tcp_src": 13,
45 "tcp_dst": 14,
46 "udp_src": 15,
47 "udp_dst": 16,
48 "sctp_src": 17,
49 "sctp_dst": 18,
50 "icmpv4_type": 19,
51 "icmpv4_code": 20,
52 "arp_op": 21,
53 "arp_spa": 22,
54 "arp_tpa": 23,
55 "arp_sha": 24,
56 "arp_tha": 25,
57 "ipv6_src": 26,
58 "ipv6_dst": 27,
59 "ipv6_flabel": 28,
60 "icmpv6_type": 29,
61 "icmpv6_code": 30,
62 "ipv6_nd_target": 31,
63 "ipv6_nd_sll": 32,
64 "ipv6_nd_tll": 33,
65 "mpls_label": 34,
66 "mpls_tc": 35,
67 "mpls_bos": 36,
68 "pbb_isid": 37,
69 "tunnel_id": 38,
70 "ipv6_exthdr": 39,
71 "vlan_vid_masked": 200, //made up
David K. Bainbridge157bdab2020-01-16 14:38:05 -080072}
73
Rohan Agrawalc32d9932020-06-15 11:01:47 +000074func (ofc *OFConnection) handleFlowAdd(ctx context.Context, flowAdd *ofp.FlowAdd) {
Girish Kumar01e0c632020-08-10 16:48:56 +000075 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-add")
76 defer span.Finish()
77
David K. Bainbridge157bdab2020-01-16 14:38:05 -080078 if logger.V(log.DebugLevel) {
79 js, _ := json.Marshal(flowAdd)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000080 logger.Debugw(ctx, "handleFlowAdd called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080081 log.Fields{
82 "device-id": ofc.DeviceID,
83 "params": js})
84 }
85
David Bainbridgef8ce7d22020-04-08 12:49:41 -070086 volthaClient := ofc.VolthaClient.Get()
87 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000088 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080089 log.Fields{"device-id": ofc.DeviceID})
90 return
91 }
92
David K. Bainbridge157bdab2020-01-16 14:38:05 -080093 // Construct the match
94 var oxmList []*voltha.OfpOxmField
95 for _, oxmField := range flowAdd.Match.GetOxmList() {
96 name := oxmMap[oxmField.GetOXMName()]
97 val := oxmField.GetOXMValue()
98 field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
99 ofpOxmField := voltha.OfpOxmField{
100 OxmClass: ofp.OFPXMCOpenflowBasic,
101 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
102 }
103 switch voltha.OxmOfbFieldTypes(name) {
104 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
105 field.Value = &voltha.OfpOxmOfbField_Port{
106 Port: uint32(val.(ofp.Port)),
107 }
108 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
109 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
110 PhysicalPort: val.(uint32),
111 }
112 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
113 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
114 TableMetadata: val.(uint64),
115 }
116 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
117 field.Value = &voltha.OfpOxmOfbField_EthType{
118 EthType: uint32(val.(ofp.EthernetType)),
119 }
120 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
121 field.Value = &voltha.OfpOxmOfbField_IpProto{
122 IpProto: uint32(val.(ofp.IpPrototype)),
123 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700124 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
125 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
126 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
127 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000128 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
129 field.Value = &voltha.OfpOxmOfbField_EthDst{
130 EthDst: val.(net.HardwareAddr),
131 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800132 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
133 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
134 UdpSrc: uint32(val.(uint16)),
135 }
136 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
137 field.Value = &voltha.OfpOxmOfbField_UdpDst{
138 UdpDst: uint32(val.(uint16)),
139 }
140 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
141 field.Value = &voltha.OfpOxmOfbField_VlanVid{
142 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
143 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000144 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
145 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
146 VlanPcp: uint32(val.(uint8)),
147 }
Don Newton7fe70f72020-02-21 13:54:11 -0500148 case 200: // voltha-protos doesn't actually have a type for vlan_mask
149 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
150 field.HasMask = true
151 ofpOxmField = voltha.OfpOxmField{
152 OxmClass: ofp.OFPXMCOpenflowBasic,
153 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
154 }
155 field.Value = &voltha.OfpOxmOfbField_VlanVid{
156 VlanVid: uint32(val.(uint16)),
157 }
158 vidMask := val.(uint16)
159 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
160 VlanVidMask: uint32(vidMask),
161 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800162 }
163 oxmList = append(oxmList, &ofpOxmField)
164 }
165
166 // Construct the instructions
167 var instructions []*voltha.OfpInstruction
168 for _, ofpInstruction := range flowAdd.GetInstructions() {
169 instructionType := ofpInstruction.GetType()
170 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
171 switch instructionType {
172 case ofp.OFPITGotoTable:
173 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
174 GotoTable: &openflow_13.OfpInstructionGotoTable{
175 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
176 },
177 }
178 case ofp.OFPITWriteMetadata:
179 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
180 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
181 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
182 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
183 },
184 }
185 case ofp.OFPITWriteActions:
186 var ofpActions []*openflow_13.OfpAction
187 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
188 ofpActions = append(ofpActions, extractAction(action))
189 }
190 instruction.Data = &openflow_13.OfpInstruction_Actions{
191 Actions: &openflow_13.OfpInstructionActions{
192 Actions: ofpActions,
193 },
194 }
195 case ofp.OFPITApplyActions:
196 var ofpActions []*openflow_13.OfpAction
197 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
198 ofpActions = append(ofpActions, extractAction(action))
199 }
200 instruction.Data = &openflow_13.OfpInstruction_Actions{
201 Actions: &openflow_13.OfpInstructionActions{
202 Actions: ofpActions,
203 },
204 }
205 case ofp.OFPITMeter:
206 instruction.Data = &openflow_13.OfpInstruction_Meter{
207 Meter: &openflow_13.OfpInstructionMeter{
208 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
209 },
210 }
211 }
212 instructions = append(instructions, &instruction)
213 }
214
215 // Construct the request
216 flowUpdate := openflow_13.FlowTableUpdate{
217 Id: ofc.DeviceID,
218 FlowMod: &voltha.OfpFlowMod{
219 Cookie: flowAdd.Cookie,
220 CookieMask: flowAdd.CookieMask,
221 TableId: uint32(flowAdd.TableId),
222 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
223 IdleTimeout: uint32(flowAdd.IdleTimeout),
224 HardTimeout: uint32(flowAdd.HardTimeout),
225 Priority: uint32(flowAdd.Priority),
226 BufferId: flowAdd.BufferId,
227 OutPort: uint32(flowAdd.OutPort),
228 OutGroup: uint32(flowAdd.OutGroup),
229 Flags: uint32(flowAdd.Flags),
230 Match: &voltha.OfpMatch{
231 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
232 OxmFields: oxmList,
233 },
234
235 Instructions: instructions,
236 },
Manindere2af7e42020-12-04 11:46:26 +0530237 Xid: flowAdd.Xid,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800238 }
239 if logger.V(log.DebugLevel) {
240 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000241 logger.Debugf(ctx, "FlowAdd being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800242 log.Fields{
243 "device-id": ofc.DeviceID,
Don Newton7fe70f72020-02-21 13:54:11 -0500244 "flow-mod-object": flowUpdate,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800245 "flow-mod-request": flowUpdateJs})
246 }
Girish Kumar01e0c632020-08-10 16:48:56 +0000247 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000248 logger.Errorw(ctx, "Error calling FlowAdd ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800249 log.Fields{
250 "device-id": ofc.DeviceID,
251 "error": err})
Andrea Campanella30342622020-03-05 20:48:26 +0100252 // Report failure to controller
253 message := ofp.NewFlowModFailedErrorMsg()
254 message.SetXid(flowAdd.Xid)
255 message.SetCode(ofp.OFPFMFCBadCommand)
256 //OF 1.3
257 message.SetVersion(4)
258 bs := make([]byte, 2)
259 //OF 1.3
260 bs[0] = byte(4)
261 //Flow Mod
262 bs[1] = byte(14)
263 //Length of the message
264 length := make([]byte, 2)
265 binary.BigEndian.PutUint16(length, 56)
266 bs = append(bs, length...)
267 empty := []byte{0, 0, 0, 0}
268 bs = append(bs, empty...)
269 //Cookie of the Flow
270 cookie := make([]byte, 52)
271 binary.BigEndian.PutUint64(cookie, flowAdd.Cookie)
272 bs = append(bs, cookie...)
273 message.SetData(bs)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000274 err := ofc.SendMessage(ctx, message)
Andrea Campanella30342622020-03-05 20:48:26 +0100275 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000276 logger.Errorw(ctx, "Error reporting failure of FlowUpdate to controller",
Andrea Campanella30342622020-03-05 20:48:26 +0100277 log.Fields{
278 "device-id": ofc.DeviceID,
279 "error": err})
280 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800281 }
282}
283
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000284func (ofc *OFConnection) handleFlowMod(ctx context.Context, flowMod *ofp.FlowMod) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000285 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification")
286 defer span.Finish()
287
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800288 if logger.V(log.DebugLevel) {
289 js, _ := json.Marshal(flowMod)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000290 logger.Debugw(ctx, "handleFlowMod called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800291 log.Fields{
292 "device-id": ofc.DeviceID,
293 "flow-mod": js})
294 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000295 logger.Errorw(ctx, "handleFlowMod not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800296 log.Fields{"device-id": ofc.DeviceID})
297}
298
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000299func (ofc *OFConnection) handleFlowModStrict(ctx context.Context, flowModStrict *ofp.FlowModifyStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000300 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification-strict")
301 defer span.Finish()
302
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800303 if logger.V(log.DebugLevel) {
304 js, _ := json.Marshal(flowModStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000305 logger.Debugw(ctx, "handleFlowModStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800306 log.Fields{
307 "device-id": ofc.DeviceID,
308 "flow-mod-strict": js})
309 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000310 logger.Error(ctx, "handleFlowModStrict not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800311 log.Fields{"device-id": ofc.DeviceID})
312}
313
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000314func (ofc *OFConnection) handleFlowDelete(ctx context.Context, flowDelete *ofp.FlowDelete) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000315 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete")
316 defer span.Finish()
317
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800318 if logger.V(log.DebugLevel) {
319 js, _ := json.Marshal(flowDelete)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000320 logger.Debugw(ctx, "handleFlowDelete called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800321 log.Fields{
322 "device-id": ofc.DeviceID,
323 "flow-delete": js})
324 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000325 logger.Error(ctx, "handleFlowDelete not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800326 log.Fields{"device-id": ofc.DeviceID})
327
328}
329
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000330func (ofc *OFConnection) handleFlowDeleteStrict(ctx context.Context, flowDeleteStrict *ofp.FlowDeleteStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000331 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete-strict")
332 defer span.Finish()
333
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800334 if logger.V(log.DebugLevel) {
335 js, _ := json.Marshal(flowDeleteStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000336 logger.Debugw(ctx, "handleFlowDeleteStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800337 log.Fields{
338 "device-id": ofc.DeviceID,
339 "flow-delete-strict": js})
340 }
341
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700342 volthaClient := ofc.VolthaClient.Get()
343 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000344 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800345 log.Fields{"device-id": ofc.DeviceID})
346 return
347 }
348
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800349 // Construct match
350 var oxmList []*voltha.OfpOxmField
351 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
352 name := oxmMap[oxmField.GetOXMName()]
353 val := oxmField.GetOXMValue()
354 var ofpOxmField voltha.OfpOxmField
355 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
356 var field voltha.OfpOxmOfbField
357 field.Type = voltha.OxmOfbFieldTypes(name)
358
359 var x openflow_13.OfpOxmField_OfbField
360 x.OfbField = &field
361 ofpOxmField.Field = &x
362
363 switch voltha.OxmOfbFieldTypes(name) {
364 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
365 field.Value = &voltha.OfpOxmOfbField_Port{
366 Port: uint32(val.(ofp.Port)),
367 }
368 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
369 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
370 PhysicalPort: val.(uint32),
371 }
372 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
373 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
374 TableMetadata: val.(uint64),
375 }
376 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
377 field.Value = &voltha.OfpOxmOfbField_EthType{
378 EthType: uint32(val.(ofp.EthernetType)),
379 }
380 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
381 field.Value = &voltha.OfpOxmOfbField_IpProto{
382 IpProto: uint32(val.(ofp.IpPrototype)),
383 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700384 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
385 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
386 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
387 }
Esin Karaman082a7012020-06-23 15:47:02 +0000388 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
389 field.Value = &voltha.OfpOxmOfbField_EthDst{
390 EthDst: val.(net.HardwareAddr),
391 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800392 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
393 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
394 UdpSrc: uint32(val.(uint16)),
395 }
396 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
397 field.Value = &voltha.OfpOxmOfbField_UdpDst{
398 UdpDst: uint32(val.(uint16)),
399 }
400 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
401 field.Value = &voltha.OfpOxmOfbField_VlanVid{
402 VlanVid: uint32(val.(uint16)),
403 }
Esin Karaman082a7012020-06-23 15:47:02 +0000404 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
405 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
406 VlanPcp: uint32(val.(uint8)),
407 }
Don Newton7fe70f72020-02-21 13:54:11 -0500408 case 200: // voltha-protos doesn't actually have a type for vlan_mask
409 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
410 field.HasMask = true
411 ofpOxmField = voltha.OfpOxmField{
412 OxmClass: ofp.OFPXMCOpenflowBasic,
413 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
414 }
415 field.Value = &voltha.OfpOxmOfbField_VlanVid{
416 VlanVid: uint32(val.(uint16)),
417 }
418 vidMask := val.(uint16)
419 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
420 VlanVidMask: uint32(vidMask),
421 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800422 }
Don Newton7fe70f72020-02-21 13:54:11 -0500423
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800424 oxmList = append(oxmList, &ofpOxmField)
425 }
426
Matteo Scandolo322c3082020-06-17 14:21:26 -0700427 responseRequired := false
428
429 if flowDeleteStrict.GetFlags() == ofp.OFPFFSendFlowRem {
430 responseRequired = true
431 }
432
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800433 // Construct request
434 flowUpdate := openflow_13.FlowTableUpdate{
435 Id: ofc.DeviceID,
436 FlowMod: &voltha.OfpFlowMod{
437 Cookie: flowDeleteStrict.Cookie,
438 CookieMask: flowDeleteStrict.CookieMask,
439 TableId: uint32(flowDeleteStrict.TableId),
440 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
441 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
442 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
443 Priority: uint32(flowDeleteStrict.Priority),
444 BufferId: flowDeleteStrict.BufferId,
445 OutPort: uint32(flowDeleteStrict.OutPort),
446 OutGroup: uint32(flowDeleteStrict.OutGroup),
447 Flags: uint32(flowDeleteStrict.Flags),
448 Match: &voltha.OfpMatch{
449 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
450 OxmFields: oxmList,
451 },
452 },
Manindere2af7e42020-12-04 11:46:26 +0530453 Xid: flowDeleteStrict.Xid,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800454 }
455
456 if logger.V(log.DebugLevel) {
457 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000458 logger.Debugf(ctx, "FlowDeleteStrict being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800459 log.Fields{
460 "device-id": ofc.DeviceID,
461 "flow-update": flowUpdateJs})
462 }
Matteo Scandolo936e2df2020-10-27 14:31:36 -0700463
Girish Kumar01e0c632020-08-10 16:48:56 +0000464 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000465 logger.Errorw(ctx, "Error calling FlowDelete ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800466 log.Fields{
467 "device-id": ofc.DeviceID,
468 "error": err})
Matteo Scandolo322c3082020-06-17 14:21:26 -0700469 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800470 }
Matteo Scandolo322c3082020-06-17 14:21:26 -0700471
472 if responseRequired {
473 response := ofp.NewFlowRemoved()
474
475 response.Cookie = flowDeleteStrict.Cookie
476 response.Priority = flowDeleteStrict.Priority
477 response.Reason = ofp.OFPRRDelete
478 response.Match = flowDeleteStrict.Match
479 response.IdleTimeout = flowDeleteStrict.IdleTimeout
480 response.HardTimeout = flowDeleteStrict.HardTimeout
481 response.Xid = flowDeleteStrict.Xid
482
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000483 err := ofc.SendMessage(ctx, response)
Matteo Scandolo322c3082020-06-17 14:21:26 -0700484 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000485 logger.Errorw(ctx, "Error sending FlowRemoved to ONOS",
Matteo Scandolo322c3082020-06-17 14:21:26 -0700486 log.Fields{
487 "device-id": ofc.DeviceID,
488 "error": err})
489 }
490 }
491
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800492}