blob: e7618f9abb118903a0322054e545f5b9ecf9f917 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
Matteo Scandolo9f619492019-10-25 13:11:58 -07002* Copyright 2018-present Open Networking Foundation
Matteo Scandolo11006992019-08-28 11:29:46 -07003
Matteo Scandolo9f619492019-10-25 13:11:58 -07004* 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
Matteo Scandolo11006992019-08-28 11:29:46 -07007
Matteo Scandolo9f619492019-10-25 13:11:58 -07008* http://www.apache.org/licenses/LICENSE-2.0
Matteo Scandolo11006992019-08-28 11:29:46 -07009
Matteo Scandolo9f619492019-10-25 13:11:58 -070010* 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.
Matteo Scandolo11006992019-08-28 11:29:46 -070015 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package main
18
19import (
Zdravko Bozakov2da76342019-10-21 09:47:35 +020020 "context"
21 "net"
22 "net/http"
23 "os"
24 "os/signal"
25 "runtime/pprof"
26 "sync"
27 "syscall"
28
Shrey Baid64cda472020-04-24 18:58:18 +053029 "github.com/Shopify/sarama"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020030 "github.com/grpc-ecosystem/grpc-gateway/runtime"
Matteo Scandolo11006992019-08-28 11:29:46 -070031 "github.com/opencord/bbsim/api/bbsim"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020032 "github.com/opencord/bbsim/api/legacy"
Matteo Scandolo82c16d02019-09-24 09:34:32 -070033 "github.com/opencord/bbsim/internal/bbsim/api"
Matteo Scandolo11006992019-08-28 11:29:46 -070034 "github.com/opencord/bbsim/internal/bbsim/devices"
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010035 "github.com/opencord/bbsim/internal/bbsim/responders/sadis"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070036 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 log "github.com/sirupsen/logrus"
Matteo Scandolo84f7d482019-08-08 19:00:47 -070038 "google.golang.org/grpc"
39 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070040)
41
Zdravko Bozakov681364d2019-11-10 14:28:46 +010042func startApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010043 address := common.Options.BBSim.ApiAddress
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010044 log.Debugf("APIServer listening on %v", address)
Matteo Scandolo84f7d482019-08-08 19:00:47 -070045 lis, err := net.Listen("tcp", address)
46 if err != nil {
47 log.Fatalf("APIServer failed to listen: %v", err)
48 }
49 grpcServer := grpc.NewServer()
Matteo Scandolo82c16d02019-09-24 09:34:32 -070050 bbsim.RegisterBBSimServer(grpcServer, api.BBSimServer{})
Matteo Scandolo84f7d482019-08-08 19:00:47 -070051
52 reflection.Register(grpcServer)
53
Shrey Baid688b4242020-07-10 20:40:10 +053054 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov681364d2019-11-10 14:28:46 +010055 go startApiRestServer(apiDoneChannel, group, address)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070056
Shrey Baid688b4242020-07-10 20:40:10 +053057 x := <-apiDoneChannel
58 if x {
Zdravko Bozakov681364d2019-11-10 14:28:46 +010059 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +020060 grpcServer.Stop()
61 log.Warnf("Stopping API gRPC server")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070062 }
63
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070064 group.Done()
Zdravko Bozakov2da76342019-10-21 09:47:35 +020065}
66
67// startApiRestServer method starts the REST server (grpc gateway) for BBSim.
Zdravko Bozakov681364d2019-11-10 14:28:46 +010068func startApiRestServer(apiDoneChannel chan bool, group *sync.WaitGroup, grpcAddress string) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +020069 ctx := context.Background()
70 ctx, cancel := context.WithCancel(ctx)
71 defer cancel()
72
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010073 address := common.Options.BBSim.RestApiAddress
Zdravko Bozakov2da76342019-10-21 09:47:35 +020074
75 mux := runtime.NewServeMux()
76 opts := []grpc.DialOption{grpc.WithInsecure()}
77
78 if err := bbsim.RegisterBBSimHandlerFromEndpoint(ctx, mux, grpcAddress, opts); err != nil {
79 log.Errorf("Could not register API server: %v", err)
80 return
81 }
82
83 s := &http.Server{Addr: address, Handler: mux}
84
85 go func() {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010086 log.Infof("REST API server listening on %s", address)
Zdravko Bozakov2da76342019-10-21 09:47:35 +020087 if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
88 log.Errorf("Could not start API server: %v", err)
89 return
90 }
91 }()
92
Shrey Baid688b4242020-07-10 20:40:10 +053093 x := <-apiDoneChannel
94 if x {
Zdravko Bozakov2da76342019-10-21 09:47:35 +020095 log.Warnf("Stopping API REST server")
Shrey Baid688b4242020-07-10 20:40:10 +053096 _ = s.Shutdown(ctx)
Zdravko Bozakov2da76342019-10-21 09:47:35 +020097 }
98
99 group.Done()
100}
101
102// This server aims to provide compatibility with the previous BBSim version. It is deprecated and will be removed in the future.
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100103func startLegacyApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100104 grpcAddress := common.Options.BBSim.LegacyApiAddress
105 restAddress := common.Options.BBSim.LegacyRestApiAddress
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200106
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100107 log.Debugf("Legacy APIServer listening on %v", grpcAddress)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200108 listener, err := net.Listen("tcp", grpcAddress)
109 if err != nil {
110 log.Fatalf("Legacy APIServer failed to listen: %v", err)
111 return
112 }
113 apiserver := grpc.NewServer()
114 legacy.RegisterBBSimServiceServer(apiserver, api.BBSimLegacyServer{})
115
Shrey Baid688b4242020-07-10 20:40:10 +0530116 go func() { _ = apiserver.Serve(listener) }()
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200117 // Start rest gateway for BBSim server
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100118 go api.StartRestGatewayService(apiDoneChannel, group, grpcAddress, restAddress)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200119
Shrey Baid688b4242020-07-10 20:40:10 +0530120 x := <-apiDoneChannel
121 if x {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100122 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200123 log.Warnf("Stopping legacy API gRPC server")
124 apiserver.Stop()
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200125 }
126
127 group.Done()
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700128}
129
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130func main() {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100131
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700132 options := common.GetBBSimOpts()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100134 common.SetLogLevel(log.StandardLogger(), options.BBSim.LogLevel, options.BBSim.LogCaller)
135 log.Tracef("BBSim options: %+v", options)
Matteo Scandolo2bf742a2019-10-01 11:33:34 -0700136
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100137 if *options.BBSim.CpuProfile != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700138 // start profiling
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100139 log.Infof("Creating profile file at: %s", *options.BBSim.CpuProfile)
140 f, err := os.Create(*options.BBSim.CpuProfile)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700141 if err != nil {
142 log.Fatal(err)
143 }
Shrey Baid688b4242020-07-10 20:40:10 +0530144 _ = pprof.StartCPUProfile(f)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700145 }
146
Matteo Scandolo4747d292019-08-05 11:50:18 -0700147 log.WithFields(log.Fields{
Pragya Arya2225f202020-01-29 18:05:01 +0530148 "OltID": options.Olt.ID,
149 "NumNniPerOlt": options.Olt.NniPorts,
150 "NumPonPerOlt": options.Olt.PonPorts,
151 "NumOnuPerPon": options.Olt.OnusPonPort,
152 "TotalOnus": options.Olt.PonPorts * options.Olt.OnusPonPort,
153 "EnableAuth": options.BBSim.EnableAuth,
154 "Dhcp": options.BBSim.EnableDhcp,
Shrey Baide72b3cc2020-05-12 00:03:06 +0530155 "Igmp": options.BBSim.EnableIgmp,
Pragya Arya2225f202020-01-29 18:05:01 +0530156 "Delay": options.BBSim.Delay,
Pragya Arya324337e2020-02-20 14:35:08 +0530157 "Events": options.BBSim.Events,
Shrey Baid64cda472020-04-24 18:58:18 +0530158 "KafkaEventTopic": options.BBSim.KafkaEventTopic,
Pragya Arya2225f202020-01-29 18:05:01 +0530159 "ControlledActivation": options.BBSim.ControlledActivation,
Anand S Katti09541352020-01-29 15:54:01 +0530160 "EnablePerf": options.BBSim.EnablePerf,
Matteo Scandolof65e6872020-04-15 15:18:43 -0700161 "CTag": options.BBSim.CTag,
162 "CTagAllocation": options.BBSim.CTagAllocation,
163 "STag": options.BBSim.STag,
164 "STagAllocation": options.BBSim.STagAllocation,
165 "SadisFormat": options.BBSim.SadisFormat,
Shrey Baidf8abccc2020-06-15 19:41:22 +0530166 "DhcpRetry": options.BBSim.DhcpRetry,
167 "AuthRetry": options.BBSim.AuthRetry,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700168 }).Info("BroadBand Simulator is on")
169
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700170 // control channels, they are only closed when the goroutine needs to be terminated
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700171 apiDoneChannel := make(chan bool)
172
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100173 olt := devices.CreateOLT(
Pragya Arya996a0892020-03-09 21:47:52 +0530174 *options,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700175 false,
176 )
Matteo Scandoloe33447a2019-10-31 12:38:23 -0700177
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100178 log.Debugf("Created OLT with id: %d", options.Olt.ID)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100179
180 sigs := make(chan os.Signal, 1)
181 // stop API servers on SIGTERM
182 signal.Notify(sigs, syscall.SIGTERM)
183
184 go func() {
185 <-sigs
186 close(apiDoneChannel)
187 }()
188
189 wg := sync.WaitGroup{}
190 wg.Add(4)
191
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700192 go startApiServer(apiDoneChannel, &wg)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200193 go startLegacyApiServer(apiDoneChannel, &wg)
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700194 log.Debugf("Started APIService")
Shrey Baid688b4242020-07-10 20:40:10 +0530195 if common.Options.BBSim.SadisServer {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100196 wg.Add(1)
197 go sadis.StartRestServer(olt, &wg)
198 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700199
Pragya Arya324337e2020-02-20 14:35:08 +0530200 if options.BBSim.Events {
201 // initialize a publisher
Shrey Baid64cda472020-04-24 18:58:18 +0530202 if err := common.InitializePublisher(sarama.NewAsyncProducer, olt.ID); err == nil {
Pragya Arya324337e2020-02-20 14:35:08 +0530203 // start a go routine which will read from channel and publish on kafka
204 go common.KafkaPublisher(olt.EventChannel)
205 } else {
206 log.Errorf("Failed to start kafka publisher: %v", err)
207 }
208 }
209
Matteo Scandolo4747d292019-08-05 11:50:18 -0700210 wg.Wait()
211
212 defer func() {
213 log.Info("BroadBand Simulator is off")
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100214 if *options.BBSim.CpuProfile != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700215 log.Info("Stopping profiler")
216 pprof.StopCPUProfile()
217 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700218 }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700219}