blob: 784a3fa85ff2a49e58a3679fcb1ee9bbd4f924e8 [file] [log] [blame]
Zdravko Bozakov958d81c2019-12-13 22:09:48 +01001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package sadis
18
19import (
20 "encoding/json"
Matteo Scandolo8a574812021-05-20 15:18:53 -070021 "fmt"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010022 "net/http"
Matteo Scandolo8a574812021-05-20 15:18:53 -070023 "strconv"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010024 "strings"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010025
26 "github.com/gorilla/mux"
27 "github.com/opencord/bbsim/internal/bbsim/devices"
28 "github.com/opencord/bbsim/internal/common"
29 log "github.com/sirupsen/logrus"
30)
31
32var sadisLogger = log.WithFields(log.Fields{
33 "module": "SADIS",
34})
35
Matteo Scandolo8a574812021-05-20 15:18:53 -070036const (
37 BaseConfigUrl = "/{version}/cfg"
38 StaticConfigUrl = "/{version}/static"
39 SadisEntryUrl = "/{version}/subscribers/{ID}"
40 SadisBwUrl = "/{version}/bandwidthprofiles/{ID}"
41)
42
Matteo Scandolocedde462021-03-09 17:37:16 -080043type SadisServer struct {
44 Olt *devices.OltDevice
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010045}
46
47// bandwidthProfiles contains some dummy profiles
Matteo Scandolo94967142021-05-28 11:37:06 -070048var bandwidthProfiles = map[string][]*SadisBWPEntry{
49 common.BP_FORMAT_MEF: {
50 {ID: "User_Bandwidth1", AIR: 100000, CBS: 10000, CIR: 30000, EBS: 1000, EIR: 100000},
51 {ID: "User_Bandwidth2", AIR: 100000, CBS: 5000, CIR: 100000, EBS: 5000, EIR: 100000},
52 {ID: "User_Bandwidth3", AIR: 100000, CBS: 5000, CIR: 1000000, EBS: 5000, EIR: 1000000},
53 {ID: "Default", AIR: 100000, CBS: 30, CIR: 600, EBS: 30, EIR: 400},
54 },
55 common.BP_FORMAT_IETF: {
56 {ID: "User_Bandwidth1", CBS: 10000, CIR: 30000, GIR: 100000, PIR: 20000, PBS: 1000},
57 {ID: "User_Bandwidth2", CBS: 5000, CIR: 100000, GIR: 100000, PIR: 30000, PBS: 5000},
58 {ID: "User_Bandwidth3", CBS: 5000, CIR: 1000000, GIR: 100000, PIR: 40000, PBS: 5000},
59 {ID: "Default", CBS: 30, CIR: 600, GIR: 0, PIR: 32000, PBS: 30},
60 },
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010061}
62
63// SadisConfig is the top-level SADIS configuration struct
64type SadisConfig struct {
65 Sadis SadisEntries `json:"sadis"`
66 BandwidthProfile BandwidthProfileEntries `json:"bandwidthprofile"`
67}
68
69type SadisEntries struct {
70 Integration SadisIntegration `json:"integration"`
71 Entries []interface{} `json:"entries,omitempty"`
72}
73type BandwidthProfileEntries struct {
74 Integration SadisIntegration `json:"integration"`
Matteo Scandolo51d6a312020-03-12 15:54:43 -070075 Entries []*SadisBWPEntry `json:"entries,omitempty"`
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010076}
77
78type SadisIntegration struct {
79 URL string `json:"url,omitempty"`
80 Cache struct {
81 Enabled bool `json:"enabled"`
82 MaxSize int `json:"maxsize"`
83 TTL string `json:"ttl"`
84 } `json:"cache"`
85}
86
87type SadisOltEntry struct {
88 ID string `json:"id"`
89 HardwareIdentifier string `json:"hardwareIdentifier"`
90 IPAddress string `json:"ipAddress"`
91 NasID string `json:"nasId"`
92 UplinkPort int `json:"uplinkPort"`
93}
94
Anand S Kattib409ee02020-02-20 20:10:00 +053095type SadisOnuEntryV2 struct {
96 ID string `json:"id"`
97 NasPortID string `json:"nasPortId"`
98 CircuitID string `json:"circuitId"`
99 RemoteID string `json:"remoteId"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700100 UniTagList []SadisUniTag `json:"uniTagList"` // this can be SadisUniTagAtt, SadisUniTagDt
Anand S Kattib409ee02020-02-20 20:10:00 +0530101}
102
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103type SadisUniTag struct {
104 UniTagMatch int `json:"uniTagMatch,omitempty"`
Shrey Baid688b4242020-07-10 20:40:10 +0530105 PonCTag int `json:"ponCTag,omitempty"`
106 PonSTag int `json:"ponSTag,omitempty"`
107 TechnologyProfileID int `json:"technologyProfileId,omitempty"`
108 UpstreamBandwidthProfile string `json:"upstreamBandwidthProfile,omitempty"`
109 DownstreamBandwidthProfile string `json:"downstreamBandwidthProfile,omitempty"`
110 IsDhcpRequired bool `json:"isDhcpRequired,omitempty"`
111 IsIgmpRequired bool `json:"isIgmpRequired,omitempty"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112 ConfiguredMacAddress string `json:"configuredMacAddress,omitempty"`
Matteo Scandolo8d281372020-09-03 16:23:37 -0700113 UsPonCTagPriority uint8 `json:"usPonCTagPriority,omitempty"`
114 UsPonSTagPriority uint8 `json:"usPonSTagPriority,omitempty"`
115 DsPonCTagPriority uint8 `json:"dsPonCTagPriority,omitempty"`
116 DsPonSTagPriority uint8 `json:"dsPonSTagPriority,omitempty"`
Matteo Scandolo4a036262020-08-17 15:56:13 -0700117 ServiceName string `json:"serviceName,omitempty"`
Matteo Scandolof65e6872020-04-15 15:18:43 -0700118}
119
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100120// SADIS BandwithProfile Entry
121type SadisBWPEntry struct {
Matteo Scandolo94967142021-05-28 11:37:06 -0700122 // common attributes
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100123 ID string `json:"id"`
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100124 CBS int `json:"cbs"`
125 CIR int `json:"cir"`
Matteo Scandolo94967142021-05-28 11:37:06 -0700126 // MEF attributes
127 AIR int `json:"air,omitempty"`
128 EBS int `json:"ebs,omitempty"`
129 EIR int `json:"eir,omitempty"`
130 // IETF attributes
131 GIR int `json:"gir,omitempty"`
132 PIR int `json:"pir,omitempty"`
133 PBS int `json:"pbs,omitempty"`
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100134}
135
136// GetSadisConfig returns a full SADIS configuration struct ready to be marshalled into JSON
Anand S Kattib409ee02020-02-20 20:10:00 +0530137func GetSadisConfig(olt *devices.OltDevice, version string) *SadisConfig {
138 sadisEntries, _ := GetSadisEntries(olt, version)
139 bwpEntries := getBWPEntries(version)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100140
141 conf := &SadisConfig{}
142 conf.Sadis = *sadisEntries
143 conf.BandwidthProfile = *bwpEntries
144
145 return conf
146}
147
Anand S Kattib409ee02020-02-20 20:10:00 +0530148func GetSadisEntries(olt *devices.OltDevice, version string) (*SadisEntries, error) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100149 solt, _ := GetOltEntry(olt)
150
151 entries := []interface{}{}
152 entries = append(entries, solt)
153
Matteo Scandolo4a036262020-08-17 15:56:13 -0700154 a := strings.Split(common.Config.BBSim.SadisRestAddress, ":")
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100155 port := a[len(a)-1]
156
157 integration := SadisIntegration{}
Anand S Kattib409ee02020-02-20 20:10:00 +0530158 integration.URL = "http://bbsim:" + port + "/" + version + "/subscribers/%s"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100159 integration.Cache.Enabled = false
160 integration.Cache.MaxSize = 50
161 integration.Cache.TTL = "PT0m"
162
163 sadis := &SadisEntries{
164 integration,
165 entries,
166 }
167
168 return sadis, nil
169}
170
171func GetOltEntry(olt *devices.OltDevice) (*SadisOltEntry, error) {
172 ip, _ := common.GetIPAddr("nni") // TODO verify which IP to report
173 solt := &SadisOltEntry{
174 ID: olt.SerialNumber,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700175 HardwareIdentifier: common.Config.Olt.DeviceId,
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100176 IPAddress: ip,
177 NasID: olt.SerialNumber,
Girish Gowdra95005602021-10-22 11:33:01 -0700178 UplinkPort: 16777216, // TODO currently assumes we only have one NNI port
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100179 }
180 return solt, nil
181}
182
Matteo Scandolo8a574812021-05-20 15:18:53 -0700183func GetOnuEntryV2(olt *devices.OltDevice, onu *devices.Onu, uniStr string) (*SadisOnuEntryV2, error) {
184 uniSuffix := "-" + uniStr
Anand S Kattib409ee02020-02-20 20:10:00 +0530185
186 sonuv2 := &SadisOnuEntryV2{
Matteo Scandolodf080442020-10-09 11:57:38 -0700187 ID: onu.Sn() + uniSuffix,
Anand S Kattib409ee02020-02-20 20:10:00 +0530188 }
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700189
Matteo Scandolo8a574812021-05-20 15:18:53 -0700190 uniId, err := strconv.ParseUint(uniStr, 10, 32)
191 if err != nil {
192 return nil, err
193 }
194
195 // find the correct UNI
196 // NOTE that in SADIS uni.Id 0 corresponds to BBSM00000101-1
197 uni, err := onu.FindUniById(uint32(uniId - 1))
198 if err != nil {
199 return nil, err
200 }
201
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202 // createUniTagList
Matteo Scandolo8a574812021-05-20 15:18:53 -0700203 for _, s := range uni.Services {
Matteo Scandolof65e6872020-04-15 15:18:43 -0700204
Matteo Scandolo4a036262020-08-17 15:56:13 -0700205 service := s.(*devices.Service)
206
207 tag := SadisUniTag{
208 ServiceName: service.Name,
209 IsIgmpRequired: service.NeedsIgmp,
210 IsDhcpRequired: service.NeedsDhcp,
211 TechnologyProfileID: service.TechnologyProfileID,
212 UpstreamBandwidthProfile: "User_Bandwidth1",
213 DownstreamBandwidthProfile: "User_Bandwidth2",
214 PonCTag: service.CTag,
215 PonSTag: service.STag,
Matteo Scandolof65e6872020-04-15 15:18:43 -0700216 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700217
218 if service.UniTagMatch != 0 {
219 tag.UniTagMatch = service.UniTagMatch
Matteo Scandolof65e6872020-04-15 15:18:43 -0700220 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700221
222 if service.ConfigureMacAddress {
223 tag.ConfiguredMacAddress = service.HwAddress.String()
224 }
225
226 if service.UsPonCTagPriority != 0 {
227 tag.UsPonCTagPriority = service.UsPonCTagPriority
228 }
229
230 if service.UsPonSTagPriority != 0 {
231 tag.UsPonSTagPriority = service.UsPonSTagPriority
232 }
233
234 if service.DsPonCTagPriority != 0 {
235 tag.DsPonCTagPriority = service.DsPonCTagPriority
236 }
237
238 if service.DsPonSTagPriority != 0 {
239 tag.DsPonSTagPriority = service.DsPonSTagPriority
240 }
241
242 sonuv2.UniTagList = append(sonuv2.UniTagList, tag)
Anand S Kattib409ee02020-02-20 20:10:00 +0530243 }
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700244
Anand S Kattib409ee02020-02-20 20:10:00 +0530245 return sonuv2, nil
246}
247
248func getBWPEntries(version string) *BandwidthProfileEntries {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700249 a := strings.Split(common.Config.BBSim.SadisRestAddress, ":")
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100250 port := a[len(a)-1]
251
252 integration := SadisIntegration{}
Anand S Kattib409ee02020-02-20 20:10:00 +0530253 integration.URL = "http://bbsim:" + port + "/" + version + "/bandwidthprofiles/%s"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100254 integration.Cache.Enabled = true
255 integration.Cache.MaxSize = 40
256 integration.Cache.TTL = "PT1m"
257
258 bwp := &BandwidthProfileEntries{
259 Integration: integration,
260 }
261
262 return bwp
263}
264
Matteo Scandolocedde462021-03-09 17:37:16 -0800265func (s *SadisServer) ServeBaseConfig(w http.ResponseWriter, r *http.Request) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100266 w.Header().Set("Content-Type", "application/json")
267 w.WriteHeader(http.StatusOK)
Anand S Kattib409ee02020-02-20 20:10:00 +0530268 vars := mux.Vars(r)
269
270 if vars["version"] != "v1" && vars["version"] != "v2" {
271 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530272 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530273 return
274 }
275
Matteo Scandolocedde462021-03-09 17:37:16 -0800276 sadisConf := GetSadisConfig(s.Olt, vars["version"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100277
278 sadisJSON, _ := json.Marshal(sadisConf)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100279
Shrey Baid688b4242020-07-10 20:40:10 +0530280 _, _ = w.Write([]byte(sadisJSON))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100281
282}
283
Matteo Scandolocedde462021-03-09 17:37:16 -0800284func (s *SadisServer) ServeStaticConfig(w http.ResponseWriter, r *http.Request) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100285 w.Header().Set("Content-Type", "application/json")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700286
Anand S Kattib409ee02020-02-20 20:10:00 +0530287 vars := mux.Vars(r)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700288
289 if vars["version"] == "v1" {
290 // TODO format error
291 http.Error(w, fmt.Sprintf("api-v1-unsupported"), http.StatusBadRequest)
292 return
293 }
294
295 w.WriteHeader(http.StatusOK)
296
Matteo Scandolocedde462021-03-09 17:37:16 -0800297 sadisConf := GetSadisConfig(s.Olt, vars["version"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100298
299 sadisConf.Sadis.Integration.URL = ""
Matteo Scandolocedde462021-03-09 17:37:16 -0800300 for i := range s.Olt.Pons {
301 for _, onu := range s.Olt.Pons[i].Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700302 if vars["version"] == "v2" {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700303 for _, u := range onu.UniPorts {
304 uni := u.(*devices.UniPort)
305 sonuV2, _ := GetOnuEntryV2(s.Olt, onu, fmt.Sprintf("%d", uni.ID+1))
306 sadisConf.Sadis.Entries = append(sadisConf.Sadis.Entries, sonuV2)
307 }
Anand S Kattib409ee02020-02-20 20:10:00 +0530308 }
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100309 }
310 }
311
312 sadisConf.BandwidthProfile.Integration.URL = ""
Matteo Scandolo94967142021-05-28 11:37:06 -0700313 sadisConf.BandwidthProfile.Entries = bandwidthProfiles[common.Config.BBSim.BandwidthProfileFormat]
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100314
315 sadisJSON, _ := json.Marshal(sadisConf)
316 sadisLogger.Tracef("SADIS JSON: %s", sadisJSON)
317
Shrey Baid688b4242020-07-10 20:40:10 +0530318 _, _ = w.Write([]byte(sadisJSON))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100319
320}
321
Matteo Scandolocedde462021-03-09 17:37:16 -0800322func (s *SadisServer) ServeEntry(w http.ResponseWriter, r *http.Request) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100323 w.Header().Set("Content-Type", "application/json")
324 vars := mux.Vars(r)
325
326 // check if the requested ID is for the OLT
Matteo Scandolocedde462021-03-09 17:37:16 -0800327 if s.Olt.SerialNumber == vars["ID"] {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100328 sadisLogger.WithFields(log.Fields{
Matteo Scandolocedde462021-03-09 17:37:16 -0800329 "OltSn": s.Olt.SerialNumber,
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100330 }).Debug("Received SADIS OLT request")
331
Matteo Scandolocedde462021-03-09 17:37:16 -0800332 sadisConf, _ := GetOltEntry(s.Olt)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100333
334 w.WriteHeader(http.StatusOK)
Shrey Baid688b4242020-07-10 20:40:10 +0530335 _ = json.NewEncoder(w).Encode(sadisConf)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100336 return
337 }
338
339 i := strings.Split(vars["ID"], "-") // split ID to get serial number and uni port
340 if len(i) != 2 {
341 w.WriteHeader(http.StatusUnprocessableEntity)
Shrey Baid688b4242020-07-10 20:40:10 +0530342 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530343 sadisLogger.Warnf("Received invalid SADIS SubscriberId: %s", vars["ID"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100344 return
345 }
346 sn, uni := i[0], i[len(i)-1]
347
Matteo Scandolocedde462021-03-09 17:37:16 -0800348 onu, err := s.Olt.FindOnuBySn(sn)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100349 if err != nil {
350 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530351 _, _ = w.Write([]byte("{}"))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100352 sadisLogger.WithFields(log.Fields{
353 "OnuSn": sn,
354 "OnuId": "NA",
Anand S Kattib409ee02020-02-20 20:10:00 +0530355 }).Warnf("Requested Subscriber entry not found for OnuSn: %s", vars["ID"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100356 return
357 }
358
359 sadisLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700360 "OnuId": onu.ID,
361 "OnuSn": sn,
362 "UniId": uni,
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100363 }).Debug("Received SADIS request")
364
Anand S Kattib409ee02020-02-20 20:10:00 +0530365 if vars["version"] == "v1" {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700366 // TODO format error
367 w.WriteHeader(http.StatusBadRequest)
368 _ = json.NewEncoder(w).Encode("Sadis v1 is not supported anymore, please go back to an earlier BBSim version")
Anand S Kattib409ee02020-02-20 20:10:00 +0530369 } else if vars["version"] == "v2" {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700370 w.WriteHeader(http.StatusOK)
Matteo Scandolocedde462021-03-09 17:37:16 -0800371 sadisConf, _ := GetOnuEntryV2(s.Olt, onu, uni)
Shrey Baid688b4242020-07-10 20:40:10 +0530372 _ = json.NewEncoder(w).Encode(sadisConf)
Anand S Kattib409ee02020-02-20 20:10:00 +0530373 }
374
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100375}
376
Matteo Scandolocedde462021-03-09 17:37:16 -0800377func (s *SadisServer) ServeBWPEntry(w http.ResponseWriter, r *http.Request) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100378 w.Header().Set("Content-Type", "application/json")
379 vars := mux.Vars(r)
380 id := vars["ID"]
Anand S Kattib409ee02020-02-20 20:10:00 +0530381
382 if vars["version"] != "v1" && vars["version"] != "v2" {
383 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530384 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530385 return
386 }
387
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100388 sadisLogger.Debugf("Received request for SADIS bandwidth profile %s", id)
389
Matteo Scandolo94967142021-05-28 11:37:06 -0700390 for _, bwpEntry := range bandwidthProfiles[common.Config.BBSim.BandwidthProfileFormat] {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100391 if bwpEntry.ID == id {
392 w.WriteHeader(http.StatusOK)
Shrey Baid688b4242020-07-10 20:40:10 +0530393 _ = json.NewEncoder(w).Encode(bwpEntry)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100394 return
395 }
396 }
397
398 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530399 _, _ = w.Write([]byte("{}"))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100400}