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