[VOL-4519] Add bbsimctl command to invalidate MDS count of an ONU

Change-Id: I8cdb6c0d5381b952a87e1d24d87cab81de0ddaf9
diff --git a/internal/bbsim/api/onus_handler.go b/internal/bbsim/api/onus_handler.go
index 8aef5e9..92ab912 100644
--- a/internal/bbsim/api/onus_handler.go
+++ b/internal/bbsim/api/onus_handler.go
@@ -19,9 +19,10 @@
 import (
 	"context"
 	"fmt"
+	"strconv"
+
 	"github.com/opencord/bbsim/internal/bbsim/types"
 	"github.com/opencord/voltha-protos/v5/go/openolt"
-	"strconv"
 
 	"github.com/opencord/bbsim/api/bbsim"
 	"github.com/opencord/bbsim/internal/bbsim/devices"
@@ -664,3 +665,28 @@
 	}
 	return &unis_ret, nil
 }
+
+// Invalidate the MDS counter of the ONU
+func (s BBSimServer) InvalidateMds(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
+	logger.WithFields(log.Fields{
+		"OnuSn": req.SerialNumber,
+	}).Infof("Received request to invalidate the MDS counter of the ONU")
+
+	res := &bbsim.Response{}
+	olt := devices.GetOLT()
+
+	onu, err := olt.FindOnuBySn(req.SerialNumber)
+	if err != nil {
+		res.StatusCode = int32(codes.NotFound)
+		res.Message = err.Error()
+		return res, err
+	}
+
+	previous := onu.MibDataSync
+	onu.InvalidateMibDataSync()
+
+	res.StatusCode = int32(codes.OK)
+	res.Message = fmt.Sprintf("MDS counter of ONU %s was %d, set to %d).", onu.Sn(), previous, onu.MibDataSync)
+
+	return res, nil
+}
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index e40c854..97c1adc 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -21,6 +21,7 @@
 	"encoding/binary"
 	"encoding/hex"
 	"fmt"
+	"math/rand"
 	"sync"
 
 	"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
@@ -1778,3 +1779,16 @@
 		return 1
 	}
 }
+
+func (o *Onu) InvalidateMibDataSync() {
+	rand.Seed(time.Now().UnixNano())
+	r := uint8(rand.Intn(10) + 1)
+
+	o.MibDataSync += r
+
+	// Since MibDataSync is a uint8, summing to it will never
+	// result in a value higher than 255, but could be 0
+	if o.MibDataSync == 0 {
+		o.MibDataSync++
+	}
+}
diff --git a/internal/bbsim/devices/onu_omci_test.go b/internal/bbsim/devices/onu_omci_test.go
index 2c2b489..751bf08 100644
--- a/internal/bbsim/devices/onu_omci_test.go
+++ b/internal/bbsim/devices/onu_omci_test.go
@@ -17,6 +17,9 @@
 package devices
 
 import (
+	"strconv"
+	"testing"
+
 	"github.com/google/gopacket"
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
 	omcilib "github.com/opencord/bbsim/internal/common/omci"
@@ -24,8 +27,6 @@
 	me "github.com/opencord/omci-lib-go/v2/generated"
 	"github.com/opencord/voltha-protos/v5/go/openolt"
 	"gotest.tools/assert"
-	"strconv"
-	"testing"
 )
 
 var mockAttr = me.AttributeValueMap{
@@ -312,6 +313,21 @@
 	assert.Equal(t, onu.MibDataSync, uint8(0))
 }
 
+func Test_MibDataSyncInvalidation(t *testing.T) {
+	onu := createMockOnu(1, 1)
+	onu.MibDataSync = 250
+	assert.Equal(t, onu.MibDataSync, uint8(250))
+
+	onu.InvalidateMibDataSync()
+
+	// check if the MDS has been changed
+	assert.Assert(t, onu.MibDataSync != uint8(250))
+
+	// the MDS has to be between 1 and 255, since 0 is valid for a reset
+	assert.Assert(t, onu.MibDataSync > 0)
+	assert.Assert(t, onu.MibDataSync <= 255)
+}
+
 func Test_GemPortValidation(t *testing.T) {
 
 	// setup
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index f929f39..80e5f0d 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -115,6 +115,12 @@
 	} `positional-args:"yes"`
 }
 
+type ONUInvalidateMds struct {
+	Args struct {
+		OnuSn OnuSnString
+	} `positional-args:"yes" required:"yes"`
+}
+
 type ONUOptions struct {
 	List              ONUList              `command:"list"`
 	Get               ONUGet               `command:"get"`
@@ -127,6 +133,7 @@
 	Alarms            AlarmOptions         `command:"alarms"`
 	Flows             ONUFlows             `command:"flows"`
 	Services          ONUServices          `command:"services"`
+	InvalidateMds     ONUInvalidateMds     `command:"invalidate_mds"`
 }
 
 func RegisterONUCommands(parser *flags.Parser) {
@@ -400,6 +407,27 @@
 	return nil
 }
 
+func (options *ONUInvalidateMds) Execute(args []string) error {
+	client, conn := connect()
+	defer conn.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+	defer cancel()
+	req := pb.ONURequest{
+		SerialNumber: string(options.Args.OnuSn),
+	}
+	res, err := client.InvalidateMds(ctx, &req)
+
+	if err != nil {
+		log.Fatalf("Cannot invalidate MDS counter on ONU %s: %v", options.Args.OnuSn, err)
+		return err
+	}
+
+	fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+
+	return nil
+}
+
 func (onuSn *OnuSnString) Complete(match string) []flags.Completion {
 	client, conn := connect()
 	defer conn.Close()