VOL-291 : PON simulator refactoring for cluster integration
- Added ponsim build target in Makefile
- Added new option to vcore to select comm type with ponsim
- Modified all proto files to include destination go package
Amendments:
- Clean up based on review comments
- Properly close GRPC connections in ponsim_olt adapter
- Added voltha namespace to some k8s templates
Change-Id: I2f349fa7b3550a8a8cc8fc676cc896f33fbb9372
diff --git a/ponsim/v2/grpc/nbi/bal_handler.go b/ponsim/v2/grpc/nbi/bal_handler.go
new file mode 100644
index 0000000..5cbafb3
--- /dev/null
+++ b/ponsim/v2/grpc/nbi/bal_handler.go
@@ -0,0 +1,82 @@
+package nbi
+
+import (
+ "context"
+ "github.com/opencord/voltha/ponsim/v2/common"
+ "github.com/opencord/voltha/protos/go/bal"
+)
+
+// TODO: fix BAL function parameters and returns
+
+type BalHandler struct {
+}
+
+func NewBalHandler() *BalHandler {
+ var handler *BalHandler
+ handler = &BalHandler{}
+ return handler
+}
+
+func (handler *BalHandler) BalApiInit(
+ ctx context.Context,
+ request *bal.BalInit,
+) (*bal.BalErr, error) {
+ common.Logger().Info("BalApiInit Called", ctx, request)
+ return &bal.BalErr{Err: bal.BalErrno_BAL_ERR_OK}, nil
+}
+
+func (handler *BalHandler) BalApiFinish(
+ ctx context.Context,
+ request *bal.BalCfg,
+) (*bal.BalErr, error) {
+ common.Logger().Info("BalApiFinish Called", ctx, request)
+ return &bal.BalErr{Err: bal.BalErrno_BAL_ERR_OK}, nil
+}
+
+func (handler *BalHandler) BalCfgSet(
+ ctx context.Context,
+ request *bal.BalCfg,
+) (*bal.BalErr, error) {
+ common.Logger().Info("BalCfgSet Called", ctx, request)
+ return &bal.BalErr{Err: bal.BalErrno_BAL_ERR_OK}, nil
+}
+
+func (handler *BalHandler) BalCfgClear(
+ ctx context.Context,
+ request *bal.BalKey,
+) (*bal.BalErr, error) {
+ common.Logger().Info("BalCfgClear Called", ctx, request)
+ return &bal.BalErr{Err: bal.BalErrno_BAL_ERR_OK}, nil
+}
+
+func (handler *BalHandler) BalCfgGet(
+ ctx context.Context,
+ request *bal.BalKey,
+) (*bal.BalCfg, error) {
+ common.Logger().Info("BalCfgGet Called", ctx, request)
+ return &bal.BalCfg{}, nil
+}
+
+func (handler *BalHandler) BalApiReboot(
+ ctx context.Context,
+ request *bal.BalReboot,
+) (*bal.BalErr, error) {
+ common.Logger().Info("BalApiReboot Called", ctx, request)
+ return &bal.BalErr{Err: bal.BalErrno_BAL_ERR_OK}, nil
+}
+
+func (handler *BalHandler) BalApiHeartbeat(
+ ctx context.Context,
+ request *bal.BalHeartbeat,
+) (*bal.BalRebootState, error) {
+ common.Logger().Info("BalApiHeartbeat Called", ctx, request)
+ return &bal.BalRebootState{}, nil
+}
+
+func (handler *BalHandler) BalCfgStatGet(
+ ctx context.Context,
+ request *bal.BalInterfaceKey,
+) (*bal.BalInterfaceStat, error) {
+ common.Logger().Info("BalCfgStatGet Called", ctx, request)
+ return &bal.BalInterfaceStat{}, nil
+}
diff --git a/ponsim/v2/grpc/nbi/ponsim_handler.go b/ponsim/v2/grpc/nbi/ponsim_handler.go
new file mode 100644
index 0000000..763f4bc
--- /dev/null
+++ b/ponsim/v2/grpc/nbi/ponsim_handler.go
@@ -0,0 +1,327 @@
+package nbi
+
+import (
+ "context"
+ "crypto/tls"
+ "errors"
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/google/gopacket"
+ "github.com/google/gopacket/layers"
+ "github.com/opencord/voltha/ponsim/v2/common"
+ "github.com/opencord/voltha/ponsim/v2/core"
+ "github.com/opencord/voltha/protos/go/voltha"
+ "github.com/sirupsen/logrus"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials"
+ "strconv"
+ "strings"
+)
+
+// TODO: Cleanup GRPC security config
+// TODO: Pass-in the certificate information as a structure parameter
+
+type PonSimHandler struct {
+ device core.PonSimInterface
+}
+
+/*
+NewPonSimHandler instantiates a handler for a PonSim device
+*/
+func NewPonSimHandler(device core.PonSimInterface) *PonSimHandler {
+ var handler *PonSimHandler
+ handler = &PonSimHandler{device: device}
+ return handler
+}
+
+/*
+SendFrame handles and forwards EGRESS packets (i.e. VOLTHA to OLT)
+*/
+func (handler *PonSimHandler) SendFrame(ctx context.Context, data *voltha.PonSimFrame) (*empty.Empty, error) {
+ frame := gopacket.NewPacket(data.Payload, layers.LayerTypeEthernet, gopacket.Default)
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "frame": frame.Dump(),
+ }).Info("Constructed frame")
+
+ handler.device.Forward(context.Background(), 2, frame)
+
+ out := new(empty.Empty)
+ return out, nil
+}
+
+/*
+ReceiveFrames handles a stream of INGRESS packets (i.e. OLT to VOLTHA)
+*/
+func (handler *PonSimHandler) ReceiveFrames(empty *empty.Empty, stream voltha.PonSim_ReceiveFramesServer) error {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Info("start-receiving-frames")
+
+ if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
+ var data []byte
+ var ok bool
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "device": (handler.device).(*core.PonSimOltDevice),
+ }).Info("receiving-frames-from-olt-device")
+
+ for {
+ select {
+ case data, ok = <-(handler.device).(*core.PonSimOltDevice).GetOutgoing():
+ if ok {
+ frame := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "frame": frame,
+ }).Info("Received incoming data")
+
+ frameBytes := &voltha.PonSimFrame{Id: handler.device.GetAddress(), Payload: data}
+ if err := stream.Send(frameBytes); err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "frame": frame,
+ "error": err,
+ }).Error("Failed to send incoming data")
+ return err
+ }
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "frame": frame,
+ }).Info("Sent incoming data")
+
+ } else {
+ return errors.New("incoming data channel has closed")
+ }
+ }
+ }
+
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Error("Not handling an OLT device")
+ }
+
+ return nil
+}
+
+/*
+GetDeviceInfo returns information of a PonSim device (OLT or ONU)
+*/
+func (handler *PonSimHandler) GetDeviceInfo(
+ ctx context.Context,
+ empty *empty.Empty,
+) (*voltha.PonSimDeviceInfo, error) {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Info("Getting device information")
+
+ var out *voltha.PonSimDeviceInfo
+
+ // Check which device type we're currently handling
+ if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Debug("Handling OLT device")
+ keys := make([]int32, 0, len((handler.device).(*core.PonSimOltDevice).GetOnus()))
+ for k := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
+ keys = append(keys, k)
+ }
+ out = &voltha.PonSimDeviceInfo{NniPort: 0, UniPorts: []int32(keys)}
+
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Debug("Handling ONU/OTHER device")
+
+ out = &voltha.PonSimDeviceInfo{}
+ }
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "result": out,
+ }).Info("Device information")
+
+ return out, nil
+}
+
+/*
+UpdateFlowTable populates and cleans up the flows for a PonSim device
+*/
+func (handler *PonSimHandler) UpdateFlowTable(
+ ctx context.Context,
+ table *voltha.FlowTable,
+) (*empty.Empty, error) {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "table": table,
+ }).Info("Updating flows")
+
+ if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
+ if table.Port == 0 {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "port": table.Port,
+ }).Debug("Updating OLT flows")
+
+ if err := (handler.device).(*core.PonSimOltDevice).InstallFlows(ctx, table.Flows); err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "error": err.Error(),
+ "flows": table.Flows,
+ }).Error("Problem updating flows on OLT")
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Debug("Updated OLT flows")
+ }
+
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "port": table.Port,
+ }).Debug("Updating ONU flows")
+
+ if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[table.Port]; ok {
+ // TODO: make it secure
+ ta := credentials.NewTLS(&tls.Config{
+ InsecureSkipVerify: true,
+ })
+
+ host := strings.Join([]string{
+ child.Device.Address,
+ strconv.Itoa(int(child.Device.Port)),
+ }, ":")
+
+ conn, err := grpc.Dial(
+ host,
+ grpc.WithTransportCredentials(ta),
+ )
+ if err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "error": err.Error(),
+ }).Error("GRPC Connection problem")
+ }
+ defer conn.Close()
+ client := voltha.NewPonSimClient(conn)
+
+ if _, err = client.UpdateFlowTable(ctx, table); err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "host": host,
+ "error": err.Error(),
+ }).Error("Problem forwarding update request to ONU")
+ }
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "port": table.Port,
+ }).Warn("Unable to find ONU")
+ }
+
+ }
+ } else if _, ok := (handler.device).(*core.PonSimOnuDevice); ok {
+ if err := (handler.device).(*core.PonSimOnuDevice).InstallFlows(ctx, table.Flows); err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "error": err.Error(),
+ "flows": table.Flows,
+ }).Error("Problem updating flows on ONU")
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Debug("Updated ONU flows")
+ }
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "port": table.Port,
+ }).Warn("Unknown device")
+ }
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "table": table,
+ }).Info("Updated flows")
+
+ out := new(empty.Empty)
+ return out, nil
+}
+
+/*
+GetStats retrieves statistics for a PonSim device
+*/
+func (handler *PonSimHandler) GetStats(
+ ctx context.Context,
+ empty *empty.Empty,
+) (*voltha.PonSimMetrics, error) {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Info("Retrieving stats")
+
+ var metrics *voltha.PonSimMetrics = new(voltha.PonSimMetrics)
+
+ if olt, ok := (handler.device).(*core.PonSimOltDevice); ok {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "olt": olt,
+ }).Debug("Retrieving stats for OLT")
+
+ // Get stats for current device
+
+ // Loop through each onus to get stats from those as well?
+ // send grpc request to each onu
+ for _, child := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
+ // TODO: make it secure
+ ta := credentials.NewTLS(&tls.Config{
+ InsecureSkipVerify: true,
+ })
+
+ host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
+ conn, err := grpc.Dial(
+ host,
+ grpc.WithTransportCredentials(ta),
+ )
+ if err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "error": err.Error(),
+ }).Error("GRPC Connection problem")
+ }
+ defer conn.Close()
+ client := voltha.NewPonSimClient(conn)
+
+ if _, err = client.GetStats(ctx, empty); err != nil {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "host": host,
+ "error": err.Error(),
+ }).Error("Problem forwarding stats request to ONU")
+ }
+ }
+ metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "metrics": metrics,
+ }).Debug("OLT Metrics")
+
+ } else if onu, ok := (handler.device).(*core.PonSimOnuDevice); ok {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ "onu": onu,
+ }).Debug("Retrieving stats for ONU")
+ } else {
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Warn("Unknown device")
+ }
+
+ common.Logger().WithFields(logrus.Fields{
+ "handler": handler,
+ }).Info("Retrieved stats")
+
+ return metrics, nil
+}
diff --git a/ponsim/v2/grpc/nbi/xponsim_handler.go b/ponsim/v2/grpc/nbi/xponsim_handler.go
new file mode 100644
index 0000000..fbc63eb
--- /dev/null
+++ b/ponsim/v2/grpc/nbi/xponsim_handler.go
@@ -0,0 +1,124 @@
+package nbi
+
+import (
+ "context"
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/opencord/voltha/ponsim/v2/core"
+ "github.com/opencord/voltha/protos/go/voltha"
+)
+
+type XPonSimHandler struct {
+ device *core.XPonSimDevice
+}
+
+func NewXPonSimHandler() *XPonSimHandler {
+ var handler *XPonSimHandler
+ handler = &XPonSimHandler{}
+ return handler
+}
+
+func (handler *XPonSimHandler) CreateInterface(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.CreateInterface(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) UpdateInterface(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.UpdateInterface(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) RemoveInterface(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.RemoveInterface(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) CreateTcont(
+ ctx context.Context,
+ config *voltha.TcontInterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.CreateTcont(ctx, config.TcontsConfigData, config.TrafficDescriptorProfileConfigData)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) UpdateTcont(
+ ctx context.Context,
+ config *voltha.TcontInterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.UpdateTcont(ctx, config.TcontsConfigData, config.TrafficDescriptorProfileConfigData)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) RemoveTcont(
+ ctx context.Context,
+ config *voltha.TcontInterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.RemoveTcont(ctx, config.TcontsConfigData, config.TrafficDescriptorProfileConfigData)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) CreateGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.CreateGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) UpdateGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.UpdateGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) RemoveGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.RemoveGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) CreateMulticastGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.CreateMulticastGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) UpdateMulticastGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.UpdateMulticastGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) RemoveMulticastGemport(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.RemoveMulticastGemport(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) CreateMulticastDistributionSet(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.CreateMulticastDistributionSet(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) UpdateMulticastDistributionSet(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.UpdateMulticastDistributionSet(ctx, config)
+ return &empty.Empty{}, nil
+}
+func (handler *XPonSimHandler) RemoveMulticastDistributionSet(
+ ctx context.Context,
+ config *voltha.InterfaceConfig,
+) (*empty.Empty, error) {
+ handler.device.RemoveMulticastDistributionSet(ctx, config)
+ return &empty.Empty{}, nil
+}