blob: 1bfb964f9eb96260c8797273286b6afb746181db [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 (
npujar5bf737f2020-01-16 19:35:25 +053020 "context"
Scott Baker2c1c4822019-10-16 11:02:41 -070021 "errors"
22 "fmt"
Girish Gowdra9447baf2019-11-05 16:42:37 +053023 "regexp"
Scott Baker2c1c4822019-10-16 11:02:41 -070024 "strconv"
pnalmas23a77d02025-01-15 11:52:48 +053025 "strings"
Gamze Abakadfdd8f82020-05-04 08:39:50 +000026 "sync"
Neha Sharma130ac6d2020-04-08 08:46:32 +000027 "time"
Scott Baker2c1c4822019-10-16 11:02:41 -070028
khenaidoo26721882021-08-11 17:42:52 -040029 "github.com/opencord/voltha-lib-go/v7/pkg/db"
30 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
31 "github.com/opencord/voltha-lib-go/v7/pkg/log"
khenaidoo26721882021-08-11 17:42:52 -040032 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
Abhay Kumar062cda52025-12-23 06:49:37 +000033 "google.golang.org/protobuf/encoding/protojson"
34 "google.golang.org/protobuf/proto"
Scott Baker2c1c4822019-10-16 11:02:41 -070035)
36
37// Interface to pon resource manager APIs
38type iPonResourceMgr interface {
Girish Gowdra248971a2021-06-01 15:14:15 -070039 GetResourceID(ctx context.Context, intfID uint32, resourceType string, numIDs uint32) ([]uint32, error)
40 FreeResourceID(ctx context.Context, intfID uint32, resourceType string, ReleaseContent []uint32) error
Scott Baker2c1c4822019-10-16 11:02:41 -070041 GetResourceTypeAllocID() string
42 GetResourceTypeGemPortID() string
Matteo Scandolob85b2f02021-03-18 14:44:41 -070043 GetResourceTypeOnuID() string
Scott Baker2c1c4822019-10-16 11:02:41 -070044 GetTechnology() string
45}
46
Scott Baker2c1c4822019-10-16 11:02:41 -070047type SchedulingPolicy int32
48
49const (
50 SchedulingPolicy_WRR SchedulingPolicy = 0
51 SchedulingPolicy_StrictPriority SchedulingPolicy = 1
52 SchedulingPolicy_Hybrid SchedulingPolicy = 2
53)
54
Scott Baker2c1c4822019-10-16 11:02:41 -070055type AdditionalBW int32
56
57const (
58 AdditionalBW_AdditionalBW_None AdditionalBW = 0
59 AdditionalBW_AdditionalBW_NA AdditionalBW = 1
60 AdditionalBW_AdditionalBW_BestEffort AdditionalBW = 2
61 AdditionalBW_AdditionalBW_Auto AdditionalBW = 3
62)
63
Scott Baker2c1c4822019-10-16 11:02:41 -070064type DiscardPolicy int32
65
66const (
67 DiscardPolicy_TailDrop DiscardPolicy = 0
68 DiscardPolicy_WTailDrop DiscardPolicy = 1
69 DiscardPolicy_Red DiscardPolicy = 2
70 DiscardPolicy_WRed DiscardPolicy = 3
71)
72
Girish Gowdra9447baf2019-11-05 16:42:37 +053073// Required uniPortName format
Girish Gowdra248971a2021-06-01 15:14:15 -070074var uniPortNameFormatRegexp = regexp.MustCompile(`^olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
Girish Gowdra9447baf2019-11-05 16:42:37 +053075
Scott Baker2c1c4822019-10-16 11:02:41 -070076// instance control defaults
77const (
78 defaultOnuInstance = "multi-instance"
79 defaultUniInstance = "single-instance"
Scott Baker2c1c4822019-10-16 11:02:41 -070080 defaultGemPayloadSize = "auto"
81)
82
Scott Baker2c1c4822019-10-16 11:02:41 -070083// default discard config constants
84const (
85 defaultMinThreshold = 0
86 defaultMaxThreshold = 0
87 defaultMaxProbability = 0
88)
89
Scott Baker2c1c4822019-10-16 11:02:41 -070090// default scheduler contants
91const (
Girish Gowdra248971a2021-06-01 15:14:15 -070092 defaultPriority = 0
93 defaultWeight = 0
Scott Baker2c1c4822019-10-16 11:02:41 -070094)
95
Scott Baker2c1c4822019-10-16 11:02:41 -070096// default GEM attribute constants
97const (
Esin Karaman8aa75a72019-12-20 13:11:59 +000098 defaultAESEncryption = "True"
99 defaultPriorityQueue = 0
100 defaultQueueWeight = 0
101 defaultMaxQueueSize = "auto"
Esin Karaman8aa75a72019-12-20 13:11:59 +0000102 defaultIsMulticast = "False"
103 defaultAccessControlList = "224.0.0.0-239.255.255.255"
104 defaultMcastGemID = 4069
Scott Baker2c1c4822019-10-16 11:02:41 -0700105)
106
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700107// Default EPON constants
108const (
109 defaultPakageType = "B"
110)
111const (
112 defaultTrafficType = "BE"
113 defaultUnsolicitedGrantSize = 0
114 defaultNominalInterval = 0
115 defaultToleratedPollJitter = 0
116 defaultRequestTransmissionPolicy = 0
117 defaultNumQueueSet = 2
118)
119const (
120 defaultQThreshold1 = 5500
121 defaultQThreshold2 = 0
122 defaultQThreshold3 = 0
123 defaultQThreshold4 = 0
124 defaultQThreshold5 = 0
125 defaultQThreshold6 = 0
126 defaultQThreshold7 = 0
127)
128
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700129const (
Andrea Campanella904fe322020-06-26 18:56:51 +0200130 xgspon = "XGS-PON"
Girish Gowdra248971a2021-06-01 15:14:15 -0700131 xgpon = "XGPON"
Andrea Campanella904fe322020-06-26 18:56:51 +0200132 gpon = "GPON"
133 epon = "EPON"
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700134)
135
Girish Gowdra248971a2021-06-01 15:14:15 -0700136const (
137 MaxUniPortPerOnu = 16 // TODO: Adapter uses its own constant for MaxUniPort. How to synchronize this and have a single source of truth?
138)
139
140type TechProfileMgr struct {
141 config *TechProfileFlags
142 resourceMgr iPonResourceMgr
143 OnuIDMgmtLock sync.RWMutex
144 GemPortIDMgmtLock sync.RWMutex
145 AllocIDMgmtLock sync.RWMutex
146 tpInstanceMap map[string]*tp_pb.TechProfileInstance // Map of tp path to tp instance
147 tpInstanceMapLock sync.RWMutex
148 eponTpInstanceMap map[string]*tp_pb.EponTechProfileInstance // Map of tp path to epon tp instance
149 epontpInstanceMapLock sync.RWMutex
150 tpMap map[uint32]*tp_pb.TechProfile // Map of tp id to tp
151 tpMapLock sync.RWMutex
152 eponTpMap map[uint32]*tp_pb.EponTechProfile // map of tp id to epon tp
153 eponTpMapLock sync.RWMutex
154}
155
Matteo Scandolof34d9082020-11-24 13:56:34 -0800156func (t *TechProfileMgr) SetKVClient(ctx context.Context, pathPrefix string) *db.Backend {
Neha Sharma94f16a92020-06-26 04:17:55 +0000157 kvClient, err := newKVClient(ctx, t.config.KVStoreType, t.config.KVStoreAddress, t.config.KVStoreTimeout)
Scott Baker2c1c4822019-10-16 11:02:41 -0700158 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000159 logger.Errorw(ctx, "failed-to-create-kv-client",
Scott Baker2c1c4822019-10-16 11:02:41 -0700160 log.Fields{
Neha Sharmadd9af392020-04-28 09:03:57 +0000161 "type": t.config.KVStoreType, "address": t.config.KVStoreAddress,
Matteo Scandolof34d9082020-11-24 13:56:34 -0800162 "timeout": t.config.KVStoreTimeout, "prefix": pathPrefix,
Scott Baker2c1c4822019-10-16 11:02:41 -0700163 "error": err.Error(),
164 })
165 return nil
166 }
sbarbari1e3e29c2019-11-05 10:06:50 -0500167 return &db.Backend{
Scott Baker2c1c4822019-10-16 11:02:41 -0700168 Client: kvClient,
169 StoreType: t.config.KVStoreType,
Neha Sharmadd9af392020-04-28 09:03:57 +0000170 Address: t.config.KVStoreAddress,
Scott Baker2c1c4822019-10-16 11:02:41 -0700171 Timeout: t.config.KVStoreTimeout,
Matteo Scandolof34d9082020-11-24 13:56:34 -0800172 PathPrefix: pathPrefix}
Scott Baker2c1c4822019-10-16 11:02:41 -0700173
174 /* TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700175 issue between kv store and backend , core is not calling NewBackend directly
Girish Gowdra248971a2021-06-01 15:14:15 -0700176 kv := model.NewBackend(t.config.kvStoreType, t.config.KVStoreHost, t.config.KVStorePort,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700177 t.config.KVStoreTimeout, kvStoreTechProfilePathPrefix)
Scott Baker2c1c4822019-10-16 11:02:41 -0700178 */
179}
180
Holger Hildebrandt40bd2672023-02-10 08:14:26 +0000181func (t *TechProfileMgr) CloseKVClient(ctx context.Context) {
182 if t.config.KVBackend != nil {
183 t.config.KVBackend.Client.Close(ctx)
184 t.config.KVBackend = nil
185 }
186 if t.config.DefaultTpKVBackend != nil {
187 t.config.DefaultTpKVBackend.Client.Close(ctx)
188 t.config.DefaultTpKVBackend = nil
189 }
190 if t.config.ResourceInstanceKVBacked != nil {
191 t.config.ResourceInstanceKVBacked.Client.Close(ctx)
192 t.config.ResourceInstanceKVBacked = nil
193 }
194}
195
pnalmas23a77d02025-01-15 11:52:48 +0530196func 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 -0700197 var techprofileObj TechProfileMgr
pnalmas23a77d02025-01-15 11:52:48 +0530198 logger.Debug(ctx, "initializing-techprofile-mananger ", log.Fields{"IntId": IntfId, "device-id": deviceId})
Girish Gowdra248971a2021-06-01 15:14:15 -0700199 techprofileObj.config = NewTechProfileFlags(kvStoreType, kvStoreAddress, basePathKvStore)
Matteo Scandolof34d9082020-11-24 13:56:34 -0800200 techprofileObj.config.KVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.TPKVPathPrefix)
201 techprofileObj.config.DefaultTpKVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.defaultTpKvPathPrefix)
Scott Baker2c1c4822019-10-16 11:02:41 -0700202 if techprofileObj.config.KVBackend == nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700203 logger.Error(ctx, "failed-to-initialize-backend")
204 return nil, errors.New("kv-backend-init-failed")
205 }
206 techprofileObj.config.ResourceInstanceKVBacked = techprofileObj.SetKVClient(ctx, techprofileObj.config.ResourceInstanceKVPathPrefix)
207 if techprofileObj.config.ResourceInstanceKVBacked == nil {
208 logger.Error(ctx, "failed-to-initialize-resource-instance-kv-backend")
209 return nil, errors.New("resource-instance-kv-backend-init-failed")
Scott Baker2c1c4822019-10-16 11:02:41 -0700210 }
211 techprofileObj.resourceMgr = resourceMgr
Girish Gowdra248971a2021-06-01 15:14:15 -0700212 techprofileObj.tpInstanceMap = make(map[string]*tp_pb.TechProfileInstance)
213 techprofileObj.eponTpInstanceMap = make(map[string]*tp_pb.EponTechProfileInstance)
214 techprofileObj.tpMap = make(map[uint32]*tp_pb.TechProfile)
215 techprofileObj.eponTpMap = make(map[uint32]*tp_pb.EponTechProfile)
216 logger.Debug(ctx, "reconcile-tp-instance-cache-start")
pnalmas23a77d02025-01-15 11:52:48 +0530217 if err := techprofileObj.reconcileTpInstancesToCache(ctx, IntfId, deviceId); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700218 logger.Errorw(ctx, "failed-to-reconcile-tp-instances", log.Fields{"err": err})
219 return nil, err
220 }
221 logger.Debug(ctx, "reconcile-tp-instance-cache-end")
222 logger.Debug(ctx, "initializing-tech-profile-manager-object-success")
Scott Baker2c1c4822019-10-16 11:02:41 -0700223 return &techprofileObj, nil
224}
225
Girish Gowdra248971a2021-06-01 15:14:15 -0700226// GetTechProfileInstanceKey returns the tp instance key that is used to reference TP Instance Map
227func (t *TechProfileMgr) GetTechProfileInstanceKey(ctx context.Context, tpID uint32, uniPortName string) string {
228 logger.Debugw(ctx, "get-tp-instance-kv-key", log.Fields{
Matteo Scandolo4fca23a2020-04-07 07:55:08 -0700229 "uniPortName": uniPortName,
Girish Gowdra248971a2021-06-01 15:14:15 -0700230 "tpId": tpID,
Matteo Scandolo4fca23a2020-04-07 07:55:08 -0700231 })
Girish Gowdra248971a2021-06-01 15:14:15 -0700232 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
233 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
234 logger.Warnw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
235 }
236 // The key path prefix (like service/voltha/technology_profiles or service/voltha_voltha/technology_profiles)
237 // is expected to be attached by the components that use this path as part of the KVBackend configuration.
238 resourceInstanceKvPathSuffix := "%s/%d/%s" // <technology>/<tpID>/<uni-port-name>
239 // <uni-port-name> must be of the format pon-{\d+}/onu-{\d+}/uni-{\d+}
240 return fmt.Sprintf(resourceInstanceKvPathSuffix, t.resourceMgr.GetTechnology(), tpID, uniPortName)
Scott Baker2c1c4822019-10-16 11:02:41 -0700241}
242
Girish Gowdra248971a2021-06-01 15:14:15 -0700243// GetTPInstance gets TP instance from cache if found
244func (t *TechProfileMgr) GetTPInstance(ctx context.Context, path string) (interface{}, error) {
245 tech := t.resourceMgr.GetTechnology()
246 switch tech {
247 case xgspon, xgpon, gpon:
248 t.tpInstanceMapLock.RLock()
249 defer t.tpInstanceMapLock.RUnlock()
250 tpInst, ok := t.tpInstanceMap[path]
251 if !ok {
252 return nil, fmt.Errorf("tp-instance-not-found-tp-path-%v", path)
253 }
254 return tpInst, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700255 case epon:
Girish Gowdra248971a2021-06-01 15:14:15 -0700256 t.epontpInstanceMapLock.RLock()
257 defer t.epontpInstanceMapLock.RUnlock()
258 tpInst, ok := t.eponTpInstanceMap[path]
259 if !ok {
260 return nil, fmt.Errorf("tp-instance-not-found-tp-path-%v", path)
261 }
262 return tpInst, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700263 default:
Girish Gowdra248971a2021-06-01 15:14:15 -0700264 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech})
265 return nil, fmt.Errorf("unknown-tech-%s-tp-path-%v", tech, path)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700266 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700267}
268
Girish Gowdra248971a2021-06-01 15:14:15 -0700269// CreateTechProfileInstance creates a new TP instance.
270func (t *TechProfileMgr) CreateTechProfileInstance(ctx context.Context, tpID uint32, uniPortName string, intfID uint32) (interface{}, error) {
271 var tpInstance *tp_pb.TechProfileInstance
272 var eponTpInstance *tp_pb.EponTechProfileInstance
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700273
Girish Gowdra248971a2021-06-01 15:14:15 -0700274 logger.Infow(ctx, "creating-tp-instance", log.Fields{"tpID": tpID, "uni": uniPortName, "intId": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700275
Girish Gowdra248971a2021-06-01 15:14:15 -0700276 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
277 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000278 logger.Errorw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
Girish Gowdra248971a2021-06-01 15:14:15 -0700279 return nil, fmt.Errorf("uni-port-name-not-confirming-to-format-%s", uniPortName)
Girish Gowdra9447baf2019-11-05 16:42:37 +0530280 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700281 tpInstancePathSuffix := t.GetTechProfileInstanceKey(ctx, tpID, uniPortName)
282
283 if t.resourceMgr.GetTechnology() == epon {
284 tp := t.getEponTPFromKVStore(ctx, tpID)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700285 if tp != nil {
Abhay Kumar062cda52025-12-23 06:49:37 +0000286 if err := t.validateInstanceControlAttr(ctx, tp.InstanceControl); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700287 logger.Error(ctx, "invalid-instance-ctrl-attr-using-default-tp")
Girish Kumar950f21e2020-08-19 17:42:29 +0000288 tp = t.getDefaultEponProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700289 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700290 logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpID": tpID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700291 }
292 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000293 logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
Girish Kumar950f21e2020-08-19 17:42:29 +0000294 tp = t.getDefaultEponProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700295 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700296 // Store TP in cache
297 t.eponTpMapLock.Lock()
298 t.eponTpMap[tpID] = tp
299 t.eponTpMapLock.Unlock()
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700300
Girish Gowdra248971a2021-06-01 15:14:15 -0700301 if eponTpInstance = t.allocateEponTPInstance(ctx, uniPortName, tp, intfID, tpInstancePathSuffix); eponTpInstance == nil {
302 logger.Error(ctx, "tp-instance-allocation-failed")
303 return nil, errors.New("tp-instance-allocation-failed")
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700304 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700305 t.epontpInstanceMapLock.Lock()
306 t.eponTpInstanceMap[tpInstancePathSuffix] = eponTpInstance
307 t.epontpInstanceMapLock.Unlock()
308 resInst := tp_pb.ResourceInstance{
309 TpId: tpID,
310 ProfileType: eponTpInstance.ProfileType,
311 SubscriberIdentifier: eponTpInstance.SubscriberIdentifier,
312 AllocId: eponTpInstance.AllocId,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700313 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700314 for _, usQAttr := range eponTpInstance.UpstreamQueueAttributeList {
315 resInst.GemportIds = append(resInst.GemportIds, usQAttr.GemportId)
316 }
317
318 logger.Infow(ctx, "epon-tp-instance-created-successfully",
319 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
Abhay Kumar062cda52025-12-23 06:49:37 +0000320 if err := t.addResourceInstanceToKVStore(ctx, tpID, uniPortName, &resInst); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700321 logger.Errorw(ctx, "failed-to-update-resource-instance-to-kv-store--freeing-up-resources", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
322 allocIDs := make([]uint32, 0)
323 allocIDs = append(allocIDs, resInst.AllocId)
324 errList := make([]error, 0)
325 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), allocIDs))
326 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), resInst.GemportIds))
327 if len(errList) > 0 {
328 logger.Errorw(ctx, "failed-to-free-up-resources-on-kv-store--system-behavior-has-become-erratic", log.Fields{"tpID": tpID, "uniPortName": uniPortName, "errList": errList})
329 }
330 return nil, err
331 }
332 return eponTpInstance, nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700333 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700334 tp := t.getTPFromKVStore(ctx, tpID)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700335 if tp != nil {
Abhay Kumar062cda52025-12-23 06:49:37 +0000336 if err := t.validateInstanceControlAttr(ctx, tp.InstanceControl); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000337 logger.Error(ctx, "invalid-instance-ctrl-attr--using-default-tp")
338 tp = t.getDefaultTechProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700339 } else {
Girish Gowdra248971a2021-06-01 15:14:15 -0700340 logger.Infow(ctx, "using-specified-tp-from-kv-store", log.Fields{"tpID": tpID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700341 }
342 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000343 logger.Info(ctx, "tp-not-found-on-kv--creating-default-tp")
344 tp = t.getDefaultTechProfile(ctx)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700345 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700346 // Store TP in cache
347 t.tpMapLock.Lock()
348 t.tpMap[tpID] = tp
349 t.tpMapLock.Unlock()
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700350
Girish Gowdra248971a2021-06-01 15:14:15 -0700351 if tpInstance = t.allocateTPInstance(ctx, uniPortName, tp, intfID, tpInstancePathSuffix); tpInstance == nil {
352 logger.Error(ctx, "tp-instance-allocation-failed")
353 return nil, errors.New("tp-instance-allocation-failed")
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700354 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700355 t.tpInstanceMapLock.Lock()
356 t.tpInstanceMap[tpInstancePathSuffix] = tpInstance
357 t.tpInstanceMapLock.Unlock()
358
359 resInst := tp_pb.ResourceInstance{
360 TpId: tpID,
361 ProfileType: tpInstance.ProfileType,
362 SubscriberIdentifier: tpInstance.SubscriberIdentifier,
363 AllocId: tpInstance.UsScheduler.AllocId,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700364 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700365 for _, usQAttr := range tpInstance.UpstreamGemPortAttributeList {
366 resInst.GemportIds = append(resInst.GemportIds, usQAttr.GemportId)
367 }
368
369 logger.Infow(ctx, "tp-instance-created-successfully",
370 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
Abhay Kumar062cda52025-12-23 06:49:37 +0000371 if err := t.addResourceInstanceToKVStore(ctx, tpID, uniPortName, &resInst); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700372 logger.Errorw(ctx, "failed-to-update-resource-instance-to-kv-store--freeing-up-resources", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
373 allocIDs := make([]uint32, 0)
374 allocIDs = append(allocIDs, resInst.AllocId)
375 errList := make([]error, 0)
376 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), allocIDs))
377 errList = append(errList, t.FreeResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), resInst.GemportIds))
378 if len(errList) > 0 {
379 logger.Fatalw(ctx, "failed-to-free-up-resources-on-kv-store--system-behavior-has-become-erratic", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
380 }
381 return nil, err
382 }
383
384 logger.Infow(ctx, "resource-instance-added-to-kv-store-successfully",
385 log.Fields{"tpID": tpID, "uni": uniPortName, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700386 return tpInstance, nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700387 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700388}
389
Girish Gowdra248971a2021-06-01 15:14:15 -0700390// DeleteTechProfileInstance deletes the TP instance from the local cache as well as deletes the corresponding
391// resource instance from the KV store.
392func (t *TechProfileMgr) DeleteTechProfileInstance(ctx context.Context, tpID uint32, uniPortName string) error {
393 // Make sure the uniPortName is as per format olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
394 if !uniPortNameFormatRegexp.Match([]byte(uniPortName)) {
395 logger.Errorw(ctx, "uni-port-name-not-confirming-to-format", log.Fields{"uniPortName": uniPortName})
396 return fmt.Errorf("uni-port-name-not-confirming-to-format--%s", uniPortName)
397 }
398 path := t.GetTechProfileInstanceKey(ctx, tpID, uniPortName)
399 logger.Infow(ctx, "delete-tp-instance-from-cache", log.Fields{"key": path})
400 t.tpInstanceMapLock.Lock()
401 delete(t.tpInstanceMap, path)
402 t.tpInstanceMapLock.Unlock()
403 if err := t.removeResourceInstanceFromKVStore(ctx, tpID, uniPortName); err != nil {
404 return err
405 }
406 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700407}
408
Girish Gowdra248971a2021-06-01 15:14:15 -0700409func (t *TechProfileMgr) GetMulticastTrafficQueues(ctx context.Context, tp *tp_pb.TechProfileInstance) []*tp_pb.TrafficQueue {
410 var encryp bool
411 NumGemPorts := len(tp.DownstreamGemPortAttributeList)
412 mcastTrafficQueues := make([]*tp_pb.TrafficQueue, 0)
413 for Count := 0; Count < NumGemPorts; Count++ {
414 if !isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
415 continue
416 }
417 if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
418 encryp = true
419 } else {
420 encryp = false
421 }
422 mcastTrafficQueues = append(mcastTrafficQueues, &tp_pb.TrafficQueue{
423 Direction: tp_pb.Direction_DOWNSTREAM,
424 GemportId: tp.DownstreamGemPortAttributeList[Count].MulticastGemId,
425 PbitMap: tp.DownstreamGemPortAttributeList[Count].PbitMap,
426 AesEncryption: encryp,
427 SchedPolicy: tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy,
428 Priority: tp.DownstreamGemPortAttributeList[Count].PriorityQ,
429 Weight: tp.DownstreamGemPortAttributeList[Count].Weight,
430 DiscardPolicy: tp.DownstreamGemPortAttributeList[Count].DiscardPolicy,
431 })
432 }
433 logger.Debugw(ctx, "Downstream Multicast Traffic queue list ", log.Fields{"queuelist": mcastTrafficQueues})
434 return mcastTrafficQueues
435}
436
437func (t *TechProfileMgr) GetGemportForPbit(ctx context.Context, tp interface{}, dir tp_pb.Direction, pbit uint32) interface{} {
438 /*
439 Function to get the Gemport mapped to a pbit.
440 */
441 switch tp := tp.(type) {
442 case *tp_pb.TechProfileInstance:
443 if dir == tp_pb.Direction_UPSTREAM {
444 // upstream GEM ports
445 numGemPorts := len(tp.UpstreamGemPortAttributeList)
446 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
447 lenOfPbitMap := len(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap)
448 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
449 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
450 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
451 if p, err := strconv.Atoi(string(tp.UpstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
452 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
453 logger.Debugw(ctx, "Found-US-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.UpstreamGemPortAttributeList[gemCnt].GemportId})
454 return tp.UpstreamGemPortAttributeList[gemCnt]
455 }
456 }
457 }
458 }
459 } else if dir == tp_pb.Direction_DOWNSTREAM {
460 //downstream GEM ports
461 numGemPorts := len(tp.DownstreamGemPortAttributeList)
462 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
463 lenOfPbitMap := len(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap)
464 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
465 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
466 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
467 if p, err := strconv.Atoi(string(tp.DownstreamGemPortAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
468 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
469 logger.Debugw(ctx, "Found-DS-GEMport-for-Pcp", log.Fields{"pbit": pbit, "GEMport": tp.DownstreamGemPortAttributeList[gemCnt].GemportId})
470 return tp.DownstreamGemPortAttributeList[gemCnt]
471 }
472 }
473 }
474 }
475 }
476 logger.Errorw(ctx, "No-GemportId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
khenaidooa5feb8e2021-10-19 17:29:22 -0400477 case *tp_pb.EponTechProfileInstance:
Girish Gowdra248971a2021-06-01 15:14:15 -0700478 if dir == tp_pb.Direction_UPSTREAM {
479 // upstream GEM ports
480 numGemPorts := len(tp.UpstreamQueueAttributeList)
481 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
482 lenOfPbitMap := len(tp.UpstreamQueueAttributeList[gemCnt].PbitMap)
483 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
484 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
485 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
486 if p, err := strconv.Atoi(string(tp.UpstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
487 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
488 logger.Debugw(ctx, "Found-US-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.UpstreamQueueAttributeList[gemCnt].GemportId})
489 return tp.UpstreamQueueAttributeList[gemCnt]
490 }
491 }
492 }
493 }
494 } else if dir == tp_pb.Direction_DOWNSTREAM {
495 //downstream GEM ports
496 numGemPorts := len(tp.DownstreamQueueAttributeList)
497 for gemCnt := 0; gemCnt < numGemPorts; gemCnt++ {
498 lenOfPbitMap := len(tp.DownstreamQueueAttributeList[gemCnt].PbitMap)
499 for pbitMapIdx := 2; pbitMapIdx < lenOfPbitMap; pbitMapIdx++ {
500 // Given a sample pbit map string "0b00000001", lenOfPbitMap is 10
501 // "lenOfPbitMap - pbitMapIdx + 1" will give pbit-i th value from LSB position in the pbit map string
502 if p, err := strconv.Atoi(string(tp.DownstreamQueueAttributeList[gemCnt].PbitMap[lenOfPbitMap-pbitMapIdx+1])); err == nil {
503 if uint32(pbitMapIdx-2) == pbit && p == 1 { // Check this p-bit is set
504 logger.Debugw(ctx, "Found-DS-Queue-for-Pcp", log.Fields{"pbit": pbit, "Queue": tp.DownstreamQueueAttributeList[gemCnt].GemportId})
505 return tp.DownstreamQueueAttributeList[gemCnt]
506 }
507 }
508 }
509 }
510 }
511 logger.Errorw(ctx, "No-QueueId-Found-For-Pcp", log.Fields{"pcpVlan": pbit})
512 default:
513 logger.Errorw(ctx, "unknown-tech", log.Fields{"tp": tp})
514 }
515 return nil
516}
517
518// FindAllTpInstances returns all TechProfile instances for a given TechProfile table-id, pon interface ID and onu ID.
519func (t *TechProfileMgr) FindAllTpInstances(ctx context.Context, oltDeviceID string, tpID uint32, intfID uint32, onuID uint32) interface{} {
520 onuTpInstancePathSuffix := fmt.Sprintf("%s/%d/olt-{%s}/pon-{%d}/onu-{%d}", t.resourceMgr.GetTechnology(), tpID, oltDeviceID, intfID, onuID)
521 tech := t.resourceMgr.GetTechnology()
522 if tech == xgspon || tech == xgpon || tech == gpon {
523 t.tpInstanceMapLock.RLock()
524 defer t.tpInstanceMapLock.RUnlock()
Abhay Kumar062cda52025-12-23 06:49:37 +0000525 tpInstancesTech := make([]*tp_pb.TechProfileInstance, 0)
Girish Gowdra248971a2021-06-01 15:14:15 -0700526 for i := 0; i < MaxUniPortPerOnu; i++ {
527 key := onuTpInstancePathSuffix + fmt.Sprintf("/uni-{%d}", i)
528 if tpInst, ok := t.tpInstanceMap[key]; ok {
Abhay Kumar062cda52025-12-23 06:49:37 +0000529 tpInstancesTech = append(tpInstancesTech, tpInst)
Girish Gowdra248971a2021-06-01 15:14:15 -0700530 }
531 }
532 return tpInstancesTech
533 } else if tech == epon {
534 t.epontpInstanceMapLock.RLock()
535 defer t.epontpInstanceMapLock.RUnlock()
Abhay Kumar062cda52025-12-23 06:49:37 +0000536 tpInstancesTech := make([]*tp_pb.EponTechProfileInstance, 0)
Girish Gowdra248971a2021-06-01 15:14:15 -0700537 for i := 0; i < MaxUniPortPerOnu; i++ {
538 key := onuTpInstancePathSuffix + fmt.Sprintf("/uni-{%d}", i)
539 if tpInst, ok := t.eponTpInstanceMap[key]; ok {
Abhay Kumar062cda52025-12-23 06:49:37 +0000540 tpInstancesTech = append(tpInstancesTech, tpInst)
Girish Gowdra248971a2021-06-01 15:14:15 -0700541 }
542 }
543 return tpInstancesTech
544 } else {
545 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech, "tpID": tpID, "onuID": onuID, "intfID": intfID})
546 }
547 return nil
548}
549
550func (t *TechProfileMgr) GetResourceID(ctx context.Context, intfID uint32, resourceType string, numIDs uint32) ([]uint32, error) {
551 logger.Debugw(ctx, "getting-resource-id", log.Fields{
552 "intf-id": intfID,
553 "resource-type": resourceType,
554 "num": numIDs,
555 })
556 var err error
557 var ids []uint32
558 switch resourceType {
559 case t.resourceMgr.GetResourceTypeAllocID():
560 t.AllocIDMgmtLock.Lock()
561 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
562 t.AllocIDMgmtLock.Unlock()
563 case t.resourceMgr.GetResourceTypeGemPortID():
564 t.GemPortIDMgmtLock.Lock()
565 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
566 t.GemPortIDMgmtLock.Unlock()
567 case t.resourceMgr.GetResourceTypeOnuID():
568 t.OnuIDMgmtLock.Lock()
569 ids, err = t.resourceMgr.GetResourceID(ctx, intfID, resourceType, numIDs)
570 t.OnuIDMgmtLock.Unlock()
571 default:
572 return nil, fmt.Errorf("resourceType %s not supported", resourceType)
573 }
574 if err != nil {
575 return nil, err
576 }
577 return ids, nil
578}
579
580func (t *TechProfileMgr) FreeResourceID(ctx context.Context, intfID uint32, resourceType string, ReleaseContent []uint32) error {
581 logger.Debugw(ctx, "freeing-resource-id", log.Fields{
582 "intf-id": intfID,
583 "resource-type": resourceType,
584 "release-content": ReleaseContent,
585 })
586 var err error
587 switch resourceType {
588 case t.resourceMgr.GetResourceTypeAllocID():
589 t.AllocIDMgmtLock.Lock()
590 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
591 t.AllocIDMgmtLock.Unlock()
592 case t.resourceMgr.GetResourceTypeGemPortID():
593 t.GemPortIDMgmtLock.Lock()
594 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
595 t.GemPortIDMgmtLock.Unlock()
596 case t.resourceMgr.GetResourceTypeOnuID():
597 t.OnuIDMgmtLock.Lock()
598 err = t.resourceMgr.FreeResourceID(ctx, intfID, resourceType, ReleaseContent)
599 t.OnuIDMgmtLock.Unlock()
600 default:
601 return fmt.Errorf("resourceType %s not supported", resourceType)
602 }
603 if err != nil {
604 return err
605 }
606 return nil
607}
608
609func (t *TechProfileMgr) GetUsScheduler(tpInstance *tp_pb.TechProfileInstance) *tp_pb.SchedulerConfig {
610 return &tp_pb.SchedulerConfig{
611 Direction: tpInstance.UsScheduler.Direction,
612 AdditionalBw: tpInstance.UsScheduler.AdditionalBw,
613 Priority: tpInstance.UsScheduler.Priority,
614 Weight: tpInstance.UsScheduler.Weight,
615 SchedPolicy: tpInstance.UsScheduler.QSchedPolicy}
616}
617
618func (t *TechProfileMgr) GetDsScheduler(tpInstance *tp_pb.TechProfileInstance) *tp_pb.SchedulerConfig {
619 return &tp_pb.SchedulerConfig{
620 Direction: tpInstance.DsScheduler.Direction,
621 AdditionalBw: tpInstance.DsScheduler.AdditionalBw,
622 Priority: tpInstance.DsScheduler.Priority,
623 Weight: tpInstance.DsScheduler.Weight,
624 SchedPolicy: tpInstance.DsScheduler.QSchedPolicy}
625}
626
627func (t *TechProfileMgr) GetTrafficScheduler(tpInstance *tp_pb.TechProfileInstance, SchedCfg *tp_pb.SchedulerConfig,
628 ShapingCfg *tp_pb.TrafficShapingInfo) *tp_pb.TrafficScheduler {
629
630 tSched := &tp_pb.TrafficScheduler{
631 Direction: SchedCfg.Direction,
632 AllocId: tpInstance.UsScheduler.AllocId,
633 TrafficShapingInfo: ShapingCfg,
634 Scheduler: SchedCfg}
635
636 return tSched
637}
638
639func (t *TechProfileMgr) GetTrafficQueues(ctx context.Context, tp *tp_pb.TechProfileInstance, direction tp_pb.Direction) ([]*tp_pb.TrafficQueue, error) {
640
641 var encryp bool
642 if direction == tp_pb.Direction_UPSTREAM {
643 // upstream GEM ports
644 NumGemPorts := len(tp.UpstreamGemPortAttributeList)
645 GemPorts := make([]*tp_pb.TrafficQueue, 0)
646 for Count := 0; Count < NumGemPorts; Count++ {
647 if tp.UpstreamGemPortAttributeList[Count].AesEncryption == "True" {
648 encryp = true
649 } else {
650 encryp = false
651 }
652
653 GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
654 Direction: direction,
655 GemportId: tp.UpstreamGemPortAttributeList[Count].GemportId,
656 PbitMap: tp.UpstreamGemPortAttributeList[Count].PbitMap,
657 AesEncryption: encryp,
658 SchedPolicy: tp.UpstreamGemPortAttributeList[Count].SchedulingPolicy,
659 Priority: tp.UpstreamGemPortAttributeList[Count].PriorityQ,
660 Weight: tp.UpstreamGemPortAttributeList[Count].Weight,
661 DiscardPolicy: tp.UpstreamGemPortAttributeList[Count].DiscardPolicy,
662 })
663 }
664 logger.Debugw(ctx, "Upstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
665 return GemPorts, nil
666 } else if direction == tp_pb.Direction_DOWNSTREAM {
667 //downstream GEM ports
668 NumGemPorts := len(tp.DownstreamGemPortAttributeList)
669 GemPorts := make([]*tp_pb.TrafficQueue, 0)
670 for Count := 0; Count < NumGemPorts; Count++ {
671 if isMulticastGem(tp.DownstreamGemPortAttributeList[Count].IsMulticast) {
672 //do not take multicast GEM ports. They are handled separately.
673 continue
674 }
675 if tp.DownstreamGemPortAttributeList[Count].AesEncryption == "True" {
676 encryp = true
677 } else {
678 encryp = false
679 }
680
681 GemPorts = append(GemPorts, &tp_pb.TrafficQueue{
682 Direction: direction,
683 GemportId: tp.DownstreamGemPortAttributeList[Count].GemportId,
684 PbitMap: tp.DownstreamGemPortAttributeList[Count].PbitMap,
685 AesEncryption: encryp,
686 SchedPolicy: tp.DownstreamGemPortAttributeList[Count].SchedulingPolicy,
687 Priority: tp.DownstreamGemPortAttributeList[Count].PriorityQ,
688 Weight: tp.DownstreamGemPortAttributeList[Count].Weight,
689 DiscardPolicy: tp.DownstreamGemPortAttributeList[Count].DiscardPolicy,
690 })
691 }
692 logger.Debugw(ctx, "Downstream Traffic queue list ", log.Fields{"queuelist": GemPorts})
693 return GemPorts, nil
694 }
695
696 logger.Errorf(ctx, "Unsupported direction %s used for generating Traffic Queue list", direction)
697 return nil, fmt.Errorf("downstream gem port traffic queue creation failed due to unsupported direction %s", direction)
698}
699
Abhay Kumar062cda52025-12-23 06:49:37 +0000700func (t *TechProfileMgr) validateInstanceControlAttr(ctx context.Context, instCtl *tp_pb.InstanceControl) error {
Girish Gowdra9447baf2019-11-05 16:42:37 +0530701 if instCtl.Onu != "single-instance" && instCtl.Onu != "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000702 logger.Errorw(ctx, "invalid-onu-instance-control-attribute", log.Fields{"onu-inst": instCtl.Onu})
Girish Gowdra9447baf2019-11-05 16:42:37 +0530703 return errors.New("invalid-onu-instance-ctl-attr")
704 }
705
706 if instCtl.Uni != "single-instance" && instCtl.Uni != "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000707 logger.Errorw(ctx, "invalid-uni-instance-control-attribute", log.Fields{"uni-inst": instCtl.Uni})
Girish Gowdra9447baf2019-11-05 16:42:37 +0530708 return errors.New("invalid-uni-instance-ctl-attr")
709 }
710
711 if instCtl.Uni == "multi-instance" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000712 logger.Error(ctx, "uni-multi-instance-tp-not-supported")
Girish Gowdra9447baf2019-11-05 16:42:37 +0530713 return errors.New("uni-multi-instance-tp-not-supported")
714 }
715
716 return nil
717}
718
Girish Gowdra248971a2021-06-01 15:14:15 -0700719// allocateTPInstance for GPON, XGPON and XGS-PON technology
720func (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 -0700721
Girish Gowdra248971a2021-06-01 15:14:15 -0700722 var usGemPortAttributeList []*tp_pb.GemPortAttributes
723 var dsGemPortAttributeList []*tp_pb.GemPortAttributes
724 var dsMulticastGemAttributeList []*tp_pb.GemPortAttributes
725 var dsUnicastGemAttributeList []*tp_pb.GemPortAttributes
Scott Baker2c1c4822019-10-16 11:02:41 -0700726 var tcontIDs []uint32
727 var gemPorts []uint32
728 var err error
729
Girish Gowdra248971a2021-06-01 15:14:15 -0700730 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 +0530731
Girish Gowdra248971a2021-06-01 15:14:15 -0700732 if tp.InstanceControl.Onu == "multi-instance" {
733 tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000734 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700735 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530736 return nil
737 }
738 } else { // "single-instance"
Girish Gowdra248971a2021-06-01 15:14:15 -0700739 if tpInst := t.getSingleInstanceTp(ctx, tpInstPathSuffix); tpInst == nil {
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530740 // No "single-instance" tp found on one any uni port for the given TP ID
741 // Allocate a new TcontID or AllocID
Girish Gowdra248971a2021-06-01 15:14:15 -0700742 tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000743 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700744 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530745 return nil
746 }
747 } else {
748 // Use the alloc-id from the existing TpInstance
Girish Gowdra248971a2021-06-01 15:14:15 -0700749 tcontIDs = append(tcontIDs, tpInst.UsScheduler.AllocId)
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530750 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700751 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000752 logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
Girish Gowdra248971a2021-06-01 15:14:15 -0700753 gemPorts, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts)
Gamze Abakadfdd8f82020-05-04 08:39:50 +0000754 if err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -0700755 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 -0700756 return nil
757 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000758 logger.Infow(ctx, "Allocated tconts and GEM ports successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
Scott Baker2c1c4822019-10-16 11:02:41 -0700759 for index := 0; index < int(tp.NumGemPorts); index++ {
760 usGemPortAttributeList = append(usGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700761 &tp_pb.GemPortAttributes{GemportId: gemPorts[index],
762 MaxQSize: tp.UpstreamGemPortAttributeList[index].MaxQSize,
Scott Baker2c1c4822019-10-16 11:02:41 -0700763 PbitMap: tp.UpstreamGemPortAttributeList[index].PbitMap,
764 AesEncryption: tp.UpstreamGemPortAttributeList[index].AesEncryption,
765 SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700766 PriorityQ: tp.UpstreamGemPortAttributeList[index].PriorityQ,
Scott Baker2c1c4822019-10-16 11:02:41 -0700767 Weight: tp.UpstreamGemPortAttributeList[index].Weight,
768 DiscardPolicy: tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
769 DiscardConfig: tp.UpstreamGemPortAttributeList[index].DiscardConfig})
Esin Karaman8aa75a72019-12-20 13:11:59 +0000770 }
771
Neha Sharma94f16a92020-06-26 04:17:55 +0000772 logger.Info(ctx, "length of DownstreamGemPortAttributeList", len(tp.DownstreamGemPortAttributeList))
Esin Karaman8aa75a72019-12-20 13:11:59 +0000773 //put multicast and unicast downstream GEM port attributes in different lists first
Girish Gowdra248971a2021-06-01 15:14:15 -0700774 for index := 0; index < len(tp.DownstreamGemPortAttributeList); index++ {
Esin Karaman8aa75a72019-12-20 13:11:59 +0000775 if isMulticastGem(tp.DownstreamGemPortAttributeList[index].IsMulticast) {
776 dsMulticastGemAttributeList = append(dsMulticastGemAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700777 &tp_pb.GemPortAttributes{
778 MulticastGemId: tp.DownstreamGemPortAttributeList[index].MulticastGemId,
779 MaxQSize: tp.DownstreamGemPortAttributeList[index].MaxQSize,
780 PbitMap: tp.DownstreamGemPortAttributeList[index].PbitMap,
781 AesEncryption: tp.DownstreamGemPortAttributeList[index].AesEncryption,
782 SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
783 PriorityQ: tp.DownstreamGemPortAttributeList[index].PriorityQ,
784 Weight: tp.DownstreamGemPortAttributeList[index].Weight,
785 DiscardPolicy: tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
786 DiscardConfig: tp.DownstreamGemPortAttributeList[index].DiscardConfig,
787 IsMulticast: tp.DownstreamGemPortAttributeList[index].IsMulticast,
788 DynamicAccessControlList: tp.DownstreamGemPortAttributeList[index].DynamicAccessControlList,
789 StaticAccessControlList: tp.DownstreamGemPortAttributeList[index].StaticAccessControlList})
Esin Karaman8aa75a72019-12-20 13:11:59 +0000790 } else {
791 dsUnicastGemAttributeList = append(dsUnicastGemAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700792 &tp_pb.GemPortAttributes{
793 MaxQSize: tp.DownstreamGemPortAttributeList[index].MaxQSize,
Esin Karaman8aa75a72019-12-20 13:11:59 +0000794 PbitMap: tp.DownstreamGemPortAttributeList[index].PbitMap,
795 AesEncryption: tp.DownstreamGemPortAttributeList[index].AesEncryption,
796 SchedulingPolicy: tp.DownstreamGemPortAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700797 PriorityQ: tp.DownstreamGemPortAttributeList[index].PriorityQ,
Esin Karaman8aa75a72019-12-20 13:11:59 +0000798 Weight: tp.DownstreamGemPortAttributeList[index].Weight,
799 DiscardPolicy: tp.DownstreamGemPortAttributeList[index].DiscardPolicy,
800 DiscardConfig: tp.DownstreamGemPortAttributeList[index].DiscardConfig})
801 }
802 }
803 //add unicast downstream GEM ports to dsGemPortAttributeList
Girish Gowdra248971a2021-06-01 15:14:15 -0700804 if dsUnicastGemAttributeList != nil {
805 for index := 0; index < int(tp.NumGemPorts); index++ {
806 dsGemPortAttributeList = append(dsGemPortAttributeList,
807 &tp_pb.GemPortAttributes{GemportId: gemPorts[index],
808 MaxQSize: dsUnicastGemAttributeList[index].MaxQSize,
809 PbitMap: dsUnicastGemAttributeList[index].PbitMap,
810 AesEncryption: dsUnicastGemAttributeList[index].AesEncryption,
811 SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
812 PriorityQ: dsUnicastGemAttributeList[index].PriorityQ,
813 Weight: dsUnicastGemAttributeList[index].Weight,
814 DiscardPolicy: dsUnicastGemAttributeList[index].DiscardPolicy,
815 DiscardConfig: dsUnicastGemAttributeList[index].DiscardConfig})
816 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700817 }
Esin Karaman8aa75a72019-12-20 13:11:59 +0000818 //add multicast GEM ports to dsGemPortAttributeList afterwards
Akash Reddy Kankanala05aff182025-05-06 12:57:32 +0530819 dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList...)
Esin Karaman8aa75a72019-12-20 13:11:59 +0000820
Girish Gowdra248971a2021-06-01 15:14:15 -0700821 return &tp_pb.TechProfileInstance{
Scott Baker2c1c4822019-10-16 11:02:41 -0700822 SubscriberIdentifier: uniPortName,
823 Name: tp.Name,
824 ProfileType: tp.ProfileType,
825 Version: tp.Version,
826 NumGemPorts: tp.NumGemPorts,
Girish Gowdra248971a2021-06-01 15:14:15 -0700827 InstanceControl: tp.InstanceControl,
828 UsScheduler: &tp_pb.SchedulerAttributes{
829 AllocId: tcontIDs[0],
Scott Baker2c1c4822019-10-16 11:02:41 -0700830 Direction: tp.UsScheduler.Direction,
831 AdditionalBw: tp.UsScheduler.AdditionalBw,
832 Priority: tp.UsScheduler.Priority,
833 Weight: tp.UsScheduler.Weight,
834 QSchedPolicy: tp.UsScheduler.QSchedPolicy},
Girish Gowdra248971a2021-06-01 15:14:15 -0700835 DsScheduler: &tp_pb.SchedulerAttributes{
836 AllocId: tcontIDs[0],
Scott Baker2c1c4822019-10-16 11:02:41 -0700837 Direction: tp.DsScheduler.Direction,
838 AdditionalBw: tp.DsScheduler.AdditionalBw,
839 Priority: tp.DsScheduler.Priority,
840 Weight: tp.DsScheduler.Weight,
841 QSchedPolicy: tp.DsScheduler.QSchedPolicy},
842 UpstreamGemPortAttributeList: usGemPortAttributeList,
843 DownstreamGemPortAttributeList: dsGemPortAttributeList}
844}
845
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700846// allocateTPInstance function for EPON
Girish Gowdra248971a2021-06-01 15:14:15 -0700847func (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 -0700848
Girish Gowdra248971a2021-06-01 15:14:15 -0700849 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
850 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700851 var tcontIDs []uint32
852 var gemPorts []uint32
853 var err error
854
Girish Gowdra248971a2021-06-01 15:14:15 -0700855 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 -0700856
Girish Gowdra248971a2021-06-01 15:14:15 -0700857 if tp.InstanceControl.Onu == "multi-instance" {
858 if tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
859 logger.Errorw(ctx, "Error getting alloc id from rsrcrMgr", log.Fields{"err": err, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700860 return nil
861 }
862 } else { // "single-instance"
Girish Gowdra248971a2021-06-01 15:14:15 -0700863 if tpInst := t.getSingleInstanceEponTp(ctx, tpInstPath); tpInst == nil {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700864 // No "single-instance" tp found on one any uni port for the given TP ID
865 // Allocate a new TcontID or AllocID
Girish Gowdra248971a2021-06-01 15:14:15 -0700866 if tcontIDs, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
867 logger.Errorw(ctx, "error-getting-alloc-id-from-resource-mgr", log.Fields{"err": err, "intfID": intfID})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700868 return nil
869 }
870 } else {
871 // Use the alloc-id from the existing TpInstance
Girish Gowdra248971a2021-06-01 15:14:15 -0700872 tcontIDs = append(tcontIDs, tpInst.AllocId)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700873 }
874 }
Girish Kumar950f21e2020-08-19 17:42:29 +0000875 logger.Debugw(ctx, "Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
Girish Gowdra248971a2021-06-01 15:14:15 -0700876 if gemPorts, err = t.GetResourceID(ctx, intfID, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts); err != nil {
877 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 -0700878 return nil
879 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700880 logger.Infow(ctx, "allocated-alloc-id-and-gemport-successfully", log.Fields{"tconts": tcontIDs, "gemports": gemPorts})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700881 for index := 0; index < int(tp.NumGemPorts); index++ {
882 usQueueAttributeList = append(usQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700883 &tp_pb.EPONQueueAttributes{GemportId: gemPorts[index],
884 MaxQSize: tp.UpstreamQueueAttributeList[index].MaxQSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700885 PbitMap: tp.UpstreamQueueAttributeList[index].PbitMap,
886 AesEncryption: tp.UpstreamQueueAttributeList[index].AesEncryption,
887 TrafficType: tp.UpstreamQueueAttributeList[index].TrafficType,
888 UnsolicitedGrantSize: tp.UpstreamQueueAttributeList[index].UnsolicitedGrantSize,
889 NominalInterval: tp.UpstreamQueueAttributeList[index].NominalInterval,
890 ToleratedPollJitter: tp.UpstreamQueueAttributeList[index].ToleratedPollJitter,
891 RequestTransmissionPolicy: tp.UpstreamQueueAttributeList[index].RequestTransmissionPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700892 NumQSets: tp.UpstreamQueueAttributeList[index].NumQSets,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700893 QThresholds: tp.UpstreamQueueAttributeList[index].QThresholds,
894 SchedulingPolicy: tp.UpstreamQueueAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700895 PriorityQ: tp.UpstreamQueueAttributeList[index].PriorityQ,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700896 Weight: tp.UpstreamQueueAttributeList[index].Weight,
897 DiscardPolicy: tp.UpstreamQueueAttributeList[index].DiscardPolicy,
898 DiscardConfig: tp.UpstreamQueueAttributeList[index].DiscardConfig})
899 }
900
Girish Gowdra248971a2021-06-01 15:14:15 -0700901 logger.Info(ctx, "length-of-downstream-gemport-attribute-list", len(tp.DownstreamQueueAttributeList))
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700902 for index := 0; index < int(tp.NumGemPorts); index++ {
903 dsQueueAttributeList = append(dsQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700904 &tp_pb.EPONQueueAttributes{GemportId: gemPorts[index],
905 MaxQSize: tp.DownstreamQueueAttributeList[index].MaxQSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700906 PbitMap: tp.DownstreamQueueAttributeList[index].PbitMap,
907 AesEncryption: tp.DownstreamQueueAttributeList[index].AesEncryption,
908 SchedulingPolicy: tp.DownstreamQueueAttributeList[index].SchedulingPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -0700909 PriorityQ: tp.DownstreamQueueAttributeList[index].PriorityQ,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700910 Weight: tp.DownstreamQueueAttributeList[index].Weight,
911 DiscardPolicy: tp.DownstreamQueueAttributeList[index].DiscardPolicy,
912 DiscardConfig: tp.DownstreamQueueAttributeList[index].DiscardConfig})
913 }
914
Girish Gowdra248971a2021-06-01 15:14:15 -0700915 return &tp_pb.EponTechProfileInstance{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700916 SubscriberIdentifier: uniPortName,
917 Name: tp.Name,
918 ProfileType: tp.ProfileType,
919 Version: tp.Version,
920 NumGemPorts: tp.NumGemPorts,
Girish Gowdra248971a2021-06-01 15:14:15 -0700921 InstanceControl: tp.InstanceControl,
922 PackageType: tp.PackageType,
923 AllocId: tcontIDs[0],
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700924 UpstreamQueueAttributeList: usQueueAttributeList,
925 DownstreamQueueAttributeList: dsQueueAttributeList}
926}
927
Girish Gowdra248971a2021-06-01 15:14:15 -0700928// getSingleInstanceTp returns another TpInstance (GPON, XGPON, XGS-PON) for an ONU on a different
Girish Gowdra32f0eff2019-11-17 09:53:29 +0530929// uni port for the same TP ID, if it finds one, else nil.
Girish Gowdra248971a2021-06-01 15:14:15 -0700930func (t *TechProfileMgr) getSingleInstanceTp(ctx context.Context, tpPathSuffix string) *tp_pb.TechProfileInstance {
Girish Gowdra9447baf2019-11-05 16:42:37 +0530931
932 // For example:
Girish Gowdra248971a2021-06-01 15:14:15 -0700933 // tpPathSuffix like "XGS-PON/64/olt-{1234}/pon-{0}/onu-{1}/uni-{1}"
934 // is broken into ["XGS-PON/64/olt-{1234}/pon-{0}/onu-{1}" ""]
935 uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPathSuffix, 2)
Girish Gowdra9447baf2019-11-05 16:42:37 +0530936
Girish Gowdra248971a2021-06-01 15:14:15 -0700937 t.tpInstanceMapLock.RLock()
938 defer t.tpInstanceMapLock.RUnlock()
939 for i := 0; i < MaxUniPortPerOnu; i++ {
940 key := fmt.Sprintf(uniPathSlice[0]+"/uni-{%d}", i)
941 if tpInst, ok := t.tpInstanceMap[key]; ok {
942 logger.Debugw(ctx, "found-single-instance-tp", log.Fields{"key": key})
943 return tpInst
Girish Gowdra9447baf2019-11-05 16:42:37 +0530944 }
945 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700946 return nil
Girish Gowdra9447baf2019-11-05 16:42:37 +0530947}
948
Girish Gowdra248971a2021-06-01 15:14:15 -0700949// getSingleInstanceTp returns another TpInstance (EPON) for an ONU on a different
950// uni port for the same TP ID, if it finds one, else nil.
951func (t *TechProfileMgr) getSingleInstanceEponTp(ctx context.Context, tpPathSuffix string) *tp_pb.EponTechProfileInstance {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700952 // For example:
Girish Gowdra248971a2021-06-01 15:14:15 -0700953 // tpPathSuffix like "EPON/64/olt-{1234}/pon-{0}/onu-{1}/uni-{1}"
954 // is broken into ["EPON/64/-{1234}/pon-{0}/onu-{1}" ""]
955 uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPathSuffix, 2)
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700956
Girish Gowdra248971a2021-06-01 15:14:15 -0700957 t.epontpInstanceMapLock.RLock()
958 defer t.epontpInstanceMapLock.RUnlock()
959 for i := 0; i < MaxUniPortPerOnu; i++ {
960 key := fmt.Sprintf(uniPathSlice[0]+"/uni-{%d}", i)
961 if tpInst, ok := t.eponTpInstanceMap[key]; ok {
962 logger.Debugw(ctx, "found-single-instance-tp", log.Fields{"key": key})
963 return tpInst
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700964 }
965 }
Girish Gowdra248971a2021-06-01 15:14:15 -0700966 return nil
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -0700967}
968
Girish Gowdra248971a2021-06-01 15:14:15 -0700969// getDefaultTechProfile returns a default TechProfile for GPON, XGPON, XGS-PON
970func (t *TechProfileMgr) getDefaultTechProfile(ctx context.Context) *tp_pb.TechProfile {
971 var usGemPortAttributeList []*tp_pb.GemPortAttributes
972 var dsGemPortAttributeList []*tp_pb.GemPortAttributes
Scott Baker2c1c4822019-10-16 11:02:41 -0700973
974 for _, pbit := range t.config.DefaultPbits {
Girish Gowdra248971a2021-06-01 15:14:15 -0700975 logger.Debugw(ctx, "creating-gem-port-profile-profile", log.Fields{"pbit": pbit})
Scott Baker2c1c4822019-10-16 11:02:41 -0700976 usGemPortAttributeList = append(usGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -0700977 &tp_pb.GemPortAttributes{
978 MaxQSize: defaultMaxQueueSize,
Scott Baker2c1c4822019-10-16 11:02:41 -0700979 PbitMap: pbit,
980 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -0700981 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
982 PriorityQ: defaultPriorityQueue,
Scott Baker2c1c4822019-10-16 11:02:41 -0700983 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -0700984 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
985 DiscardConfigV2: &tp_pb.DiscardConfig{
986 DiscardPolicy: tp_pb.DiscardPolicy_Red,
987 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
988 RedDiscardConfig: &tp_pb.RedDiscardConfig{
989 MinThreshold: defaultMinThreshold,
990 MaxThreshold: defaultMaxThreshold,
991 MaxProbability: defaultMaxProbability,
992 },
993 },
994 },
995 DiscardConfig: &tp_pb.RedDiscardConfig{
Scott Baker2c1c4822019-10-16 11:02:41 -0700996 MinThreshold: defaultMinThreshold,
997 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -0700998 MaxProbability: defaultMaxProbability,
999 },
1000 })
Scott Baker2c1c4822019-10-16 11:02:41 -07001001 dsGemPortAttributeList = append(dsGemPortAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001002 &tp_pb.GemPortAttributes{
1003 MaxQSize: defaultMaxQueueSize,
Scott Baker2c1c4822019-10-16 11:02:41 -07001004 PbitMap: pbit,
1005 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -07001006 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1007 PriorityQ: defaultPriorityQueue,
Scott Baker2c1c4822019-10-16 11:02:41 -07001008 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001009 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1010 DiscardConfigV2: &tp_pb.DiscardConfig{
1011 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1012 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1013 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1014 MinThreshold: defaultMinThreshold,
1015 MaxThreshold: defaultMaxThreshold,
1016 MaxProbability: defaultMaxProbability,
1017 },
1018 },
1019 },
1020 DiscardConfig: &tp_pb.RedDiscardConfig{
Scott Baker2c1c4822019-10-16 11:02:41 -07001021 MinThreshold: defaultMinThreshold,
1022 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001023 MaxProbability: defaultMaxProbability,
1024 },
1025 IsMulticast: defaultIsMulticast,
1026 DynamicAccessControlList: defaultAccessControlList,
1027 StaticAccessControlList: defaultAccessControlList,
1028 MulticastGemId: defaultMcastGemID})
Scott Baker2c1c4822019-10-16 11:02:41 -07001029 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001030 return &tp_pb.TechProfile{
Scott Baker2c1c4822019-10-16 11:02:41 -07001031 Name: t.config.DefaultTPName,
1032 ProfileType: t.resourceMgr.GetTechnology(),
1033 Version: t.config.TPVersion,
1034 NumGemPorts: uint32(len(usGemPortAttributeList)),
Girish Gowdra248971a2021-06-01 15:14:15 -07001035 InstanceControl: &tp_pb.InstanceControl{
Scott Baker2c1c4822019-10-16 11:02:41 -07001036 Onu: defaultOnuInstance,
1037 Uni: defaultUniInstance,
1038 MaxGemPayloadSize: defaultGemPayloadSize},
Girish Gowdra248971a2021-06-01 15:14:15 -07001039 UsScheduler: &tp_pb.SchedulerAttributes{
1040 Direction: tp_pb.Direction_UPSTREAM,
1041 AdditionalBw: tp_pb.AdditionalBW_AdditionalBW_BestEffort,
Scott Baker2c1c4822019-10-16 11:02:41 -07001042 Priority: defaultPriority,
1043 Weight: defaultWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001044 QSchedPolicy: tp_pb.SchedulingPolicy_Hybrid},
1045 DsScheduler: &tp_pb.SchedulerAttributes{
1046 Direction: tp_pb.Direction_DOWNSTREAM,
1047 AdditionalBw: tp_pb.AdditionalBW_AdditionalBW_BestEffort,
Scott Baker2c1c4822019-10-16 11:02:41 -07001048 Priority: defaultPriority,
1049 Weight: defaultWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001050 QSchedPolicy: tp_pb.SchedulingPolicy_Hybrid},
Scott Baker2c1c4822019-10-16 11:02:41 -07001051 UpstreamGemPortAttributeList: usGemPortAttributeList,
1052 DownstreamGemPortAttributeList: dsGemPortAttributeList}
1053}
1054
Girish Gowdra248971a2021-06-01 15:14:15 -07001055// getDefaultEponProfile returns a default TechProfile for EPON
1056func (t *TechProfileMgr) getDefaultEponProfile(ctx context.Context) *tp_pb.EponTechProfile {
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001057
Girish Gowdra248971a2021-06-01 15:14:15 -07001058 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
1059 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001060
1061 for _, pbit := range t.config.DefaultPbits {
Girish Kumar950f21e2020-08-19 17:42:29 +00001062 logger.Debugw(ctx, "Creating Queue", log.Fields{"pbit": pbit})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001063 usQueueAttributeList = append(usQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001064 &tp_pb.EPONQueueAttributes{
1065 MaxQSize: defaultMaxQueueSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001066 PbitMap: pbit,
1067 AesEncryption: defaultAESEncryption,
1068 TrafficType: defaultTrafficType,
1069 UnsolicitedGrantSize: defaultUnsolicitedGrantSize,
1070 NominalInterval: defaultNominalInterval,
1071 ToleratedPollJitter: defaultToleratedPollJitter,
1072 RequestTransmissionPolicy: defaultRequestTransmissionPolicy,
Girish Gowdra248971a2021-06-01 15:14:15 -07001073 NumQSets: defaultNumQueueSet,
1074 QThresholds: &tp_pb.QThresholds{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001075 QThreshold1: defaultQThreshold1,
1076 QThreshold2: defaultQThreshold2,
1077 QThreshold3: defaultQThreshold3,
1078 QThreshold4: defaultQThreshold4,
1079 QThreshold5: defaultQThreshold5,
1080 QThreshold6: defaultQThreshold6,
1081 QThreshold7: defaultQThreshold7},
Girish Gowdra248971a2021-06-01 15:14:15 -07001082 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1083 PriorityQ: defaultPriorityQueue,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001084 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001085 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1086 DiscardConfigV2: &tp_pb.DiscardConfig{
1087 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1088 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1089 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1090 MinThreshold: defaultMinThreshold,
1091 MaxThreshold: defaultMaxThreshold,
1092 MaxProbability: defaultMaxProbability,
1093 },
1094 },
1095 },
1096 DiscardConfig: &tp_pb.RedDiscardConfig{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001097 MinThreshold: defaultMinThreshold,
1098 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001099 MaxProbability: defaultMaxProbability,
1100 }})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001101 dsQueueAttributeList = append(dsQueueAttributeList,
Girish Gowdra248971a2021-06-01 15:14:15 -07001102 &tp_pb.EPONQueueAttributes{
1103 MaxQSize: defaultMaxQueueSize,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001104 PbitMap: pbit,
1105 AesEncryption: defaultAESEncryption,
Girish Gowdra248971a2021-06-01 15:14:15 -07001106 SchedulingPolicy: tp_pb.SchedulingPolicy_WRR,
1107 PriorityQ: defaultPriorityQueue,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001108 Weight: defaultQueueWeight,
Girish Gowdra248971a2021-06-01 15:14:15 -07001109 DiscardPolicy: tp_pb.DiscardPolicy_TailDrop,
1110 DiscardConfigV2: &tp_pb.DiscardConfig{
1111 DiscardPolicy: tp_pb.DiscardPolicy_Red,
1112 DiscardConfig: &tp_pb.DiscardConfig_RedDiscardConfig{
1113 RedDiscardConfig: &tp_pb.RedDiscardConfig{
1114 MinThreshold: defaultMinThreshold,
1115 MaxThreshold: defaultMaxThreshold,
1116 MaxProbability: defaultMaxProbability,
1117 },
1118 },
1119 },
1120 DiscardConfig: &tp_pb.RedDiscardConfig{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001121 MinThreshold: defaultMinThreshold,
1122 MaxThreshold: defaultMaxThreshold,
Girish Gowdra248971a2021-06-01 15:14:15 -07001123 MaxProbability: defaultMaxProbability,
1124 }})
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001125 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001126 return &tp_pb.EponTechProfile{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001127 Name: t.config.DefaultTPName,
1128 ProfileType: t.resourceMgr.GetTechnology(),
1129 Version: t.config.TPVersion,
1130 NumGemPorts: uint32(len(usQueueAttributeList)),
Girish Gowdra248971a2021-06-01 15:14:15 -07001131 InstanceControl: &tp_pb.InstanceControl{
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001132 Onu: defaultOnuInstance,
1133 Uni: defaultUniInstance,
1134 MaxGemPayloadSize: defaultGemPayloadSize},
Girish Gowdra248971a2021-06-01 15:14:15 -07001135 PackageType: defaultPakageType,
Takahiro Suzuki98cd2b92020-03-13 14:50:08 -07001136 UpstreamQueueAttributeList: usQueueAttributeList,
1137 DownstreamQueueAttributeList: dsQueueAttributeList}
1138}
1139
Joey Armstrong7f8436c2023-07-09 20:23:27 -04001140// isMulticastGem returns true if isMulticast attribute value of a GEM port is true; false otherwise
Esin Karaman8aa75a72019-12-20 13:11:59 +00001141func isMulticastGem(isMulticastAttrValue string) bool {
1142 return isMulticastAttrValue != "" &&
1143 (isMulticastAttrValue == "True" || isMulticastAttrValue == "true" || isMulticastAttrValue == "TRUE")
1144}
1145
Abhay Kumar062cda52025-12-23 06:49:37 +00001146func (t *TechProfileMgr) addResourceInstanceToKVStore(ctx context.Context, tpID uint32, uniPortName string, resInst *tp_pb.ResourceInstance) error {
1147 logger.Debugw(ctx, "adding-resource-instance-to-kv-store", log.Fields{"tpID": tpID, "uniPortName": uniPortName})
1148 val, err := proto.Marshal(resInst)
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001149 if err != nil {
Abhay Kumar062cda52025-12-23 06:49:37 +00001150 logger.Errorw(ctx, "failed-to-marshall-resource-instance", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001151 return err
1152 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001153 err = t.config.ResourceInstanceKVBacked.Put(ctx, fmt.Sprintf("%s/%d/%s", t.resourceMgr.GetTechnology(), tpID, uniPortName), val)
1154 return err
1155}
1156
1157func (t *TechProfileMgr) removeResourceInstanceFromKVStore(ctx context.Context, tpID uint32, uniPortName string) error {
1158 logger.Debugw(ctx, "removing-resource-instance-to-kv-store", log.Fields{"tpID": tpID, "uniPortName": uniPortName})
1159 if err := t.config.ResourceInstanceKVBacked.Delete(ctx, fmt.Sprintf("%s/%d/%s", t.resourceMgr.GetTechnology(), tpID, uniPortName)); err != nil {
1160 logger.Errorw(ctx, "error-removing-resource-instance-to-kv-store", log.Fields{"err": err, "tpID": tpID, "uniPortName": uniPortName})
1161 return err
1162 }
1163 return nil
1164}
1165
1166func (t *TechProfileMgr) getTPFromKVStore(ctx context.Context, tpID uint32) *tp_pb.TechProfile {
1167 var tp *tp_pb.TechProfile
1168 t.tpMapLock.RLock()
1169 tp, ok := t.tpMap[tpID]
1170 t.tpMapLock.RUnlock()
1171 if ok {
1172 logger.Debugw(ctx, "found-tp-in-cache", log.Fields{"tpID": tpID})
1173 return tp
1174 }
1175 key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), tpID)
1176 logger.Debugw(ctx, "getting-tp-from-kv-store", log.Fields{"tpID": tpID, "Key": key})
1177 kvresult, err := t.config.DefaultTpKVBackend.Get(ctx, key)
1178 if err != nil {
1179 logger.Errorw(ctx, "error-fetching-from-kv-store", log.Fields{"err": err, "key": key})
1180 return nil
1181 }
1182 if kvresult != nil {
1183 /* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
1184 if value, err := kvstore.ToByte(kvresult.Value); err == nil {
1185 lTp := &tp_pb.TechProfile{}
Abhay Kumar062cda52025-12-23 06:49:37 +00001186 if err = protojson.Unmarshal(value, lTp); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -07001187 logger.Errorw(ctx, "error-unmarshalling-tp-from-kv-store", log.Fields{"err": err, "tpID": tpID, "error": err})
1188 return nil
1189 }
1190
Abhay Kumar062cda52025-12-23 06:49:37 +00001191 logger.Debugw(ctx, "success-fetched-tp-from-kv-store", log.Fields{"tpID": tpID})
Girish Gowdra248971a2021-06-01 15:14:15 -07001192 return lTp
1193 } else {
1194 logger.Errorw(ctx, "error-decoding-tp", log.Fields{"err": err, "tpID": tpID})
1195 // We we create a default profile in this case.
1196 }
1197 }
1198
1199 return nil
1200}
1201
1202func (t *TechProfileMgr) getEponTPFromKVStore(ctx context.Context, tpID uint32) *tp_pb.EponTechProfile {
1203 var eponTp *tp_pb.EponTechProfile
1204 t.eponTpMapLock.RLock()
1205 eponTp, ok := t.eponTpMap[tpID]
1206 t.eponTpMapLock.RUnlock()
1207 if ok {
1208 logger.Debugw(ctx, "found-tp-in-cache", log.Fields{"tpID": tpID})
1209 return eponTp
1210 }
1211 key := fmt.Sprintf(t.config.TPFileKVPath, t.resourceMgr.GetTechnology(), tpID)
1212 logger.Debugw(ctx, "getting-epon-tp-from-kv-store", log.Fields{"tpID": tpID, "Key": key})
1213 kvresult, err := t.config.DefaultTpKVBackend.Get(ctx, key)
1214 if err != nil {
1215 logger.Errorw(ctx, "error-fetching-from-kv-store", log.Fields{"err": err, "key": key})
1216 return nil
1217 }
1218 if kvresult != nil {
1219 /* Backend will return Value in string format,needs to be converted to []byte before unmarshal*/
1220 if value, err := kvstore.ToByte(kvresult.Value); err == nil {
1221 lEponTp := &tp_pb.EponTechProfile{}
Abhay Kumar062cda52025-12-23 06:49:37 +00001222 if err = protojson.Unmarshal(value, lEponTp); err != nil {
Girish Gowdra248971a2021-06-01 15:14:15 -07001223 logger.Errorw(ctx, "error-unmarshalling-epon-tp-from-kv-store", log.Fields{"err": err, "tpID": tpID, "error": err})
1224 return nil
1225 }
1226
Abhay Kumar062cda52025-12-23 06:49:37 +00001227 logger.Debugw(ctx, "success-fetching-epon-tp-from-kv-store", log.Fields{"tpID": tpID})
Girish Gowdra248971a2021-06-01 15:14:15 -07001228 return lEponTp
1229 }
1230 }
1231 return nil
1232}
1233
1234func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
1235
1236 logger.Infow(ctx, "kv-store", log.Fields{"storeType": storeType, "address": address})
1237 switch storeType {
1238 case "etcd":
1239 return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
serkant.uluderyae5afeff2021-02-23 18:00:23 +03001240 case "redis":
1241 return kvstore.NewRedisClient(address, timeout, false)
1242 case "redis-sentinel":
1243 return kvstore.NewRedisClient(address, timeout, true)
Girish Gowdra248971a2021-06-01 15:14:15 -07001244 }
serkant.uluderyae5afeff2021-02-23 18:00:23 +03001245
Girish Gowdra248971a2021-06-01 15:14:15 -07001246 return nil, errors.New("unsupported-kv-store")
1247}
1248
1249// buildTpInstanceFromResourceInstance for GPON, XGPON and XGS-PON technology - build TpInstance from TechProfile template and ResourceInstance
1250func (t *TechProfileMgr) buildTpInstanceFromResourceInstance(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance) *tp_pb.TechProfileInstance {
1251
Girish Gowdra248971a2021-06-01 15:14:15 -07001252 if len(resInst.GemportIds) != int(tp.NumGemPorts) {
1253 logger.Errorw(ctx, "mismatch-in-number-of-gemports-between-template-and-resource-instance",
1254 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1255 return nil
1256 }
Girish Gowdra248971a2021-06-01 15:14:15 -07001257
pnalmas23a77d02025-01-15 11:52:48 +05301258 usGemPortAttributeList := make([]*tp_pb.GemPortAttributes, 0, tp.NumGemPorts)
1259 dsGemPortAttributeList := make([]*tp_pb.GemPortAttributes, 0, tp.NumGemPorts)
1260 dsMulticastGemAttributeList := make([]*tp_pb.GemPortAttributes, 0)
1261 dsUnicastGemAttributeList := make([]*tp_pb.GemPortAttributes, 0)
1262
1263 logger.Debugw(ctx, "Building TP Instance",
1264 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1265
1266 usGemPortAttributeList = t.buildUpstreamGemPortAttributes(ctx, tp, resInst, usGemPortAttributeList)
1267 dsUnicastGemAttributeList, dsMulticastGemAttributeList = t.separateDownstreamGemPortAttributes(ctx, tp, dsUnicastGemAttributeList, dsMulticastGemAttributeList)
1268 dsGemPortAttributeList = t.buildDownstreamGemPortAttributes(ctx, tp, resInst, dsUnicastGemAttributeList, dsMulticastGemAttributeList, dsGemPortAttributeList)
Girish Gowdra248971a2021-06-01 15:14:15 -07001269
1270 return &tp_pb.TechProfileInstance{
1271 SubscriberIdentifier: resInst.SubscriberIdentifier,
1272 Name: tp.Name,
1273 ProfileType: tp.ProfileType,
1274 Version: tp.Version,
1275 NumGemPorts: tp.NumGemPorts,
1276 InstanceControl: tp.InstanceControl,
1277 UsScheduler: &tp_pb.SchedulerAttributes{
1278 AllocId: resInst.AllocId,
1279 Direction: tp.UsScheduler.Direction,
1280 AdditionalBw: tp.UsScheduler.AdditionalBw,
1281 Priority: tp.UsScheduler.Priority,
1282 Weight: tp.UsScheduler.Weight,
1283 QSchedPolicy: tp.UsScheduler.QSchedPolicy},
1284 DsScheduler: &tp_pb.SchedulerAttributes{
1285 AllocId: resInst.AllocId,
1286 Direction: tp.DsScheduler.Direction,
1287 AdditionalBw: tp.DsScheduler.AdditionalBw,
1288 Priority: tp.DsScheduler.Priority,
1289 Weight: tp.DsScheduler.Weight,
1290 QSchedPolicy: tp.DsScheduler.QSchedPolicy},
1291 UpstreamGemPortAttributeList: usGemPortAttributeList,
1292 DownstreamGemPortAttributeList: dsGemPortAttributeList}
1293}
1294
1295// buildEponTpInstanceFromResourceInstance for EPON technology - build EponTpInstance from EponTechProfile template and ResourceInstance
1296func (t *TechProfileMgr) buildEponTpInstanceFromResourceInstance(ctx context.Context, tp *tp_pb.EponTechProfile, resInst *tp_pb.ResourceInstance) *tp_pb.EponTechProfileInstance {
1297
1298 var usQueueAttributeList []*tp_pb.EPONQueueAttributes
1299 var dsQueueAttributeList []*tp_pb.EPONQueueAttributes
1300
1301 if len(resInst.GemportIds) != int(tp.NumGemPorts) {
1302 logger.Errorw(ctx, "mismatch-in-number-of-gemports-between-epon-tp-template-and-resource-instance",
1303 log.Fields{"tpID": resInst.TpId, "totalResInstGemPortIDs": len(resInst.GemportIds), "totalTpTemplateGemPorts": tp.NumGemPorts})
1304 return nil
1305 }
1306
1307 for index := 0; index < int(tp.NumGemPorts); index++ {
1308 usQueueAttributeList = append(usQueueAttributeList,
1309 &tp_pb.EPONQueueAttributes{GemportId: resInst.GemportIds[index],
1310 MaxQSize: tp.UpstreamQueueAttributeList[index].MaxQSize,
1311 PbitMap: tp.UpstreamQueueAttributeList[index].PbitMap,
1312 AesEncryption: tp.UpstreamQueueAttributeList[index].AesEncryption,
1313 TrafficType: tp.UpstreamQueueAttributeList[index].TrafficType,
1314 UnsolicitedGrantSize: tp.UpstreamQueueAttributeList[index].UnsolicitedGrantSize,
1315 NominalInterval: tp.UpstreamQueueAttributeList[index].NominalInterval,
1316 ToleratedPollJitter: tp.UpstreamQueueAttributeList[index].ToleratedPollJitter,
1317 RequestTransmissionPolicy: tp.UpstreamQueueAttributeList[index].RequestTransmissionPolicy,
1318 NumQSets: tp.UpstreamQueueAttributeList[index].NumQSets,
1319 QThresholds: tp.UpstreamQueueAttributeList[index].QThresholds,
1320 SchedulingPolicy: tp.UpstreamQueueAttributeList[index].SchedulingPolicy,
1321 PriorityQ: tp.UpstreamQueueAttributeList[index].PriorityQ,
1322 Weight: tp.UpstreamQueueAttributeList[index].Weight,
1323 DiscardPolicy: tp.UpstreamQueueAttributeList[index].DiscardPolicy,
1324 DiscardConfig: tp.UpstreamQueueAttributeList[index].DiscardConfig})
1325 }
1326
1327 for index := 0; index < int(tp.NumGemPorts); index++ {
1328 dsQueueAttributeList = append(dsQueueAttributeList,
1329 &tp_pb.EPONQueueAttributes{GemportId: resInst.GemportIds[index],
1330 MaxQSize: tp.DownstreamQueueAttributeList[index].MaxQSize,
1331 PbitMap: tp.DownstreamQueueAttributeList[index].PbitMap,
1332 AesEncryption: tp.DownstreamQueueAttributeList[index].AesEncryption,
1333 SchedulingPolicy: tp.DownstreamQueueAttributeList[index].SchedulingPolicy,
1334 PriorityQ: tp.DownstreamQueueAttributeList[index].PriorityQ,
1335 Weight: tp.DownstreamQueueAttributeList[index].Weight,
1336 DiscardPolicy: tp.DownstreamQueueAttributeList[index].DiscardPolicy,
1337 DiscardConfig: tp.DownstreamQueueAttributeList[index].DiscardConfig})
1338 }
1339
1340 return &tp_pb.EponTechProfileInstance{
1341 SubscriberIdentifier: resInst.SubscriberIdentifier,
1342 Name: tp.Name,
1343 ProfileType: tp.ProfileType,
1344 Version: tp.Version,
1345 NumGemPorts: tp.NumGemPorts,
1346 InstanceControl: tp.InstanceControl,
1347 PackageType: tp.PackageType,
1348 AllocId: resInst.AllocId,
1349 UpstreamQueueAttributeList: usQueueAttributeList,
1350 DownstreamQueueAttributeList: dsQueueAttributeList}
1351}
1352
1353func (t *TechProfileMgr) getTpInstanceFromResourceInstance(ctx context.Context, resInst *tp_pb.ResourceInstance) *tp_pb.TechProfileInstance {
1354 if resInst == nil {
1355 logger.Error(ctx, "resource-instance-nil")
1356 return nil
1357 }
1358 tp := t.getTPFromKVStore(ctx, resInst.TpId)
1359 if tp == nil {
1360 logger.Warnw(ctx, "tp-not-found-on-kv--creating-default-tp", log.Fields{"tpID": resInst.TpId})
1361 tp = t.getDefaultTechProfile(ctx)
1362 }
1363 return t.buildTpInstanceFromResourceInstance(ctx, tp, resInst)
1364}
1365
1366func (t *TechProfileMgr) getEponTpInstanceFromResourceInstance(ctx context.Context, resInst *tp_pb.ResourceInstance) *tp_pb.EponTechProfileInstance {
1367 if resInst == nil {
1368 logger.Error(ctx, "resource-instance-nil")
1369 return nil
1370 }
1371 eponTp := t.getEponTPFromKVStore(ctx, resInst.TpId)
1372 if eponTp == nil {
1373 logger.Warnw(ctx, "tp-not-found-on-kv--creating-default-tp", log.Fields{"tpID": resInst.TpId})
1374 eponTp = t.getDefaultEponProfile(ctx)
1375 }
1376 return t.buildEponTpInstanceFromResourceInstance(ctx, eponTp, resInst)
1377}
1378
pnalmas23a77d02025-01-15 11:52:48 +05301379func (t *TechProfileMgr) reconcileTpInstancesToCache(ctx context.Context, IntfId uint32, deviceId string) error {
Girish Gowdra248971a2021-06-01 15:14:15 -07001380
1381 tech := t.resourceMgr.GetTechnology()
1382 newCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
1383 defer cancel()
Girish Gowdra248971a2021-06-01 15:14:15 -07001384
pnalmas23a77d02025-01-15 11:52:48 +05301385 //VOL-5417:Only reconcile the tech profiles for the subscribers associated with this PON port on this device.
1386 //Getting the list of supported tech profile IDs and then reconciling the tech profiles for these IDs associated
1387 //with the subscribers on this device for this PON port.
1388
1389 //Fetching the techprofile Keys from the KV Store.
1390 tpkeys, _ := t.config.DefaultTpKVBackend.GetWithPrefixKeysOnly(ctx, tech)
1391
1392 // Extract the techprofile Ids from the keys
1393 // The tpkeys will be of the format "service/voltha/technology_profiles/GPON/65"
1394 // where 65 is the techprofile Id
1395 tpIds := make([]uint32, 0)
1396
1397 for _, key := range tpkeys {
1398 parts := strings.Split(key, "/")
1399 // Ensure the key has the expected format
1400 if len(parts) < 5 {
1401 logger.Errorw(ctx, "Key does not match expected format", log.Fields{"key": key})
1402 continue
Girish Gowdra248971a2021-06-01 15:14:15 -07001403 }
pnalmas23a77d02025-01-15 11:52:48 +05301404 // Convert the last part of the key to uint32 (techprofile Id)
1405 tpId, err := strconv.Atoi(parts[len(parts)-1])
1406 if err != nil {
1407 logger.Errorw(ctx, "Error converting techprofile Id to int", log.Fields{"key": key, "error": err})
1408 continue
Girish Gowdra248971a2021-06-01 15:14:15 -07001409 }
pnalmas23a77d02025-01-15 11:52:48 +05301410 tpIds = append(tpIds, uint32(tpId))
Girish Gowdra248971a2021-06-01 15:14:15 -07001411 }
1412
pnalmas23a77d02025-01-15 11:52:48 +05301413 //for each tpid form a prefix and get the resource instance
1414 for _, tpId := range tpIds {
1415 prefix := fmt.Sprintf("%s/%d/olt-{%s}/pon-{%d}", tech, tpId, deviceId, IntfId)
1416 kvPairs, _ := t.config.ResourceInstanceKVBacked.GetWithPrefix(newCtx, prefix)
1417 //check if KvPairs is empty and if not then reconcile the techprofile instance
1418 if len(kvPairs) > 0 {
1419 for keyPath, kvPair := range kvPairs {
1420 if value, err := kvstore.ToByte(kvPair.Value); err == nil {
1421 var resInst tp_pb.ResourceInstance
1422 if err = proto.Unmarshal(value, &resInst); err != nil {
1423 logger.Errorw(ctx, "error-unmarshal-kv-pair", log.Fields{"err": err, "keyPath": keyPath, "value": value})
1424 continue
1425 } else {
1426 if tech == xgspon || tech == xgpon || tech == gpon {
1427 if tpInst := t.getTpInstanceFromResourceInstance(ctx, &resInst); tpInst != nil {
1428 keySuffixSlice := regexp.MustCompile(t.config.ResourceInstanceKVPathPrefix+"/").Split(keyPath, 2)
1429 if len(keySuffixSlice) == 2 {
1430 keySuffixFormatRegexp := regexp.MustCompile(`^[a-zA-Z\-]+/[0-9]+/olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
1431 if !keySuffixFormatRegexp.Match([]byte(keySuffixSlice[1])) {
1432 logger.Errorw(ctx, "kv-path-not-confirming-to-format", log.Fields{"kvPath": keySuffixSlice[1]})
1433 continue
1434 }
1435 } else {
1436 logger.Errorw(ctx, "kv-instance-key-path-not-in-the-expected-format", log.Fields{"kvPath": keyPath})
1437 continue
1438 }
1439 t.tpInstanceMapLock.Lock()
1440 t.tpInstanceMap[keySuffixSlice[1]] = tpInst
1441 t.tpInstanceMapLock.Unlock()
1442 logger.Infow(ctx, "reconciled-tp-success", log.Fields{"keyPath": keyPath})
1443 }
1444 } else if tech == epon {
1445 if eponTpInst := t.getEponTpInstanceFromResourceInstance(ctx, &resInst); eponTpInst != nil {
1446 keySuffixSlice := regexp.MustCompile(t.config.ResourceInstanceKVPathPrefix+"/").Split(keyPath, 2)
1447 if len(keySuffixSlice) == 2 {
1448 keySuffixFormatRegexp := regexp.MustCompile(`^[a-zA-Z\-]+/[0-9]+/olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)
1449 if !keySuffixFormatRegexp.Match([]byte(keySuffixSlice[1])) {
1450 logger.Errorw(ctx, "kv-path-not-confirming-to-format", log.Fields{"kvPath": keySuffixSlice[1]})
1451 continue
1452 }
1453 } else {
1454 logger.Errorw(ctx, "kv-instance-key-path-not-in-the-expected-format", log.Fields{"kvPath": keyPath})
1455 continue
1456 }
1457 t.epontpInstanceMapLock.Lock()
1458 t.eponTpInstanceMap[keySuffixSlice[1]] = eponTpInst
1459 t.epontpInstanceMapLock.Unlock()
1460 logger.Debugw(ctx, "reconciled-epon-tp-success", log.Fields{"keyPath": keyPath})
1461 }
1462 } else {
1463 logger.Errorw(ctx, "unknown-tech", log.Fields{"tech": tech})
1464 return fmt.Errorf("unknown-tech-%v", tech)
1465 }
1466 }
1467 } else {
1468 logger.Errorw(ctx, "error-converting-kv-pair-value-to-byte", log.Fields{"err": err})
1469 }
1470
1471 }
1472
1473 return nil
1474 }
1475 }
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001476 return nil
1477}
pnalmas23a77d02025-01-15 11:52:48 +05301478
1479func (t *TechProfileMgr) buildUpstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance, usGemPortAttributeList []*tp_pb.GemPortAttributes) []*tp_pb.GemPortAttributes {
1480 for index := 0; index < int(tp.NumGemPorts); index++ {
1481 usGemPortAttributeList = append(usGemPortAttributeList, &tp_pb.GemPortAttributes{
1482 GemportId: resInst.GemportIds[index],
1483 MaxQSize: tp.UpstreamGemPortAttributeList[index].MaxQSize,
1484 PbitMap: tp.UpstreamGemPortAttributeList[index].PbitMap,
1485 AesEncryption: tp.UpstreamGemPortAttributeList[index].AesEncryption,
1486 SchedulingPolicy: tp.UpstreamGemPortAttributeList[index].SchedulingPolicy,
1487 PriorityQ: tp.UpstreamGemPortAttributeList[index].PriorityQ,
1488 Weight: tp.UpstreamGemPortAttributeList[index].Weight,
1489 DiscardPolicy: tp.UpstreamGemPortAttributeList[index].DiscardPolicy,
1490 DiscardConfig: tp.UpstreamGemPortAttributeList[index].DiscardConfig,
1491 })
1492 }
1493 logger.Debugw(ctx, "Processed upstream GEM port attributes", log.Fields{"count": len(usGemPortAttributeList)})
1494 return usGemPortAttributeList
1495}
1496
1497func (t *TechProfileMgr) separateDownstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, dsUnicastGemAttributeList, dsMulticastGemAttributeList []*tp_pb.GemPortAttributes) ([]*tp_pb.GemPortAttributes, []*tp_pb.GemPortAttributes) {
1498 for _, attr := range tp.DownstreamGemPortAttributeList {
1499 if isMulticastGem(attr.IsMulticast) {
1500 dsMulticastGemAttributeList = append(dsMulticastGemAttributeList, &tp_pb.GemPortAttributes{
1501 MulticastGemId: attr.MulticastGemId,
1502 MaxQSize: attr.MaxQSize,
1503 PbitMap: attr.PbitMap,
1504 AesEncryption: attr.AesEncryption,
1505 SchedulingPolicy: attr.SchedulingPolicy,
1506 PriorityQ: attr.PriorityQ,
1507 Weight: attr.Weight,
1508 DiscardPolicy: attr.DiscardPolicy,
1509 DiscardConfig: attr.DiscardConfig,
1510 IsMulticast: attr.IsMulticast,
1511 DynamicAccessControlList: attr.DynamicAccessControlList,
1512 StaticAccessControlList: attr.StaticAccessControlList,
1513 })
1514 } else {
1515 dsUnicastGemAttributeList = append(dsUnicastGemAttributeList, &tp_pb.GemPortAttributes{
1516 MaxQSize: attr.MaxQSize,
1517 PbitMap: attr.PbitMap,
1518 AesEncryption: attr.AesEncryption,
1519 SchedulingPolicy: attr.SchedulingPolicy,
1520 PriorityQ: attr.PriorityQ,
1521 Weight: attr.Weight,
1522 DiscardPolicy: attr.DiscardPolicy,
1523 DiscardConfig: attr.DiscardConfig,
1524 })
1525 }
1526 }
1527 logger.Debugw(ctx, "Processed downstream GEM port attributes", log.Fields{
1528 "unicastCount": len(dsUnicastGemAttributeList), "multicastCount": len(dsMulticastGemAttributeList)})
1529 return dsUnicastGemAttributeList, dsMulticastGemAttributeList
1530}
1531
1532func (t *TechProfileMgr) buildDownstreamGemPortAttributes(ctx context.Context, tp *tp_pb.TechProfile, resInst *tp_pb.ResourceInstance, dsUnicastGemAttributeList, dsMulticastGemAttributeList, dsGemPortAttributeList []*tp_pb.GemPortAttributes) []*tp_pb.GemPortAttributes {
1533 for index := 0; index < int(tp.NumGemPorts) && index < len(dsUnicastGemAttributeList); index++ {
1534 dsGemPortAttributeList = append(dsGemPortAttributeList, &tp_pb.GemPortAttributes{
1535 GemportId: resInst.GemportIds[index],
1536 MaxQSize: dsUnicastGemAttributeList[index].MaxQSize,
1537 PbitMap: dsUnicastGemAttributeList[index].PbitMap,
1538 AesEncryption: dsUnicastGemAttributeList[index].AesEncryption,
1539 SchedulingPolicy: dsUnicastGemAttributeList[index].SchedulingPolicy,
1540 PriorityQ: dsUnicastGemAttributeList[index].PriorityQ,
1541 Weight: dsUnicastGemAttributeList[index].Weight,
1542 DiscardPolicy: dsUnicastGemAttributeList[index].DiscardPolicy,
1543 DiscardConfig: dsUnicastGemAttributeList[index].DiscardConfig,
1544 })
1545 }
1546 dsGemPortAttributeList = append(dsGemPortAttributeList, dsMulticastGemAttributeList...)
1547 logger.Debugw(ctx, "Processed downstream GEM port attributes for final list", log.Fields{"count": len(dsGemPortAttributeList)})
1548 return dsGemPortAttributeList
1549}