blob: 1c8a906c18007934a32dd817468050c2ee4a5c83 [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 },
237 }
238 if logger.V(log.DebugLevel) {
239 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000240 logger.Debugf(ctx, "FlowAdd being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800241 log.Fields{
242 "device-id": ofc.DeviceID,
Don Newton7fe70f72020-02-21 13:54:11 -0500243 "flow-mod-object": flowUpdate,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800244 "flow-mod-request": flowUpdateJs})
245 }
Girish Kumar01e0c632020-08-10 16:48:56 +0000246 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000247 logger.Errorw(ctx, "Error calling FlowAdd ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800248 log.Fields{
249 "device-id": ofc.DeviceID,
250 "error": err})
Andrea Campanella30342622020-03-05 20:48:26 +0100251 // Report failure to controller
252 message := ofp.NewFlowModFailedErrorMsg()
253 message.SetXid(flowAdd.Xid)
254 message.SetCode(ofp.OFPFMFCBadCommand)
255 //OF 1.3
256 message.SetVersion(4)
257 bs := make([]byte, 2)
258 //OF 1.3
259 bs[0] = byte(4)
260 //Flow Mod
261 bs[1] = byte(14)
262 //Length of the message
263 length := make([]byte, 2)
264 binary.BigEndian.PutUint16(length, 56)
265 bs = append(bs, length...)
266 empty := []byte{0, 0, 0, 0}
267 bs = append(bs, empty...)
268 //Cookie of the Flow
269 cookie := make([]byte, 52)
270 binary.BigEndian.PutUint64(cookie, flowAdd.Cookie)
271 bs = append(bs, cookie...)
272 message.SetData(bs)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000273 err := ofc.SendMessage(ctx, message)
Andrea Campanella30342622020-03-05 20:48:26 +0100274 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000275 logger.Errorw(ctx, "Error reporting failure of FlowUpdate to controller",
Andrea Campanella30342622020-03-05 20:48:26 +0100276 log.Fields{
277 "device-id": ofc.DeviceID,
278 "error": err})
279 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800280 }
281}
282
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000283func (ofc *OFConnection) handleFlowMod(ctx context.Context, flowMod *ofp.FlowMod) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000284 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification")
285 defer span.Finish()
286
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800287 if logger.V(log.DebugLevel) {
288 js, _ := json.Marshal(flowMod)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000289 logger.Debugw(ctx, "handleFlowMod called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800290 log.Fields{
291 "device-id": ofc.DeviceID,
292 "flow-mod": js})
293 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000294 logger.Errorw(ctx, "handleFlowMod not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800295 log.Fields{"device-id": ofc.DeviceID})
296}
297
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000298func (ofc *OFConnection) handleFlowModStrict(ctx context.Context, flowModStrict *ofp.FlowModifyStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000299 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification-strict")
300 defer span.Finish()
301
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800302 if logger.V(log.DebugLevel) {
303 js, _ := json.Marshal(flowModStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000304 logger.Debugw(ctx, "handleFlowModStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800305 log.Fields{
306 "device-id": ofc.DeviceID,
307 "flow-mod-strict": js})
308 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000309 logger.Error(ctx, "handleFlowModStrict not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800310 log.Fields{"device-id": ofc.DeviceID})
311}
312
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000313func (ofc *OFConnection) handleFlowDelete(ctx context.Context, flowDelete *ofp.FlowDelete) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000314 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete")
315 defer span.Finish()
316
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800317 if logger.V(log.DebugLevel) {
318 js, _ := json.Marshal(flowDelete)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000319 logger.Debugw(ctx, "handleFlowDelete called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800320 log.Fields{
321 "device-id": ofc.DeviceID,
322 "flow-delete": js})
323 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000324 logger.Error(ctx, "handleFlowDelete not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800325 log.Fields{"device-id": ofc.DeviceID})
326
327}
328
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000329func (ofc *OFConnection) handleFlowDeleteStrict(ctx context.Context, flowDeleteStrict *ofp.FlowDeleteStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000330 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete-strict")
331 defer span.Finish()
332
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800333 if logger.V(log.DebugLevel) {
334 js, _ := json.Marshal(flowDeleteStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000335 logger.Debugw(ctx, "handleFlowDeleteStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800336 log.Fields{
337 "device-id": ofc.DeviceID,
338 "flow-delete-strict": js})
339 }
340
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700341 volthaClient := ofc.VolthaClient.Get()
342 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000343 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800344 log.Fields{"device-id": ofc.DeviceID})
345 return
346 }
347
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800348 // Construct match
349 var oxmList []*voltha.OfpOxmField
350 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
351 name := oxmMap[oxmField.GetOXMName()]
352 val := oxmField.GetOXMValue()
353 var ofpOxmField voltha.OfpOxmField
354 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
355 var field voltha.OfpOxmOfbField
356 field.Type = voltha.OxmOfbFieldTypes(name)
357
358 var x openflow_13.OfpOxmField_OfbField
359 x.OfbField = &field
360 ofpOxmField.Field = &x
361
362 switch voltha.OxmOfbFieldTypes(name) {
363 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
364 field.Value = &voltha.OfpOxmOfbField_Port{
365 Port: uint32(val.(ofp.Port)),
366 }
367 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
368 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
369 PhysicalPort: val.(uint32),
370 }
371 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
372 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
373 TableMetadata: val.(uint64),
374 }
375 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
376 field.Value = &voltha.OfpOxmOfbField_EthType{
377 EthType: uint32(val.(ofp.EthernetType)),
378 }
379 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
380 field.Value = &voltha.OfpOxmOfbField_IpProto{
381 IpProto: uint32(val.(ofp.IpPrototype)),
382 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700383 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
384 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
385 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
386 }
Esin Karaman082a7012020-06-23 15:47:02 +0000387 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
388 field.Value = &voltha.OfpOxmOfbField_EthDst{
389 EthDst: val.(net.HardwareAddr),
390 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800391 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
392 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
393 UdpSrc: uint32(val.(uint16)),
394 }
395 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
396 field.Value = &voltha.OfpOxmOfbField_UdpDst{
397 UdpDst: uint32(val.(uint16)),
398 }
399 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
400 field.Value = &voltha.OfpOxmOfbField_VlanVid{
401 VlanVid: uint32(val.(uint16)),
402 }
Esin Karaman082a7012020-06-23 15:47:02 +0000403 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
404 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
405 VlanPcp: uint32(val.(uint8)),
406 }
Don Newton7fe70f72020-02-21 13:54:11 -0500407 case 200: // voltha-protos doesn't actually have a type for vlan_mask
408 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
409 field.HasMask = true
410 ofpOxmField = voltha.OfpOxmField{
411 OxmClass: ofp.OFPXMCOpenflowBasic,
412 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
413 }
414 field.Value = &voltha.OfpOxmOfbField_VlanVid{
415 VlanVid: uint32(val.(uint16)),
416 }
417 vidMask := val.(uint16)
418 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
419 VlanVidMask: uint32(vidMask),
420 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800421 }
Don Newton7fe70f72020-02-21 13:54:11 -0500422
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800423 oxmList = append(oxmList, &ofpOxmField)
424 }
425
Matteo Scandolo322c3082020-06-17 14:21:26 -0700426 responseRequired := false
427
428 if flowDeleteStrict.GetFlags() == ofp.OFPFFSendFlowRem {
429 responseRequired = true
430 }
431
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800432 // Construct request
433 flowUpdate := openflow_13.FlowTableUpdate{
434 Id: ofc.DeviceID,
435 FlowMod: &voltha.OfpFlowMod{
436 Cookie: flowDeleteStrict.Cookie,
437 CookieMask: flowDeleteStrict.CookieMask,
438 TableId: uint32(flowDeleteStrict.TableId),
439 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
440 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
441 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
442 Priority: uint32(flowDeleteStrict.Priority),
443 BufferId: flowDeleteStrict.BufferId,
444 OutPort: uint32(flowDeleteStrict.OutPort),
445 OutGroup: uint32(flowDeleteStrict.OutGroup),
446 Flags: uint32(flowDeleteStrict.Flags),
447 Match: &voltha.OfpMatch{
448 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
449 OxmFields: oxmList,
450 },
451 },
452 }
453
454 if logger.V(log.DebugLevel) {
455 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000456 logger.Debugf(ctx, "FlowDeleteStrict being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800457 log.Fields{
458 "device-id": ofc.DeviceID,
459 "flow-update": flowUpdateJs})
460 }
Matteo Scandolo936e2df2020-10-27 14:31:36 -0700461
Girish Kumar01e0c632020-08-10 16:48:56 +0000462 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000463 logger.Errorw(ctx, "Error calling FlowDelete ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800464 log.Fields{
465 "device-id": ofc.DeviceID,
466 "error": err})
Matteo Scandolo322c3082020-06-17 14:21:26 -0700467 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800468 }
Matteo Scandolo322c3082020-06-17 14:21:26 -0700469
470 if responseRequired {
471 response := ofp.NewFlowRemoved()
472
473 response.Cookie = flowDeleteStrict.Cookie
474 response.Priority = flowDeleteStrict.Priority
475 response.Reason = ofp.OFPRRDelete
476 response.Match = flowDeleteStrict.Match
477 response.IdleTimeout = flowDeleteStrict.IdleTimeout
478 response.HardTimeout = flowDeleteStrict.HardTimeout
479 response.Xid = flowDeleteStrict.Xid
480
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000481 err := ofc.SendMessage(ctx, response)
Matteo Scandolo322c3082020-06-17 14:21:26 -0700482 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000483 logger.Errorw(ctx, "Error sending FlowRemoved to ONOS",
Matteo Scandolo322c3082020-06-17 14:21:26 -0700484 log.Fields{
485 "device-id": ofc.DeviceID,
486 "error": err})
487 }
488 }
489
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800490}