blob: 97bd1286760210f54249e63b6a5e2ade2aa285db [file] [log] [blame]
Keita NISHIMOTO9708e042018-10-27 09:24:44 +09001/*
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
17package core
18
19import (
Matteo Scandolo88e91892018-11-06 16:29:19 -080020 "flag"
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090021 "os"
22 "os/signal"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020023 "reflect"
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090024 "strconv"
Matteo Scandolo88e91892018-11-06 16:29:19 -080025 "strings"
26 "sync"
Zdravko Bozakov078a2712019-07-19 23:25:15 +020027 "syscall"
Mahir Gunyel32dfd722019-08-05 16:18:06 +030028 "time"
Matteo Scandolo88e91892018-11-06 16:29:19 -080029
Zack Williams2abf3932019-08-05 14:07:05 -070030 "github.com/opencord/voltha-bbsim/common/logger"
31 "github.com/opencord/voltha-bbsim/device"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020032 log "github.com/sirupsen/logrus"
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090033)
34
Zdravko Bozakov078a2712019-07-19 23:25:15 +020035// Constants for tester mode
Keita NISHIMOTO2807c542019-06-04 22:58:32 +090036const (
37 DEFAULT Mode = iota
38 AAA
39 BOTH
40)
41
Zdravko Bozakov078a2712019-07-19 23:25:15 +020042// Mode store emulation mode
Keita NISHIMOTO2807c542019-06-04 22:58:32 +090043type Mode int
44
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020045// AutoONUActivate is flag for Auto ONU Add on/off.
46var AutoONUActivate int
47
Zdravko Bozakov078a2712019-07-19 23:25:15 +020048//Option is the structure to store the user provided flag values
49type Option struct {
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020050 address string
51 port uint32
52 mgmtGrpcPort uint32
53 mgmtRestPort uint32
54 oltid uint32
55 npon uint32
56 nonus uint32
57 aaawait int
58 dhcpwait int
59 dhcpservip string
Mahir Gunyel32dfd722019-08-05 16:18:06 +030060 intvl time.Duration
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020061 interactiveOnuActivation bool
62 Mode Mode
63 KafkaBroker string
64 Debuglvl string
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090065}
66
Zdravko Bozakov078a2712019-07-19 23:25:15 +020067// GetOptions receives command line options and stores them in Option structure
68func GetOptions() *Option {
69 o := new(Option)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090070 addressport := flag.String("H", ":50060", "IP address:port")
Matteo Scandolo88e91892018-11-06 16:29:19 -080071 oltid := flag.Int("id", 0, "OLT-ID")
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090072 npon := flag.Int("i", 1, "Number of PON-IF ports")
73 nonus := flag.Int("n", 1, "Number of ONUs per PON-IF port")
74 modeopt := flag.String("m", "default", "Emulation mode (default, aaa, both (aaa & dhcp))")
Keita NISHIMOTO2807c542019-06-04 22:58:32 +090075 aaawait := flag.Int("aw", 2, "Wait time (sec) for activation WPA supplicants after EAPOL flow entry installed")
76 dhcpwait := flag.Int("dw", 2, "Wait time (sec) for activation DHCP clients after DHCP flow entry installed")
Keita NISHIMOTO2f8a6a42019-02-08 09:47:07 +090077 dhcpservip := flag.String("s", "182.21.0.128", "DHCP Server IP Address")
Mahir Gunyel32dfd722019-08-05 16:18:06 +030078 intvl := flag.Duration("v", 0, "Interval each Discovery Indication, in the form of unit+suffix, such as '10ms', '1s' or '1m''. defaults to 0")
Matteo Scandolo88e91892018-11-06 16:29:19 -080079 kafkaBroker := flag.String("k", "", "Kafka broker")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020080 interactiveOnuActivation := flag.Bool("ia", false, "Enable interactive activation of ONUs")
81 mgmtGrpcPort := flag.Int("grpc", 50061, "BBSim API server gRPC port")
82 mgmtRestPort := flag.Int("rest", 50062, "BBSim API server REST port")
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090083 o.Mode = DEFAULT
Mahir Gunyel09183342019-01-29 14:26:50 -080084 debg := flag.String("d", "DEBUG", "Debug Level(TRACE DEBUG INFO WARN ERROR)")
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090085 flag.Parse()
86 if *modeopt == "aaa" {
87 o.Mode = AAA
88 } else if *modeopt == "both" {
89 o.Mode = BOTH
90 }
Mahir Gunyel09183342019-01-29 14:26:50 -080091 o.Debuglvl = *debg
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090092 o.oltid = uint32(*oltid)
93 o.npon = uint32(*npon)
Zdravko Bozakov078a2712019-07-19 23:25:15 +020094 // make sure to have at-lease 1 PON port available
95 if o.npon == 0 {
96 o.npon = 1
97 }
Keita NISHIMOTO9708e042018-10-27 09:24:44 +090098 o.nonus = uint32(*nonus)
Zdravko Bozakov078a2712019-07-19 23:25:15 +020099 // make sure to have at-least 1 ONU is available
100 if o.nonus == 0 {
101 o.nonus = 1
102 }
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900103 o.aaawait = *aaawait
104 o.dhcpwait = *dhcpwait
105 o.dhcpservip = *dhcpservip
106 o.intvl = *intvl
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200107 o.interactiveOnuActivation = *interactiveOnuActivation
Matteo Scandolo88e91892018-11-06 16:29:19 -0800108 o.KafkaBroker = *kafkaBroker
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200109 // make sure that 'IP:Port' or ':Port' provided properly.
110 if !strings.Contains(*addressport, ":") {
111 log.Fatal("Invalid address given (missing colon)")
112 }
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200113 o.address = strings.Split(*addressport, ":")[0]
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900114 tmp, _ := strconv.Atoi(strings.Split(*addressport, ":")[1])
115 o.port = uint32(tmp)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200116 o.mgmtGrpcPort = uint32(*mgmtGrpcPort)
117 o.mgmtRestPort = uint32(*mgmtRestPort)
118
119 if o.interactiveOnuActivation == true {
120 log.Info("Automatic ONU activation disabled: use BBSim API to activate ONUs")
121 }
122
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900123 return o
124}
125
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200126//Mediator stores option, server and testmanager to mediate
127type Mediator struct {
128 opt *Option
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900129 server *Server
130 testmanager *TestManager
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900131}
132
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200133// NewMediator returns a new Mediator object
134func NewMediator(o *Option) *Mediator {
135 m := new(Mediator)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900136 m.opt = o
Matteo Scandolo88e91892018-11-06 16:29:19 -0800137 logger.WithFields(log.Fields{
138 "ip": o.address,
139 "baseport": o.port,
140 "pon_ports": o.npon,
141 "onus": o.nonus,
142 "mode": o.Mode,
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200143 }).Debug("New Mediator")
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900144 return m
145}
146
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200147// Start Mediator
148func (m *Mediator) Start() {
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900149 var wg sync.WaitGroup
150 opt := m.opt
Keita NISHIMOTO3af86da2018-12-12 10:34:43 +0900151 server := NewCore(opt)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200152 server.wg = &sync.WaitGroup{}
153 server.wg.Add(1)
154 go server.StartServerActionLoop(&wg)
155 server.serverActionCh <- "start"
156 go server.startMgmtServer(&wg)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900157
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900158 tm := NewTestManager(opt)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900159 m.server = server
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900160 m.testmanager = tm
Matteo Scandolo88e91892018-11-06 16:29:19 -0800161 go func() {
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900162 m.Mediate()
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900163 }()
164
165 c := make(chan os.Signal, 1)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200166 signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900167 go func() {
Matteo Scandolo88e91892018-11-06 16:29:19 -0800168 defer func() {
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900169 logger.Debug("SIGINT catcher Done")
170 wg.Done()
171 }()
172 for sig := range c {
173 wg.Add(1)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200174 logger.Debug("SIGINT %v", sig)
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900175 close(c)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200176 server.Stop() // Non-blocking
177 err := tm.Stop() // Non-blocking
178 if err != nil {
179 logger.Error("Error stopping the TestManager %v", err)
180 }
181 err = server.stopMgmtServer()
182 if err != nil {
183 logger.Error("Error stopping the Management Server %v", err)
184 }
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200185 server.wg.Done()
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900186 return
187 }
188 }()
189 wg.Wait()
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200190 server.wg.Wait()
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900191}
192
Zdravko Bozakov8b9328c2019-05-15 05:13:34 +0200193// Mediate method is invoked on OLT and ONU state change
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200194func (m *Mediator) Mediate() {
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900195 defer logger.Debug("Mediate Done")
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900196 for sr := range m.server.stateRepCh {
197 next := sr.next
198 current := sr.current
199 dev := sr.device
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700200 key := dev.GetDevkey()
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200201 if reflect.TypeOf(dev) == reflect.TypeOf(&device.Olt{}) {
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700202 logger.WithFields(log.Fields{
203 "device": dev,
204 }).Debugf("Received OLT Device state change %v Current: %d Next: %d", key, current, next)
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900205 if err := transitOlt(current, next, m.testmanager, m.opt); err != nil {
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900206 logger.Error("%v", err)
207 }
208 } else if reflect.TypeOf(dev) == reflect.TypeOf(&device.Onu{}) {
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700209 logger.WithFields(log.Fields{
210 "device": dev,
211 }).Debugf("Received ONU Device state change %v Current: %d Next: %d", key, current, next)
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900212 if err := transitOnu(key, current, next, m.testmanager, m.opt); err != nil {
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900213 logger.Error("%v", err)
214 }
Keita NISHIMOTO9708e042018-10-27 09:24:44 +0900215 }
216 }
Matteo Scandolo88e91892018-11-06 16:29:19 -0800217}
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900218
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200219func transitOlt(current device.State, next device.State, tm *TestManager, o *Option) error {
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900220 logger.Debug("trnsitOlt called current:%d , next:%d", current, next)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200221 if current == device.OltPreactive && next == device.OltActive {
222 err := tm.Start()
223 if err != nil {
224 logger.Error("Error starting the TestManager %v", err)
225 }
Mahir Gunyel639c4f72019-04-26 12:05:32 -0700226 nniup, _ := makeNniName(o.oltid)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200227 err = activateDHCPServer(nniup, o.dhcpservip)
228 if err != nil {
229 logger.Error("Error activating DHCP Server %v", err)
230 }
231 } else if current == device.OltActive && next == device.OltPreactive {
232 err := tm.Stop()
233 if err != nil {
234 logger.Error("Error stoping the TestManager %v", err)
235 }
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900236 }
237 return nil
238}
239
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200240func transitOnu(key device.Devkey, previous device.State, current device.State, tm *TestManager, o *Option) error {
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700241 logger.Debug("transitOnu called with key: %v, previous: %s, current: %s", key, device.ONUState[previous], device.ONUState[current])
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900242 if o.Mode == AAA || o.Mode == BOTH {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200243 if previous == device.OnuActive && current == device.OnuOmciActive {
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700244 logger.Debug("Starting WPASupplicant for device %v", key)
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900245 t := tm.CreateTester("AAA", o, key, activateWPASupplicant, o.aaawait)
246 if err := tm.StartTester(t); err != nil {
247 logger.Error("Cannot Start AAA Executer error:%v", err)
248 }
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200249 } else if previous == device.OnuOmciActive && current == device.OnuInactive {
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900250 if err := tm.StopTester("AAA", key); err != nil {
251 logger.Error("Cannot Stop AAA Executer error:%v", err)
252 }
Keita NISHIMOTO7bce7692019-01-19 09:31:09 +0900253 }
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900254 }
255
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200256 if o.Mode == BOTH {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200257 if previous == device.OnuOmciActive && current == device.OnuAuthenticated {
Matteo Scandolo67add0c2019-08-01 16:41:14 -0700258 logger.Debug("Starting DHCP client for device %v", key)
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900259 t := tm.CreateTester("DHCP", o, key, activateDHCPClient, o.dhcpwait)
260 if err := tm.StartTester(t); err != nil {
261 logger.Error("Cannot Start DHCP Executer error:%v", err)
262 }
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200263 } else if previous == device.OnuAuthenticated && current == device.OnuInactive {
Keita NISHIMOTO2807c542019-06-04 22:58:32 +0900264 if err := tm.StopTester("DHCP", key); err != nil {
265 logger.Error("Cannot Stop DHCP Executer error:%v", err)
266 }
Keita NISHIMOTOdd9f6732019-02-09 09:41:31 +0900267 }
Keita NISHIMOTO7bce7692019-01-19 09:31:09 +0900268 }
Keita NISHIMOTO3f080622019-01-16 10:21:22 +0900269 return nil
Mahir Gunyel09183342019-01-29 14:26:50 -0800270}