blob: 37e68646bc640e4721255ed9774fd5aeee8d5774 [file] [log] [blame]
Don Newton98fd8812019-09-23 15:15:02 -04001/*
2 Copyright 2017 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"
21 "encoding/json"
22 "github.com/opencord/voltha-protos/go/openflow_13"
23 pb "github.com/opencord/voltha-protos/go/voltha"
24 ofp "github.com/skydive-project/goloxi/of13"
25 "log"
26)
27
28var oxmMap = map[string]int32{
29 "in_port": 0,
30 "in_phy_port": 1,
31 "metadata": 2,
32 "eth_dst": 3,
33 "eth_src": 4,
34 "eth_type": 5,
35 "vlan_vid": 6,
36 "vlan_pcp": 7,
37 "ip_dscp": 8,
38 "ip_ecn": 9,
39 "ip_proto": 10,
40 "ipv4_src": 11,
41 "ipv4_dst": 12,
42 "tcp_src": 13,
43 "tcp_dst": 14,
44 "udp_src": 15,
45 "udp_dst": 16,
46 "sctp_src": 17,
47 "sctp_dst": 18,
48 "icmpv4_type": 19,
49 "icmpv4_code": 20,
50 "arp_op": 21,
51 "arp_spa": 22,
52 "arp_tpa": 23,
53 "arp_sha": 24,
54 "arp_tha": 25,
55 "ipv6_src": 26,
56 "ipv6_dst": 27,
57 "ipv6_flabel": 28,
58 "icmpv6_type": 29,
59 "icmpv6_code": 30,
60 "ipv6_nd_target": 31,
61 "ipv6_nd_sll": 32,
62 "ipv6_nd_tll": 33,
63 "mpls_label": 34,
64 "mpls_tc": 35,
65 "mpls_bos": 36,
66 "pbb_isid": 37,
67 "tunnel_id": 38,
68 "ipv6_exthdr": 39,
69}
70
71func handleFlowAdd(flowAdd *ofp.FlowAdd, deviceId string) {
72 js, _ := json.Marshal(flowAdd)
73 log.Printf("handleFlowAdd called with %s", js)
74
75 var flowUpdate openflow_13.FlowTableUpdate
76 flowUpdate.Id = deviceId
77 var flowMod pb.OfpFlowMod
78 flowMod.Cookie = flowAdd.Cookie
79 flowMod.CookieMask = flowAdd.CookieMask
80 flowMod.TableId = uint32(flowAdd.TableId)
81 flowMod.Command = pb.OfpFlowModCommand_OFPFC_ADD
82 flowMod.IdleTimeout = uint32(flowAdd.IdleTimeout)
83 flowMod.HardTimeout = uint32(flowAdd.HardTimeout)
84 flowMod.Priority = uint32(flowAdd.Priority)
85 flowMod.BufferId = flowAdd.BufferId
86 flowMod.OutPort = uint32(flowAdd.OutPort)
87 flowMod.OutGroup = uint32(flowAdd.OutGroup)
88 flowMod.Flags = uint32(flowAdd.Flags)
89 inMatch := flowAdd.Match
90 var flowMatch pb.OfpMatch
91 flowMatch.Type = pb.OfpMatchType(inMatch.GetType())
92 var oxmList []*pb.OfpOxmField
93 inOxmList := inMatch.GetOxmList()
94 for i := 0; i < len(inOxmList); i++ {
95 oxmField := inOxmList[i]
96 j, _ := json.Marshal(oxmField)
97
98 name := oxmMap[oxmField.GetOXMName()]
99 log.Printf("\n\n\n %s %d %s\n\n\n", j, name, oxmField.GetOXMName())
100
101 val := oxmField.GetOXMValue()
102 var ofpOxmField pb.OfpOxmField
103 ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
104 var field pb.OfpOxmOfbField
105
106 field.Type = pb.OxmOfbFieldTypes(name)
107 log.Println("****\nFieldType: " + openflow_13.OxmOfbFieldTypes_name[name] + "\n\n\n\n")
108
109 var x openflow_13.OfpOxmField_OfbField
110 x.OfbField = &field
111 ofpOxmField.Field = &x
112
113 switch pb.OxmOfbFieldTypes(name) {
114 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
115 port := val.(ofp.Port)
116 var value pb.OfpOxmOfbField_Port
117 value.Port = uint32(port)
118 field.Value = &value
119 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
120 phyPort := val.(uint32)
121 var value pb.OfpOxmOfbField_PhysicalPort
122 value.PhysicalPort = phyPort
123 field.Value = &value
124 case pb.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
125 metadata := val.(uint64)
126 var value pb.OfpOxmOfbField_TableMetadata
127 value.TableMetadata = metadata
128 field.Value = &value
129 case pb.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
130 ethType := val.(ofp.EthernetType)
131 var value pb.OfpOxmOfbField_EthType
132 value.EthType = uint32(ethType)
133 field.Value = &value
134 case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
135 proto := val.(ofp.IpPrototype)
136 var value pb.OfpOxmOfbField_IpProto
137 value.IpProto = uint32(proto)
138 field.Value = &value
139 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
140 udpSrc := val.(uint16)
141 var value pb.OfpOxmOfbField_UdpSrc
142 value.UdpSrc = uint32(udpSrc)
143 log.Printf("udpSrc %v", udpSrc)
144 field.Value = &value
145 case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
146 udpDst := val.(uint16)
147 var value pb.OfpOxmOfbField_UdpDst
148 value.UdpDst = uint32(udpDst)
149 field.Value = &value
150 }
151 oxmList = append(oxmList, &ofpOxmField)
152 }
153 flowMatch.OxmFields = oxmList
154 flowMod.Match = &flowMatch
155 var instructions []*pb.OfpInstruction
156 ofpInstructions := flowAdd.GetInstructions()
157 for i := 0; i < len(ofpInstructions); i++ {
158 var instruction pb.OfpInstruction
159 ofpInstruction := ofpInstructions[i]
160 instructionType := ofpInstruction.GetType()
161 instruction.Type = uint32(instructionType)
162 switch instructionType {
163 case 1:
164 goToTable := ofpInstruction.(ofp.IInstructionGotoTable)
165 var ofpGoToTable openflow_13.OfpInstruction_GotoTable
166 ofpGoToTable.GotoTable.TableId = uint32(goToTable.GetTableId())
167 instruction.Data = &ofpGoToTable
168 case 2:
169 writeMetaData := ofpInstruction.(ofp.IInstructionWriteMetadata)
170 var ofpWriteMetadata openflow_13.OfpInstruction_WriteMetadata
171 ofpWriteMetadata.WriteMetadata.Metadata = writeMetaData.GetMetadata()
172 ofpWriteMetadata.WriteMetadata.MetadataMask = writeMetaData.GetMetadataMask()
173 instruction.Data = &ofpWriteMetadata
174 case 3:
175 writeAction := ofpInstruction.(ofp.IInstructionWriteActions)
176 var ofpInstructionActions openflow_13.OfpInstruction_Actions
177 var ofpActions []*openflow_13.OfpAction
178 actions := writeAction.GetActions()
179 for i := 0; i < len(actions); i++ {
180 action := actions[i]
181 ofpAction := extractAction(action)
182 ofpActions = append(ofpActions, ofpAction)
183 }
184 instruction.Data = &ofpInstructionActions
185 case 4:
186 applyAction := ofpInstruction.(ofp.IInstructionApplyActions)
187 var ofpInstructionActions openflow_13.OfpInstruction_Actions
188 var ofpActions []*openflow_13.OfpAction
189 actions := applyAction.GetActions()
190 for i := 0; i < len(actions); i++ {
191 action := actions[i]
192 ofpAction := extractAction(action)
193 ofpActions = append(ofpActions, ofpAction)
194 }
195 var actionsHolder openflow_13.OfpInstructionActions
196 actionsHolder.Actions = ofpActions
197 ofpInstructionActions.Actions = &actionsHolder
198 instruction.Data = &ofpInstructionActions
199
200 }
201 instructions = append(instructions, &instruction)
202 }
203
204 flowMod.Instructions = instructions
205 flowUpdate.FlowMod = &flowMod
206 grpcClient := *getGrpcClient()
207 flowUpdateJs, _ := json.Marshal(flowUpdate)
208 log.Printf("FLOW UPDATE %s", flowUpdateJs)
209 empty, err := grpcClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate)
210 if err != nil {
211 log.Printf("ERROR DOING FLOW MOD ADD %v", err)
212 }
213 emptyJs, _ := json.Marshal(empty)
214 log.Printf("FLOW MOD RESPONSE %s", emptyJs)
215
216}
217
218func handleFlowMod(flowMod *ofp.FlowMod, deviceId string) {
219 js, _ := json.Marshal(flowMod)
220 log.Printf("handleFlowMod called with %s", js)
221}
222
223func handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict, deviceId string) {
224 js, _ := json.Marshal(flowModStrict)
225 log.Printf("handleFlowModStrict called with %s", js)
226}
227func handleFlowDelete(flowDelete *ofp.FlowDelete, deviceId string) {
228 js, _ := json.Marshal(flowDelete)
229 log.Printf("handleFlowDelete called with %s", js)
230
231}
232func handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict, deviceId string) {
233 js, _ := json.Marshal(flowDeleteStrict)
234 log.Printf("handleFlowDeleteStrict called with %s", js)
235
236}
237func extractAction(action ofp.IAction) *openflow_13.OfpAction {
238 var ofpAction openflow_13.OfpAction
239 switch action.GetType() {
240 case 0: // Output
241 var outputAction openflow_13.OfpAction_Output
242 loxiOutputAction := action.(*ofp.ActionOutput)
243 var output openflow_13.OfpActionOutput
244 output.Port = uint32(loxiOutputAction.Port)
245 output.MaxLen = uint32(loxiOutputAction.MaxLen)
246 outputAction.Output = &output
247 ofpAction.Action = &outputAction
248 case 11: //CopyTtlOut
249 case 12: //CopyTtlIn
250 case 15: //SetMplsTtl
251 case 16: //DecMplsTtl
252 case 17: //PushVlan
253 var pushVlan openflow_13.OfpAction_Push
254 loxiPushAction := action.(*ofp.ActionPopVlan)
255 fields := loxiPushAction.GetActionFields()
256 fieldsJS, _ := json.Marshal(fields)
257 log.Printf("\n\nPushVlan fields %s\n\n", fieldsJS)
258 pushVlan.Push.Ethertype = 0x8100 //TODO This should be available in the fields
259 ofpAction.Type = openflow_13.OfpActionType_OFPAT_PUSH_VLAN
260 case 18: //PopVlan
261 ofpAction.Type = openflow_13.OfpActionType_OFPAT_POP_VLAN
262 case 19: //PushMpls
263 case 20: //PopMpls
264 case 21: //SetQueue
265 case 22: //ActionGroup
266 case 23: //SetNwTtl
267 case 24: //DecNwTtl
268 case 25: //SetField
269 var setField openflow_13.OfpAction_SetField
270 loxiSetField := action.(*ofp.ActionSetField)
271 fields := loxiSetField.GetActionFields()
272 fieldsJS, _ := json.Marshal(fields)
273 log.Printf("\n\nSet Fields fields %s\n\n", fieldsJS)
274
275 ofpAction.Action = &setField
276 case 26: //PushPbb
277 case 27: //PopPbb
278 case 65535: //Experimenter
279
280 }
281 return &ofpAction
282
283}