blob: 1d96d2caccf39ecc54c3d4ed35bfd51999db57de [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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
20import (
21 "context"
22 "crypto/md5"
23 "encoding/json"
24 "errors"
25 "fmt"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "github.com/opencord/voltha-go/common/log"
27 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040028 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053029 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040030 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053031 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070032 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
33 "github.com/opencord/voltha-protos/go/voltha"
manikkaraj k17652a72019-05-06 09:06:36 -040034 "math/big"
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040035 //deepcopy "github.com/getlantern/deepcopy"
manikkaraj kbf256be2019-03-25 00:13:48 +053036)
37
38const (
39 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053040
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070041 //HsiaFlow flow category
42 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053043
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070044 //EapolFlow flow category
45 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053046
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070047 //IPProtoDhcp flow category
48 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoIgmp flow category
51 IPProtoIgmp = 2
52
53 //EapEthType eapethtype value
54 EapEthType = 0x888e
55 //LldpEthType lldp ethtype value
56 LldpEthType = 0x88cc
57
58 //IgmpProto proto value
59 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053060
61 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070062
63 //DefaultMgmtVlan default vlan value
64 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053065
manikkaraj kbf256be2019-03-25 00:13:48 +053066 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067
68 //UPSTREAM constant
69 UPSTREAM = "upstream"
70 //DOWNSTREAM constant
71 DOWNSTREAM = "downstream"
72 //PacketTagType constant
73 PacketTagType = "pkt_tag_type"
74 //UNTAGGED constant
75 UNTAGGED = "untagged"
76 //SingleTag constant
77 SingleTag = "single_tag"
78 //DoubleTag constant
79 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053080
81 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082
83 //EthType constant
84 EthType = "eth_type"
85 //TPID constant
86 TPID = "tpid"
87 //IPProto constant
88 IPProto = "ip_proto"
89 //InPort constant
90 InPort = "in_port"
91 //VlanVid constant
92 VlanVid = "vlan_vid"
93 //VlanPcp constant
94 VlanPcp = "vlan_pcp"
95
96 //UDPDst constant
97 UDPDst = "udp_dst"
98 //UDPSrc constant
99 UDPSrc = "udp_src"
100 //Ipv4Dst constant
101 Ipv4Dst = "ipv4_dst"
102 //Ipv4Src constant
103 Ipv4Src = "ipv4_src"
104 //METADATA constant
105 METADATA = "metadata"
106 //TunnelID constant
107 TunnelID = "tunnel_id"
108 //OUTPUT constant
109 OUTPUT = "output"
110 // Actions
111
112 //PopVlan constant
113 PopVlan = "pop_vlan"
114 //PushVlan constant
115 PushVlan = "push_vlan"
116 //TrapToHost constant
117 TrapToHost = "trap_to_host"
manikkaraj kbf256be2019-03-25 00:13:48 +0530118)
119
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400120type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 intfID uint32
122 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400123 serialNumber string
124}
125
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126type onuIDKey struct {
127 intfID uint32
128 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400129}
130
131type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700132 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400133 gemPort uint32
134}
135
136type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 intfID uint32
138 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400139 logicalPort uint32
140}
141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530143type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400144 techprofile []*tp.TechProfileMgr
145 deviceHandler *DeviceHandler
146 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700147 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400148 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
149 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
150 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
151 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530152}
153
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700154//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530155func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
156 log.Info("Initializing flow manager")
157 var flowMgr OpenOltFlowMgr
158 flowMgr.deviceHandler = dh
159 flowMgr.resourceMgr = rsrcMgr
160 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
161 log.Error("Error while populating tech profile mgr\n")
162 return nil
163 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700164 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400165 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
166 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
167 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530168 log.Info("Initialization of flow manager success!!")
169 return &flowMgr
170}
171
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700172func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400173 if direction == UPSTREAM {
174 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700175 return 0x1<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400176 } else if direction == DOWNSTREAM {
177 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700178 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400179 } else {
180 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400182 }
183}
184
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400186 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400188
189 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400191 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
192 deviceFlow.FlowId, deviceFlow.FlowType))
193 storedFlow.Cookie = flowFromCore.Id
194 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
195 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
199 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530200 var gemPorts []uint32
201
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo, "classifier": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204 log.Infow("sorting flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
manikkaraj kbf256be2019-03-25 00:13:48 +0530205 "classifierInfo": classifierInfo, "actionInfo": actionInfo})
206
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 uni := getUniPortPath(intfID, onuID, uniID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530208 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209 allocID, gemPorts = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, flow.GetTableId())
210 if allocID == nil || gemPorts == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530211 log.Error("alloc-id-gem-ports-unavailable")
212 return
213 }
214
215 /* Flows can't be added specific to gemport unless p-bits are received.
216 * Hence adding flows for all gemports
217 */
218 for _, gemPort := range gemPorts {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219 if ipProto, ok := classifierInfo[IPProto]; ok {
220 if ipProto.(uint32) == IPProtoDhcp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530221 log.Info("Adding DHCP flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700222 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
223 } else if ipProto == IPProtoIgmp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530224 log.Info("igmp flow add ignored, not implemented yet")
225 } else {
226 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
227 //return errors.New("Invalid-Classifier-to-handle")
228 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229 } else if ethType, ok := classifierInfo[EthType]; ok {
230 if ethType.(uint32) == EapEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 log.Info("Adding EAPOL flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700232 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, DefaultMgmtVlan)
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400233 if vlan := getSubscriberVlan(utils.GetInPort(flow)); vlan != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlan)
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 }
236 // Send Techprofile download event to child device in go routine as it takes time
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 if ethType == LldpEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 log.Info("Adding LLDP flow")
241 addLLDPFlow(flow, portNo)
242 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243 } else if _, ok := actionInfo[PushVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530244 log.Info("Adding upstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
246 } else if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530247 log.Info("Adding Downstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700248 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530249 } else {
250 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
251 }
252 }
253}
254
255// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700256func (f *OpenOltFlowMgr) createTcontGemports(intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, tableID uint32) ([]uint32, []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530257 var allocID []uint32
258 var gemPortIDs []uint32
259 //If we already have allocated earlier for this onu, render them
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700260 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
261 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700263 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 if len(allocID) != 0 && len(gemPortIDs) != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 log.Debug("Rendered Tcont and GEM ports from resource manager", log.Fields{"intfId": intfID, "onuId": onuID, "uniPort": uniID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530266 "allocID": allocID, "gemPortIDs": gemPortIDs})
267 return allocID, gemPortIDs
268 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530270
271 //FIXME: If table id is <= 63 using 64 as table id
272 if tableID < tp.DEFAULT_TECH_PROFILE_TABLE_ID {
273 tableID = tp.DEFAULT_TECH_PROFILE_TABLE_ID
274 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700275 tpPath := f.getTPpath(intfID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530276 // Check tech profile instance already exists for derived port name
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700277 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(tableID, tpPath)
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 if err != nil { // This should not happen, something wrong in KV backend transaction
279 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tableID": tableID, "path": tpPath})
280 return nil, nil
281 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530283 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700284 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(tableID, uni, intfID)
285 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530286 log.Error("Tech-profile-instance-creation-failed")
287 return nil, nil
288 }
289 } else {
290 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
291 }
292 // Get upstream and downstream scheduler protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700293 usScheduler := f.techprofile[intfID].GetUsScheduler(techProfileInstance)
294 dsScheduler := f.techprofile[intfID].GetDsScheduler(techProfileInstance)
manikkaraj kbf256be2019-03-25 00:13:48 +0530295 // Get TCONTS protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700296 tconts := f.techprofile[intfID].GetTconts(techProfileInstance, usScheduler, dsScheduler)
manikkaraj kbf256be2019-03-25 00:13:48 +0530297 if len(tconts) == 0 {
298 log.Error("TCONTS not found ")
299 return nil, nil
300 }
301 log.Debugw("Sending Create tcont to device",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700302 log.Fields{"onu": onuID, "uni": uniID, "portNo": "", "tconts": tconts})
manikkaraj kbf256be2019-03-25 00:13:48 +0530303 if _, err := f.deviceHandler.Client.CreateTconts(context.Background(),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700304 &openoltpb2.Tconts{IntfId: intfID,
305 OnuId: onuID,
306 UniId: uniID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530307 PortNo: uniPort,
308 Tconts: tconts}); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400309 log.Errorw("Error while creating TCONT in device", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530310 return nil, nil
311 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700312 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
313 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
manikkaraj kbf256be2019-03-25 00:13:48 +0530314 gemPortIDs = append(gemPortIDs, gem.GemportID)
315 }
316 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
317 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700318 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530319 return allocID, gemPortIDs
320}
321
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700322func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530323
324 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700325 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530326 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700327 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530328 log.Error("Errow while uploading allocID to KV store")
329 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700330 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530331 log.Error("Errow while uploading GEMports to KV store")
332 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700333 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530334 log.Error("Errow while uploading gemtopon map to KV store")
335 }
336 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400337 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700338 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400339 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530340}
341
342func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
343 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700344 for intfID := range techRange.IntfIds {
345 f.techprofile = append(f.techprofile, f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr)
manikkaraj kbf256be2019-03-25 00:13:48 +0530346 }
347 }
348 //Make sure we have as many tech_profiles as there are pon ports on the device
349 if len(f.techprofile) != int(f.resourceMgr.DevInfo.GetPonPorts()) {
350 log.Errorw("Error while populating techprofile",
351 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700352 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530353 }
354 log.Infow("Populated techprofile per ponport successfully",
355 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
356 return nil
357}
358
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700359func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530360 portNo uint32, uplinkClassifier map[string]interface{},
361 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700362 allocID uint32, gemportID uint32) {
363 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530364 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700365 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
366 UPSTREAM, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530367 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530368}
369
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700370func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530371 portNo uint32, downlinkClassifier map[string]interface{},
372 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700373 allocID uint32, gemportID uint32) {
374 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530375 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
376 "downlinkAction": downlinkAction})
manikkaraj k17652a72019-05-06 09:06:36 -0400377 // Ignore private VLAN flow given by decomposer, cannot do anything with this flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700378 if uint32(downlinkClassifier[METADATA].(uint64)) == MkUniPortNum(intfID, onuID, uniID) &&
379 downlinkClassifier[VlanVid] == (uint32(ofp.OfpVlanId_OFPVID_PRESENT)|4000) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530380 log.Infow("EAPOL DL flow , Already added ,ignoring it", log.Fields{"downlinkClassifier": downlinkClassifier,
381 "downlinkAction": downlinkAction})
382 return
383 }
384 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700385 downlinkAction[PopVlan] = true
386 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
387 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
388 DOWNSTREAM, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530389}
390
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700391func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530392 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700393 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530394 /* One of the OLT platform (Broadcom BAL) requires that symmetric
395 flows require the same flow_id to be used across UL and DL.
396 Since HSIA flow is the only symmetric flow currently, we need to
397 re-use the flow_id across both direction. The 'flow_category'
398 takes priority over flow_cookie to find any available HSIA_FLOW
399 id for the ONU.
400 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700401 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
402 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530403 "logicalFlow": *logicalFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400404 flowCategory := "HSIA"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700405 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
406 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, flowCategory)
Manikkaraj k884c1242019-04-11 16:26:42 +0530407 if err != nil {
408 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
409 return
410 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700411 var classifierProto *openoltpb2.Classifier
412 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530413 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
414 log.Error("Error in making classifier protobuf for hsia flow")
415 return
416 }
417 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
418 if actionProto = makeOpenOltActionField(action); actionProto == nil {
419 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
420 return
421 }
422 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700423 networkIntfID := f.deviceHandler.nniIntfID
424 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
425 OnuId: int32(onuID),
426 UniId: int32(uniID),
427 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530428 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700429 AllocId: int32(allocID),
430 NetworkIntfId: int32(networkIntfID),
431 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530432 Classifier: classifierProto,
433 Action: actionProto,
434 Priority: int32(logicalFlow.Priority),
435 Cookie: logicalFlow.Cookie,
436 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400437 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530438 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, "HSIA", flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530440 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
441 flow.OnuId,
442 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400443 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530444 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
445 return
446 }
447 }
448}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449func (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 +0530450
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700451 var dhcpFlow openoltpb2.Flow
452 var actionProto *openoltpb2.Action
453 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530454
455 // Clear the action map
456 for k := range action {
457 delete(action, k)
458 }
459
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460 action[TrapToHost] = true
461 classifier[UDPSrc] = uint32(68)
462 classifier[UDPDst] = uint32(67)
463 classifier[PacketTagType] = SingleTag
464 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530465
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530467
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700468 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530469
470 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530472 return
473 }
474
475 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
476
477 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
478 log.Error("Error in making classifier protobuf for ul flow")
479 return
480 }
481 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
482 if actionProto = makeOpenOltActionField(action); actionProto == nil {
483 log.Error("Error in making action protobuf for ul flow")
484 return
485 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530487
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
489 OnuId: int32(onuID),
490 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530491 FlowId: flowID,
492 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 AllocId: int32(allocID),
494 NetworkIntfId: int32(networkIntfID),
495 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530496 Classifier: classifierProto,
497 Action: actionProto,
498 Priority: int32(logicalFlow.Priority),
499 Cookie: logicalFlow.Cookie,
500 PortNo: portNo}
501
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400502 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530503 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400504 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530505 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
506 dhcpFlow.OnuId,
507 dhcpFlow.UniId,
508 dhcpFlow.FlowId, flowsToKVStore); err != nil {
509 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
510 return
511 }
512 }
513
manikkaraj kbf256be2019-03-25 00:13:48 +0530514 return
515}
516
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
518func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
519 log.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfID, "onuId": onuID, "portNo": portNo, "allocId": allocID, "gemPortId": gemPortID, "vlanId": vlanID, "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530520
521 uplinkClassifier := make(map[string]interface{})
522 uplinkAction := make(map[string]interface{})
523 downlinkClassifier := make(map[string]interface{})
524 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 var upstreamFlow openoltpb2.Flow
526 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530527
528 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529 uplinkClassifier[EthType] = uint32(EapEthType)
530 uplinkClassifier[PacketTagType] = SingleTag
531 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530532 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 uplinkAction[TrapToHost] = true
534 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530535 //Add Uplink EAPOL Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530537 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530539 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530540 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 var classifierProto *openoltpb2.Classifier
542 var actionProto *openoltpb2.Action
543 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530544
545 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
546 log.Error("Error in making classifier protobuf for ul flow")
547 return
548 }
549 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
550 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
551 log.Error("Error in making action protobuf for ul flow")
552 return
553 }
554 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 networkIntfID := f.deviceHandler.nniIntfID
556 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
557 OnuId: int32(onuID),
558 UniId: int32(uniID),
559 FlowId: uplinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530560 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700561 AllocId: int32(allocID),
562 NetworkIntfId: int32(networkIntfID),
563 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530564 Classifier: classifierProto,
565 Action: actionProto,
566 Priority: int32(logicalFlow.Priority),
567 Cookie: logicalFlow.Cookie,
568 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400569 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530570 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400571 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530573 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
574 upstreamFlow.OnuId,
575 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400576 upstreamFlow.FlowId,
577 /* lowCategory, */
578 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530579 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
580 return
581 }
582 }
583
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 if vlanID == DefaultMgmtVlan {
manikkaraj kbf256be2019-03-25 00:13:48 +0530585 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
586 # requirement)
587 # On one of the platforms (Broadcom BAL), when same DL classifier
588 # vlan was used across multiple ONUs, eapol flow re-adds after
589 # flow delete (cases of onu reboot/disable) fails.
590 # In order to generate unique vlan, a combination of intf_id
591 # onu_id and uniId is used.
592 # uniId defaults to 0, so add 1 to it.
593 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
595 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530596 // Assert that we do not generate invalid vlans under no condition
597 if specialVlanDlFlow <= 2 {
598 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
599 return
600 }
601 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
602 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 downlinkClassifier[PacketTagType] = SingleTag
604 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530605 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 downlinkAction[PushVlan] = true
607 downlinkAction[VlanVid] = vlanID
608 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
609 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530610 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530611 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530613 return
614 }
615 log.Debugw("Creating DL EAPOL flow",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530617 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
618 log.Error("Error in making classifier protobuf for downlink flow")
619 return
620 }
621 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
622 log.Error("Error in making action protobuf for dl flow")
623 return
624 }
625 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
627 OnuId: int32(onuID),
628 UniId: int32(uniID),
629 FlowId: downlinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 AllocId: int32(allocID),
632 NetworkIntfId: int32(networkIntfID),
633 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530634 Classifier: classifierProto,
635 Action: actionProto,
636 Priority: int32(logicalFlow.Priority),
637 Cookie: logicalFlow.Cookie,
638 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400639 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530640 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400641 flowCategory := ""
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700642 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530643 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
644 downstreamFlow.OnuId,
645 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400646 downstreamFlow.FlowId,
647 /* flowCategory, */
648 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530649 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
650 return
651 }
652 }
653 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 log.Infow("EAPOL flow with non-default mgmt vlan is not supported", log.Fields{"vlanId": vlanID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530655 return
656 }
657 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
658}
659
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700660func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
661 var classifier openoltpb2.Classifier
662 if etherType, ok := classifierInfo[EthType]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530663 classifier.EthType = etherType.(uint32)
664 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 if ipProto, ok := classifierInfo[IPProto]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530666 classifier.IpProto = ipProto.(uint32)
667 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 if vlanID, ok := classifierInfo[VlanVid]; ok {
669 classifier.OVid = (vlanID.(uint32)) & 0xFFF
manikkaraj kbf256be2019-03-25 00:13:48 +0530670 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530671 if metadata, ok := classifierInfo[METADATA]; ok { // TODO: Revisit
672 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530673 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530675 classifier.OPbits = vlanPcp.(uint32)
676 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530678 classifier.SrcPort = udpSrc.(uint32)
679 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 if udpDst, ok := classifierInfo[UDPDst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530681 classifier.DstPort = udpDst.(uint32)
682 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700683 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530684 classifier.DstIp = ipv4Dst.(uint32)
685 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 if ipv4Src, ok := classifierInfo[Ipv4Src]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530687 classifier.SrcIp = ipv4Src.(uint32)
688 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
690 if pktTagType.(string) == SingleTag {
691 classifier.PktTagType = SingleTag
692 } else if pktTagType.(string) == DoubleTag {
693 classifier.PktTagType = DoubleTag
manikkaraj kbf256be2019-03-25 00:13:48 +0530694 } else if pktTagType.(string) == UNTAGGED {
695 classifier.PktTagType = UNTAGGED
696 } else {
697 log.Error("Invalid tag type in classifier") // should not hit
698 return nil
699 }
700 }
701 return &classifier
702}
703
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700704func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
705 var actionCmd openoltpb2.ActionCmd
706 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530707 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 if _, ok := actionInfo[PopVlan]; ok {
709 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530710 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700711 } else if _, ok := actionInfo[PushVlan]; ok {
712 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530713 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 } else if _, ok := actionInfo[TrapToHost]; ok {
715 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530716 } else {
717 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
718 return nil
719 }
720 return &action
721}
722
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string) string {
manikkaraj kbf256be2019-03-25 00:13:48 +0530724 /*
725 FIXME
726 Should get Table id form the flow, as of now hardcoded to DEFAULT_TECH_PROFILE_TABLE_ID (64)
727 'tp_path' contains the suffix part of the tech_profile_instance path. The prefix to the 'tp_path' should be set to
728 TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
729 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 return f.techprofile[intfID].GetTechProfileInstanceKVPath(tp.DEFAULT_TECH_PROFILE_TABLE_ID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530731}
732
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530734 if len(classifier) == 0 { // should never happen
735 log.Error("Invalid classfier object")
736 return 0
737 }
738 var jsonData []byte
739 var flowString string
740 var err error
741 // TODO: Do we need to marshall ??
742 if jsonData, err = json.Marshal(classifier); err != nil {
743 log.Error("Failed to encode classifier")
744 return 0
745 }
746 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 if gemPortID != 0 {
748 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 }
750 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530752 hash := big.NewInt(0)
753 hash.SetBytes(h.Sum(nil))
754 return hash.Uint64()
755}
756
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
758 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
759 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400760 /* For flows which trap out of the NNI, the AccessIntfId is invalid
761 (set to -1). In such cases, we need to refer to the NetworkIntfId .
762 */
763 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400765 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400767 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 // Get existing flows matching flowid for given subscriber from KV store
769 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400770 if existingFlows != nil {
771 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 //for _, f := range *existingFlows {
773 // flows = append(flows, f)
774 //}
775 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400776 }
777 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 +0530778 return &flows
779}
780
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400781//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
782// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
783// var intfId uint32
784// /* For flows which trap out of the NNI, the AccessIntfId is invalid
785// (set to -1). In such cases, we need to refer to the NetworkIntfId .
786// */
787// if flow.AccessIntfId != -1 {
788// intfId = uint32(flow.AccessIntfId)
789// } else {
790// intfId = uint32(flow.NetworkIntfId)
791// }
792// // Get existing flows matching flowid for given subscriber from KV store
793// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
794// if existingFlows != nil {
795// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
796// for _, f := range *existingFlows {
797// flows = append(flows, f)
798// }
799// }
800// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
801// return &flows
802//}
803
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400805 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400807 log.Debug("Error while Storing flow into KV store")
808 return err
809 }
810 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 return nil
812}
813
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700814func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
manikkaraj kbf256be2019-03-25 00:13:48 +0530815 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
816 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
817 if err != nil {
818 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
819 return false
820 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700821 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
822 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400823 f.registerFlow(logicalFlow, deviceFlow)
824 return true
825}
826
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700827func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400828 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
829 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
830 if err != nil {
831 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
832 return false
833 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700834 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 return true
836}
837
838/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
839 //update core flows_proxy : flows_proxy.update('/', flows)
840}
841
842func generateStoredId(flowId uint32, direction string)uint32{
843
844 if direction == UPSTREAM{
845 log.Debug("Upstream flow shifting flowid")
846 return ((0x1 << 15) | flowId)
847 }else if direction == DOWNSTREAM{
848 log.Debug("Downstream flow not shifting flowid")
849 return flowId
850 }else{
851 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
852 return flowId
853 }
854}
855
856*/
857
858func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700859 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +0530860}
861
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
863 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
864}
865
866//getOnuChildDevice to fetch onu
867func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
868 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
869 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
870 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530871 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700872 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +0530873 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530875 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
876 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530877}
878
879func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700880 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 return nil
882}
883
884func getSubscriberVlan(inPort uint32) uint32 {
885 /* For EAPOL case we will use default VLAN , so will implement later if required */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700886 log.Info("unimplemented inport %v", inPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 return 0
888}
889
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
891 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530892}
893
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400895 if id>>15 == 0x1 {
896 return id & 0x7fff, UPSTREAM
897 }
898 return id, DOWNSTREAM
899}
900
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700901func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
902 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
903 ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400904 if err != nil {
905 log.Error(err)
906 return
907 }
908 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700909 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400910
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400912 if flowsInfo == nil {
913 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400915 return
916 }
917 var updatedFlows []rsrcMgr.FlowInfo
918
919 for _, flow := range *flowsInfo {
920 updatedFlows = append(updatedFlows, flow)
921 }
922
923 for i, storedFlow := range updatedFlows {
924 if flowDirection == storedFlow.Flow.FlowType {
925 //Remove the Flow from FlowInfo
926 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
927 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
928 break
929 }
930 }
931
932 if len(updatedFlows) >= 0 {
933 // There are still flows referencing the same flow_id.
934 // So the flow should not be freed yet.
935 // For ex: Case of HSIA where same flow is shared
936 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400938 return
939 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700940 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
941 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
942 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400943 if len(flowIds) == 0 {
944 /* TODO: Remove Upstream and Downstream Schedulers */
945 }
946}
947
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700948//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400949func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
950 log.Debugw("Removing Flow", log.Fields{"flow": flow})
951 var deviceFlowsToRemove []ofp.OfpFlowStats
952 var deletedFlowsIdx []int
953 for _, curFlow := range f.storedDeviceFlows {
954 if curFlow.Cookie == flow.Id {
955 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
956 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
957 }
958 }
959 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
960 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961 id, direction := f.decodeStoredID(curFlow.GetId())
962 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400963 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
964 log.Debug("Flow removed from device successfully")
965 deletedFlowsIdx = append(deletedFlowsIdx, index)
966 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
967 }
968
969 }
970 // Can be done in separate go routine as it takes time ?
971 for _, flowToRemove := range deletedFlowsIdx {
972 for index, storedFlow := range f.storedDeviceFlows {
973 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
974 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
975 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
976 break
977 }
978 }
979 }
980 log.Debugw("Flows removed from the data store",
981 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
982 return
983}
984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985// AddFlow add flow to device
manikkaraj kbf256be2019-03-25 00:13:48 +0530986func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 classifierInfo := make(map[string]interface{})
988 actionInfo := make(map[string]interface{})
manikkaraj kbf256be2019-03-25 00:13:48 +0530989 log.Debug("Adding Flow", log.Fields{"flow": flow})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400990 for _, field := range utils.GetOfbFields(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 f.updateClassifierInfo(field, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400993 for _, action := range utils.GetActions(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 f.updateFlowActionInfo(action, actionInfo, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +0530995 }
manikkaraj k17652a72019-05-06 09:06:36 -0400996 /* Controller bound trap flows */
997 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
998 log.Debug("Controller bound trap flows, getting inport from tunnelid")
999 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001001 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 classifierInfo[InPort] = uniPort
1003 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
manikkaraj kbf256be2019-03-25 00:13:48 +05301004 } else {
manikkaraj k17652a72019-05-06 09:06:36 -04001005 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1006 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301007 }
1008 }
manikkaraj k17652a72019-05-06 09:06:36 -04001009 } else {
1010 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1011 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 if portType := IntfIDToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001013 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001014 actionInfo[OUTPUT] = uniPort
1015 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1016 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
manikkaraj k17652a72019-05-06 09:06:36 -04001018 return
1019 }
1020 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001022 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 classifierInfo[InPort] = uniPort
manikkaraj k17652a72019-05-06 09:06:36 -04001024 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1025 "outport": actionInfo[OUTPUT].(uint32)})
1026 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
manikkaraj k17652a72019-05-06 09:06:36 -04001028 "outPort": actionInfo[OUTPUT].(uint32)})
1029 return
1030 }
1031 }
1032 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[OUTPUT]})
1034 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[OUTPUT].(uint32))
1035 if ipProto, ok := classifierInfo[IPProto]; ok {
1036 if ipProto.(uint32) == IPProtoDhcp {
1037 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001038 if udpSrc.(uint32) == uint32(67) {
1039 log.Debug("trap-dhcp-from-nni-flow")
1040 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1041 return
1042 }
1043 }
1044 }
1045 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301047}
1048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001049func (f *OpenOltFlowMgr) updateClassifierInfo(field *ofp.OfpOxmOfbField, classifierInfo map[string]interface{}) {
1050 if field.Type == utils.ETH_TYPE {
1051 classifierInfo[EthType] = field.GetEthType()
1052 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1053 } else if field.Type == utils.IP_PROTO {
1054 classifierInfo[IPProto] = field.GetIpProto()
1055 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1056 } else if field.Type == utils.IN_PORT {
1057 classifierInfo[InPort] = field.GetPort()
1058 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1059 } else if field.Type == utils.VLAN_VID {
1060 classifierInfo[VlanVid] = field.GetVlanVid()
1061 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1062 } else if field.Type == utils.VLAN_PCP {
1063 classifierInfo[VlanPcp] = field.GetVlanPcp()
1064 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1065 } else if field.Type == utils.UDP_DST {
1066 classifierInfo[UDPDst] = field.GetUdpDst()
1067 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1068 } else if field.Type == utils.UDP_SRC {
1069 classifierInfo[UDPSrc] = field.GetUdpSrc()
1070 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1071 } else if field.Type == utils.IPV4_DST {
1072 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1073 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1074 } else if field.Type == utils.IPV4_SRC {
1075 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1076 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1077 } else if field.Type == utils.METADATA {
1078 classifierInfo[METADATA] = field.GetTableMetadata()
1079 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
1080 } else if field.Type == utils.TUNNEL_ID {
1081 classifierInfo[TunnelID] = field.GetTunnelId()
1082 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1083 } else {
1084 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1085 return
1086 }
1087}
manikkaraj kbf256be2019-03-25 00:13:48 +05301088
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001089func (f *OpenOltFlowMgr) updateFlowActionInfo(action *ofp.OfpAction, actionInfo map[string]interface{}, classifierInfo map[string]interface{}) {
1090 if action.Type == utils.OUTPUT {
1091 if out := action.GetOutput(); out != nil {
1092 actionInfo[OUTPUT] = out.GetPort()
1093 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
1094 } else {
1095 log.Error("Invalid output port in action")
1096 return
1097 }
1098 } else if action.Type == utils.POP_VLAN {
1099 actionInfo[PopVlan] = true
1100 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1101 } else if action.Type == utils.PUSH_VLAN {
1102 if out := action.GetPush(); out != nil {
1103 if tpid := out.GetEthertype(); tpid != 0x8100 {
1104 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1105 } else {
1106 actionInfo[PushVlan] = true
1107 actionInfo[TPID] = tpid
1108 log.Debugw("action-type-push-vlan",
1109 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1110 }
1111 }
1112 } else if action.Type == utils.SET_FIELD {
1113 if out := action.GetSetField(); out != nil {
1114 if field := out.GetField(); field != nil {
1115 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1116 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1117 return
1118 }
1119 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1120 if ofbField := field.GetOfbField(); ofbField != nil {
1121 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1122 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1123 actionInfo[VlanVid] = vlan & 0xfff
1124 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1125 } else {
1126 log.Error("No Invalid vlan id in set vlan-vid action")
1127 }
1128 } else {
1129 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1130 }
1131 }
1132 }
1133 }
1134 } else {
1135 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1136 return
1137 }
1138}
1139
1140//sendTPDownloadMsgToChild send payload
1141func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string) error {
1142
1143 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301144 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001145 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301146 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301147 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301148 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001149
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 tpPath := f.getTPpath(intfID, uni)
1151 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001152 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1153 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1154 tpDownloadMsg,
1155 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1156 f.deviceHandler.deviceType,
1157 onuDevice.Type,
1158 onuDevice.Id,
1159 onuDevice.ProxyAddress.DeviceId, "")
1160 if sendErr != nil {
1161 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1162 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1163 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1164 return sendErr
1165 }
1166 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301167 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301168}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001171func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1173 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001174 f.onuIds[onuIDkey] = onu
1175 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1176}
1177
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001178//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1179func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1180 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001181 if val, ok := f.onuIds[onuIDkey]; ok {
1182 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001183 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1184 f.onuGemPortIds[gemportKey] = onuInfo
1185 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001186 return
1187 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001189}
1190
1191// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192
1193//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1194func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1195 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001196 if serialNumber != "" {
1197 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001199 }
1200 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1202 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1203 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1204 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001205 }
1206 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001207 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1208 return uint32(0), errors.New("key error, onuid is not found") // ONU ID 0 is not a valid one
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001209}
1210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001211//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1212func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001213 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001215 var err error
1216
1217 if packetIn.IntfType == "pon" {
1218 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001219 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001220 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1221 return logicalPortNum, err
1222 }
1223 if packetIn.PortNo != 0 {
1224 logicalPortNum = packetIn.PortNo
1225 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226 uniID := uint32(0) // FIXME - multi-uni support
1227 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001228 }
1229 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001230 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001231 f.packetInGemPort[pktInkey] = packetIn.GemportId
1232 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001233 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001234 }
1235 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1236 return logicalPortNum, nil
1237}
1238
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001239//GetPacketOutGemPortID returns gemPortId
1240func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1241 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001242 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001243 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001244 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001246 } else {
1247 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001249 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001250 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001251}
1252
1253func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1254 log.Debug("Adding trap-dhcp-of-nni-flow")
1255 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 classifier[PacketTagType] = DoubleTag
1257 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001258 /* We manage flowId resource pool on per PON port basis.
1259 Since this situation is tricky, as a hack, we pass the NNI port
1260 index (network_intf_id) as PON port Index for the flowId resource
1261 pool. Also, there is no ONU Id available for trapping DHCP packets
1262 on NNI port, use onu_id as -1 (invalid)
1263 ****************** CAVEAT *******************
1264 This logic works if the NNI Port Id falls within the same valid
1265 range of PON Port Ids. If this doesn't work for some OLT Vendor
1266 we need to have a re-look at this.
1267 *********************************************
1268 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 onuID := -1
1270 uniID := -1
1271 gemPortID := -1
1272 allocID := -1
1273 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001274 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001276 log.Debug("Flow-exists--not-re-adding")
1277 return
1278 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie, "")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001280 if err != nil {
1281 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1282 return
1283 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001284 var classifierProto *openoltpb2.Classifier
1285 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001286 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1287 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1288 return
1289 }
1290 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1291 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1292 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1293 return
1294 }
1295 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1297 OnuId: int32(onuID), // OnuId not required
1298 UniId: int32(uniID), // UniId not used
1299 FlowId: flowID,
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001300 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301 AllocId: int32(allocID), // AllocId not used
1302 NetworkIntfId: int32(networkInterfaceID),
1303 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001304 Classifier: classifierProto,
1305 Action: actionProto,
1306 Priority: int32(logicalFlow.Priority),
1307 Cookie: logicalFlow.Cookie,
1308 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001309 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001310 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001311 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1312 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1313 int32(onuID),
1314 int32(uniID),
1315 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001316 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1317 }
1318 }
1319 return
1320}