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/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
+}