blob: 498f6e7207ccb0e59fcd3dc8b2f92c4a05632168 [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"
Daniele Rossi22db98e2019-07-11 11:50:00 +000036 "google.golang.org/grpc/codes"
37 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053038)
39
40const (
41 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053042
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070043 //HsiaFlow flow category
44 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //EapolFlow flow category
47 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //IPProtoDhcp flow category
50 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070052 //IPProtoIgmp flow category
53 IPProtoIgmp = 2
54
55 //EapEthType eapethtype value
56 EapEthType = 0x888e
57 //LldpEthType lldp ethtype value
58 LldpEthType = 0x88cc
59
60 //IgmpProto proto value
61 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053062
63 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
65 //DefaultMgmtVlan default vlan value
66 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053067
manikkaraj kbf256be2019-03-25 00:13:48 +053068 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069
70 //UPSTREAM constant
71 UPSTREAM = "upstream"
72 //DOWNSTREAM constant
73 DOWNSTREAM = "downstream"
74 //PacketTagType constant
75 PacketTagType = "pkt_tag_type"
76 //UNTAGGED constant
77 UNTAGGED = "untagged"
78 //SingleTag constant
79 SingleTag = "single_tag"
80 //DoubleTag constant
81 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053082
83 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084
85 //EthType constant
86 EthType = "eth_type"
87 //TPID constant
88 TPID = "tpid"
89 //IPProto constant
90 IPProto = "ip_proto"
91 //InPort constant
92 InPort = "in_port"
93 //VlanVid constant
94 VlanVid = "vlan_vid"
95 //VlanPcp constant
96 VlanPcp = "vlan_pcp"
97
98 //UDPDst constant
99 UDPDst = "udp_dst"
100 //UDPSrc constant
101 UDPSrc = "udp_src"
102 //Ipv4Dst constant
103 Ipv4Dst = "ipv4_dst"
104 //Ipv4Src constant
105 Ipv4Src = "ipv4_src"
106 //METADATA constant
107 METADATA = "metadata"
108 //TunnelID constant
109 TunnelID = "tunnel_id"
110 //OUTPUT constant
111 OUTPUT = "output"
112 // Actions
113
114 //PopVlan constant
115 PopVlan = "pop_vlan"
116 //PushVlan constant
117 PushVlan = "push_vlan"
118 //TrapToHost constant
119 TrapToHost = "trap_to_host"
manikkaraj kbf256be2019-03-25 00:13:48 +0530120)
121
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400122type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 intfID uint32
124 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400125 serialNumber string
126}
127
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700128type onuIDKey struct {
129 intfID uint32
130 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400131}
132
133type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400135 gemPort uint32
136}
137
138type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 intfID uint32
140 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400141 logicalPort uint32
142}
143
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700144//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530145type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400146 techprofile []*tp.TechProfileMgr
147 deviceHandler *DeviceHandler
148 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700149 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400150 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
151 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
152 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
153 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530154}
155
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700156//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530157func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
158 log.Info("Initializing flow manager")
159 var flowMgr OpenOltFlowMgr
160 flowMgr.deviceHandler = dh
161 flowMgr.resourceMgr = rsrcMgr
162 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
163 log.Error("Error while populating tech profile mgr\n")
164 return nil
165 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400167 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
168 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
169 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530170 log.Info("Initialization of flow manager success!!")
171 return &flowMgr
172}
173
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400175 if direction == UPSTREAM {
176 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700177 return 0x1<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400178 } else if direction == DOWNSTREAM {
179 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700180 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400181 } else {
182 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700183 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400184 }
185}
186
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400188 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400190
191 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400193 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
194 deviceFlow.FlowId, deviceFlow.FlowType))
195 storedFlow.Cookie = flowFromCore.Id
196 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
197 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
198}
199
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700200func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
201 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530202 var gemPorts []uint32
Matt Jeanneret77199612019-07-26 18:08:35 -0400203 var uni string
manikkaraj kbf256be2019-03-25 00:13:48 +0530204
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700205 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 +0530206
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 log.Infow("sorting flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
manikkaraj kbf256be2019-03-25 00:13:48 +0530208 "classifierInfo": classifierInfo, "actionInfo": actionInfo})
209
Matt Jeanneret77199612019-07-26 18:08:35 -0400210 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
211 // is because the flow is an NNI flow and there would be no onu resources associated with it
212 // TODO: properly deal with NNI flows
213 if onuID > 0 {
214 uni = getUniPortPath(intfID, onuID, uniID)
215 log.Debugw("Uni port name", log.Fields{"uni": uni})
216 allocID, gemPorts = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, flow.GetTableId())
217 if allocID == nil || gemPorts == nil {
218 log.Error("alloc-id-gem-ports-unavailable")
219 return
220 }
221 log.Debugw("Generated required alloc and gemport ids", log.Fields{"alloc_id": allocID, "gemPorts": gemPorts})
222 } else {
223 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530224 return
225 }
226
227 /* Flows can't be added specific to gemport unless p-bits are received.
228 * Hence adding flows for all gemports
229 */
230 for _, gemPort := range gemPorts {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700231 if ipProto, ok := classifierInfo[IPProto]; ok {
232 if ipProto.(uint32) == IPProtoDhcp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 log.Info("Adding DHCP flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700235 } else if ipProto.(uint32) == IPProtoIgmp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 log.Info("igmp flow add ignored, not implemented yet")
237 } else {
238 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
239 //return errors.New("Invalid-Classifier-to-handle")
240 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700241 } else if ethType, ok := classifierInfo[EthType]; ok {
242 if ethType.(uint32) == EapEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530243 log.Info("Adding EAPOL flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700244 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, DefaultMgmtVlan)
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400245 if vlan := getSubscriberVlan(utils.GetInPort(flow)); vlan != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700246 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlan)
manikkaraj kbf256be2019-03-25 00:13:48 +0530247 }
248 // Send Techprofile download event to child device in go routine as it takes time
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700249 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700251 if ethType == LldpEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530252 log.Info("Adding LLDP flow")
253 addLLDPFlow(flow, portNo)
254 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700255 } else if _, ok := actionInfo[PushVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530256 log.Info("Adding upstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700257 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
258 } else if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 log.Info("Adding Downstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700260 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530261 } else {
262 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
263 }
264 }
265}
266
267// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268func (f *OpenOltFlowMgr) createTcontGemports(intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, tableID uint32) ([]uint32, []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530269 var allocID []uint32
270 var gemPortIDs []uint32
271 //If we already have allocated earlier for this onu, render them
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
273 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530274 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700275 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530276 if len(allocID) != 0 && len(gemPortIDs) != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700277 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 +0530278 "allocID": allocID, "gemPortIDs": gemPortIDs})
279 return allocID, gemPortIDs
280 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700281 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530282
283 //FIXME: If table id is <= 63 using 64 as table id
284 if tableID < tp.DEFAULT_TECH_PROFILE_TABLE_ID {
285 tableID = tp.DEFAULT_TECH_PROFILE_TABLE_ID
286 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700287 tpPath := f.getTPpath(intfID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530288 // Check tech profile instance already exists for derived port name
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700289 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(tableID, tpPath)
manikkaraj kbf256be2019-03-25 00:13:48 +0530290 if err != nil { // This should not happen, something wrong in KV backend transaction
291 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tableID": tableID, "path": tpPath})
292 return nil, nil
293 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700294 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530295 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700296 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(tableID, uni, intfID)
297 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530298 log.Error("Tech-profile-instance-creation-failed")
299 return nil, nil
300 }
301 } else {
302 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
303 }
304 // Get upstream and downstream scheduler protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700305 usScheduler := f.techprofile[intfID].GetUsScheduler(techProfileInstance)
306 dsScheduler := f.techprofile[intfID].GetDsScheduler(techProfileInstance)
manikkaraj kbf256be2019-03-25 00:13:48 +0530307 // Get TCONTS protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700308 tconts := f.techprofile[intfID].GetTconts(techProfileInstance, usScheduler, dsScheduler)
manikkaraj kbf256be2019-03-25 00:13:48 +0530309 if len(tconts) == 0 {
310 log.Error("TCONTS not found ")
311 return nil, nil
312 }
313 log.Debugw("Sending Create tcont to device",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700314 log.Fields{"onu": onuID, "uni": uniID, "portNo": "", "tconts": tconts})
manikkaraj kbf256be2019-03-25 00:13:48 +0530315 if _, err := f.deviceHandler.Client.CreateTconts(context.Background(),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700316 &openoltpb2.Tconts{IntfId: intfID,
317 OnuId: onuID,
318 UniId: uniID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530319 PortNo: uniPort,
320 Tconts: tconts}); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400321 log.Errorw("Error while creating TCONT in device", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530322 return nil, nil
323 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700324 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
325 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
manikkaraj kbf256be2019-03-25 00:13:48 +0530326 gemPortIDs = append(gemPortIDs, gem.GemportID)
327 }
328 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
329 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700330 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530331 return allocID, gemPortIDs
332}
333
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700334func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530335
336 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700337 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530338 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700339 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530340 log.Error("Errow while uploading allocID to KV store")
341 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700342 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530343 log.Error("Errow while uploading GEMports to KV store")
344 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700345 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530346 log.Error("Errow while uploading gemtopon map to KV store")
347 }
348 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400349 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700350 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400351 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530352}
353
354func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
355 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700356 for intfID := range techRange.IntfIds {
357 f.techprofile = append(f.techprofile, f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr)
manikkaraj kbf256be2019-03-25 00:13:48 +0530358 }
359 }
360 //Make sure we have as many tech_profiles as there are pon ports on the device
361 if len(f.techprofile) != int(f.resourceMgr.DevInfo.GetPonPorts()) {
362 log.Errorw("Error while populating techprofile",
363 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700364 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530365 }
366 log.Infow("Populated techprofile per ponport successfully",
367 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
368 return nil
369}
370
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700371func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530372 portNo uint32, uplinkClassifier map[string]interface{},
373 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700374 allocID uint32, gemportID uint32) {
375 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530376 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700377 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
378 UPSTREAM, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530379 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530380}
381
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700382func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530383 portNo uint32, downlinkClassifier map[string]interface{},
384 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700385 allocID uint32, gemportID uint32) {
386 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530387 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
388 "downlinkAction": downlinkAction})
manikkaraj k17652a72019-05-06 09:06:36 -0400389 // Ignore private VLAN flow given by decomposer, cannot do anything with this flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700390 if uint32(downlinkClassifier[METADATA].(uint64)) == MkUniPortNum(intfID, onuID, uniID) &&
391 downlinkClassifier[VlanVid] == (uint32(ofp.OfpVlanId_OFPVID_PRESENT)|4000) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530392 log.Infow("EAPOL DL flow , Already added ,ignoring it", log.Fields{"downlinkClassifier": downlinkClassifier,
393 "downlinkAction": downlinkAction})
394 return
395 }
396 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700397 downlinkAction[PopVlan] = true
398 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
399 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
400 DOWNSTREAM, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530401}
402
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530404 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700405 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530406 /* One of the OLT platform (Broadcom BAL) requires that symmetric
407 flows require the same flow_id to be used across UL and DL.
408 Since HSIA flow is the only symmetric flow currently, we need to
409 re-use the flow_id across both direction. The 'flow_category'
410 takes priority over flow_cookie to find any available HSIA_FLOW
411 id for the ONU.
412 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700413 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
414 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530415 "logicalFlow": *logicalFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400416 flowCategory := "HSIA"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700417 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
418 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, flowCategory)
Manikkaraj k884c1242019-04-11 16:26:42 +0530419 if err != nil {
420 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
421 return
422 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700423 var classifierProto *openoltpb2.Classifier
424 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530425 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
426 log.Error("Error in making classifier protobuf for hsia flow")
427 return
428 }
429 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
430 if actionProto = makeOpenOltActionField(action); actionProto == nil {
431 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
432 return
433 }
434 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700435 networkIntfID := f.deviceHandler.nniIntfID
436 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
437 OnuId: int32(onuID),
438 UniId: int32(uniID),
439 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530440 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 AllocId: int32(allocID),
442 NetworkIntfId: int32(networkIntfID),
443 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530444 Classifier: classifierProto,
445 Action: actionProto,
446 Priority: int32(logicalFlow.Priority),
447 Cookie: logicalFlow.Cookie,
448 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400449 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530450 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700451 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, "HSIA", flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530452 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
453 flow.OnuId,
454 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400455 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530456 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
457 return
458 }
459 }
460}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700461func (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 +0530462
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 var dhcpFlow openoltpb2.Flow
464 var actionProto *openoltpb2.Action
465 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530466
467 // Clear the action map
468 for k := range action {
469 delete(action, k)
470 }
471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700472 action[TrapToHost] = true
473 classifier[UDPSrc] = uint32(68)
474 classifier[UDPDst] = uint32(67)
475 classifier[PacketTagType] = SingleTag
476 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530479
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530481
482 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530484 return
485 }
486
487 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
488
489 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
490 log.Error("Error in making classifier protobuf for ul flow")
491 return
492 }
493 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
494 if actionProto = makeOpenOltActionField(action); actionProto == nil {
495 log.Error("Error in making action protobuf for ul flow")
496 return
497 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700498 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530499
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
501 OnuId: int32(onuID),
502 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530503 FlowId: flowID,
504 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 AllocId: int32(allocID),
506 NetworkIntfId: int32(networkIntfID),
507 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530508 Classifier: classifierProto,
509 Action: actionProto,
510 Priority: int32(logicalFlow.Priority),
511 Cookie: logicalFlow.Cookie,
512 PortNo: portNo}
513
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400514 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530515 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400516 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530517 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
518 dhcpFlow.OnuId,
519 dhcpFlow.UniId,
520 dhcpFlow.FlowId, flowsToKVStore); err != nil {
521 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
522 return
523 }
524 }
525
manikkaraj kbf256be2019-03-25 00:13:48 +0530526 return
527}
528
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
530func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
531 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 +0530532
533 uplinkClassifier := make(map[string]interface{})
534 uplinkAction := make(map[string]interface{})
535 downlinkClassifier := make(map[string]interface{})
536 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700537 var upstreamFlow openoltpb2.Flow
538 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530539
540 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 uplinkClassifier[EthType] = uint32(EapEthType)
542 uplinkClassifier[PacketTagType] = SingleTag
543 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530544 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700545 uplinkAction[TrapToHost] = true
546 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530547 //Add Uplink EAPOL Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530549 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530551 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530552 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 var classifierProto *openoltpb2.Classifier
554 var actionProto *openoltpb2.Action
555 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530556
557 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
558 log.Error("Error in making classifier protobuf for ul flow")
559 return
560 }
561 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
562 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
563 log.Error("Error in making action protobuf for ul flow")
564 return
565 }
566 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567 networkIntfID := f.deviceHandler.nniIntfID
568 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
569 OnuId: int32(onuID),
570 UniId: int32(uniID),
571 FlowId: uplinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530572 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 AllocId: int32(allocID),
574 NetworkIntfId: int32(networkIntfID),
575 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530576 Classifier: classifierProto,
577 Action: actionProto,
578 Priority: int32(logicalFlow.Priority),
579 Cookie: logicalFlow.Cookie,
580 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400581 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530582 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400583 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530585 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
586 upstreamFlow.OnuId,
587 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400588 upstreamFlow.FlowId,
589 /* lowCategory, */
590 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530591 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
592 return
593 }
594 }
595
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700596 if vlanID == DefaultMgmtVlan {
manikkaraj kbf256be2019-03-25 00:13:48 +0530597 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
598 # requirement)
599 # On one of the platforms (Broadcom BAL), when same DL classifier
600 # vlan was used across multiple ONUs, eapol flow re-adds after
601 # flow delete (cases of onu reboot/disable) fails.
602 # In order to generate unique vlan, a combination of intf_id
603 # onu_id and uniId is used.
604 # uniId defaults to 0, so add 1 to it.
605 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
607 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530608 // Assert that we do not generate invalid vlans under no condition
609 if specialVlanDlFlow <= 2 {
610 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
611 return
612 }
613 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
614 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 downlinkClassifier[PacketTagType] = SingleTag
616 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530617 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 downlinkAction[PushVlan] = true
619 downlinkAction[VlanVid] = vlanID
620 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
621 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530622 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530623 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530625 return
626 }
627 log.Debugw("Creating DL EAPOL flow",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530629 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
630 log.Error("Error in making classifier protobuf for downlink flow")
631 return
632 }
633 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
634 log.Error("Error in making action protobuf for dl flow")
635 return
636 }
637 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
639 OnuId: int32(onuID),
640 UniId: int32(uniID),
641 FlowId: downlinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530642 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 AllocId: int32(allocID),
644 NetworkIntfId: int32(networkIntfID),
645 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530646 Classifier: classifierProto,
647 Action: actionProto,
648 Priority: int32(logicalFlow.Priority),
649 Cookie: logicalFlow.Cookie,
650 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400651 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530652 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400653 flowCategory := ""
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530655 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
656 downstreamFlow.OnuId,
657 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400658 downstreamFlow.FlowId,
659 /* flowCategory, */
660 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530661 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
662 return
663 }
664 }
665 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 log.Infow("EAPOL flow with non-default mgmt vlan is not supported", log.Fields{"vlanId": vlanID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530667 return
668 }
669 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
670}
671
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
673 var classifier openoltpb2.Classifier
674 if etherType, ok := classifierInfo[EthType]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530675 classifier.EthType = etherType.(uint32)
676 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 if ipProto, ok := classifierInfo[IPProto]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530678 classifier.IpProto = ipProto.(uint32)
679 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 if vlanID, ok := classifierInfo[VlanVid]; ok {
681 classifier.OVid = (vlanID.(uint32)) & 0xFFF
manikkaraj kbf256be2019-03-25 00:13:48 +0530682 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530683 if metadata, ok := classifierInfo[METADATA]; ok { // TODO: Revisit
684 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530685 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530687 classifier.OPbits = vlanPcp.(uint32)
688 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530690 classifier.SrcPort = udpSrc.(uint32)
691 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 if udpDst, ok := classifierInfo[UDPDst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530693 classifier.DstPort = udpDst.(uint32)
694 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530696 classifier.DstIp = ipv4Dst.(uint32)
697 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 if ipv4Src, ok := classifierInfo[Ipv4Src]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530699 classifier.SrcIp = ipv4Src.(uint32)
700 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
702 if pktTagType.(string) == SingleTag {
703 classifier.PktTagType = SingleTag
704 } else if pktTagType.(string) == DoubleTag {
705 classifier.PktTagType = DoubleTag
manikkaraj kbf256be2019-03-25 00:13:48 +0530706 } else if pktTagType.(string) == UNTAGGED {
707 classifier.PktTagType = UNTAGGED
708 } else {
709 log.Error("Invalid tag type in classifier") // should not hit
710 return nil
711 }
712 }
713 return &classifier
714}
715
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700716func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
717 var actionCmd openoltpb2.ActionCmd
718 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530719 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 if _, ok := actionInfo[PopVlan]; ok {
721 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530722 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723 } else if _, ok := actionInfo[PushVlan]; ok {
724 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530725 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 } else if _, ok := actionInfo[TrapToHost]; ok {
727 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530728 } else {
729 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
730 return nil
731 }
732 return &action
733}
734
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string) string {
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 /*
737 FIXME
738 Should get Table id form the flow, as of now hardcoded to DEFAULT_TECH_PROFILE_TABLE_ID (64)
739 'tp_path' contains the suffix part of the tech_profile_instance path. The prefix to the 'tp_path' should be set to
740 TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
741 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 return f.techprofile[intfID].GetTechProfileInstanceKVPath(tp.DEFAULT_TECH_PROFILE_TABLE_ID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530743}
744
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530746 if len(classifier) == 0 { // should never happen
747 log.Error("Invalid classfier object")
748 return 0
749 }
750 var jsonData []byte
751 var flowString string
752 var err error
753 // TODO: Do we need to marshall ??
754 if jsonData, err = json.Marshal(classifier); err != nil {
755 log.Error("Failed to encode classifier")
756 return 0
757 }
758 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 if gemPortID != 0 {
760 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530761 }
762 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530764 hash := big.NewInt(0)
765 hash.SetBytes(h.Sum(nil))
766 return hash.Uint64()
767}
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
770 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
771 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400772 /* For flows which trap out of the NNI, the AccessIntfId is invalid
773 (set to -1). In such cases, we need to refer to the NetworkIntfId .
774 */
775 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400777 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400779 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780 // Get existing flows matching flowid for given subscriber from KV store
781 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400782 if existingFlows != nil {
783 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 //for _, f := range *existingFlows {
785 // flows = append(flows, f)
786 //}
787 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400788 }
789 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 +0530790 return &flows
791}
792
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400793//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
794// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
795// var intfId uint32
796// /* For flows which trap out of the NNI, the AccessIntfId is invalid
797// (set to -1). In such cases, we need to refer to the NetworkIntfId .
798// */
799// if flow.AccessIntfId != -1 {
800// intfId = uint32(flow.AccessIntfId)
801// } else {
802// intfId = uint32(flow.NetworkIntfId)
803// }
804// // Get existing flows matching flowid for given subscriber from KV store
805// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
806// if existingFlows != nil {
807// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
808// for _, f := range *existingFlows {
809// flows = append(flows, f)
810// }
811// }
812// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
813// return &flows
814//}
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400817 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400819 log.Debug("Error while Storing flow into KV store")
820 return err
821 }
822 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 return nil
824}
825
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700826func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000827
828 var intfID uint32
829 /* For flows which trap out of the NNI, the AccessIntfId is invalid
830 (set to -1). In such cases, we need to refer to the NetworkIntfId .
831 */
832 if deviceFlow.AccessIntfId != -1 {
833 intfID = uint32(deviceFlow.AccessIntfId)
834 } else {
835 intfID = uint32(deviceFlow.NetworkIntfId)
836 }
837
manikkaraj kbf256be2019-03-25 00:13:48 +0530838 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
839 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000840
841 st, _ := status.FromError(err)
842 if st.Code() == codes.AlreadyExists {
843 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 return false
845 }
Daniele Rossi22db98e2019-07-11 11:50:00 +0000846
847 if err != nil {
848 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
849 f.resourceMgr.FreeFlowID(intfID, uint32(deviceFlow.OnuId), uint32(deviceFlow.UniId), deviceFlow.FlowId)
850 return false
851 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400853 f.registerFlow(logicalFlow, deviceFlow)
854 return true
855}
856
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400858 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
859 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
860 if err != nil {
861 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
862 return false
863 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700864 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 return true
866}
867
868/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
869 //update core flows_proxy : flows_proxy.update('/', flows)
870}
871
872func generateStoredId(flowId uint32, direction string)uint32{
873
874 if direction == UPSTREAM{
875 log.Debug("Upstream flow shifting flowid")
876 return ((0x1 << 15) | flowId)
877 }else if direction == DOWNSTREAM{
878 log.Debug("Downstream flow not shifting flowid")
879 return flowId
880 }else{
881 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
882 return flowId
883 }
884}
885
886*/
887
888func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +0530890}
891
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
893 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
894}
895
896//getOnuChildDevice to fetch onu
897func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
898 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
899 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
900 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530901 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700902 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +0530903 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +0530904 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530905 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
906 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530907}
908
909func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530911 return nil
912}
913
914func getSubscriberVlan(inPort uint32) uint32 {
915 /* For EAPOL case we will use default VLAN , so will implement later if required */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916 log.Info("unimplemented inport %v", inPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530917 return 0
918}
919
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
921 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530922}
923
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400925 if id>>15 == 0x1 {
926 return id & 0x7fff, UPSTREAM
927 }
928 return id, DOWNSTREAM
929}
930
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
932 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
933 ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400934 if err != nil {
935 log.Error(err)
936 return
937 }
938 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400940
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400942 if flowsInfo == nil {
943 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400945 return
946 }
947 var updatedFlows []rsrcMgr.FlowInfo
948
949 for _, flow := range *flowsInfo {
950 updatedFlows = append(updatedFlows, flow)
951 }
952
953 for i, storedFlow := range updatedFlows {
954 if flowDirection == storedFlow.Flow.FlowType {
955 //Remove the Flow from FlowInfo
956 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
957 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
958 break
959 }
960 }
961
962 if len(updatedFlows) >= 0 {
963 // There are still flows referencing the same flow_id.
964 // So the flow should not be freed yet.
965 // For ex: Case of HSIA where same flow is shared
966 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700967 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400968 return
969 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700970 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
971 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
972 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400973 if len(flowIds) == 0 {
974 /* TODO: Remove Upstream and Downstream Schedulers */
975 }
976}
977
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400979func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
980 log.Debugw("Removing Flow", log.Fields{"flow": flow})
981 var deviceFlowsToRemove []ofp.OfpFlowStats
982 var deletedFlowsIdx []int
983 for _, curFlow := range f.storedDeviceFlows {
984 if curFlow.Cookie == flow.Id {
985 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
986 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
987 }
988 }
989 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
990 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 id, direction := f.decodeStoredID(curFlow.GetId())
992 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400993 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
994 log.Debug("Flow removed from device successfully")
995 deletedFlowsIdx = append(deletedFlowsIdx, index)
996 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
997 }
998
999 }
1000 // Can be done in separate go routine as it takes time ?
1001 for _, flowToRemove := range deletedFlowsIdx {
1002 for index, storedFlow := range f.storedDeviceFlows {
1003 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1004 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1005 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1006 break
1007 }
1008 }
1009 }
1010 log.Debugw("Flows removed from the data store",
1011 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1012 return
1013}
1014
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015// AddFlow add flow to device
manikkaraj kbf256be2019-03-25 00:13:48 +05301016func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 classifierInfo := make(map[string]interface{})
1018 actionInfo := make(map[string]interface{})
manikkaraj kbf256be2019-03-25 00:13:48 +05301019 log.Debug("Adding Flow", log.Fields{"flow": flow})
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001020 for _, field := range utils.GetOfbFields(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 f.updateClassifierInfo(field, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301022 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001023 for _, action := range utils.GetActions(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 f.updateFlowActionInfo(action, actionInfo, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301025 }
manikkaraj k17652a72019-05-06 09:06:36 -04001026 /* Controller bound trap flows */
1027 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
1028 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1029 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001031 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032 classifierInfo[InPort] = uniPort
1033 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 +05301034 } else {
manikkaraj k17652a72019-05-06 09:06:36 -04001035 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1036 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301037 }
1038 }
manikkaraj k17652a72019-05-06 09:06:36 -04001039 } else {
1040 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1041 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001042 if portType := IntfIDToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001043 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001044 actionInfo[OUTPUT] = uniPort
1045 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1046 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001047 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 -04001048 return
1049 }
1050 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001052 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001053 classifierInfo[InPort] = uniPort
manikkaraj k17652a72019-05-06 09:06:36 -04001054 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1055 "outport": actionInfo[OUTPUT].(uint32)})
1056 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 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 -04001058 "outPort": actionInfo[OUTPUT].(uint32)})
1059 return
1060 }
1061 }
1062 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001063 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[OUTPUT]})
1064 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[OUTPUT].(uint32))
1065 if ipProto, ok := classifierInfo[IPProto]; ok {
1066 if ipProto.(uint32) == IPProtoDhcp {
1067 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001068 if udpSrc.(uint32) == uint32(67) {
1069 log.Debug("trap-dhcp-from-nni-flow")
1070 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1071 return
1072 }
1073 }
1074 }
1075 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001076 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301077}
1078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079func (f *OpenOltFlowMgr) updateClassifierInfo(field *ofp.OfpOxmOfbField, classifierInfo map[string]interface{}) {
1080 if field.Type == utils.ETH_TYPE {
1081 classifierInfo[EthType] = field.GetEthType()
1082 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1083 } else if field.Type == utils.IP_PROTO {
1084 classifierInfo[IPProto] = field.GetIpProto()
1085 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1086 } else if field.Type == utils.IN_PORT {
1087 classifierInfo[InPort] = field.GetPort()
1088 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1089 } else if field.Type == utils.VLAN_VID {
1090 classifierInfo[VlanVid] = field.GetVlanVid()
1091 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1092 } else if field.Type == utils.VLAN_PCP {
1093 classifierInfo[VlanPcp] = field.GetVlanPcp()
1094 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1095 } else if field.Type == utils.UDP_DST {
1096 classifierInfo[UDPDst] = field.GetUdpDst()
1097 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1098 } else if field.Type == utils.UDP_SRC {
1099 classifierInfo[UDPSrc] = field.GetUdpSrc()
1100 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1101 } else if field.Type == utils.IPV4_DST {
1102 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1103 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1104 } else if field.Type == utils.IPV4_SRC {
1105 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1106 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1107 } else if field.Type == utils.METADATA {
1108 classifierInfo[METADATA] = field.GetTableMetadata()
1109 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
1110 } else if field.Type == utils.TUNNEL_ID {
1111 classifierInfo[TunnelID] = field.GetTunnelId()
1112 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1113 } else {
1114 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1115 return
1116 }
1117}
manikkaraj kbf256be2019-03-25 00:13:48 +05301118
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119func (f *OpenOltFlowMgr) updateFlowActionInfo(action *ofp.OfpAction, actionInfo map[string]interface{}, classifierInfo map[string]interface{}) {
1120 if action.Type == utils.OUTPUT {
1121 if out := action.GetOutput(); out != nil {
1122 actionInfo[OUTPUT] = out.GetPort()
1123 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
1124 } else {
1125 log.Error("Invalid output port in action")
1126 return
1127 }
1128 } else if action.Type == utils.POP_VLAN {
1129 actionInfo[PopVlan] = true
1130 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1131 } else if action.Type == utils.PUSH_VLAN {
1132 if out := action.GetPush(); out != nil {
1133 if tpid := out.GetEthertype(); tpid != 0x8100 {
1134 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1135 } else {
1136 actionInfo[PushVlan] = true
1137 actionInfo[TPID] = tpid
1138 log.Debugw("action-type-push-vlan",
1139 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1140 }
1141 }
1142 } else if action.Type == utils.SET_FIELD {
1143 if out := action.GetSetField(); out != nil {
1144 if field := out.GetField(); field != nil {
1145 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1146 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1147 return
1148 }
1149 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1150 if ofbField := field.GetOfbField(); ofbField != nil {
1151 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1152 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1153 actionInfo[VlanVid] = vlan & 0xfff
1154 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1155 } else {
1156 log.Error("No Invalid vlan id in set vlan-vid action")
1157 }
1158 } else {
1159 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1160 }
1161 }
1162 }
1163 }
1164 } else {
1165 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1166 return
1167 }
1168}
1169
1170//sendTPDownloadMsgToChild send payload
1171func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string) error {
1172
1173 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301174 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001175 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301176 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301177 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301178 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001179
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180 tpPath := f.getTPpath(intfID, uni)
1181 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001182 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1183 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1184 tpDownloadMsg,
1185 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1186 f.deviceHandler.deviceType,
1187 onuDevice.Type,
1188 onuDevice.Id,
1189 onuDevice.ProxyAddress.DeviceId, "")
1190 if sendErr != nil {
1191 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1192 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1193 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1194 return sendErr
1195 }
1196 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301197 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301198}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001199
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001200//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001201func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1203 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001204 f.onuIds[onuIDkey] = onu
1205 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1206}
1207
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1209func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1210 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001211 if val, ok := f.onuIds[onuIDkey]; ok {
1212 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1214 f.onuGemPortIds[gemportKey] = onuInfo
1215 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001216 return
1217 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001218 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001219}
1220
1221// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222
1223//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1224func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1225 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 -04001226 if serialNumber != "" {
1227 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001228 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001229 }
1230 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001231 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1232 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1233 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1234 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001235 }
1236 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001237 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1238 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 -04001239}
1240
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001241//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1242func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001243 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001245 var err error
1246
1247 if packetIn.IntfType == "pon" {
1248 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001250 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1251 return logicalPortNum, err
1252 }
1253 if packetIn.PortNo != 0 {
1254 logicalPortNum = packetIn.PortNo
1255 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 uniID := uint32(0) // FIXME - multi-uni support
1257 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001258 }
1259 // 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 -07001260 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001261 f.packetInGemPort[pktInkey] = packetIn.GemportId
1262 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001263 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001264 }
1265 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1266 return logicalPortNum, nil
1267}
1268
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269//GetPacketOutGemPortID returns gemPortId
1270func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1271 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001272 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001274 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001276 } else {
1277 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001279 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001280 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001281}
1282
1283func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1284 log.Debug("Adding trap-dhcp-of-nni-flow")
1285 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001286 classifier[PacketTagType] = DoubleTag
1287 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001288 /* We manage flowId resource pool on per PON port basis.
1289 Since this situation is tricky, as a hack, we pass the NNI port
1290 index (network_intf_id) as PON port Index for the flowId resource
1291 pool. Also, there is no ONU Id available for trapping DHCP packets
1292 on NNI port, use onu_id as -1 (invalid)
1293 ****************** CAVEAT *******************
1294 This logic works if the NNI Port Id falls within the same valid
1295 range of PON Port Ids. If this doesn't work for some OLT Vendor
1296 we need to have a re-look at this.
1297 *********************************************
1298 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 onuID := -1
1300 uniID := -1
1301 gemPortID := -1
1302 allocID := -1
1303 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001304 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001306 log.Debug("Flow-exists--not-re-adding")
1307 return
1308 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001309 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie, "")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001310 if err != nil {
1311 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1312 return
1313 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314 var classifierProto *openoltpb2.Classifier
1315 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001316 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1317 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1318 return
1319 }
1320 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1321 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1322 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1323 return
1324 }
1325 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001326 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1327 OnuId: int32(onuID), // OnuId not required
1328 UniId: int32(uniID), // UniId not used
1329 FlowId: flowID,
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001330 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001331 AllocId: int32(allocID), // AllocId not used
1332 NetworkIntfId: int32(networkInterfaceID),
1333 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001334 Classifier: classifierProto,
1335 Action: actionProto,
1336 Priority: int32(logicalFlow.Priority),
1337 Cookie: logicalFlow.Cookie,
1338 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001339 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001340 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1342 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1343 int32(onuID),
1344 int32(uniID),
1345 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001346 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1347 }
1348 }
1349 return
1350}