blob: cdda5d897296bfe8c9088373bbf8ee1ed3ea6cb9 [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
203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204 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 +0530205
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700206 log.Infow("sorting flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
manikkaraj kbf256be2019-03-25 00:13:48 +0530207 "classifierInfo": classifierInfo, "actionInfo": actionInfo})
208
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209 uni := getUniPortPath(intfID, onuID, uniID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530210 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211 allocID, gemPorts = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, flow.GetTableId())
212 if allocID == nil || gemPorts == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530213 log.Error("alloc-id-gem-ports-unavailable")
214 return
215 }
216
217 /* Flows can't be added specific to gemport unless p-bits are received.
218 * Hence adding flows for all gemports
219 */
220 for _, gemPort := range gemPorts {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700221 if ipProto, ok := classifierInfo[IPProto]; ok {
222 if ipProto.(uint32) == IPProtoDhcp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530223 log.Info("Adding DHCP flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
225 } else if ipProto == IPProtoIgmp {
manikkaraj kbf256be2019-03-25 00:13:48 +0530226 log.Info("igmp flow add ignored, not implemented yet")
227 } else {
228 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
229 //return errors.New("Invalid-Classifier-to-handle")
230 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700231 } else if ethType, ok := classifierInfo[EthType]; ok {
232 if ethType.(uint32) == EapEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 log.Info("Adding EAPOL flow")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, DefaultMgmtVlan)
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400235 if vlan := getSubscriberVlan(utils.GetInPort(flow)); vlan != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700236 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlan)
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 }
238 // Send Techprofile download event to child device in go routine as it takes time
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700241 if ethType == LldpEthType {
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 log.Info("Adding LLDP flow")
243 addLLDPFlow(flow, portNo)
244 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245 } else if _, ok := actionInfo[PushVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530246 log.Info("Adding upstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700247 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
248 } else if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530249 log.Info("Adding Downstream data rule")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700250 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530251 } else {
252 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
253 }
254 }
255}
256
257// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700258func (f *OpenOltFlowMgr) createTcontGemports(intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, tableID uint32) ([]uint32, []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 var allocID []uint32
260 var gemPortIDs []uint32
261 //If we already have allocated earlier for this onu, render them
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700262 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
263 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530266 if len(allocID) != 0 && len(gemPortIDs) != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 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 +0530268 "allocID": allocID, "gemPortIDs": gemPortIDs})
269 return allocID, gemPortIDs
270 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530272
273 //FIXME: If table id is <= 63 using 64 as table id
274 if tableID < tp.DEFAULT_TECH_PROFILE_TABLE_ID {
275 tableID = tp.DEFAULT_TECH_PROFILE_TABLE_ID
276 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700277 tpPath := f.getTPpath(intfID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 // Check tech profile instance already exists for derived port name
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700279 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(tableID, tpPath)
manikkaraj kbf256be2019-03-25 00:13:48 +0530280 if err != nil { // This should not happen, something wrong in KV backend transaction
281 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tableID": tableID, "path": tpPath})
282 return nil, nil
283 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700284 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530285 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700286 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(tableID, uni, intfID)
287 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530288 log.Error("Tech-profile-instance-creation-failed")
289 return nil, nil
290 }
291 } else {
292 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
293 }
294 // Get upstream and downstream scheduler protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700295 usScheduler := f.techprofile[intfID].GetUsScheduler(techProfileInstance)
296 dsScheduler := f.techprofile[intfID].GetDsScheduler(techProfileInstance)
manikkaraj kbf256be2019-03-25 00:13:48 +0530297 // Get TCONTS protos
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700298 tconts := f.techprofile[intfID].GetTconts(techProfileInstance, usScheduler, dsScheduler)
manikkaraj kbf256be2019-03-25 00:13:48 +0530299 if len(tconts) == 0 {
300 log.Error("TCONTS not found ")
301 return nil, nil
302 }
303 log.Debugw("Sending Create tcont to device",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700304 log.Fields{"onu": onuID, "uni": uniID, "portNo": "", "tconts": tconts})
manikkaraj kbf256be2019-03-25 00:13:48 +0530305 if _, err := f.deviceHandler.Client.CreateTconts(context.Background(),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700306 &openoltpb2.Tconts{IntfId: intfID,
307 OnuId: onuID,
308 UniId: uniID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530309 PortNo: uniPort,
310 Tconts: tconts}); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400311 log.Errorw("Error while creating TCONT in device", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530312 return nil, nil
313 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700314 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
315 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
manikkaraj kbf256be2019-03-25 00:13:48 +0530316 gemPortIDs = append(gemPortIDs, gem.GemportID)
317 }
318 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
319 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700320 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530321 return allocID, gemPortIDs
322}
323
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700324func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530325
326 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700327 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530328 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700329 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530330 log.Error("Errow while uploading allocID to KV store")
331 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700332 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530333 log.Error("Errow while uploading GEMports to KV store")
334 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530336 log.Error("Errow while uploading gemtopon map to KV store")
337 }
338 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400339 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700340 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400341 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530342}
343
344func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
345 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700346 for intfID := range techRange.IntfIds {
347 f.techprofile = append(f.techprofile, f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr)
manikkaraj kbf256be2019-03-25 00:13:48 +0530348 }
349 }
350 //Make sure we have as many tech_profiles as there are pon ports on the device
351 if len(f.techprofile) != int(f.resourceMgr.DevInfo.GetPonPorts()) {
352 log.Errorw("Error while populating techprofile",
353 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700354 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530355 }
356 log.Infow("Populated techprofile per ponport successfully",
357 log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
358 return nil
359}
360
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700361func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530362 portNo uint32, uplinkClassifier map[string]interface{},
363 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700364 allocID uint32, gemportID uint32) {
365 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530366 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700367 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
368 UPSTREAM, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530369 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530370}
371
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530373 portNo uint32, downlinkClassifier map[string]interface{},
374 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700375 allocID uint32, gemportID uint32) {
376 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530377 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
378 "downlinkAction": downlinkAction})
manikkaraj k17652a72019-05-06 09:06:36 -0400379 // Ignore private VLAN flow given by decomposer, cannot do anything with this flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700380 if uint32(downlinkClassifier[METADATA].(uint64)) == MkUniPortNum(intfID, onuID, uniID) &&
381 downlinkClassifier[VlanVid] == (uint32(ofp.OfpVlanId_OFPVID_PRESENT)|4000) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530382 log.Infow("EAPOL DL flow , Already added ,ignoring it", log.Fields{"downlinkClassifier": downlinkClassifier,
383 "downlinkAction": downlinkAction})
384 return
385 }
386 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 downlinkAction[PopVlan] = true
388 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
389 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
390 DOWNSTREAM, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530391}
392
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700393func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530394 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700395 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530396 /* One of the OLT platform (Broadcom BAL) requires that symmetric
397 flows require the same flow_id to be used across UL and DL.
398 Since HSIA flow is the only symmetric flow currently, we need to
399 re-use the flow_id across both direction. The 'flow_category'
400 takes priority over flow_cookie to find any available HSIA_FLOW
401 id for the ONU.
402 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
404 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530405 "logicalFlow": *logicalFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400406 flowCategory := "HSIA"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700407 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
408 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, flowCategory)
Manikkaraj k884c1242019-04-11 16:26:42 +0530409 if err != nil {
410 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
411 return
412 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700413 var classifierProto *openoltpb2.Classifier
414 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530415 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
416 log.Error("Error in making classifier protobuf for hsia flow")
417 return
418 }
419 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
420 if actionProto = makeOpenOltActionField(action); actionProto == nil {
421 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
422 return
423 }
424 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700425 networkIntfID := f.deviceHandler.nniIntfID
426 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
427 OnuId: int32(onuID),
428 UniId: int32(uniID),
429 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530430 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700431 AllocId: int32(allocID),
432 NetworkIntfId: int32(networkIntfID),
433 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530434 Classifier: classifierProto,
435 Action: actionProto,
436 Priority: int32(logicalFlow.Priority),
437 Cookie: logicalFlow.Cookie,
438 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400439 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530440 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, "HSIA", flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530442 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
443 flow.OnuId,
444 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400445 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530446 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
447 return
448 }
449 }
450}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700451func (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 +0530452
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700453 var dhcpFlow openoltpb2.Flow
454 var actionProto *openoltpb2.Action
455 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530456
457 // Clear the action map
458 for k := range action {
459 delete(action, k)
460 }
461
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700462 action[TrapToHost] = true
463 classifier[UDPSrc] = uint32(68)
464 classifier[UDPDst] = uint32(67)
465 classifier[PacketTagType] = SingleTag
466 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530467
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700468 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530469
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700470 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530471
472 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700473 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530474 return
475 }
476
477 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
478
479 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
480 log.Error("Error in making classifier protobuf for ul flow")
481 return
482 }
483 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
484 if actionProto = makeOpenOltActionField(action); actionProto == nil {
485 log.Error("Error in making action protobuf for ul flow")
486 return
487 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530489
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
491 OnuId: int32(onuID),
492 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530493 FlowId: flowID,
494 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 AllocId: int32(allocID),
496 NetworkIntfId: int32(networkIntfID),
497 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530498 Classifier: classifierProto,
499 Action: actionProto,
500 Priority: int32(logicalFlow.Priority),
501 Cookie: logicalFlow.Cookie,
502 PortNo: portNo}
503
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400504 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530505 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400506 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530507 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
508 dhcpFlow.OnuId,
509 dhcpFlow.UniId,
510 dhcpFlow.FlowId, flowsToKVStore); err != nil {
511 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
512 return
513 }
514 }
515
manikkaraj kbf256be2019-03-25 00:13:48 +0530516 return
517}
518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
520func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
521 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 +0530522
523 uplinkClassifier := make(map[string]interface{})
524 uplinkAction := make(map[string]interface{})
525 downlinkClassifier := make(map[string]interface{})
526 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700527 var upstreamFlow openoltpb2.Flow
528 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530529
530 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 uplinkClassifier[EthType] = uint32(EapEthType)
532 uplinkClassifier[PacketTagType] = SingleTag
533 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530534 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700535 uplinkAction[TrapToHost] = true
536 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530537 //Add Uplink EAPOL Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530539 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530541 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530542 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700543 var classifierProto *openoltpb2.Classifier
544 var actionProto *openoltpb2.Action
545 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530546
547 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
548 log.Error("Error in making classifier protobuf for ul flow")
549 return
550 }
551 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
552 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
553 log.Error("Error in making action protobuf for ul flow")
554 return
555 }
556 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557 networkIntfID := f.deviceHandler.nniIntfID
558 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
559 OnuId: int32(onuID),
560 UniId: int32(uniID),
561 FlowId: uplinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530562 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 AllocId: int32(allocID),
564 NetworkIntfId: int32(networkIntfID),
565 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530566 Classifier: classifierProto,
567 Action: actionProto,
568 Priority: int32(logicalFlow.Priority),
569 Cookie: logicalFlow.Cookie,
570 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400571 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530572 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400573 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530575 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
576 upstreamFlow.OnuId,
577 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400578 upstreamFlow.FlowId,
579 /* lowCategory, */
580 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530581 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
582 return
583 }
584 }
585
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700586 if vlanID == DefaultMgmtVlan {
manikkaraj kbf256be2019-03-25 00:13:48 +0530587 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
588 # requirement)
589 # On one of the platforms (Broadcom BAL), when same DL classifier
590 # vlan was used across multiple ONUs, eapol flow re-adds after
591 # flow delete (cases of onu reboot/disable) fails.
592 # In order to generate unique vlan, a combination of intf_id
593 # onu_id and uniId is used.
594 # uniId defaults to 0, so add 1 to it.
595 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700596 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
597 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530598 // Assert that we do not generate invalid vlans under no condition
599 if specialVlanDlFlow <= 2 {
600 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
601 return
602 }
603 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
604 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 downlinkClassifier[PacketTagType] = SingleTag
606 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530607 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700608 downlinkAction[PushVlan] = true
609 downlinkAction[VlanVid] = vlanID
610 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
611 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, flowStoreCookie, "")
manikkaraj kbf256be2019-03-25 00:13:48 +0530612 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530613 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530615 return
616 }
617 log.Debugw("Creating DL EAPOL flow",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530619 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
620 log.Error("Error in making classifier protobuf for downlink flow")
621 return
622 }
623 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
624 log.Error("Error in making action protobuf for dl flow")
625 return
626 }
627 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
629 OnuId: int32(onuID),
630 UniId: int32(uniID),
631 FlowId: downlinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530632 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 AllocId: int32(allocID),
634 NetworkIntfId: int32(networkIntfID),
635 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530636 Classifier: classifierProto,
637 Action: actionProto,
638 Priority: int32(logicalFlow.Priority),
639 Cookie: logicalFlow.Cookie,
640 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400641 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530642 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400643 flowCategory := ""
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700644 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530645 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
646 downstreamFlow.OnuId,
647 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400648 downstreamFlow.FlowId,
649 /* flowCategory, */
650 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530651 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
652 return
653 }
654 }
655 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 log.Infow("EAPOL flow with non-default mgmt vlan is not supported", log.Fields{"vlanId": vlanID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530657 return
658 }
659 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
660}
661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
663 var classifier openoltpb2.Classifier
664 if etherType, ok := classifierInfo[EthType]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530665 classifier.EthType = etherType.(uint32)
666 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 if ipProto, ok := classifierInfo[IPProto]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530668 classifier.IpProto = ipProto.(uint32)
669 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 if vlanID, ok := classifierInfo[VlanVid]; ok {
671 classifier.OVid = (vlanID.(uint32)) & 0xFFF
manikkaraj kbf256be2019-03-25 00:13:48 +0530672 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530673 if metadata, ok := classifierInfo[METADATA]; ok { // TODO: Revisit
674 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530675 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700676 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530677 classifier.OPbits = vlanPcp.(uint32)
678 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700679 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530680 classifier.SrcPort = udpSrc.(uint32)
681 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 if udpDst, ok := classifierInfo[UDPDst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530683 classifier.DstPort = udpDst.(uint32)
684 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530686 classifier.DstIp = ipv4Dst.(uint32)
687 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 if ipv4Src, ok := classifierInfo[Ipv4Src]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530689 classifier.SrcIp = ipv4Src.(uint32)
690 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
692 if pktTagType.(string) == SingleTag {
693 classifier.PktTagType = SingleTag
694 } else if pktTagType.(string) == DoubleTag {
695 classifier.PktTagType = DoubleTag
manikkaraj kbf256be2019-03-25 00:13:48 +0530696 } else if pktTagType.(string) == UNTAGGED {
697 classifier.PktTagType = UNTAGGED
698 } else {
699 log.Error("Invalid tag type in classifier") // should not hit
700 return nil
701 }
702 }
703 return &classifier
704}
705
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
707 var actionCmd openoltpb2.ActionCmd
708 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530709 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 if _, ok := actionInfo[PopVlan]; ok {
711 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530712 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 } else if _, ok := actionInfo[PushVlan]; ok {
714 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530715 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700716 } else if _, ok := actionInfo[TrapToHost]; ok {
717 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530718 } else {
719 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
720 return nil
721 }
722 return &action
723}
724
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string) string {
manikkaraj kbf256be2019-03-25 00:13:48 +0530726 /*
727 FIXME
728 Should get Table id form the flow, as of now hardcoded to DEFAULT_TECH_PROFILE_TABLE_ID (64)
729 'tp_path' contains the suffix part of the tech_profile_instance path. The prefix to the 'tp_path' should be set to
730 TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
731 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 return f.techprofile[intfID].GetTechProfileInstanceKVPath(tp.DEFAULT_TECH_PROFILE_TABLE_ID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530733}
734
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 if len(classifier) == 0 { // should never happen
737 log.Error("Invalid classfier object")
738 return 0
739 }
740 var jsonData []byte
741 var flowString string
742 var err error
743 // TODO: Do we need to marshall ??
744 if jsonData, err = json.Marshal(classifier); err != nil {
745 log.Error("Failed to encode classifier")
746 return 0
747 }
748 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 if gemPortID != 0 {
750 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530751 }
752 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700753 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530754 hash := big.NewInt(0)
755 hash.SetBytes(h.Sum(nil))
756 return hash.Uint64()
757}
758
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
760 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
761 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400762 /* For flows which trap out of the NNI, the AccessIntfId is invalid
763 (set to -1). In such cases, we need to refer to the NetworkIntfId .
764 */
765 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400767 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400769 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 // Get existing flows matching flowid for given subscriber from KV store
771 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400772 if existingFlows != nil {
773 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 //for _, f := range *existingFlows {
775 // flows = append(flows, f)
776 //}
777 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400778 }
779 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 +0530780 return &flows
781}
782
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400783//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
784// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
785// var intfId uint32
786// /* For flows which trap out of the NNI, the AccessIntfId is invalid
787// (set to -1). In such cases, we need to refer to the NetworkIntfId .
788// */
789// if flow.AccessIntfId != -1 {
790// intfId = uint32(flow.AccessIntfId)
791// } else {
792// intfId = uint32(flow.NetworkIntfId)
793// }
794// // Get existing flows matching flowid for given subscriber from KV store
795// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
796// if existingFlows != nil {
797// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
798// for _, f := range *existingFlows {
799// flows = append(flows, f)
800// }
801// }
802// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
803// return &flows
804//}
805
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400807 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700808 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400809 log.Debug("Error while Storing flow into KV store")
810 return err
811 }
812 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530813 return nil
814}
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000817
818 var intfID uint32
819 /* For flows which trap out of the NNI, the AccessIntfId is invalid
820 (set to -1). In such cases, we need to refer to the NetworkIntfId .
821 */
822 if deviceFlow.AccessIntfId != -1 {
823 intfID = uint32(deviceFlow.AccessIntfId)
824 } else {
825 intfID = uint32(deviceFlow.NetworkIntfId)
826 }
827
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
829 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000830
831 st, _ := status.FromError(err)
832 if st.Code() == codes.AlreadyExists {
833 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 return false
835 }
Daniele Rossi22db98e2019-07-11 11:50:00 +0000836
837 if err != nil {
838 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
839 f.resourceMgr.FreeFlowID(intfID, uint32(deviceFlow.OnuId), uint32(deviceFlow.UniId), deviceFlow.FlowId)
840 return false
841 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400843 f.registerFlow(logicalFlow, deviceFlow)
844 return true
845}
846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400848 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
849 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
850 if err != nil {
851 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
852 return false
853 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530855 return true
856}
857
858/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
859 //update core flows_proxy : flows_proxy.update('/', flows)
860}
861
862func generateStoredId(flowId uint32, direction string)uint32{
863
864 if direction == UPSTREAM{
865 log.Debug("Upstream flow shifting flowid")
866 return ((0x1 << 15) | flowId)
867 }else if direction == DOWNSTREAM{
868 log.Debug("Downstream flow not shifting flowid")
869 return flowId
870 }else{
871 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
872 return flowId
873 }
874}
875
876*/
877
878func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +0530880}
881
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
883 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
884}
885
886//getOnuChildDevice to fetch onu
887func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
888 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
889 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
890 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530891 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +0530893 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +0530894 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530895 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
896 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530897}
898
899func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700900 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530901 return nil
902}
903
904func getSubscriberVlan(inPort uint32) uint32 {
905 /* For EAPOL case we will use default VLAN , so will implement later if required */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 log.Info("unimplemented inport %v", inPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530907 return 0
908}
909
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
911 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530912}
913
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400915 if id>>15 == 0x1 {
916 return id & 0x7fff, UPSTREAM
917 }
918 return id, DOWNSTREAM
919}
920
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
922 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
923 ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400924 if err != nil {
925 log.Error(err)
926 return
927 }
928 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400930
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400932 if flowsInfo == nil {
933 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400935 return
936 }
937 var updatedFlows []rsrcMgr.FlowInfo
938
939 for _, flow := range *flowsInfo {
940 updatedFlows = append(updatedFlows, flow)
941 }
942
943 for i, storedFlow := range updatedFlows {
944 if flowDirection == storedFlow.Flow.FlowType {
945 //Remove the Flow from FlowInfo
946 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
947 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
948 break
949 }
950 }
951
952 if len(updatedFlows) >= 0 {
953 // There are still flows referencing the same flow_id.
954 // So the flow should not be freed yet.
955 // For ex: Case of HSIA where same flow is shared
956 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400958 return
959 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
961 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
962 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400963 if len(flowIds) == 0 {
964 /* TODO: Remove Upstream and Downstream Schedulers */
965 }
966}
967
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400969func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
970 log.Debugw("Removing Flow", log.Fields{"flow": flow})
971 var deviceFlowsToRemove []ofp.OfpFlowStats
972 var deletedFlowsIdx []int
973 for _, curFlow := range f.storedDeviceFlows {
974 if curFlow.Cookie == flow.Id {
975 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
976 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
977 }
978 }
979 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
980 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 id, direction := f.decodeStoredID(curFlow.GetId())
982 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400983 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
984 log.Debug("Flow removed from device successfully")
985 deletedFlowsIdx = append(deletedFlowsIdx, index)
986 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
987 }
988
989 }
990 // Can be done in separate go routine as it takes time ?
991 for _, flowToRemove := range deletedFlowsIdx {
992 for index, storedFlow := range f.storedDeviceFlows {
993 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
994 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
995 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
996 break
997 }
998 }
999 }
1000 log.Debugw("Flows removed from the data store",
1001 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1002 return
1003}
1004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005// AddFlow add flow to device
manikkaraj kbf256be2019-03-25 00:13:48 +05301006func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007 classifierInfo := make(map[string]interface{})
1008 actionInfo := make(map[string]interface{})
manikkaraj kbf256be2019-03-25 00:13:48 +05301009 log.Debug("Adding Flow", log.Fields{"flow": flow})
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001010 for _, field := range utils.GetOfbFields(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 f.updateClassifierInfo(field, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301012 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001013 for _, action := range utils.GetActions(flow) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 f.updateFlowActionInfo(action, actionInfo, classifierInfo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301015 }
manikkaraj k17652a72019-05-06 09:06:36 -04001016 /* Controller bound trap flows */
1017 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
1018 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1019 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001021 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001022 classifierInfo[InPort] = uniPort
1023 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 +05301024 } else {
manikkaraj k17652a72019-05-06 09:06:36 -04001025 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1026 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301027 }
1028 }
manikkaraj k17652a72019-05-06 09:06:36 -04001029 } else {
1030 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1031 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032 if portType := IntfIDToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001033 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001034 actionInfo[OUTPUT] = uniPort
1035 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1036 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 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 -04001038 return
1039 }
1040 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001042 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 classifierInfo[InPort] = uniPort
manikkaraj k17652a72019-05-06 09:06:36 -04001044 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1045 "outport": actionInfo[OUTPUT].(uint32)})
1046 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001047 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 -04001048 "outPort": actionInfo[OUTPUT].(uint32)})
1049 return
1050 }
1051 }
1052 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001053 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[OUTPUT]})
1054 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[OUTPUT].(uint32))
1055 if ipProto, ok := classifierInfo[IPProto]; ok {
1056 if ipProto.(uint32) == IPProtoDhcp {
1057 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001058 if udpSrc.(uint32) == uint32(67) {
1059 log.Debug("trap-dhcp-from-nni-flow")
1060 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1061 return
1062 }
1063 }
1064 }
1065 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001066 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301067}
1068
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001069func (f *OpenOltFlowMgr) updateClassifierInfo(field *ofp.OfpOxmOfbField, classifierInfo map[string]interface{}) {
1070 if field.Type == utils.ETH_TYPE {
1071 classifierInfo[EthType] = field.GetEthType()
1072 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1073 } else if field.Type == utils.IP_PROTO {
1074 classifierInfo[IPProto] = field.GetIpProto()
1075 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1076 } else if field.Type == utils.IN_PORT {
1077 classifierInfo[InPort] = field.GetPort()
1078 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1079 } else if field.Type == utils.VLAN_VID {
1080 classifierInfo[VlanVid] = field.GetVlanVid()
1081 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1082 } else if field.Type == utils.VLAN_PCP {
1083 classifierInfo[VlanPcp] = field.GetVlanPcp()
1084 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1085 } else if field.Type == utils.UDP_DST {
1086 classifierInfo[UDPDst] = field.GetUdpDst()
1087 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1088 } else if field.Type == utils.UDP_SRC {
1089 classifierInfo[UDPSrc] = field.GetUdpSrc()
1090 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1091 } else if field.Type == utils.IPV4_DST {
1092 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1093 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1094 } else if field.Type == utils.IPV4_SRC {
1095 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1096 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1097 } else if field.Type == utils.METADATA {
1098 classifierInfo[METADATA] = field.GetTableMetadata()
1099 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
1100 } else if field.Type == utils.TUNNEL_ID {
1101 classifierInfo[TunnelID] = field.GetTunnelId()
1102 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1103 } else {
1104 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1105 return
1106 }
1107}
manikkaraj kbf256be2019-03-25 00:13:48 +05301108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109func (f *OpenOltFlowMgr) updateFlowActionInfo(action *ofp.OfpAction, actionInfo map[string]interface{}, classifierInfo map[string]interface{}) {
1110 if action.Type == utils.OUTPUT {
1111 if out := action.GetOutput(); out != nil {
1112 actionInfo[OUTPUT] = out.GetPort()
1113 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
1114 } else {
1115 log.Error("Invalid output port in action")
1116 return
1117 }
1118 } else if action.Type == utils.POP_VLAN {
1119 actionInfo[PopVlan] = true
1120 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1121 } else if action.Type == utils.PUSH_VLAN {
1122 if out := action.GetPush(); out != nil {
1123 if tpid := out.GetEthertype(); tpid != 0x8100 {
1124 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1125 } else {
1126 actionInfo[PushVlan] = true
1127 actionInfo[TPID] = tpid
1128 log.Debugw("action-type-push-vlan",
1129 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1130 }
1131 }
1132 } else if action.Type == utils.SET_FIELD {
1133 if out := action.GetSetField(); out != nil {
1134 if field := out.GetField(); field != nil {
1135 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1136 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1137 return
1138 }
1139 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1140 if ofbField := field.GetOfbField(); ofbField != nil {
1141 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1142 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1143 actionInfo[VlanVid] = vlan & 0xfff
1144 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1145 } else {
1146 log.Error("No Invalid vlan id in set vlan-vid action")
1147 }
1148 } else {
1149 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1150 }
1151 }
1152 }
1153 }
1154 } else {
1155 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1156 return
1157 }
1158}
1159
1160//sendTPDownloadMsgToChild send payload
1161func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string) error {
1162
1163 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301164 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301166 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301167 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301168 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170 tpPath := f.getTPpath(intfID, uni)
1171 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001172 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1173 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1174 tpDownloadMsg,
1175 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1176 f.deviceHandler.deviceType,
1177 onuDevice.Type,
1178 onuDevice.Id,
1179 onuDevice.ProxyAddress.DeviceId, "")
1180 if sendErr != nil {
1181 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1182 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1183 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1184 return sendErr
1185 }
1186 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301187 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301188}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001189
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001191func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1193 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001194 f.onuIds[onuIDkey] = onu
1195 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1196}
1197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1199func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1200 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001201 if val, ok := f.onuIds[onuIDkey]; ok {
1202 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1204 f.onuGemPortIds[gemportKey] = onuInfo
1205 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001206 return
1207 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001209}
1210
1211// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212
1213//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1214func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1215 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 -04001216 if serialNumber != "" {
1217 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001218 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001219 }
1220 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1222 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1223 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1224 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001225 }
1226 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1228 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 -04001229}
1230
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001231//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1232func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001233 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001235 var err error
1236
1237 if packetIn.IntfType == "pon" {
1238 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001239 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001240 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1241 return logicalPortNum, err
1242 }
1243 if packetIn.PortNo != 0 {
1244 logicalPortNum = packetIn.PortNo
1245 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 uniID := uint32(0) // FIXME - multi-uni support
1247 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001248 }
1249 // 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 -07001250 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001251 f.packetInGemPort[pktInkey] = packetIn.GemportId
1252 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001254 }
1255 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1256 return logicalPortNum, nil
1257}
1258
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001259//GetPacketOutGemPortID returns gemPortId
1260func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1261 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001262 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001263 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001264 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001266 } else {
1267 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001269 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001270 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001271}
1272
1273func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1274 log.Debug("Adding trap-dhcp-of-nni-flow")
1275 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001276 classifier[PacketTagType] = DoubleTag
1277 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001278 /* We manage flowId resource pool on per PON port basis.
1279 Since this situation is tricky, as a hack, we pass the NNI port
1280 index (network_intf_id) as PON port Index for the flowId resource
1281 pool. Also, there is no ONU Id available for trapping DHCP packets
1282 on NNI port, use onu_id as -1 (invalid)
1283 ****************** CAVEAT *******************
1284 This logic works if the NNI Port Id falls within the same valid
1285 range of PON Port Ids. If this doesn't work for some OLT Vendor
1286 we need to have a re-look at this.
1287 *********************************************
1288 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001289 onuID := -1
1290 uniID := -1
1291 gemPortID := -1
1292 allocID := -1
1293 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001294 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001296 log.Debug("Flow-exists--not-re-adding")
1297 return
1298 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie, "")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001300 if err != nil {
1301 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1302 return
1303 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304 var classifierProto *openoltpb2.Classifier
1305 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001306 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1307 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1308 return
1309 }
1310 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1311 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1312 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1313 return
1314 }
1315 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1317 OnuId: int32(onuID), // OnuId not required
1318 UniId: int32(uniID), // UniId not used
1319 FlowId: flowID,
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001320 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 AllocId: int32(allocID), // AllocId not used
1322 NetworkIntfId: int32(networkInterfaceID),
1323 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001324 Classifier: classifierProto,
1325 Action: actionProto,
1326 Priority: int32(logicalFlow.Priority),
1327 Cookie: logicalFlow.Cookie,
1328 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001329 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001330 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001331 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1332 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1333 int32(onuID),
1334 int32(uniID),
1335 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001336 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1337 }
1338 }
1339 return
1340}