blob: 2466dbb94a43744b94a35a77e95f686db474ee45 [file] [log] [blame]
Keita NISHIMOTOd771cd12018-06-07 08:37:24 +09001package main
2
3import (
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
18type server struct{
19 olt olt
20 onus map[uint32][]onu
21}
22
23
24type oltState int
25
26const(
27 PRE_ENABLE oltState = iota
28 OLT_UP
29 PONIF_UP
30 ONU_DISCOVERED
31)
32
33
34//a
35type 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
49type intf struct{
50 Type string
51 IntfID uint32
52 OperState string
53}
54
55type onu struct{
56 IntfID uint32
57 OperState string
58 SerialNumber *openolt.SerialNumber
59}
60
61func 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
84func createSN(oltid uint32, intfid uint32, onuid uint32) string{
85 sn := fmt.Sprintf("%X%X%02X", oltid, intfid, onuid)
86 return sn
87}
88
89func 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
101func 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
112func 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
117func 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
124func 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
163func 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
172func 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
184func 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
196func 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
208func 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
220func printBanner(){
221 log.Println(" ________ _______ ________ ")
222 log.Println(" / ____ | / ____ | / ______/ __ ")
223 log.Println(" / /____/ / / /____/ / / /_____ /_/ ")
224 log.Println(" / _____ | / _____ | /______ | __ __________ ")
225 log.Println(" / /____/ / / /____/ / _______/ / / / / __ __ / ")
226 log.Println("/________/ /________/ /________/ /_/ /_/ /_/ /_/ ")
227}
228
229func 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
247func (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
256func (s *server)OmciMsgOut(c context.Context, msg *openolt.OmciMsg)(*openolt.Empty, error){
257 return new(openolt.Empty), nil
258}
259
260func (s *server) OnuPacketOut(c context.Context, packet *openolt.OnuPacket)(*openolt.Empty, error){
261 return new(openolt.Empty), nil
262}
263
264func (s *server) FlowAdd(c context.Context, flow *openolt.Flow)(*openolt.Empty, error){
265 return new(openolt.Empty), nil
266}
267
268func (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
283func (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
290func 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}