First Commit of Voltha-Go-Controller from Radisys

Change-Id: I8e2e908e7ab09a4fe3d86849da18b6d69dcf4ab0
diff --git a/internal/pkg/util/concurrentmap.go b/internal/pkg/util/concurrentmap.go
new file mode 100644
index 0000000..f16bb29
--- /dev/null
+++ b/internal/pkg/util/concurrentmap.go
@@ -0,0 +1,87 @@
+/*
+* Copyright 2022-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 util
+
+import (
+	"sync"
+
+	"go.uber.org/atomic"
+)
+
+// ConcurrentMap implements a wrapper on top of SyncMap so that the count is also maintained
+type ConcurrentMap struct {
+	syncMap sync.Map
+	count   *atomic.Uint64
+	MapLock sync.RWMutex
+}
+
+// NewConcurrentMap - Initializes new ConcurentMap Object
+func NewConcurrentMap() *ConcurrentMap {
+	var cm ConcurrentMap
+	cm.count = atomic.NewUint64(0)
+	return &cm
+}
+
+// Get - Gets return the value store in the sync map
+//If value is present, the result will be true else false
+func (cm *ConcurrentMap) Get(key interface{}) (value interface{}, result bool) {
+	return cm.syncMap.Load(key)
+}
+
+// Set - Store the value in sync map against the key provided
+func (cm *ConcurrentMap) Set(key, value interface{}) {
+	if cm.count == nil {
+		cm.count = atomic.NewUint64(0)
+	}
+	_, exists := cm.syncMap.Load(key)
+	cm.syncMap.Store(key, value)
+	if !exists {
+		cm.count.Inc()
+	}
+}
+
+// Remove - Removes the key-value pair from the sync map
+func (cm *ConcurrentMap) Remove(key interface{}) bool {
+
+	if _, ok := cm.syncMap.Load(key); ok {
+		cm.syncMap.Delete(key)
+		cm.count.Dec()
+		return true
+	}
+	return false
+}
+
+// Range calls f sequentially for each key and value present in the sync map.
+// If f returns false, range stops the iteration.
+//
+// Range does not necessarily correspond to any consistent snapshot of the Sync Map's
+// contents: no key will be visited more than once, but if the value for any key
+// is stored or deleted concurrently, Range may reflect any mapping for that key
+// from any point during the Range call.
+//
+// Range may be O(N) with the number of elements in the sync map even if f returns
+// false after a constant number of calls.
+func (cm *ConcurrentMap) Range(f func(key, value interface{}) bool) {
+	cm.syncMap.Range(f)
+}
+
+// Length - return the no of entries present in the map
+func (cm *ConcurrentMap) Length() uint64 {
+	if cm.count == nil {
+		return 0
+	}
+	return cm.count.Load()
+}
diff --git a/internal/pkg/util/envutils/envutils.go b/internal/pkg/util/envutils/envutils.go
new file mode 100644
index 0000000..2c7d2ca
--- /dev/null
+++ b/internal/pkg/util/envutils/envutils.go
@@ -0,0 +1,123 @@
+/*
+* Copyright 2022-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 envutils provides the env parsing utility functions
+package envutils
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+)
+
+// common constants
+const (
+	// common environment variables
+
+	KafkaAdapterHost     = "KAFKA_ADAPTER_HOST"
+	KafkaAdapterPort     = "KAFKA_ADAPTER_PORT"
+	KafkaClusterHost     = "KAFKA_CLUSTER_HOST"
+	KafkaClusterPort     = "KAFKA_CLUSTER_PORT"
+	KvStoreType          = "KV_STORE_TYPE"
+	KvStoreTimeout       = "KV_STORE_TIMEOUT"
+	KvStoreHost          = "KV_STORE_HOST"
+	KvStorePort          = "KV_STORE_PORT"
+	AdapterTopic         = "ADAPTER_TOPIC"
+	CoreTopic            = "CORE_TOPIC"
+	EventTopic           = "EVENT_TOPIC"
+	LogLevel             = "LOG_LEVEL"
+	OnuNumber            = "ONU_NUMBER"
+	Banner               = "BANNER"
+	DisplayVersionOnly   = "DISPLAY_VERSION_ONLY"
+	ProbeHost            = "PROBE_HOST"
+	ProbePort            = "PROBE_PORT"
+	LiveProbeInterval    = "LIVE_PROBE_INTERVAL"
+	NotLiveProbeInterval = "NOT_LIVE_PROBE_INTERVAL"
+	VolthaHost           = "VOLTHA_HOST"
+	VolthaPort           = "VOLTHA_PORT"
+	HostName             = "HOST_NAME"
+
+	// openolt adapter environment variables
+
+	HeartbeatCheckInterval      = "HEARTBEAT_CHECK_INTERVAL"
+	HeartbeatFailReportInterval = "HEARTBEAT_FAIL_REPORT_INTERVAL"
+	GrpcTimeoutInterval         = "GRPC_TIMEOUT_INTERVAL"
+
+	// rwcore environment variables
+
+	RWCoreEndpoint            = "RW_CORE_ENDPOINT"
+	GrpcHost                  = "GRPC_HOST"
+	GrpcPort                  = "GRPC_PORT"
+	AffinityRouterTopic       = "AFFINITY_ROUTER_TOPIC"
+	InCompetingMode           = "IN_COMPETING_MODE"
+	KVTxnKeyDelTime           = "KV_TXN_KEY_DEL_TIME"
+	KVStoreDataPrefix         = "KV_STORE_DATA_PREFIX"
+	LongRunningRequestTimeout = "LONG_RUNNING_REQ_TIMEOUT"
+	DefaultRequestTimeout     = "DEFAULT_REQ_TIMEOUT"
+	DefaultCoreTimeout        = "DEFAULT_CORE_TIMEOUT"
+	CoreBindingKey            = "CORE_BINDING_KEY"
+	CorePairTopic             = "CORE_PAIR_TOPIC"
+	MaxConnectionRetries      = "MAX_CONNECTION_RETRIES"
+	ConnectionRetryInterval   = "CONNECTION_RETRY_INTERVAL"
+
+	// vgc environment variables
+
+	DeviceListRefreshInterval = "DEVICE_LIST_REFRESH_INTERVAL" // in seconds
+	CPUProfile                = "CPU_PROFILE"
+	MemProfile                = "MEM_PROFILE"
+	VendorID                  = "VENDOR_ID"
+    DeviceSyncDuration        = "DEVICE_SYNC_DURATION"
+	// openonu environment variables
+
+	OmciPacketCapture = "SAVE_OMCI_PACKET_CAPTURE"
+)
+
+// ParseStringEnvVariable reads the environment variable and returns env as string
+func ParseStringEnvVariable(envVarName string, defaultVal string) string {
+	envValue := os.Getenv(envVarName)
+	if envValue == "" {
+		fmt.Println("Environment variable " + envVarName + " undefined")
+		return defaultVal
+	}
+	return envValue
+}
+
+// ParseIntEnvVariable reads the environment variable and returns env as int64
+func ParseIntEnvVariable(envVarName string, defaultVal int64) int64 {
+	envValue := os.Getenv(envVarName)
+	if envValue == "" {
+		fmt.Println("Environment variable "+envVarName+" undefined", envVarName)
+		return defaultVal
+	}
+	returnVal, err := strconv.Atoi(envValue)
+	if err != nil {
+		fmt.Println("Unable to convert string to integer environment variable")
+		return defaultVal
+	}
+	return int64(returnVal)
+}
+
+// ParseBoolEnvVariable reads the environment variable and returns env as boolean
+func ParseBoolEnvVariable(envVarName string, defaultVal bool) bool {
+	envValue := os.Getenv(envVarName)
+	if envValue == "" {
+		fmt.Println("Environment variable " + envVarName + " undefined")
+		return defaultVal
+	}
+	if envValue == "true" || envValue == "True" {
+		return true
+	}
+	return false
+}
diff --git a/internal/pkg/util/utils.go b/internal/pkg/util/utils.go
new file mode 100644
index 0000000..0711053
--- /dev/null
+++ b/internal/pkg/util/utils.go
@@ -0,0 +1,148 @@
+/*
+* Copyright 2022-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 util
+
+import (
+	"encoding/binary"
+	"net"
+	"strings"
+
+	"voltha-go-controller/internal/pkg/of"
+)
+
+// RemoveFromSlice to remove particular value from given slice.
+func RemoveFromSlice(s []string, value string) []string {
+	i := 0
+	for i = 0; i < len(s); i++ {
+		if s[i] == value {
+			break
+		}
+	}
+	if i != len(s) {
+		//It means value is found in the slice
+		s[len(s)-1], s[i] = s[i], s[len(s)-1]
+		return s[:len(s)-1]
+	}
+	return s
+}
+
+//IsSliceSame - check and return true if the two slices are identical
+func IsSliceSame(ref, rcvd []uint32) bool {
+
+	var found bool
+	if len(ref) != len(rcvd) {
+		return false
+	}
+
+	for _, refEntry := range ref {
+		found = false
+
+		for _, rcvdEntry := range rcvd {
+			if refEntry == rcvdEntry {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return false
+		}
+	}
+	return true
+}
+
+//IsPbitSliceSame - check and return true if the two slices are identical
+func IsPbitSliceSame(ref, rcvd []of.PbitType) bool {
+
+	var found bool
+	if len(ref) != len(rcvd) {
+		return false
+	}
+
+	for _, refEntry := range ref {
+		found = false
+
+		for _, rcvdEntry := range rcvd {
+			if refEntry == rcvdEntry {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return false
+		}
+	}
+	return true
+}
+
+// IsNniPort is to check if given port is Nni Port.
+func IsNniPort(id uint32) bool {
+	return (id >= 0x100000)
+}
+
+// Uint32ToByte to convert uint32 to byte
+func Uint32ToByte(value uint32) []byte {
+	byteValue := make([]byte, 4)
+	binary.BigEndian.PutUint32(byteValue[0:4], value)
+	return byteValue
+}
+
+// IP2LongConv convert ip address to integer value.
+func IP2LongConv(ip net.IP) uint32 {
+	if len(ip) == 16 {
+		return binary.BigEndian.Uint32(ip[12:16])
+	}
+	return binary.BigEndian.Uint32(ip)
+}
+
+// Long2ipConv convert integer to ip address.
+func Long2ipConv(nn uint32) net.IP {
+	ip := make(net.IP, 4)
+	binary.BigEndian.PutUint32(ip, nn)
+	return ip
+}
+
+// GetExpIPList converts list or range of IPs to expanded IP list
+func GetExpIPList(ips []string) []net.IP {
+	ipList := []net.IP{}
+
+	for _, ipOrRange := range ips {
+		if strings.Contains(ipOrRange, "-") {
+			var splits = strings.Split(ipOrRange, "-")
+			ipStart := IP2LongConv(net.ParseIP(splits[0]))
+			ipEnd := IP2LongConv(net.ParseIP(splits[1]))
+
+			for i := ipStart; i <= ipEnd; i++ {
+				ipList = append(ipList, Long2ipConv(i))
+			}
+		} else {
+			ipList = append(ipList, net.ParseIP(ipOrRange))
+		}
+	}
+	return ipList
+}
+
+// MacAddrsMatch for comparison of MAC addresses and return true if MAC addresses matches
+func MacAddrsMatch(addr1 net.HardwareAddr, addr2 net.HardwareAddr) bool {
+	if len(addr1) != len(addr2) {
+		return false
+	}
+	for i := 0; i < len(addr1); i++ {
+		if addr1[i] != addr2[i] {
+			return false
+		}
+	}
+	return true
+}