[VOL-3745] Chaos Monkey: BBSIM-ONU does not respond to OMCI requests

Change-Id: I9d52a05657be448839f0a180126736ec9a33eaaf
diff --git a/VERSION b/VERSION
index bcfbf47..dc1e644 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.0-dev
+1.6.0
diff --git a/cmd/bbsim/bbsim.go b/cmd/bbsim/bbsim.go
index d7a85b9..23a00ef 100644
--- a/cmd/bbsim/bbsim.go
+++ b/cmd/bbsim/bbsim.go
@@ -18,7 +18,6 @@
 
 import (
 	"context"
-	"github.com/opencord/bbsim/internal/bbsim/responders/webserver"
 	"net"
 	"net/http"
 	"os"
@@ -27,6 +26,8 @@
 	"sync"
 	"syscall"
 
+	"github.com/opencord/bbsim/internal/bbsim/responders/webserver"
+
 	"github.com/Shopify/sarama"
 	"github.com/grpc-ecosystem/grpc-gateway/runtime"
 	"github.com/opencord/bbsim/api/bbsim"
@@ -158,6 +159,7 @@
 		"DhcpRetry":            common.Config.BBSim.DhcpRetry,
 		"AuthRetry":            common.Config.BBSim.AuthRetry,
 		"OltRebootDelay":       common.Config.Olt.OltRebootDelay,
+		"OmciResponseRate":     common.Config.Olt.OmciResponseRate,
 	}).Info("BroadBand Simulator is on")
 
 	// control channels, they are only closed when the goroutine needs to be terminated
diff --git a/configs/bbsim.yaml b/configs/bbsim.yaml
index 2f4322f..6265e5c 100644
--- a/configs/bbsim.yaml
+++ b/configs/bbsim.yaml
@@ -40,7 +40,8 @@
   # firmware_version: ""
   # device_id: 0a:0a:0a:0a:0a:<id>
   port_stats_interval: 20 # in seconds
-
+  # omci_response_rate: 10
+  
 # BBR settings
 bbr:
   log: bbr.log
diff --git a/docs/source/bbsim_config.rst b/docs/source/bbsim_config.rst
index 9893583..70089a3 100644
--- a/docs/source/bbsim_config.rst
+++ b/docs/source/bbsim_config.rst
@@ -53,6 +53,9 @@
             IP address:port (default ":50071")
       -services string
             Service Configuration file path (default "configs/att-services.yaml")
+      -omci_response_rate int
+            Amount of OMCI messages to respond to - ranges from 0 (drop all messages)
+            to 10 (respond to all messages) so that if it's set to 9 we don't respond to every 10th message.
 
 
 
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index 1c4e099..746a58b 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -20,15 +20,16 @@
 	"context"
 	"encoding/hex"
 	"fmt"
-	"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
-	"github.com/opencord/bbsim/internal/bbsim/types"
-	omcilib "github.com/opencord/bbsim/internal/common/omci"
-	"github.com/opencord/voltha-protos/v4/go/ext/config"
 	"net"
 	"strconv"
 	"sync"
 	"time"
 
+	"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
+	"github.com/opencord/bbsim/internal/bbsim/types"
+	omcilib "github.com/opencord/bbsim/internal/common/omci"
+	"github.com/opencord/voltha-protos/v4/go/ext/config"
+
 	"github.com/google/gopacket"
 	"github.com/google/gopacket/layers"
 	"github.com/looplab/fsm"
@@ -94,10 +95,11 @@
 
 	// Allocated Resources
 	// this data are to verify that the openolt adapter does not duplicate resources
-	AllocIDsLock   sync.RWMutex
-	AllocIDs       map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
-	GemPortIDsLock sync.RWMutex
-	GemPortIDs     map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
+	AllocIDsLock     sync.RWMutex
+	AllocIDs         map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
+	GemPortIDsLock   sync.RWMutex
+	GemPortIDs       map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
+	OmciResponseRate uint8
 }
 
 var olt OltDevice
@@ -133,6 +135,7 @@
 		PreviouslyConnected: false,
 		AllocIDs:            make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
 		GemPortIDs:          make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
+		OmciResponseRate:    options.Olt.OmciResponseRate,
 	}
 
 	if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index 466f383..e2ed180 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -20,18 +20,20 @@
 	"context"
 	"encoding/hex"
 	"fmt"
+	"sync"
+
 	pb "github.com/opencord/bbsim/api/bbsim"
 	"github.com/opencord/bbsim/internal/bbsim/alarmsim"
-	"sync"
+
+	"net"
+	"strconv"
+	"time"
 
 	"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
 	"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
 	"github.com/opencord/bbsim/internal/bbsim/responders/eapol"
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
 	me "github.com/opencord/omci-lib-go/generated"
-	"net"
-	"strconv"
-	"time"
 
 	"github.com/google/gopacket/layers"
 	"github.com/jpillora/backoff"
@@ -49,6 +51,10 @@
 })
 
 const (
+	maxOmciMsgCounter = 10
+)
+
+const (
 	// ONU transitions
 	OnuTxInitialize            = "initialize"
 	OnuTxDiscover              = "discover"
@@ -118,6 +124,8 @@
 	ImageSoftwareReceivedSections int
 	ActiveImageEntityId           uint16
 	CommittedImageEntityId        uint16
+	OmciResponseRate              uint8
+	OmciMsgCounter                uint8
 
 	// OMCI params (Used in BBR)
 	tid       uint16
@@ -153,6 +161,8 @@
 		ImageSoftwareReceivedSections: 0,
 		ActiveImageEntityId:           0, // when we start the SoftwareImage with ID 0 is active and committed
 		CommittedImageEntityId:        0,
+		OmciResponseRate:              olt.OmciResponseRate,
+		OmciMsgCounter:                0,
 	}
 	o.SerialNumber = NewSN(olt.ID, pon.ID, id)
 	// NOTE this state machine is used to track the operational
@@ -732,6 +742,19 @@
 		"SerialNumber": o.Sn(),
 	}).Trace("omci-message-decoded")
 
+	if o.OmciMsgCounter < maxOmciMsgCounter {
+		o.OmciMsgCounter++
+	} else {
+		o.OmciMsgCounter = 1
+	}
+	if o.OmciMsgCounter > o.OmciResponseRate {
+		onuLogger.WithFields(log.Fields{
+			"OmciMsgCounter":   o.OmciMsgCounter,
+			"OmciResponseRate": o.OmciResponseRate,
+			"omciMsgType":      msg.OmciMsg.MessageType,
+		}).Debug("skip-omci-msg-response")
+		return
+	}
 	var responsePkt []byte
 	var errResp error
 	switch msg.OmciMsg.MessageType {
diff --git a/internal/bbsim/devices/onu_omci_test.go b/internal/bbsim/devices/onu_omci_test.go
index 246514b..20f8a35 100644
--- a/internal/bbsim/devices/onu_omci_test.go
+++ b/internal/bbsim/devices/onu_omci_test.go
@@ -17,6 +17,8 @@
 package devices
 
 import (
+	"testing"
+
 	"github.com/google/gopacket"
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
 	omcilib "github.com/opencord/bbsim/internal/common/omci"
@@ -24,7 +26,6 @@
 	me "github.com/opencord/omci-lib-go/generated"
 	"github.com/opencord/voltha-protos/v4/go/openolt"
 	"gotest.tools/assert"
-	"testing"
 )
 
 var mockAttr = me.AttributeValueMap{
@@ -240,3 +241,21 @@
 	responseLayer = omciToCreateResponse(t, omciPkt)
 	assert.Equal(t, responseLayer.Result, me.ProcessingError)
 }
+
+func Test_OmciResponseRate(t *testing.T) {
+
+	onu := createMockOnu(1, 1)
+
+	for onu.OmciResponseRate = 0; onu.OmciResponseRate <= maxOmciMsgCounter; onu.OmciResponseRate++ {
+		//t.Logf("onu.OmciResponseRate: %d", onu.OmciResponseRate)
+		stream := &mockStream{
+			Calls: make(map[int]*openolt.Indication),
+		}
+		//send ten OMCI requests and check if number of responses is only equal to onu.OmciResponseRate
+		for i := 0; i < 10; i++ {
+			onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciSetRequest(t)), stream)
+			//t.Logf("stream.CallCount: %d", stream.CallCount)
+		}
+		assert.Equal(t, stream.CallCount, int(onu.OmciResponseRate))
+	}
+}
diff --git a/internal/bbsim/devices/onu_test_helpers.go b/internal/bbsim/devices/onu_test_helpers.go
index 2f18199..e441e73 100644
--- a/internal/bbsim/devices/onu_test_helpers.go
+++ b/internal/bbsim/devices/onu_test_helpers.go
@@ -19,10 +19,11 @@
 import (
 	"context"
 	"errors"
+	"time"
+
 	"github.com/opencord/bbsim/internal/bbsim/types"
 	"github.com/opencord/voltha-protos/v4/go/common"
 	"github.com/opencord/voltha-protos/v4/go/ext/config"
-	"time"
 
 	"github.com/opencord/voltha-protos/v4/go/openolt"
 	"github.com/opencord/voltha-protos/v4/go/tech_profile"
@@ -145,6 +146,8 @@
 			AllocatedAllocIds: make(map[uint16]*openolt.SerialNumber),
 			Olt:               &OltDevice{},
 		},
+		OmciResponseRate: 10,
+		OmciMsgCounter:   0,
 	}
 	o.SerialNumber = NewSN(0, ponPortId, o.ID)
 	o.Channel = make(chan types.Message, 10)
diff --git a/internal/common/options.go b/internal/common/options.go
index 9978d9e..a8010be 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -86,6 +86,7 @@
 	ID                 int    `yaml:"id"`
 	OltRebootDelay     int    `yaml:"reboot_delay"`
 	PortStatsInterval  int    `yaml:"port_stats_interval"`
+	OmciResponseRate   uint8  `yaml:"omci_response_rate"`
 }
 
 type BBSimConfig struct {
@@ -223,6 +224,7 @@
 	pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
 	onu := flag.Int("onu", int(conf.Olt.OnusPonPort), "Number of ONU devices per PON port to be emulated")
 	oltRebootDelay := flag.Int("oltRebootDelay", conf.Olt.OltRebootDelay, "Time that BBSim should before restarting after a reboot")
+	omci_response_rate := flag.Int("omci_response_rate", int(conf.Olt.OmciResponseRate), "Amount of OMCI messages to respond to")
 
 	openolt_address := flag.String("openolt_address", conf.BBSim.OpenOltAddress, "IP address:port")
 	api_address := flag.String("api_address", conf.BBSim.ApiAddress, "IP address:port")
@@ -251,6 +253,7 @@
 	conf.Olt.PonPorts = uint32(*pon)
 	conf.Olt.OnusPonPort = uint32(*onu)
 	conf.Olt.OltRebootDelay = *oltRebootDelay
+	conf.Olt.OmciResponseRate = uint8(*omci_response_rate)
 	conf.BBSim.ConfigFile = *configFile
 	conf.BBSim.ServiceConfigFile = *servicesFile
 	conf.BBSim.CpuProfile = profileCpu
@@ -315,6 +318,7 @@
 			ID:                 0,
 			OltRebootDelay:     60,
 			PortStatsInterval:  20,
+			OmciResponseRate:   10,
 		},
 		BBRConfig{
 			LogLevel:  "debug",