blob: 1a47d17791ea1ef8d9e4fc0ce8b8cf0a4a1065c3 [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"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080024 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "github.com/opencord/voltha-protos/v3/go/openflow_13"
26 "github.com/opencord/voltha-protos/v3/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) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080075 if logger.V(log.DebugLevel) {
76 js, _ := json.Marshal(flowAdd)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000077 logger.Debugw(ctx, "handleFlowAdd called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080078 log.Fields{
79 "device-id": ofc.DeviceID,
80 "params": js})
81 }
82
David Bainbridgef8ce7d22020-04-08 12:49:41 -070083 volthaClient := ofc.VolthaClient.Get()
84 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000085 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080086 log.Fields{"device-id": ofc.DeviceID})
87 return
88 }
89
David K. Bainbridge157bdab2020-01-16 14:38:05 -080090 // Construct the match
91 var oxmList []*voltha.OfpOxmField
92 for _, oxmField := range flowAdd.Match.GetOxmList() {
93 name := oxmMap[oxmField.GetOXMName()]
94 val := oxmField.GetOXMValue()
95 field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
96 ofpOxmField := voltha.OfpOxmField{
97 OxmClass: ofp.OFPXMCOpenflowBasic,
98 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
99 }
100 switch voltha.OxmOfbFieldTypes(name) {
101 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
102 field.Value = &voltha.OfpOxmOfbField_Port{
103 Port: uint32(val.(ofp.Port)),
104 }
105 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
106 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
107 PhysicalPort: val.(uint32),
108 }
109 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
110 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
111 TableMetadata: val.(uint64),
112 }
113 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
114 field.Value = &voltha.OfpOxmOfbField_EthType{
115 EthType: uint32(val.(ofp.EthernetType)),
116 }
117 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
118 field.Value = &voltha.OfpOxmOfbField_IpProto{
119 IpProto: uint32(val.(ofp.IpPrototype)),
120 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700121 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
122 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
123 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
124 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000125 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
126 field.Value = &voltha.OfpOxmOfbField_EthDst{
127 EthDst: val.(net.HardwareAddr),
128 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800129 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
130 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
131 UdpSrc: uint32(val.(uint16)),
132 }
133 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
134 field.Value = &voltha.OfpOxmOfbField_UdpDst{
135 UdpDst: uint32(val.(uint16)),
136 }
137 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
138 field.Value = &voltha.OfpOxmOfbField_VlanVid{
139 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
140 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000141 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
142 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
143 VlanPcp: uint32(val.(uint8)),
144 }
Don Newton7fe70f72020-02-21 13:54:11 -0500145 case 200: // voltha-protos doesn't actually have a type for vlan_mask
146 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
147 field.HasMask = true
148 ofpOxmField = voltha.OfpOxmField{
149 OxmClass: ofp.OFPXMCOpenflowBasic,
150 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
151 }
152 field.Value = &voltha.OfpOxmOfbField_VlanVid{
153 VlanVid: uint32(val.(uint16)),
154 }
155 vidMask := val.(uint16)
156 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
157 VlanVidMask: uint32(vidMask),
158 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800159 }
160 oxmList = append(oxmList, &ofpOxmField)
161 }
162
163 // Construct the instructions
164 var instructions []*voltha.OfpInstruction
165 for _, ofpInstruction := range flowAdd.GetInstructions() {
166 instructionType := ofpInstruction.GetType()
167 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
168 switch instructionType {
169 case ofp.OFPITGotoTable:
170 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
171 GotoTable: &openflow_13.OfpInstructionGotoTable{
172 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
173 },
174 }
175 case ofp.OFPITWriteMetadata:
176 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
177 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
178 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
179 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
180 },
181 }
182 case ofp.OFPITWriteActions:
183 var ofpActions []*openflow_13.OfpAction
184 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
185 ofpActions = append(ofpActions, extractAction(action))
186 }
187 instruction.Data = &openflow_13.OfpInstruction_Actions{
188 Actions: &openflow_13.OfpInstructionActions{
189 Actions: ofpActions,
190 },
191 }
192 case ofp.OFPITApplyActions:
193 var ofpActions []*openflow_13.OfpAction
194 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
195 ofpActions = append(ofpActions, extractAction(action))
196 }
197 instruction.Data = &openflow_13.OfpInstruction_Actions{
198 Actions: &openflow_13.OfpInstructionActions{
199 Actions: ofpActions,
200 },
201 }
202 case ofp.OFPITMeter:
203 instruction.Data = &openflow_13.OfpInstruction_Meter{
204 Meter: &openflow_13.OfpInstructionMeter{
205 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
206 },
207 }
208 }
209 instructions = append(instructions, &instruction)
210 }
211
212 // Construct the request
213 flowUpdate := openflow_13.FlowTableUpdate{
214 Id: ofc.DeviceID,
215 FlowMod: &voltha.OfpFlowMod{
216 Cookie: flowAdd.Cookie,
217 CookieMask: flowAdd.CookieMask,
218 TableId: uint32(flowAdd.TableId),
219 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
220 IdleTimeout: uint32(flowAdd.IdleTimeout),
221 HardTimeout: uint32(flowAdd.HardTimeout),
222 Priority: uint32(flowAdd.Priority),
223 BufferId: flowAdd.BufferId,
224 OutPort: uint32(flowAdd.OutPort),
225 OutGroup: uint32(flowAdd.OutGroup),
226 Flags: uint32(flowAdd.Flags),
227 Match: &voltha.OfpMatch{
228 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
229 OxmFields: oxmList,
230 },
231
232 Instructions: instructions,
233 },
234 }
235 if logger.V(log.DebugLevel) {
236 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000237 logger.Debugf(ctx, "FlowAdd being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800238 log.Fields{
239 "device-id": ofc.DeviceID,
Don Newton7fe70f72020-02-21 13:54:11 -0500240 "flow-mod-object": flowUpdate,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800241 "flow-mod-request": flowUpdateJs})
242 }
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700243 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000244 logger.Errorw(ctx, "Error calling FlowAdd ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800245 log.Fields{
246 "device-id": ofc.DeviceID,
247 "error": err})
Andrea Campanella30342622020-03-05 20:48:26 +0100248 // Report failure to controller
249 message := ofp.NewFlowModFailedErrorMsg()
250 message.SetXid(flowAdd.Xid)
251 message.SetCode(ofp.OFPFMFCBadCommand)
252 //OF 1.3
253 message.SetVersion(4)
254 bs := make([]byte, 2)
255 //OF 1.3
256 bs[0] = byte(4)
257 //Flow Mod
258 bs[1] = byte(14)
259 //Length of the message
260 length := make([]byte, 2)
261 binary.BigEndian.PutUint16(length, 56)
262 bs = append(bs, length...)
263 empty := []byte{0, 0, 0, 0}
264 bs = append(bs, empty...)
265 //Cookie of the Flow
266 cookie := make([]byte, 52)
267 binary.BigEndian.PutUint64(cookie, flowAdd.Cookie)
268 bs = append(bs, cookie...)
269 message.SetData(bs)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000270 err := ofc.SendMessage(ctx, message)
Andrea Campanella30342622020-03-05 20:48:26 +0100271 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000272 logger.Errorw(ctx, "Error reporting failure of FlowUpdate to controller",
Andrea Campanella30342622020-03-05 20:48:26 +0100273 log.Fields{
274 "device-id": ofc.DeviceID,
275 "error": err})
276 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800277 }
278}
279
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000280func (ofc *OFConnection) handleFlowMod(ctx context.Context, flowMod *ofp.FlowMod) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800281 if logger.V(log.DebugLevel) {
282 js, _ := json.Marshal(flowMod)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000283 logger.Debugw(ctx, "handleFlowMod called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800284 log.Fields{
285 "device-id": ofc.DeviceID,
286 "flow-mod": js})
287 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000288 logger.Errorw(ctx, "handleFlowMod not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800289 log.Fields{"device-id": ofc.DeviceID})
290}
291
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000292func (ofc *OFConnection) handleFlowModStrict(ctx context.Context, flowModStrict *ofp.FlowModifyStrict) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800293 if logger.V(log.DebugLevel) {
294 js, _ := json.Marshal(flowModStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000295 logger.Debugw(ctx, "handleFlowModStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800296 log.Fields{
297 "device-id": ofc.DeviceID,
298 "flow-mod-strict": js})
299 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000300 logger.Error(ctx, "handleFlowModStrict not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800301 log.Fields{"device-id": ofc.DeviceID})
302}
303
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000304func (ofc *OFConnection) handleFlowDelete(ctx context.Context, flowDelete *ofp.FlowDelete) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800305 if logger.V(log.DebugLevel) {
306 js, _ := json.Marshal(flowDelete)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000307 logger.Debugw(ctx, "handleFlowDelete called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800308 log.Fields{
309 "device-id": ofc.DeviceID,
310 "flow-delete": js})
311 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000312 logger.Error(ctx, "handleFlowDelete not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800313 log.Fields{"device-id": ofc.DeviceID})
314
315}
316
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000317func (ofc *OFConnection) handleFlowDeleteStrict(ctx context.Context, flowDeleteStrict *ofp.FlowDeleteStrict) {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800318 if logger.V(log.DebugLevel) {
319 js, _ := json.Marshal(flowDeleteStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000320 logger.Debugw(ctx, "handleFlowDeleteStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800321 log.Fields{
322 "device-id": ofc.DeviceID,
323 "flow-delete-strict": js})
324 }
325
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700326 volthaClient := ofc.VolthaClient.Get()
327 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000328 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800329 log.Fields{"device-id": ofc.DeviceID})
330 return
331 }
332
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800333 // Construct match
334 var oxmList []*voltha.OfpOxmField
335 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
336 name := oxmMap[oxmField.GetOXMName()]
337 val := oxmField.GetOXMValue()
338 var ofpOxmField voltha.OfpOxmField
339 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
340 var field voltha.OfpOxmOfbField
341 field.Type = voltha.OxmOfbFieldTypes(name)
342
343 var x openflow_13.OfpOxmField_OfbField
344 x.OfbField = &field
345 ofpOxmField.Field = &x
346
347 switch voltha.OxmOfbFieldTypes(name) {
348 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
349 field.Value = &voltha.OfpOxmOfbField_Port{
350 Port: uint32(val.(ofp.Port)),
351 }
352 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
353 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
354 PhysicalPort: val.(uint32),
355 }
356 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
357 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
358 TableMetadata: val.(uint64),
359 }
360 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
361 field.Value = &voltha.OfpOxmOfbField_EthType{
362 EthType: uint32(val.(ofp.EthernetType)),
363 }
364 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
365 field.Value = &voltha.OfpOxmOfbField_IpProto{
366 IpProto: uint32(val.(ofp.IpPrototype)),
367 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700368 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
369 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
370 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
371 }
Esin Karaman082a7012020-06-23 15:47:02 +0000372 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
373 field.Value = &voltha.OfpOxmOfbField_EthDst{
374 EthDst: val.(net.HardwareAddr),
375 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800376 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
377 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
378 UdpSrc: uint32(val.(uint16)),
379 }
380 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
381 field.Value = &voltha.OfpOxmOfbField_UdpDst{
382 UdpDst: uint32(val.(uint16)),
383 }
384 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
385 field.Value = &voltha.OfpOxmOfbField_VlanVid{
386 VlanVid: uint32(val.(uint16)),
387 }
Esin Karaman082a7012020-06-23 15:47:02 +0000388 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
389 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
390 VlanPcp: uint32(val.(uint8)),
391 }
Don Newton7fe70f72020-02-21 13:54:11 -0500392 case 200: // voltha-protos doesn't actually have a type for vlan_mask
393 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
394 field.HasMask = true
395 ofpOxmField = voltha.OfpOxmField{
396 OxmClass: ofp.OFPXMCOpenflowBasic,
397 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
398 }
399 field.Value = &voltha.OfpOxmOfbField_VlanVid{
400 VlanVid: uint32(val.(uint16)),
401 }
402 vidMask := val.(uint16)
403 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
404 VlanVidMask: uint32(vidMask),
405 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800406 }
Don Newton7fe70f72020-02-21 13:54:11 -0500407
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800408 oxmList = append(oxmList, &ofpOxmField)
409 }
410
Matteo Scandolo322c3082020-06-17 14:21:26 -0700411 responseRequired := false
412
413 if flowDeleteStrict.GetFlags() == ofp.OFPFFSendFlowRem {
414 responseRequired = true
415 }
416
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800417 // Construct request
418 flowUpdate := openflow_13.FlowTableUpdate{
419 Id: ofc.DeviceID,
420 FlowMod: &voltha.OfpFlowMod{
421 Cookie: flowDeleteStrict.Cookie,
422 CookieMask: flowDeleteStrict.CookieMask,
423 TableId: uint32(flowDeleteStrict.TableId),
424 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
425 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
426 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
427 Priority: uint32(flowDeleteStrict.Priority),
428 BufferId: flowDeleteStrict.BufferId,
429 OutPort: uint32(flowDeleteStrict.OutPort),
430 OutGroup: uint32(flowDeleteStrict.OutGroup),
431 Flags: uint32(flowDeleteStrict.Flags),
432 Match: &voltha.OfpMatch{
433 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
434 OxmFields: oxmList,
435 },
436 },
437 }
438
439 if logger.V(log.DebugLevel) {
440 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000441 logger.Debugf(ctx, "FlowDeleteStrict being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800442 log.Fields{
443 "device-id": ofc.DeviceID,
444 "flow-update": flowUpdateJs})
445 }
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700446 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000447 logger.Errorw(ctx, "Error calling FlowDelete ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800448 log.Fields{
449 "device-id": ofc.DeviceID,
450 "error": err})
Matteo Scandolo322c3082020-06-17 14:21:26 -0700451 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800452 }
Matteo Scandolo322c3082020-06-17 14:21:26 -0700453
454 if responseRequired {
455 response := ofp.NewFlowRemoved()
456
457 response.Cookie = flowDeleteStrict.Cookie
458 response.Priority = flowDeleteStrict.Priority
459 response.Reason = ofp.OFPRRDelete
460 response.Match = flowDeleteStrict.Match
461 response.IdleTimeout = flowDeleteStrict.IdleTimeout
462 response.HardTimeout = flowDeleteStrict.HardTimeout
463 response.Xid = flowDeleteStrict.Xid
464
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000465 err := ofc.SendMessage(ctx, response)
Matteo Scandolo322c3082020-06-17 14:21:26 -0700466 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000467 logger.Errorw(ctx, "Error sending FlowRemoved to ONOS",
Matteo Scandolo322c3082020-06-17 14:21:26 -0700468 log.Fields{
469 "device-id": ofc.DeviceID,
470 "error": err})
471 }
472 }
473
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800474}