Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 1 | /* |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 2 | * Copyright 2018-present Open Networking Foundation |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 3 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 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 |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 7 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 9 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 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. |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 17 | package main |
| 18 | |
| 19 | import ( |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 20 | "context" |
| 21 | "net" |
| 22 | "net/http" |
| 23 | "os" |
| 24 | "os/signal" |
| 25 | "runtime/pprof" |
| 26 | "sync" |
| 27 | "syscall" |
| 28 | |
Shrey Baid | 64cda47 | 2020-04-24 18:58:18 +0530 | [diff] [blame] | 29 | "github.com/Shopify/sarama" |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 30 | "github.com/grpc-ecosystem/grpc-gateway/runtime" |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 31 | "github.com/opencord/bbsim/api/bbsim" |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 32 | "github.com/opencord/bbsim/api/legacy" |
Matteo Scandolo | 82c16d0 | 2019-09-24 09:34:32 -0700 | [diff] [blame] | 33 | "github.com/opencord/bbsim/internal/bbsim/api" |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 34 | "github.com/opencord/bbsim/internal/bbsim/devices" |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 35 | "github.com/opencord/bbsim/internal/bbsim/responders/sadis" |
Matteo Scandolo | 40e067f | 2019-10-16 16:59:41 -0700 | [diff] [blame] | 36 | "github.com/opencord/bbsim/internal/common" |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 37 | log "github.com/sirupsen/logrus" |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 38 | "google.golang.org/grpc" |
| 39 | "google.golang.org/grpc/reflection" |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 40 | ) |
| 41 | |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 42 | func startApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) { |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 43 | address := common.Options.BBSim.ApiAddress |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 44 | log.Debugf("APIServer listening on %v", address) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 45 | 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 Scandolo | 82c16d0 | 2019-09-24 09:34:32 -0700 | [diff] [blame] | 50 | bbsim.RegisterBBSimServer(grpcServer, api.BBSimServer{}) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 51 | |
| 52 | reflection.Register(grpcServer) |
| 53 | |
| 54 | go grpcServer.Serve(lis) |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 55 | go startApiRestServer(apiDoneChannel, group, address) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 56 | |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 57 | select { |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 58 | case <-apiDoneChannel: |
| 59 | // if the API channel is closed, stop the gRPC server |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 60 | grpcServer.Stop() |
| 61 | log.Warnf("Stopping API gRPC server") |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 62 | } |
| 63 | |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 64 | group.Done() |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | // startApiRestServer method starts the REST server (grpc gateway) for BBSim. |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 68 | func startApiRestServer(apiDoneChannel chan bool, group *sync.WaitGroup, grpcAddress string) { |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 69 | ctx := context.Background() |
| 70 | ctx, cancel := context.WithCancel(ctx) |
| 71 | defer cancel() |
| 72 | |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 73 | address := common.Options.BBSim.RestApiAddress |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 74 | |
| 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 Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 86 | log.Infof("REST API server listening on %s", address) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 87 | if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
| 88 | log.Errorf("Could not start API server: %v", err) |
| 89 | return |
| 90 | } |
| 91 | }() |
| 92 | |
| 93 | select { |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 94 | case <-apiDoneChannel: |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 95 | log.Warnf("Stopping API REST server") |
| 96 | s.Shutdown(ctx) |
| 97 | } |
| 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 Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 103 | func startLegacyApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) { |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 104 | grpcAddress := common.Options.BBSim.LegacyApiAddress |
| 105 | restAddress := common.Options.BBSim.LegacyRestApiAddress |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 106 | |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 107 | log.Debugf("Legacy APIServer listening on %v", grpcAddress) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 108 | 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 | |
| 116 | go apiserver.Serve(listener) |
| 117 | // Start rest gateway for BBSim server |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 118 | go api.StartRestGatewayService(apiDoneChannel, group, grpcAddress, restAddress) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 119 | |
| 120 | select { |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 121 | case <-apiDoneChannel: |
| 122 | // if the API channel is closed, stop the gRPC server |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 123 | log.Warnf("Stopping legacy API gRPC server") |
| 124 | apiserver.Stop() |
| 125 | break |
| 126 | |
| 127 | } |
| 128 | |
| 129 | group.Done() |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 130 | } |
| 131 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 132 | func main() { |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 133 | |
Matteo Scandolo | 40e067f | 2019-10-16 16:59:41 -0700 | [diff] [blame] | 134 | options := common.GetBBSimOpts() |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 135 | |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 136 | common.SetLogLevel(log.StandardLogger(), options.BBSim.LogLevel, options.BBSim.LogCaller) |
| 137 | log.Tracef("BBSim options: %+v", options) |
Matteo Scandolo | 2bf742a | 2019-10-01 11:33:34 -0700 | [diff] [blame] | 138 | |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 139 | if *options.BBSim.CpuProfile != "" { |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 140 | // start profiling |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 141 | log.Infof("Creating profile file at: %s", *options.BBSim.CpuProfile) |
| 142 | f, err := os.Create(*options.BBSim.CpuProfile) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 143 | if err != nil { |
| 144 | log.Fatal(err) |
| 145 | } |
| 146 | pprof.StartCPUProfile(f) |
| 147 | } |
| 148 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 149 | log.WithFields(log.Fields{ |
Pragya Arya | 2225f20 | 2020-01-29 18:05:01 +0530 | [diff] [blame] | 150 | "OltID": options.Olt.ID, |
| 151 | "NumNniPerOlt": options.Olt.NniPorts, |
| 152 | "NumPonPerOlt": options.Olt.PonPorts, |
| 153 | "NumOnuPerPon": options.Olt.OnusPonPort, |
| 154 | "TotalOnus": options.Olt.PonPorts * options.Olt.OnusPonPort, |
| 155 | "EnableAuth": options.BBSim.EnableAuth, |
| 156 | "Dhcp": options.BBSim.EnableDhcp, |
Shrey Baid | e72b3cc | 2020-05-12 00:03:06 +0530 | [diff] [blame^] | 157 | "Igmp": options.BBSim.EnableIgmp, |
Pragya Arya | 2225f20 | 2020-01-29 18:05:01 +0530 | [diff] [blame] | 158 | "Delay": options.BBSim.Delay, |
Pragya Arya | 324337e | 2020-02-20 14:35:08 +0530 | [diff] [blame] | 159 | "Events": options.BBSim.Events, |
Shrey Baid | 64cda47 | 2020-04-24 18:58:18 +0530 | [diff] [blame] | 160 | "KafkaEventTopic": options.BBSim.KafkaEventTopic, |
Pragya Arya | 2225f20 | 2020-01-29 18:05:01 +0530 | [diff] [blame] | 161 | "ControlledActivation": options.BBSim.ControlledActivation, |
Anand S Katti | 0954135 | 2020-01-29 15:54:01 +0530 | [diff] [blame] | 162 | "EnablePerf": options.BBSim.EnablePerf, |
Matteo Scandolo | f65e687 | 2020-04-15 15:18:43 -0700 | [diff] [blame] | 163 | "CTag": options.BBSim.CTag, |
| 164 | "CTagAllocation": options.BBSim.CTagAllocation, |
| 165 | "STag": options.BBSim.STag, |
| 166 | "STagAllocation": options.BBSim.STagAllocation, |
| 167 | "SadisFormat": options.BBSim.SadisFormat, |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 168 | }).Info("BroadBand Simulator is on") |
| 169 | |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 170 | // control channels, they are only closed when the goroutine needs to be terminated |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 171 | apiDoneChannel := make(chan bool) |
| 172 | |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 173 | olt := devices.CreateOLT( |
Pragya Arya | 996a089 | 2020-03-09 21:47:52 +0530 | [diff] [blame] | 174 | *options, |
Matteo Scandolo | c114709 | 2019-10-29 09:38:33 -0700 | [diff] [blame] | 175 | false, |
| 176 | ) |
Matteo Scandolo | e33447a | 2019-10-31 12:38:23 -0700 | [diff] [blame] | 177 | |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 178 | log.Debugf("Created OLT with id: %d", options.Olt.ID) |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 179 | |
| 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 Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 192 | go startApiServer(apiDoneChannel, &wg) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 193 | go startLegacyApiServer(apiDoneChannel, &wg) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 194 | log.Debugf("Started APIService") |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 195 | if common.Options.BBSim.SadisServer != false { |
| 196 | wg.Add(1) |
| 197 | go sadis.StartRestServer(olt, &wg) |
| 198 | } |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 199 | |
Pragya Arya | 324337e | 2020-02-20 14:35:08 +0530 | [diff] [blame] | 200 | if options.BBSim.Events { |
| 201 | // initialize a publisher |
Shrey Baid | 64cda47 | 2020-04-24 18:58:18 +0530 | [diff] [blame] | 202 | if err := common.InitializePublisher(sarama.NewAsyncProducer, olt.ID); err == nil { |
Pragya Arya | 324337e | 2020-02-20 14:35:08 +0530 | [diff] [blame] | 203 | // 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 Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 210 | wg.Wait() |
| 211 | |
| 212 | defer func() { |
| 213 | log.Info("BroadBand Simulator is off") |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 214 | if *options.BBSim.CpuProfile != "" { |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 215 | log.Info("Stopping profiler") |
| 216 | pprof.StopCPUProfile() |
| 217 | } |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 218 | }() |
Matteo Scandolo | 4b3fc7e | 2019-09-17 16:49:54 -0700 | [diff] [blame] | 219 | } |