blob: c3e202dd28644ebc37aa9fffecd79af0959a468b [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
Joey Armstrong9cdee9f2024-01-03 04:56:14 -05002 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
Scott Baker2c1c4822019-10-16 11:02:41 -07003
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 */
Akash Reddy Kankanala05aff182025-05-06 12:57:32 +053016//nolint:staticcheck
Scott Baker2c1c4822019-10-16 11:02:41 -070017package techprofile
18
19import (
Girish Gowdra248971a2021-06-01 15:14:15 -070020 "bytes"
npujar5bf737f2020-01-16 19:35:25 +053021 "context"
Scott Baker2c1c4822019-10-16 11:02:41 -070022 "errors"
23 "fmt"
Girish Gowdra9447baf2019-11-05 16:42:37 +053024 "regexp"
Scott Baker2c1c4822019-10-16 11:02:41 -070025 "strconv"
pnalmas23a77d02025-01-15 11:52:48 +053026 "strings"
Gamze Abakadfdd8f82020-05-04 08:39:50 +000027 "sync"
Neha Sharma130ac6d2020-04-08 08:46:32 +000028 "time"
Scott Baker2c1c4822019-10-16 11:02:41 -070029
khenaidoo26721882021-08-11 17:42:52 -040030 "github.com/golang/protobuf/jsonpb"
31 "github.com/golang/protobuf/proto"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db"
33 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
34 "github.com/opencord/voltha-lib-go/v7/pkg/log"
khenaidoo26721882021-08-11 17:42:52 -040035 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
Scott Baker2c1c4822019-10-16 11:02:41 -070036)
37
38// Interface to pon resource manager APIs
39type iPonResourceMgr interface {
Girish Gowdra248971a2021-06-01 15:14:15 -070040 GetResourceID(ctx context.Context, intfID uint32, resourceType string, numIDs uint32) ([]uint32, error)
41 FreeResourceID(ctx context.Context, intfID uint32, resourceType string, ReleaseContent []uint32) error
Scott Baker2c1c4822019-10-16 11:02:41 -070042 GetResourceTypeAllocID() string
43 GetResourceTypeGemPortID() string
Matteo Scandolob85b2f02021-03-18 14:44:41 -070044 GetResourceTypeOnuID() string
Scott Baker2c1c4822019-10-16 11:02:41 -070045 GetTechnology() string
46}
47
Scott Baker2c1c4822019-10-16 11:02:41 -070048type SchedulingPolicy int32
49
50const (
51 SchedulingPolicy_WRR SchedulingPolicy = 0
52 SchedulingPolicy_StrictPriority SchedulingPolicy = 1
53 SchedulingPolicy_Hybrid SchedulingPolicy = 2
54)
55
Scott Baker2c1c4822019-10-16 11:02:41 -070056type AdditionalBW int32
57
58const (
59 AdditionalBW_AdditionalBW_None AdditionalBW = 0
60 AdditionalBW_AdditionalBW_NA AdditionalBW = 1
61 AdditionalBW_AdditionalBW_BestEffort AdditionalBW = 2
62 AdditionalBW_AdditionalBW_Auto AdditionalBW = 3
63)
64
Scott Baker2c1c4822019-10-16 11:02:41 -070065type DiscardPolicy int32
66
67const (
68 DiscardPolicy_TailDrop DiscardPolicy = 0
69 DiscardPolicy_WTailDrop DiscardPolicy = 1
70 DiscardPolicy_Red DiscardPolicy = 2
71 DiscardPolicy_WRed DiscardPolicy = 3
72)
73
Girish Gowdra9447baf2019-11-05 16:42:37 +053074// Required uniPortName format
Girish Gowdra248971a2021-06-01 15:14:15 -070075var uniPortNameFormatRegexp = regexp.MustCompile(`^olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
Girish Gowdra9447baf2019-11-05 16:42:37 +053076
Scott Baker2c1c4822019-10-16 11:02:41 -070077// instance control defaults
78const (
79 defaultOnuInstance = "multi-instance"
80 defaultUniInstance = "single-instance"
Scott Baker2c1c4822019-10-16 11:02:41 -070081 defaultGemPayloadSize = "auto"
82)
83
Scott Baker2c1c4822019-10-16 11:02:41 -070084// default discard config constants
85const (
86 defaultMinThreshold = 0
87 defaultMaxThreshold = 0
88 defaultMaxProbability = 0
89)
90
Scott Baker2c1c4822019-10-16 11:02:41 -070091// default scheduler contants
92const (
Girish Gowdra248971a2021-06-01 15:14:15 -070093 defaultPriority = 0
94 defaultWeight = 0
Scott Baker2c1c4822019-10-16 11:02:41 -070095)
96
Scott Baker2c1c4822019-10-16 11:02:41 -070097// default GEM attribute constants
98const (
Esin Karaman8aa75a72019-12-20 13:11:59 +000099 defaultAESEncryption = "True"
100 defaultPriorityQueue = 0
101 defaultQueueWeight = 0
102 defaultMaxQueueSize = "auto"
Esin Karaman8aa75a72019-12-20 13:11:59 +0000103 defaultIsMulticast = "False"
104 defaultAccessControlList = "224.0.0.0-239.255.255.255"
105 defaultMcastGemID = 4069
Scott Baker2c1c4822019-10-16 11:02:41 -0700106)
107
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700108// Default EPON constants
109const (
110 defaultPakageType = "B"
111)
112const (
113 defaultTrafficType = "BE"
114 defaultUnsolicitedGrantSize = 0
115 defaultNominalInterval = 0
116 defaultToleratedPollJitter = 0
117 defaultRequestTransmissionPolicy = 0
118 defaultNumQueueSet = 2
119)
120const (
121 defaultQThreshold1 = 5500
122 defaultQThreshold2 = 0
123 defaultQThreshold3 = 0
124 defaultQThreshold4 = 0
125 defaultQThreshold5 = 0
126 defaultQThreshold6 = 0
127 defaultQThreshold7 = 0
128)
129
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700130const (
Andrea Campanella904fe322020-06-26 18:56:51 +0200131 xgspon = "XGS-PON"
Girish Gowdra248971a2021-06-01 15:14:15 -0700132 xgpon = "XGPON"
Andrea Campanella904fe322020-06-26 18:56:51 +0200133 gpon = "GPON"
134 epon = "EPON"
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700135)
136
Girish Gowdra248971a2021-06-01 15:14:15 -0700137const (
138 MaxUniPortPerOnu = 16 // TODO: Adapter uses its own constant for MaxUniPort. How to synchronize this and have a single source of truth?
139)
140
141type TechProfileMgr struct {
142 config *TechProfileFlags
143 resourceMgr iPonResourceMgr
144 OnuIDMgmtLock sync.RWMutex
145 GemPortIDMgmtLock sync.RWMutex
146 AllocIDMgmtLock sync.RWMutex
147 tpInstanceMap map[string]*tp_pb.TechProfileInstance // Map of tp path to tp instance
148 tpInstanceMapLock sync.RWMutex
149 eponTpInstanceMap map[string]*tp_pb.EponTechProfileInstance // Map of tp path to epon tp instance
150 epontpInstanceMapLock sync.RWMutex
151 tpMap map[uint32]*tp_pb.TechProfile // Map of tp id to tp
152 tpMapLock sync.RWMutex
153 eponTpMap map[uint32]*tp_pb.EponTechProfile // map of tp id to epon tp
154 eponTpMapLock sync.RWMutex
155}
156
Matteo Scandolof34d9082020-11-24 13:56:34 -0800157func (t *TechProfileMgr) SetKVClient(ctx context.Context, pathPrefix string) *db.Backend {
Neha Sharma94f16a92020-06-26 04:17:55 +0000158 kvClient, err := newKVClient(ctx, t.config.KVStoreType, t.config.KVStoreAddress, t.config.KVStoreTimeout)
Scott Baker2c1c4822019-10-16 11:02:41 -0700159 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000160 logger.Errorw(ctx, "failed-to-create-kv-client",
Scott Baker2c1c4822019-10-16 11:02:41 -0700161 log.Fields{
Neha Sharmadd9af392020-04-28 09:03:57 +0000162 "type": t.config.KVStoreType, "address": t.config.KVStoreAddress,
Matteo Scandolof34d9082020-11-24 13:56:34 -0800163 "timeout": t.config.KVStoreTimeout, "prefix": pathPrefix,
Scott Baker2c1c4822019-10-16 11:02:41 -0700164 "error": err.Error(),
165 })
166 return nil
167 }
sbarbari1e3e29c2019-11-05 10:06:50 -0500168 return &db.Backend{
Scott Baker2c1c4822019-10-16 11:02:41 -0700169 Client: kvClient,
170 StoreType: t.config.KVStoreType,
Neha Sharmadd9af392020-04-28 09:03:57 +0000171 Address: t.config.KVStoreAddress,
Scott Baker2c1c4822019-10-16 11:02:41 -0700172 Timeout: t.config.KVStoreTimeout,
Matteo Scandolof34d9082020-11-24 13:56:34 -0800173 PathPrefix: pathPrefix}
Scott Baker2c1c4822019-10-16 11:02:41 -0700174
175 /* TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700176 issue between kv store and backend , core is not calling NewBackend directly
Girish Gowdra248971a2021-06-01 15:14:15 -0700177 kv := model.NewBackend(t.config.kvStoreType, t.config.KVStoreHost, t.config.KVStorePort,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700178 t.config.KVStoreTimeout, kvStoreTechProfilePathPrefix)
Scott Baker2c1c4822019-10-16 11:02:41 -0700179 */
180}
181
Holger Hildebrandt40bd2672023-02-10 08:14:26 +0000182func (t *TechProfileMgr) CloseKVClient(ctx context.Context) {
183 if t.config.KVBackend != nil {
184 t.config.KVBackend.Client.Close(ctx)
185 t.config.KVBackend = nil
186 }
187 if t.config.DefaultTpKVBackend != nil {
188 t.config.DefaultTpKVBackend.Client.Close(ctx)
189 t.config.DefaultTpKVBackend = nil
190 }
191 if t.config.ResourceInstanceKVBacked != nil {
192 t.config.ResourceInstanceKVBacked.Client.Close(ctx)
193 t.config.ResourceInstanceKVBacked = nil
194 }
195}
196
pnalmas23a77d02025-01-15 11:52:48 +0530197func NewTechProfile(ctx context.Context, IntfId uint32, deviceId string, resourceMgr iPonResourceMgr, kvStoreType string, kvStoreAddress string, basePathKvStore string) (*TechProfileMgr, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700198 var techprofileObj TechProfileMgr
pnalmas23a77d02025-01-15 11:52:48 +0530199 logger.Debug(ctx, "initializing-techprofile-mananger ", log.Fields{"IntId": IntfId, "device-id": deviceId})
Girish Gowdra248971a2021-06-01 15:14:15 -0700200 techprofileObj.config = NewTechProfileFlags(kvStoreType, kvStoreAddress, basePathKvStore)
Matteo Scandolof34d9082020-11-24 13:56:34 -0800201 techprofileObj.config.KVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.TPKVPathPrefix)
202 techprofileObj.config.DefaultTpKVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.defaultTpKvPathPrefix)
Scott Baker2c1c4822019-10-16 11:02:41 -0700203 if techprofileObj.config.KVBackend == nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700204 logger.Error(ctx, "failed-to-initialize-backend")
205 return nil, errors.New("kv-backend-init-failed")
206 }
207 techprofileObj.config.ResourceInstanceKVBacked = techprofileObj.SetKVClient(ctx, techprofileObj.config.ResourceInstanceKVPathPrefix)
208 if techprofileObj.config.ResourceInstanceKVBacked == nil {
209 logger.Error(ctx, "failed-to-initialize-resource-instance-kv-backend")
210 return nil, errors.New("resource-instance-kv-backend-init-failed")
Scott Baker2c1c4822019-10-16 11:02:41 -0700211 }
212 techprofileObj.resourceMgr = resourceMgr
Girish Gowdra248971a2021-06-01 15:14:15 -0700213 techprofileObj.tpInstanceMap = make(map[string]*tp_pb.TechProfileInstance)
214 techprofileObj.eponTpInstanceMap = make(map[string]*tp_pb.EponTechProfileInstance)
215 techprofileObj.tpMap = make(map[uint32]*tp_pb.TechProfile)
216 techprofileObj.eponTpMap = make(map[uint32]*tp_pb.EponTechProfile)
217 logger.Debug(ctx, "reconcile-tp-instance-cache-start")
pnalmas23a77d02025-01-15 11:52:48 +0530218 if err := techprofileObj.reconcileTpInstancesToCache(ctx, IntfId, deviceId); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700219 logger.Errorw(ctx, "failed-to-reconcile-tp-instances", log.Fields{"err": err})
220 return nil, err
221 }
222 logger.Debug(ctx, "reconcile-tp-instance-cache-end")
223 logger.Debug(ctx, "initializing-tech-profile-manager-object-success")
Scott Baker2c1c4822019-10-16 11:02:41 -0700224 return &techprofileObj, nil
225}
226
Girish Gowdra248971a2021-06-01 15:14:15 -0700227// GetTechProfileInstanceKey returns the tp instance key that is used to reference TP Instance Map
228func (t *TechProfileMgr) GetTechProfileInstanceKey(ctx context.Context, tpID uint32, uniPortName string) string {
229 logger.Debugw(ctx, "get-tp-instance-kv-key", log.Fields{
Matteo Scandolo4fca23a2020-04-07 07:55:08 -0700230 "uniPortName": uniPortName,
Girish Gowdra248971a2021-06-01 15:14:15 -0700231 "tpId": tpID,
Matteo Scandolo4fca23a2020-04-07 07:55:08 -0700232 })
Girish Gowdra248971a2021-06-01 15:14:15 -0700233 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
234 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
235 logger.Warnw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
236 }
237 // The key path prefix (like service/voltha/technology_profiles or service/voltha_voltha/technology_profiles)
238 // is expected to be attached by the components that use this path as part of the KVBackend configuration.
239 resourceInstanceKvPathSuffix := "%s/%d/%s" // <technology>/<tpID>/<uni-port-name>
240 // <uni-port-name> must be of the format pon-{\d+}/onu-{\d+}/uni-{\d+}
241 return fmt.Sprintf(resourceInstanceKvPathSuffix, t.resourceMgr.GetTechnology(), tpID, uniPortName)
Scott Baker2c1c4822019-10-16 11:02:41 -0700242}
243
Girish Gowdra248971a2021-06-01 15:14:15 -0700244// GetTPInstance gets TP instance from cache if found
245func (t *TechProfileMgr) GetTPInstance(ctx context.Context, path string) (interface{}, error) {
246 tech := t.resourceMgr.GetTechnology()
247 switch tech {
248 case xgspon, xgpon, gpon:
249 t.tpInstanceMapLock.RLock()
250 defer t.tpInstanceMapLock.RUnlock()
251 tpInst, ok := t.tpInstanceMap[path]
252 if !ok {
253 return nil, fmt.Errorf("tp-instance-not-found-tp-path-%v", path)
254 }
255 return tpInst, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700256 case epon:
Girish Gowdra248971a2021-06-01 15:14:15 -0700257 t.epontpInstanceMapLock.RLock()
258 defer t.epontpInstanceMapLock.RUnlock()
259 tpInst, ok := t.eponTpInstanceMap[path]
260 if !ok {
261 return nil, fmt.Errorf("tp-instance-not-found-tp-path-%v", path)
262 }
263 return tpInst, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700264 default:
Girish Gowdra248971a2021-06-01 15:14:15 -0700265 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech})
266 return nil, fmt.Errorf("unknown-tech-%s-tp-path-%v", tech, path)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700267 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700268}
269
Girish Gowdra248971a2021-06-01 15:14:15 -0700270// CreateTechProfileInstance creates a new TP instance.
271func (t *TechProfileMgr) CreateTechProfileInstance(ctx context.Context, tpID uint32, uniPortName string, intfID uint32) (interface{}, error) {
272 var tpInstance *tp_pb.TechProfileInstance
273 var eponTpInstance *tp_pb.EponTechProfileInstance
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700274
Girish Gowdra248971a2021-06-01 15:14:15 -0700275 logger.Infow(ctx, "creating-tp-instance", log.Fields{"tpID": tpID, "uni": uniPortName, "intId": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700276
Girish Gowdra248971a2021-06-01 15:14:15 -0700277 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
278 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000279 logger.Errorw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
Girish Gowdra248971a2021-06-01 15:14:15 -0700280 return nil, fmt.Errorf("uni-port-name-not-confirming-to-format-%s", uniPortName)
Girish Gowdra9447baf2019-11-05 16:42:37 +0530281 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700282 tpInstancePathSuffix := t.GetTechProfileInstanceKey(ctx, tpID, uniPortName)
283
284 if t.resourceMgr.GetTechnology() == epon {
285 tp := t.getEponTPFromKVStore(ctx, tpID)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700286 if tp != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700287 if err := t.validateInstanceControlAttr(ctx, *tp.InstanceControl); err != nil {
288 logger.Error(ctx, "invalid-instance-ctrl-attr-using-default-tp")
Girish Kumar950f21e2020-08-19 17:42:29 +0000289 tp = t.getDefaultEponProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700290 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700291 logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpID": tpID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700292 }
293 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000294 logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
Girish Kumar950f21e2020-08-19 17:42:29 +0000295 tp = t.getDefaultEponProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700296 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700297 // Store TP in cache
298 t.eponTpMapLock.Lock()
299 t.eponTpMap[tpID] = tp
300 t.eponTpMapLock.Unlock()
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700301
Girish Gowdra248971a2021-06-01 15:14:15 -0700302 if eponTpInstance = t.allocateEponTPInstance(ctx, uniPortName, tp, intfID, tpInstancePathSuffix); eponTpInstance == nil {
303 logger.Error(ctx, "tp-instance-allocation-failed")
304 return nil, errors.New("tp-instance-allocation-failed")
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700305 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700306 t.epontpInstanceMapLock.Lock()
307 t.eponTpInstanceMap[tpInstancePathSuffix] = eponTpInstance
308 t.epontpInstanceMapLock.Unlock()
309 resInst := tp_pb.ResourceInstance{
310 TpId: tpID,
311 ProfileType: eponTpInstance.ProfileType,
312 SubscriberIdentifier: eponTpInstance.SubscriberIdentifier,
313 AllocId: eponTpInstance.AllocId,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700314 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700315 for _, usQAttr := range eponTpInstance.UpstreamQueueAttributeList {
316 resInst.GemportIds = append(resInst.GemportIds, usQAttr.GemportId)
317 }
318
319 logger.Infow(ctx, "epon-tp-instance-created-successfully",
320 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
321 if err := t.addResourceInstanceToKVStore(ctx, tpID, uniPortName, resInst); err != nil {
322 logger.Errorw(ctx, "failed-to-update-resource-instance-to-kv-store--freeing-up-resources", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
323 allocIDs := make([]uint32, 0)
324 allocIDs = append(allocIDs, resInst.AllocId)
325 errList := make([]error, 0)
326 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), allocIDs))
327 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), resInst.GemportIds))
328 if len(errList) > 0 {
329 logger.Errorw(ctx, "failed-to-free-up-resources-on-kv-store--system-behavior-has-become-erratic", log.Fields{"tpID": tpID, "uniPortName": uniPortName, "errList": errList})
330 }
331 return nil, err
332 }
333 return eponTpInstance, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700334 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700335 tp := t.getTPFromKVStore(ctx, tpID)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700336 if tp != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700337 if err := t.validateInstanceControlAttr(ctx, *tp.InstanceControl); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000338 logger.Error(ctx, "invalid-instance-ctrl-attr--using-default-tp")
339 tp = t.getDefaultTechProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700340 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700341 logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpID": tpID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700342 }
343 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000344 logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
345 tp = t.getDefaultTechProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700346 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700347 // Store TP in cache
348 t.tpMapLock.Lock()
349 t.tpMap[tpID] = tp
350 t.tpMapLock.Unlock()
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700351
Girish Gowdra248971a2021-06-01 15:14:15 -0700352 if tpInstance = t.allocateTPInstance(ctx, uniPortName, tp, intfID, tpInstancePathSuffix); tpInstance == nil {
353 logger.Error(ctx, "tp-instance-allocation-failed")
354 return nil, errors.New("tp-instance-allocation-failed")
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700355 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700356 t.tpInstanceMapLock.Lock()
357 t.tpInstanceMap[tpInstancePathSuffix] = tpInstance
358 t.tpInstanceMapLock.Unlock()
359
360 resInst := tp_pb.ResourceInstance{
361 TpId: tpID,
362 ProfileType: tpInstance.ProfileType,
363 SubscriberIdentifier: tpInstance.SubscriberIdentifier,
364 AllocId: tpInstance.UsScheduler.AllocId,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700365 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700366 for _, usQAttr := range tpInstance.UpstreamGemPortAttributeList {
367 resInst.GemportIds = append(resInst.GemportIds, usQAttr.GemportId)
368 }
369
370 logger.Infow(ctx, "tp-instance-created-successfully",
371 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
372 if err := t.addResourceInstanceToKVStore(ctx, tpID, uniPortName, resInst); err != nil {
373 logger.Errorw(ctx, "failed-to-update-resource-instance-to-kv-store--freeing-up-resources", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
374 allocIDs := make([]uint32, 0)
375 allocIDs = append(allocIDs, resInst.AllocId)
376 errList := make([]error, 0)
377 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), allocIDs))
378 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), resInst.GemportIds))
379 if len(errList) > 0 {
380 logger.Fatalw(ctx, "failed-to-free-up-resources-on-kv-store--system-behavior-has-become-erratic", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
381 }
382 return nil, err
383 }
384
385 logger.Infow(ctx, "resource-instance-added-to-kv-store-successfully",
386 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700387 return tpInstance, nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700388 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700389}
390
Girish Gowdra248971a2021-06-01 15:14:15 -0700391// DeleteTechProfileInstance deletes the TP instance from the local cache as well as deletes the corresponding
392// resource instance from the KV store.
393func (t *TechProfileMgr) DeleteTechProfileInstance(ctx context.Context, tpID uint32, uniPortName string) error {
394 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
395 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
396 logger.Errorw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
397 return fmt.Errorf("uni-port-name-not-confirming-to-format--%s", uniPortName)
398 }
399 path := t.GetTechProfileInstanceKey(ctx, tpID, uniPortName)
400 logger.Infow(ctx, "delete-tp-instance-from-cache", log.Fields{"key": path})
401 t.tpInstanceMapLock.Lock()
402 delete(t.tpInstanceMap, path)
403 t.tpInstanceMapLock.Unlock()
404 if err := t.removeResourceInstanceFromKVStore(ctx, tpID, uniPortName); err != nil {
405 return err
406 }
407 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700408}
409
Girish Gowdra248971a2021-06-01 15:14:15 -0700410func (t *TechProfileMgr) GetMulticastTrafficQueues(ctx context.Context, tp *tp_pb.TechProfileInstance) []*tp_pb.TrafficQueue {
411 var encryp bool
412 NumGemPorts := len(tp.DownstreamGemPortAttributeList)
413 mcastTrafficQueues := make([]*tp_pb.TrafficQueue, 0)
414 for Count := 0; Count < NumGemPorts; Count++ {
415 if !isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
416 continue
417 }
418 if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
419 encryp = true
420 } else {
421 encryp = false
422 }
423 mcastTrafficQueues = append(mcastTrafficQueues, &tp_pb.TrafficQueue{
424 Direction: tp_pb.Direction_DOWNSTREAM,
425 GemportId: tp.DownstreamGemPortAttributeList[Count].MulticastGemId,
426 PbitMap: tp.DownstreamGemPortAttributeList[Count].PbitMap,
427 AesEncryption: encryp,
428 SchedPolicy: tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy,
429 Priority: tp.DownstreamGemPortAttributeList[Count].PriorityQ,
430 Weight: tp.DownstreamGemPortAttributeList[Count].Weight,
431 DiscardPolicy: tp.DownstreamGemPortAttributeList[Count].DiscardPolicy,
432 })
433 }
434 logger.Debugw(ctx, "Downstream Multicast Traffic queue list ", log.Fields{"queuelist": mcastTrafficQueues})
435 return mcastTrafficQueues
436}
437
438func (t *TechProfileMgr) GetGemportForPbit(ctx context.Context, tp interface{}, dir tp_pb.Direction, pbit uint32) interface{} {
439 /*
440 Function to get the Gemport mapped to a pbit.
441 */
442 switch tp := tp.(type) {
443 case *tp_pb.TechProfileInstance:
444 if dir == tp_pb.Direction_UPSTREAM {
445 // upstream GEM ports
446 numGemPorts := len(tp.UpstreamGemPortAttributeList)
447 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
448 lenOfPbitMap := len(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap)
449 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
450 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
451 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
452 if p, err := strconv.Atoi(string(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
453 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
454 logger.Debugw(ctx, "Found-US-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.UpstreamGemPortAttributeList[gemCnt].GemportId})
455 return tp.UpstreamGemPortAttributeList[gemCnt]
456 }
457 }
458 }
459 }
460 } else if dir == tp_pb.Direction_DOWNSTREAM {
461 //downstream GEM ports
462 numGemPorts := len(tp.DownstreamGemPortAttributeList)
463 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
464 lenOfPbitMap := len(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap)
465 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
466 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
467 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
468 if p, err := strconv.Atoi(string(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
469 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
470 logger.Debugw(ctx, "Found-DS-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.DownstreamGemPortAttributeList[gemCnt].GemportId})
471 return tp.DownstreamGemPortAttributeList[gemCnt]
472 }
473 }
474 }
475 }
476 }
477 logger.Errorw(ctx, "No-GemportId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
khenaidooa5feb8e2021-10-19 17:29:22 -0400478 case *tp_pb.EponTechProfileInstance:
Girish Gowdra248971a2021-06-01 15:14:15 -0700479 if dir == tp_pb.Direction_UPSTREAM {
480 // upstream GEM ports
481 numGemPorts := len(tp.UpstreamQueueAttributeList)
482 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
483 lenOfPbitMap := len(tp.UpstreamQueueAttributeList[gemCnt].PbitMap)
484 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
485 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
486 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
487 if p, err := strconv.Atoi(string(tp.UpstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
488 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
489 logger.Debugw(ctx, "Found-US-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.UpstreamQueueAttributeList[gemCnt].GemportId})
490 return tp.UpstreamQueueAttributeList[gemCnt]
491 }
492 }
493 }
494 }
495 } else if dir == tp_pb.Direction_DOWNSTREAM {
496 //downstream GEM ports
497 numGemPorts := len(tp.DownstreamQueueAttributeList)
498 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
499 lenOfPbitMap := len(tp.DownstreamQueueAttributeList[gemCnt].PbitMap)
500 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
501 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
502 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
503 if p, err := strconv.Atoi(string(tp.DownstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
504 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
505 logger.Debugw(ctx, "Found-DS-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.DownstreamQueueAttributeList[gemCnt].GemportId})
506 return tp.DownstreamQueueAttributeList[gemCnt]
507 }
508 }
509 }
510 }
511 }
512 logger.Errorw(ctx, "No-QueueId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
513 default:
514 logger.Errorw(ctx, "unknown-tech", log.Fields{"tp": tp})
515 }
516 return nil
517}
518
519// FindAllTpInstances returns all TechProfile instances for a given TechProfile table-id, pon interface ID and onu ID.
520func (t *TechProfileMgr) FindAllTpInstances(ctx context.Context, oltDeviceID string, tpID uint32, intfID uint32, onuID uint32) interface{} {
521 onuTpInstancePathSuffix := fmt.Sprintf("%s/%d/olt-{%s}/pon-{%d}/onu-{%d}", t.resourceMgr.GetTechnology(), tpID, oltDeviceID, intfID, onuID)
522 tech := t.resourceMgr.GetTechnology()
523 if tech == xgspon || tech == xgpon || tech == gpon {
524 t.tpInstanceMapLock.RLock()
525 defer t.tpInstanceMapLock.RUnlock()
526 tpInstancesTech := make([]tp_pb.TechProfileInstance, 0)
527 for i := 0; i < MaxUniPortPerOnu; i++ {
528 key := onuTpInstancePathSuffix + fmt.Sprintf("/uni-{%d}", i)
529 if tpInst, ok := t.tpInstanceMap[key]; ok {
530 tpInstancesTech = append(tpInstancesTech, *tpInst)
531 }
532 }
533 return tpInstancesTech
534 } else if tech == epon {
535 t.epontpInstanceMapLock.RLock()
536 defer t.epontpInstanceMapLock.RUnlock()
537 tpInstancesTech := make([]tp_pb.EponTechProfileInstance, 0)
538 for i := 0; i < MaxUniPortPerOnu; i++ {
539 key := onuTpInstancePathSuffix + fmt.Sprintf("/uni-{%d}", i)
540 if tpInst, ok := t.eponTpInstanceMap[key]; ok {
541 tpInstancesTech = append(tpInstancesTech, *tpInst)
542 }
543 }
544 return tpInstancesTech
545 } else {
546 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech, "tpID": tpID, "onuID": onuID, "intfID": intfID})
547 }
548 return nil
549}
550
551func (t *TechProfileMgr) GetResourceID(ctx context.Context, intfID uint32, resourceType string, numIDs uint32) ([]uint32, error) {
552 logger.Debugw(ctx, "getting-resource-id", log.Fields{
553 "intf-id": intfID,
554 "resource-type": resourceType,
555 "num": numIDs,
556 })
557 var err error
558 var ids []uint32
559 switch resourceType {
560 case t.resourceMgr.GetResourceTypeAllocID():
561 t.AllocIDMgmtLock.Lock()
562 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
563 t.AllocIDMgmtLock.Unlock()
564 case t.resourceMgr.GetResourceTypeGemPortID():
565 t.GemPortIDMgmtLock.Lock()
566 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
567 t.GemPortIDMgmtLock.Unlock()
568 case t.resourceMgr.GetResourceTypeOnuID():
569 t.OnuIDMgmtLock.Lock()
570 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
571 t.OnuIDMgmtLock.Unlock()
572 default:
573 return nil, fmt.Errorf("resourceType %s not supported", resourceType)
574 }
575 if err != nil {
576 return nil, err
577 }
578 return ids, nil
579}
580
581func (t *TechProfileMgr) FreeResourceID(ctx context.Context, intfID uint32, resourceType string, ReleaseContent []uint32) error {
582 logger.Debugw(ctx, "freeing-resource-id", log.Fields{
583 "intf-id": intfID,
584 "resource-type": resourceType,
585 "release-content": ReleaseContent,
586 })
587 var err error
588 switch resourceType {
589 case t.resourceMgr.GetResourceTypeAllocID():
590 t.AllocIDMgmtLock.Lock()
591 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
592 t.AllocIDMgmtLock.Unlock()
593 case t.resourceMgr.GetResourceTypeGemPortID():
594 t.GemPortIDMgmtLock.Lock()
595 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
596 t.GemPortIDMgmtLock.Unlock()
597 case t.resourceMgr.GetResourceTypeOnuID():
598 t.OnuIDMgmtLock.Lock()
599 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
600 t.OnuIDMgmtLock.Unlock()
601 default:
602 return fmt.Errorf("resourceType %s not supported", resourceType)
603 }
604 if err != nil {
605 return err
606 }
607 return nil
608}
609
610func (t *TechProfileMgr) GetUsScheduler(tpInstance *tp_pb.TechProfileInstance) *tp_pb.SchedulerConfig {
611 return &tp_pb.SchedulerConfig{
612 Direction: tpInstance.UsScheduler.Direction,
613 AdditionalBw: tpInstance.UsScheduler.AdditionalBw,
614 Priority: tpInstance.UsScheduler.Priority,
615 Weight: tpInstance.UsScheduler.Weight,
616 SchedPolicy: tpInstance.UsScheduler.QSchedPolicy}
617}
618
619func (t *TechProfileMgr) GetDsScheduler(tpInstance *tp_pb.TechProfileInstance) *tp_pb.SchedulerConfig {
620 return &tp_pb.SchedulerConfig{
621 Direction: tpInstance.DsScheduler.Direction,
622 AdditionalBw: tpInstance.DsScheduler.AdditionalBw,
623 Priority: tpInstance.DsScheduler.Priority,
624 Weight: tpInstance.DsScheduler.Weight,
625 SchedPolicy: tpInstance.DsScheduler.QSchedPolicy}
626}
627
628func (t *TechProfileMgr) GetTrafficScheduler(tpInstance *tp_pb.TechProfileInstance, SchedCfg *tp_pb.SchedulerConfig,
629 ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler {
630
631 tSched := &tp_pb.TrafficScheduler{
632 Direction: SchedCfg.Direction,
633 AllocId: tpInstance.UsScheduler.AllocId,
634 TrafficShapingInfo: ShapingCfg,
635 Scheduler: SchedCfg}
636
637 return tSched
638}
639
640func (t *TechProfileMgr) GetTrafficQueues(ctx context.Context, tp *tp_pb.TechProfileInstance, direction tp_pb.Direction) ([]*tp_pb.TrafficQueue, error) {
641
642 var encryp bool
643 if direction == tp_pb.Direction_UPSTREAM {
644 // upstream GEM ports
645 NumGemPorts := len(tp.UpstreamGemPortAttributeList)
646 GemPorts := make([]*tp_pb.TrafficQueue, 0)
647 for Count := 0; Count < NumGemPorts; Count++ {
648 if tp.UpstreamGemPortAttributeList[Count].AesEncryption == "True" {
649 encryp = true
650 } else {
651 encryp = false
652 }
653
654 GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
655 Direction: direction,
656 GemportId: tp.UpstreamGemPortAttributeList[Count].GemportId,
657 PbitMap: tp.UpstreamGemPortAttributeList[Count].PbitMap,
658 AesEncryption: encryp,
659 SchedPolicy: tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy,
660 Priority: tp.UpstreamGemPortAttributeList[Count].PriorityQ,
661 Weight: tp.UpstreamGemPortAttributeList[Count].Weight,
662 DiscardPolicy: tp.UpstreamGemPortAttributeList[Count].DiscardPolicy,
663 })
664 }
665 logger.Debugw(ctx, "Upstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
666 return GemPorts, nil
667 } else if direction == tp_pb.Direction_DOWNSTREAM {
668 //downstream GEM ports
669 NumGemPorts := len(tp.DownstreamGemPortAttributeList)
670 GemPorts := make([]*tp_pb.TrafficQueue, 0)
671 for Count := 0; Count < NumGemPorts; Count++ {
672 if isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
673 //do not take multicast GEM ports. They are handled separately.
674 continue
675 }
676 if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
677 encryp = true
678 } else {
679 encryp = false
680 }
681
682 GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
683 Direction: direction,
684 GemportId: tp.DownstreamGemPortAttributeList[Count].GemportId,
685 PbitMap: tp.DownstreamGemPortAttributeList[Count].PbitMap,
686 AesEncryption: encryp,
687 SchedPolicy: tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy,
688 Priority: tp.DownstreamGemPortAttributeList[Count].PriorityQ,
689 Weight: tp.DownstreamGemPortAttributeList[Count].Weight,
690 DiscardPolicy: tp.DownstreamGemPortAttributeList[Count].DiscardPolicy,
691 })
692 }
693 logger.Debugw(ctx, "Downstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
694 return GemPorts, nil
695 }
696
697 logger.Errorf(ctx, "Unsupported direction %s used for generating Traffic Queue list", direction)
698 return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unsupported direction %s", direction)
699}
700
701func (t *TechProfileMgr) validateInstanceControlAttr(ctx context.Context, instCtl tp_pb.InstanceControl) error {
Girish Gowdra9447baf2019-11-05 16:42:37 +0530702 if instCtl.Onu != "single-instance" && instCtl.Onu != "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000703 logger.Errorw(ctx, "invalid-onu-instance-control-attribute", log.Fields{"onu-inst": instCtl.Onu})
Girish Gowdra9447baf2019-11-05 16:42:37 +0530704 return errors.New("invalid-onu-instance-ctl-attr")
705 }
706
707 if instCtl.Uni != "single-instance" && instCtl.Uni != "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000708 logger.Errorw(ctx, "invalid-uni-instance-control-attribute", log.Fields{"uni-inst": instCtl.Uni})
Girish Gowdra9447baf2019-11-05 16:42:37 +0530709 return errors.New("invalid-uni-instance-ctl-attr")
710 }
711
712 if instCtl.Uni == "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000713 logger.Error(ctx, "uni-multi-instance-tp-not-supported")
Girish Gowdra9447baf2019-11-05 16:42:37 +0530714 return errors.New("uni-multi-instance-tp-not-supported")
715 }
716
717 return nil
718}
719
Girish Gowdra248971a2021-06-01 15:14:15 -0700720// allocateTPInstance for GPON, XGPON and XGS-PON technology
721func (t *TechProfileMgr) allocateTPInstance(ctx context.Context, uniPortName string, tp *tp_pb.TechProfile, intfID uint32, tpInstPathSuffix string) *tp_pb.TechProfileInstance {
Scott Baker2c1c4822019-10-16 11:02:41 -0700722
Girish Gowdra248971a2021-06-01 15:14:15 -0700723 var usGemPortAttributeList []*tp_pb.GemPortAttributes
724 var dsGemPortAttributeList []*tp_pb.GemPortAttributes
725 var dsMulticastGemAttributeList []*tp_pb.GemPortAttributes
726 var dsUnicastGemAttributeList []*tp_pb.GemPortAttributes
Scott Baker2c1c4822019-10-16 11:02:41 -0700727 var tcontIDs []uint32
728 var gemPorts []uint32
729 var err error
730
Girish Gowdra248971a2021-06-01 15:14:15 -0700731 logger.Infow(ctx, "Allocating TechProfileMgr instance from techprofile template", log.Fields{"uniPortName": uniPortName, "intfID": intfID, "numGem": tp.NumGemPorts})
Girish Gowdra9447baf2019-11-05 16:42:37 +0530732
Girish Gowdra248971a2021-06-01 15:14:15 -0700733 if tp.InstanceControl.Onu == "multi-instance" {
734 tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000735 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700736 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530737 return nil
738 }
739 } else { // "single-instance"
Girish Gowdra248971a2021-06-01 15:14:15 -0700740 if tpInst := t.getSingleInstanceTp(ctx, tpInstPathSuffix); tpInst == nil {
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530741 // No "single-instance" tp found on one any uni port for the given TP ID
742 // Allocate a new TcontID or AllocID
Girish Gowdra248971a2021-06-01 15:14:15 -0700743 tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000744 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700745 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530746 return nil
747 }
748 } else {
749 // Use the alloc-id from the existing TpInstance
Girish Gowdra248971a2021-06-01 15:14:15 -0700750 tcontIDs = append(tcontIDs, tpInst.UsScheduler.AllocId)
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530751 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700752 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000753 logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
Girish Gowdra248971a2021-06-01 15:14:15 -0700754 gemPorts, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000755 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700756 logger.Errorw(ctx, "Error getting gemport ids from rsrcrMgr", log.Fields{"err": err, "intfID": intfID, "numGemports": tp.NumGemPorts})
Scott Baker2c1c4822019-10-16 11:02:41 -0700757 return nil
758 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000759 logger.Infow(ctx, "Allocated tconts and GEM ports successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
Scott Baker2c1c4822019-10-16 11:02:41 -0700760 for index := 0; index < int(tp.NumGemPorts); index++ {
761 usGemPortAttributeList = append(usGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700762 &tp_pb.GemPortAttributes{GemportId: gemPorts[index],
763 MaxQSize: tp.UpstreamGemPortAttributeList[index].MaxQSize,
Scott Baker2c1c4822019-10-16 11:02:41 -0700764 PbitMap: tp.UpstreamGemPortAttributeList[index].PbitMap,
765 AesEncryption: tp.UpstreamGemPortAttributeList[index].AesEncryption,
766 SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700767 PriorityQ: tp.UpstreamGemPortAttributeList[index].PriorityQ,
Scott Baker2c1c4822019-10-16 11:02:41 -0700768 Weight: tp.UpstreamGemPortAttributeList[index].Weight,
769 DiscardPolicy: tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
770 DiscardConfig: tp.UpstreamGemPortAttributeList[index].DiscardConfig})
Esin Karaman8aa75a72019-12-20 13:11:59 +0000771 }
772
Neha Sharma94f16a92020-06-26 04:17:55 +0000773 logger.Info(ctx, "length of DownstreamGemPortAttributeList", len(tp.DownstreamGemPortAttributeList))
Esin Karaman8aa75a72019-12-20 13:11:59 +0000774 //put multicast and unicast downstream GEM port attributes in different lists first
Girish Gowdra248971a2021-06-01 15:14:15 -0700775 for index := 0; index < len(tp.DownstreamGemPortAttributeList); index++ {
Esin Karaman8aa75a72019-12-20 13:11:59 +0000776 if isMulticastGem(tp.DownstreamGemPortAttributeList[index].IsMulticast) {
777 dsMulticastGemAttributeList = append(dsMulticastGemAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700778 &tp_pb.GemPortAttributes{
779 MulticastGemId: tp.DownstreamGemPortAttributeList[index].MulticastGemId,
780 MaxQSize: tp.DownstreamGemPortAttributeList[index].MaxQSize,
781 PbitMap: tp.DownstreamGemPortAttributeList[index].PbitMap,
782 AesEncryption: tp.DownstreamGemPortAttributeList[index].AesEncryption,
783 SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
784 PriorityQ: tp.DownstreamGemPortAttributeList[index].PriorityQ,
785 Weight: tp.DownstreamGemPortAttributeList[index].Weight,
786 DiscardPolicy: tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
787 DiscardConfig: tp.DownstreamGemPortAttributeList[index].DiscardConfig,
788 IsMulticast: tp.DownstreamGemPortAttributeList[index].IsMulticast,
789 DynamicAccessControlList: tp.DownstreamGemPortAttributeList[index].DynamicAccessControlList,
790 StaticAccessControlList: tp.DownstreamGemPortAttributeList[index].StaticAccessControlList})
Esin Karaman8aa75a72019-12-20 13:11:59 +0000791 } else {
792 dsUnicastGemAttributeList = append(dsUnicastGemAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700793 &tp_pb.GemPortAttributes{
794 MaxQSize: tp.DownstreamGemPortAttributeList[index].MaxQSize,
Esin Karaman8aa75a72019-12-20 13:11:59 +0000795 PbitMap: tp.DownstreamGemPortAttributeList[index].PbitMap,
796 AesEncryption: tp.DownstreamGemPortAttributeList[index].AesEncryption,
797 SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700798 PriorityQ: tp.DownstreamGemPortAttributeList[index].PriorityQ,
Esin Karaman8aa75a72019-12-20 13:11:59 +0000799 Weight: tp.DownstreamGemPortAttributeList[index].Weight,
800 DiscardPolicy: tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
801 DiscardConfig: tp.DownstreamGemPortAttributeList[index].DiscardConfig})
802 }
803 }
804 //add unicast downstream GEM ports to dsGemPortAttributeList
Girish Gowdra248971a2021-06-01 15:14:15 -0700805 if dsUnicastGemAttributeList != nil {
806 for index := 0; index < int(tp.NumGemPorts); index++ {
807 dsGemPortAttributeList = append(dsGemPortAttributeList,
808 &tp_pb.GemPortAttributes{GemportId: gemPorts[index],
809 MaxQSize: dsUnicastGemAttributeList[index].MaxQSize,
810 PbitMap: dsUnicastGemAttributeList[index].PbitMap,
811 AesEncryption: dsUnicastGemAttributeList[index].AesEncryption,
812 SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
813 PriorityQ: dsUnicastGemAttributeList[index].PriorityQ,
814 Weight: dsUnicastGemAttributeList[index].Weight,
815 DiscardPolicy: dsUnicastGemAttributeList[index].DiscardPolicy,
816 DiscardConfig: dsUnicastGemAttributeList[index].DiscardConfig})
817 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700818 }
Esin Karaman8aa75a72019-12-20 13:11:59 +0000819 //add multicast GEM ports to dsGemPortAttributeList afterwards
Akash Reddy Kankanala05aff182025-05-06 12:57:32 +0530820 dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList...)
Esin Karaman8aa75a72019-12-20 13:11:59 +0000821
Girish Gowdra248971a2021-06-01 15:14:15 -0700822 return &tp_pb.TechProfileInstance{
Scott Baker2c1c4822019-10-16 11:02:41 -0700823 SubscriberIdentifier: uniPortName,
824 Name: tp.Name,
825 ProfileType: tp.ProfileType,
826 Version: tp.Version,
827 NumGemPorts: tp.NumGemPorts,
Girish Gowdra248971a2021-06-01 15:14:15 -0700828 InstanceControl: tp.InstanceControl,
829 UsScheduler: &tp_pb.SchedulerAttributes{
830 AllocId: tcontIDs[0],
Scott Baker2c1c4822019-10-16 11:02:41 -0700831 Direction: tp.UsScheduler.Direction,
832 AdditionalBw: tp.UsScheduler.AdditionalBw,
833 Priority: tp.UsScheduler.Priority,
834 Weight: tp.UsScheduler.Weight,
835 QSchedPolicy: tp.UsScheduler.QSchedPolicy},
Girish Gowdra248971a2021-06-01 15:14:15 -0700836 DsScheduler: &tp_pb.SchedulerAttributes{
837 AllocId: tcontIDs[0],
Scott Baker2c1c4822019-10-16 11:02:41 -0700838 Direction: tp.DsScheduler.Direction,
839 AdditionalBw: tp.DsScheduler.AdditionalBw,
840 Priority: tp.DsScheduler.Priority,
841 Weight: tp.DsScheduler.Weight,
842 QSchedPolicy: tp.DsScheduler.QSchedPolicy},
843 UpstreamGemPortAttributeList: usGemPortAttributeList,
844 DownstreamGemPortAttributeList: dsGemPortAttributeList}
845}
846
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700847// allocateTPInstance function for EPON
Girish Gowdra248971a2021-06-01 15:14:15 -0700848func (t *TechProfileMgr) allocateEponTPInstance(ctx context.Context, uniPortName string, tp *tp_pb.EponTechProfile, intfID uint32, tpInstPath string) *tp_pb.EponTechProfileInstance {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700849
Girish Gowdra248971a2021-06-01 15:14:15 -0700850 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
851 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700852 var tcontIDs []uint32
853 var gemPorts []uint32
854 var err error
855
Girish Gowdra248971a2021-06-01 15:14:15 -0700856 logger.Infow(ctx, "allocating-tp-instance-from-tp-template", log.Fields{"uniPortName": uniPortName, "intfID": intfID, "numGem": tp.NumGemPorts})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700857
Girish Gowdra248971a2021-06-01 15:14:15 -0700858 if tp.InstanceControl.Onu == "multi-instance" {
859 if tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
860 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700861 return nil
862 }
863 } else { // "single-instance"
Girish Gowdra248971a2021-06-01 15:14:15 -0700864 if tpInst := t.getSingleInstanceEponTp(ctx, tpInstPath); tpInst == nil {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700865 // No "single-instance" tp found on one any uni port for the given TP ID
866 // Allocate a new TcontID or AllocID
Girish Gowdra248971a2021-06-01 15:14:15 -0700867 if tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
868 logger.Errorw(ctx, "error-getting-alloc-id-from-resource-mgr", log.Fields{"err": err, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700869 return nil
870 }
871 } else {
872 // Use the alloc-id from the existing TpInstance
Girish Gowdra248971a2021-06-01 15:14:15 -0700873 tcontIDs = append(tcontIDs, tpInst.AllocId)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700874 }
875 }
Girish Kumar950f21e2020-08-19 17:42:29 +0000876 logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
Girish Gowdra248971a2021-06-01 15:14:15 -0700877 if gemPorts, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts); err != nil {
878 logger.Errorw(ctx, "error-getting-gemport-id-from-resource-mgr", log.Fields{"err": err, "intfID": intfID, "numGemports": tp.NumGemPorts})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700879 return nil
880 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700881 logger.Infow(ctx, "allocated-alloc-id-and-gemport-successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700882 for index := 0; index < int(tp.NumGemPorts); index++ {
883 usQueueAttributeList = append(usQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700884 &tp_pb.EPONQueueAttributes{GemportId: gemPorts[index],
885 MaxQSize: tp.UpstreamQueueAttributeList[index].MaxQSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700886 PbitMap: tp.UpstreamQueueAttributeList[index].PbitMap,
887 AesEncryption: tp.UpstreamQueueAttributeList[index].AesEncryption,
888 TrafficType: tp.UpstreamQueueAttributeList[index].TrafficType,
889 UnsolicitedGrantSize: tp.UpstreamQueueAttributeList[index].UnsolicitedGrantSize,
890 NominalInterval: tp.UpstreamQueueAttributeList[index].NominalInterval,
891 ToleratedPollJitter: tp.UpstreamQueueAttributeList[index].ToleratedPollJitter,
892 RequestTransmissionPolicy: tp.UpstreamQueueAttributeList[index].RequestTransmissionPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700893 NumQSets: tp.UpstreamQueueAttributeList[index].NumQSets,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700894 QThresholds: tp.UpstreamQueueAttributeList[index].QThresholds,
895 SchedulingPolicy: tp.UpstreamQueueAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700896 PriorityQ: tp.UpstreamQueueAttributeList[index].PriorityQ,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700897 Weight: tp.UpstreamQueueAttributeList[index].Weight,
898 DiscardPolicy: tp.UpstreamQueueAttributeList[index].DiscardPolicy,
899 DiscardConfig: tp.UpstreamQueueAttributeList[index].DiscardConfig})
900 }
901
Girish Gowdra248971a2021-06-01 15:14:15 -0700902 logger.Info(ctx, "length-of-downstream-gemport-attribute-list", len(tp.DownstreamQueueAttributeList))
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700903 for index := 0; index < int(tp.NumGemPorts); index++ {
904 dsQueueAttributeList = append(dsQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700905 &tp_pb.EPONQueueAttributes{GemportId: gemPorts[index],
906 MaxQSize: tp.DownstreamQueueAttributeList[index].MaxQSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700907 PbitMap: tp.DownstreamQueueAttributeList[index].PbitMap,
908 AesEncryption: tp.DownstreamQueueAttributeList[index].AesEncryption,
909 SchedulingPolicy: tp.DownstreamQueueAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700910 PriorityQ: tp.DownstreamQueueAttributeList[index].PriorityQ,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700911 Weight: tp.DownstreamQueueAttributeList[index].Weight,
912 DiscardPolicy: tp.DownstreamQueueAttributeList[index].DiscardPolicy,
913 DiscardConfig: tp.DownstreamQueueAttributeList[index].DiscardConfig})
914 }
915
Girish Gowdra248971a2021-06-01 15:14:15 -0700916 return &tp_pb.EponTechProfileInstance{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700917 SubscriberIdentifier: uniPortName,
918 Name: tp.Name,
919 ProfileType: tp.ProfileType,
920 Version: tp.Version,
921 NumGemPorts: tp.NumGemPorts,
Girish Gowdra248971a2021-06-01 15:14:15 -0700922 InstanceControl: tp.InstanceControl,
923 PackageType: tp.PackageType,
924 AllocId: tcontIDs[0],
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700925 UpstreamQueueAttributeList: usQueueAttributeList,
926 DownstreamQueueAttributeList: dsQueueAttributeList}
927}
928
Girish Gowdra248971a2021-06-01 15:14:15 -0700929// getSingleInstanceTp returns another TpInstance (GPON, XGPON, XGS-PON) for an ONU on a different
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530930// uni port for the same TP ID, if it finds one, else nil.
Girish Gowdra248971a2021-06-01 15:14:15 -0700931func (t *TechProfileMgr) getSingleInstanceTp(ctx context.Context, tpPathSuffix string) *tp_pb.TechProfileInstance {
Girish Gowdra9447baf2019-11-05 16:42:37 +0530932
933 // For example:
Girish Gowdra248971a2021-06-01 15:14:15 -0700934 // tpPathSuffix like "XGS-PON/64/olt-{1234}/pon-{0}/onu-{1}/uni-{1}"
935 // is broken into ["XGS-PON/64/olt-{1234}/pon-{0}/onu-{1}" ""]
936 uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPathSuffix, 2)
Girish Gowdra9447baf2019-11-05 16:42:37 +0530937
Girish Gowdra248971a2021-06-01 15:14:15 -0700938 t.tpInstanceMapLock.RLock()
939 defer t.tpInstanceMapLock.RUnlock()
940 for i := 0; i < MaxUniPortPerOnu; i++ {
941 key := fmt.Sprintf(uniPathSlice[0]+"/uni-{%d}", i)
942 if tpInst, ok := t.tpInstanceMap[key]; ok {
943 logger.Debugw(ctx, "found-single-instance-tp", log.Fields{"key": key})
944 return tpInst
Girish Gowdra9447baf2019-11-05 16:42:37 +0530945 }
946 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700947 return nil
Girish Gowdra9447baf2019-11-05 16:42:37 +0530948}
949
Girish Gowdra248971a2021-06-01 15:14:15 -0700950// getSingleInstanceTp returns another TpInstance (EPON) for an ONU on a different
951// uni port for the same TP ID, if it finds one, else nil.
952func (t *TechProfileMgr) getSingleInstanceEponTp(ctx context.Context, tpPathSuffix string) *tp_pb.EponTechProfileInstance {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700953 // For example:
Girish Gowdra248971a2021-06-01 15:14:15 -0700954 // tpPathSuffix like "EPON/64/olt-{1234}/pon-{0}/onu-{1}/uni-{1}"
955 // is broken into ["EPON/64/-{1234}/pon-{0}/onu-{1}" ""]
956 uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPathSuffix, 2)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700957
Girish Gowdra248971a2021-06-01 15:14:15 -0700958 t.epontpInstanceMapLock.RLock()
959 defer t.epontpInstanceMapLock.RUnlock()
960 for i := 0; i < MaxUniPortPerOnu; i++ {
961 key := fmt.Sprintf(uniPathSlice[0]+"/uni-{%d}", i)
962 if tpInst, ok := t.eponTpInstanceMap[key]; ok {
963 logger.Debugw(ctx, "found-single-instance-tp", log.Fields{"key": key})
964 return tpInst
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700965 }
966 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700967 return nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700968}
969
Girish Gowdra248971a2021-06-01 15:14:15 -0700970// getDefaultTechProfile returns a default TechProfile for GPON, XGPON, XGS-PON
971func (t *TechProfileMgr) getDefaultTechProfile(ctx context.Context) *tp_pb.TechProfile {
972 var usGemPortAttributeList []*tp_pb.GemPortAttributes
973 var dsGemPortAttributeList []*tp_pb.GemPortAttributes
Scott Baker2c1c4822019-10-16 11:02:41 -0700974
975 for _, pbit := range t.config.DefaultPbits {
Girish Gowdra248971a2021-06-01 15:14:15 -0700976 logger.Debugw(ctx, "creating-gem-port-profile-profile", log.Fields{"pbit": pbit})
Scott Baker2c1c4822019-10-16 11:02:41 -0700977 usGemPortAttributeList = append(usGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700978 &tp_pb.GemPortAttributes{
979 MaxQSize: defaultMaxQueueSize,
Scott Baker2c1c4822019-10-16 11:02:41 -0700980 PbitMap: pbit,
981 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -0700982 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
983 PriorityQ: defaultPriorityQueue,
Scott Baker2c1c4822019-10-16 11:02:41 -0700984 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -0700985 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
986 DiscardConfigV2: &tp_pb.DiscardConfig{
987 DiscardPolicy: tp_pb.DiscardPolicy_Red,
988 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
989 RedDiscardConfig: &tp_pb.RedDiscardConfig{
990 MinThreshold: defaultMinThreshold,
991 MaxThreshold: defaultMaxThreshold,
992 MaxProbability: defaultMaxProbability,
993 },
994 },
995 },
996 DiscardConfig: &tp_pb.RedDiscardConfig{
Scott Baker2c1c4822019-10-16 11:02:41 -0700997 MinThreshold: defaultMinThreshold,
998 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -0700999 MaxProbability: defaultMaxProbability,
1000 },
1001 })
Scott Baker2c1c4822019-10-16 11:02:41 -07001002 dsGemPortAttributeList = append(dsGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001003 &tp_pb.GemPortAttributes{
1004 MaxQSize: defaultMaxQueueSize,
Scott Baker2c1c4822019-10-16 11:02:41 -07001005 PbitMap: pbit,
1006 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -07001007 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1008 PriorityQ: defaultPriorityQueue,
Scott Baker2c1c4822019-10-16 11:02:41 -07001009 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001010 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1011 DiscardConfigV2: &tp_pb.DiscardConfig{
1012 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1013 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1014 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1015 MinThreshold: defaultMinThreshold,
1016 MaxThreshold: defaultMaxThreshold,
1017 MaxProbability: defaultMaxProbability,
1018 },
1019 },
1020 },
1021 DiscardConfig: &tp_pb.RedDiscardConfig{
Scott Baker2c1c4822019-10-16 11:02:41 -07001022 MinThreshold: defaultMinThreshold,
1023 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001024 MaxProbability: defaultMaxProbability,
1025 },
1026 IsMulticast: defaultIsMulticast,
1027 DynamicAccessControlList: defaultAccessControlList,
1028 StaticAccessControlList: defaultAccessControlList,
1029 MulticastGemId: defaultMcastGemID})
Scott Baker2c1c4822019-10-16 11:02:41 -07001030 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001031 return &tp_pb.TechProfile{
Scott Baker2c1c4822019-10-16 11:02:41 -07001032 Name: t.config.DefaultTPName,
1033 ProfileType: t.resourceMgr.GetTechnology(),
1034 Version: t.config.TPVersion,
1035 NumGemPorts: uint32(len(usGemPortAttributeList)),
Girish Gowdra248971a2021-06-01 15:14:15 -07001036 InstanceControl: &tp_pb.InstanceControl{
Scott Baker2c1c4822019-10-16 11:02:41 -07001037 Onu: defaultOnuInstance,
1038 Uni: defaultUniInstance,
1039 MaxGemPayloadSize: defaultGemPayloadSize},
Girish Gowdra248971a2021-06-01 15:14:15 -07001040 UsScheduler: &tp_pb.SchedulerAttributes{
1041 Direction: tp_pb.Direction_UPSTREAM,
1042 AdditionalBw: tp_pb.AdditionalBW_AdditionalBW_BestEffort,
Scott Baker2c1c4822019-10-16 11:02:41 -07001043 Priority: defaultPriority,
1044 Weight: defaultWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001045 QSchedPolicy: tp_pb.SchedulingPolicy_Hybrid},
1046 DsScheduler: &tp_pb.SchedulerAttributes{
1047 Direction: tp_pb.Direction_DOWNSTREAM,
1048 AdditionalBw: tp_pb.AdditionalBW_AdditionalBW_BestEffort,
Scott Baker2c1c4822019-10-16 11:02:41 -07001049 Priority: defaultPriority,
1050 Weight: defaultWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001051 QSchedPolicy: tp_pb.SchedulingPolicy_Hybrid},
Scott Baker2c1c4822019-10-16 11:02:41 -07001052 UpstreamGemPortAttributeList: usGemPortAttributeList,
1053 DownstreamGemPortAttributeList: dsGemPortAttributeList}
1054}
1055
Girish Gowdra248971a2021-06-01 15:14:15 -07001056// getDefaultEponProfile returns a default TechProfile for EPON
1057func (t *TechProfileMgr) getDefaultEponProfile(ctx context.Context) *tp_pb.EponTechProfile {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001058
Girish Gowdra248971a2021-06-01 15:14:15 -07001059 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
1060 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001061
1062 for _, pbit := range t.config.DefaultPbits {
Girish Kumar950f21e2020-08-19 17:42:29 +00001063 logger.Debugw(ctx, "Creating Queue", log.Fields{"pbit": pbit})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001064 usQueueAttributeList = append(usQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001065 &tp_pb.EPONQueueAttributes{
1066 MaxQSize: defaultMaxQueueSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001067 PbitMap: pbit,
1068 AesEncryption: defaultAESEncryption,
1069 TrafficType: defaultTrafficType,
1070 UnsolicitedGrantSize: defaultUnsolicitedGrantSize,
1071 NominalInterval: defaultNominalInterval,
1072 ToleratedPollJitter: defaultToleratedPollJitter,
1073 RequestTransmissionPolicy: defaultRequestTransmissionPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -07001074 NumQSets: defaultNumQueueSet,
1075 QThresholds: &tp_pb.QThresholds{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001076 QThreshold1: defaultQThreshold1,
1077 QThreshold2: defaultQThreshold2,
1078 QThreshold3: defaultQThreshold3,
1079 QThreshold4: defaultQThreshold4,
1080 QThreshold5: defaultQThreshold5,
1081 QThreshold6: defaultQThreshold6,
1082 QThreshold7: defaultQThreshold7},
Girish Gowdra248971a2021-06-01 15:14:15 -07001083 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1084 PriorityQ: defaultPriorityQueue,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001085 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001086 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1087 DiscardConfigV2: &tp_pb.DiscardConfig{
1088 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1089 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1090 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1091 MinThreshold: defaultMinThreshold,
1092 MaxThreshold: defaultMaxThreshold,
1093 MaxProbability: defaultMaxProbability,
1094 },
1095 },
1096 },
1097 DiscardConfig: &tp_pb.RedDiscardConfig{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001098 MinThreshold: defaultMinThreshold,
1099 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001100 MaxProbability: defaultMaxProbability,
1101 }})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001102 dsQueueAttributeList = append(dsQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001103 &tp_pb.EPONQueueAttributes{
1104 MaxQSize: defaultMaxQueueSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001105 PbitMap: pbit,
1106 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -07001107 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1108 PriorityQ: defaultPriorityQueue,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001109 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001110 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1111 DiscardConfigV2: &tp_pb.DiscardConfig{
1112 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1113 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1114 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1115 MinThreshold: defaultMinThreshold,
1116 MaxThreshold: defaultMaxThreshold,
1117 MaxProbability: defaultMaxProbability,
1118 },
1119 },
1120 },
1121 DiscardConfig: &tp_pb.RedDiscardConfig{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001122 MinThreshold: defaultMinThreshold,
1123 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001124 MaxProbability: defaultMaxProbability,
1125 }})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001126 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001127 return &tp_pb.EponTechProfile{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001128 Name: t.config.DefaultTPName,
1129 ProfileType: t.resourceMgr.GetTechnology(),
1130 Version: t.config.TPVersion,
1131 NumGemPorts: uint32(len(usQueueAttributeList)),
Girish Gowdra248971a2021-06-01 15:14:15 -07001132 InstanceControl: &tp_pb.InstanceControl{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001133 Onu: defaultOnuInstance,
1134 Uni: defaultUniInstance,
1135 MaxGemPayloadSize: defaultGemPayloadSize},
Girish Gowdra248971a2021-06-01 15:14:15 -07001136 PackageType: defaultPakageType,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001137 UpstreamQueueAttributeList: usQueueAttributeList,
1138 DownstreamQueueAttributeList: dsQueueAttributeList}
1139}
1140
Joey Armstrong7f8436c2023-07-09 20:23:27 -04001141// isMulticastGem returns true if isMulticast attribute value of a GEM port is true; false otherwise
Esin Karaman8aa75a72019-12-20 13:11:59 +00001142func isMulticastGem(isMulticastAttrValue string) bool {
1143 return isMulticastAttrValue != "" &&
1144 (isMulticastAttrValue == "True" || isMulticastAttrValue == "true" || isMulticastAttrValue == "TRUE")
1145}
1146
Girish Gowdra248971a2021-06-01 15:14:15 -07001147func (t *TechProfileMgr) addResourceInstanceToKVStore(ctx context.Context, tpID uint32, uniPortName string, resInst tp_pb.ResourceInstance) error {
1148 logger.Debugw(ctx, "adding-resource-instance-to-kv-store", log.Fields{"tpID": tpID, "uniPortName": uniPortName, "resInst": resInst})
1149 val, err := proto.Marshal(&resInst)
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001150 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -07001151 logger.Errorw(ctx, "failed-to-marshall-resource-instance", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName, "resInst": resInst})
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001152 return err
1153 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001154 err = t.config.ResourceInstanceKVBacked.Put(ctx, fmt.Sprintf("%s/%d/%s", t.resourceMgr.GetTechnology(), tpID, uniPortName), val)
1155 return err
1156}
1157
1158func (t *TechProfileMgr) removeResourceInstanceFromKVStore(ctx context.Context, tpID uint32, uniPortName string) error {
1159 logger.Debugw(ctx, "removing-resource-instance-to-kv-store", log.Fields{"tpID": tpID, "uniPortName": uniPortName})
1160 if err := t.config.ResourceInstanceKVBacked.Delete(ctx, fmt.Sprintf("%s/%d/%s", t.resourceMgr.GetTechnology(), tpID, uniPortName)); err != nil {
1161 logger.Errorw(ctx, "error-removing-resource-instance-to-kv-store", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
1162 return err
1163 }
1164 return nil
1165}
1166
1167func (t *TechProfileMgr) getTPFromKVStore(ctx context.Context, tpID uint32) *tp_pb.TechProfile {
1168 var tp *tp_pb.TechProfile
1169 t.tpMapLock.RLock()
1170 tp, ok := t.tpMap[tpID]
1171 t.tpMapLock.RUnlock()
1172 if ok {
1173 logger.Debugw(ctx, "found-tp-in-cache", log.Fields{"tpID": tpID})
1174 return tp
1175 }
1176 key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), tpID)
1177 logger.Debugw(ctx, "getting-tp-from-kv-store", log.Fields{"tpID": tpID, "Key": key})
1178 kvresult, err := t.config.DefaultTpKVBackend.Get(ctx, key)
1179 if err != nil {
1180 logger.Errorw(ctx, "error-fetching-from-kv-store", log.Fields{"err": err, "key": key})
1181 return nil
1182 }
1183 if kvresult != nil {
1184 /* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
1185 if value, err := kvstore.ToByte(kvresult.Value); err == nil {
1186 lTp := &tp_pb.TechProfile{}
1187 reader := bytes.NewReader(value)
1188 if err = jsonpb.Unmarshal(reader, lTp); err != nil {
1189 logger.Errorw(ctx, "error-unmarshalling-tp-from-kv-store", log.Fields{"err": err, "tpID": tpID, "error": err})
1190 return nil
1191 }
1192
1193 logger.Debugw(ctx, "success-fetched-tp-from-kv-store", log.Fields{"tpID": tpID, "value": *lTp})
1194 return lTp
1195 } else {
1196 logger.Errorw(ctx, "error-decoding-tp", log.Fields{"err": err, "tpID": tpID})
1197 // We we create a default profile in this case.
1198 }
1199 }
1200
1201 return nil
1202}
1203
1204func (t *TechProfileMgr) getEponTPFromKVStore(ctx context.Context, tpID uint32) *tp_pb.EponTechProfile {
1205 var eponTp *tp_pb.EponTechProfile
1206 t.eponTpMapLock.RLock()
1207 eponTp, ok := t.eponTpMap[tpID]
1208 t.eponTpMapLock.RUnlock()
1209 if ok {
1210 logger.Debugw(ctx, "found-tp-in-cache", log.Fields{"tpID": tpID})
1211 return eponTp
1212 }
1213 key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), tpID)
1214 logger.Debugw(ctx, "getting-epon-tp-from-kv-store", log.Fields{"tpID": tpID, "Key": key})
1215 kvresult, err := t.config.DefaultTpKVBackend.Get(ctx, key)
1216 if err != nil {
1217 logger.Errorw(ctx, "error-fetching-from-kv-store", log.Fields{"err": err, "key": key})
1218 return nil
1219 }
1220 if kvresult != nil {
1221 /* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
1222 if value, err := kvstore.ToByte(kvresult.Value); err == nil {
1223 lEponTp := &tp_pb.EponTechProfile{}
1224 reader := bytes.NewReader(value)
1225 if err = jsonpb.Unmarshal(reader, lEponTp); err != nil {
1226 logger.Errorw(ctx, "error-unmarshalling-epon-tp-from-kv-store", log.Fields{"err": err, "tpID": tpID, "error": err})
1227 return nil
1228 }
1229
1230 logger.Debugw(ctx, "success-fetching-epon-tp-from-kv-store", log.Fields{"tpID": tpID, "value": *lEponTp})
1231 return lEponTp
1232 }
1233 }
1234 return nil
1235}
1236
1237func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
1238
1239 logger.Infow(ctx, "kv-store", log.Fields{"storeType": storeType, "address": address})
1240 switch storeType {
1241 case "etcd":
1242 return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
serkant.uluderyae5afeff2021-02-23 18:00:23 +03001243 case "redis":
1244 return kvstore.NewRedisClient(address, timeout, false)
1245 case "redis-sentinel":
1246 return kvstore.NewRedisClient(address, timeout, true)
Girish Gowdra248971a2021-06-01 15:14:15 -07001247 }
serkant.uluderyae5afeff2021-02-23 18:00:23 +03001248
Girish Gowdra248971a2021-06-01 15:14:15 -07001249 return nil, errors.New("unsupported-kv-store")
1250}
1251
1252// buildTpInstanceFromResourceInstance for GPON, XGPON and XGS-PON technology - build TpInstance from TechProfile template and ResourceInstance
1253func (t *TechProfileMgr) buildTpInstanceFromResourceInstance(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance) *tp_pb.TechProfileInstance {
1254
Girish Gowdra248971a2021-06-01 15:14:15 -07001255 if len(resInst.GemportIds) != int(tp.NumGemPorts) {
1256 logger.Errorw(ctx, "mismatch-in-number-of-gemports-between-template-and-resource-instance",
1257 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1258 return nil
1259 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001260
pnalmas23a77d02025-01-15 11:52:48 +05301261 usGemPortAttributeList := make([]*tp_pb.GemPortAttributes, 0, tp.NumGemPorts)
1262 dsGemPortAttributeList := make([]*tp_pb.GemPortAttributes, 0, tp.NumGemPorts)
1263 dsMulticastGemAttributeList := make([]*tp_pb.GemPortAttributes, 0)
1264 dsUnicastGemAttributeList := make([]*tp_pb.GemPortAttributes, 0)
1265
1266 logger.Debugw(ctx, "Building TP Instance",
1267 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1268
1269 usGemPortAttributeList = t.buildUpstreamGemPortAttributes(ctx, tp, resInst, usGemPortAttributeList)
1270 dsUnicastGemAttributeList, dsMulticastGemAttributeList = t.separateDownstreamGemPortAttributes(ctx, tp, dsUnicastGemAttributeList, dsMulticastGemAttributeList)
1271 dsGemPortAttributeList = t.buildDownstreamGemPortAttributes(ctx, tp, resInst, dsUnicastGemAttributeList, dsMulticastGemAttributeList, dsGemPortAttributeList)
Girish Gowdra248971a2021-06-01 15:14:15 -07001272
1273 return &tp_pb.TechProfileInstance{
1274 SubscriberIdentifier: resInst.SubscriberIdentifier,
1275 Name: tp.Name,
1276 ProfileType: tp.ProfileType,
1277 Version: tp.Version,
1278 NumGemPorts: tp.NumGemPorts,
1279 InstanceControl: tp.InstanceControl,
1280 UsScheduler: &tp_pb.SchedulerAttributes{
1281 AllocId: resInst.AllocId,
1282 Direction: tp.UsScheduler.Direction,
1283 AdditionalBw: tp.UsScheduler.AdditionalBw,
1284 Priority: tp.UsScheduler.Priority,
1285 Weight: tp.UsScheduler.Weight,
1286 QSchedPolicy: tp.UsScheduler.QSchedPolicy},
1287 DsScheduler: &tp_pb.SchedulerAttributes{
1288 AllocId: resInst.AllocId,
1289 Direction: tp.DsScheduler.Direction,
1290 AdditionalBw: tp.DsScheduler.AdditionalBw,
1291 Priority: tp.DsScheduler.Priority,
1292 Weight: tp.DsScheduler.Weight,
1293 QSchedPolicy: tp.DsScheduler.QSchedPolicy},
1294 UpstreamGemPortAttributeList: usGemPortAttributeList,
1295 DownstreamGemPortAttributeList: dsGemPortAttributeList}
1296}
1297
1298// buildEponTpInstanceFromResourceInstance for EPON technology - build EponTpInstance from EponTechProfile template and ResourceInstance
1299func (t *TechProfileMgr) buildEponTpInstanceFromResourceInstance(ctx context.Context, tp *tp_pb.EponTechProfile, resInst *tp_pb.ResourceInstance) *tp_pb.EponTechProfileInstance {
1300
1301 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
1302 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
1303
1304 if len(resInst.GemportIds) != int(tp.NumGemPorts) {
1305 logger.Errorw(ctx, "mismatch-in-number-of-gemports-between-epon-tp-template-and-resource-instance",
1306 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1307 return nil
1308 }
1309
1310 for index := 0; index < int(tp.NumGemPorts); index++ {
1311 usQueueAttributeList = append(usQueueAttributeList,
1312 &tp_pb.EPONQueueAttributes{GemportId: resInst.GemportIds[index],
1313 MaxQSize: tp.UpstreamQueueAttributeList[index].MaxQSize,
1314 PbitMap: tp.UpstreamQueueAttributeList[index].PbitMap,
1315 AesEncryption: tp.UpstreamQueueAttributeList[index].AesEncryption,
1316 TrafficType: tp.UpstreamQueueAttributeList[index].TrafficType,
1317 UnsolicitedGrantSize: tp.UpstreamQueueAttributeList[index].UnsolicitedGrantSize,
1318 NominalInterval: tp.UpstreamQueueAttributeList[index].NominalInterval,
1319 ToleratedPollJitter: tp.UpstreamQueueAttributeList[index].ToleratedPollJitter,
1320 RequestTransmissionPolicy: tp.UpstreamQueueAttributeList[index].RequestTransmissionPolicy,
1321 NumQSets: tp.UpstreamQueueAttributeList[index].NumQSets,
1322 QThresholds: tp.UpstreamQueueAttributeList[index].QThresholds,
1323 SchedulingPolicy: tp.UpstreamQueueAttributeList[index].SchedulingPolicy,
1324 PriorityQ: tp.UpstreamQueueAttributeList[index].PriorityQ,
1325 Weight: tp.UpstreamQueueAttributeList[index].Weight,
1326 DiscardPolicy: tp.UpstreamQueueAttributeList[index].DiscardPolicy,
1327 DiscardConfig: tp.UpstreamQueueAttributeList[index].DiscardConfig})
1328 }
1329
1330 for index := 0; index < int(tp.NumGemPorts); index++ {
1331 dsQueueAttributeList = append(dsQueueAttributeList,
1332 &tp_pb.EPONQueueAttributes{GemportId: resInst.GemportIds[index],
1333 MaxQSize: tp.DownstreamQueueAttributeList[index].MaxQSize,
1334 PbitMap: tp.DownstreamQueueAttributeList[index].PbitMap,
1335 AesEncryption: tp.DownstreamQueueAttributeList[index].AesEncryption,
1336 SchedulingPolicy: tp.DownstreamQueueAttributeList[index].SchedulingPolicy,
1337 PriorityQ: tp.DownstreamQueueAttributeList[index].PriorityQ,
1338 Weight: tp.DownstreamQueueAttributeList[index].Weight,
1339 DiscardPolicy: tp.DownstreamQueueAttributeList[index].DiscardPolicy,
1340 DiscardConfig: tp.DownstreamQueueAttributeList[index].DiscardConfig})
1341 }
1342
1343 return &tp_pb.EponTechProfileInstance{
1344 SubscriberIdentifier: resInst.SubscriberIdentifier,
1345 Name: tp.Name,
1346 ProfileType: tp.ProfileType,
1347 Version: tp.Version,
1348 NumGemPorts: tp.NumGemPorts,
1349 InstanceControl: tp.InstanceControl,
1350 PackageType: tp.PackageType,
1351 AllocId: resInst.AllocId,
1352 UpstreamQueueAttributeList: usQueueAttributeList,
1353 DownstreamQueueAttributeList: dsQueueAttributeList}
1354}
1355
1356func (t *TechProfileMgr) getTpInstanceFromResourceInstance(ctx context.Context, resInst *tp_pb.ResourceInstance) *tp_pb.TechProfileInstance {
1357 if resInst == nil {
1358 logger.Error(ctx, "resource-instance-nil")
1359 return nil
1360 }
1361 tp := t.getTPFromKVStore(ctx, resInst.TpId)
1362 if tp == nil {
1363 logger.Warnw(ctx, "tp-not-found-on-kv--creating-default-tp", log.Fields{"tpID": resInst.TpId})
1364 tp = t.getDefaultTechProfile(ctx)
1365 }
1366 return t.buildTpInstanceFromResourceInstance(ctx, tp, resInst)
1367}
1368
1369func (t *TechProfileMgr) getEponTpInstanceFromResourceInstance(ctx context.Context, resInst *tp_pb.ResourceInstance) *tp_pb.EponTechProfileInstance {
1370 if resInst == nil {
1371 logger.Error(ctx, "resource-instance-nil")
1372 return nil
1373 }
1374 eponTp := t.getEponTPFromKVStore(ctx, resInst.TpId)
1375 if eponTp == nil {
1376 logger.Warnw(ctx, "tp-not-found-on-kv--creating-default-tp", log.Fields{"tpID": resInst.TpId})
1377 eponTp = t.getDefaultEponProfile(ctx)
1378 }
1379 return t.buildEponTpInstanceFromResourceInstance(ctx, eponTp, resInst)
1380}
1381
pnalmas23a77d02025-01-15 11:52:48 +05301382func (t *TechProfileMgr) reconcileTpInstancesToCache(ctx context.Context, IntfId uint32, deviceId string) error {
Girish Gowdra248971a2021-06-01 15:14:15 -07001383
1384 tech := t.resourceMgr.GetTechnology()
1385 newCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
1386 defer cancel()
Girish Gowdra248971a2021-06-01 15:14:15 -07001387
pnalmas23a77d02025-01-15 11:52:48 +05301388 //VOL-5417:Only reconcile the tech profiles for the subscribers associated with this PON port on this device.
1389 //Getting the list of supported tech profile IDs and then reconciling the tech profiles for these IDs associated
1390 //with the subscribers on this device for this PON port.
1391
1392 //Fetching the techprofile Keys from the KV Store.
1393 tpkeys, _ := t.config.DefaultTpKVBackend.GetWithPrefixKeysOnly(ctx, tech)
1394
1395 // Extract the techprofile Ids from the keys
1396 // The tpkeys will be of the format "service/voltha/technology_profiles/GPON/65"
1397 // where 65 is the techprofile Id
1398 tpIds := make([]uint32, 0)
1399
1400 for _, key := range tpkeys {
1401 parts := strings.Split(key, "/")
1402 // Ensure the key has the expected format
1403 if len(parts) < 5 {
1404 logger.Errorw(ctx, "Key does not match expected format", log.Fields{"key": key})
1405 continue
Girish Gowdra248971a2021-06-01 15:14:15 -07001406 }
pnalmas23a77d02025-01-15 11:52:48 +05301407 // Convert the last part of the key to uint32 (techprofile Id)
1408 tpId, err := strconv.Atoi(parts[len(parts)-1])
1409 if err != nil {
1410 logger.Errorw(ctx, "Error converting techprofile Id to int", log.Fields{"key": key, "error": err})
1411 continue
Girish Gowdra248971a2021-06-01 15:14:15 -07001412 }
pnalmas23a77d02025-01-15 11:52:48 +05301413 tpIds = append(tpIds, uint32(tpId))
Girish Gowdra248971a2021-06-01 15:14:15 -07001414 }
1415
pnalmas23a77d02025-01-15 11:52:48 +05301416 //for each tpid form a prefix and get the resource instance
1417 for _, tpId := range tpIds {
1418 prefix := fmt.Sprintf("%s/%d/olt-{%s}/pon-{%d}", tech, tpId, deviceId, IntfId)
1419 kvPairs, _ := t.config.ResourceInstanceKVBacked.GetWithPrefix(newCtx, prefix)
1420 //check if KvPairs is empty and if not then reconcile the techprofile instance
1421 if len(kvPairs) > 0 {
1422 for keyPath, kvPair := range kvPairs {
1423 if value, err := kvstore.ToByte(kvPair.Value); err == nil {
1424 var resInst tp_pb.ResourceInstance
1425 if err = proto.Unmarshal(value, &resInst); err != nil {
1426 logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"err": err, "keyPath": keyPath, "value": value})
1427 continue
1428 } else {
1429 if tech == xgspon || tech == xgpon || tech == gpon {
1430 if tpInst := t.getTpInstanceFromResourceInstance(ctx, &resInst); tpInst != nil {
1431 keySuffixSlice := regexp.MustCompile(t.config.ResourceInstanceKVPathPrefix+"/").Split(keyPath, 2)
1432 if len(keySuffixSlice) == 2 {
1433 keySuffixFormatRegexp := regexp.MustCompile(`^[a-zA-Z\-]+/[0-9]+/olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
1434 if !keySuffixFormatRegexp.Match([]byte(keySuffixSlice[1])) {
1435 logger.Errorw(ctx, "kv-path-not-confirming-to-format", log.Fields{"kvPath": keySuffixSlice[1]})
1436 continue
1437 }
1438 } else {
1439 logger.Errorw(ctx, "kv-instance-key-path-not-in-the-expected-format", log.Fields{"kvPath": keyPath})
1440 continue
1441 }
1442 t.tpInstanceMapLock.Lock()
1443 t.tpInstanceMap[keySuffixSlice[1]] = tpInst
1444 t.tpInstanceMapLock.Unlock()
1445 logger.Infow(ctx, "reconciled-tp-success", log.Fields{"keyPath": keyPath})
1446 }
1447 } else if tech == epon {
1448 if eponTpInst := t.getEponTpInstanceFromResourceInstance(ctx, &resInst); eponTpInst != nil {
1449 keySuffixSlice := regexp.MustCompile(t.config.ResourceInstanceKVPathPrefix+"/").Split(keyPath, 2)
1450 if len(keySuffixSlice) == 2 {
1451 keySuffixFormatRegexp := regexp.MustCompile(`^[a-zA-Z\-]+/[0-9]+/olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
1452 if !keySuffixFormatRegexp.Match([]byte(keySuffixSlice[1])) {
1453 logger.Errorw(ctx, "kv-path-not-confirming-to-format", log.Fields{"kvPath": keySuffixSlice[1]})
1454 continue
1455 }
1456 } else {
1457 logger.Errorw(ctx, "kv-instance-key-path-not-in-the-expected-format", log.Fields{"kvPath": keyPath})
1458 continue
1459 }
1460 t.epontpInstanceMapLock.Lock()
1461 t.eponTpInstanceMap[keySuffixSlice[1]] = eponTpInst
1462 t.epontpInstanceMapLock.Unlock()
1463 logger.Debugw(ctx, "reconciled-epon-tp-success", log.Fields{"keyPath": keyPath})
1464 }
1465 } else {
1466 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech})
1467 return fmt.Errorf("unknown-tech-%v", tech)
1468 }
1469 }
1470 } else {
1471 logger.Errorw(ctx, "error-converting-kv-pair-value-to-byte", log.Fields{"err": err})
1472 }
1473
1474 }
1475
1476 return nil
1477 }
1478 }
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001479 return nil
1480}
pnalmas23a77d02025-01-15 11:52:48 +05301481
1482func (t *TechProfileMgr) buildUpstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance, usGemPortAttributeList []*tp_pb.GemPortAttributes) []*tp_pb.GemPortAttributes {
1483 for index := 0; index < int(tp.NumGemPorts); index++ {
1484 usGemPortAttributeList = append(usGemPortAttributeList, &tp_pb.GemPortAttributes{
1485 GemportId: resInst.GemportIds[index],
1486 MaxQSize: tp.UpstreamGemPortAttributeList[index].MaxQSize,
1487 PbitMap: tp.UpstreamGemPortAttributeList[index].PbitMap,
1488 AesEncryption: tp.UpstreamGemPortAttributeList[index].AesEncryption,
1489 SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
1490 PriorityQ: tp.UpstreamGemPortAttributeList[index].PriorityQ,
1491 Weight: tp.UpstreamGemPortAttributeList[index].Weight,
1492 DiscardPolicy: tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
1493 DiscardConfig: tp.UpstreamGemPortAttributeList[index].DiscardConfig,
1494 })
1495 }
1496 logger.Debugw(ctx, "Processed upstream GEM port attributes", log.Fields{"count": len(usGemPortAttributeList)})
1497 return usGemPortAttributeList
1498}
1499
1500func (t *TechProfileMgr) separateDownstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, dsUnicastGemAttributeList, dsMulticastGemAttributeList []*tp_pb.GemPortAttributes) ([]*tp_pb.GemPortAttributes, []*tp_pb.GemPortAttributes) {
1501 for _, attr := range tp.DownstreamGemPortAttributeList {
1502 if isMulticastGem(attr.IsMulticast) {
1503 dsMulticastGemAttributeList = append(dsMulticastGemAttributeList, &tp_pb.GemPortAttributes{
1504 MulticastGemId: attr.MulticastGemId,
1505 MaxQSize: attr.MaxQSize,
1506 PbitMap: attr.PbitMap,
1507 AesEncryption: attr.AesEncryption,
1508 SchedulingPolicy: attr.SchedulingPolicy,
1509 PriorityQ: attr.PriorityQ,
1510 Weight: attr.Weight,
1511 DiscardPolicy: attr.DiscardPolicy,
1512 DiscardConfig: attr.DiscardConfig,
1513 IsMulticast: attr.IsMulticast,
1514 DynamicAccessControlList: attr.DynamicAccessControlList,
1515 StaticAccessControlList: attr.StaticAccessControlList,
1516 })
1517 } else {
1518 dsUnicastGemAttributeList = append(dsUnicastGemAttributeList, &tp_pb.GemPortAttributes{
1519 MaxQSize: attr.MaxQSize,
1520 PbitMap: attr.PbitMap,
1521 AesEncryption: attr.AesEncryption,
1522 SchedulingPolicy: attr.SchedulingPolicy,
1523 PriorityQ: attr.PriorityQ,
1524 Weight: attr.Weight,
1525 DiscardPolicy: attr.DiscardPolicy,
1526 DiscardConfig: attr.DiscardConfig,
1527 })
1528 }
1529 }
1530 logger.Debugw(ctx, "Processed downstream GEM port attributes", log.Fields{
1531 "unicastCount": len(dsUnicastGemAttributeList), "multicastCount": len(dsMulticastGemAttributeList)})
1532 return dsUnicastGemAttributeList, dsMulticastGemAttributeList
1533}
1534
1535func (t *TechProfileMgr) buildDownstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance, dsUnicastGemAttributeList, dsMulticastGemAttributeList, dsGemPortAttributeList []*tp_pb.GemPortAttributes) []*tp_pb.GemPortAttributes {
1536 for index := 0; index < int(tp.NumGemPorts) && index < len(dsUnicastGemAttributeList); index++ {
1537 dsGemPortAttributeList = append(dsGemPortAttributeList, &tp_pb.GemPortAttributes{
1538 GemportId: resInst.GemportIds[index],
1539 MaxQSize: dsUnicastGemAttributeList[index].MaxQSize,
1540 PbitMap: dsUnicastGemAttributeList[index].PbitMap,
1541 AesEncryption: dsUnicastGemAttributeList[index].AesEncryption,
1542 SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
1543 PriorityQ: dsUnicastGemAttributeList[index].PriorityQ,
1544 Weight: dsUnicastGemAttributeList[index].Weight,
1545 DiscardPolicy: dsUnicastGemAttributeList[index].DiscardPolicy,
1546 DiscardConfig: dsUnicastGemAttributeList[index].DiscardConfig,
1547 })
1548 }
1549 dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList...)
1550 logger.Debugw(ctx, "Processed downstream GEM port attributes for final list", log.Fields{"count": len(dsGemPortAttributeList)})
1551 return dsGemPortAttributeList
1552}