SEBA-758 send periodic port stats to voltha
SEBA-790 get flow, gemport, and tcont information through API
fix lint errors

Change-Id: I10909e1992eba71d8e54c976ccbcea8778e35539
diff --git a/Makefile b/Makefile
index 37ae4a0..6cfcc89 100644
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,7 @@
 DOCKER_LABEL_BUILD_DATE  ?= $(shell date -u "+%Y-%m-%dT%H:%M:%SZ")
 
 GRPC_GW_PATH             ?= $(shell GO111MODULE=on go list -f '{{ .Dir }}' -m github.com/grpc-ecosystem/grpc-gateway)
+PROTO_PATH               ?= $(shell GO111MODULE=on go list -f '{{ .Dir }}' -m github.com/opencord/voltha-protos)
 
 bbsim: dep bbsimapi
 	GO111MODULE=on go build -i -v -o $@
@@ -45,6 +46,7 @@
 	@protoc -I ./api \
 	-I${GRPC_GW_PATH}/third_party/googleapis/ \
 	-I${GRPC_GW_PATH}/ \
+	-I${PROTO_PATH}/protos/ \
 	--go_out=plugins=grpc:api/ \
 	--grpc-gateway_out=logtostderr=true,allow_delete_body=true:api/ \
 	api/bbsim.proto
@@ -54,7 +56,7 @@
 	-I${GRPC_GW_PATH}/third_party/googleapis/ \
 	-I${GRPC_GW_PATH}/ \
 	--swagger_out=logtostderr=true,allow_delete_body=true:api/swagger/ \
-	bbsim.proto
+	api/bbsim.proto
 
 test: dep bbsimapi
 	GO111MODULE=on go test -v ./...
diff --git a/api/bbsim.proto b/api/bbsim.proto
index 494f947..1b35541 100644
--- a/api/bbsim.proto
+++ b/api/bbsim.proto
@@ -17,35 +17,40 @@
 
 import "google/api/annotations.proto";
 import "protoc-gen-swagger/options/annotations.proto";
+import "voltha_protos/openolt.proto";
+import "voltha_protos/tech_profile.proto";
 
 option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
-    info: {
+	info: {
 	title: "BBSim API";
 	version: "1.0";
-    };
-    schemes: HTTP;
-    consumes: "application/json";
-    produces: "application/json";
-    responses: {
+	contact: {
+		url: "http://opencord.org";
+		};
+	};
+	schemes: HTTP;
+	consumes: "application/json";
+	produces: "application/json";
+	responses: {
 	key: "404";
 	value: {
-	    description: "Returned when the resource does not exist.";
-	    schema: {
-		    json_schema: {
-		      type: STRING;
+		description: "Returned when the resource does not exist.";
+		schema: {
+			json_schema: {
+			  type: STRING;
 		}
-	    }
+		}
 	}
-    }
+	}
 };
 
 // OLT information
 message OLTInfo {
-    int64   olt_id = 1;
-    string  olt_serial = 2;
-    string  olt_ip = 3;
-    string  olt_state = 4;
-    string  olt_vendor = 5;
+	int64   olt_id = 1;
+	string  olt_serial = 2;
+	string  olt_ip = 3;
+	string  olt_state = 4;
+	string  olt_vendor = 5;
 }
 
 // ONU information
@@ -58,139 +63,159 @@
     string oper_state = 4;
     // ONU internal state
     string onu_state = 5;
+    repeated uint32 gemports = 6;
+    Tconts tconts = 7;
 }
 
 // Bulk ONU operations
 message ONUs {
-    repeated ONUInfo onus = 1;
+	repeated ONUInfo onus = 1;
 }
 
 message ONURequest {
-    ONUInfo onu = 1;
-    ONUs onus_batch = 2;
+	ONUInfo onu = 1;
+	ONUs onus_batch = 2;
 }
 
 // Port information
 message PortInfo {
-    string port_type = 1;
-    uint32 port_id = 2;
-    int32  pon_port_max_onus = 3;
-    uint32 pon_port_active_onus = 4;
-    string port_state = 5;
-    string alarm_state = 6;
+	string port_type = 1;
+	uint32 port_id = 2;
+	uint32 pon_port_max_onus = 3;
+	uint32 pon_port_active_onus = 4;
+	string port_state = 5;
+	string alarm_state = 6;
 }
 
 // Bulk port information
 message Ports {
-    repeated PortInfo ports = 1;
+	repeated PortInfo ports = 1;
 }
 
 // BBSim status
 message OLTStatusResponse {
-    OLTInfo olt = 1;
-    repeated PortInfo ports = 2;
+	OLTInfo olt = 1;
+	repeated PortInfo ports = 2;
 }
 
 // BBSim response message
 message BBSimResponse {
-    string status_msg = 1;
+	string status_msg = 1;
 }
 
 // ONU alarm request
 message ONUAlarmRequest {
-    // ONU serial number
-    string onu_serial = 1; 
-    // Alarm types are:
-    //   "signaldegrade"
-    //   "lossofomcichannel"
-    //   "lossofploam"
-    string alarm_type = 2;
-    // "on"/"off" indicates raised or cleared alarm 
-    string status = 3;                 }
+	// ONU serial number
+	string onu_serial = 1;
+	// Alarm types are:
+	//   "signaldegrade"
+	//   "lossofomcichannel"
+	//   "lossofploam"
+	string alarm_type = 2;
+	// "on"/"off" indicates raised or cleared alarm
+	string status = 3;                 }
 
 // OLT alarm request
 message OLTAlarmRequest {
-    uint32 port_id = 1;
-    string port_type = 2;
-    string status = 3;
+	uint32 port_id = 1;
+	string port_type = 2;
+	string status = 3;
 }
 
 // Device action
 message DeviceAction {
-    string device_type = 1;             // ONU or OLT
-    string device_serial_number = 2;    // Device serial number
-    string device_action = 3;           // soft or hard reboot
+	string device_type = 1;             // ONU or OLT
+	string serial_number = 2;    // Device serial number
+	string action = 3;           // soft or hard reboot
+}
+
+message Tconts {
+    fixed32 uni_id = 4;
+	fixed32 port_no = 5;
+	repeated tech_profile.TrafficScheduler tconts = 3;
+}
+
+message Flows {
+    repeated openolt.Flow flows = 1;
 }
 
 message Empty {}
 
 service BBSimService {
 
-    // Get current status of OLT
-    rpc OLTStatus(Empty) returns (OLTStatusResponse) {
-        option (google.api.http) = {
-            get : "/v1/olt"
-            additional_bindings {get : "/v1/olt/status"}
-        };
-    }
+	// Get current status of OLT
+	rpc OLTStatus(Empty) returns (OLTStatusResponse) {
+		option (google.api.http) = {
+			get : "/v1/olt"
+			additional_bindings {get : "/v1/olt/status"}
+		};
+	}
 
-    // Get status of a PON/NNI port
-    rpc PortStatus(PortInfo) returns (Ports) {
-        option (google.api.http) = {
-            get : "/v1/olt/ports/{port_type}"
-        };
-    }
+	// Get status of a PON/NNI port
+	rpc PortStatus(PortInfo) returns (Ports) {
+		option (google.api.http) = {
+			get : "/v1/olt/ports/{port_type}/{port_id}/status"
+		};
+	}
 
-    // Get status of all or specific ONUs
-    rpc ONUStatus(ONURequest) returns (ONUs) {
-        option (google.api.http) = {
-            get : "/v1/olt/onus"
-            additional_bindings { get : "/v1/olt/ports/{onu.pon_port_id}/onus" }
-            additional_bindings { get : "/v1/olt/onus/{onu.onu_serial}" }
-        };
-    }
+	// Get status of all or specific ONUs
+	rpc ONUStatus(ONURequest) returns (ONUs) {
+		option (google.api.http) = {
+			get : "/v1/olt/onus"
+			additional_bindings { get : "/v1/olt/ports/{onu.pon_port_id}/onus" }
+			additional_bindings { get : "/v1/olt/onus/{onu.onu_serial}" }
+		};
+	}
 
-    // Single/bulk activate ONU(s) for specific PON port(s)
-    rpc ONUActivate(ONURequest) returns (BBSimResponse) {
-        option (google.api.http) = {
-            post : "/v1/olt/onus"
-            body: "onus_batch"
-            additional_bindings { post : "/v1/olt/ports/{onu.pon_port_id}/onus" }
-            additional_bindings { post : "/v1/olt/ports/{onu.pon_port_id}/onus/{onu.onu_serial}" }
-        };
-    }
-    
-    // Deactivate ONU(s) for specific PON port(s) specified by  
-    // a given onu_serial, onu_id, or pon_port_id
-    rpc ONUDeactivate(ONURequest) returns (BBSimResponse) {
-        option (google.api.http) = {
-            delete : "/v1/olt/onus"
-            body: "onus_batch"
-            additional_bindings { delete: "/v1/olt/onus/{onu.onu_serial}" }
-            additional_bindings { delete: "/v1/olt/ports/{onu.pon_port_id}/onus" }
-            additional_bindings { delete: "/v1/olt/ports/{onu.pon_port_id}/onus/{onu.onu_id}" }
-        };
-    }
+	// Single/bulk activate ONU(s) for specific PON port(s)
+	rpc ONUActivate(ONURequest) returns (BBSimResponse) {
+		option (google.api.http) = {
+			post : "/v1/olt/onus"
+			body: "onus_batch"
+			additional_bindings { post : "/v1/olt/ports/{onu.pon_port_id}/onus" }
+			additional_bindings { post : "/v1/olt/ports/{onu.pon_port_id}/onus/{onu.onu_serial}" }
+		};
+	}
 
-    // Generate ONU related alarms
-    rpc GenerateONUAlarm(ONUAlarmRequest) returns (BBSimResponse) {
-        option (google.api.http) = {
-            post : "/v1/olt/onus/{onu_serial}/alarms/{alarm_type}/{status}"
-        };
-    }
+	// Deactivate ONU(s) for specific PON port(s) specified by
+	// a given onu_serial, onu_id, or pon_port_id
+	rpc ONUDeactivate(ONURequest) returns (BBSimResponse) {
+		option (google.api.http) = {
+			delete : "/v1/olt/onus"
+			body: "onus_batch"
+			additional_bindings { delete: "/v1/olt/onus/{onu.onu_serial}" }
+			additional_bindings { delete: "/v1/olt/ports/{onu.pon_port_id}/onus" }
+			additional_bindings { delete: "/v1/olt/ports/{onu.pon_port_id}/onus/{onu.onu_id}" }
+		};
+	}
 
-    // Generate OLT related alarms
-    rpc GenerateOLTAlarm(OLTAlarmRequest) returns (BBSimResponse) {
-        option (google.api.http) = {
-            post : "/v1/olt/ports/{port_type}/{port_id}/alarms/los/{status}"
-        };
-    }
+	// Generate ONU related alarms
+	rpc GenerateONUAlarm(ONUAlarmRequest) returns (BBSimResponse) {
+		option (google.api.http) = {
+			post : "/v1/olt/onus/{onu_serial}/alarms/{alarm_type}/{status}"
+		};
+	}
 
-    // Perform actions on OLT/ONU devices (e.g. reboot)
-    rpc PerformDeviceAction(DeviceAction) returns (BBSimResponse) {
-        option (google.api.http) = {
-            patch: "/v1/{device_type}/reboot"
-            additional_bindings { patch : "/v1/olt/{device_type}/{device_serial_number}/reboot/{device_action}"}
-        };
-    }
+	// Generate OLT related alarms
+	rpc GenerateOLTAlarm(OLTAlarmRequest) returns (BBSimResponse) {
+		option (google.api.http) = {
+			post : "/v1/olt/ports/{port_type}/{port_id}/alarms/los/{status}"
+		};
+	}
+
+	// Perform actions on OLT/ONU devices (e.g. reboot)
+	rpc PerformDeviceAction(DeviceAction) returns (BBSimResponse) {
+		option (google.api.http) = {
+			patch: "/v1/{device_type}/action/{action}"
+			additional_bindings { patch : "/v1/olt/{device_type}/{serial_number}/action/{action}"}
+		};
+	}
+
+	// Get flows
+	rpc GetFlows(ONUInfo) returns(Flows) {
+	    option (google.api.http) = {
+	        get: "/v1/olt/flows"
+	        additional_bindings {get: "/v1/olt/onu/{onu_serial}/flows"}
+	    };
+	}
 }
diff --git a/common/logger/logger.go b/common/logger/logger.go
index 6efe0f1..3701284 100644
--- a/common/logger/logger.go
+++ b/common/logger/logger.go
@@ -31,6 +31,22 @@
 func Setup(kafkaBroker string, level string) {
 
 	logger := log.New()
+	formatter := &log.TextFormatter{
+		ForceColors:               false,
+		DisableColors:             false,
+		EnvironmentOverrideColors: false,
+		DisableTimestamp:          false,
+		FullTimestamp:             true,
+		TimestampFormat:           time.RFC3339Nano,
+		DisableSorting:            false,
+		SortingFunc:               nil,
+		DisableLevelTruncation:    false,
+		QuoteEmptyFields:          true,
+		FieldMap:                  nil,
+		CallerPrettyfier:          nil,
+	}
+	logger.SetFormatter(formatter)
+
 	//logger.SetReportCaller(true)
 	myLogger = logger.WithField("topics", []string{"bbsim.log"})
 
@@ -121,3 +137,8 @@
 func Debug(msg string, args ...interface{}) {
 	myLogger.Debugf(msg, args...)
 }
+
+// Trace logs with log level trace
+func Trace(msg string, args ...interface{}) {
+	myLogger.Tracef(msg, args...)
+}
diff --git a/core/alarms.go b/core/alarms.go
index 2261b55..c48c493 100644
--- a/core/alarms.go
+++ b/core/alarms.go
@@ -19,9 +19,10 @@
 import (
 	"strconv"
 
-	pb "github.com/opencord/voltha-bbsim/api"
+	api "github.com/opencord/voltha-bbsim/api"
 	"github.com/opencord/voltha-bbsim/common/logger"
 	"github.com/opencord/voltha-bbsim/device"
+	flowHandler "github.com/opencord/voltha-bbsim/flow"
 	openolt "github.com/opencord/voltha-protos/go/openolt"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -40,49 +41,49 @@
 	AlarmOff = "off"
 )
 
-func (s *Server) handleOnuAlarm(in *pb.ONUAlarmRequest) (*pb.BBSimResponse, error) {
+func (s *Server) handleOnuAlarm(in *api.ONUAlarmRequest) (*api.BBSimResponse, error) {
+	logger.Trace("handleOnuAlarm() invoked")
 	value, ok := s.SNmap.Load(in.OnuSerial)
-	onu := value.(*device.Onu)
 	if !ok {
-		return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial)
+		return &api.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial)
 	}
 
-	if (onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_LOS_ON_OLT_PON_LOS) &&
+	onu := value.(*device.Onu)
+	if (onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuLosOnOltPonLos) &&
 		(in.AlarmType != OnuLossOfPloam) {
-		return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm")
+		return &api.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm")
 	}
 
 	if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && (in.AlarmType != OnuLossOfPloam) {
 		// Don't send onu alarm as OLT-PON is down
-		return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm")
+		return &api.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm")
 	}
 	switch in.AlarmType {
 	case OnuLossOfOmciChannel:
 		Ind := formulateLossOfOmciChannelAlarm(in.Status, onu)
 		if in.Status == AlarmOn {
-			onu.UpdateIntState(device.ONU_OMCI_CHANNEL_LOS_RAISED)
+			onu.UpdateIntState(device.OnuOmciChannelLosRaised)
 		} else {
-			onu.UpdateIntState(device.ONU_ACTIVE)
+			onu.UpdateIntState(device.OnuActive)
 		}
 		s.alarmCh <- Ind
-		return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+		return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 
 	case OnuSignalDegrade:
 		Ind := formulateSignalDegradeAlarm(in.Status, onu)
 		s.alarmCh <- Ind
-		return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+		return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 
 	case OnuLossOfPloam:
 		if in.Status == AlarmOn {
-			onu.UpdateIntState(device.ONU_LOS_RAISED)
+			onu.UpdateIntState(device.OnuLosRaised)
 			device.UpdateOnusOpStatus(onu.IntfID, onu, "down")
 		} else {
-			onu.UpdateIntState(device.ONU_ACTIVE)
+			onu.UpdateIntState(device.OnuActive)
 			device.UpdateOnusOpStatus(onu.IntfID, onu, "up")
-			// TODO is it required to check onu state?
 			err := sendOnuDiscInd(*s.EnableServer, onu)
 			if err != nil {
-				logger.Error("Error: %v", err.Error())
+				logger.Error("Error: %s", err.Error())
 			}
 		}
 		Ind := formulateLossOfPLOAM(in.Status, onu)
@@ -100,17 +101,18 @@
 
 	default:
 		logger.Debug("Unhandled alarm type")
-		return &pb.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type")
+		return &api.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type")
 	}
 
 }
 
-func (s *Server) handleOltAlarm(in *pb.OLTAlarmRequest) (*pb.BBSimResponse, error) {
+func (s *Server) handleOltAlarm(in *api.OLTAlarmRequest) (*api.BBSimResponse, error) {
+	logger.Trace("handleOltAlarm() invoked")
 	switch in.PortType {
 	case device.IntfNni:
 
 		if !s.isNniIntfPresentInOlt(in.PortId) {
-			return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt")
+			return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt")
 		}
 
 		Ind := formulateOLTLOSAlarm(in.Status, in.PortId, device.IntfNni)
@@ -119,13 +121,13 @@
 
 	case device.IntfPon:
 		if !s.isPonIntfPresentInOlt(in.PortId) {
-			return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt")
+			return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt")
 		}
 		Ind := formulateOLTLOSAlarm(in.Status, in.PortId, in.PortType)
 		s.alarmCh <- Ind
 		onusOperstat := s.setPONPortState(in.PortId, in.Status)
 		for _, onu := range s.Onumap[in.PortId] {
-			if onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_FREE {
+			if onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuFree {
 				continue // Skip for onus which have independently raised onu los
 			}
 
@@ -136,23 +138,33 @@
 			s.sendOnuLosOnOltPonLos(onu, in.Status)
 		}
 	default:
-		return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "invalid interface type provided")
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid interface type provided")
 	}
 
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 }
 
 func (s *Server) setNNIPortState(portID uint32, alarmstatus string) {
+	logger.Trace("setNNIPortState() invoked")
 	switch alarmstatus {
 	case AlarmOn:
 		s.Olt.UpdateNniPortState(portID, device.NniLosRaised, "down")
+		err := flowHandler.PortDown(0)
+		if err != nil {
+			logger.Error("Failed in port down %v", err)
+		}
 
 	case AlarmOff:
 		s.Olt.UpdateNniPortState(portID, device.NniLosCleared, "up")
+		err := flowHandler.PortUp(0)
+		if err != nil {
+			logger.Error("Failed in port up %v", err)
+		}
 	}
 }
 
 func (s *Server) setPONPortState(portID uint32, alarmstatus string) string {
+	logger.Trace("setPONPortState() invoked")
 	switch alarmstatus {
 	case AlarmOn:
 		s.Olt.UpdatePonPortState(portID, device.PonLosRaised, "down")
@@ -166,12 +178,13 @@
 }
 
 func (s *Server) sendOnuLosOnOltPonLos(onu *device.Onu, status string) {
-	var internalState device.DeviceState
+	logger.Trace("sendOnuLosOnOltPonLos() invoked")
+	var internalState device.State
 
 	if status == AlarmOn {
-		internalState = device.ONU_LOS_ON_OLT_PON_LOS
+		internalState = device.OnuLosOnOltPonLos
 	} else if status == AlarmOff {
-		internalState = device.ONU_ACTIVE
+		internalState = device.OnuActive
 	}
 
 	Ind := formulateLossOfPLOAM(status, onu)
@@ -189,7 +202,7 @@
 }
 
 func formulateLossOfOmciChannelAlarm(status string, onu *device.Onu) *openolt.Indication {
-	logger.Debug("formulateLossofOmciChannelAlarm() invoked")
+	logger.Trace("formulateLossofOmciChannelAlarm() invoked")
 
 	alarmIndication := &openolt.AlarmIndication_OnuLossOmciInd{
 		OnuLossOmciInd: &openolt.OnuLossOfOmciChannelIndication{
@@ -209,7 +222,7 @@
 }
 
 func formulateSignalDegradeAlarm(status string, onu *device.Onu) *openolt.Indication {
-	logger.Debug("formulateSignalDegrade() invoked")
+	logger.Trace("formulateSignalDegrade() invoked")
 	alarmIndication := &openolt.AlarmIndication_OnuSignalDegradeInd{
 		OnuSignalDegradeInd: &openolt.OnuSignalDegradeIndication{
 			IntfId:              onu.IntfID,
@@ -227,7 +240,7 @@
 }
 
 func formulateLossOfPLOAM(status string, onu *device.Onu) *openolt.Indication {
-	logger.Debug("formulateLossOfPLOAM() invoked")
+	logger.Trace("formulateLossOfPLOAM() invoked")
 
 	alarmIndication := &openolt.AlarmIndication_OnuAlarmInd{OnuAlarmInd: &openolt.OnuAlarmIndication{
 		IntfId:             onu.IntfID,
@@ -258,12 +271,17 @@
 	return Ind
 }
 
-func (s *Server) checkAndSendOltPonLos(serial string, status string, intfType string) (*pb.BBSimResponse, error) {
-	value, _ := s.SNmap.Load(serial)
+func (s *Server) checkAndSendOltPonLos(serial string, status string, intfType string) (*api.BBSimResponse, error) {
+	value, ok := s.SNmap.Load(serial)
+	if !ok {
+		logger.Debug(serial + " not found in OLT-" + strconv.Itoa(int(s.Olt.ID)))
+		return &api.BBSimResponse{}, nil
+	}
+
 	onu := value.(*device.Onu)
 	if s.getNoOfActiveOnuByPortID(onu.IntfID) == 0 {
 		logger.Warn("Warning: Sending OLT-LOS, as all onus on pon-port %v raised los", onu.IntfID)
-		request := &pb.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon}
+		request := &api.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon}
 		resp, err := s.handleOltAlarm(request)
 		return resp, err
 	}
@@ -273,11 +291,12 @@
 		s.alarmCh <- Ind
 	}
 
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 }
 
 func interfaceIDToPortNo(intfid uint32, intfType string) uint32 {
-	// Converts interface-id to port-numbers that can be understood by the voltha
+	logger.Trace("interfaceIDToPortNo() invoked")
+	// Converts interface-id to port-numbers that can be understood by the VOLTHA
 	if intfType == device.IntfNni {
 		// nni at voltha starts with 65536
 		// nni = 65536 + interface_id
diff --git a/core/api_handler.go b/core/api_handler.go
index 8bc2c09..470f365 100644
--- a/core/api_handler.go
+++ b/core/api_handler.go
@@ -22,16 +22,26 @@
 	"strconv"
 	"time"
 
-	pb "github.com/opencord/voltha-bbsim/api"
+	api "github.com/opencord/voltha-bbsim/api"
 	"github.com/opencord/voltha-bbsim/common/logger"
 	"github.com/opencord/voltha-bbsim/device"
+	"github.com/opencord/voltha-bbsim/flow"
+	openolt "github.com/opencord/voltha-protos/go/openolt"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
 
-// handleONUActivate process ONU status request
-func (s *Server) handleONUStatusRequest(in *pb.ONUInfo) (*pb.ONUs, error) {
-	onuInfo := &pb.ONUs{}
+// Constants for reboot delays
+const (
+	OltRebootDelay     = 40
+	OnuSoftRebootDelay = 10
+	OnuHardRebootDelay = 30
+)
+
+// handleONUStatusRequest process ONU status request
+func (s *Server) handleONUStatusRequest(in *api.ONUInfo) (*api.ONUs, error) {
+	logger.Trace("handleONUStatusRequest() invoked")
+	onuInfo := &api.ONUs{}
 	if in.OnuSerial != "" { // Get status of single ONU by SerialNumber
 		// Get OpenOlt serial number from string
 		sn, err := getOpenoltSerialNumber(in.OnuSerial)
@@ -73,14 +83,14 @@
 }
 
 // handleONUActivate method handles ONU activate requests from user.
-func (s *Server) handleONUActivate(in []*pb.ONUInfo) (*pb.BBSimResponse, error) {
-	logger.Info("handleONUActivate request received")
+func (s *Server) handleONUActivate(in []*api.ONUInfo) (*api.BBSimResponse, error) {
+	logger.Trace("handleONUActivate request received")
 	logger.Debug("Received values: %+v\n", in)
 
 	// Check if indication is enabled
 	if s.EnableServer == nil {
 		logger.Error(OLTNotEnabled)
-		return &pb.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, OLTNotEnabled)
+		return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, OLTNotEnabled)
 	}
 
 	onuaddmap := make(map[uint32][]*device.Onu)
@@ -90,12 +100,21 @@
 	for _, onu := range in {
 		intfid := onu.PonPortId
 
+		if !s.isPonIntfPresentInOlt(intfid) {
+			return &api.BBSimResponse{}, status.Errorf(codes.OutOfRange, "PON-"+strconv.Itoa(int(intfid))+
+				" not present in OLT-"+strconv.Itoa(int(s.Olt.ID)))
+		}
+
+		if s.Olt.PonIntfs[intfid].AlarmState == device.PonLosRaised {
+			return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "pon-"+strconv.Itoa(int(intfid))+" is not active")
+		}
+
 		// Get the free ONU object for the intfid
 		Onu, err := s.GetNextFreeOnu(intfid)
 		if err != nil {
 			markONUsFree(onuaddmap)
 			logger.Error("Failed to get free ONU object for intfID %d :%v", intfid, err)
-			return &pb.BBSimResponse{}, status.Errorf(codes.ResourceExhausted, err.Error())
+			return &api.BBSimResponse{}, status.Errorf(codes.ResourceExhausted, err.Error())
 		}
 
 		// Check if Serial number is provided by user
@@ -104,9 +123,9 @@
 			sn, err := getOpenoltSerialNumber(onu.OnuSerial)
 			if err != nil {
 				logger.Error("Failed to get OpenOlt serial number %v", err)
-				Onu.InternalState = device.ONU_FREE
+				Onu.InternalState = device.OnuFree
 				markONUsFree(onuaddmap)
-				return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "serial number: "+onu.OnuSerial+" is invalid")
+				return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "serial number: "+onu.OnuSerial+" is invalid")
 			}
 
 			// Check if serial number is not duplicate in requested ONUs
@@ -115,8 +134,8 @@
 					logger.Error("Duplicate serial number found %s", sn)
 					// Mark ONUs free
 					markONUsFree(onuaddmap)
-					Onu.InternalState = device.ONU_FREE
-					return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "duplicate serial number: "+onu.OnuSerial+" provided")
+					Onu.InternalState = device.OnuFree
+					return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "duplicate serial number: "+onu.OnuSerial+" provided")
 				}
 			}
 			newSerialNums = append(newSerialNums, onu.OnuSerial)
@@ -127,8 +146,8 @@
 				logger.Error("Provided serial number %v already exist", sn)
 				// Mark ONUs free
 				markONUsFree(onuaddmap)
-				Onu.InternalState = device.ONU_FREE
-				return &pb.BBSimResponse{}, status.Errorf(codes.AlreadyExists, "serial number: "+onu.OnuSerial+" already exist")
+				Onu.InternalState = device.OnuFree
+				return &api.BBSimResponse{}, status.Errorf(codes.AlreadyExists, "serial number: "+onu.OnuSerial+" already exist")
 			}
 
 			// Store user provided serial number in ONU object
@@ -143,11 +162,12 @@
 		s.activateONUs(*s.EnableServer, onuaddmap)
 	}
 
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 }
 
 // handleONUDeactivate deactivates ONU described by a single ONUInfo object
-func (s *Server) handleONUDeactivate(in *pb.ONUInfo) error {
+func (s *Server) handleONUDeactivate(in *api.ONUInfo) error {
+	logger.Trace("handleONUDeactivate() invoked")
 
 	if s.EnableServer == nil {
 		logger.Error(OLTNotEnabled)
@@ -191,15 +211,32 @@
 }
 
 func (s *Server) handleOLTReboot() {
-	logger.Debug("HandleOLTReboot() invoked")
+	logger.Trace("HandleOLTReboot() invoked")
 	logger.Debug("Sending stop to serverActionCh")
 	s.serverActionCh <- OpenOltStop
-	time.Sleep(40 * time.Second)
+
+	// Delete all flows
+	err := flow.DeleteAllFlows()
+	if err != nil {
+		logger.Warn("%v", err)
+	}
+
+	// clear flowMap
+	s.FlowMap = make(map[device.FlowKey]*openolt.Flow)
+
+	// clear flow IDs from ONU objects
+	for intfID := range s.Onumap {
+		for _, onu := range s.Onumap[intfID] {
+			onu.Flows = nil
+		}
+	}
+
+	time.Sleep(OltRebootDelay * time.Second)
 
 	logger.Debug("Sending start to serverActionCh")
 	s.serverActionCh <- OpenOltStart
 	for {
-		if s.Olt.GetIntState() == device.OLT_ACTIVE {
+		if s.Olt.GetIntState() == device.OltActive {
 			logger.Info("Info: OLT reactivated")
 			break
 		}
@@ -209,23 +246,24 @@
 }
 
 func (s *Server) handleONUHardReboot(onu *device.Onu) {
-	logger.Debug("handleONUHardReboot() invoked")
+	logger.Trace("handleONUHardReboot() invoked")
 	_ = sendDyingGaspInd(*s.EnableServer, onu.IntfID, onu.OnuID)
 	device.UpdateOnusOpStatus(onu.IntfID, onu, "down")
 	// send operstat down to voltha
 	_ = sendOnuInd(*s.EnableServer, onu, "down", "up")
 	// Give OEH some time to perform cleanup
-	time.Sleep(30 * time.Second)
+	time.Sleep(OnuHardRebootDelay * time.Second)
 	s.activateOnu(onu)
 }
 
 func (s *Server) handleONUSoftReboot(IntfID uint32, OnuID uint32) {
-	logger.Debug("handleONUSoftReboot() invoked")
+	logger.Trace("handleONUSoftReboot() invoked")
 	onu, err := s.GetOnuByID(OnuID, IntfID)
 	if err != nil {
 		logger.Error("No onu found with given OnuID on interface %v", IntfID)
+		return
 	}
-	OnuAlarmRequest := &pb.ONUAlarmRequest{
+	OnuAlarmRequest := &api.ONUAlarmRequest{
 		OnuSerial: stringifySerialNumber(onu.SerialNumber),
 		AlarmType: OnuLossOfPloam,
 		Status:    "on",
@@ -236,7 +274,7 @@
 		logger.Error(err.Error())
 	}
 	// Clear alarm
-	time.Sleep(10 * time.Second)
+	time.Sleep(OnuSoftRebootDelay * time.Second)
 	OnuAlarmRequest.Status = "off"
 	_, err = s.handleOnuAlarm(OnuAlarmRequest)
 	if err != nil {
@@ -246,12 +284,13 @@
 
 // GetNextFreeOnu returns free onu object for specified interface ID
 func (s *Server) GetNextFreeOnu(intfid uint32) (*device.Onu, error) {
+	logger.Trace("GetNextFreeOnu() invoked")
 	onus, ok := s.Onumap[intfid]
 	if !ok {
 		return nil, errors.New("interface " + strconv.Itoa(int(intfid)) + " not present in ONU map")
 	}
 	for _, onu := range onus {
-		if onu.InternalState == device.ONU_FREE {
+		if onu.InternalState == device.OnuFree {
 			// If auto generated serial number is already used by some other ONU,
 			// continue to find for other free object
 			snkey := stringifySerialNumber(onu.SerialNumber)
@@ -259,7 +298,7 @@
 				continue
 			}
 			// Update Onu Internal State
-			onu.InternalState = device.ONU_INACTIVE
+			onu.InternalState = device.OnuInactive
 			return onu, nil
 		}
 	}
@@ -268,8 +307,9 @@
 
 // DeactivateAllOnuByIntfID deletes all ONUs for given PON port ID
 func (s *Server) DeactivateAllOnuByIntfID(intfid uint32) error {
+	logger.Trace("DeactivateAllOnuByIntfID() invoked")
 	for _, onu := range s.Onumap[intfid] {
-		if onu.InternalState == device.ONU_FREE || onu.InternalState == device.ONU_INACTIVE {
+		if onu.InternalState == device.OnuFree || onu.InternalState == device.OnuInactive {
 			continue
 		}
 		if err := s.HandleOnuDeactivate(onu); err != nil {
@@ -281,10 +321,11 @@
 
 // HandleOnuDeactivate method handles ONU state changes and sending Indication to voltha
 func (s *Server) HandleOnuDeactivate(onu *device.Onu) error {
-	logger.Debug("Deactivating ONU %d for Intf: %d", onu.OnuID, onu.IntfID)
+	logger.Trace("HandleOnuDeactivate() invoked")
+	logger.Info("Deactivating ONU %d for Intf: %d", onu.OnuID, onu.IntfID)
 
 	// Update ONU internal state to ONU_INACTIVE
-	s.updateDevIntState(onu, device.ONU_INACTIVE)
+	s.updateDevIntState(onu, device.OnuInactive)
 
 	// Update ONU operstate to down
 	onu.OperState = "down"
@@ -296,80 +337,106 @@
 }
 
 func markONUsFree(onumap map[uint32][]*device.Onu) {
+	logger.Trace("markONUsFree() invoked")
 	for intfid := range onumap {
 		for _, onu := range onumap[intfid] {
-			onu.UpdateIntState(device.ONU_FREE)
+			onu.UpdateIntState(device.OnuFree)
 		}
 	}
 }
 
-func copyONUInfo(onu *device.Onu) *pb.ONUInfo {
-	onuData := &pb.ONUInfo{
+func copyONUInfo(onu *device.Onu) *api.ONUInfo {
+	onuData := &api.ONUInfo{
 		OnuId:     onu.OnuID,
 		PonPortId: onu.IntfID,
 		OnuSerial: stringifySerialNumber(onu.SerialNumber),
 		OnuState:  device.ONUState[onu.InternalState],
 		OperState: onu.OperState,
 	}
+
+	// update gemports
+	for _, gemPorts := range onu.GemPortMap {
+		onuData.Gemports = append(onuData.Gemports, gemPorts...)
+	}
+
+	// fill T-CONT data for ONU
+	if onu.Tconts != nil {
+		onuData.Tconts = &api.Tconts{
+			UniId:  onu.Tconts.UniId,
+			PortNo: onu.Tconts.PortNo,
+			Tconts: onu.Tconts.TrafficScheds,
+		}
+	}
+
 	return onuData
 }
 
-func (s *Server) fetchPortDetail(intfID uint32, portType string) (*pb.PortInfo, error) {
-	logger.Debug("fetchPortDetail() invoked")
-	portInfo := &pb.PortInfo{}
-	switch portType {
-	case device.IntfNni:
-		if !s.isNniIntfPresentInOlt(intfID) {
-			return &pb.PortInfo{}, errors.New("NNI " + strconv.Itoa(int(intfID)) + " not present in " +
-				strconv.Itoa(int(s.Olt.ID)))
-		}
-		portInfo = &pb.PortInfo{
-			PortType:          portType,
-			PortId:            intfID,
-			PonPortMaxOnus:    0,
-			PonPortActiveOnus: 0,
-			PortState:         s.Olt.NniIntfs[intfID].OperState,
-			AlarmState:        device.OLTAlarmStateToString[s.Olt.NniIntfs[intfID].AlarmState],
-		}
-		return portInfo, nil
+func (s *Server) fetchPortDetail(intfID uint32, portType string) (*api.PortInfo, error) {
+	logger.Trace("fetchPortDetail() invoked %s-%d", portType, intfID)
 
-	case device.IntfPon:
-		if !s.isPonIntfPresentInOlt(intfID) {
-			return &pb.PortInfo{}, errors.New("PON " + strconv.Itoa(int(intfID)) + " not present in OLT-" +
-				strconv.Itoa(int(s.Olt.ID)))
-		}
-		portInfo = &pb.PortInfo{
-			PortType:          portType,
-			PortId:            intfID,
-			PonPortMaxOnus:    int32(len(s.Onumap[uint32(intfID)])),
-			PonPortActiveOnus: s.getNoOfActiveOnuByPortID(intfID),
-			PortState:         s.Olt.PonIntfs[intfID].OperState,
-			AlarmState:        device.OLTAlarmStateToString[s.Olt.PonIntfs[intfID].AlarmState],
-		}
-		return portInfo, nil
-	default:
-		return &pb.PortInfo{}, errors.New(portType + " is not a valid port type")
+	portInfo := &api.PortInfo{}
+	var maxOnu, activeOnu uint32
+	var alarmState device.AlarmState
+	var state string
+
+	// Get info for specified port
+	if portType == device.IntfNni && s.isNniIntfPresentInOlt(intfID) {
+		state = s.Olt.NniIntfs[intfID].OperState
+		alarmState = s.Olt.NniIntfs[intfID].AlarmState
+
+	} else if portType == device.IntfPon && s.isPonIntfPresentInOlt(intfID) {
+		maxOnu = uint32(len(s.Onumap[intfID]))
+		activeOnu = s.getNoOfActiveOnuByPortID(intfID)
+		state = s.Olt.PonIntfs[intfID].OperState
+		alarmState = s.Olt.PonIntfs[intfID].AlarmState
+
+	} else {
+		return &api.PortInfo{}, errors.New(portType + "-" + strconv.Itoa(int(intfID)) + " not present in OLT-" +
+			strconv.Itoa(int(s.Olt.ID)))
 	}
+
+	// fill proto structure
+	portInfo = &api.PortInfo{
+		PortType:          portType,
+		PortId:            intfID,
+		PonPortMaxOnus:    maxOnu,
+		PonPortActiveOnus: activeOnu,
+		PortState:         state,
+	}
+
+	// update alarm state only when alarm is raised
+	if alarmState == device.NniLosRaised || alarmState == device.PonLosRaised {
+		portInfo.AlarmState = device.OLTAlarmStateToString[alarmState]
+	}
+
+	return portInfo, nil
 }
 
-func (s *Server) validateDeviceActionRequest(request *pb.DeviceAction) (*pb.DeviceAction, error) {
+func (s *Server) validateDeviceActionRequest(request *api.DeviceAction) (*api.DeviceAction, error) {
+	logger.Trace("validateDeviceActionRequest() invoked")
 	switch request.DeviceType {
 	case DeviceTypeOnu:
-		if request.DeviceSerialNumber == "" {
+		if request.SerialNumber == "" {
 			return request, errors.New("onu serial number can not be blank")
 		}
 
-		if len(request.DeviceSerialNumber) != SerialNumberLength {
+		if len(request.SerialNumber) != SerialNumberLength {
 			return request, errors.New("invalid serial number provided")
 		}
 
-		if request.DeviceAction != SoftReboot && request.DeviceAction != HardReboot {
+		_, exist := s.SNmap.Load(request.SerialNumber)
+		if !exist {
+			return &api.DeviceAction{}, errors.New(request.SerialNumber + " not present in OLT-" +
+				strconv.Itoa(int(s.Olt.ID)))
+		}
+
+		if request.Action != SoftReboot && request.Action != HardReboot {
 			return request, errors.New("invalid device action provided")
 		}
 		return request, nil
 	case DeviceTypeOlt:
 		request.DeviceType = DeviceTypeOlt
-		request.DeviceAction = HardReboot
+		request.Action = HardReboot
 		return request, nil
 	default:
 		return request, errors.New("invalid device type")
@@ -379,7 +446,7 @@
 func (s *Server) getNoOfActiveOnuByPortID(portID uint32) uint32 {
 	var noOfActiveOnus uint32
 	for _, onu := range s.Onumap[portID] {
-		if onu.InternalState == device.ONU_ACTIVE || onu.InternalState == device.ONU_OMCIACTIVE {
+		if onu.InternalState >= device.OnuActive {
 			noOfActiveOnus++
 		}
 	}
diff --git a/core/api_service.go b/core/api_service.go
index 7475484..f09b036 100644
--- a/core/api_service.go
+++ b/core/api_service.go
@@ -20,10 +20,9 @@
 	"context"
 	"net"
 	"net/http"
-	"sync"
 
 	"github.com/grpc-ecosystem/grpc-gateway/runtime"
-	pb "github.com/opencord/voltha-bbsim/api"
+	api "github.com/opencord/voltha-bbsim/api"
 	"github.com/opencord/voltha-bbsim/common/logger"
 	"github.com/opencord/voltha-bbsim/device"
 	"google.golang.org/grpc"
@@ -43,10 +42,10 @@
 )
 
 // OLTStatus method returns OLT status.
-func (s *Server) OLTStatus(ctx context.Context, in *pb.Empty) (*pb.OLTStatusResponse, error) {
-	logger.Debug("OLTStatus request received")
-	oltInfo := &pb.OLTStatusResponse{
-		Olt: &pb.OLTInfo{
+func (s *Server) OLTStatus(ctx context.Context, in *api.Empty) (*api.OLTStatusResponse, error) {
+	logger.Trace("OLTStatus request received")
+	oltInfo := &api.OLTStatusResponse{
+		Olt: &api.OLTInfo{
 			OltId:     int64(s.Olt.ID),
 			OltSerial: s.Olt.SerialNumber,
 			OltIp:     getOltIP().String(),
@@ -69,38 +68,32 @@
 }
 
 // PortStatus method returns Port status.
-func (s *Server) PortStatus(ctx context.Context, in *pb.PortInfo) (*pb.Ports, error) {
-	portInfo := &pb.Ports{}
-	logger.Debug("PortStatus() invoked")
-	if in.PortType == device.IntfNni {
-		for _, nniPort := range s.Olt.NniIntfs {
-			nniPortInfo, _ := s.fetchPortDetail(nniPort.IntfID, nniPort.Type)
-			portInfo.Ports = append(portInfo.Ports, nniPortInfo)
-		}
-	} else if in.PortType == device.IntfPon {
-		for _, ponPort := range s.Olt.PonIntfs {
-			ponPortInfo, _ := s.fetchPortDetail(ponPort.IntfID, ponPort.Type)
-			portInfo.Ports = append(portInfo.Ports, ponPortInfo)
-		}
-	} else {
-		return &pb.Ports{}, status.Errorf(codes.InvalidArgument, "Invalid port type")
+func (s *Server) PortStatus(ctx context.Context, in *api.PortInfo) (*api.Ports, error) {
+	logger.Trace("PortStatus() invoked")
+	ports := &api.Ports{}
+	portInfo, err := s.fetchPortDetail(in.PortId, in.PortType)
 
+	if err != nil {
+		return &api.Ports{}, status.Errorf(codes.InvalidArgument, err.Error())
 	}
-	return portInfo, nil
+
+	ports.Ports = append(ports.Ports, portInfo)
+	return ports, nil
 }
 
 // ONUStatus method returns ONU status.
-func (s *Server) ONUStatus(ctx context.Context, in *pb.ONURequest) (*pb.ONUs, error) {
-	logger.Debug("ONUStatus request received")
+func (s *Server) ONUStatus(ctx context.Context, in *api.ONURequest) (*api.ONUs, error) {
+	logger.Trace("ONUStatus request received")
 	if in.GetOnu() != nil {
 		logger.Debug("Received single ONU: %+v, %d\n", in.GetOnu(), in.GetOnu().PonPortId)
 		return s.handleONUStatusRequest(in.GetOnu())
 	}
-	logger.Debug("Received bulk ONUs status request")
-	onuInfo := &pb.ONUs{}
+
+	logger.Debug("Received all ONUS status request")
+	onuInfo := &api.ONUs{}
 	for intfid := range s.Onumap {
 		for _, onu := range s.Onumap[intfid] {
-			if onu.InternalState != device.ONU_FREE {
+			if onu.InternalState != device.OnuFree {
 				onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(onu))
 			}
 		}
@@ -109,11 +102,11 @@
 }
 
 // ONUActivate method handles ONU activate requests from user.
-func (s *Server) ONUActivate(ctx context.Context, in *pb.ONURequest) (*pb.BBSimResponse, error) {
-	logger.Info("ONUActivate request received")
+func (s *Server) ONUActivate(ctx context.Context, in *api.ONURequest) (*api.BBSimResponse, error) {
+	logger.Trace("ONUActivate request received")
 	logger.Debug("Received values: %+v\n", in)
 
-	var onuInfo = []*pb.ONUInfo{}
+	var onuInfo []*api.ONUInfo
 	// Activate single ONU
 	if in.GetOnu() != nil {
 		logger.Debug("Received single ONU: %+v\n", in.GetOnu())
@@ -123,14 +116,14 @@
 		onuInfo = in.GetOnusBatch().GetOnus()
 	} else {
 		logger.Debug("Received empty request body")
-		return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, RequestFailed)
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, RequestFailed)
 	}
 	resp, err := s.handleONUActivate(onuInfo)
 	return resp, err
 }
 
 // ONUDeactivate method handles ONU deactivation request.
-func (s *Server) ONUDeactivate(ctx context.Context, in *pb.ONURequest) (*pb.BBSimResponse, error) {
+func (s *Server) ONUDeactivate(ctx context.Context, in *api.ONURequest) (*api.BBSimResponse, error) {
 	logger.Info("ONUDeactivate request received")
 
 	// deactivate single ONU
@@ -138,7 +131,7 @@
 		logger.Debug("Received single ONU: %+v\n", in.GetOnu())
 		err := s.handleONUDeactivate(in.GetOnu())
 		if err != nil {
-			return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
+			return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
 		}
 	} else if len(in.GetOnusBatch().GetOnus()) != 0 { // bulk deactivate
 		logger.Debug("Received multiple ONUs")
@@ -146,7 +139,7 @@
 			logger.Debug("ONU values: %+v\n", onuinfo)
 			err := s.handleONUDeactivate(onuinfo)
 			if err != nil {
-				return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
+				return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
 			}
 		}
 	} else {
@@ -154,62 +147,89 @@
 		for intfID := range s.Onumap {
 			if err := s.DeactivateAllOnuByIntfID(intfID); err != nil {
 				logger.Error("Failed in ONUDeactivate: %v", err)
-				return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
+				return &api.BBSimResponse{}, status.Errorf(codes.Aborted, RequestFailed)
 			}
 		}
 	}
 
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
+
 }
 
 // GenerateONUAlarm RPC generates alarm for the onu
-func (s *Server) GenerateONUAlarm(ctx context.Context, in *pb.ONUAlarmRequest) (*pb.BBSimResponse, error) {
-	logger.Debug("GenerateONUAlarms() invoked")
+func (s *Server) GenerateONUAlarm(ctx context.Context, in *api.ONUAlarmRequest) (*api.BBSimResponse, error) {
+	logger.Trace("GenerateONUAlarms() invoked")
 	if in.OnuSerial == "" {
-		return &pb.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "serial number can not be blank")
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "serial number can not be blank")
 	}
 	if len(in.OnuSerial) != SerialNumberLength {
-		return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid serial number given (length mismatch)")
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid serial number given (length mismatch)")
 	}
 	if in.Status != "on" && in.Status != "off" {
-		return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
 	}
 	if s.alarmCh == nil {
-		return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "alarm-channel not created, can not send alarm")
+		return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "alarm-channel not created, can not send alarm")
 	}
-	// TODO put these checks inside handleOnuAlarm for modularity
 	resp, err := s.handleOnuAlarm(in)
 	return resp, err
 }
 
 // GenerateOLTAlarm RPC generates alarm for the OLT
-func (s *Server) GenerateOLTAlarm(ctx context.Context, in *pb.OLTAlarmRequest) (*pb.BBSimResponse, error) {
-	logger.Debug("GenerateOLTAlarm() invoked")
+func (s *Server) GenerateOLTAlarm(ctx context.Context, in *api.OLTAlarmRequest) (*api.BBSimResponse, error) {
+	logger.Trace("GenerateOLTAlarm() invoked")
 	if in.Status != "on" && in.Status != "off" {
-		return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid alarm status provided")
 	}
 	if s.alarmCh == nil {
-		return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "alarm-channel not created, can not send alarm")
+		return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "alarm-channel not created, can not send alarm")
 	}
 	resp, err := s.handleOltAlarm(in)
 	if err != nil {
 		return resp, err
 	}
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
 }
 
 // PerformDeviceAction rpc take the device request and performs OLT and ONU hard and soft reboot
-func (s *Server) PerformDeviceAction(ctx context.Context, in *pb.DeviceAction) (*pb.BBSimResponse, error) {
-	logger.Debug("PerformDeviceAction() invoked")
+func (s *Server) PerformDeviceAction(ctx context.Context, in *api.DeviceAction) (*api.BBSimResponse, error) {
+	logger.Trace("PerformDeviceAction() invoked")
 	if s.deviceActionCh == nil {
-		return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "device action channel not created, can not entertain request")
+		return &api.BBSimResponse{}, status.Errorf(codes.FailedPrecondition, "device action channel not created, can not entertain request")
 	}
 	in, err := s.validateDeviceActionRequest(in)
 	if err != nil {
-		return &pb.BBSimResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
+		return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
 	}
 	s.deviceActionCh <- in
-	return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+	return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
+}
+
+// GetFlows returns all flows or flows for specified ONU
+func (s *Server) GetFlows(ctx context.Context, in *api.ONUInfo) (*api.Flows, error) {
+	logger.Info("GetFlow request received")
+	flows := &api.Flows{}
+	if in.OnuSerial == "" {
+		for _, flow := range s.FlowMap {
+			flowInfo := flow
+			flows.Flows = append(flows.Flows, flowInfo)
+		}
+	} else {
+		serialNumber, err := getOpenoltSerialNumber(in.OnuSerial)
+		if err != nil {
+			return flows, status.Errorf(codes.InvalidArgument, err.Error())
+		}
+		onu, found := s.getOnuFromSNmap(serialNumber)
+		if !found {
+			return flows, status.Errorf(codes.InvalidArgument, "ONU with serial number %s not activated yet", in.OnuSerial)
+		}
+		for _, flowKey := range onu.Flows {
+			flow := s.FlowMap[flowKey]
+			flowInfo := flow
+			flows.Flows = append(flows.Flows, flowInfo)
+		}
+	}
+	return flows, nil
 }
 
 // NewMgmtAPIServer method starts BBSim gRPC server.
@@ -221,7 +241,7 @@
 }
 
 // StartRestGatewayService method starts REST server for BBSim.
-func StartRestGatewayService(grpcAddress string, hostandport string, wg *sync.WaitGroup) {
+func StartRestGatewayService(grpcAddress string, hostandport string) {
 	ctx := context.Background()
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
@@ -229,7 +249,7 @@
 	mux := runtime.NewServeMux()
 	opts := []grpc.DialOption{grpc.WithInsecure()}
 	// Register REST endpoints
-	err := pb.RegisterBBSimServiceHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
+	err := api.RegisterBBSimServiceHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
 	if err != nil {
 		logger.Error("%v", err)
 		return
diff --git a/core/core_server.go b/core/core_server.go
index a8d9d52..64bd6c7 100644
--- a/core/core_server.go
+++ b/core/core_server.go
@@ -29,7 +29,7 @@
 	"github.com/google/gopacket/layers"
 	"github.com/google/gopacket/pcap"
 	omci "github.com/opencord/omci-sim"
-	pb "github.com/opencord/voltha-bbsim/api"
+	api "github.com/opencord/voltha-bbsim/api"
 	"github.com/opencord/voltha-bbsim/common/logger"
 	"github.com/opencord/voltha-bbsim/device"
 	flowHandler "github.com/opencord/voltha-bbsim/flow"
@@ -49,6 +49,7 @@
 	SerialNumberLength = 12
 	OpenOltStart       = "start"
 	OpenOltStop        = "stop"
+	AutoDiscoveryDelay = 5
 )
 
 // Server structure consists of all the params required for BBsim.
@@ -78,9 +79,9 @@
 	eapolOut        chan *byteMsg
 	dhcpIn          chan *byteMsg
 	dhcpOut         chan *byteMsg
-	FlowMap         map[FlowKey]*openolt.Flow
+	FlowMap         map[device.FlowKey]*openolt.Flow
 	alarmCh         chan *openolt.Indication
-	deviceActionCh  chan *pb.DeviceAction
+	deviceActionCh  chan *api.DeviceAction
 	serverActionCh  chan string
 }
 
@@ -91,26 +92,19 @@
 }
 
 type byteMsg struct {
-	IntfId uint32
-	OnuId  uint32
+	IntfID uint32
+	OnuID  uint32
 	Byte   []byte
 }
 
 type stateReport struct {
 	device  device.Device
-	current device.DeviceState
-	next    device.DeviceState
+	current device.State
+	next    device.State
 }
 
-// FlowKey used for FlowMap key
-type FlowKey struct {
-	FlowID        uint32
-	FlowDirection string
-}
-
-//Has options (OLT id, number onu ports) from mediator
 // NewCore initialize OLT and ONU objects
-func NewCore(opt *option) *Server {
+func NewCore(opt *Option) *Server {
 	// TODO: make it decent
 	oltid := opt.oltid
 	npon := opt.npon
@@ -145,17 +139,14 @@
 		eapolOut:        make(chan *byteMsg, 1024),
 		dhcpIn:          make(chan *byteMsg, 1024),
 		dhcpOut:         make(chan *byteMsg, 1024),
-		FlowMap:         make(map[FlowKey]*openolt.Flow),
+		FlowMap:         make(map[device.FlowKey]*openolt.Flow),
 		serverActionCh:  make(chan string),
 	}
 	logger.Info("OLT %d created: %v", s.Olt.ID, s.Olt)
-
-	nnni := s.Olt.NumNniIntf
-	logger.Info("OLT ID: %d was retrieved.", s.Olt.ID)
 	logger.Info("OLT Serial-Number: %v", s.Olt.SerialNumber)
 	// Creating Onu Map
 	for intfid := uint32(0); intfid < npon; intfid++ {
-		s.Onumap[intfid] = device.NewOnus(oltid, intfid, nonus, nnni)
+		s.Onumap[intfid] = device.NewOnus(oltid, intfid, nonus)
 	}
 
 	logger.Debug("Onu Map:")
@@ -221,7 +212,7 @@
 	grpcAddressPort := s.gRPCAddress + ":" + strconv.Itoa(int(s.mgmtGrpcPort))
 	restAddressPort := s.gRPCAddress + ":" + strconv.Itoa(int(s.mgmtRestPort))
 	// Start rest gateway for BBSim server
-	go StartRestGatewayService(grpcAddressPort, restAddressPort, wg)
+	go StartRestGatewayService(grpcAddressPort, restAddressPort)
 	addressPort := s.gRPCAddress + ":" + strconv.Itoa(int(s.mgmtGrpcPort))
 
 	listener, apiserver, err := NewMgmtAPIServer(addressPort)
@@ -231,7 +222,7 @@
 	}
 
 	s.mgmtServer = apiserver
-	pb.RegisterBBSimServiceServer(apiserver, s)
+	api.RegisterBBSimServiceServer(apiserver, s)
 	if e := apiserver.Serve(listener); e != nil {
 		logger.Error("Failed to run management api server %v", e)
 		return
@@ -259,17 +250,17 @@
 		// 		onu.Initialize()
 		// 	}
 		// }
-		s.updateDevIntState(olt, device.OLT_INACTIVE)
+		s.updateDevIntState(olt, device.OltInactive)
 		logger.Debug("Enable() Done")
 	}()
 	logger.Debug("Enable() Start")
 	s.EnableServer = sv
+	flowHandler.InitializePacketInStream(*sv)
 	if err := s.activateOLT(*sv); err != nil {
 		return err
 	}
 
-	s.updateDevIntState(olt, device.OLT_PREACTIVE)
-
+	s.updateDevIntState(olt, device.OltPreactive)
 	coreCtx := context.Background()
 	coreCtx, corecancel := context.WithCancel(coreCtx)
 	s.cancel = corecancel
@@ -279,6 +270,9 @@
 
 	if s.AutoONUActivate == true {
 		// Initialize all ONUs
+		// Allow some delay for OLT to become active at the VOLTHA side, before sending ONU discovery indication.
+		// Otherwise, ONU discovery indication may get processed at the VOLTHA before OLT state becomes active.
+		time.Sleep(AutoDiscoveryDelay * time.Second)
 		for intfid := range s.Onumap {
 			for _, onu := range s.Onumap[intfid] {
 				onu.Initialize()
@@ -308,7 +302,8 @@
 	s.StopPktLoops()
 }
 
-func (s *Server) updateDevIntState(dev device.Device, state device.DeviceState) {
+func (s *Server) updateDevIntState(dev device.Device, state device.State) {
+	logger.Debug("updateDevIntState called state:%d", state)
 	current := dev.GetIntState()
 	dev.UpdateIntState(state)
 	logger.Debug("updateDevIntState called state: current %s, next %s", device.ONUState[current], device.ONUState[dev.GetIntState()])
@@ -322,8 +317,7 @@
 	}
 }
 
-func (s *Server) updateOnuIntState(intfid uint32, onuid uint32, state device.DeviceState) error {
-
+func (s *Server) updateOnuIntState(intfid uint32, onuid uint32, state device.State) error {
 	onu, err := s.GetOnuByID(onuid, intfid)
 
 	if err != nil {
@@ -376,15 +370,17 @@
 	logger.Debug("activateOLT() Start")
 	// Activate OLT
 	olt := s.Olt
+	olt.OperState = "up"
 	if err := sendOltIndUp(stream, olt); err != nil {
+		olt.OperState = "down"
 		return err
 	}
-	olt.OperState = "up"
 	logger.Info("OLT %s sent OltInd.", olt.Name)
 
 	// OLT sends Interface Indication to Adapter
 	if err := sendIntfInd(stream, olt); err != nil {
 		logger.Error("Fail to sendIntfInd: %v", err)
+		olt.OperState = "down"
 		return err
 	}
 	logger.Info("OLT %s sent IntfInd.", olt.Name)
@@ -392,6 +388,7 @@
 	// OLT sends Operation Indication to Adapter after activating each interface
 	if err := sendOperInd(stream, olt); err != nil {
 		logger.Error("Fail to sendOperInd: %v", err)
+		olt.OperState = "down"
 		return err
 	}
 	logger.Info("OLT %s sent OperInd.", olt.Name)
@@ -406,9 +403,10 @@
 		s.Vethnames = []string{}
 		s.Ioinfos = []*Ioinfo{}
 		s.wg.Done()
-		s.updateDevIntState(s.Olt, device.OLT_PREACTIVE)
+		s.updateDevIntState(s.Olt, device.OltPreactive)
 		logger.Debug("StartPktLoops () Done")
 	}()
+	go s.sendPortStats()
 	s.alarmCh = make(chan *openolt.Indication, 10)
 	go startAlarmLoop(stream, s.alarmCh)
 	go s.startDeviceActionLoop()
@@ -442,7 +440,7 @@
 }
 
 func createIoinfos(oltid uint32, Vethnames []string) ([]*Ioinfo, []string, error) {
-	ioinfos := []*Ioinfo{}
+	var ioinfos []*Ioinfo
 	var err error
 	var handler *pcap.Handle
 	nniup, nnidw := makeNniName(oltid)
@@ -546,21 +544,21 @@
 		close(nnichannel)
 	}()
 	logger.Debug("BEFORE OLT_ACTIVE")
-	s.updateDevIntState(s.Olt, device.OLT_ACTIVE)
+	s.updateDevIntState(s.Olt, device.OltActive)
 	logger.Debug("AFTER  OLT_ACTIVE")
 	data := &openolt.Indication_PktInd{}
 	for {
 		select {
 		case msg := <-s.omciIn:
-			logger.Debug("OLT %d send omci indication, IF %v (ONU-ID: %v) pkt:%x.", s.Olt.ID, msg.IntfId, msg.OnuId, msg.Pkt)
-			omci := &openolt.Indication_OmciInd{OmciInd: &msg}
-			if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
-				logger.Error("send omci indication failed: %v", err)
+			logger.Debug("OLT %d send omciInd indication, IF %v (ONU-ID: %v) pkt:%x.", s.Olt.ID, msg.IntfId, msg.OnuId, msg.Pkt)
+			omciInd := &openolt.Indication_OmciInd{OmciInd: &msg}
+			if err := stream.Send(&openolt.Indication{Data: omciInd}); err != nil {
+				logger.Error("send omciInd indication failed: %v", err)
 				continue
 			}
 		case msg := <-s.eapolIn:
-			intfid := msg.IntfId
-			onuid := msg.OnuId
+			intfid := msg.IntfID
+			onuid := msg.OnuID
 			gemid, err := s.getGemPortID(intfid, onuid)
 			if err != nil {
 				logger.Error("Failed to getGemPortID intfid:%d onuid:%d", intfid, onuid)
@@ -575,8 +573,8 @@
 				return err
 			}
 		case msg := <-s.dhcpIn: // TODO: We should put omciIn, eapolIn, dhcpIn toghether
-			intfid := msg.IntfId
-			onuid := msg.OnuId
+			intfid := msg.IntfID
+			onuid := msg.OnuID
 			gemid, err := s.getGemPortID(intfid, onuid)
 			bytes := msg.Byte
 			pkt := gopacket.NewPacket(bytes, layers.LayerTypeEthernet, gopacket.Default)
@@ -626,12 +624,12 @@
 			onuid := nnipkt.Info.onuid
 			intfid := nnipkt.Info.intfid
 			onu, _ := s.GetOnuByID(onuid, intfid)
+			pkt := nnipkt.Pkt
 
 			device.LoggerWithOnu(onu).Info("Received packet from NNI in grpc Server.")
 
-			pkt := nnipkt.Pkt
 			data = &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{IntfType: "nni", IntfId: intfid, Pkt: pkt.Data()}}
-			if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
+			if err = stream.Send(&openolt.Indication{Data: data}); err != nil {
 				logger.Error("Fail to send PktInd indication: %v", err)
 				return err
 			}
@@ -656,7 +654,7 @@
 		ethtype := pkt.EthernetType
 		if ethtype == layers.EthernetTypeEAPOL {
 			device.LoggerWithOnu(onu).Info("Received downstream packet is EAPOL.")
-			eapolPkt := byteMsg{IntfId: intfid, OnuId: onuid, Byte: rawpkt.Data()}
+			eapolPkt := byteMsg{IntfID: intfid, OnuID: onuid, Byte: rawpkt.Data()}
 			s.eapolOut <- &eapolPkt
 			return nil
 		} else if layerDHCP := rawpkt.Layer(layers.LayerTypeDHCPv4); layerDHCP != nil {
@@ -677,7 +675,7 @@
 				}
 			}
 			logger.Debug("%s", poppkt.Dump())
-			dhcpPkt := byteMsg{IntfId: intfid, OnuId: onuid, Byte: poppkt.Data()}
+			dhcpPkt := byteMsg{IntfID: intfid, OnuID: onuid, Byte: poppkt.Data()}
 			s.dhcpOut <- &dhcpPkt
 			return nil
 		} else {
@@ -713,30 +711,24 @@
 	}
 	ioinfo, err := s.IdentifyNniIoinfo("inside")
 	if err != nil {
+		logger.Error("failed to get ioinfo")
 		return err
 	}
 	handle := ioinfo.handler
 	logger.Debug("%s", poppkt.Dump())
 	SendNni(handle, poppkt)
+	// Send packet to nni port
+	if err := flowHandler.PacketOut(poppkt, "nni", ioinfo.intfid); err != nil {
+		logger.Error("Error in sending packet to nni port")
+	}
 	return nil
 }
 
-// IsAllOnuActive checks for ONU_ACTIVE state for all the onus in the map
-func IsAllOnuActive(onumap map[uint32][]*device.Onu) bool {
-	for _, onus := range onumap {
-		for _, onu := range onus {
-			if onu.GetIntState() != device.ONU_ACTIVE {
-				return false
-			}
-		}
-	}
-	return true
-}
-
+// isAllOnuOmciActive checks for OnuOmciActive state for all the onus in the map
 func (s *Server) isAllOnuOmciActive() bool {
 	for _, onus := range s.Onumap {
 		for _, onu := range onus {
-			if onu.GetIntState() != device.ONU_OMCIACTIVE {
+			if onu.GetIntState() != device.OnuOmciActive {
 				return false
 			}
 		}
@@ -754,7 +746,9 @@
 			logger.Error("Failed to getGemPortID: %s", err)
 			return 0, err
 		}
-		gemportid = onu.GemportID
+		for _, gemports := range onu.GemPortMap {
+			return gemports[0], nil
+		}
 	}
 	return uint32(gemportid), nil
 }
@@ -839,7 +833,7 @@
 	s.SNmap.Range(
 		func(key, value interface{}) bool {
 			onu := value.(*device.Onu)
-			if onu.InternalState == device.ONU_LOS_RAISED {
+			if onu.InternalState == device.OnuLosRaised {
 				return true
 			}
 
@@ -876,19 +870,19 @@
 // TODO all onu and olt related actions (like alarms) should be handled using this function
 func (s *Server) startDeviceActionLoop() {
 	logger.Debug("startDeviceActionLoop invoked")
-	s.deviceActionCh = make(chan *pb.DeviceAction, 10)
+	s.deviceActionCh = make(chan *api.DeviceAction, 10)
 	for {
 		logger.Debug("Action channel loop started")
 		select {
 		case Req := <-s.deviceActionCh:
-			logger.Debug("Reboot Action Type: %+v", Req.DeviceAction)
+			logger.Debug("Reboot Action Type: %+v", Req.Action)
 			switch Req.DeviceType {
 			case DeviceTypeOnu:
-				value, _ := s.SNmap.Load(Req.DeviceSerialNumber)
+				value, _ := s.SNmap.Load(Req.SerialNumber)
 				onu := value.(*device.Onu)
-				if Req.DeviceAction == SoftReboot {
+				if Req.Action == SoftReboot {
 					s.handleONUSoftReboot(onu.IntfID, onu.OnuID)
-				} else if Req.DeviceAction == HardReboot {
+				} else if Req.Action == HardReboot {
 					s.handleONUHardReboot(onu)
 				}
 			case DeviceTypeOlt:
@@ -900,3 +894,27 @@
 		}
 	}
 }
+
+func (s *Server) sendPortStats() {
+	for {
+		for i, port := range s.Olt.NniIntfs {
+			// send nni port stats
+			logger.Debug("Sending port stats for NNI %d", port.IntfID)
+			err := sendPortStats(*s.EnableServer, &s.Olt.NniIntfs[i])
+			if err != nil {
+				logger.Error("Failed to send port stats for NNI %d", port.IntfID)
+			}
+		}
+
+		for i, port := range s.Olt.PonIntfs {
+			// send pon port stats
+			logger.Debug("Sending port stats for PON %d", port.IntfID)
+			err := sendPortStats(*s.EnableServer, &s.Olt.PonIntfs[i])
+			if err != nil {
+				logger.Error("Failed to send port stats for PON %d", port.IntfID)
+			}
+		}
+
+		time.Sleep(10 * time.Second)
+	}
+}
diff --git a/core/dhcp.go b/core/dhcp.go
index b885ec5..c4f1f9a 100644
--- a/core/dhcp.go
+++ b/core/dhcp.go
@@ -33,10 +33,10 @@
 
 // Constants for DHCP states
 const (
-	DHCP_INIT clientState = iota + 1
-	DHCP_SELECTING
-	DHCP_REQUESTING
-	DHCP_BOUND
+	DhcpInit clientState = iota + 1
+	DhcpSelecting
+	DhcpRequesting
+	DhcpBound
 )
 
 type dhcpResponder struct {
@@ -50,7 +50,7 @@
 	srcIP    *net.IPAddr
 	serverIP *net.IPAddr
 	hostname string
-	curId    uint32
+	curID    uint32
 	curState clientState
 }
 
@@ -94,11 +94,11 @@
 			case msg := <-dhcpOut:
 				logger.Debug("Received dhcp message from dhcpOut")
 
-				if c, ok := clients[clientKey{intfid: msg.IntfId, onuid: msg.OnuId}]; ok {
+				if c, ok := clients[clientKey{intfid: msg.IntfID, onuid: msg.OnuID}]; ok {
 					nextstate := respondMessage("DHCP", *c, msg, dhcpIn)
 					c.updateState(nextstate)
 				} else {
-					logger.Error("Failed to find dhcp client instance intfid:%d onuid:%d", msg.IntfId, msg.OnuId)
+					logger.Error("Failed to find dhcp client instance intfid:%d onuid:%d", msg.IntfID, msg.OnuID)
 				}
 			case <-ctx.Done():
 				return
@@ -112,8 +112,8 @@
 	client := dhcpClientInstance{key: clientKey{intfid: intfid, onuid: onuid},
 		srcaddr:  &net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, 0x07, byte(onuid)},
 		hostname: "voltha",
-		curId:    rand.Uint32(),
-		curState: DHCP_INIT}
+		curID:    rand.Uint32(),
+		curState: DhcpInit}
 
 	dhcp := client.createDHCPDisc()
 	bytes, err := client.createDHCP(dhcp)
@@ -125,9 +125,9 @@
 	dhcpIn := resp.dhcpIn
 	if err := client.sendBytes(bytes, dhcpIn); err != nil {
 		logger.Error("Failed to send DHCP Discovery")
-		return errors.New("Failed to send DHCP Discovery")
+		return errors.New("failed to send DHCP Discovery")
 	}
-	client.curState = DHCP_SELECTING
+	client.curState = DhcpSelecting
 	logger.Debug("Sending DHCP Discovery intfid:%d onuid:%d", intfid, onuid)
 	resp.clients[clientKey{intfid: intfid, onuid: onuid}] = &client
 	return nil
@@ -147,30 +147,30 @@
 	if dhcp.Operation == layers.DHCPOpReply && msgType == layers.DHCPMsgTypeOffer {
 		logger.Debug("Received DHCP Offer")
 		logger.Debug(recvpkt.Dump())
-		if cur == DHCP_SELECTING {
+		if cur == DhcpSelecting {
 			senddhcp := c.createDHCPReq()
 			sendbytes, err := c.createDHCP(senddhcp)
 			if err != nil {
 				logger.Debug("Failed to createDHCP")
 				return cur, nil, err
 			}
-			return DHCP_REQUESTING, sendbytes, nil
+			return DhcpRequesting, sendbytes, nil
 		}
 	} else if dhcp.Operation == layers.DHCPOpReply && msgType == layers.DHCPMsgTypeAck {
 		logger.Debug("Received DHCP Ack")
 		logger.Debug(recvpkt.Dump())
-		if cur == DHCP_REQUESTING {
-			return DHCP_BOUND, nil, nil
+		if cur == DhcpRequesting {
+			return DhcpBound, nil, nil
 		}
 	} else if dhcp.Operation == layers.DHCPOpReply && msgType == layers.DHCPMsgTypeRelease {
-		if cur == DHCP_BOUND {
+		if cur == DhcpBound {
 			senddhcp := c.createDHCPDisc()
 			sendbytes, err := c.createDHCP(senddhcp)
 			if err != nil {
 				fmt.Println("Failed to createDHCP")
-				return DHCP_INIT, nil, err
+				return DhcpInit, nil, err
 			}
-			return DHCP_SELECTING, sendbytes, nil
+			return DhcpSelecting, sendbytes, nil
 		}
 	} else {
 		logger.Debug("Received unsupported DHCP message Operation:%d MsgType:%d", dhcp.Operation, msgType)
@@ -222,8 +222,12 @@
 		DstPort: 67,
 	}
 
-	udpLayer.SetNetworkLayerForChecksum(ipLayer)
-	if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
+	err := udpLayer.SetNetworkLayerForChecksum(ipLayer)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
 		return nil, err
 	}
 
@@ -237,21 +241,21 @@
 		HardwareType: layers.LinkTypeEthernet,
 		HardwareLen:  6,
 		HardwareOpts: 0,
-		Xid:          c.curId,
+		Xid:          c.curID,
 		ClientHWAddr: *c.srcaddr,
 	}
 }
 
 func (c *dhcpClientInstance) createDefaultOpts() []layers.DHCPOption {
 	hostname := []byte(c.hostname)
-	opts := []layers.DHCPOption{}
+	var opts []layers.DHCPOption
 	opts = append(opts, layers.DHCPOption{
 		Type:   layers.DHCPOptHostname,
 		Data:   hostname,
 		Length: uint8(len(hostname)),
 	})
 
-	bytes := []byte{}
+	var bytes []byte
 	for _, option := range defaultParamsRequestList {
 		bytes = append(bytes, byte(option))
 	}
@@ -267,7 +271,7 @@
 func (c *dhcpClientInstance) createDHCPDisc() *layers.DHCPv4 {
 	dhcpLayer := c.createDefaultDHCPReq()
 	defaultOpts := c.createDefaultOpts()
-	dhcpLayer.Options = append([]layers.DHCPOption{layers.DHCPOption{
+	dhcpLayer.Options = append([]layers.DHCPOption{{
 		Type:   layers.DHCPOptMessageType,
 		Data:   []byte{byte(layers.DHCPMsgTypeDiscover)},
 		Length: 1,
@@ -311,8 +315,8 @@
 
 func (c *dhcpClientInstance) sendBytes(bytes []byte, dhcpIn chan *byteMsg) error {
 	// Send our packet
-	msg := byteMsg{IntfId: c.key.intfid,
-		OnuId: c.key.onuid,
+	msg := byteMsg{IntfID: c.key.intfid,
+		OnuID: c.key.onuid,
 		Byte:  bytes}
 	dhcpIn <- &msg
 	logger.Debug("sendBytes intfid:%d onuid:%d", c.key.intfid, c.key.onuid)
@@ -324,7 +328,7 @@
 	layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
 	dhcp, _ := layerDHCP.(*layers.DHCPv4)
 	if dhcp == nil {
-		return nil, errors.New("Failed to extract DHCP")
+		return nil, errors.New("failed to extract DHCP")
 	}
 	return dhcp, nil
 }
@@ -344,5 +348,5 @@
 			}
 		}
 	}
-	return 0, errors.New("Failed to extract MsgType from dhcp")
+	return 0, errors.New("failed to extract MsgType from dhcp")
 }
diff --git a/core/eapol.go b/core/eapol.go
index ff14509..0300141 100644
--- a/core/eapol.go
+++ b/core/eapol.go
@@ -22,7 +22,6 @@
 	"encoding/hex"
 	"errors"
 	"fmt"
-	log "github.com/sirupsen/logrus"
 	"net"
 	"sync"
 	"time"
@@ -30,16 +29,17 @@
 	"github.com/google/gopacket"
 	"github.com/google/gopacket/layers"
 	"github.com/opencord/voltha-bbsim/common/logger"
+	log "github.com/sirupsen/logrus"
 )
 
 type clientState int
 
 // Constants for eapol states
 const (
-	EAP_START clientState = iota + 1 // TODO: This state definition should support 802.1X
-	EAP_RESPID
-	EAP_RESPCHA
-	EAP_SUCCESS
+	EapStart clientState = iota + 1 // TODO: This state definition should support 802.1X
+	EapRespid
+	EapRespcha
+	EapSuccess
 )
 
 func (eap clientState) String() string {
@@ -61,7 +61,7 @@
 	key      clientKey
 	srcaddr  *net.HardwareAddr
 	version  uint8
-	curId    uint8
+	curID    uint8
 	curState clientState
 }
 
@@ -91,17 +91,17 @@
 		for {
 			select {
 			case msg := <-eapolOut:
-				logger.Debug("Received eapol from eapolOut intfid:%d onuid:%d", msg.IntfId, msg.OnuId)
+				logger.Debug("Received eapol from eapolOut intfid:%d onuid:%d", msg.IntfID, msg.OnuID)
 				responder := getEAPResponder()
 				clients := responder.clients
-				if c, ok := clients[clientKey{intfid: msg.IntfId, onuid: msg.OnuId}]; ok {
-					logger.Debug("Got client intfid:%d onuid: %d (ClientID: %v)", c.key.intfid, c.key.onuid, c.curId)
+				if c, ok := clients[clientKey{intfid: msg.IntfID, onuid: msg.OnuID}]; ok {
+					logger.Debug("Got client intfid:%d onuid: %d (ClientID: %v)", c.key.intfid, c.key.onuid, c.curID)
 					nextstate := respondMessage("EAPOL", *c, msg, eapolIn)
 					c.updateState(nextstate)
 				} else {
 					logger.WithFields(log.Fields{
 						"clients": clients,
-					}).Errorf("Failed to find eapol client instance intfid:%d onuid:%d", msg.IntfId, msg.OnuId)
+					}).Errorf("Failed to find eapol client instance intfid:%d onuid:%d", msg.IntfID, msg.OnuID)
 				}
 			case <-ctx.Done():
 				return
@@ -136,7 +136,7 @@
 		responder := getEAPResponder()
 		clients := responder.clients
 		if c, ok := clients[clientKey{intfid: intfid, onuid: onuid}]; ok {
-			if c.curState == EAP_SUCCESS {
+			if c.curState == EapSuccess {
 				logger.WithFields(log.Fields{
 					"int_id": intfid,
 					"onu_id": onuid,
@@ -144,7 +144,7 @@
 				break
 			}
 			// Reset state to EAP start
-			c.updateState(EAP_START)
+			c.updateState(EapStart)
 		} else {
 			logger.WithFields(log.Fields{
 				"clients": clients,
@@ -168,8 +168,8 @@
 	client := eapClientInstance{key: clientKey{intfid: intfid, onuid: onuid},
 		srcaddr:  &net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, 0x07, byte(onuid)},
 		version:  1,
-		curId:    0,
-		curState: EAP_START}
+		curID:    0,
+		curState: EapStart}
 
 	eap := client.createEAPStart()
 	bytes := client.createEAPOL(eap)
@@ -191,31 +191,31 @@
 	if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeIdentity {
 		logger.Debug("Received EAP-Request/Identity")
 		logger.Debug(recvpkt.Dump())
-		c.curId = eap.Id
-		if cur == EAP_START {
+		c.curID = eap.Id
+		if cur == EapStart {
 			reseap := c.createEAPResID()
 			pkt := c.createEAPOL(reseap)
-			logger.Debug("Moving from EAP_START to EAP_RESPID")
-			return EAP_RESPID, pkt, nil
+			logger.Debug("Moving from EapStart to EapRespid")
+			return EapRespid, pkt, nil
 		}
 	} else if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeOTP {
 		logger.Debug("Received EAP-Request/Challenge")
 		logger.Debug(recvpkt.Dump())
-		if cur == EAP_RESPID {
-			c.curId = eap.Id
-			senddata := getMD5Data(c.curId, eap)
+		if cur == EapRespid {
+			c.curID = eap.Id
+			senddata := getMD5Data(c.curID, eap)
 			senddata = append([]byte{0x10}, senddata...)
 			sendeap := c.createEAPResCha(senddata)
 			pkt := c.createEAPOL(sendeap)
-			logger.Debug("Moving from EAP_RESPID to EAP_RESPCHA")
-			return EAP_RESPCHA, pkt, nil
+			logger.Debug("Moving from EapRespid to EapRespcha")
+			return EapRespcha, pkt, nil
 		}
 	} else if eap.Code == layers.EAPCodeSuccess && eap.Type == layers.EAPTypeNone {
 		logger.Debug("Received EAP-Success")
 		logger.Debug(recvpkt.Dump())
-		if cur == EAP_RESPCHA {
-			logger.Debug("Moving from EAP_RESPCHA to EAP_SUCCESS")
-			return EAP_SUCCESS, nil, nil
+		if cur == EapRespcha {
+			logger.Debug("Moving from EapRespcha to EapSuccess")
+			return EapSuccess, nil, nil
 		}
 	} else {
 		logger.Debug("Received unsupported EAP")
@@ -242,8 +242,8 @@
 
 func sendBytes(key clientKey, pkt []byte, chIn chan *byteMsg) error {
 	// Send our packet
-	msg := byteMsg{IntfId: key.intfid,
-		OnuId: key.onuid,
+	msg := byteMsg{IntfID: key.intfid,
+		OnuID: key.onuid,
 		Byte:  pkt}
 	chIn <- &msg
 	logger.Debug("sendBytes intfid:%d onuid:%d", key.intfid, key.onuid)
@@ -262,12 +262,12 @@
 	}
 
 	if eap == nil { // EAP Start
-		gopacket.SerializeLayers(buffer, options,
+		_ = gopacket.SerializeLayers(buffer, options,
 			ethernetLayer,
 			&layers.EAPOL{Version: c.version, Type: 1, Length: 0},
 		)
 	} else {
-		gopacket.SerializeLayers(buffer, options,
+		_ = gopacket.SerializeLayers(buffer, options,
 			ethernetLayer,
 			&layers.EAPOL{Version: c.version, Type: 0, Length: eap.Length},
 			eap,
@@ -283,7 +283,7 @@
 
 func (c *eapClientInstance) createEAPResID() *layers.EAP {
 	eap := layers.EAP{Code: layers.EAPCodeResponse,
-		Id:       c.curId,
+		Id:       c.curID,
 		Length:   9,
 		Type:     layers.EAPTypeIdentity,
 		TypeData: []byte{0x75, 0x73, 0x65, 0x72}}
@@ -292,7 +292,7 @@
 
 func (c *eapClientInstance) createEAPResCha(payload []byte) *layers.EAP {
 	eap := layers.EAP{Code: layers.EAPCodeResponse,
-		Id: c.curId, Length: 22,
+		Id: c.curID, Length: 22,
 		Type:     layers.EAPTypeOTP,
 		TypeData: payload}
 	return &eap
@@ -314,7 +314,7 @@
 	layerEAPOL := pkt.Layer(layers.LayerTypeEAPOL)
 	eapol, _ := layerEAPOL.(*layers.EAPOL)
 	if eapol == nil {
-		return nil, errors.New("Cannot extract EAPOL")
+		return nil, errors.New("cannot extract EAPOL")
 	}
 	return eapol, nil
 }
@@ -323,7 +323,7 @@
 	layerEAP := pkt.Layer(layers.LayerTypeEAP)
 	eap, _ := layerEAP.(*layers.EAP)
 	if eap == nil {
-		return nil, errors.New("Cannot extract EAP")
+		return nil, errors.New("cannot extract EAP")
 	}
 	return eap, nil
 }
diff --git a/core/grpc_service.go b/core/grpc_service.go
index 651ebc7..29c93b7 100644
--- a/core/grpc_service.go
+++ b/core/grpc_service.go
@@ -17,7 +17,6 @@
 package core
 
 import (
-	"github.com/opencord/voltha-protos/go/tech_profile"
 	"net"
 
 	"github.com/google/gopacket"
@@ -27,6 +26,7 @@
 	"github.com/opencord/voltha-bbsim/device"
 	flowHandler "github.com/opencord/voltha-bbsim/flow"
 	openolt "github.com/opencord/voltha-protos/go/openolt"
+	"github.com/opencord/voltha-protos/go/tech_profile"
 	log "github.com/sirupsen/logrus"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
@@ -62,6 +62,7 @@
 	}
 
 	if s.EnableServer != nil {
+		s.Olt.OperState = "up"
 		if err := sendOltIndUp(*s.EnableServer, s.Olt); err != nil {
 			logger.Error("Failed to send OLT UP indication for reenable OLT: %v", err)
 			return new(openolt.Empty), err
@@ -102,16 +103,16 @@
 
 // ActivateOnu method handles ONU activation request from VOLTHA
 func (s *Server) ActivateOnu(c context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
-	logger.Debug("OLT receives ActivateONU()")
+	logger.Trace("OLT receives ActivateONU()")
 
 	matched, exist := s.getOnuFromSNmap(onu.SerialNumber)
 	if !exist {
-		logger.Fatal("ONU not found with serial nnumber %v", onu.SerialNumber)
+		logger.Error("ONU not found with serial nnumber %v", onu.SerialNumber)
 		return new(openolt.Empty), status.Errorf(codes.NotFound, "ONU not found with serial number %v", onu.SerialNumber)
 	}
 	onuid := onu.OnuId
 	matched.OnuID = onuid
-	s.updateDevIntState(matched, device.ONU_ACTIVE)
+	s.updateDevIntState(matched, device.OnuActive)
 	logger.Debug("ONU IntfID: %d OnuID: %d activated succesufully.", onu.IntfId, onu.OnuId)
 	if err := sendOnuInd(*s.EnableServer, matched, "up", "up"); err != nil {
 		logger.Error("Failed to send ONU Indication intfID %d, onuID %d", matched.IntfID, matched.OnuID)
@@ -122,14 +123,29 @@
 }
 
 // CreateTrafficSchedulers method should handle TrafficScheduler creation
-func (s *Server) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
-	logger.Debug("OLT receives CreateTrafficSchedulers()")
+func (s *Server) CreateTrafficSchedulers(c context.Context, traffScheduler *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
+	logger.Debug("OLT receives CreateTrafficSchedulers %v", traffScheduler)
+	onu, err := s.GetOnuByID(traffScheduler.OnuId, traffScheduler.IntfId)
+	if err != nil {
+		return new(openolt.Empty), err
+	}
+	onu.Tconts = traffScheduler
 	return new(openolt.Empty), nil
 }
 
 // RemoveTrafficSchedulers method should handle TrafficScheduler removal
-func (s *Server) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
-	logger.Debug("OLT receives RemoveTrafficSchedulers()")
+func (s *Server) RemoveTrafficSchedulers(c context.Context, traffScheduler *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
+	logger.Debug("OLT receives RemoveTrafficSchedulers %v", traffScheduler)
+	onu, err := s.GetOnuByID(traffScheduler.OnuId, traffScheduler.IntfId)
+	if err != nil {
+		return new(openolt.Empty), err
+	}
+	for _, tcont := range traffScheduler.TrafficScheds {
+		if _, exist := onu.GemPortMap[tcont.AllocId]; exist {
+			delete(onu.GemPortMap, tcont.AllocId)
+		}
+	}
+	onu.Tconts = nil
 	return new(openolt.Empty), nil
 }
 
@@ -160,7 +176,7 @@
 	}
 
 	// Mark ONU internal state as ONU_FREE and reset onuID
-	Onu.InternalState = device.ONU_FREE
+	Onu.InternalState = device.OnuFree
 	Onu.OnuID = 0
 
 	// Get snMap key for the ONU serial number
@@ -172,6 +188,7 @@
 	return new(openolt.Empty), nil
 }
 
+// GetOnuInfo returns ONU info to VOLTHA
 func (s *Server) GetOnuInfo(c context.Context, onu *openolt.Onu) (*openolt.OnuIndication, error) {
 	logger.Debug("Olt receives GetOnuInfo() intfID: %d, onuID: %d", onu.IntfId, onu.OnuId)
 	Onu, err := s.GetOnuByID(onu.OnuId, onu.IntfId)
@@ -199,8 +216,8 @@
 	state := onu.GetIntState()
 	logger.Debug("ONU-ID: %v, ONU state: %d", msg.OnuId, state)
 
-	// If ONU is ONU_INACTIVE, ONU_FREE or ONU_OMCI_CHANNEL_LOS_RAISED drop
-	if state != device.ONU_ACTIVE && state != device.ONU_OMCIACTIVE && state != device.ONU_AUTHENTICATED {
+	// If ONU is not ACTIVE drop OMCI message
+	if state < device.OnuActive {
 		logger.Info("ONU (IF %v ONU-ID: %v) is not ACTIVE, so not processing OmciMsg", msg.IntfId, msg.OnuId)
 		return new(openolt.Empty), nil
 	}
@@ -208,6 +225,7 @@
 	return new(openolt.Empty), nil
 }
 
+// OnuPacketOut is used by voltha to send OnuPackets to BBSIM
 func (s *Server) OnuPacketOut(c context.Context, packet *openolt.OnuPacket) (*openolt.Empty, error) {
 	onu, err := s.GetOnuByID(packet.OnuId, packet.IntfId)
 	if err != nil {
@@ -225,6 +243,7 @@
 	return new(openolt.Empty), nil
 }
 
+// UplinkPacketOut sends uplink packets to BBSIM
 func (s *Server) UplinkPacketOut(c context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
 	logger.Debug("OLT %d receives UplinkPacketOut().", s.Olt.ID)
 	rawpkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
@@ -238,7 +257,7 @@
 func (s *Server) FlowAdd(c context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
 	logger.Debug("OLT %d receives FlowAdd() %v", s.Olt.ID, flow)
 	// Check if flow already present
-	flowKey := FlowKey{
+	flowKey := device.FlowKey{
 		FlowID:        flow.FlowId,
 		FlowDirection: flow.FlowType,
 	}
@@ -251,7 +270,6 @@
 	err := flowHandler.AddFlow(flow)
 	if err != nil {
 		logger.Error("Error in pushing flow to datapath")
-		return new(openolt.Empty), err
 	}
 
 	// Update flowMap
@@ -259,12 +277,18 @@
 
 	onu, err := s.GetOnuByID(uint32(flow.OnuId), uint32(flow.AccessIntfId))
 	if err == nil {
-		onu.GemportID = uint16(flow.GemportId)
-
-		device.LoggerWithOnu(onu).WithFields(log.Fields{
-			"olt":   s.Olt.ID,
-			"c_tag": flow.Action.IVid,
-		}).Debug("OLT receives FlowAdd().")
+		exist := false
+		// check if gemport already present in ONU
+		for _, gemport := range onu.GemPortMap[uint32(flow.AllocId)] {
+			if gemport == uint32(flow.GemportId) {
+				exist = true
+				break
+			}
+		}
+		// if not present already, then append in gemport list
+		if !exist {
+			onu.GemPortMap[uint32(flow.AllocId)] = append(onu.GemPortMap[uint32(flow.AllocId)], uint32(flow.GemportId))
+		}
 
 		// EAPOL flow
 		if flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) {
@@ -290,9 +314,8 @@
 				if omcistate != omci.DONE {
 					logger.Warn("FlowAdd() OMCI state %d is not \"DONE\"", omci.GetOnuOmciState(onu.OnuID, onu.IntfID))
 				}
-				_ = s.updateOnuIntState(onu.IntfID, onu.OnuID, device.ONU_OMCIACTIVE)
+				_ = s.updateOnuIntState(onu.IntfID, onu.OnuID, device.OnuOmciActive)
 			}
-
 		}
 
 		// DHCP flow
@@ -305,11 +328,11 @@
 				if omcistate != omci.DONE {
 					logger.Warn("FlowAdd() OMCI state %d is not \"DONE\"", omci.GetOnuOmciState(onu.OnuID, onu.IntfID))
 				}
-				_ = s.updateOnuIntState(onu.IntfID, onu.OnuID, device.ONU_AUTHENTICATED)
+				_ = s.updateOnuIntState(onu.IntfID, onu.OnuID, device.OnuAuthenticated)
 			}
 		}
-		// Update flow ID in ONU object
-		onu.FlowIDs = append(onu.FlowIDs, flow.FlowId)
+		// Update flows in ONU object
+		onu.Flows = append(onu.Flows, flowKey)
 	}
 	return new(openolt.Empty), nil
 }
@@ -319,7 +342,7 @@
 	logger.Debug("OLT %d receives FlowRemove(): %v", s.Olt.ID, flow)
 
 	// Check if flow exists
-	flowKey := FlowKey{
+	flowKey := device.FlowKey{
 		FlowID:        flow.FlowId,
 		FlowDirection: flow.FlowType,
 	}
@@ -332,20 +355,16 @@
 	// Send delete flow to flowHandler
 	err := flowHandler.DeleteFlow(flow)
 	if err != nil {
-		return new(openolt.Empty), err
+		logger.Error("failed to delete flow")
 	}
 
 	onu, err := s.GetOnuByID(uint32(flow.OnuId), uint32(flow.AccessIntfId))
 	if err != nil {
 		logger.Warn("Failed flow remove %v", err)
 	} else {
-		// Delete flowID from onu
-		onu.DeleteFlowID(flow.FlowId)
-		device.LoggerWithOnu(onu).WithFields(log.Fields{
-			"olt":   s.Olt.ID,
-			"c_tag": flow.Action.IVid,
-		}).Debug("OLT receives FlowRemove().")
-		logger.Debug("Flows %v in ONU %d", onu.FlowIDs, onu.OnuID)
+		// Delete flows from onu
+		onu.DeleteFlow(flowKey)
+		logger.Debug("Flows %v in onu %d", onu.Flows, onu.OnuID)
 	}
 
 	// Delete flow from flowMap
@@ -354,6 +373,7 @@
 	return new(openolt.Empty), nil
 }
 
+// HeartbeatCheck is currently not used by voltha
 func (s *Server) HeartbeatCheck(c context.Context, empty *openolt.Empty) (*openolt.Heartbeat, error) {
 	logger.Debug("OLT %d receives HeartbeatCheck().", s.Olt.ID)
 	signature := new(openolt.Heartbeat)
@@ -361,11 +381,13 @@
 	return signature, nil
 }
 
+// EnablePonIf enables pon interfaces at BBSIM
 func (s *Server) EnablePonIf(c context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
 	logger.Debug("OLT %d receives EnablePonIf().", s.Olt.ID)
 	return new(openolt.Empty), nil
 }
 
+// GetPonIf returns interface info to VOLTHA
 func (s *Server) GetPonIf(c context.Context, intf *openolt.Interface) (*openolt.IntfIndication, error) {
 	logger.Debug("OLT %d receives GetPonIf().", s.Olt.ID)
 	stat := new(openolt.IntfIndication)
@@ -380,6 +402,7 @@
 
 }
 
+// DisablePonIf disables pon interface at BBSIM
 func (s *Server) DisablePonIf(c context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
 	logger.Debug("OLT %d receives DisablePonIf().", s.Olt.ID)
 	return new(openolt.Empty), nil
@@ -409,7 +432,7 @@
 
 // NewGrpcServer starts openolt gRPC server
 func NewGrpcServer(addrport string) (l net.Listener, g *grpc.Server, e error) {
-	logger.Debug("OpenOLT gRPC server listening %s ...", addrport)
+	logger.Info("OpenOLT gRPC server listening %s ...", addrport)
 	g = grpc.NewServer()
 	l, e = net.Listen("tcp", addrport)
 	return
diff --git a/core/io_info.go b/core/io_info.go
index 527aaa4..caad5ef 100644
--- a/core/io_info.go
+++ b/core/io_info.go
@@ -41,7 +41,7 @@
 			return ioinfo, nil
 		}
 	}
-	err := errors.New("No matched Ioinfo is found")
+	err := errors.New("no matched Ioinfo is found")
 	logger.Error("identifyUniIoinfo %s", err)
 	return nil, err
 }
@@ -53,7 +53,7 @@
 			return ioinfo, nil
 		}
 	}
-	err := errors.New("No matched Ioinfo is found")
+	err := errors.New("no matched Ioinfo is found")
 	logger.Error("IdentifyNniIoinfo %s", err)
 	return nil, err
 }
@@ -84,13 +84,13 @@
 }
 
 // RemoveVeth deletes veth by given name
-func RemoveVeth(name string) error {
+func RemoveVeth(name string) {
 	err := exec.Command("ip", "link", "del", name).Run()
 	if err != nil {
 		logger.WithField("veth", name).Error("Fail to removeVeth()", err)
+		return
 	}
 	logger.WithField("veth", name).Info("Veth was removed.")
-	return err
 }
 
 // RemoveVeths deletes veth
diff --git a/core/io_worker.go b/core/io_worker.go
index 1c090a8..ec70cc9 100644
--- a/core/io_worker.go
+++ b/core/io_worker.go
@@ -33,7 +33,8 @@
 	logger.Debug("recvWorker runs. handler: %v", *handler)
 	packetSource := gopacket.NewPacketSource(handler, handler.LinkType())
 	for packet := range packetSource.Packets() {
-		logger.Debug("recv packet from IF: %v ", *handler)
+		logger.Debug("recv packet from IF: %v", *handler)
+		logger.Debug("Packet received %v", packet)
 		// logger.Println(packet.Dump())
 		pkt := Packet{}
 		pkt.Info = io
@@ -71,10 +72,14 @@
 				EthernetType: layer.Type,
 			}
 			buffer := gopacket.NewSerializeBuffer()
-			gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
+			err := gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
 				ethernetLayer,
 				gopacket.Payload(layer.Payload),
 			)
+			if err != nil {
+				logger.Error("%v", err)
+			}
+
 			retpkt := gopacket.NewPacket(
 				buffer.Bytes(),
 				layers.LayerTypeEthernet,
@@ -102,7 +107,7 @@
 		}
 
 		buffer := gopacket.NewSerializeBuffer()
-		gopacket.SerializeLayers(
+		err := gopacket.SerializeLayers(
 			buffer,
 			gopacket.SerializeOptions{
 				FixLengths: false,
@@ -111,6 +116,10 @@
 			dot1qLayer,
 			gopacket.Payload(eth.Payload),
 		)
+		if err != nil {
+			logger.Error("%v", err)
+		}
+
 		ret := gopacket.NewPacket(
 			buffer.Bytes(),
 			layers.LayerTypeEthernet,
@@ -172,13 +181,13 @@
 
 func getVethHandler(vethname string) (*pcap.Handle, error) {
 	var (
-		device            = vethname
+		deviceName        = vethname
 		snapshotLen int32 = 1518
 		promiscuous       = false
 		err         error
 		timeout     = pcap.BlockForever
 	)
-	handle, err := pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
+	handle, err := pcap.OpenLive(deviceName, snapshotLen, promiscuous, timeout)
 	if err != nil {
 		return nil, err
 	}
diff --git a/core/mediator.go b/core/mediator.go
index 0756651..97bd128 100644
--- a/core/mediator.go
+++ b/core/mediator.go
@@ -24,6 +24,7 @@
 	"strconv"
 	"strings"
 	"sync"
+	"syscall"
 	"time"
 
 	"github.com/opencord/voltha-bbsim/common/logger"
@@ -31,19 +32,21 @@
 	log "github.com/sirupsen/logrus"
 )
 
+// Constants for tester mode
 const (
 	DEFAULT Mode = iota
 	AAA
 	BOTH
 )
 
-// Store emulation mode
+// Mode store emulation mode
 type Mode int
 
 // AutoONUActivate is flag for Auto ONU Add on/off.
 var AutoONUActivate int
 
-type option struct {
+//Option is the structure to store the user provided flag values
+type Option struct {
 	address                  string
 	port                     uint32
 	mgmtGrpcPort             uint32
@@ -61,9 +64,9 @@
 	Debuglvl                 string
 }
 
-// GetOptions receives command line options and stores them in option structure
-func GetOptions() *option {
-	o := new(option)
+// GetOptions receives command line options and stores them in Option structure
+func GetOptions() *Option {
+	o := new(Option)
 	addressport := flag.String("H", ":50060", "IP address:port")
 	oltid := flag.Int("id", 0, "OLT-ID")
 	npon := flag.Int("i", 1, "Number of PON-IF ports")
@@ -88,13 +91,25 @@
 	o.Debuglvl = *debg
 	o.oltid = uint32(*oltid)
 	o.npon = uint32(*npon)
+	// make sure to have at-lease 1 PON port available
+	if o.npon == 0 {
+		o.npon = 1
+	}
 	o.nonus = uint32(*nonus)
+	// make sure to have at-least 1 ONU is available
+	if o.nonus == 0 {
+		o.nonus = 1
+	}
 	o.aaawait = *aaawait
 	o.dhcpwait = *dhcpwait
 	o.dhcpservip = *dhcpservip
 	o.intvl = *intvl
 	o.interactiveOnuActivation = *interactiveOnuActivation
 	o.KafkaBroker = *kafkaBroker
+	// make sure that 'IP:Port' or ':Port' provided properly.
+	if !strings.Contains(*addressport, ":") {
+		log.Fatal("Invalid address given (missing colon)")
+	}
 	o.address = strings.Split(*addressport, ":")[0]
 	tmp, _ := strconv.Atoi(strings.Split(*addressport, ":")[1])
 	o.port = uint32(tmp)
@@ -108,15 +123,16 @@
 	return o
 }
 
-type mediator struct {
-	opt         *option
+//Mediator stores option, server and testmanager to mediate
+type Mediator struct {
+	opt         *Option
 	server      *Server
 	testmanager *TestManager
 }
 
-// NewMediator returns a new mediator object
-func NewMediator(o *option) *mediator {
-	m := new(mediator)
+// NewMediator returns a new Mediator object
+func NewMediator(o *Option) *Mediator {
+	m := new(Mediator)
 	m.opt = o
 	logger.WithFields(log.Fields{
 		"ip":        o.address,
@@ -124,12 +140,12 @@
 		"pon_ports": o.npon,
 		"onus":      o.nonus,
 		"mode":      o.Mode,
-	}).Debug("New mediator")
+	}).Debug("New Mediator")
 	return m
 }
 
-// Start mediator
-func (m *mediator) Start() {
+// Start Mediator
+func (m *Mediator) Start() {
 	var wg sync.WaitGroup
 	opt := m.opt
 	server := NewCore(opt)
@@ -147,7 +163,7 @@
 	}()
 
 	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt)
+	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
 	go func() {
 		defer func() {
 			logger.Debug("SIGINT catcher Done")
@@ -157,9 +173,15 @@
 			wg.Add(1)
 			logger.Debug("SIGINT %v", sig)
 			close(c)
-			server.Stop() // Non-blocking
-			tm.Stop()     // Non-blocking
-			server.stopMgmtServer()
+			server.Stop()    // Non-blocking
+			err := tm.Stop() // Non-blocking
+			if err != nil {
+				logger.Error("Error stopping the TestManager %v", err)
+			}
+			err = server.stopMgmtServer()
+			if err != nil {
+				logger.Error("Error stopping the Management Server %v", err)
+			}
 			server.wg.Done()
 			return
 		}
@@ -169,7 +191,7 @@
 }
 
 // Mediate method is invoked on OLT and ONU state change
-func (m *mediator) Mediate() {
+func (m *Mediator) Mediate() {
 	defer logger.Debug("Mediate Done")
 	for sr := range m.server.stateRepCh {
 		next := sr.next
@@ -194,31 +216,37 @@
 	}
 }
 
-func transitOlt(current device.DeviceState, next device.DeviceState, tm *TestManager, o *option) error {
+func transitOlt(current device.State, next device.State, tm *TestManager, o *Option) error {
 	logger.Debug("trnsitOlt called current:%d , next:%d", current, next)
-	if current == device.OLT_PREACTIVE && next == device.OLT_ACTIVE {
-		tm.Start()
+	if current == device.OltPreactive && next == device.OltActive {
+		err := tm.Start()
+		if err != nil {
+			logger.Error("Error starting the TestManager %v", err)
+		}
 		nniup, _ := makeNniName(o.oltid)
-		activateDHCPServer(nniup, o.dhcpservip)
-	} else if current == device.OLT_ACTIVE && next == device.OLT_PREACTIVE {
-		tm.Stop()
-	} else if current == device.OLT_ACTIVE && next == device.OLT_INACTIVE {
-		// Reboot case
-		// TODO Point of discussion
+		err = activateDHCPServer(nniup, o.dhcpservip)
+		if err != nil {
+			logger.Error("Error activating DHCP Server %v", err)
+		}
+	} else if current == device.OltActive && next == device.OltPreactive {
+		err := tm.Stop()
+		if err != nil {
+			logger.Error("Error stoping the TestManager %v", err)
+		}
 	}
 	return nil
 }
 
-func transitOnu(key device.Devkey, previous device.DeviceState, current device.DeviceState, tm *TestManager, o *option) error {
+func transitOnu(key device.Devkey, previous device.State, current device.State, tm *TestManager, o *Option) error {
 	logger.Debug("transitOnu called with key: %v, previous: %s, current: %s", key, device.ONUState[previous], device.ONUState[current])
 	if o.Mode == AAA || o.Mode == BOTH {
-		if previous == device.ONU_ACTIVE && current == device.ONU_OMCIACTIVE {
+		if previous == device.OnuActive && current == device.OnuOmciActive {
 			logger.Debug("Starting WPASupplicant for device %v", key)
 			t := tm.CreateTester("AAA", o, key, activateWPASupplicant, o.aaawait)
 			if err := tm.StartTester(t); err != nil {
 				logger.Error("Cannot Start AAA Executer error:%v", err)
 			}
-		} else if previous == device.ONU_OMCIACTIVE && current == device.ONU_INACTIVE {
+		} else if previous == device.OnuOmciActive && current == device.OnuInactive {
 			if err := tm.StopTester("AAA", key); err != nil {
 				logger.Error("Cannot Stop AAA Executer error:%v", err)
 			}
@@ -226,13 +254,13 @@
 	}
 
 	if o.Mode == BOTH {
-		if previous == device.ONU_OMCIACTIVE && current == device.ONU_AUTHENTICATED {
+		if previous == device.OnuOmciActive && current == device.OnuAuthenticated {
 			logger.Debug("Starting DHCP client for device %v", key)
 			t := tm.CreateTester("DHCP", o, key, activateDHCPClient, o.dhcpwait)
 			if err := tm.StartTester(t); err != nil {
 				logger.Error("Cannot Start DHCP Executer error:%v", err)
 			}
-		} else if previous == device.ONU_AUTHENTICATED && current == device.ONU_INACTIVE {
+		} else if previous == device.OnuAuthenticated && current == device.OnuInactive {
 			if err := tm.StopTester("DHCP", key); err != nil {
 				logger.Error("Cannot Stop DHCP Executer error:%v", err)
 			}
diff --git a/core/omci.go b/core/omci.go
index 857e98e..3caed49 100644
--- a/core/omci.go
+++ b/core/omci.go
@@ -86,5 +86,16 @@
 			logger.Info("ONU reboot recieved")
 			s.handleONUSoftReboot(IntfID, OnuID)
 		}
+	} else if MEClass == omci.GEMPortNetworkCTP {
+		switch msgType {
+		case omci.Create:
+			logger.Info("GEMPort created")
+			gemport, err := omci.GetGemPortId(IntfID, OnuID)
+			if err != nil {
+				logger.Error("error in getting gemport %v", err)
+				return
+			}
+			logger.Info("GEM Port %d created at ONU %d intf-id %d", gemport, OnuID, IntfID)
+		}
 	}
 }
diff --git a/core/openolt_service.go b/core/openolt_service.go
index 7c7f498..cd96970 100644
--- a/core/openolt_service.go
+++ b/core/openolt_service.go
@@ -17,14 +17,14 @@
 package core
 
 import (
-
 	"github.com/opencord/voltha-bbsim/common/logger"
 	"github.com/opencord/voltha-bbsim/device"
+	"github.com/opencord/voltha-bbsim/flow"
 	openolt "github.com/opencord/voltha-protos/go/openolt"
 )
 
 func sendOltIndUp(stream openolt.Openolt_EnableIndicationServer, olt *device.Olt) error {
-	data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: "up"}}
+	data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: olt.OperState}}
 	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
 		logger.Error("Failed to send OLT UP indication: %v", err)
 		return err
@@ -45,7 +45,7 @@
 	// There is no need to send IntfInd for NNI
 	for i := uint32(0); i < olt.NumPonIntf; i++ {
 		intf := olt.PonIntfs[i]
-		data := &openolt.Indication_IntfInd{&openolt.IntfIndication{IntfId: intf.IntfID, OperState: intf.OperState}}
+		data := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{IntfId: intf.IntfID, OperState: intf.OperState}}
 		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
 			logger.Error("Failed to send Intf [id: %d] indication : %v", i, err)
 			return err
@@ -59,7 +59,7 @@
 	// Send OperInd for Nni
 	for i := uint32(0); i < olt.NumNniIntf; i++ {
 		intf := olt.NniIntfs[i]
-		data := &openolt.Indication_IntfOperInd{&openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
+		data := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
 		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
 			logger.Error("Failed to send NNI IntfOper [id: %d] indication : %v", i, err)
 			return err
@@ -70,7 +70,7 @@
 	// Send OperInd for Pon
 	for i := uint32(0); i < olt.NumPonIntf; i++ {
 		intf := olt.PonIntfs[i]
-		data := &openolt.Indication_IntfOperInd{&openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
+		data := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
 		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
 			logger.Error("Failed to send PON IntfOper [id: %d] indication : %v", i, err)
 			return err
@@ -133,3 +133,12 @@
 		}
 	}
 }
+
+func sendPortStats(stream openolt.Openolt_EnableIndicationServer, port *device.Port) error {
+	portStats := flow.GetPortStats(&port.PortStats)
+	portStats.IntfId = interfaceIDToPortNo(port.IntfID, port.Type)
+	data := &openolt.Indication_PortStats{
+		PortStats: portStats,
+	}
+	return stream.Send(&openolt.Indication{Data: data})
+}
diff --git a/core/tester.go b/core/tester.go
index 623447d..2f445c7 100644
--- a/core/tester.go
+++ b/core/tester.go
@@ -48,14 +48,14 @@
 }
 
 // NewTestManager returns new TestManager
-func NewTestManager(opt *option) *TestManager {
+func NewTestManager(opt *Option) *TestManager {
 	t := new(TestManager)
 	t.DhcpServerIP = opt.dhcpservip
 	return t
 }
 
 // CreateTester creates instance of Tester
-func (*TestManager) CreateTester(testtype string, opt *option, key device.Devkey, fn func(device.Devkey) error, waitsec int) *Tester {
+func (*TestManager) CreateTester(testtype string, opt *Option, key device.Devkey, fn func(device.Devkey) error, waitsec int) *Tester {
 	logger.Debug("CreateTester() called")
 	t := new(Tester)
 	t.Type = testtype
@@ -87,6 +87,7 @@
 	return nil
 }
 
+// StartTester starts the test
 func (tm *TestManager) StartTester(t *Tester) error {
 	testtype := t.Type
 	key := t.Key
@@ -142,15 +143,30 @@
 	logger.Info("TestManager Initialize () called")
 	pids := tm.Pid
 	logger.Debug("Runnig Process: %v", pids)
-	KillProcesses(pids)
-	exec.Command("rm", "/var/run/dhcpd.pid").Run()    // This is for DHCP server activation
-	exec.Command("touch", "/var/run/dhcpd.pid").Run() // This is for DHCP server activation
+
+	err := KillProcesses(pids)
+	if err != nil {
+		logger.Error("%v", err)
+	}
+
+	err = exec.Command("rm", "/var/run/dhcpd.pid").Run() // This is for DHCP server activation
+	if err != nil {
+		logger.Error("%v", err)
+	}
+
+	err = exec.Command("touch", "/var/run/dhcpd.pid").Run() // This is for DHCP server activation
+	if err != nil {
+		logger.Error("%v", err)
+	}
 }
 
 // KillProcesses kill process by specified pid
 func KillProcesses(pids []int) error {
 	for _, pname := range pids {
-		killProcess(pname)
+		err := killProcess(pname)
+		if err != nil {
+			logger.Error("%v", err)
+		}
 	}
 	return nil
 }
diff --git a/device/device_olt.go b/device/device_olt.go
index b3dc2c3..719f67b 100644
--- a/device/device_olt.go
+++ b/device/device_olt.go
@@ -21,13 +21,14 @@
 	"sync"
 )
 
-type DeviceState int
+//State represents the OLT States
+type State int
 
 // Device interface provides common methods for OLT and ONU devices
 type Device interface {
 	Initialize()
-	UpdateIntState(intstate DeviceState)
-	GetIntState() DeviceState
+	UpdateIntState(intstate State)
+	GetIntState() State
 	GetDevkey() Devkey
 }
 
@@ -46,10 +47,10 @@
 	SerialNumber       string
 	Manufacture        string
 	Name               string
-	InternalState      DeviceState
+	InternalState      State
 	OperState          string
-	NniIntfs           []nniIntf
-	PonIntfs           []ponIntf
+	NniIntfs           []Port
+	PonIntfs           []Port
 	HeartbeatSignature uint32
 	mu                 *sync.Mutex
 }
@@ -68,21 +69,21 @@
 	NniLosRaised
 )
 
-type ponIntf struct {
+// Port info for NNI and PON ports
+type Port struct {
 	Type       string
 	IntfID     uint32
 	OperState  string
 	AlarmState AlarmState
+	PortStats  PortStats
 }
 
-type nniIntf struct {
-	Type       string
-	IntfID     uint32
-	OperState  string
-	AlarmState AlarmState
+// PortStats for NNI and PON ports
+type PortStats struct {
+	Packets uint64
 }
 
-// Constants for port types
+// Constants for Port types
 const (
 	IntfPon = "pon"
 	IntfNni = "nni"
@@ -96,9 +97,9 @@
 
 // Constants for OLT states
 const (
-	OLT_INACTIVE  DeviceState = iota // OLT/ONUs are not instantiated
-	OLT_PREACTIVE                    // Before PacketInDaemon Running
-	OLT_ACTIVE                       // After PacketInDaemon Running
+	OltInactive  State = iota // OLT/ONUs are not instantiated
+	OltPreactive              // Before PacketInDaemon Running
+	OltActive                 // After PacketInDaemon Running
 )
 
 // OLTAlarmStateToString is used to get alarm state as string
@@ -116,12 +117,12 @@
 	olt.NumPonIntf = npon
 	olt.NumNniIntf = nnni
 	olt.Name = "BBSIM OLT"
-	olt.InternalState = OLT_INACTIVE
+	olt.InternalState = OltInactive
 	olt.OperState = "up"
 	olt.Manufacture = "BBSIM"
 	olt.SerialNumber = "BBSIMOLT00" + strconv.FormatInt(int64(oltid), 10)
-	olt.NniIntfs = make([]nniIntf, olt.NumNniIntf)
-	olt.PonIntfs = make([]ponIntf, olt.NumPonIntf)
+	olt.NniIntfs = make([]Port, olt.NumNniIntf)
+	olt.PonIntfs = make([]Port, olt.NumPonIntf)
 	olt.HeartbeatSignature = oltid
 	olt.mu = &sync.Mutex{}
 	for i := uint32(0); i < olt.NumNniIntf; i++ {
@@ -141,7 +142,7 @@
 
 // Initialize method initializes NNI and PON ports
 func (olt *Olt) Initialize() {
-	olt.InternalState = OLT_INACTIVE
+	olt.InternalState = OltInactive
 	olt.OperState = "up"
 	for i := uint32(0); i < olt.NumNniIntf; i++ {
 		olt.NniIntfs[i].IntfID = i
@@ -158,7 +159,7 @@
 }
 
 // GetIntState returns internal state of OLT
-func (olt *Olt) GetIntState() DeviceState {
+func (olt *Olt) GetIntState() State {
 	olt.mu.Lock()
 	defer olt.mu.Unlock()
 	return olt.InternalState
@@ -170,7 +171,7 @@
 }
 
 // UpdateIntState method updates OLT internal state
-func (olt *Olt) UpdateIntState(intstate DeviceState) {
+func (olt *Olt) UpdateIntState(intstate State) {
 	olt.mu.Lock()
 	defer olt.mu.Unlock()
 	olt.InternalState = intstate
diff --git a/device/device_onu.go b/device/device_onu.go
index aafa793..b0af2c2 100644
--- a/device/device_onu.go
+++ b/device/device_onu.go
@@ -22,43 +22,51 @@
 
 	"github.com/opencord/voltha-bbsim/common/logger"
 	openolt "github.com/opencord/voltha-protos/go/openolt"
+	techprofile "github.com/opencord/voltha-protos/go/tech_profile"
 	log "github.com/sirupsen/logrus"
 )
 
 // Constants for the ONU states
 const (
-	ONU_INACTIVE DeviceState = iota // TODO: Each stage name should be more accurate
-	ONU_ACTIVE
-	ONU_OMCIACTIVE
-	ONU_AUTHENTICATED
-	ONU_LOS_RAISED
-	ONU_OMCI_CHANNEL_LOS_RAISED
-	ONU_LOS_ON_OLT_PON_LOS // TODO give more suitable and crisp name
-	ONU_FREE
+	OnuFree State = iota // TODO: Each stage name should be more accurate
+	OnuInactive
+	OnuLosRaised
+	OnuLosOnOltPonLos
+	OnuOmciChannelLosRaised
+	OnuActive
+	OnuOmciActive
+	OnuAuthenticated
 )
 
 // ONUState maps int value of device state to string
-var ONUState = map[DeviceState]string{
-	ONU_INACTIVE:                "ONU_INACTIVE",
-	ONU_ACTIVE:                  "ONU_ACTIVE",
-	ONU_OMCIACTIVE:              "ONU_OMCIACTIVE",
-	ONU_AUTHENTICATED:           "ONU_AUTHENTICATED",
-	ONU_LOS_RAISED:              "ONU_LOS_RAISED",
-	ONU_OMCI_CHANNEL_LOS_RAISED: "ONU_OMCI_CHANNEL_LOS_RAISED",
-	ONU_LOS_ON_OLT_PON_LOS:      "ONU_LOS_ON_OLT_PON_LOS",
-	ONU_FREE:                    "ONU_FREE",
+var ONUState = map[State]string{
+	OnuFree:                 "ONU_FREE",
+	OnuInactive:             "ONU_INACTIVE",
+	OnuLosRaised:            "ONU_LOS_RAISED",
+	OnuLosOnOltPonLos:       "ONU_LOS_ON_OLT_PON_LOS",
+	OnuOmciChannelLosRaised: "ONU_OMCI_CHANNEL_LOS_RAISED",
+	OnuActive:               "ONU_ACTIVE",
+	OnuOmciActive:           "ONU_OMCIACTIVE",
+	OnuAuthenticated:        "ONU_AUTHENTICATED",
+}
+
+// FlowKey used for FlowMap key
+type FlowKey struct {
+	FlowID        uint32
+	FlowDirection string
 }
 
 // Onu structure stores information of ONUs
 type Onu struct {
-	InternalState DeviceState
+	InternalState State
 	OltID         uint32
 	IntfID        uint32
 	OperState     string
 	SerialNumber  *openolt.SerialNumber
 	OnuID         uint32
-	GemportID     uint16
-	FlowIDs       []uint32
+	GemPortMap    map[uint32][]uint32 // alloc-id is used as key and corresponding gem-ports are stored in slice
+	Tconts        *techprofile.TrafficSchedulers
+	Flows         []FlowKey
 	mu            *sync.Mutex
 }
 
@@ -69,11 +77,11 @@
 }
 
 // NewOnus initializes and returns slice of Onu objects
-func NewOnus(oltid uint32, intfid uint32, nonus uint32, nnni uint32) []*Onu {
-	onus := []*Onu{}
+func NewOnus(oltid uint32, intfid uint32, nonus uint32) []*Onu {
+	var onus []*Onu
 	for i := 1; i <= int(nonus); i++ {
 		onu := Onu{}
-		onu.InternalState = ONU_FREE // New Onu Initialised with state ONU_FREE
+		onu.InternalState = OnuFree // New Onu Initialised with state ONU_FREE
 		onu.mu = &sync.Mutex{}
 		onu.IntfID = intfid
 		onu.OltID = oltid
@@ -81,7 +89,7 @@
 		onu.SerialNumber = new(openolt.SerialNumber)
 		onu.SerialNumber.VendorId = []byte("BBSM")
 		onu.SerialNumber.VendorSpecific = NewSN(oltid, intfid, uint32(i))
-		onu.GemportID = 0
+		onu.GemPortMap = make(map[uint32][]uint32)
 		onus = append(onus, &onu)
 	}
 	return onus
@@ -90,19 +98,7 @@
 // Initialize method initializes ONU state to up and ONU_INACTIVE
 func (onu *Onu) Initialize() {
 	onu.OperState = "up"
-	onu.InternalState = ONU_INACTIVE
-}
-
-// ValidateONU method validate ONU based on the serial number in onuMap
-func ValidateONU(targetonu openolt.Onu, regonus map[uint32][]*Onu) bool {
-	for _, onus := range regonus {
-		for _, onu := range onus {
-			if ValidateSN(*targetonu.SerialNumber, *onu.SerialNumber) {
-				return true
-			}
-		}
-	}
-	return false
+	onu.InternalState = OnuInactive
 }
 
 // ValidateSN compares two serial numbers and returns result as true/false
@@ -120,7 +116,7 @@
 }
 
 // UpdateIntState method updates ONU internal state
-func (onu *Onu) UpdateIntState(intstate DeviceState) {
+func (onu *Onu) UpdateIntState(intstate State) {
 	onu.mu.Lock()
 	defer onu.mu.Unlock()
 	onu.InternalState = intstate
@@ -132,21 +128,21 @@
 }
 
 // GetIntState returns ONU internal state
-func (onu *Onu) GetIntState() DeviceState {
+func (onu *Onu) GetIntState() State {
 	onu.mu.Lock()
 	defer onu.mu.Unlock()
 	return onu.InternalState
 }
 
-// DeleteFlowID method search and delete flowID from the onu flowIDs slice
-func (onu *Onu) DeleteFlowID(flowID uint32) {
-	for pos, id := range onu.FlowIDs {
-		if id == flowID {
-			// delete the flowID by shifting all flowIDs by one
-			onu.FlowIDs = append(onu.FlowIDs[:pos], onu.FlowIDs[pos+1:]...)
-			t := make([]uint32, len(onu.FlowIDs))
-			copy(t, onu.FlowIDs)
-			onu.FlowIDs = t
+// DeleteFlow method search and delete flowKey from the onu flows slice
+func (onu *Onu) DeleteFlow(key FlowKey) {
+	for pos, flowKey := range onu.Flows {
+		if flowKey == key {
+			// delete the flowKey by shifting all flowKeys by one
+			onu.Flows = append(onu.Flows[:pos], onu.Flows[pos+1:]...)
+			t := make([]FlowKey, len(onu.Flows))
+			copy(t, onu.Flows)
+			onu.Flows = t
 			break
 		}
 	}
diff --git a/device/utils.go b/device/utils.go
index 7e0eca3..2d4cc28 100644
--- a/device/utils.go
+++ b/device/utils.go
@@ -17,19 +17,17 @@
 package device
 
 import (
-	"fmt"
-
 	"github.com/opencord/voltha-bbsim/common/logger"
 	log "github.com/sirupsen/logrus"
 	"strconv"
 )
 
+// OnuToSn returns serial number in string format for given ONU
 func OnuToSn(onu *Onu) string {
-	// FIXME
-	// see https://github.com/opencord/voltha/blob/master/voltha/adapters/openolt/openolt_device.py#L929-L943
-	return string(onu.SerialNumber.VendorId) + "00000" + fmt.Sprint(onu.IntfID) + "0" + fmt.Sprintf("%x", onu.OnuID-1)
+	return string(onu.SerialNumber.VendorId) + ConvB2S(onu.SerialNumber.VendorSpecific)
 }
 
+// LoggerWithOnu method logs ONU fields
 func LoggerWithOnu(onu *Onu) *log.Entry {
 
 	if onu == nil {
@@ -39,12 +37,13 @@
 
 	return logger.GetLogger().WithFields(log.Fields{
 		"serial_number": OnuToSn(onu),
-		"interfaceId":   onu.IntfID,
-		"onuId":         onu.OnuID,
-		"oltId":         onu.OltID,
+		"interfaceID":   onu.IntfID,
+		"onuID":         onu.OnuID,
+		"oltID":         onu.OltID,
 	})
 }
 
+// ConvB2S converts byte array to string
 func ConvB2S(b []byte) string {
 	s := ""
 	for _, i := range b {
diff --git a/flow/flow.go b/flow/flow.go
index f1d6e10..7e47db9 100644
--- a/flow/flow.go
+++ b/flow/flow.go
@@ -17,20 +17,28 @@
 package flow
 
 import (
+	"math/rand"
+	"time"
+
+	"github.com/google/gopacket"
 	"github.com/opencord/voltha-bbsim/common/logger"
+	"github.com/opencord/voltha-bbsim/device"
 	openolt "github.com/opencord/voltha-protos/go/openolt"
 	log "github.com/sirupsen/logrus"
 )
 
-var flowManager FlowManager
+var flowManager Manager
 
-// FlowManager interface for common methods of controller
-type FlowManager interface {
+// Manager interface for common methods of controller
+type Manager interface {
 	AddFlow(flow *openolt.Flow) error
 	DeleteFlow(flow *openolt.Flow) error
+	DeleteAllFlows() error
 	PortUp(portID uint32) error
 	PortDown(portID uint32) error
 	GetFlow(onuID uint32) ([]*openolt.Flow, error)
+	InitializePacketInStream(s openolt.Openolt_EnableIndicationServer)
+	PacketOut(packet gopacket.Packet, s string, u uint32) error
 }
 
 // DefaultFlowController empty struct
@@ -45,6 +53,11 @@
 	return
 }
 
+// InitializePacketInStream initializes the stream to send packets towards VOLTHA
+func InitializePacketInStream(s openolt.Openolt_EnableIndicationServer) {
+	flowManager.InitializePacketInStream(s)
+}
+
 // AddFlow abstracts actual implementation of flow addition
 func AddFlow(flow *openolt.Flow) error {
 	return flowManager.AddFlow(flow)
@@ -55,6 +68,11 @@
 	return flowManager.DeleteFlow(flow)
 }
 
+// DeleteAllFlows abstracts actual implementation of flow deletion
+func DeleteAllFlows() error {
+	return flowManager.DeleteAllFlows()
+}
+
 // PortUp abstracts actual implementation of port up
 func PortUp(portID uint32) error {
 	return flowManager.PortUp(portID)
@@ -65,8 +83,43 @@
 	return flowManager.PortDown(portID)
 }
 
+// PacketOut abstracts actual implementation of sending packet out
+func PacketOut(packet gopacket.Packet, intfType string, intfID uint32) error {
+	return flowManager.PacketOut(packet, intfType, intfID)
+}
+
+// GetPortStats return stats for specified interface
+func GetPortStats(portStats *device.PortStats) *openolt.PortStatistics {
+
+	// increment current packet count by random number
+	pkts := portStats.Packets + uint64((rand.Intn(50)+1)*10)
+	portStats.Packets = pkts
+	logger.Info("Packet count %d", portStats.Packets)
+
+	// fill all other stats based on packet count
+	nextPortStats := &openolt.PortStatistics{
+		RxBytes:        pkts * 64,
+		RxPackets:      pkts,
+		RxUcastPackets: pkts * 40 / 100,
+		RxMcastPackets: pkts * 30 / 100,
+		RxBcastPackets: pkts * 30 / 100,
+		RxErrorPackets: 0,
+		TxBytes:        pkts * 64,
+		TxPackets:      pkts,
+		TxUcastPackets: pkts * 40 / 100,
+		TxMcastPackets: pkts * 30 / 100,
+		TxBcastPackets: pkts * 30 / 100,
+		TxErrorPackets: 0,
+		RxCrcErrors:    0,
+		BipErrors:      0,
+		Timestamp:      uint32(time.Now().Unix()),
+	}
+
+	return nextPortStats
+}
+
 // InitializeDefaultFlowController method to initialize default controller
-func InitializeDefaultFlowController() FlowManager {
+func InitializeDefaultFlowController() Manager {
 	logger.Debug("Default controller initialized")
 	return new(DefaultFlowController)
 }
@@ -90,6 +143,12 @@
 	return nil
 }
 
+// DeleteAllFlows implemented for DefaultFlowController
+func (fc *DefaultFlowController) DeleteAllFlows() error {
+	logger.Debug("DeleteAllFlows invoked")
+	return nil
+}
+
 // GetFlow implemented for DefaultFlowController
 func (fc *DefaultFlowController) GetFlow(onuID uint32) ([]*openolt.Flow, error) {
 	return nil, nil
@@ -106,3 +165,14 @@
 	logger.Debug("PortDown invoked %d", portID)
 	return nil
 }
+
+// InitializePacketInStream implemented for DefaultFlowController
+func (fc *DefaultFlowController) InitializePacketInStream(s openolt.Openolt_EnableIndicationServer) {
+	logger.Debug("Initialize Openolt stream")
+}
+
+// PacketOut implemented for DefaultFlowController
+func (fc *DefaultFlowController) PacketOut(pkt gopacket.Packet, intfType string, intfID uint32) error {
+	logger.Debug("PacketOut invoked intfType: %s, intfID: %d", intfType, intfID)
+	return nil
+}