[VOL-4111] Dinamically generating the MibDB during ONU creation and use
that to drive the MibUploadNextResponse generation

Change-Id: I67dbbe0700a7fbec802516fc6b2a9aff496022de
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
new file mode 100644
index 0000000..c8696a7
--- /dev/null
+++ b/internal/common/omci/onu_mib_db.go
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package omci
+
+import (
+	"encoding/binary"
+	"encoding/hex"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type MibDbEntry struct {
+	classId  me.ClassID
+	entityId EntityID
+	params   me.AttributeValueMap
+}
+
+type MibDb struct {
+	NumberOfCommands uint16
+	items            []MibDbEntry
+}
+
+type EntityID []byte
+
+func (e EntityID) ToString() string {
+	return hex.EncodeToString(e)
+}
+
+func (e EntityID) ToUint16() uint16 {
+	return binary.BigEndian.Uint16(e)
+}
+
+func (e EntityID) ToUint32() uint32 {
+	return binary.BigEndian.Uint32(e)
+}
+
+const (
+	cardHolderOnuType byte = 0x01 // ONU is a single piece of integrated equipment
+	ethernetUnitType  byte = 0x2f // Ethernet BASE-T
+	xgsPonUnitType    byte = 0xee // XG-PON10G10
+	cardHolderSlotID  byte = 0x01
+	tcontSlotId       byte = 0x80 // why is this not the same as the cardHolderSlotID, it does not point to anything
+	aniGId            byte = 0x01
+
+	upstreamPriorityQueues   = 8  // Number of queues for each T-CONT
+	downstreamPriorityQueues = 16 // Number of queues for each PPTP
+	tconts                   = 8  // NOTE will we ever need to configure this?
+	// trafficSchedulers        = 8  // NOTE will we ever need to configure this?
+)
+
+var (
+	cardHolderEntityID  = EntityID{cardHolderOnuType, cardHolderSlotID}
+	circuitPackEntityID = cardHolderEntityID // is the same as that of the cardholder ME containing this circuit pack instance
+)
+
+func GenerateUniPortEntityId(id uint32) EntityID {
+	return EntityID{cardHolderSlotID, byte(id)}
+}
+
+// creates a MIB database for a ONU
+// CircuitPack and CardHolder are static, everything else can be configured
+func GenerateMibDatabase(uniPortCount int) (*MibDb, error) {
+
+	mibDb := MibDb{
+		items: []MibDbEntry{},
+	}
+
+	// the first element to return is the ONU-Data
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.OnuDataClassID,
+		EntityID{0x00, 0x00},
+		me.AttributeValueMap{"MibDataSync": 0}, // FIXME this needs to be parametrized before sending the response
+	})
+
+	// then we report the CardHolder
+	// NOTE we have not report it till now, so leave it commented out
+	//mibDb.items = append(mibDb.items, MibDbEntry{
+	//	me.CardholderClassID,
+	//	cardHolderEntityID,
+	//	me.AttributeValueMap{
+	//		"ActualPlugInUnitType":   cardHolderOnuType,
+	//		"ExpectedPlugInUnitType": ethernetUnitType,
+	//	},
+	//})
+
+	// circuitPack XG-PON10G10
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"Type":          xgsPonUnitType,
+			"NumberOfPorts": 1, // NOTE is this the ANI port? must be
+			"SerialNumber":  ToOctets("BBSM-Circuit-Pack-ani", 20),
+			"Version":       ToOctets("v0.0.1", 20),
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"VendorId":            "ONF",
+			"AdministrativeState": 0,
+			"OperationalState":    0,
+			"BridgedOrIpInd":      0,
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"EquipmentId":                 ToOctets("BBSM-Circuit-Pack", 20),
+			"CardConfiguration":           0,
+			"TotalTContBufferNumber":      8,
+			"TotalPriorityQueueNumber":    8,
+			"TotalTrafficSchedulerNumber": 0,
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"PowerShedOverride": uint32(0),
+		},
+	})
+
+	// ANI-G
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.AniGClassID,
+		EntityID{tcontSlotId, aniGId},
+		me.AttributeValueMap{
+			"Arc":                         0,
+			"ArcInterval":                 0,
+			"Deprecated":                  0,
+			"GemBlockLength":              48,
+			"LowerOpticalThreshold":       255,
+			"LowerTransmitPowerThreshold": 129,
+			"OnuResponseTime":             0,
+			"OpticalSignalLevel":          57428,
+			"PiggybackDbaReporting":       0,
+			"SignalDegradeThreshold":      9,
+			"SignalFailThreshold":         5,
+			"SrIndication":                1,
+			"TotalTcontNumber":            8,
+			"TransmitOpticalLevel":        3171,
+			"UpperOpticalThreshold":       255,
+			"UpperTransmitPowerThreshold": 129,
+		},
+	})
+
+	// circuitPack Ethernet
+	// NOTE the circuit pack is divided in multiple messages as too big to fit in a single one
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"Type":          ethernetUnitType,
+			"NumberOfPorts": uniPortCount,
+			"SerialNumber":  ToOctets("BBSM-Circuit-Pack", 20),
+			"Version":       ToOctets("v0.0.1", 20),
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"VendorId":            "ONF",
+			"AdministrativeState": 0,
+			"OperationalState":    0,
+			"BridgedOrIpInd":      0,
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"EquipmentId":                 ToOctets("BBSM-Circuit-Pack", 20),
+			"CardConfiguration":           0,
+			"TotalTContBufferNumber":      8,
+			"TotalPriorityQueueNumber":    8,
+			"TotalTrafficSchedulerNumber": 16,
+		},
+	})
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.CircuitPackClassID,
+		circuitPackEntityID,
+		me.AttributeValueMap{
+			"PowerShedOverride": uint32(0),
+		},
+	})
+
+	// PPTP and UNI-Gs
+	// NOTE this are dependent on the number of UNI this ONU supports
+	// Through an identical ID, the UNI-G ME is implicitly linked to an instance of a PPTP
+	for i := 1; i <= uniPortCount; i++ {
+		uniEntityId := GenerateUniPortEntityId(uint32(i))
+
+		mibDb.items = append(mibDb.items, MibDbEntry{
+			me.PhysicalPathTerminationPointEthernetUniClassID,
+			uniEntityId,
+			me.AttributeValueMap{
+				"ExpectedType":                  0,
+				"SensedType":                    ethernetUnitType,
+				"AutoDetectionConfiguration":    0,
+				"EthernetLoopbackConfiguration": 0,
+				"AdministrativeState":           0,
+				"OperationalState":              0,
+				"ConfigurationInd":              3,
+				"MaxFrameSize":                  1518,
+				"DteOrDceInd":                   0,
+				"PauseTime":                     0,
+				"BridgedOrIpInd":                2,
+				"Arc":                           0,
+				"ArcInterval":                   0,
+				"PppoeFilter":                   0,
+				"PowerControl":                  0,
+			},
+		})
+
+		mibDb.items = append(mibDb.items, MibDbEntry{
+			me.UniGClassID,
+			uniEntityId,
+			me.AttributeValueMap{
+				"AdministrativeState":         0,
+				"Deprecated":                  0,
+				"ManagementCapability":        0,
+				"NonOmciManagementIdentifier": 0,
+				"RelayAgentOptions":           0,
+			},
+		})
+
+		// Downstream Queues (related to PPTP)
+		// 16 priorities queues for each UNI Ports
+		// EntityID = cardHolderSlotID + Uni EntityID (0101)
+		for j := 1; j <= downstreamPriorityQueues; j++ {
+			queueEntityId := EntityID{cardHolderSlotID, byte(j)}
+
+			// we first report the PriorityQueue without any attribute
+			mibDb.items = append(mibDb.items, MibDbEntry{
+				me.PriorityQueueClassID,
+				queueEntityId, //was not reported in the original implementation
+				me.AttributeValueMap{},
+			})
+
+			// then we report it with the required attributes
+			// In the downstream direction, the first byte is the slot number and the second byte is the port number of the queue's destination port.
+			relatedPort := append(uniEntityId, 0x00, byte(j))
+			mibDb.items = append(mibDb.items, MibDbEntry{
+				me.PriorityQueueClassID,
+				queueEntityId, //was not reported in the original implementation
+				me.AttributeValueMap{
+					"QueueConfigurationOption":                            0,
+					"MaximumQueueSize":                                    100,
+					"AllocatedQueueSize":                                  100,
+					"DiscardBlockCounterResetInterval":                    0,
+					"ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+					"RelatedPort":                                         relatedPort.ToUint32(),
+					"TrafficSchedulerPointer":                             0, //it was hardcoded to 0x0108 in the current implementation
+					"Weight":                                              1,
+					"BackPressureOperation":                               1,
+					"BackPressureTime":                                    0,
+					"BackPressureOccurQueueThreshold":                     0,
+					"BackPressureClearQueueThreshold":                     0,
+				},
+			})
+		}
+	}
+
+	// T-CONTS and Traffic Schedulers
+	for i := 1; i <= tconts; i++ {
+		tcontEntityId := EntityID{tcontSlotId, byte(i)}
+
+		mibDb.items = append(mibDb.items, MibDbEntry{
+			me.TContClassID,
+			tcontEntityId,
+			me.AttributeValueMap{
+				"AllocId": 65535,
+			},
+		})
+
+		tsEntityId := EntityID{cardHolderSlotID, byte(i)}
+		mibDb.items = append(mibDb.items, MibDbEntry{
+			me.TrafficSchedulerClassID,
+			tsEntityId, //was not reported in the original implementation
+			me.AttributeValueMap{
+				"TContPointer":            tcontEntityId.ToUint16(), // was hardcoded to a non-existing t-cont
+				"TrafficSchedulerPointer": 0,
+				"Policy":                  02,
+				"PriorityWeight":          0,
+			},
+		})
+
+		for j := 1; j <= upstreamPriorityQueues; j++ {
+			queueEntityId := EntityID{tcontSlotId, byte(j)}
+			// Upstream Queues (related to traffic schedulers)
+			// 8 priorities queues per TCONT
+			// EntityID = tcontSlotId + Uni EntityID (8001)
+
+			// we first report the PriorityQueue without any attribute
+			mibDb.items = append(mibDb.items, MibDbEntry{
+				me.PriorityQueueClassID,
+				queueEntityId, //was not reported in the original implementation
+				me.AttributeValueMap{},
+			})
+
+			// then we report it with the required attributes
+			// In the upstream direction, the first 2 bytes are the ME ID of the associated T- CONT, the first byte of which is a slot number, the second byte a T-CONT number.
+			relatedPort := append(tcontEntityId, 0x00, byte(j))
+			mibDb.items = append(mibDb.items, MibDbEntry{
+				me.PriorityQueueClassID,
+				queueEntityId, //was not reported in the original implementation
+				me.AttributeValueMap{
+					"QueueConfigurationOption":                            0,
+					"MaximumQueueSize":                                    100,
+					"AllocatedQueueSize":                                  100,
+					"DiscardBlockCounterResetInterval":                    0,
+					"ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+					"RelatedPort":                                         relatedPort.ToUint32(),
+					"TrafficSchedulerPointer":                             tsEntityId.ToUint16(), //it was hardcoded to 0x0108 in the current implementation
+					"Weight":                                              1,
+					"BackPressureOperation":                               1,
+					"BackPressureTime":                                    0,
+					"BackPressureOccurQueueThreshold":                     0,
+					"BackPressureClearQueueThreshold":                     0,
+				},
+			})
+		}
+	}
+
+	// ONU-2g
+	mibDb.items = append(mibDb.items, MibDbEntry{
+		me.Onu2GClassID,
+		EntityID{0x00, 0x00},
+		me.AttributeValueMap{
+			"ConnectivityCapability":                      127,
+			"CurrentConnectivityMode":                     0,
+			"Deprecated":                                  1,
+			"PriorityQueueScaleFactor":                    1,
+			"QualityOfServiceQosConfigurationFlexibility": 63,
+			"Sysuptime":                                   0,
+			"TotalGemPortIdNumber":                        8,
+			"TotalPriorityQueueNumber":                    64,
+			"TotalTrafficSchedulerNumber":                 8,
+		},
+	})
+
+	mibDb.NumberOfCommands = uint16(len(mibDb.items))
+
+	return &mibDb, nil
+}