blob: 4f8ab63aaa0d2cba20fee60a15b5eb04447c36fc [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"
Andrea Campanella18448bc2021-07-08 18:47:22 +020024 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninder12b909f2020-10-23 14:23:36 +053025 "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 }
ssiddiquidf20bf72021-08-23 14:00:56 +0530132 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC:
133 field.Value = &voltha.OfpOxmOfbField_EthSrc{
134 EthSrc: val.(net.HardwareAddr),
135 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800136 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
137 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
138 UdpSrc: uint32(val.(uint16)),
139 }
140 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
141 field.Value = &voltha.OfpOxmOfbField_UdpDst{
142 UdpDst: uint32(val.(uint16)),
143 }
144 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
145 field.Value = &voltha.OfpOxmOfbField_VlanVid{
146 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
147 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000148 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
149 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
150 VlanPcp: uint32(val.(uint8)),
151 }
ssiddiquidf20bf72021-08-23 14:00:56 +0530152 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_LABEL:
153 field.Value = &voltha.OfpOxmOfbField_MplsLabel{
154 MplsLabel: val.(uint32),
155 }
156 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_BOS:
157 field.Value = &voltha.OfpOxmOfbField_MplsBos{
158 MplsBos: uint32(val.(uint8)),
159 }
160 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_TC:
161 field.Value = &voltha.OfpOxmOfbField_MplsTc{
162 MplsTc: val.(uint32),
163 }
Don Newton7fe70f72020-02-21 13:54:11 -0500164 case 200: // voltha-protos doesn't actually have a type for vlan_mask
165 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
166 field.HasMask = true
167 ofpOxmField = voltha.OfpOxmField{
168 OxmClass: ofp.OFPXMCOpenflowBasic,
169 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
170 }
171 field.Value = &voltha.OfpOxmOfbField_VlanVid{
172 VlanVid: uint32(val.(uint16)),
173 }
174 vidMask := val.(uint16)
175 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
176 VlanVidMask: uint32(vidMask),
177 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800178 }
179 oxmList = append(oxmList, &ofpOxmField)
180 }
181
182 // Construct the instructions
183 var instructions []*voltha.OfpInstruction
184 for _, ofpInstruction := range flowAdd.GetInstructions() {
185 instructionType := ofpInstruction.GetType()
186 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
187 switch instructionType {
188 case ofp.OFPITGotoTable:
189 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
190 GotoTable: &openflow_13.OfpInstructionGotoTable{
191 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
192 },
193 }
194 case ofp.OFPITWriteMetadata:
195 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
196 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
197 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
198 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
199 },
200 }
201 case ofp.OFPITWriteActions:
202 var ofpActions []*openflow_13.OfpAction
203 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
204 ofpActions = append(ofpActions, extractAction(action))
205 }
206 instruction.Data = &openflow_13.OfpInstruction_Actions{
207 Actions: &openflow_13.OfpInstructionActions{
208 Actions: ofpActions,
209 },
210 }
211 case ofp.OFPITApplyActions:
212 var ofpActions []*openflow_13.OfpAction
213 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
214 ofpActions = append(ofpActions, extractAction(action))
215 }
216 instruction.Data = &openflow_13.OfpInstruction_Actions{
217 Actions: &openflow_13.OfpInstructionActions{
218 Actions: ofpActions,
219 },
220 }
221 case ofp.OFPITMeter:
222 instruction.Data = &openflow_13.OfpInstruction_Meter{
223 Meter: &openflow_13.OfpInstructionMeter{
224 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
225 },
226 }
227 }
228 instructions = append(instructions, &instruction)
229 }
230
231 // Construct the request
232 flowUpdate := openflow_13.FlowTableUpdate{
233 Id: ofc.DeviceID,
234 FlowMod: &voltha.OfpFlowMod{
235 Cookie: flowAdd.Cookie,
236 CookieMask: flowAdd.CookieMask,
237 TableId: uint32(flowAdd.TableId),
238 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
239 IdleTimeout: uint32(flowAdd.IdleTimeout),
240 HardTimeout: uint32(flowAdd.HardTimeout),
241 Priority: uint32(flowAdd.Priority),
242 BufferId: flowAdd.BufferId,
243 OutPort: uint32(flowAdd.OutPort),
244 OutGroup: uint32(flowAdd.OutGroup),
245 Flags: uint32(flowAdd.Flags),
246 Match: &voltha.OfpMatch{
247 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
248 OxmFields: oxmList,
249 },
250
251 Instructions: instructions,
252 },
Manindere2af7e42020-12-04 11:46:26 +0530253 Xid: flowAdd.Xid,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800254 }
255 if logger.V(log.DebugLevel) {
256 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000257 logger.Debugf(ctx, "FlowAdd being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800258 log.Fields{
259 "device-id": ofc.DeviceID,
Don Newton7fe70f72020-02-21 13:54:11 -0500260 "flow-mod-object": flowUpdate,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800261 "flow-mod-request": flowUpdateJs})
262 }
Girish Kumar01e0c632020-08-10 16:48:56 +0000263 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000264 logger.Errorw(ctx, "Error calling FlowAdd ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800265 log.Fields{
266 "device-id": ofc.DeviceID,
267 "error": err})
Andrea Campanella30342622020-03-05 20:48:26 +0100268 // Report failure to controller
269 message := ofp.NewFlowModFailedErrorMsg()
270 message.SetXid(flowAdd.Xid)
271 message.SetCode(ofp.OFPFMFCBadCommand)
272 //OF 1.3
273 message.SetVersion(4)
274 bs := make([]byte, 2)
275 //OF 1.3
276 bs[0] = byte(4)
277 //Flow Mod
278 bs[1] = byte(14)
279 //Length of the message
280 length := make([]byte, 2)
281 binary.BigEndian.PutUint16(length, 56)
282 bs = append(bs, length...)
283 empty := []byte{0, 0, 0, 0}
284 bs = append(bs, empty...)
285 //Cookie of the Flow
286 cookie := make([]byte, 52)
287 binary.BigEndian.PutUint64(cookie, flowAdd.Cookie)
288 bs = append(bs, cookie...)
289 message.SetData(bs)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000290 err := ofc.SendMessage(ctx, message)
Andrea Campanella30342622020-03-05 20:48:26 +0100291 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000292 logger.Errorw(ctx, "Error reporting failure of FlowUpdate to controller",
Andrea Campanella30342622020-03-05 20:48:26 +0100293 log.Fields{
294 "device-id": ofc.DeviceID,
295 "error": err})
296 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800297 }
298}
299
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000300func (ofc *OFConnection) handleFlowMod(ctx context.Context, flowMod *ofp.FlowMod) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000301 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification")
302 defer span.Finish()
303
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800304 if logger.V(log.DebugLevel) {
305 js, _ := json.Marshal(flowMod)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000306 logger.Debugw(ctx, "handleFlowMod called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800307 log.Fields{
308 "device-id": ofc.DeviceID,
309 "flow-mod": js})
310 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000311 logger.Errorw(ctx, "handleFlowMod not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800312 log.Fields{"device-id": ofc.DeviceID})
313}
314
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000315func (ofc *OFConnection) handleFlowModStrict(ctx context.Context, flowModStrict *ofp.FlowModifyStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000316 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-modification-strict")
317 defer span.Finish()
318
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800319 if logger.V(log.DebugLevel) {
320 js, _ := json.Marshal(flowModStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000321 logger.Debugw(ctx, "handleFlowModStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800322 log.Fields{
323 "device-id": ofc.DeviceID,
324 "flow-mod-strict": js})
325 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000326 logger.Error(ctx, "handleFlowModStrict not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800327 log.Fields{"device-id": ofc.DeviceID})
328}
329
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000330func (ofc *OFConnection) handleFlowDelete(ctx context.Context, flowDelete *ofp.FlowDelete) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000331 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete")
332 defer span.Finish()
333
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800334 if logger.V(log.DebugLevel) {
335 js, _ := json.Marshal(flowDelete)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000336 logger.Debugw(ctx, "handleFlowDelete called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800337 log.Fields{
338 "device-id": ofc.DeviceID,
339 "flow-delete": js})
340 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000341 logger.Error(ctx, "handleFlowDelete not implemented",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800342 log.Fields{"device-id": ofc.DeviceID})
343
344}
345
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000346func (ofc *OFConnection) handleFlowDeleteStrict(ctx context.Context, flowDeleteStrict *ofp.FlowDeleteStrict) {
Girish Kumar01e0c632020-08-10 16:48:56 +0000347 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-delete-strict")
348 defer span.Finish()
349
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800350 if logger.V(log.DebugLevel) {
351 js, _ := json.Marshal(flowDeleteStrict)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000352 logger.Debugw(ctx, "handleFlowDeleteStrict called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800353 log.Fields{
354 "device-id": ofc.DeviceID,
355 "flow-delete-strict": js})
356 }
357
David Bainbridgef8ce7d22020-04-08 12:49:41 -0700358 volthaClient := ofc.VolthaClient.Get()
359 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000360 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800361 log.Fields{"device-id": ofc.DeviceID})
362 return
363 }
364
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800365 // Construct match
366 var oxmList []*voltha.OfpOxmField
367 for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
368 name := oxmMap[oxmField.GetOXMName()]
369 val := oxmField.GetOXMValue()
370 var ofpOxmField voltha.OfpOxmField
371 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
372 var field voltha.OfpOxmOfbField
373 field.Type = voltha.OxmOfbFieldTypes(name)
374
375 var x openflow_13.OfpOxmField_OfbField
376 x.OfbField = &field
377 ofpOxmField.Field = &x
378
379 switch voltha.OxmOfbFieldTypes(name) {
380 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
381 field.Value = &voltha.OfpOxmOfbField_Port{
382 Port: uint32(val.(ofp.Port)),
383 }
384 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
385 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
386 PhysicalPort: val.(uint32),
387 }
388 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
389 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
390 TableMetadata: val.(uint64),
391 }
392 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
393 field.Value = &voltha.OfpOxmOfbField_EthType{
394 EthType: uint32(val.(ofp.EthernetType)),
395 }
396 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
397 field.Value = &voltha.OfpOxmOfbField_IpProto{
398 IpProto: uint32(val.(ofp.IpPrototype)),
399 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700400 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
401 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
402 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
403 }
Esin Karaman082a7012020-06-23 15:47:02 +0000404 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
405 field.Value = &voltha.OfpOxmOfbField_EthDst{
406 EthDst: val.(net.HardwareAddr),
407 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800408 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
409 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
410 UdpSrc: uint32(val.(uint16)),
411 }
412 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
413 field.Value = &voltha.OfpOxmOfbField_UdpDst{
414 UdpDst: uint32(val.(uint16)),
415 }
416 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
417 field.Value = &voltha.OfpOxmOfbField_VlanVid{
418 VlanVid: uint32(val.(uint16)),
419 }
Esin Karaman082a7012020-06-23 15:47:02 +0000420 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
421 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
422 VlanPcp: uint32(val.(uint8)),
423 }
Don Newton7fe70f72020-02-21 13:54:11 -0500424 case 200: // voltha-protos doesn't actually have a type for vlan_mask
425 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
426 field.HasMask = true
427 ofpOxmField = voltha.OfpOxmField{
428 OxmClass: ofp.OFPXMCOpenflowBasic,
429 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
430 }
431 field.Value = &voltha.OfpOxmOfbField_VlanVid{
432 VlanVid: uint32(val.(uint16)),
433 }
434 vidMask := val.(uint16)
435 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
436 VlanVidMask: uint32(vidMask),
437 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800438 }
Don Newton7fe70f72020-02-21 13:54:11 -0500439
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800440 oxmList = append(oxmList, &ofpOxmField)
441 }
442
Matteo Scandolo322c3082020-06-17 14:21:26 -0700443 responseRequired := false
444
445 if flowDeleteStrict.GetFlags() == ofp.OFPFFSendFlowRem {
446 responseRequired = true
447 }
448
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800449 // Construct request
450 flowUpdate := openflow_13.FlowTableUpdate{
451 Id: ofc.DeviceID,
452 FlowMod: &voltha.OfpFlowMod{
453 Cookie: flowDeleteStrict.Cookie,
454 CookieMask: flowDeleteStrict.CookieMask,
455 TableId: uint32(flowDeleteStrict.TableId),
456 Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
457 IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
458 HardTimeout: uint32(flowDeleteStrict.HardTimeout),
459 Priority: uint32(flowDeleteStrict.Priority),
460 BufferId: flowDeleteStrict.BufferId,
461 OutPort: uint32(flowDeleteStrict.OutPort),
462 OutGroup: uint32(flowDeleteStrict.OutGroup),
463 Flags: uint32(flowDeleteStrict.Flags),
464 Match: &voltha.OfpMatch{
465 Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
466 OxmFields: oxmList,
467 },
468 },
Manindere2af7e42020-12-04 11:46:26 +0530469 Xid: flowDeleteStrict.Xid,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800470 }
471
472 if logger.V(log.DebugLevel) {
473 flowUpdateJs, _ := json.Marshal(flowUpdate)
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000474 logger.Debugf(ctx, "FlowDeleteStrict being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800475 log.Fields{
476 "device-id": ofc.DeviceID,
477 "flow-update": flowUpdateJs})
478 }
Matteo Scandolo936e2df2020-10-27 14:31:36 -0700479
Girish Kumar01e0c632020-08-10 16:48:56 +0000480 if _, err := volthaClient.UpdateLogicalDeviceFlowTable(log.WithSpanFromContext(context.Background(), ctx), &flowUpdate); err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000481 logger.Errorw(ctx, "Error calling FlowDelete ",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800482 log.Fields{
483 "device-id": ofc.DeviceID,
484 "error": err})
Matteo Scandolo322c3082020-06-17 14:21:26 -0700485 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800486 }
Matteo Scandolo322c3082020-06-17 14:21:26 -0700487
488 if responseRequired {
489 response := ofp.NewFlowRemoved()
490
491 response.Cookie = flowDeleteStrict.Cookie
492 response.Priority = flowDeleteStrict.Priority
493 response.Reason = ofp.OFPRRDelete
494 response.Match = flowDeleteStrict.Match
495 response.IdleTimeout = flowDeleteStrict.IdleTimeout
496 response.HardTimeout = flowDeleteStrict.HardTimeout
497 response.Xid = flowDeleteStrict.Xid
498
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000499 err := ofc.SendMessage(ctx, response)
Matteo Scandolo322c3082020-06-17 14:21:26 -0700500 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000501 logger.Errorw(ctx, "Error sending FlowRemoved to ONOS",
Matteo Scandolo322c3082020-06-17 14:21:26 -0700502 log.Fields{
503 "device-id": ofc.DeviceID,
504 "error": err})
505 }
506 }
507
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800508}