Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 1 | /* |
| 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 | |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 17 | package main |
| 18 | |
| 19 | import ( |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 20 | "log" |
| 21 | "net" |
Zack Williams | 86f8720 | 2018-10-05 10:36:32 -0700 | [diff] [blame^] | 22 | "gerrit.opencord.org/voltha-bbsim/openolt" |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 23 | "google.golang.org/grpc" |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 24 | "fmt" |
| 25 | "flag" |
| 26 | "reflect" |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 27 | "strings" |
| 28 | "strconv" |
| 29 | "sync" |
| 30 | ) |
| 31 | |
| 32 | type server struct{ |
| 33 | olt olt |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 34 | onus map[uint32]map[uint32]*onu |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 35 | } |
| 36 | |
| 37 | |
| 38 | type oltState int |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 39 | type onuState int |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 40 | |
| 41 | const( |
| 42 | PRE_ENABLE oltState = iota |
| 43 | OLT_UP |
| 44 | PONIF_UP |
| 45 | ONU_DISCOVERED |
| 46 | ) |
| 47 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 48 | const( |
| 49 | ONU_PRE_ACTIVATED onuState = iota |
| 50 | ONU_ACTIVATED |
| 51 | ) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 52 | |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 53 | type olt struct { |
| 54 | ID uint32 |
| 55 | NumPonIntf uint32 |
| 56 | NumNniIntf uint32 |
| 57 | Mac string |
| 58 | SerialNumber string |
| 59 | Manufacture string |
| 60 | Name string |
| 61 | internalState oltState |
| 62 | OperState string |
| 63 | Intfs []intf |
| 64 | HeartbeatSignature uint32 |
| 65 | } |
| 66 | |
| 67 | type intf struct{ |
| 68 | Type string |
| 69 | IntfID uint32 |
| 70 | OperState string |
| 71 | } |
| 72 | |
| 73 | type onu struct{ |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 74 | internalState onuState |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 75 | IntfID uint32 |
| 76 | OperState string |
| 77 | SerialNumber *openolt.SerialNumber |
| 78 | } |
| 79 | |
| 80 | func createOlt(oltid uint32, npon uint32, nnni uint32) olt{ |
| 81 | olt := olt {} |
| 82 | olt.ID = oltid |
| 83 | olt.NumPonIntf = npon |
| 84 | olt.NumNniIntf = nnni |
| 85 | olt.Name = "BBSIM OLT" |
| 86 | olt.internalState = PRE_ENABLE |
| 87 | olt.OperState = "up" |
| 88 | olt.Intfs = make([]intf, olt.NumPonIntf + olt.NumNniIntf) |
| 89 | olt.HeartbeatSignature = oltid |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 90 | for i := uint32(0); i < olt.NumNniIntf; i ++ { |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 91 | olt.Intfs[i].IntfID = i |
| 92 | olt.Intfs[i].OperState = "up" |
| 93 | olt.Intfs[i].Type = "nni" |
| 94 | } |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 95 | for i := uint32(olt.NumNniIntf); i < olt.NumPonIntf + olt.NumNniIntf; i ++ { |
| 96 | olt.Intfs[i].IntfID = i |
| 97 | olt.Intfs[i].OperState = "up" |
| 98 | olt.Intfs[i].Type = "pon" |
| 99 | } |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 100 | return olt |
| 101 | } |
| 102 | |
| 103 | func createSN(oltid uint32, intfid uint32, onuid uint32) string{ |
| 104 | sn := fmt.Sprintf("%X%X%02X", oltid, intfid, onuid) |
| 105 | return sn |
| 106 | } |
| 107 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 108 | func createOnus(oltid uint32, intfid uint32, nonus uint32, nnni uint32) map[uint32] *onu { |
| 109 | onus := make(map[uint32] *onu ,nonus) |
| 110 | for onuid := uint32(1 + (intfid - nnni) * nonus); onuid <= (intfid - nnni + 1) * nonus; onuid ++ { |
| 111 | onu := onu{} |
| 112 | onu.internalState = ONU_PRE_ACTIVATED |
| 113 | onu.IntfID = intfid |
| 114 | onu.OperState = "up" |
| 115 | onu.SerialNumber = new(openolt.SerialNumber) |
| 116 | onu.SerialNumber.VendorId = []byte("BRCM") |
| 117 | onu.SerialNumber.VendorSpecific = []byte(createSN(oltid, intfid, uint32(onuid))) //FIX |
| 118 | onus[onuid] = &onu |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 119 | } |
| 120 | return onus |
| 121 | } |
| 122 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 123 | func validateONU(targetonu openolt.Onu, regonus map[uint32]map[uint32] *onu) bool{ |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 124 | for _, onus := range regonus{ |
| 125 | for _, onu := range onus{ |
| 126 | if validateSN(*targetonu.SerialNumber, *onu.SerialNumber){ |
| 127 | return true |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | return false |
| 132 | } |
| 133 | |
| 134 | func validateSN(sn1 openolt.SerialNumber, sn2 openolt.SerialNumber) bool{ |
| 135 | return reflect.DeepEqual(sn1.VendorId, sn2.VendorId) && reflect.DeepEqual(sn1.VendorSpecific, sn2.VendorSpecific) |
| 136 | } |
| 137 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 138 | func isAllONUActive(regonus map[uint32]map[uint32] *onu ) bool{ |
| 139 | for _, onus := range regonus{ |
| 140 | for _, onu := range onus{ |
| 141 | if onu.internalState != ONU_ACTIVATED{ |
| 142 | return false |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | return true |
| 147 | } |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 148 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 149 | func updateOnusOpStatus(ponif uint32, onus map[uint32] *onu, opstatus string){ |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 150 | for i, onu := range onus{ |
| 151 | onu.OperState = "up" |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 152 | log.Printf("(PONIF:%d) ONU [%d] discovered.\n", ponif, i) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
| 156 | func activateOLT(s *server, stream openolt.Openolt_EnableIndicationServer) error{ |
| 157 | // Activate OLT |
| 158 | olt := &s.olt |
| 159 | onus := s.onus |
| 160 | if err := sendOltInd(stream, olt); err != nil { |
| 161 | return err |
| 162 | } |
| 163 | olt.OperState = "up" |
| 164 | olt.internalState = OLT_UP |
| 165 | log.Printf("OLT %s sent OltInd.\n", olt.Name) |
| 166 | |
| 167 | |
| 168 | // OLT sends Interface Indication to Adapter |
| 169 | if err := sendIntfInd(stream, olt); err != nil { |
| 170 | return err |
| 171 | } |
| 172 | log.Printf("OLT %s sent IntfInd.\n", olt.Name) |
| 173 | |
| 174 | // OLT sends Operation Indication to Adapter after activating each interface |
| 175 | //time.Sleep(IF_UP_TIME * time.Second) |
| 176 | olt.internalState = PONIF_UP |
| 177 | if err := sendOperInd(stream, olt); err != nil { |
| 178 | return err |
| 179 | } |
| 180 | log.Printf("OLT %s sent OperInd.\n", olt.Name) |
| 181 | |
| 182 | // OLT sends ONU Discover Indication to Adapter after ONU discovery |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 183 | for intfid := uint32(olt.NumNniIntf); intfid < olt.NumNniIntf + olt.NumPonIntf; intfid ++ { |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 184 | updateOnusOpStatus(intfid, onus[intfid], "up") |
| 185 | } |
| 186 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 187 | for intfid := uint32(olt.NumNniIntf); intfid < olt.NumNniIntf + olt.NumPonIntf; intfid ++ { |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 188 | sendOnuDiscInd(stream, onus[intfid]) |
| 189 | log.Printf("OLT id:%d sent ONUDiscInd.\n", olt.ID) |
| 190 | } |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 191 | |
| 192 | for{ |
| 193 | //log.Printf("stop %v\n", s.onus) |
| 194 | if isAllONUActive(s.onus){ |
| 195 | //log.Printf("break! %v\n", s.onus) |
| 196 | break |
| 197 | } |
| 198 | } |
| 199 | for intfid := uint32(olt.NumNniIntf); intfid < olt.NumNniIntf + olt.NumPonIntf; intfid ++ { |
| 200 | sendOnuInd(stream, onus[intfid]) |
| 201 | log.Printf("OLT id:%d sent ONUInd.\n", olt.ID) |
| 202 | } |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 203 | return nil |
| 204 | } |
| 205 | |
| 206 | func sendOltInd(stream openolt.Openolt_EnableIndicationServer, olt *olt) error{ |
| 207 | data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: "up"}} |
| 208 | if err := stream.Send(&openolt.Indication{Data: data}); err != nil { |
| 209 | log.Printf("Failed to send OLT indication: %v\n", err) |
| 210 | return err |
| 211 | } |
| 212 | return nil |
| 213 | } |
| 214 | |
| 215 | func sendIntfInd(stream openolt.Openolt_EnableIndicationServer, olt *olt) error{ |
| 216 | for i := uint32(0); i < olt.NumPonIntf + olt.NumNniIntf; i ++ { |
| 217 | intf := olt.Intfs[i] |
| 218 | data := &openolt.Indication_IntfInd{&openolt.IntfIndication{IntfId: intf.IntfID, OperState: intf.OperState}} |
| 219 | if err := stream.Send(&openolt.Indication{Data: data}); err != nil { |
| 220 | log.Printf("Failed to send Intf [id: %d] indication : %v\n", i, err) |
| 221 | return err |
| 222 | } |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 223 | log.Printf("SendIntfInd olt:%d intf:%d (%s)\n", olt.ID, intf.IntfID, intf.Type) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 224 | } |
| 225 | return nil |
| 226 | } |
| 227 | |
| 228 | func sendOperInd(stream openolt.Openolt_EnableIndicationServer, olt *olt) error{ |
| 229 | for i := uint32(0); i < olt.NumPonIntf + olt.NumNniIntf; i ++ { |
| 230 | intf := olt.Intfs[i] |
| 231 | data := &openolt.Indication_IntfOperInd{&openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}} |
| 232 | if err := stream.Send(&openolt.Indication{Data: data}); err != nil { |
| 233 | log.Printf("Failed to send IntfOper [id: %d] indication : %v\n", i, err) |
| 234 | return err |
| 235 | } |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 236 | log.Printf("SendOperInd olt:%d intf:%d (%s)\n", olt.ID, intf.IntfID, intf.Type) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 237 | } |
| 238 | return nil |
| 239 | } |
| 240 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 241 | func sendOnuDiscInd(stream openolt.Openolt_EnableIndicationServer, onus map[uint32] *onu) error{ |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 242 | for i, onu := range onus { |
| 243 | data := &openolt.Indication_OnuDiscInd{&openolt.OnuDiscIndication{IntfId: onu.IntfID, SerialNumber:onu.SerialNumber}} |
| 244 | log.Printf("sendONUDiscInd Onuid: %d\n", i) |
| 245 | if err := stream.Send(&openolt.Indication{Data: data}); err != nil { |
| 246 | log.Printf("Failed to send ONUDiscInd [id: %d]: %v\n", i, err) |
| 247 | return err |
| 248 | } |
| 249 | } |
| 250 | return nil |
| 251 | } |
| 252 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 253 | func sendOnuInd(stream openolt.Openolt_EnableIndicationServer, onus map[uint32] *onu) error{ |
| 254 | for i, onu := range onus { |
| 255 | data := &openolt.Indication_OnuInd{&openolt.OnuIndication{IntfId: onu.IntfID, OnuId: uint32(i), OperState: "up", AdminState: "up", SerialNumber:onu.SerialNumber}} |
| 256 | log.Printf("sendONUInd Onuid: %d\n", i) |
| 257 | if err := stream.Send(&openolt.Indication{Data: data}); err != nil { |
| 258 | log.Printf("Failed to send ONUInd [id: %d]: %v\n", i, err) |
| 259 | return err |
| 260 | } |
| 261 | } |
| 262 | return nil |
| 263 | } |
| 264 | |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 265 | func newServer(oltid uint32, npon uint32, nonus uint32) *server{ |
| 266 | s := new(server) |
| 267 | s.olt = createOlt(oltid, npon, 1) |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 268 | nnni := s.olt.NumNniIntf |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 269 | log.Printf("OLT ID: %d was retrieved.\n", s.olt.ID) |
| 270 | |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 271 | s.onus = make(map[uint32]map[uint32] *onu) |
| 272 | for intfid := nnni; intfid < npon + nnni; intfid ++ { |
| 273 | s.onus[intfid] = createOnus(oltid, intfid, nonus, nnni) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 274 | } |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 275 | //log.Printf("s.onus: %v\n", s.onus) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 276 | return s |
| 277 | } |
| 278 | |
| 279 | func printBanner(){ |
| 280 | log.Println(" ________ _______ ________ ") |
| 281 | log.Println(" / ____ | / ____ | / ______/ __ ") |
| 282 | log.Println(" / /____/ / / /____/ / / /_____ /_/ ") |
| 283 | log.Println(" / _____ | / _____ | /______ | __ __________ ") |
| 284 | log.Println(" / /____/ / / /____/ / _______/ / / / / __ __ / ") |
| 285 | log.Println("/________/ /________/ /________/ /_/ /_/ /_/ /_/ ") |
| 286 | } |
| 287 | |
| 288 | func getOptions()(string, uint32, uint32, uint32, uint32){ |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 289 | addressport := flag.String("H","127.0.0.1:50060","IP address:port") |
| 290 | nolts := flag.Int("N", 1, "Number of OLTs") |
| 291 | nports := flag.Int("i", 1, "Number of PON-IF ports") |
| 292 | nonus := flag.Int("n", 1, "Number of ONUs per PON-IF port") |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 293 | flag.Parse() |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 294 | fmt.Printf("%v\n", *addressport) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 295 | //fmt.Println("nports:", *nports, "nonus:", *nonus) |
Keita NISHIMOTO | 26dab09 | 2018-07-06 09:52:45 +0900 | [diff] [blame] | 296 | address := strings.Split(*addressport, ":")[0] |
| 297 | port,_ := strconv.Atoi(strings.Split(*addressport, ":")[1]) |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 298 | return address, uint32(port), uint32(*nolts), uint32(*nports), uint32(*nonus) |
| 299 | } |
| 300 | |
| 301 | |
Keita NISHIMOTO | d771cd1 | 2018-06-07 08:37:24 +0900 | [diff] [blame] | 302 | func main() { |
| 303 | printBanner() |
| 304 | ipaddress, baseport, nolts, npon, nonus := getOptions() |
| 305 | log.Printf("ip:%s, baseport:%d, nolts:%d, npon:%d, nonus:%d\n", ipaddress, baseport, nolts, npon, nonus) |
| 306 | servers := make([] *server, nolts) |
| 307 | grpcservers := make([] *grpc.Server, nolts) |
| 308 | lis := make([] net.Listener, nolts) |
| 309 | var wg sync.WaitGroup |
| 310 | wg.Add(int(nolts)) |
| 311 | for oltid := uint32(0); oltid < nolts; oltid ++ { |
| 312 | portnum := baseport + oltid |
| 313 | addressport := ipaddress + ":" + strconv.Itoa(int(portnum)) |
| 314 | log.Printf("Listening %s ...", addressport) |
| 315 | lis[oltid], _ = net.Listen("tcp", addressport) |
| 316 | servers[oltid] = newServer(oltid, npon, nonus) |
| 317 | grpcservers[oltid] = grpc.NewServer() |
| 318 | openolt.RegisterOpenoltServer(grpcservers[oltid], servers[oltid]) |
| 319 | go grpcservers[oltid].Serve(lis[oltid]) |
| 320 | } |
| 321 | wg.Wait() |
| 322 | } |