blob: 444fd57432b42dfa52ee254cac35fe562166a1e0 [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"
21 "net/http"
22 "strings"
23 "sync"
24
25 "github.com/gorilla/mux"
26 "github.com/opencord/bbsim/internal/bbsim/devices"
27 "github.com/opencord/bbsim/internal/common"
28 log "github.com/sirupsen/logrus"
29)
30
31var sadisLogger = log.WithFields(log.Fields{
32 "module": "SADIS",
33})
34
35type sadisServer struct {
36 olt *devices.OltDevice
37}
38
39// bandwidthProfiles contains some dummy profiles
Matteo Scandolo51d6a312020-03-12 15:54:43 -070040var bandwidthProfiles = []*SadisBWPEntry{
Shrey Baid688b4242020-07-10 20:40:10 +053041 {ID: "User_Bandwidth1", AIR: 100000, CBS: 10000, CIR: 30000, EBS: 1000, EIR: 100000},
42 {ID: "User_Bandwidth2", AIR: 100000, CBS: 5000, CIR: 100000, EBS: 5000, EIR: 100000},
43 {ID: "User_Bandwidth3", AIR: 100000, CBS: 5000, CIR: 1000000, EBS: 5000, EIR: 1000000},
44 {ID: "Default", AIR: 100000, CBS: 30, CIR: 600, EBS: 30, EIR: 400},
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010045}
46
47// SadisConfig is the top-level SADIS configuration struct
48type SadisConfig struct {
49 Sadis SadisEntries `json:"sadis"`
50 BandwidthProfile BandwidthProfileEntries `json:"bandwidthprofile"`
51}
52
53type SadisEntries struct {
54 Integration SadisIntegration `json:"integration"`
55 Entries []interface{} `json:"entries,omitempty"`
56}
57type BandwidthProfileEntries struct {
58 Integration SadisIntegration `json:"integration"`
Matteo Scandolo51d6a312020-03-12 15:54:43 -070059 Entries []*SadisBWPEntry `json:"entries,omitempty"`
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010060}
61
62type SadisIntegration struct {
63 URL string `json:"url,omitempty"`
64 Cache struct {
65 Enabled bool `json:"enabled"`
66 MaxSize int `json:"maxsize"`
67 TTL string `json:"ttl"`
68 } `json:"cache"`
69}
70
71type SadisOltEntry struct {
72 ID string `json:"id"`
73 HardwareIdentifier string `json:"hardwareIdentifier"`
74 IPAddress string `json:"ipAddress"`
75 NasID string `json:"nasId"`
76 UplinkPort int `json:"uplinkPort"`
77}
78
Anand S Kattib409ee02020-02-20 20:10:00 +053079type SadisOnuEntryV2 struct {
80 ID string `json:"id"`
81 NasPortID string `json:"nasPortId"`
82 CircuitID string `json:"circuitId"`
83 RemoteID string `json:"remoteId"`
Matteo Scandolo4a036262020-08-17 15:56:13 -070084 UniTagList []SadisUniTag `json:"uniTagList"` // this can be SadisUniTagAtt, SadisUniTagDt
Anand S Kattib409ee02020-02-20 20:10:00 +053085}
86
Matteo Scandolo4a036262020-08-17 15:56:13 -070087type SadisUniTag struct {
88 UniTagMatch int `json:"uniTagMatch,omitempty"`
Shrey Baid688b4242020-07-10 20:40:10 +053089 PonCTag int `json:"ponCTag,omitempty"`
90 PonSTag int `json:"ponSTag,omitempty"`
91 TechnologyProfileID int `json:"technologyProfileId,omitempty"`
92 UpstreamBandwidthProfile string `json:"upstreamBandwidthProfile,omitempty"`
93 DownstreamBandwidthProfile string `json:"downstreamBandwidthProfile,omitempty"`
94 IsDhcpRequired bool `json:"isDhcpRequired,omitempty"`
95 IsIgmpRequired bool `json:"isIgmpRequired,omitempty"`
Matteo Scandolo4a036262020-08-17 15:56:13 -070096 ConfiguredMacAddress string `json:"configuredMacAddress,omitempty"`
97 UsPonCTagPriority int `json:"usPonCTagPriority,omitempty"`
98 UsPonSTagPriority int `json:"usPonSTagPriority,omitempty"`
99 DsPonCTagPriority int `json:"dsPonCTagPriority,omitempty"`
100 DsPonSTagPriority int `json:"dsPonSTagPriority,omitempty"`
101 ServiceName string `json:"serviceName,omitempty"`
Matteo Scandolof65e6872020-04-15 15:18:43 -0700102}
103
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100104// SADIS BandwithProfile Entry
105type SadisBWPEntry struct {
106 ID string `json:"id"`
107 AIR int `json:"air"`
108 CBS int `json:"cbs"`
109 CIR int `json:"cir"`
110 EBS int `json:"ebs"`
111 EIR int `json:"eir"`
112}
113
114// GetSadisConfig returns a full SADIS configuration struct ready to be marshalled into JSON
Anand S Kattib409ee02020-02-20 20:10:00 +0530115func GetSadisConfig(olt *devices.OltDevice, version string) *SadisConfig {
116 sadisEntries, _ := GetSadisEntries(olt, version)
117 bwpEntries := getBWPEntries(version)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100118
119 conf := &SadisConfig{}
120 conf.Sadis = *sadisEntries
121 conf.BandwidthProfile = *bwpEntries
122
123 return conf
124}
125
Anand S Kattib409ee02020-02-20 20:10:00 +0530126func GetSadisEntries(olt *devices.OltDevice, version string) (*SadisEntries, error) {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100127 solt, _ := GetOltEntry(olt)
128
129 entries := []interface{}{}
130 entries = append(entries, solt)
131
Matteo Scandolo4a036262020-08-17 15:56:13 -0700132 a := strings.Split(common.Config.BBSim.SadisRestAddress, ":")
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100133 port := a[len(a)-1]
134
135 integration := SadisIntegration{}
Anand S Kattib409ee02020-02-20 20:10:00 +0530136 integration.URL = "http://bbsim:" + port + "/" + version + "/subscribers/%s"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100137 integration.Cache.Enabled = false
138 integration.Cache.MaxSize = 50
139 integration.Cache.TTL = "PT0m"
140
141 sadis := &SadisEntries{
142 integration,
143 entries,
144 }
145
146 return sadis, nil
147}
148
149func GetOltEntry(olt *devices.OltDevice) (*SadisOltEntry, error) {
150 ip, _ := common.GetIPAddr("nni") // TODO verify which IP to report
151 solt := &SadisOltEntry{
152 ID: olt.SerialNumber,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700153 HardwareIdentifier: common.Config.Olt.DeviceId,
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100154 IPAddress: ip,
155 NasID: olt.SerialNumber,
Anand S Kattib409ee02020-02-20 20:10:00 +0530156 UplinkPort: 1048576, // TODO currently assumes we only have one NNI port
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100157 }
158 return solt, nil
159}
160
Anand S Kattib409ee02020-02-20 20:10:00 +0530161func GetOnuEntryV2(olt *devices.OltDevice, onu *devices.Onu, uniId string) (*SadisOnuEntryV2, error) {
162 uniSuffix := "-" + uniId
163
164 sonuv2 := &SadisOnuEntryV2{
165 ID: onu.Sn() + uniSuffix,
166 NasPortID: onu.Sn() + uniSuffix,
167 CircuitID: onu.Sn() + uniSuffix,
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700168 RemoteID: onu.Sn() + uniSuffix,
Anand S Kattib409ee02020-02-20 20:10:00 +0530169 }
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700170
Matteo Scandolo4a036262020-08-17 15:56:13 -0700171 // createUniTagList
172 for _, s := range onu.Services {
Matteo Scandolof65e6872020-04-15 15:18:43 -0700173
Matteo Scandolo4a036262020-08-17 15:56:13 -0700174 service := s.(*devices.Service)
175
176 tag := SadisUniTag{
177 ServiceName: service.Name,
178 IsIgmpRequired: service.NeedsIgmp,
179 IsDhcpRequired: service.NeedsDhcp,
180 TechnologyProfileID: service.TechnologyProfileID,
181 UpstreamBandwidthProfile: "User_Bandwidth1",
182 DownstreamBandwidthProfile: "User_Bandwidth2",
183 PonCTag: service.CTag,
184 PonSTag: service.STag,
Matteo Scandolof65e6872020-04-15 15:18:43 -0700185 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700186
187 if service.UniTagMatch != 0 {
188 tag.UniTagMatch = service.UniTagMatch
Matteo Scandolof65e6872020-04-15 15:18:43 -0700189 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700190
191 if service.ConfigureMacAddress {
192 tag.ConfiguredMacAddress = service.HwAddress.String()
193 }
194
195 if service.UsPonCTagPriority != 0 {
196 tag.UsPonCTagPriority = service.UsPonCTagPriority
197 }
198
199 if service.UsPonSTagPriority != 0 {
200 tag.UsPonSTagPriority = service.UsPonSTagPriority
201 }
202
203 if service.DsPonCTagPriority != 0 {
204 tag.DsPonCTagPriority = service.DsPonCTagPriority
205 }
206
207 if service.DsPonSTagPriority != 0 {
208 tag.DsPonSTagPriority = service.DsPonSTagPriority
209 }
210
211 sonuv2.UniTagList = append(sonuv2.UniTagList, tag)
Anand S Kattib409ee02020-02-20 20:10:00 +0530212 }
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700213
Anand S Kattib409ee02020-02-20 20:10:00 +0530214 return sonuv2, nil
215}
216
217func getBWPEntries(version string) *BandwidthProfileEntries {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700218 a := strings.Split(common.Config.BBSim.SadisRestAddress, ":")
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100219 port := a[len(a)-1]
220
221 integration := SadisIntegration{}
Anand S Kattib409ee02020-02-20 20:10:00 +0530222 integration.URL = "http://bbsim:" + port + "/" + version + "/bandwidthprofiles/%s"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100223 integration.Cache.Enabled = true
224 integration.Cache.MaxSize = 40
225 integration.Cache.TTL = "PT1m"
226
227 bwp := &BandwidthProfileEntries{
228 Integration: integration,
229 }
230
231 return bwp
232}
233
234func (s *sadisServer) ServeBaseConfig(w http.ResponseWriter, r *http.Request) {
235 w.Header().Set("Content-Type", "application/json")
236 w.WriteHeader(http.StatusOK)
Anand S Kattib409ee02020-02-20 20:10:00 +0530237 vars := mux.Vars(r)
238
239 if vars["version"] != "v1" && vars["version"] != "v2" {
240 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530241 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530242 return
243 }
244
245 sadisConf := GetSadisConfig(s.olt, vars["version"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100246
247 sadisJSON, _ := json.Marshal(sadisConf)
248 sadisLogger.Tracef("SADIS JSON: %s", sadisJSON)
249
Shrey Baid688b4242020-07-10 20:40:10 +0530250 _, _ = w.Write([]byte(sadisJSON))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100251
252}
253
254func (s *sadisServer) ServeStaticConfig(w http.ResponseWriter, r *http.Request) {
255 w.Header().Set("Content-Type", "application/json")
256 w.WriteHeader(http.StatusOK)
Anand S Kattib409ee02020-02-20 20:10:00 +0530257 vars := mux.Vars(r)
258 sadisConf := GetSadisConfig(s.olt, vars["version"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100259
260 sadisConf.Sadis.Integration.URL = ""
261 for i := range s.olt.Pons {
262 for _, onu := range s.olt.Pons[i].Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700263 if vars["version"] == "v2" {
Anand S Kattib409ee02020-02-20 20:10:00 +0530264 sonuV2, _ := GetOnuEntryV2(s.olt, onu, "1")
265 sadisConf.Sadis.Entries = append(sadisConf.Sadis.Entries, sonuV2)
Anand S Kattib409ee02020-02-20 20:10:00 +0530266 }
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100267 }
268 }
269
270 sadisConf.BandwidthProfile.Integration.URL = ""
271 sadisConf.BandwidthProfile.Entries = bandwidthProfiles
272
273 sadisJSON, _ := json.Marshal(sadisConf)
274 sadisLogger.Tracef("SADIS JSON: %s", sadisJSON)
275
Shrey Baid688b4242020-07-10 20:40:10 +0530276 _, _ = w.Write([]byte(sadisJSON))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100277
278}
279
280func (s *sadisServer) ServeEntry(w http.ResponseWriter, r *http.Request) {
281 w.Header().Set("Content-Type", "application/json")
282 vars := mux.Vars(r)
283
284 // check if the requested ID is for the OLT
285 if s.olt.SerialNumber == vars["ID"] {
286 sadisLogger.WithFields(log.Fields{
287 "OltSn": s.olt.SerialNumber,
288 }).Debug("Received SADIS OLT request")
289
290 sadisConf, _ := GetOltEntry(s.olt)
291
292 w.WriteHeader(http.StatusOK)
Shrey Baid688b4242020-07-10 20:40:10 +0530293 _ = json.NewEncoder(w).Encode(sadisConf)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100294 return
295 }
296
297 i := strings.Split(vars["ID"], "-") // split ID to get serial number and uni port
298 if len(i) != 2 {
299 w.WriteHeader(http.StatusUnprocessableEntity)
Shrey Baid688b4242020-07-10 20:40:10 +0530300 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530301 sadisLogger.Warnf("Received invalid SADIS SubscriberId: %s", vars["ID"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100302 return
303 }
304 sn, uni := i[0], i[len(i)-1]
305
306 onu, err := s.olt.FindOnuBySn(sn)
307 if err != nil {
308 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530309 _, _ = w.Write([]byte("{}"))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100310 sadisLogger.WithFields(log.Fields{
311 "OnuSn": sn,
312 "OnuId": "NA",
Anand S Kattib409ee02020-02-20 20:10:00 +0530313 }).Warnf("Requested Subscriber entry not found for OnuSn: %s", vars["ID"])
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100314 return
315 }
316
317 sadisLogger.WithFields(log.Fields{
318 "OnuId": onu.ID,
319 "OnuSn": sn,
320 "OnuPortNo": uni,
321 }).Debug("Received SADIS request")
322
Anand S Kattib409ee02020-02-20 20:10:00 +0530323 if vars["version"] == "v1" {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700324 // TODO format error
325 w.WriteHeader(http.StatusBadRequest)
326 _ = 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 +0530327 } else if vars["version"] == "v2" {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700328 w.WriteHeader(http.StatusOK)
Anand S Kattib409ee02020-02-20 20:10:00 +0530329 sadisConf, _ := GetOnuEntryV2(s.olt, onu, uni)
Shrey Baid688b4242020-07-10 20:40:10 +0530330 _ = json.NewEncoder(w).Encode(sadisConf)
Anand S Kattib409ee02020-02-20 20:10:00 +0530331 }
332
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100333}
334
335func (s *sadisServer) ServeBWPEntry(w http.ResponseWriter, r *http.Request) {
336 w.Header().Set("Content-Type", "application/json")
337 vars := mux.Vars(r)
338 id := vars["ID"]
Anand S Kattib409ee02020-02-20 20:10:00 +0530339
340 if vars["version"] != "v1" && vars["version"] != "v2" {
341 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530342 _, _ = w.Write([]byte("{}"))
Anand S Kattib409ee02020-02-20 20:10:00 +0530343 return
344 }
345
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100346 sadisLogger.Debugf("Received request for SADIS bandwidth profile %s", id)
347
Matteo Scandolo51d6a312020-03-12 15:54:43 -0700348 for _, bwpEntry := range bandwidthProfiles {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100349 if bwpEntry.ID == id {
350 w.WriteHeader(http.StatusOK)
Shrey Baid688b4242020-07-10 20:40:10 +0530351 _ = json.NewEncoder(w).Encode(bwpEntry)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100352 return
353 }
354 }
355
356 w.WriteHeader(http.StatusNotFound)
Shrey Baid688b4242020-07-10 20:40:10 +0530357 _, _ = w.Write([]byte("{}"))
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100358}
359
360// StartRestServer starts REST server which returns a SADIS configuration for the currently simulated OLT
361func StartRestServer(olt *devices.OltDevice, wg *sync.WaitGroup) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700362 addr := common.Config.BBSim.SadisRestAddress
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100363 sadisLogger.Infof("SADIS server listening on %s", addr)
364 s := &sadisServer{
365 olt: olt,
366 }
367
368 router := mux.NewRouter().StrictSlash(true)
Anand S Kattib409ee02020-02-20 20:10:00 +0530369 router.HandleFunc("/{version}/cfg", s.ServeBaseConfig)
370 router.HandleFunc("/{version}/static", s.ServeStaticConfig)
371 router.HandleFunc("/{version}/subscribers/{ID}", s.ServeEntry)
372 router.HandleFunc("/{version}/bandwidthprofiles/{ID}", s.ServeBWPEntry)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100373
374 log.Fatal(http.ListenAndServe(addr, router))
375
376 wg.Done()
377}