blob: 19abc2629e183db0a732f290bb265bf2ed5bcf1e [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
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 adaptercore
18
19import (
20 "context"
21 "crypto/md5"
22 "encoding/json"
23 "errors"
24 "fmt"
manikkaraj kbf256be2019-03-25 00:13:48 +053025 "github.com/opencord/voltha-go/common/log"
26 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040027 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053028 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040029 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053030 ofp "github.com/opencord/voltha-protos/go/openflow_13"
31 openolt_pb2 "github.com/opencord/voltha-protos/go/openolt"
32 voltha "github.com/opencord/voltha-protos/go/voltha"
manikkaraj k17652a72019-05-06 09:06:36 -040033 "math/big"
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040034 //deepcopy "github.com/getlantern/deepcopy"
manikkaraj kbf256be2019-03-25 00:13:48 +053035)
36
37const (
38 // Flow categories
39 HSIA_FLOW = "HSIA_FLOW"
40 EAPOL_FLOW = "EAPOL_FLOW"
41
42 IP_PROTO_DHCP = 17
43
44 IP_PROTO_IGMP = 2
45
46 EAP_ETH_TYPE = 0x888e
47 LLDP_ETH_TYPE = 0x88cc
48
49 IGMP_PROTO = 2
50
51 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
52 DEFAULT_MGMT_VLAN = 4091
53
manikkaraj kbf256be2019-03-25 00:13:48 +053054 // Openolt Flow
55 UPSTREAM = "upstream"
56 DOWNSTREAM = "downstream"
57 PACKET_TAG_TYPE = "pkt_tag_type"
58 UNTAGGED = "untagged"
59 SINGLE_TAG = "single_tag"
60 DOUBLE_TAG = "double_tag"
61
62 // classifierInfo
manikkaraj k17652a72019-05-06 09:06:36 -040063 ETH_TYPE = "eth_type"
64 TPID = "tpid"
65 IP_PROTO = "ip_proto"
66 IN_PORT = "in_port"
67 VLAN_VID = "vlan_vid"
68 VLAN_PCP = "vlan_pcp"
69 UDP_DST = "udp_dst"
70 UDP_SRC = "udp_src"
71 IPV4_DST = "ipv4_dst"
72 IPV4_SRC = "ipv4_src"
73 METADATA = "metadata"
74 TUNNEL_ID = "tunnel_id"
75 OUTPUT = "output"
manikkaraj kbf256be2019-03-25 00:13:48 +053076 // Action
77 POP_VLAN = "pop_vlan"
78 PUSH_VLAN = "push_vlan"
79 TRAP_TO_HOST = "trap_to_host"
80)
81
manikkaraj k9eb6cac2019-05-09 12:32:03 -040082type onuInfo struct {
83 intfId uint32
84 onuId uint32
85 serialNumber string
86}
87
88type onuIdKey struct {
89 intfId uint32
90 onuId uint32
91}
92
93type gemPortKey struct {
94 intfId uint32
95 gemPort uint32
96}
97
98type packetInInfoKey struct {
99 intfId uint32
100 onuId uint32
101 logicalPort uint32
102}
103
manikkaraj kbf256be2019-03-25 00:13:48 +0530104type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400105 techprofile []*tp.TechProfileMgr
106 deviceHandler *DeviceHandler
107 resourceMgr *rsrcMgr.OpenOltResourceMgr
108 onuIds map[onuIdKey]onuInfo //OnuId -> OnuInfo
109 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
110 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
111 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
112 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530113}
114
115func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
116 log.Info("Initializing flow manager")
117 var flowMgr OpenOltFlowMgr
118 flowMgr.deviceHandler = dh
119 flowMgr.resourceMgr = rsrcMgr
120 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
121 log.Error("Error while populating tech profile mgr\n")
122 return nil
123 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400124 flowMgr.onuIds = make(map[onuIdKey]onuInfo)
125 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
126 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
127 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530128 log.Info("Initialization of flow manager success!!")
129 return &flowMgr
130}
131
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400132func (f *OpenOltFlowMgr) generateStoredFlowId(flowId uint32, direction string) (uint64, error) {
133 if direction == UPSTREAM {
134 log.Debug("upstream flow, shifting id")
135 return 0x1<<15 | uint64(flowId), nil
136 } else if direction == DOWNSTREAM {
137 log.Debug("downstream flow, not shifting id")
138 return uint64(flowId), nil
139 } else {
140 log.Debug("Unrecognized direction")
141 return 0, errors.New(fmt.Sprintf("Unrecognized direction %s", direction))
142 }
143}
144
145func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openolt_pb2.Flow) {
146 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
147 log.Fields{"device": f.deviceHandler.deviceId})
148
149 var storedFlow ofp.OfpFlowStats
150 storedFlow.Id, _ = f.generateStoredFlowId(deviceFlow.FlowId, deviceFlow.FlowType)
151 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
152 deviceFlow.FlowId, deviceFlow.FlowType))
153 storedFlow.Cookie = flowFromCore.Id
154 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
155 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
156}
157
manikkaraj kbf256be2019-03-25 00:13:48 +0530158func (f *OpenOltFlowMgr) divideAndAddFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
159 var allocId []uint32
160 var gemPorts []uint32
161
162 log.Infow("Dividing flow", log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "portNo": portNo, "classifier": classifierInfo, "action": actionInfo})
163
164 log.Infow("sorting flow", log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "portNo": portNo,
165 "classifierInfo": classifierInfo, "actionInfo": actionInfo})
166
167 uni := getUniPortPath(intfId, onuId, uniId)
168 log.Debugw("Uni port name", log.Fields{"uni": uni})
169 allocId, gemPorts = f.createTcontGemports(intfId, onuId, uniId, uni, portNo, flow.GetTableId())
170 if allocId == nil || gemPorts == nil {
171 log.Error("alloc-id-gem-ports-unavailable")
172 return
173 }
174
175 /* Flows can't be added specific to gemport unless p-bits are received.
176 * Hence adding flows for all gemports
177 */
178 for _, gemPort := range gemPorts {
179 if ipProto, ok := classifierInfo[IP_PROTO]; ok {
180 if ipProto.(uint32) == IP_PROTO_DHCP {
181 log.Info("Adding DHCP flow")
182 f.addDHCPTrapFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
183 } else if ipProto == IP_PROTO_IGMP {
184 log.Info("igmp flow add ignored, not implemented yet")
185 } else {
186 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
187 //return errors.New("Invalid-Classifier-to-handle")
188 }
189 } else if ethType, ok := classifierInfo[ETH_TYPE]; ok {
190 if ethType.(uint32) == EAP_ETH_TYPE {
191 log.Info("Adding EAPOL flow")
192 f.addEAPOLFlow(intfId, onuId, uniId, portNo, flow, allocId[0], gemPort, DEFAULT_MGMT_VLAN)
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400193 if vlan := getSubscriberVlan(utils.GetInPort(flow)); vlan != 0 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530194 f.addEAPOLFlow(intfId, onuId, uniId, portNo, flow, allocId[0], gemPort, vlan)
195 }
196 // Send Techprofile download event to child device in go routine as it takes time
197 go f.sendTPDownloadMsgToChild(intfId, onuId, uniId, uni)
198 }
199 if ethType == LLDP_ETH_TYPE {
200 log.Info("Adding LLDP flow")
201 addLLDPFlow(flow, portNo)
202 }
203 } else if _, ok := actionInfo[PUSH_VLAN]; ok {
204 log.Info("Adding upstream data rule")
205 f.addUpstreamDataFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
206 } else if _, ok := actionInfo[POP_VLAN]; ok {
207 log.Info("Adding Downstream data rule")
208 f.addDownstreamDataFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
209 } else {
210 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
211 }
212 }
213}
214
215// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
216func (f *OpenOltFlowMgr) createTcontGemports(intfId uint32, onuId uint32, uniId uint32, uni string, uniPort uint32, tableID uint32) ([]uint32, []uint32) {
217 var allocID []uint32
218 var gemPortIDs []uint32
219 //If we already have allocated earlier for this onu, render them
Abhilash S.L8ee90712019-04-29 16:24:22 +0530220 if tcontId := f.resourceMgr.GetCurrentAllocIDForOnu(intfId, onuId, uniId); tcontId != 0 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530221 allocID = append(allocID, tcontId)
222 }
223 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfId, onuId, uniId)
224 if len(allocID) != 0 && len(gemPortIDs) != 0 {
225 log.Debug("Rendered Tcont and GEM ports from resource manager", log.Fields{"intfId": intfId, "onuId": onuId, "uniPort": uniId,
226 "allocID": allocID, "gemPortIDs": gemPortIDs})
227 return allocID, gemPortIDs
228 }
229 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfId, "onu": onuId, "uni": uniId})
230
231 //FIXME: If table id is <= 63 using 64 as table id
232 if tableID < tp.DEFAULT_TECH_PROFILE_TABLE_ID {
233 tableID = tp.DEFAULT_TECH_PROFILE_TABLE_ID
234 }
235 tpPath := f.getTPpath(intfId, uni)
236 // Check tech profile instance already exists for derived port name
237 tech_profile_instance, err := f.techprofile[intfId].GetTPInstanceFromKVStore(tableID, tpPath)
238 if err != nil { // This should not happen, something wrong in KV backend transaction
239 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tableID": tableID, "path": tpPath})
240 return nil, nil
241 }
242 if tech_profile_instance == nil {
243 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
244 tech_profile_instance = f.techprofile[intfId].CreateTechProfInstance(tableID, uni, intfId)
245 if tech_profile_instance == nil {
246 log.Error("Tech-profile-instance-creation-failed")
247 return nil, nil
248 }
249 } else {
250 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
251 }
252 // Get upstream and downstream scheduler protos
253 us_scheduler := f.techprofile[intfId].GetUsScheduler(tech_profile_instance)
254 ds_scheduler := f.techprofile[intfId].GetDsScheduler(tech_profile_instance)
255 // Get TCONTS protos
256 tconts := f.techprofile[intfId].GetTconts(tech_profile_instance, us_scheduler, ds_scheduler)
257 if len(tconts) == 0 {
258 log.Error("TCONTS not found ")
259 return nil, nil
260 }
261 log.Debugw("Sending Create tcont to device",
262 log.Fields{"onu": onuId, "uni": uniId, "portNo": "", "tconts": tconts})
263 if _, err := f.deviceHandler.Client.CreateTconts(context.Background(),
264 &openolt_pb2.Tconts{IntfId: intfId,
265 OnuId: onuId,
266 UniId: uniId,
267 PortNo: uniPort,
268 Tconts: tconts}); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400269 log.Errorw("Error while creating TCONT in device", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530270 return nil, nil
271 }
272 allocID = append(allocID, tech_profile_instance.UsScheduler.AllocID)
273 for _, gem := range tech_profile_instance.UpstreamGemPortAttributeList {
274 gemPortIDs = append(gemPortIDs, gem.GemportID)
275 }
276 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
277 // Send Tconts and GEM ports to KV store
278 f.storeTcontsGEMPortsIntoKVStore(intfId, onuId, uniId, allocID, gemPortIDs)
279 return allocID, gemPortIDs
280}
281
282func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfId uint32, onuId uint32, uniId uint32, allocID []uint32, gemPortIDs []uint32) {
283
284 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
285 log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "allocID": allocID, "gemPortIDs": gemPortIDs})
286 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
287 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfId, onuId, uniId, allocID); err != nil {
288 log.Error("Errow while uploading allocID to KV store")
289 }
290 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfId, onuId, uniId, gemPortIDs); err != nil {
291 log.Error("Errow while uploading GEMports to KV store")
292 }
293 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfId, onuId, uniId); err != nil {
294 log.Error("Errow while uploading gemtopon map to KV store")
295 }
296 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400297 for _, gemPort := range gemPortIDs {
298 f.addGemPortToOnuInfoMap(intfId, onuId, gemPort)
299 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530300}
301
302func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
303 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
304 for intfId := range techRange.IntfIds {
305 f.techprofile = append(f.techprofile, f.resourceMgr.ResourceMgrs[uint32(intfId)].TechProfileMgr)
306 }
307 }
308 //Make sure we have as many tech_profiles as there are pon ports on the device
309 if len(f.techprofile) != int(f.resourceMgr.DevInfo.GetPonPorts()) {
310 log.Errorw("Error while populating techprofile",
311 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
312 return errors.New("Error while populating techprofile mgrs")
313 }
314 log.Infow("Populated techprofile per ponport successfully",
315 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
316 return nil
317}
318
Manikkaraj k884c1242019-04-11 16:26:42 +0530319func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfId uint32, onuId uint32, uniId uint32,
320 portNo uint32, uplinkClassifier map[string]interface{},
321 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
322 allocId uint32, gemportId uint32) {
323 uplinkClassifier[PACKET_TAG_TYPE] = SINGLE_TAG
324 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
325 f.addHSIAFlow(intfId, onuId, uniId, portNo, uplinkClassifier, uplinkAction,
326 UPSTREAM, logicalFlow, allocId, gemportId)
327 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530328}
329
Manikkaraj k884c1242019-04-11 16:26:42 +0530330func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfId uint32, onuId uint32, uniId uint32,
331 portNo uint32, downlinkClassifier map[string]interface{},
332 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
333 allocId uint32, gemportId uint32) {
334 downlinkClassifier[PACKET_TAG_TYPE] = DOUBLE_TAG
335 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
336 "downlinkAction": downlinkAction})
manikkaraj k17652a72019-05-06 09:06:36 -0400337 // Ignore private VLAN flow given by decomposer, cannot do anything with this flow
Manikkaraj k884c1242019-04-11 16:26:42 +0530338 if uint32(downlinkClassifier[METADATA].(uint64)) == MkUniPortNum(intfId, onuId, uniId) &&
339 downlinkClassifier[VLAN_VID] == (uint32(ofp.OfpVlanId_OFPVID_PRESENT)|4000) {
340 log.Infow("EAPOL DL flow , Already added ,ignoring it", log.Fields{"downlinkClassifier": downlinkClassifier,
341 "downlinkAction": downlinkAction})
342 return
343 }
344 /* Already this info available classifier? */
345 downlinkAction[POP_VLAN] = true
346 downlinkAction[VLAN_VID] = downlinkClassifier[VLAN_VID]
347 f.addHSIAFlow(intfId, onuId, uniId, portNo, downlinkClassifier, downlinkAction,
348 DOWNSTREAM, logicalFlow, allocId, gemportId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530349}
350
Manikkaraj k884c1242019-04-11 16:26:42 +0530351func (f *OpenOltFlowMgr) addHSIAFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, classifier map[string]interface{},
352 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
353 allocId uint32, gemPortId uint32) {
354 /* One of the OLT platform (Broadcom BAL) requires that symmetric
355 flows require the same flow_id to be used across UL and DL.
356 Since HSIA flow is the only symmetric flow currently, we need to
357 re-use the flow_id across both direction. The 'flow_category'
358 takes priority over flow_cookie to find any available HSIA_FLOW
359 id for the ONU.
360 */
361 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "classifier": classifier,
362 "action": action, "direction": direction, "allocId": allocId, "gemPortId": gemPortId,
363 "logicalFlow": *logicalFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400364 flowCategory := "HSIA"
Manikkaraj k884c1242019-04-11 16:26:42 +0530365 flowStoreCookie := getFlowStoreCookie(classifier, gemPortId)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400366 flowId, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, flowCategory)
Manikkaraj k884c1242019-04-11 16:26:42 +0530367 if err != nil {
368 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
369 return
370 }
371 var classifierProto *openolt_pb2.Classifier
372 var actionProto *openolt_pb2.Action
373 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
374 log.Error("Error in making classifier protobuf for hsia flow")
375 return
376 }
377 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
378 if actionProto = makeOpenOltActionField(action); actionProto == nil {
379 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
380 return
381 }
382 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400383 networkIntfId := f.deviceHandler.nniIntfId
Manikkaraj k884c1242019-04-11 16:26:42 +0530384 flow := openolt_pb2.Flow{AccessIntfId: int32(intfId),
385 OnuId: int32(onuId),
386 UniId: int32(uniId),
387 FlowId: flowId,
388 FlowType: direction,
389 AllocId: int32(allocId),
Devmalya Paul0099c9c2019-06-10 14:40:30 +0530390 NetworkIntfId: int32(networkIntfId),
Manikkaraj k884c1242019-04-11 16:26:42 +0530391 GemportId: int32(gemPortId),
392 Classifier: classifierProto,
393 Action: actionProto,
394 Priority: int32(logicalFlow.Priority),
395 Cookie: logicalFlow.Cookie,
396 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400397 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530398 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400399 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, "HSIA", flowId)
Manikkaraj k884c1242019-04-11 16:26:42 +0530400 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
401 flow.OnuId,
402 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400403 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530404 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
405 return
406 }
407 }
408}
manikkaraj kbf256be2019-03-25 00:13:48 +0530409func (f *OpenOltFlowMgr) addDHCPTrapFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530410
411 var dhcpFlow openolt_pb2.Flow
412 var actionProto *openolt_pb2.Action
413 var classifierProto *openolt_pb2.Classifier
414
415 // Clear the action map
416 for k := range action {
417 delete(action, k)
418 }
419
420 action[TRAP_TO_HOST] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400421 classifier[UDP_SRC] = uint32(68)
422 classifier[UDP_DST] = uint32(67)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530423 classifier[PACKET_TAG_TYPE] = SINGLE_TAG
424 delete(classifier, VLAN_VID)
425
426 flowStoreCookie := getFlowStoreCookie(classifier, gemPortId)
427
428 flowID, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, "")
429
430 if err != nil {
431 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfId, "onuId": onuId, "flowStoreCookie": flowStoreCookie})
432 return
433 }
434
435 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
436
437 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
438 log.Error("Error in making classifier protobuf for ul flow")
439 return
440 }
441 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
442 if actionProto = makeOpenOltActionField(action); actionProto == nil {
443 log.Error("Error in making action protobuf for ul flow")
444 return
445 }
Girish Gowdru1110ef22019-06-24 11:17:59 -0400446 networkIntfId := f.deviceHandler.nniIntfId
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530447
448 dhcpFlow = openolt_pb2.Flow{AccessIntfId: int32(intfId),
449 OnuId: int32(onuId),
450 UniId: int32(uniId),
451 FlowId: flowID,
452 FlowType: UPSTREAM,
453 AllocId: int32(allocId),
Devmalya Paul0099c9c2019-06-10 14:40:30 +0530454 NetworkIntfId: int32(networkIntfId),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530455 GemportId: int32(gemPortId),
456 Classifier: classifierProto,
457 Action: actionProto,
458 Priority: int32(logicalFlow.Priority),
459 Cookie: logicalFlow.Cookie,
460 PortNo: portNo}
461
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400462 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530463 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400464 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530465 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
466 dhcpFlow.OnuId,
467 dhcpFlow.UniId,
468 dhcpFlow.FlowId, flowsToKVStore); err != nil {
469 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
470 return
471 }
472 }
473
manikkaraj kbf256be2019-03-25 00:13:48 +0530474 return
475}
476
477// Add EAPOL to device
478func (f *OpenOltFlowMgr) addEAPOLFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32) {
479 log.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfId, "onuId": onuId, "portNo": portNo, "allocId": allocId, "gemPortId": gemPortId, "vlanId": vlanId, "flow": logicalFlow})
480
481 uplinkClassifier := make(map[string]interface{})
482 uplinkAction := make(map[string]interface{})
483 downlinkClassifier := make(map[string]interface{})
484 downlinkAction := make(map[string]interface{})
485 var upstreamFlow openolt_pb2.Flow
486 var downstreamFlow openolt_pb2.Flow
487
488 // Fill Classfier
489 uplinkClassifier[ETH_TYPE] = uint32(EAP_ETH_TYPE)
490 uplinkClassifier[PACKET_TAG_TYPE] = SINGLE_TAG
491 uplinkClassifier[VLAN_VID] = vlanId
492 // Fill action
493 uplinkAction[TRAP_TO_HOST] = true
494 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortId)
495 //Add Uplink EAPOL Flow
496 uplinkFlowId, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, "")
497 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530498 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfId, "onuId": onuId, "flowStoreCookie": flowStoreCookie})
499 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530500 }
501 var classifierProto *openolt_pb2.Classifier
502 var actionProto *openolt_pb2.Action
503 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowId})
504
505 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
506 log.Error("Error in making classifier protobuf for ul flow")
507 return
508 }
509 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
510 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
511 log.Error("Error in making action protobuf for ul flow")
512 return
513 }
514 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400515 networkIntfId := f.deviceHandler.nniIntfId
manikkaraj kbf256be2019-03-25 00:13:48 +0530516 upstreamFlow = openolt_pb2.Flow{AccessIntfId: int32(intfId),
517 OnuId: int32(onuId),
518 UniId: int32(uniId),
519 FlowId: uplinkFlowId,
520 FlowType: UPSTREAM,
521 AllocId: int32(allocId),
Devmalya Paul0099c9c2019-06-10 14:40:30 +0530522 NetworkIntfId: int32(networkIntfId),
manikkaraj kbf256be2019-03-25 00:13:48 +0530523 GemportId: int32(gemPortId),
524 Classifier: classifierProto,
525 Action: actionProto,
526 Priority: int32(logicalFlow.Priority),
527 Cookie: logicalFlow.Cookie,
528 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400529 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530530 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400531 flowCategory := "EAPOL"
532 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530533 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
534 upstreamFlow.OnuId,
535 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400536 upstreamFlow.FlowId,
537 /* lowCategory, */
538 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530539 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
540 return
541 }
542 }
543
544 if vlanId == DEFAULT_MGMT_VLAN {
545 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
546 # requirement)
547 # On one of the platforms (Broadcom BAL), when same DL classifier
548 # vlan was used across multiple ONUs, eapol flow re-adds after
549 # flow delete (cases of onu reboot/disable) fails.
550 # In order to generate unique vlan, a combination of intf_id
551 # onu_id and uniId is used.
552 # uniId defaults to 0, so add 1 to it.
553 */
554 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanId})
555 specialVlanDlFlow := 4090 - intfId*onuId*(uniId+1)
556 // Assert that we do not generate invalid vlans under no condition
557 if specialVlanDlFlow <= 2 {
558 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
559 return
560 }
561 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
562 // Fill Classfier
563 downlinkClassifier[PACKET_TAG_TYPE] = SINGLE_TAG
564 downlinkClassifier[VLAN_VID] = uint32(specialVlanDlFlow)
565 // Fill action
566 downlinkAction[PUSH_VLAN] = true
567 downlinkAction[VLAN_VID] = vlanId
568 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortId)
569 downlinkFlowId, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, "")
570 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530571 log.Errorw("flowId unavailable for DL EAPOL",
manikkaraj kbf256be2019-03-25 00:13:48 +0530572 log.Fields{"intfId": intfId, "onuId": onuId, "flowStoreCookie": flowStoreCookie})
573 return
574 }
575 log.Debugw("Creating DL EAPOL flow",
576 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowId})
577 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
578 log.Error("Error in making classifier protobuf for downlink flow")
579 return
580 }
581 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
582 log.Error("Error in making action protobuf for dl flow")
583 return
584 }
585 // Downstream flow in grpc protobuf
586 downstreamFlow = openolt_pb2.Flow{AccessIntfId: int32(intfId),
587 OnuId: int32(onuId),
588 UniId: int32(uniId),
589 FlowId: downlinkFlowId,
590 FlowType: DOWNSTREAM,
591 AllocId: int32(allocId),
Devmalya Paul0099c9c2019-06-10 14:40:30 +0530592 NetworkIntfId: int32(networkIntfId),
manikkaraj kbf256be2019-03-25 00:13:48 +0530593 GemportId: int32(gemPortId),
594 Classifier: classifierProto,
595 Action: actionProto,
596 Priority: int32(logicalFlow.Priority),
597 Cookie: logicalFlow.Cookie,
598 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400599 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530600 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400601 flowCategory := ""
602 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530603 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
604 downstreamFlow.OnuId,
605 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400606 downstreamFlow.FlowId,
607 /* flowCategory, */
608 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530609 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
610 return
611 }
612 }
613 } else {
614 log.Infow("EAPOL flow with non-default mgmt vlan is not supported", log.Fields{"vlanId": vlanId})
615 return
616 }
617 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
618}
619
620func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openolt_pb2.Classifier {
621 var classifier openolt_pb2.Classifier
622 if etherType, ok := classifierInfo[ETH_TYPE]; ok {
623 classifier.EthType = etherType.(uint32)
624 }
625 if ipProto, ok := classifierInfo[IP_PROTO]; ok {
626 classifier.IpProto = ipProto.(uint32)
627 }
628 if vlanId, ok := classifierInfo[VLAN_VID]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400629 classifier.OVid = (vlanId.(uint32)) & 0xFFF
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530631 if metadata, ok := classifierInfo[METADATA]; ok { // TODO: Revisit
632 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530633 }
634 if vlanPcp, ok := classifierInfo[VLAN_PCP]; ok {
635 classifier.OPbits = vlanPcp.(uint32)
636 }
637 if udpSrc, ok := classifierInfo[UDP_SRC]; ok {
638 classifier.SrcPort = udpSrc.(uint32)
639 }
640 if udpDst, ok := classifierInfo[UDP_DST]; ok {
641 classifier.DstPort = udpDst.(uint32)
642 }
643 if ipv4Dst, ok := classifierInfo[IPV4_DST]; ok {
644 classifier.DstIp = ipv4Dst.(uint32)
645 }
646 if ipv4Src, ok := classifierInfo[IPV4_SRC]; ok {
647 classifier.SrcIp = ipv4Src.(uint32)
648 }
649 if pktTagType, ok := classifierInfo[PACKET_TAG_TYPE]; ok {
650 if pktTagType.(string) == SINGLE_TAG {
651 classifier.PktTagType = SINGLE_TAG
652 } else if pktTagType.(string) == DOUBLE_TAG {
653 classifier.PktTagType = DOUBLE_TAG
654 } else if pktTagType.(string) == UNTAGGED {
655 classifier.PktTagType = UNTAGGED
656 } else {
657 log.Error("Invalid tag type in classifier") // should not hit
658 return nil
659 }
660 }
661 return &classifier
662}
663
664func makeOpenOltActionField(actionInfo map[string]interface{}) *openolt_pb2.Action {
665 var actionCmd openolt_pb2.ActionCmd
666 var action openolt_pb2.Action
667 action.Cmd = &actionCmd
668 if _, ok := actionInfo[POP_VLAN]; ok {
669 action.OVid = actionInfo[VLAN_VID].(uint32)
670 action.Cmd.RemoveOuterTag = true
671 } else if _, ok := actionInfo[PUSH_VLAN]; ok {
672 action.OVid = actionInfo[VLAN_VID].(uint32)
673 action.Cmd.AddOuterTag = true
674 } else if _, ok := actionInfo[TRAP_TO_HOST]; ok {
675 action.Cmd.TrapToHost = actionInfo[TRAP_TO_HOST].(bool)
676 } else {
677 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
678 return nil
679 }
680 return &action
681}
682
683func (f *OpenOltFlowMgr) getTPpath(intfId uint32, uni string) string {
684 /*
685 FIXME
686 Should get Table id form the flow, as of now hardcoded to DEFAULT_TECH_PROFILE_TABLE_ID (64)
687 'tp_path' contains the suffix part of the tech_profile_instance path. The prefix to the 'tp_path' should be set to
688 TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
689 */
690 return f.techprofile[intfId].GetTechProfileInstanceKVPath(tp.DEFAULT_TECH_PROFILE_TABLE_ID, uni)
691}
692
693func getFlowStoreCookie(classifier map[string]interface{}, gemPortId uint32) uint64 {
694 if len(classifier) == 0 { // should never happen
695 log.Error("Invalid classfier object")
696 return 0
697 }
698 var jsonData []byte
699 var flowString string
700 var err error
701 // TODO: Do we need to marshall ??
702 if jsonData, err = json.Marshal(classifier); err != nil {
703 log.Error("Failed to encode classifier")
704 return 0
705 }
706 flowString = string(jsonData)
707 if gemPortId != 0 {
708 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortId))
709 }
710 h := md5.New()
711 h.Write([]byte(flowString))
712 hash := big.NewInt(0)
713 hash.SetBytes(h.Sum(nil))
714 return hash.Uint64()
715}
716
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400717func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowId uint32) *[]rsrcMgr.FlowInfo {
manikkaraj k17652a72019-05-06 09:06:36 -0400718 var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400719 var intfId uint32
720 /* For flows which trap out of the NNI, the AccessIntfId is invalid
721 (set to -1). In such cases, we need to refer to the NetworkIntfId .
722 */
723 if flow.AccessIntfId != -1 {
724 intfId = uint32(flow.AccessIntfId)
725 } else {
726 intfId = uint32(flow.NetworkIntfId)
727 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400728 existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400729 if existingFlows != nil {
730 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
731 for _, f := range *existingFlows {
732 flows = append(flows, f)
733 }
734 }
735 log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 return &flows
737}
738
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400739//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
740// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
741// var intfId uint32
742// /* For flows which trap out of the NNI, the AccessIntfId is invalid
743// (set to -1). In such cases, we need to refer to the NetworkIntfId .
744// */
745// if flow.AccessIntfId != -1 {
746// intfId = uint32(flow.AccessIntfId)
747// } else {
748// intfId = uint32(flow.NetworkIntfId)
749// }
750// // Get existing flows matching flowid for given subscriber from KV store
751// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
752// if existingFlows != nil {
753// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
754// for _, f := range *existingFlows {
755// flows = append(flows, f)
756// }
757// }
758// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
759// return &flows
760//}
761
manikkaraj k17652a72019-05-06 09:06:36 -0400762func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfId int32, onuId int32, uniId int32, flowId uint32, flows *[]rsrcMgr.FlowInfo) error {
763 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
764 if err := f.resourceMgr.UpdateFlowIDInfo(intfId, onuId, uniId, flowId, flows); err != nil {
765 log.Debug("Error while Storing flow into KV store")
766 return err
767 }
768 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530769 return nil
770}
771
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400772func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openolt_pb2.Flow) bool {
manikkaraj kbf256be2019-03-25 00:13:48 +0530773 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
774 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
775 if err != nil {
776 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
777 return false
778 }
779 log.Debugw("Flow added to device successfuly ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400780 f.registerFlow(logicalFlow, deviceFlow)
781 return true
782}
783
784func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openolt_pb2.Flow) bool {
785 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
786 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
787 if err != nil {
788 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
789 return false
790 }
791 log.Debugw("Flow removed from device successfuly ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 return true
793}
794
795/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
796 //update core flows_proxy : flows_proxy.update('/', flows)
797}
798
799func generateStoredId(flowId uint32, direction string)uint32{
800
801 if direction == UPSTREAM{
802 log.Debug("Upstream flow shifting flowid")
803 return ((0x1 << 15) | flowId)
804 }else if direction == DOWNSTREAM{
805 log.Debug("Downstream flow not shifting flowid")
806 return flowId
807 }else{
808 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
809 return flowId
810 }
811}
812
813*/
814
815func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
816 log.Info("Unimplemented")
817}
818func getUniPortPath(intfId uint32, onuId uint32, uniId uint32) string {
819 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfId, onuId, uniId)
820}
821
Manikkaraj k884c1242019-04-11 16:26:42 +0530822func (f *OpenOltFlowMgr) getOnuChildDevice(intfId uint32, onuId uint32) (*voltha.Device, error) {
823 log.Debugw("GetChildDevice", log.Fields{"pon port": intfId, "onuId": onuId})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400824 parentPortNo := IntfIdToPortNo(intfId, voltha.Port_PON_OLT)
Manikkaraj k884c1242019-04-11 16:26:42 +0530825 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuId)
826 if onuDevice == nil {
827 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuId})
828 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530830 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
831 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530832}
833
834func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
835 log.Info("Unimplemented")
836 return nil
837}
838
839func getSubscriberVlan(inPort uint32) uint32 {
840 /* For EAPOL case we will use default VLAN , so will implement later if required */
841 log.Info("Unimplemented")
842 return 0
843}
844
845func (f *OpenOltFlowMgr) clear_flows_and_scheduler_for_logical_port(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
846 log.Info("Unimplemented")
847}
848
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400849func (f *OpenOltFlowMgr) decodeStoredId(id uint64) (uint64, string) {
850 if id>>15 == 0x1 {
851 return id & 0x7fff, UPSTREAM
852 }
853 return id, DOWNSTREAM
854}
855
856func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowId uint32, flowDirection string) {
857 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowId": flowId, "flowDirection": flowDirection, "flow": *flow})
858 ponIntf, onuId, uniId, err := FlowExtractInfo(flow, flowDirection)
859 if err != nil {
860 log.Error(err)
861 return
862 }
863 log.Debugw("Extracted access info from flow to be deleted",
864 log.Fields{"ponIntf": ponIntf, "onuId": onuId, "uniId": uniId, "flowId": flowId})
865
866 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuId, uniId, flowId)
867 if flowsInfo == nil {
868 log.Debugw("No FlowInfo found found in KV store",
869 log.Fields{"ponIntf": ponIntf, "onuId": onuId, "uniId": uniId, "flowId": flowId})
870 return
871 }
872 var updatedFlows []rsrcMgr.FlowInfo
873
874 for _, flow := range *flowsInfo {
875 updatedFlows = append(updatedFlows, flow)
876 }
877
878 for i, storedFlow := range updatedFlows {
879 if flowDirection == storedFlow.Flow.FlowType {
880 //Remove the Flow from FlowInfo
881 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
882 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
883 break
884 }
885 }
886
887 if len(updatedFlows) >= 0 {
888 // There are still flows referencing the same flow_id.
889 // So the flow should not be freed yet.
890 // For ex: Case of HSIA where same flow is shared
891 // between DS and US.
892 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuId), int32(uniId), flowId, &updatedFlows)
893 return
894 }
895 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuId, "uniId": uniId, "flowId": flowId})
896 f.resourceMgr.FreeFlowID(ponIntf, onuId, uniId, flowId)
897 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuId, uniId)
898 if len(flowIds) == 0 {
899 /* TODO: Remove Upstream and Downstream Schedulers */
900 }
901}
902
903func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
904 log.Debugw("Removing Flow", log.Fields{"flow": flow})
905 var deviceFlowsToRemove []ofp.OfpFlowStats
906 var deletedFlowsIdx []int
907 for _, curFlow := range f.storedDeviceFlows {
908 if curFlow.Cookie == flow.Id {
909 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
910 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
911 }
912 }
913 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
914 for index, curFlow := range deviceFlowsToRemove {
915 id, direction := f.decodeStoredId(curFlow.GetId())
916 removeFlowMessage := openolt_pb2.Flow{FlowId: uint32(id), FlowType: direction}
917 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
918 log.Debug("Flow removed from device successfully")
919 deletedFlowsIdx = append(deletedFlowsIdx, index)
920 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
921 }
922
923 }
924 // Can be done in separate go routine as it takes time ?
925 for _, flowToRemove := range deletedFlowsIdx {
926 for index, storedFlow := range f.storedDeviceFlows {
927 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
928 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
929 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
930 break
931 }
932 }
933 }
934 log.Debugw("Flows removed from the data store",
935 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
936 return
937}
938
manikkaraj kbf256be2019-03-25 00:13:48 +0530939func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats) {
940 classifierInfo := make(map[string]interface{}, 0)
941 actionInfo := make(map[string]interface{}, 0)
942 log.Debug("Adding Flow", log.Fields{"flow": flow})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400943 for _, field := range utils.GetOfbFields(flow) {
944 if field.Type == utils.ETH_TYPE {
manikkaraj kbf256be2019-03-25 00:13:48 +0530945 classifierInfo[ETH_TYPE] = field.GetEthType()
946 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[ETH_TYPE].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400947 } else if field.Type == utils.IP_PROTO {
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 classifierInfo[IP_PROTO] = field.GetIpProto()
949 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IP_PROTO].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400950 } else if field.Type == utils.IN_PORT {
manikkaraj kbf256be2019-03-25 00:13:48 +0530951 classifierInfo[IN_PORT] = field.GetPort()
952 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[IN_PORT].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400953 } else if field.Type == utils.VLAN_VID {
manikkaraj kbf256be2019-03-25 00:13:48 +0530954 classifierInfo[VLAN_VID] = field.GetVlanVid()
955 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VLAN_VID].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400956 } else if field.Type == utils.VLAN_PCP {
manikkaraj kbf256be2019-03-25 00:13:48 +0530957 classifierInfo[VLAN_PCP] = field.GetVlanPcp()
958 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VLAN_PCP].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400959 } else if field.Type == utils.UDP_DST {
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 classifierInfo[UDP_DST] = field.GetUdpDst()
961 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDP_DST].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400962 } else if field.Type == utils.UDP_SRC {
manikkaraj kbf256be2019-03-25 00:13:48 +0530963 classifierInfo[UDP_SRC] = field.GetUdpSrc()
964 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDP_SRC].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400965 } else if field.Type == utils.IPV4_DST {
manikkaraj kbf256be2019-03-25 00:13:48 +0530966 classifierInfo[IPV4_DST] = field.GetIpv4Dst()
967 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[IPV4_DST].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400968 } else if field.Type == utils.IPV4_SRC {
manikkaraj kbf256be2019-03-25 00:13:48 +0530969 classifierInfo[IPV4_SRC] = field.GetIpv4Src()
970 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[IPV4_SRC].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400971 } else if field.Type == utils.METADATA {
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 classifierInfo[METADATA] = field.GetTableMetadata()
973 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400974 } else if field.Type == utils.TUNNEL_ID {
manikkaraj k17652a72019-05-06 09:06:36 -0400975 classifierInfo[TUNNEL_ID] = field.GetTunnelId()
976 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TUNNEL_ID].(uint64)})
manikkaraj kbf256be2019-03-25 00:13:48 +0530977 } else {
978 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
979 return
980 }
981 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400982 for _, action := range utils.GetActions(flow) {
983 if action.Type == utils.OUTPUT {
manikkaraj kbf256be2019-03-25 00:13:48 +0530984 if out := action.GetOutput(); out != nil {
985 actionInfo[OUTPUT] = out.GetPort()
986 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
987 } else {
988 log.Error("Invalid output port in action")
989 return
990 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400991 } else if action.Type == utils.POP_VLAN {
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 actionInfo[POP_VLAN] = true
993 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[IN_PORT].(uint32)})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400994 } else if action.Type == utils.PUSH_VLAN {
manikkaraj kbf256be2019-03-25 00:13:48 +0530995 if out := action.GetPush(); out != nil {
996 if tpid := out.GetEthertype(); tpid != 0x8100 {
997 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PUSH_VLAN].(int32)})
998 } else {
999 actionInfo[PUSH_VLAN] = true
1000 actionInfo[TPID] = tpid
1001 log.Debugw("action-type-push-vlan",
1002 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[IN_PORT].(uint32)})
1003 }
1004 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001005 } else if action.Type == utils.SET_FIELD {
manikkaraj kbf256be2019-03-25 00:13:48 +05301006 if out := action.GetSetField(); out != nil {
1007 if field := out.GetField(); field != nil {
1008 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1009 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1010 return
1011 }
1012 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1013 if ofbField := field.GetOfbField(); ofbField != nil {
1014 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1015 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1016 actionInfo[VLAN_VID] = vlan & 0xfff
1017 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VLAN_VID].(uint32)})
1018 } else {
1019 log.Error("No Invalid vlan id in set vlan-vid action")
1020 }
1021 } else {
1022 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1023 }
1024 }
1025 }
1026 }
1027 } else {
1028 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1029 return
1030 }
1031 }
manikkaraj k17652a72019-05-06 09:06:36 -04001032 /* Controller bound trap flows */
1033 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
1034 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1035 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1036 if portType := IntfIdToPortTypeName(classifierInfo[IN_PORT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001037 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001038 classifierInfo[IN_PORT] = uniPort
1039 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[IN_PORT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
manikkaraj kbf256be2019-03-25 00:13:48 +05301040 } else {
manikkaraj k17652a72019-05-06 09:06:36 -04001041 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1042 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301043 }
1044 }
manikkaraj k17652a72019-05-06 09:06:36 -04001045 } else {
1046 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1047 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
1048 if portType := IntfIdToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001049 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001050 actionInfo[OUTPUT] = uniPort
1051 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1052 } else {
1053 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[IN_PORT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1054 return
1055 }
1056 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1057 } else if portType := IntfIdToPortTypeName(classifierInfo[IN_PORT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001058 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001059 classifierInfo[IN_PORT] = uniPort
1060 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1061 "outport": actionInfo[OUTPUT].(uint32)})
1062 } else {
1063 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[IN_PORT].(uint32),
1064 "outPort": actionInfo[OUTPUT].(uint32)})
1065 return
1066 }
1067 }
1068 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301069 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[IN_PORT], "action_output": actionInfo[OUTPUT]})
1070 portNo, intfId, onuId, uniId := ExtractAccessFromFlow(classifierInfo[IN_PORT].(uint32), actionInfo[OUTPUT].(uint32))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001071 if ipProto, ok := classifierInfo[IP_PROTO]; ok {
1072 if ipProto.(uint32) == IP_PROTO_DHCP {
1073 if udpSrc, ok := classifierInfo[UDP_SRC]; ok {
1074 if udpSrc.(uint32) == uint32(67) {
1075 log.Debug("trap-dhcp-from-nni-flow")
1076 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1077 return
1078 }
1079 }
1080 }
1081 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 f.divideAndAddFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow)
1083}
1084
Manikkaraj k884c1242019-04-11 16:26:42 +05301085func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfId uint32, onuId uint32, uniId uint32, uni string) error {
manikkaraj kbf256be2019-03-25 00:13:48 +05301086
Manikkaraj k884c1242019-04-11 16:26:42 +05301087 onuDevice, err := f.getOnuChildDevice(intfId, onuId)
1088 if err != nil {
1089 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuId})
1090 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301091 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301092 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001093
1094 tpPath := f.getTPpath(intfId, uni)
1095 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniId, Path: tpPath}
1096 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1097 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1098 tpDownloadMsg,
1099 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1100 f.deviceHandler.deviceType,
1101 onuDevice.Type,
1102 onuDevice.Id,
1103 onuDevice.ProxyAddress.DeviceId, "")
1104 if sendErr != nil {
1105 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1106 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1107 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1108 return sendErr
1109 }
1110 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301111 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301112}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001113
1114// This function adds onu info to cache
1115func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
1116 onu := onuInfo{intfId: intfID, onuId: onuID, serialNumber: serialNum}
1117 onuIDkey := onuIdKey{intfId: intfID, onuId: onuID}
1118 f.onuIds[onuIDkey] = onu
1119 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1120}
1121
1122// This function stores adds GEMport to ONU map
1123func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfId uint32, onuId uint32, gemPort uint32) {
1124 onuIDkey := onuIdKey{intfId: intfId, onuId: onuId}
1125 if val, ok := f.onuIds[onuIDkey]; ok {
1126 onuInfo := val
1127 gemPortKey := gemPortKey{intfId: intfId, gemPort: gemPort}
1128 f.onuGemPortIds[gemPortKey] = onuInfo
1129 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfId, "onuId": onuInfo.onuId})
1130 return
1131 }
1132 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfId, "onuId": onuId, "gemPort": gemPort})
1133}
1134
1135// This function Lookup maps by serialNumber or (intfId, gemPort)
1136// Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1137func (f *OpenOltFlowMgr) getOnuIdfromGemPortMap(serialNumber string, intfId uint32, gemPortId uint32) (uint32, error) {
1138 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfId, "gemPortId": gemPortId})
1139 if serialNumber != "" {
1140 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
1141 return onuInfo.onuId, nil
1142 }
1143 } else {
1144 gemPortKey := gemPortKey{intfId: intfId, gemPort: gemPortId}
1145 if onuInfo, ok := f.onuGemPortIds[gemPortKey]; ok {
1146 log.Debugw("Retrived onu info from access", log.Fields{"intfId": intfId, "gemPortId": gemPortId, "onuId": onuInfo.onuId})
1147 return onuInfo.onuId, nil
1148 }
1149 }
1150 log.Errorw("ONU ID is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfId, "gemPort": gemPortId})
1151 return uint32(0), errors.New("Key Error ,ONU ID is not found") // ONU ID 0 is not a valid one
1152}
1153
1154// This function computes logical port UNI/NNI port from packet-in indication and returns the same
1155func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openolt_pb2.PacketIndication) (uint32, error) {
1156 var logicalPortNum uint32
1157 var onuId uint32
1158 var err error
1159
1160 if packetIn.IntfType == "pon" {
1161 // packet indication does not have serial number , so sending as nil
1162 if onuId, err = f.getOnuIdfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
1163 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1164 return logicalPortNum, err
1165 }
1166 if packetIn.PortNo != 0 {
1167 logicalPortNum = packetIn.PortNo
1168 } else {
1169 uniId := uint32(0) // FIXME - multi-uni support
1170 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuId, uniId)
1171 }
1172 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
1173 pktInkey := packetInInfoKey{intfId: packetIn.IntfId, onuId: onuId, logicalPort: logicalPortNum}
1174 f.packetInGemPort[pktInkey] = packetIn.GemportId
1175 } else if packetIn.IntfType == "nni" {
1176 logicalPortNum = IntfIdToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
1177 }
1178 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1179 return logicalPortNum, nil
1180}
1181
1182func (f *OpenOltFlowMgr) GetPacketOutGemPortId(intfId uint32, onuId uint32, portNum uint32) (uint32, error) {
1183 var gemPortId uint32
1184 var err error
1185 key := packetInInfoKey{intfId: intfId, onuId: onuId, logicalPort: portNum}
1186 if val, ok := f.packetInGemPort[key]; ok {
1187 gemPortId = val
1188 } else {
1189 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
1190 err = errors.New("Key-Error while fetching packet-out GEM port")
1191 }
1192 return gemPortId, err
1193}
1194
1195func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1196 log.Debug("Adding trap-dhcp-of-nni-flow")
1197 action := make(map[string]interface{})
1198 classifier[PACKET_TAG_TYPE] = DOUBLE_TAG
1199 action[TRAP_TO_HOST] = true
1200 /* We manage flowId resource pool on per PON port basis.
1201 Since this situation is tricky, as a hack, we pass the NNI port
1202 index (network_intf_id) as PON port Index for the flowId resource
1203 pool. Also, there is no ONU Id available for trapping DHCP packets
1204 on NNI port, use onu_id as -1 (invalid)
1205 ****************** CAVEAT *******************
1206 This logic works if the NNI Port Id falls within the same valid
1207 range of PON Port Ids. If this doesn't work for some OLT Vendor
1208 we need to have a re-look at this.
1209 *********************************************
1210 */
1211 onuId := -1
1212 uniId := -1
1213 gemPortId := -1
1214 allocId := -1
Girish Gowdru1110ef22019-06-24 11:17:59 -04001215 networkInterfaceId := f.deviceHandler.nniIntfId
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001216 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
1217 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceId), uint32(onuId), uint32(uniId), flowStoreCookie); present {
1218 log.Debug("Flow-exists--not-re-adding")
1219 return
1220 }
1221 flowId, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceId), uint32(onuId), uint32(uniId), flowStoreCookie, "")
1222 if err != nil {
1223 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1224 return
1225 }
1226 var classifierProto *openolt_pb2.Classifier
1227 var actionProto *openolt_pb2.Action
1228 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1229 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1230 return
1231 }
1232 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1233 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1234 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1235 return
1236 }
1237 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1238 downstreamflow := openolt_pb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1239 OnuId: int32(onuId), // OnuId not required
1240 UniId: int32(uniId), // UniId not used
1241 FlowId: flowId,
1242 FlowType: DOWNSTREAM,
Devmalya Paul0099c9c2019-06-10 14:40:30 +05301243 AllocId: int32(allocId), // AllocId not used
1244 NetworkIntfId: int32(networkInterfaceId),
1245 GemportId: int32(gemPortId), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001246 Classifier: classifierProto,
1247 Action: actionProto,
1248 Priority: int32(logicalFlow.Priority),
1249 Cookie: logicalFlow.Cookie,
1250 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001251 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001252 log.Debug("DHCP trap on NNI flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001253 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001254 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceId),
1255 int32(onuId),
1256 int32(uniId),
1257 flowId, flowsToKVStore); err != nil {
1258 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1259 }
1260 }
1261 return
1262}