VOL-2292: Create application for scale testing of BAL

- Base framework created and is functional
- Able to provision ATT techprofile with scheduler, queue and eapol
  flow creation.
- Extensible framework provided to add various operator workflows
- README has details about how to build, run, configure and extend
  the framework.

Change-Id: I71774959281881278c14b48bee7f9adc0b81ec68
diff --git a/vendor/github.com/boljen/go-bitmap/LICENSE b/vendor/github.com/boljen/go-bitmap/LICENSE
new file mode 100644
index 0000000..13cc28c
--- /dev/null
+++ b/vendor/github.com/boljen/go-bitmap/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Bol Christophe
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/boljen/go-bitmap/README.md b/vendor/github.com/boljen/go-bitmap/README.md
new file mode 100644
index 0000000..5ff5eba
--- /dev/null
+++ b/vendor/github.com/boljen/go-bitmap/README.md
@@ -0,0 +1,30 @@
+# Bitmap (Go)
+
+Package bitmap implements (thread-safe) bitmap functions and abstractions
+
+## Install
+
+    go get github.com/boljen/go-bitmap
+
+## Documentation
+
+See [godoc](https://godoc.org/github.com/boljen/go-bitmap)
+
+## Example
+
+    package main
+
+    import (
+        "fmt"
+        "github.com/boljen/go-bitmap"
+    )
+
+    func main() {
+        bm := bitmap.New(100)
+        bm.Set(0, true)
+        fmt.Println(bm.Get(0))
+    }
+
+## License
+
+MIT
diff --git a/vendor/github.com/boljen/go-bitmap/atomic.go b/vendor/github.com/boljen/go-bitmap/atomic.go
new file mode 100644
index 0000000..f04d76e
--- /dev/null
+++ b/vendor/github.com/boljen/go-bitmap/atomic.go
@@ -0,0 +1,64 @@
+package bitmap
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+var oobPanic = "SetAtomic not allowed on a bitmapSlice of cap() < 4"
+
+// SetAtomic is similar to Set except that it performs the operation atomically.
+func SetAtomic(bitmap []byte, targetBit int, targetValue bool) {
+	ov := (*[1]uint32)(unsafe.Pointer(&bitmap[targetBit/32]))[:]
+	SetAtomicUint32(ov, targetBit%32, targetValue)
+}
+
+// SetAtomic is similar to Set except that it performs the operation atomically.
+// It needs a bitmapSlice where the capacity is at least 4 bytes.
+func _SetAtomic(bitmapSlice []byte, targetBit int, targetValue bool) {
+	targetByteIndex := targetBit / 8
+	targetBitIndex := targetBit % 8
+	targetOffset := 0
+
+	// SetAtomic needs to modify 4 bytes of data so we panic when the slice
+	// doesn't have a capacity of at least 4 bytes.
+	if cap(bitmapSlice) < 4 {
+		panic(oobPanic)
+	}
+
+	// Calculate the Offset of the targetByte inside the 4-byte atomic batch.
+	// This is needed to ensure that atomic operations can happen as long as
+	// the bitmapSlice equals 4 bytes or more.
+	if cap(bitmapSlice) < targetByteIndex+3 {
+		targetOffset = cap(bitmapSlice) - targetByteIndex
+	}
+
+	// This gets a pointer to the memory of 4 bytes inside the bitmapSlice.
+	// It stores this pointer as an *uint32 so that it can be used to
+	// execute sync.atomic operations.
+	targetBytePointer := (*uint32)(unsafe.Pointer(&bitmapSlice[targetByteIndex-targetOffset]))
+
+	for {
+		// localValue is a copy of the uint32 value at *targetBytePointer.
+		// It's used to check whether the targetBit must be updated,
+		// and if so, to construct the new value for targetBytePointer.
+		localValue := atomic.LoadUint32(targetBytePointer)
+
+		// This "neutralizes" the uint32 conversion by getting a pointer to the
+		// 4-byte array stored undereneath the uint32.
+		targetByteCopyPointer := (*[4]byte)(unsafe.Pointer(&localValue))
+
+		// Work is done when targetBit is already set to targetValue.
+		if GetBit(targetByteCopyPointer[targetOffset], targetBitIndex) == targetValue {
+			return
+		}
+
+		// Modify the targetBit and update memory so that the targetBit is the only bit
+		// that has been modified in the batch.
+		referenceValue := localValue
+		SetBitRef(&targetByteCopyPointer[targetOffset], targetBitIndex, targetValue)
+		if atomic.CompareAndSwapUint32(targetBytePointer, referenceValue, localValue) {
+			break
+		}
+	}
+}
diff --git a/vendor/github.com/boljen/go-bitmap/bitmap.go b/vendor/github.com/boljen/go-bitmap/bitmap.go
new file mode 100644
index 0000000..dfe5cc2
--- /dev/null
+++ b/vendor/github.com/boljen/go-bitmap/bitmap.go
@@ -0,0 +1,200 @@
+// Package bitmap implements (thread-safe) bitmap functions and abstractions.
+//
+// Installation
+//
+// 	  go get github.com/boljen/go-bitmap
+package bitmap
+
+import "sync"
+
+var (
+	tA = [8]byte{1, 2, 4, 8, 16, 32, 64, 128}
+	tB = [8]byte{254, 253, 251, 247, 239, 223, 191, 127}
+)
+
+func dataOrCopy(d []byte, c bool) []byte {
+	if !c {
+		return d
+	}
+	ndata := make([]byte, len(d))
+	copy(ndata, d)
+	return ndata
+}
+
+// NewSlice creates a new byteslice with length l (in bits).
+// The actual size in bits might be up to 7 bits larger because
+// they are stored in a byteslice.
+func NewSlice(l int) []byte {
+	remainder := l % 8
+	if remainder != 0 {
+		remainder = 1
+	}
+	return make([]byte, l/8+remainder)
+}
+
+// Get returns the value of bit i from map m.
+// It doesn't check the bounds of the slice.
+func Get(m []byte, i int) bool {
+	return m[i/8]&tA[i%8] != 0
+}
+
+// Set sets bit i of map m to value v.
+// It doesn't check the bounds of the slice.
+func Set(m []byte, i int, v bool) {
+	index := i / 8
+	bit := i % 8
+	if v {
+		m[index] = m[index] | tA[bit]
+	} else {
+		m[index] = m[index] & tB[bit]
+	}
+}
+
+// GetBit returns the value of bit i of byte b.
+// The bit index must be between 0 and 7.
+func GetBit(b byte, i int) bool {
+	return b&tA[i] != 0
+}
+
+// SetBit sets bit i of byte b to value v.
+// The bit index must be between 0 and 7.
+func SetBit(b byte, i int, v bool) byte {
+	if v {
+		return b | tA[i]
+	}
+	return b & tB[i]
+}
+
+// SetBitRef sets bit i of byte *b to value v.
+func SetBitRef(b *byte, i int, v bool) {
+	if v {
+		*b = *b | tA[i]
+	} else {
+		*b = *b & tB[i]
+	}
+}
+
+// Len returns the length (in bits) of the provided byteslice.
+// It will always be a multipile of 8 bits.
+func Len(m []byte) int {
+	return len(m) * 8
+}
+
+// Bitmap is a byteslice with bitmap functions.
+// Creating one form existing data is as simple as bitmap := Bitmap(data).
+type Bitmap []byte
+
+// New creates a new Bitmap instance with length l (in bits).
+func New(l int) Bitmap {
+	return NewSlice(l)
+}
+
+// Len wraps around the Len function.
+func (b Bitmap) Len() int {
+	return Len(b)
+}
+
+// Get wraps around the Get function.
+func (b Bitmap) Get(i int) bool {
+	return Get(b, i)
+}
+
+// Set wraps around the Set function.
+func (b Bitmap) Set(i int, v bool) {
+	Set(b, i, v)
+}
+
+// Data returns the data of the bitmap.
+// If copy is false the actual underlying slice will be returned.
+func (b Bitmap) Data(copy bool) []byte {
+	return dataOrCopy(b, copy)
+}
+
+// Threadsafe implements thread-safe read- and write locking for the bitmap.
+type Threadsafe struct {
+	bm Bitmap
+	mu sync.RWMutex
+}
+
+// TSFromData creates a new Threadsafe using the provided data.
+// If copy is true the actual slice will be used.
+func TSFromData(data []byte, copy bool) *Threadsafe {
+	return &Threadsafe{
+		bm: Bitmap(dataOrCopy(data, copy)),
+	}
+}
+
+// NewTS creates a new Threadsafe instance.
+func NewTS(length int) *Threadsafe {
+	return &Threadsafe{
+		bm: New(length),
+	}
+}
+
+// Data returns the data of the bitmap.
+// If copy is false the actual underlying slice will be returned.
+func (b *Threadsafe) Data(copy bool) []byte {
+	b.mu.RLock()
+	data := dataOrCopy(b.bm, copy)
+	b.mu.RUnlock()
+	return data
+}
+
+// Len wraps around the Len function.
+func (b Threadsafe) Len() int {
+	b.mu.RLock()
+	l := b.bm.Len()
+	b.mu.RUnlock()
+	return l
+}
+
+// Get wraps around the Get function.
+func (b Threadsafe) Get(i int) bool {
+	b.mu.RLock()
+	v := b.bm.Get(i)
+	b.mu.RUnlock()
+	return v
+}
+
+// Set wraps around the Set function.
+func (b Threadsafe) Set(i int, v bool) {
+	b.mu.Lock()
+	b.bm.Set(i, v)
+	b.mu.Unlock()
+}
+
+// Concurrent is a bitmap implementation that achieves thread-safety
+// using atomic operations along with some unsafe.
+// It performs atomic operations on 32bits of data.
+type Concurrent []byte
+
+// NewConcurrent returns a concurrent bitmap.
+// It will create a bitmap
+func NewConcurrent(l int) Concurrent {
+	remainder := l % 8
+	if remainder != 0 {
+		remainder = 1
+	}
+	return make([]byte, l/8+remainder, l/8+remainder+3)
+}
+
+// Get wraps around the Get function.
+func (c Concurrent) Get(b int) bool {
+	return Get(c, b)
+}
+
+// Set wraps around the SetAtomic function.
+func (c Concurrent) Set(b int, v bool) {
+	SetAtomic(c, b, v)
+}
+
+// Len wraps around the Len function.
+func (c Concurrent) Len() int {
+	return Len(c)
+}
+
+// Data returns the data of the bitmap.
+// If copy is false the actual underlying slice will be returned.
+func (c Concurrent) Data(copy bool) []byte {
+	return dataOrCopy(c, copy)
+}
diff --git a/vendor/github.com/boljen/go-bitmap/uintmap.go b/vendor/github.com/boljen/go-bitmap/uintmap.go
new file mode 100644
index 0000000..72cbf4a
--- /dev/null
+++ b/vendor/github.com/boljen/go-bitmap/uintmap.go
@@ -0,0 +1,32 @@
+package bitmap
+
+import (
+	"sync/atomic"
+	"unsafe"
+)
+
+// SetAtomicUint32 sets the target bit to the target value inside the uint32
+// encded bitmap.
+func SetAtomicUint32(bitmap []uint32, targetBit int, targetValue bool) {
+	targetIndex := targetBit / 32
+	BitOffset := targetBit % 32
+
+	for {
+		localValue := atomic.LoadUint32(&bitmap[targetIndex])
+		targetBytes := (*[4]byte)(unsafe.Pointer(&localValue))[:]
+		if Get(targetBytes, BitOffset) == targetValue {
+			return
+		}
+		referenceValue := localValue
+		Set(targetBytes, BitOffset, targetValue)
+		if atomic.CompareAndSwapUint32(&bitmap[targetIndex], referenceValue, localValue) {
+			break
+		}
+	}
+}
+
+// GetAtomicUint32 gets the target bit from an uint32 encoded bitmap.
+func GetAtomicUint32(bitmap []uint32, targetBit int) bool {
+	data := (*[4]byte)(unsafe.Pointer(&bitmap[targetBit/32]))[:]
+	return Get(data, targetBit%32)
+}