blob: c331502278896bd9e735015dc371f1d4f824879e [file] [log] [blame]
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001/*
2 * Portions copyright 2019-present Open Networking Foundation
3 * Original copyright 2019-present Ciena Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package commands
19
20import (
21 "context"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070022 "fmt"
Anand S Katti09541352020-01-29 15:54:01 +053023 "os"
24 "strconv"
25 "strings"
26
Matteo Scandolo8df63df2019-09-12 10:34:32 -070027 "github.com/jessevdk/go-flags"
Anand S Katti09541352020-01-29 15:54:01 +053028 "github.com/olekukonko/tablewriter"
Matteo Scandolo8df63df2019-09-12 10:34:32 -070029 pb "github.com/opencord/bbsim/api/bbsim"
30 "github.com/opencord/bbsim/internal/bbsimctl/config"
31 "github.com/opencord/cordctl/pkg/format"
32 log "github.com/sirupsen/logrus"
33 "google.golang.org/grpc"
Matteo Scandolo8df63df2019-09-12 10:34:32 -070034)
35
36const (
Matteo Scandolo40e067f2019-10-16 16:59:41 -070037 DEFAULT_ONU_DEVICE_HEADER_FORMAT = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .PortNo }}\t{{ .SerialNumber }}\t{{ .HwAddress }}\t{{ .STag }}\t{{ .CTag }}\t{{ .OperState }}\t{{ .InternalState }}"
Matteo Scandolo8df63df2019-09-12 10:34:32 -070038)
39
Matteo Scandolo10f965c2019-09-24 10:40:46 -070040type OnuSnString string
Arjun E K57a7fcb2020-01-30 06:44:45 +000041type IgmpSubAction string
42
43const IgmpJoinKey string = "join"
44const IgmpLeaveKey string = "leave"
Arjun E Kdd443f02020-02-07 15:24:01 +000045const IgmpJoinKeyV3 string = "joinv3"
Arjun E K57a7fcb2020-01-30 06:44:45 +000046
Matteo Scandolo10f965c2019-09-24 10:40:46 -070047type ONUList struct{}
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070048
49type ONUGet struct {
50 Args struct {
51 OnuSn OnuSnString
52 } `positional-args:"yes" required:"yes"`
53}
54
Matteo Scandolo10f965c2019-09-24 10:40:46 -070055type ONUShutDown struct {
56 Args struct {
57 OnuSn OnuSnString
58 } `positional-args:"yes" required:"yes"`
Matteo Scandolo8df63df2019-09-12 10:34:32 -070059}
60
Matteo Scandolo10f965c2019-09-24 10:40:46 -070061type ONUPowerOn struct {
62 Args struct {
63 OnuSn OnuSnString
64 } `positional-args:"yes" required:"yes"`
65}
66
Matteo Scandoloe383d5d2019-10-25 14:47:27 -070067type ONUEapolRestart struct {
68 Args struct {
69 OnuSn OnuSnString
70 } `positional-args:"yes" required:"yes"`
71}
72
73type ONUDhcpRestart struct {
74 Args struct {
75 OnuSn OnuSnString
76 } `positional-args:"yes" required:"yes"`
77}
78
Arjun E K57a7fcb2020-01-30 06:44:45 +000079type ONUIgmp struct {
80 Args struct {
81 OnuSn OnuSnString
82 SubAction IgmpSubAction
83 } `positional-args:"yes" required:"yes"`
84}
85
Pragya Arya8bdb4532020-03-02 17:08:09 +053086type ONUTrafficSchedulers struct {
87 Args struct {
88 OnuSn OnuSnString
89 } `positional-args:"yes" required:"yes"`
90}
91
92type ONUFlows struct {
93 Args struct {
94 OnuSn OnuSnString
95 } `positional-args:"yes" required:"yes"`
96}
97
Matteo Scandolo10f965c2019-09-24 10:40:46 -070098type ONUOptions struct {
Anand S Katti09541352020-01-29 15:54:01 +053099 List ONUList `command:"list"`
100 Get ONUGet `command:"get"`
101 ShutDown ONUShutDown `command:"shutdown"`
102 PowerOn ONUPowerOn `command:"poweron"`
103 RestartEapol ONUEapolRestart `command:"auth_restart"`
104 RestartDchp ONUDhcpRestart `command:"dhcp_restart"`
105 Igmp ONUIgmp `command:"igmp"`
106 TrafficSchedulers ONUTrafficSchedulers `command:"traffic_schedulers"`
Anand S Katti86552f92020-03-03 21:56:32 +0530107 Alarms AlarmOptions `command:"alarms"`
Pragya Arya8bdb4532020-03-02 17:08:09 +0530108 Flows ONUFlows `command:"flows"`
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700109}
110
111func RegisterONUCommands(parser *flags.Parser) {
112 parser.AddCommand("onu", "ONU Commands", "Commands to query and manipulate ONU devices", &ONUOptions{})
113}
114
115func connect() (pb.BBSimClient, *grpc.ClientConn) {
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700116 conn, err := grpc.Dial(config.GlobalConfig.Server, grpc.WithInsecure())
117
118 if err != nil {
Matteo Scandolo2bf742a2019-10-01 11:33:34 -0700119 log.Fatalf("did not connect: %v", err)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700120 return nil, conn
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700121 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700122 return pb.NewBBSimClient(conn), conn
123}
124
125func getONUs() *pb.ONUs {
126
127 client, conn := connect()
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700128 defer conn.Close()
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700129
130 // Contact the server and print out its response.
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700131 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
132 defer cancel()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700133
134 onus, err := client.GetONUs(ctx, &pb.Empty{})
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700135 if err != nil {
Matteo Scandolo2bf742a2019-10-01 11:33:34 -0700136 log.Fatalf("could not get OLT: %v", err)
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700137 return nil
138 }
139 return onus
140}
141
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700142func (options *ONUList) Execute(args []string) error {
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700143 onus := getONUs()
144
145 // print out
146 tableFormat := format.Format(DEFAULT_ONU_DEVICE_HEADER_FORMAT)
147 if err := tableFormat.Execute(os.Stdout, true, onus.Items); err != nil {
148 log.Fatalf("Error while formatting ONUs table: %s", err)
149 }
150
151 return nil
152}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700153
Matteo Scandolod2ca2c72019-10-04 16:50:22 -0700154func (options *ONUGet) Execute(args []string) error {
155 client, conn := connect()
156 defer conn.Close()
157
158 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
159 defer cancel()
160 req := pb.ONURequest{
161 SerialNumber: string(options.Args.OnuSn),
162 }
163 res, err := client.GetONU(ctx, &req)
164
165 if err != nil {
166 log.Fatalf("Cannot not shutdown ONU %s: %v", options.Args.OnuSn, err)
167 return err
168 }
169
170 tableFormat := format.Format(DEFAULT_ONU_DEVICE_HEADER_FORMAT)
171 if err := tableFormat.Execute(os.Stdout, true, []*pb.ONU{res}); err != nil {
172 log.Fatalf("Error while formatting ONUs table: %s", err)
173 }
174
175 return nil
176}
177
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700178func (options *ONUShutDown) Execute(args []string) error {
179
180 client, conn := connect()
181 defer conn.Close()
182
183 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
184 defer cancel()
185 req := pb.ONURequest{
186 SerialNumber: string(options.Args.OnuSn),
187 }
188 res, err := client.ShutdownONU(ctx, &req)
189
190 if err != nil {
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700191 log.Fatalf("Cannot shutdown ONU %s: %v", options.Args.OnuSn, err)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700192 return err
193 }
194
195 fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
196
197 return nil
198}
199
200func (options *ONUPowerOn) Execute(args []string) error {
201 client, conn := connect()
202 defer conn.Close()
203
204 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
205 defer cancel()
206 req := pb.ONURequest{
207 SerialNumber: string(options.Args.OnuSn),
208 }
209 res, err := client.PoweronONU(ctx, &req)
210
211 if err != nil {
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700212 log.Fatalf("Cannot power on ONU %s: %v", options.Args.OnuSn, err)
213 return err
214 }
215
216 fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
217
218 return nil
219}
220
221func (options *ONUEapolRestart) Execute(args []string) error {
222 client, conn := connect()
223 defer conn.Close()
224
225 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
226 defer cancel()
227 req := pb.ONURequest{
228 SerialNumber: string(options.Args.OnuSn),
229 }
230 res, err := client.RestartEapol(ctx, &req)
231
232 if err != nil {
233 log.Fatalf("Cannot restart EAPOL for ONU %s: %v", options.Args.OnuSn, err)
234 return err
235 }
236
237 fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
238
239 return nil
240}
241
242func (options *ONUDhcpRestart) Execute(args []string) error {
243 client, conn := connect()
244 defer conn.Close()
245
246 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
247 defer cancel()
248 req := pb.ONURequest{
249 SerialNumber: string(options.Args.OnuSn),
250 }
251 res, err := client.RestartDhcp(ctx, &req)
252
253 if err != nil {
254 log.Fatalf("Cannot restart DHCP for ONU %s: %v", options.Args.OnuSn, err)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700255 return err
256 }
257
258 fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
259
260 return nil
261}
262
Arjun E K57a7fcb2020-01-30 06:44:45 +0000263func (options *ONUIgmp) Execute(args []string) error {
264 client, conn := connect()
265 defer conn.Close()
266
267 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
268 defer cancel()
269
270 req := pb.ONURequest{
271 SerialNumber: string(options.Args.OnuSn),
272 }
273
274 var subActionVal pb.SubActionTypes
275 if string(options.Args.SubAction) == IgmpJoinKey {
276 subActionVal = pb.SubActionTypes_JOIN
277 } else if string(options.Args.SubAction) == IgmpLeaveKey {
278 subActionVal = pb.SubActionTypes_LEAVE
Anand S Katti09541352020-01-29 15:54:01 +0530279 } else if string(options.Args.SubAction) == IgmpJoinKeyV3 {
280 subActionVal = pb.SubActionTypes_JOINV3
281 }
Arjun E K57a7fcb2020-01-30 06:44:45 +0000282
283 igmpReq := pb.IgmpRequest{
284 OnuReq: &req,
285 SubActionVal: subActionVal,
286 }
287 res, err := client.GetONU(ctx, igmpReq.OnuReq)
288 if err != nil {
289 log.WithFields(log.Fields{
290 "SerialNumber": options.Args.OnuSn,
291 }).Errorf("Cannot not get details on ONU error: %v", err)
292 }
293 log.WithFields(log.Fields{
294 "SerialNumber": igmpReq.OnuReq.SerialNumber,
295 }).Debugf("ONU has indentified : %s", res)
296
297 igmpRes, igmpErr := client.ChangeIgmpState(ctx, &igmpReq)
298 if igmpErr != nil {
299 log.WithFields(log.Fields{
300 "SubAction": options.Args.SubAction,
301 }).Errorf("Could not process Action: error: %v", igmpErr)
302 } else {
303 log.WithFields(log.Fields{
304 "SubAction": options.Args.SubAction,
305 }).Debugf("igmp state has been changed with response: %s",
306 igmpRes.Message)
307 }
308
309 return nil
310}
311
Pragya Arya8bdb4532020-03-02 17:08:09 +0530312func (options *ONUFlows) Execute(args []string) error {
313 client, conn := connect()
314 defer conn.Close()
315
316 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
317 defer cancel()
318 req := pb.ONURequest{
319 SerialNumber: string(options.Args.OnuSn),
320 }
321 res, err := client.GetFlows(ctx, &req)
322 if err != nil {
323 log.Errorf("Cannot get flows for ONU %s: %v", options.Args.OnuSn, err)
324 return err
325 }
326
327 if res.Flows == nil {
328 fmt.Println(fmt.Sprintf("ONU %s has no flows", options.Args.OnuSn))
329 return nil
330 }
331
332 flowHeader := []string{
333 "access_intf_id",
334 "onu_id",
335 "uni_id",
336 "flow_id",
337 "flow_type",
338 "eth_type",
339 "alloc_id",
340 "network_intf_id",
341 "gemport_id",
342 "classifier",
343 "action",
344 "priority",
345 "cookie",
346 "port_no",
347 }
348
349 tableFlow := tablewriter.NewWriter(os.Stdout)
350 tableFlow.SetRowLine(true)
351 fmt.Fprintf(os.Stdout, "ONU Flows:\n")
352 tableFlow.SetHeader(flowHeader)
353
354 for _, flow := range res.Flows {
355 flowInfo := []string{}
356 flowInfo = append(flowInfo,
357 strconv.Itoa(int(flow.AccessIntfId)),
358 strconv.Itoa(int(flow.OnuId)),
359 strconv.Itoa(int(flow.UniId)),
360 strconv.Itoa(int(flow.FlowId)),
361 flow.FlowType,
362 fmt.Sprintf("%x", flow.Classifier.EthType),
363 strconv.Itoa(int(flow.AllocId)),
364 strconv.Itoa(int(flow.NetworkIntfId)),
365 strconv.Itoa(int(flow.GemportId)),
366 flow.Classifier.String(),
367 flow.Action.String(),
368 strconv.Itoa(int(flow.Priority)),
369 strconv.Itoa(int(flow.Cookie)),
370 strconv.Itoa(int(flow.PortNo)),
371 )
372 tableFlow.Append(flowInfo)
373 }
374 tableFlow.Render()
375 tableFlow.SetNewLine("")
376 return nil
377}
378
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700379func (onuSn *OnuSnString) Complete(match string) []flags.Completion {
380 client, conn := connect()
381 defer conn.Close()
382
383 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
384 defer cancel()
385
386 onus, err := client.GetONUs(ctx, &pb.Empty{})
387 if err != nil {
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700388 log.Fatalf("could not get ONUs: %v", err)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700389 return nil
390 }
391
392 list := make([]flags.Completion, 0)
393 for _, k := range onus.Items {
394 if strings.HasPrefix(k.SerialNumber, match) {
395 list = append(list, flags.Completion{Item: k.SerialNumber})
396 }
397 }
398
399 return list
400}
Anand S Katti09541352020-01-29 15:54:01 +0530401
402func (options *ONUTrafficSchedulers) Execute(args []string) error {
403 client, conn := connect()
404 defer conn.Close()
405
406 ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
407 defer cancel()
408 req := pb.ONURequest{
409 SerialNumber: string(options.Args.OnuSn),
410 }
411 res, err := client.GetOnuTrafficSchedulers(ctx, &req)
412 if err != nil {
413 log.Fatalf("Cannot get traffic schedulers for ONU %s: %v", options.Args.OnuSn, err)
414 return err
415 }
416
417 if res.TraffSchedulers == nil {
418 log.Fatalf("Cannot get traffic schedulers for ONU: %s (unavailable)", options.Args.OnuSn)
419 return nil
420 }
421
422 SchedulerHeader := []string{"Direction",
423 "AllocId",
424 "Scheduler.Direction",
425 "Scheduler.AdditionalBw",
426 "Scheduler.Priority",
427 "Scheduler.Weight",
428 "Scheduler.SchedPolicy",
429 }
430
431 ShapingInfoHeader := []string{"InferredAdditionBwIndication",
432 "Cbs",
433 "Cir",
434 "Gir",
435 "Pbs",
436 "Pir",
437 }
438
439 SchedulerVals := []string{}
440 ShapingInfoVals := []string{}
441 for _, v := range res.TraffSchedulers.TrafficScheds {
442 SchedulerVals = append(SchedulerVals,
443 v.GetDirection().String(),
444 strconv.Itoa(int(v.GetAllocId())),
445 v.Scheduler.GetDirection().String(),
446 v.Scheduler.GetAdditionalBw().String(),
447 strconv.Itoa(int(v.Scheduler.GetPriority())),
448 strconv.Itoa(int(v.Scheduler.GetWeight())),
449 v.GetScheduler().GetSchedPolicy().String(),
450 )
451
452 ShapingInfoVals = append(ShapingInfoVals,
453 v.TrafficShapingInfo.GetAddBwInd().String(),
454 strconv.Itoa(int(v.TrafficShapingInfo.GetCbs())),
455 strconv.Itoa(int(v.TrafficShapingInfo.GetCir())),
456 strconv.Itoa(int(v.TrafficShapingInfo.GetGir())),
457 strconv.Itoa(int(v.TrafficShapingInfo.GetPbs())),
458 strconv.Itoa(int(v.TrafficShapingInfo.GetPir())),
459 )
460 }
461
462 fmt.Fprintf(os.Stdout, "OnuId: %d \n", int(res.TraffSchedulers.OnuId))
463 fmt.Fprintf(os.Stdout, "IntfId: %d \n", int(res.TraffSchedulers.IntfId))
464 fmt.Fprintf(os.Stdout, "UniId: %d \n", int(res.TraffSchedulers.UniId))
465 fmt.Fprintf(os.Stdout, "OnuPortNo: %d \n", int(res.TraffSchedulers.PortNo))
466
467 tableSched := tablewriter.NewWriter(os.Stdout)
468 tableSched.SetRowLine(true)
469 fmt.Fprintf(os.Stdout, "Traffic Schedulers Info:\n")
470 tableSched.SetHeader(SchedulerHeader)
471 tableSched.Append(SchedulerVals)
472 tableSched.Render()
473 tableSched.SetNewLine("")
474
475 tableShap := tablewriter.NewWriter(os.Stdout)
476 tableShap.SetRowLine(true)
477 fmt.Fprintf(os.Stdout, "Traffic Shaping Info:\n")
478 tableShap.SetHeader(ShapingInfoHeader)
479 tableShap.Append(ShapingInfoVals)
480 tableShap.Render()
481
482 return nil
483}