blob: fd71798a82447e11c7e1a7a7f94bd2396eb18e61 [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 Hart60c5d772020-03-30 18:28:40 -070023 "net"
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +000024
25 ofp "github.com/opencord/goloxi/of13"
26 "github.com/opencord/voltha-lib-go/v7/pkg/log"
27 "github.com/opencord/voltha-protos/v5/go/openflow_13"
28 "github.com/opencord/voltha-protos/v5/go/voltha"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080029)
30
31var oxmMap = map[string]int32{
Don Newton7fe70f72020-02-21 13:54:11 -050032 "in_port": 0,
33 "in_phy_port": 1,
34 "metadata": 2,
35 "eth_dst": 3,
36 "eth_src": 4,
37 "eth_type": 5,
38 "vlan_vid": 6,
39 "vlan_pcp": 7,
40 "ip_dscp": 8,
41 "ip_ecn": 9,
42 "ip_proto": 10,
43 "ipv4_src": 11,
44 "ipv4_dst": 12,
45 "tcp_src": 13,
46 "tcp_dst": 14,
47 "udp_src": 15,
48 "udp_dst": 16,
49 "sctp_src": 17,
50 "sctp_dst": 18,
51 "icmpv4_type": 19,
52 "icmpv4_code": 20,
53 "arp_op": 21,
54 "arp_spa": 22,
55 "arp_tpa": 23,
56 "arp_sha": 24,
57 "arp_tha": 25,
58 "ipv6_src": 26,
59 "ipv6_dst": 27,
60 "ipv6_flabel": 28,
61 "icmpv6_type": 29,
62 "icmpv6_code": 30,
63 "ipv6_nd_target": 31,
64 "ipv6_nd_sll": 32,
65 "ipv6_nd_tll": 33,
66 "mpls_label": 34,
67 "mpls_tc": 35,
68 "mpls_bos": 36,
69 "pbb_isid": 37,
70 "tunnel_id": 38,
71 "ipv6_exthdr": 39,
72 "vlan_vid_masked": 200, //made up
David K. Bainbridge157bdab2020-01-16 14:38:05 -080073}
74
Rohan Agrawalc32d9932020-06-15 11:01:47 +000075func (ofc *OFConnection) handleFlowAdd(ctx context.Context, flowAdd *ofp.FlowAdd) {
Girish Kumar01e0c632020-08-10 16:48:56 +000076 span, ctx := log.CreateChildSpan(ctx, "openflow-flow-add")
77 defer span.Finish()
78
David K. Bainbridge157bdab2020-01-16 14:38:05 -080079 if logger.V(log.DebugLevel) {
80 js, _ := json.Marshal(flowAdd)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000081 logger.Debugw(ctx, "handleFlowAdd called",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080082 log.Fields{
83 "device-id": ofc.DeviceID,
84 "params": js})
85 }
86
David Bainbridgef8ce7d22020-04-08 12:49:41 -070087 volthaClient := ofc.VolthaClient.Get()
88 if volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000089 logger.Errorw(ctx, "no-voltha-connection",
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080090 log.Fields{"device-id": ofc.DeviceID})
91 return
92 }
93
David K. Bainbridge157bdab2020-01-16 14:38:05 -080094 // Construct the match
95 var oxmList []*voltha.OfpOxmField
96 for _, oxmField := range flowAdd.Match.GetOxmList() {
97 name := oxmMap[oxmField.GetOXMName()]
98 val := oxmField.GetOXMValue()
99 field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
100 ofpOxmField := voltha.OfpOxmField{
101 OxmClass: ofp.OFPXMCOpenflowBasic,
102 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
103 }
104 switch voltha.OxmOfbFieldTypes(name) {
105 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
106 field.Value = &voltha.OfpOxmOfbField_Port{
107 Port: uint32(val.(ofp.Port)),
108 }
109 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
110 field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
111 PhysicalPort: val.(uint32),
112 }
113 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
114 field.Value = &voltha.OfpOxmOfbField_TableMetadata{
115 TableMetadata: val.(uint64),
116 }
117 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
118 field.Value = &voltha.OfpOxmOfbField_EthType{
119 EthType: uint32(val.(ofp.EthernetType)),
120 }
121 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
122 field.Value = &voltha.OfpOxmOfbField_IpProto{
123 IpProto: uint32(val.(ofp.IpPrototype)),
124 }
Jonathan Hart60c5d772020-03-30 18:28:40 -0700125 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
126 field.Value = &voltha.OfpOxmOfbField_Ipv4Dst{
127 Ipv4Dst: binary.BigEndian.Uint32(val.(net.IP)),
128 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000129 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST:
130 field.Value = &voltha.OfpOxmOfbField_EthDst{
131 EthDst: val.(net.HardwareAddr),
132 }
ssiddiquidf20bf72021-08-23 14:00:56 +0530133 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC:
134 field.Value = &voltha.OfpOxmOfbField_EthSrc{
135 EthSrc: val.(net.HardwareAddr),
136 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800137 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
138 field.Value = &voltha.OfpOxmOfbField_UdpSrc{
139 UdpSrc: uint32(val.(uint16)),
140 }
141 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
142 field.Value = &voltha.OfpOxmOfbField_UdpDst{
143 UdpDst: uint32(val.(uint16)),
144 }
145 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
146 field.Value = &voltha.OfpOxmOfbField_VlanVid{
147 VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
148 }
Gamze Abaka3e2b2ce2020-05-09 10:21:40 +0000149 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
150 field.Value = &voltha.OfpOxmOfbField_VlanPcp{
151 VlanPcp: uint32(val.(uint8)),
152 }
ssiddiquidf20bf72021-08-23 14:00:56 +0530153 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_LABEL:
154 field.Value = &voltha.OfpOxmOfbField_MplsLabel{
155 MplsLabel: val.(uint32),
156 }
157 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_BOS:
158 field.Value = &voltha.OfpOxmOfbField_MplsBos{
159 MplsBos: uint32(val.(uint8)),
160 }
161 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_TC:
162 field.Value = &voltha.OfpOxmOfbField_MplsTc{
163 MplsTc: val.(uint32),
164 }
Don Newton7fe70f72020-02-21 13:54:11 -0500165 case 200: // voltha-protos doesn't actually have a type for vlan_mask
166 field = voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(oxmMap["vlan_vid"])}
167 field.HasMask = true
168 ofpOxmField = voltha.OfpOxmField{
169 OxmClass: ofp.OFPXMCOpenflowBasic,
170 Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
171 }
172 field.Value = &voltha.OfpOxmOfbField_VlanVid{
173 VlanVid: uint32(val.(uint16)),
174 }
175 vidMask := val.(uint16)
176 field.Mask = &voltha.OfpOxmOfbField_VlanVidMask{
177 VlanVidMask: uint32(vidMask),
178 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800179 }
180 oxmList = append(oxmList, &ofpOxmField)
181 }
182
183 // Construct the instructions
184 var instructions []*voltha.OfpInstruction
185 for _, ofpInstruction := range flowAdd.GetInstructions() {
186 instructionType := ofpInstruction.GetType()
187 instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
188 switch instructionType {
189 case ofp.OFPITGotoTable:
190 instruction.Data = &openflow_13.OfpInstruction_GotoTable{
191 GotoTable: &openflow_13.OfpInstructionGotoTable{
192 TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
193 },
194 }
195 case ofp.OFPITWriteMetadata:
196 instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
197 WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
198 Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
199 MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
200 },
201 }
202 case ofp.OFPITWriteActions:
203 var ofpActions []*openflow_13.OfpAction
204 for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
205 ofpActions = append(ofpActions, extractAction(action))
206 }
207 instruction.Data = &openflow_13.OfpInstruction_Actions{
208 Actions: &openflow_13.OfpInstructionActions{
209 Actions: ofpActions,
210 },
211 }
212 case ofp.OFPITApplyActions:
213 var ofpActions []*openflow_13.OfpAction
214 for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
215 ofpActions = append(ofpActions, extractAction(action))
216 }
217 instruction.Data = &openflow_13.OfpInstruction_Actions{
218 Actions: &openflow_13.OfpInstructionActions{
219 Actions: ofpActions,
220 },
221 }
222 case ofp.OFPITMeter:
223 instruction.Data = &openflow_13.OfpInstruction_Meter{
224 Meter: &openflow_13.OfpInstructionMeter{
225 MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
226 },
227 }
228 }
229 instructions = append(instructions, &instruction)
230 }
231
232 // Construct the request
233 flowUpdate := openflow_13.FlowTableUpdate{
234 Id: ofc.DeviceID,
235 FlowMod: &voltha.OfpFlowMod{
236 Cookie: flowAdd.Cookie,
237 CookieMask: flowAdd.CookieMask,
238 TableId: uint32(flowAdd.TableId),
239 Command: voltha.OfpFlowModCommand_OFPFC_ADD,
240 IdleTimeout: uint32(flowAdd.IdleTimeout),
241 HardTimeout: uint32(flowAdd.HardTimeout),
242 Priority: uint32(flowAdd.Priority),
243 BufferId: flowAdd.BufferId,
244 OutPort: uint32(flowAdd.OutPort),
245 OutGroup: uint32(flowAdd.OutGroup),
246 Flags: uint32(flowAdd.Flags),
247 Match: &voltha.OfpMatch{
248 Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
249 OxmFields: oxmList,
250 },
251
252 Instructions: instructions,
253 },
Manindere2af7e42020-12-04 11:46:26 +0530254 Xid: flowAdd.Xid,
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800255 }
256 if logger.V(log.DebugLevel) {
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +0000257 logger.Debugw(ctx, "FlowAdd being sent to Voltha",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800258 log.Fields{
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +0000259 "device-id": ofc.DeviceID,
260 "flow-mod-object": flowUpdate,
261 })
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800262 }
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}