[VOL-4437] Adding support for unkown attributes

Change-Id: I54b1fbefdb75ca3ec4abfc83b57b232d07c76873
diff --git a/VERSION b/VERSION
index 1cac385..0eed1a2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.11.0
+1.12.0
diff --git a/cmd/bbsim/bbsim.go b/cmd/bbsim/bbsim.go
index b51ff86..b5b613f 100644
--- a/cmd/bbsim/bbsim.go
+++ b/cmd/bbsim/bbsim.go
@@ -146,21 +146,22 @@
 	}
 
 	log.WithFields(log.Fields{
-		"OltID":                common.Config.Olt.ID,
-		"NumNniPerOlt":         common.Config.Olt.NniPorts,
-		"NumPonPerOlt":         common.Config.Olt.PonPorts,
-		"NumOnuPerPon":         common.Config.Olt.OnusPonPort,
-		"PonConfiguration":     *common.PonsConfig,
-		"TotalOnus":            common.Config.Olt.PonPorts * common.Config.Olt.OnusPonPort,
-		"Delay":                common.Config.BBSim.Delay,
-		"Events":               common.Config.BBSim.Events,
-		"KafkaEventTopic":      common.Config.BBSim.KafkaEventTopic,
-		"ControlledActivation": common.Config.BBSim.ControlledActivation,
-		"EnablePerf":           common.Config.BBSim.EnablePerf,
-		"DhcpRetry":            common.Config.BBSim.DhcpRetry,
-		"AuthRetry":            common.Config.BBSim.AuthRetry,
-		"OltRebootDelay":       common.Config.Olt.OltRebootDelay,
-		"OmciResponseRate":     common.Config.Olt.OmciResponseRate,
+		"OltID":                       common.Config.Olt.ID,
+		"NumNniPerOlt":                common.Config.Olt.NniPorts,
+		"NumPonPerOlt":                common.Config.Olt.PonPorts,
+		"NumOnuPerPon":                common.Config.Olt.OnusPonPort,
+		"PonConfiguration":            *common.PonsConfig,
+		"TotalOnus":                   common.Config.Olt.PonPorts * common.Config.Olt.OnusPonPort,
+		"Delay":                       common.Config.BBSim.Delay,
+		"Events":                      common.Config.BBSim.Events,
+		"KafkaEventTopic":             common.Config.BBSim.KafkaEventTopic,
+		"ControlledActivation":        common.Config.BBSim.ControlledActivation,
+		"EnablePerf":                  common.Config.BBSim.EnablePerf,
+		"DhcpRetry":                   common.Config.BBSim.DhcpRetry,
+		"AuthRetry":                   common.Config.BBSim.AuthRetry,
+		"OltRebootDelay":              common.Config.Olt.OltRebootDelay,
+		"OmciResponseRate":            common.Config.Olt.OmciResponseRate,
+		"injectOmciUnknownAttributes": common.Config.BBSim.InjectOmciUnknownAttributes,
 	}).Info("BroadBand Simulator is on")
 
 	// control channels, they are only closed when the goroutine needs to be terminated
diff --git a/docs/source/bbsim_config.rst b/docs/source/bbsim_config.rst
index 78146f9..279e606 100644
--- a/docs/source/bbsim_config.rst
+++ b/docs/source/bbsim_config.rst
@@ -33,6 +33,8 @@
            Enable sending BBSim events on configured kafka server
      -enableperf
            Setting this flag will cause BBSim to not store data like traffic schedulers, flows of ONUs etc..
+     -injectOmciUnknownAttributes
+           Generate a MibDB packet with Unknown Attributes
      -kafkaAddress string
            IP:Port for kafka (default ":9092")
      -kafkaEventTopic string
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
index 9578416..2214f2e 100644
--- a/internal/common/omci/mib_test.go
+++ b/internal/common/omci/mib_test.go
@@ -17,6 +17,8 @@
 package omci
 
 import (
+	"encoding/binary"
+	"reflect"
 	"testing"
 
 	"github.com/google/gopacket"
@@ -45,6 +47,16 @@
 	assert.Equal(t, msgObj.Result, me.Success)
 }
 
+func TestSetTxIdInEncodedPacket(t *testing.T) {
+	basePkt := []byte{129, 42, 46, 10, 0, 2, 0, 0, 0, 37, 0, 1, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, 0, 40, 40, 206, 0, 226}
+	res := SetTxIdInEncodedPacket(basePkt, uint16(292))
+	assert.Equal(t, len(basePkt), len(res))
+
+	b := res[0:2]
+	txId := binary.BigEndian.Uint16(b)
+	assert.Equal(t, uint16(292), txId)
+}
+
 // types for TestCreateMibUploadNextResponse test
 type mibArgs struct {
 	omciPkt gopacket.Packet
@@ -92,6 +104,7 @@
 		me.OnuDataClassID,
 		onuDataEntityId,
 		me.AttributeValueMap{me.OnuData_MibDataSync: 0},
+		nil,
 	})
 
 	mibDb.items = append(mibDb.items, MibDbEntry{
@@ -103,6 +116,7 @@
 			me.CircuitPack_SerialNumber:  ToOctets("BBSM-Circuit-Pack", 20),
 			me.CircuitPack_Version:       ToOctets("v0.0.1", 20),
 		},
+		nil,
 	})
 
 	mibDb.items = append(mibDb.items, MibDbEntry{
@@ -126,6 +140,7 @@
 			me.AniG_UpperOpticalThreshold:       255,
 			me.AniG_UpperTransmitPowerThreshold: 129,
 		},
+		nil,
 	})
 
 	mibDb.items = append(mibDb.items, MibDbEntry{
@@ -142,6 +157,17 @@
 			me.Onu2G_TotalPriorityQueueNumber:                    64,
 			me.Onu2G_TotalTrafficSchedulerNumber:                 8,
 		},
+		nil,
+	})
+
+	// create an entry with UnkownAttributes set
+	var customPktTxId uint16 = 5
+	customPkt := []byte{0, byte(customPktTxId), 46, 10, 0, 2, 0, 0, 0, 37, 0, 1, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, 0, 40, 40, 206, 0, 226}
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.ClassID(37),
+		nil,
+		me.AttributeValueMap{},
+		customPkt,
 	})
 
 	tests := []struct {
@@ -157,6 +183,8 @@
 			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 3, entityID: anigEntityId.ToUint16(), entityClass: me.AniGClassID, attributes: map[string]interface{}{me.AniG_GemBlockLength: uint16(48)}}},
 		{"mibUploadNext-3", createTestMibUploadNextArgs(t, 4, 3),
 			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 4, entityID: onuDataEntityId.ToUint16(), entityClass: me.Onu2GClassID, attributes: map[string]interface{}{me.Onu2G_TotalPriorityQueueNumber: uint16(64)}}},
+		{"mibUploadNext-unknown-attrs", createTestMibUploadNextArgs(t, 5, 4),
+			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: customPktTxId, entityID: 1, entityClass: me.ClassID(37), attributes: map[string]interface{}{"UnknownAttr_1": []uint8{1}}}},
 	}
 
 	for _, tt := range tests {
@@ -182,7 +210,15 @@
 			for k, v := range tt.want.attributes {
 				attr, err := msgObj.ReportedME.GetAttribute(k)
 				assert.NilError(t, err)
-				assert.Equal(t, attr, v)
+				if isSlice(attr) {
+					expected := v.([]uint8)
+					data := attr.([]uint8)
+					for i, val := range data {
+						assert.Equal(t, expected[i], val)
+					}
+				} else {
+					assert.Equal(t, attr, v)
+				}
 			}
 		})
 	}
@@ -192,3 +228,7 @@
 	_, err := CreateMibUploadNextResponse(args.omciPkt, args.omciMsg, MDS, &mibDb)
 	assert.Error(t, err, "mibdb-does-not-contain-item")
 }
+
+func isSlice(v interface{}) bool {
+	return reflect.TypeOf(v).Kind() == reflect.Slice
+}
diff --git a/internal/common/omci/mibpackets.go b/internal/common/omci/mibpackets.go
index 8b7afcb..d22908d 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -17,6 +17,7 @@
 package omci
 
 import (
+	"encoding/binary"
 	"errors"
 	"fmt"
 	"github.com/google/gopacket"
@@ -47,6 +48,15 @@
 	return buffer.Bytes(), nil
 }
 
+func SetTxIdInEncodedPacket(packet []byte, txId uint16) []byte {
+	valid := packet[2:]
+
+	b := make([]byte, 2)
+	binary.BigEndian.PutUint16(b, txId)
+
+	return append(b, valid...)
+}
+
 func CreateMibResetRequest(tid uint16) ([]byte, error) {
 
 	request := &omci.MibResetRequest{
@@ -106,6 +116,9 @@
 		},
 		NumberOfCommands: numberOfCommands,
 	}
+
+	omciLogger.WithFields(log.Fields{"NumberOfCommands": numberOfCommands}).Debug("mib-upload-response")
+
 	pkt, err := Serialize(omci.MibUploadResponseType, request, tid)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
@@ -175,6 +188,22 @@
 		return nil, fmt.Errorf("mibdb-does-not-contain-item")
 	}
 	currentEntry := mibDb.items[int(msgObj.CommandSequenceNumber)]
+
+	// if packet is set then we don't need to serialize the packet, it's already done
+	if currentEntry.packet != nil {
+		omciLogger.WithFields(log.Fields{
+			"CommandSequenceNumber": msgObj.CommandSequenceNumber,
+			"MibDbNumberOfCommands": mibDb.NumberOfCommands,
+			"packet":                currentEntry.packet,
+			"request-txid":          omciMsg.TransactionID,
+		}).Info("sending-custom-packet")
+
+		// NOTE we need to replace the first two bytes of the packet with the correct transactionId
+		pkt := SetTxIdInEncodedPacket(currentEntry.packet, omciMsg.TransactionID)
+
+		return pkt, nil
+	}
+
 	reportedMe, meErr := me.LoadManagedEntityDefinition(currentEntry.classId, me.ParamData{
 		EntityID:   currentEntry.entityId.ToUint16(),
 		Attributes: currentEntry.params,
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
index 2902fd2..23d2e99 100644
--- a/internal/common/omci/onu_mib_db.go
+++ b/internal/common/omci/onu_mib_db.go
@@ -20,15 +20,20 @@
 	"bytes"
 	"encoding/binary"
 	"encoding/hex"
-
+	"github.com/google/gopacket"
 	"github.com/opencord/bbsim/internal/common"
+	"github.com/opencord/omci-lib-go/v2"
 	me "github.com/opencord/omci-lib-go/v2/generated"
 )
 
+// MibDbEntry contains all the information needed to build a
+// MibUploadNextResponse packet.
+// if Packet has a value all the other fields are ignored and the packet is sent as is.
 type MibDbEntry struct {
 	classId  me.ClassID
 	entityId EntityID
 	params   me.AttributeValueMap
+	packet   []byte
 }
 
 type MibDb struct {
@@ -105,6 +110,7 @@
 		me.OnuDataClassID,
 		EntityID{0x00, 0x00},
 		me.AttributeValueMap{me.OnuData_MibDataSync: 0}, // FIXME this needs to be parametrized before sending the response
+		nil,
 	})
 
 	// then we report the CardHolder
@@ -137,6 +143,7 @@
 			me.CircuitPack_SerialNumber:  ToOctets("BBSM-Circuit-Pack-ani", 20),
 			me.CircuitPack_Version:       ToOctets("v0.0.1", 20),
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -147,6 +154,7 @@
 			me.CircuitPack_OperationalState:    0,
 			me.CircuitPack_BridgedOrIpInd:      0,
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -158,6 +166,7 @@
 			me.CircuitPack_TotalPriorityQueueNumber:    8,
 			me.CircuitPack_TotalTrafficSchedulerNumber: 0,
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -165,6 +174,7 @@
 		me.AttributeValueMap{
 			me.CircuitPack_PowerShedOverride: uint32(0),
 		},
+		nil,
 	})
 
 	// ANI-G
@@ -189,6 +199,7 @@
 			me.AniG_UpperOpticalThreshold:       255,
 			me.AniG_UpperTransmitPowerThreshold: 129,
 		},
+		nil,
 	})
 
 	// circuitPack Ethernet
@@ -202,6 +213,7 @@
 			me.CircuitPack_SerialNumber:  ToOctets("BBSM-Circuit-Pack", 20),
 			me.CircuitPack_Version:       ToOctets("v0.0.1", 20),
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -212,6 +224,7 @@
 			me.CircuitPack_OperationalState:    0,
 			me.CircuitPack_BridgedOrIpInd:      0,
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -223,6 +236,7 @@
 			me.CircuitPack_TotalPriorityQueueNumber:    8,
 			me.CircuitPack_TotalTrafficSchedulerNumber: 16,
 		},
+		nil,
 	})
 	mibDb.items = append(mibDb.items, MibDbEntry{
 		me.CircuitPackClassID,
@@ -230,6 +244,7 @@
 		me.AttributeValueMap{
 			me.CircuitPack_PowerShedOverride: uint32(0),
 		},
+		nil,
 	})
 
 	if potsUniPortCount > 0 {
@@ -244,6 +259,7 @@
 				me.CircuitPack_SerialNumber:  ToOctets("BBSM-Circuit-Pack", 20),
 				me.CircuitPack_Version:       ToOctets("v0.0.1", 20),
 			},
+			nil,
 		})
 		mibDb.items = append(mibDb.items, MibDbEntry{
 			me.CircuitPackClassID,
@@ -254,6 +270,7 @@
 				me.CircuitPack_OperationalState:    0,
 				me.CircuitPack_BridgedOrIpInd:      0,
 			},
+			nil,
 		})
 		mibDb.items = append(mibDb.items, MibDbEntry{
 			me.CircuitPackClassID,
@@ -265,6 +282,7 @@
 				me.CircuitPack_TotalPriorityQueueNumber:    8,
 				me.CircuitPack_TotalTrafficSchedulerNumber: 16,
 			},
+			nil,
 		})
 		mibDb.items = append(mibDb.items, MibDbEntry{
 			me.CircuitPackClassID,
@@ -272,6 +290,7 @@
 			me.AttributeValueMap{
 				me.CircuitPack_PowerShedOverride: uint32(0),
 			},
+			nil,
 		})
 	}
 
@@ -304,6 +323,7 @@
 					me.PhysicalPathTerminationPointEthernetUni_PppoeFilter:                   0,
 					me.PhysicalPathTerminationPointEthernetUni_PowerControl:                  0,
 				},
+				nil,
 			})
 		} else {
 			// the remaining ones are pots UNIs, the same is done in onu.go
@@ -325,6 +345,7 @@
 					me.PhysicalPathTerminationPointPotsUni_NominalFeedVoltage:  0,
 					me.PhysicalPathTerminationPointPotsUni_LossOfSoftswitch:    0,
 				},
+				nil,
 			})
 		}
 
@@ -338,6 +359,7 @@
 				me.UniG_NonOmciManagementIdentifier: 0,
 				me.UniG_RelayAgentOptions:           0,
 			},
+			nil,
 		})
 
 		// Downstream Queues (related to PPTP)
@@ -351,6 +373,7 @@
 				me.PriorityQueueClassID,
 				queueEntityId, //was not reported in the original implementation
 				me.AttributeValueMap{},
+				nil,
 			})
 
 			// then we report it with the required attributes
@@ -373,6 +396,7 @@
 					me.PriorityQueue_BackPressureOccurQueueThreshold:                     0,
 					me.PriorityQueue_BackPressureClearQueueThreshold:                     0,
 				},
+				nil,
 			})
 		}
 	}
@@ -387,6 +411,7 @@
 			me.AttributeValueMap{
 				me.TCont_AllocId: 65535,
 			},
+			nil,
 		})
 
 		tsEntityId := EntityID{cardHolderSlotID, byte(i)}
@@ -399,6 +424,7 @@
 				me.TrafficScheduler_Policy:                  02,
 				me.TrafficScheduler_PriorityWeight:          0,
 			},
+			nil,
 		})
 
 		for j := 1; j <= upstreamPriorityQueues; j++ {
@@ -412,6 +438,7 @@
 				me.PriorityQueueClassID,
 				queueEntityId, //was not reported in the original implementation
 				me.AttributeValueMap{},
+				nil,
 			})
 
 			// then we report it with the required attributes
@@ -434,6 +461,7 @@
 					me.PriorityQueue_BackPressureOccurQueueThreshold:                     0,
 					me.PriorityQueue_BackPressureClearQueueThreshold:                     0,
 				},
+				nil,
 			})
 		}
 	}
@@ -453,8 +481,41 @@
 			me.Onu2G_TotalPriorityQueueNumber:                    64,
 			me.Onu2G_TotalTrafficSchedulerNumber:                 8,
 		},
+		nil,
 	})
 
+	if common.Config.BBSim.InjectOmciUnknownAttributes {
+		// NOTE the TxID is actually replaced
+		// by SetTxIdInEncodedPacket in CreateMibUploadNextResponse
+		txId := uint16(33066)
+
+		b := make([]byte, 4)
+		binary.BigEndian.PutUint16(b, txId)
+		b[2] = byte(omci.MibUploadNextResponseType)
+		b[3] = byte(omci.BaselineIdent)
+		omciHdr := hex.EncodeToString(b)
+
+		//omciHdr := "00032e0a"
+		msgHdr := "00020000"
+		reportedMeHdr := "002500018000"
+		attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+		trailer := "0000002828ce00e2"
+		msg := omciHdr + msgHdr + reportedMeHdr + attr + trailer
+		data, err := hex.DecodeString(msg)
+		if err != nil {
+			omciLogger.Fatal("cannot-create-custom-packet")
+		}
+
+		packet := gopacket.NewPacket(data, omci.LayerTypeOMCI, gopacket.Lazy)
+
+		mibDb.items = append(mibDb.items, MibDbEntry{
+			me.ClassID(37), // G.988 "Intentionally left blank"
+			nil,
+			me.AttributeValueMap{},
+			packet.Data(),
+		})
+	}
+
 	mibDb.NumberOfCommands = uint16(len(mibDb.items))
 
 	return &mibDb, nil
diff --git a/internal/common/omci/onu_mib_db_test.go b/internal/common/omci/onu_mib_db_test.go
index 2794aa4..7a589ad 100644
--- a/internal/common/omci/onu_mib_db_test.go
+++ b/internal/common/omci/onu_mib_db_test.go
@@ -17,9 +17,11 @@
 package omci
 
 import (
+	"fmt"
+	"github.com/google/gopacket"
+	"github.com/opencord/bbsim/internal/common"
 	"testing"
 
-	"github.com/opencord/bbsim/internal/common"
 	"github.com/opencord/omci-lib-go/v2"
 	me "github.com/opencord/omci-lib-go/v2/generated"
 	"github.com/stretchr/testify/assert"
@@ -56,6 +58,11 @@
 }
 
 func Test_GenerateMibDatabase(t *testing.T) {
+	common.Config = &common.GlobalConfig{
+		BBSim: common.BBSimConfig{
+			InjectOmciUnknownAttributes: false,
+		},
+	}
 	const uniPortCount = 4
 	mibDb, err := GenerateMibDatabase(uniPortCount, 0, common.XGSPON)
 
@@ -93,6 +100,11 @@
 }
 
 func Test_GenerateMibDatabase_withPots(t *testing.T) {
+	common.Config = &common.GlobalConfig{
+		BBSim: common.BBSimConfig{
+			InjectOmciUnknownAttributes: false,
+		},
+	}
 	const uniPortCount = 4
 	const potsPortCount = 1
 	mibDb, err := GenerateMibDatabase(uniPortCount, potsPortCount, common.XGSPON)
@@ -129,3 +141,38 @@
 	}
 
 }
+
+func Test_GenerateMibDatabase_withUnkownAttrs(t *testing.T) {
+
+	common.Config = &common.GlobalConfig{
+		BBSim: common.BBSimConfig{
+			InjectOmciUnknownAttributes: true,
+		},
+	}
+
+	const uniPortCount = 4
+	const baseMibEntries = 291                    // see Test_GenerateMibDatabase for breakdown
+	const expectedMibEntries = baseMibEntries + 1 // expecting one hardcoded packet
+	mibDb, err := GenerateMibDatabase(uniPortCount, 0, common.XGSPON)
+
+	assert.NoError(t, err)
+	assert.NotNil(t, mibDb)
+	assert.Equal(t, expectedMibEntries, int(mibDb.NumberOfCommands))
+
+	entry := mibDb.items[expectedMibEntries-1] // select the last entry, it's the hardcoded packet
+	fmt.Println(entry.packet)
+	assert.NotNil(t, entry)
+	assert.Equal(t, me.ClassID(37), entry.classId)
+	assert.Nil(t, entry.entityId)
+	assert.Equal(t, 0, len(entry.params))
+	assert.NotNil(t, entry.packet)
+
+	// check that we're generating a valid OMCI payload
+	packet := gopacket.NewPacket(entry.packet, omci.LayerTypeOMCI, gopacket.Lazy)
+	omciLayer := packet.Layer(omci.LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+	omciMsg, ok := omciLayer.(*omci.OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, omci.MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, uint16(33066), omciMsg.TransactionID)
+}
diff --git a/internal/common/options.go b/internal/common/options.go
index 58cec20..494473c 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -164,29 +164,30 @@
 }
 
 type BBSimConfig struct {
-	ConfigFile             string
-	ServiceConfigFile      string
-	PonsConfigFile         string
-	DhcpRetry              bool    `yaml:"dhcp_retry"`
-	AuthRetry              bool    `yaml:"auth_retry"`
-	LogLevel               string  `yaml:"log_level"`
-	LogCaller              bool    `yaml:"log_caller"`
-	Delay                  int     `yaml:"delay"`
-	CpuProfile             *string `yaml:"cpu_profile"`
-	OpenOltAddress         string  `yaml:"openolt_address"`
-	ApiAddress             string  `yaml:"api_address"`
-	RestApiAddress         string  `yaml:"rest_api_address"`
-	LegacyApiAddress       string  `yaml:"legacy_api_address"`
-	LegacyRestApiAddress   string  `yaml:"legacy_rest_api_address"`
-	SadisRestAddress       string  `yaml:"sadis_rest_address"`
-	SadisServer            bool    `yaml:"sadis_server"`
-	KafkaAddress           string  `yaml:"kafka_address"`
-	Events                 bool    `yaml:"enable_events"`
-	ControlledActivation   string  `yaml:"controlled_activation"`
-	EnablePerf             bool    `yaml:"enable_perf"`
-	KafkaEventTopic        string  `yaml:"kafka_event_topic"`
-	DmiServerAddress       string  `yaml:"dmi_server_address"`
-	BandwidthProfileFormat string  `yaml:"bp_format"`
+	ConfigFile                  string
+	ServiceConfigFile           string
+	PonsConfigFile              string
+	DhcpRetry                   bool    `yaml:"dhcp_retry"`
+	AuthRetry                   bool    `yaml:"auth_retry"`
+	LogLevel                    string  `yaml:"log_level"`
+	LogCaller                   bool    `yaml:"log_caller"`
+	Delay                       int     `yaml:"delay"`
+	CpuProfile                  *string `yaml:"cpu_profile"`
+	OpenOltAddress              string  `yaml:"openolt_address"`
+	ApiAddress                  string  `yaml:"api_address"`
+	RestApiAddress              string  `yaml:"rest_api_address"`
+	LegacyApiAddress            string  `yaml:"legacy_api_address"`
+	LegacyRestApiAddress        string  `yaml:"legacy_rest_api_address"`
+	SadisRestAddress            string  `yaml:"sadis_rest_address"`
+	SadisServer                 bool    `yaml:"sadis_server"`
+	KafkaAddress                string  `yaml:"kafka_address"`
+	Events                      bool    `yaml:"enable_events"`
+	ControlledActivation        string  `yaml:"controlled_activation"`
+	EnablePerf                  bool    `yaml:"enable_perf"`
+	KafkaEventTopic             string  `yaml:"kafka_event_topic"`
+	DmiServerAddress            string  `yaml:"dmi_server_address"`
+	BandwidthProfileFormat      string  `yaml:"bp_format"`
+	InjectOmciUnknownAttributes bool    `yaml:"inject_omci_unknown_attributes"`
 }
 
 type BBRConfig struct {
@@ -355,6 +356,7 @@
 	kafkaEventTopic := flag.String("kafkaEventTopic", conf.BBSim.KafkaEventTopic, "Ability to configure the topic on which BBSim publishes events on Kafka")
 	dhcpRetry := flag.Bool("dhcpRetry", conf.BBSim.DhcpRetry, "Set this flag if BBSim should retry DHCP upon failure until success")
 	authRetry := flag.Bool("authRetry", conf.BBSim.AuthRetry, "Set this flag if BBSim should retry EAPOL (Authentication) upon failure until success")
+	injectOmciUnknownAttributes := flag.Bool("injectOmciUnknownAttributes", conf.BBSim.InjectOmciUnknownAttributes, "Generate a MibDB packet with Unknown Attributes")
 
 	flag.Parse()
 
@@ -385,6 +387,7 @@
 	conf.BBSim.AuthRetry = *authRetry
 	conf.BBSim.DhcpRetry = *dhcpRetry
 	conf.BBSim.DmiServerAddress = *dmi_server_address
+	conf.BBSim.InjectOmciUnknownAttributes = *injectOmciUnknownAttributes
 
 	// update device id if not set
 	if conf.Olt.DeviceId == "" {
@@ -409,26 +412,27 @@
 			// PonsConfigFile is left intentionally blank here
 			// to use the default values computed at runtime depending
 			// on the loaded Services
-			PonsConfigFile:         "",
-			LogLevel:               "debug",
-			LogCaller:              false,
-			Delay:                  200,
-			OpenOltAddress:         ":50060",
-			ApiAddress:             ":50070",
-			RestApiAddress:         ":50071",
-			LegacyApiAddress:       ":50072",
-			LegacyRestApiAddress:   ":50073",
-			SadisRestAddress:       ":50074",
-			SadisServer:            true,
-			KafkaAddress:           ":9092",
-			Events:                 false,
-			ControlledActivation:   "default",
-			EnablePerf:             false,
-			KafkaEventTopic:        "",
-			DhcpRetry:              false,
-			AuthRetry:              false,
-			DmiServerAddress:       ":50075",
-			BandwidthProfileFormat: BP_FORMAT_MEF,
+			PonsConfigFile:              "",
+			LogLevel:                    "debug",
+			LogCaller:                   false,
+			Delay:                       200,
+			OpenOltAddress:              ":50060",
+			ApiAddress:                  ":50070",
+			RestApiAddress:              ":50071",
+			LegacyApiAddress:            ":50072",
+			LegacyRestApiAddress:        ":50073",
+			SadisRestAddress:            ":50074",
+			SadisServer:                 true,
+			KafkaAddress:                ":9092",
+			Events:                      false,
+			ControlledActivation:        "default",
+			EnablePerf:                  false,
+			KafkaEventTopic:             "",
+			DhcpRetry:                   false,
+			AuthRetry:                   false,
+			DmiServerAddress:            ":50075",
+			BandwidthProfileFormat:      BP_FORMAT_MEF,
+			InjectOmciUnknownAttributes: false,
 		},
 		OltConfig{
 			Vendor:             "BBSim",