diff --git a/adaptercore/openolt_flowmgr.go b/adaptercore/openolt_flowmgr.go
new file mode 100644
index 0000000..8d90fd8
--- /dev/null
+++ b/adaptercore/openolt_flowmgr.go
@@ -0,0 +1,749 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package adaptercore
+
+import (
+	"context"
+	"crypto/md5"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"math/big"
+
+	rsrcMgr "github.com/opencord/voltha-go/adapters/openolt/adaptercore/resourcemanager"
+	"github.com/opencord/voltha-go/common/log"
+	tp "github.com/opencord/voltha-go/common/techprofile"
+	fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
+	ofp "github.com/opencord/voltha-protos/go/openflow_13"
+	openolt_pb2 "github.com/opencord/voltha-protos/go/openolt"
+	voltha "github.com/opencord/voltha-protos/go/voltha"
+)
+
+const (
+	// Flow categories
+	HSIA_FLOW  = "HSIA_FLOW"
+	EAPOL_FLOW = "EAPOL_FLOW"
+
+	IP_PROTO_DHCP = 17
+
+	IP_PROTO_IGMP = 2
+
+	EAP_ETH_TYPE  = 0x888e
+	LLDP_ETH_TYPE = 0x88cc
+
+	IGMP_PROTO = 2
+
+	//FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
+	DEFAULT_MGMT_VLAN = 4091
+
+	DEFAULT_NETWORK_INTERFACE_ID = 0
+
+	// Openolt Flow
+	UPSTREAM        = "upstream"
+	DOWNSTREAM      = "downstream"
+	PACKET_TAG_TYPE = "pkt_tag_type"
+	UNTAGGED        = "untagged"
+	SINGLE_TAG      = "single_tag"
+	DOUBLE_TAG      = "double_tag"
+
+	// classifierInfo
+	ETH_TYPE = "eth_type"
+	TPID     = "tpid"
+	IP_PROTO = "ip_proto"
+	IN_PORT  = "in_port"
+	VLAN_VID = "vlan_vid"
+	VLAN_PCP = "vlan_pcp"
+	UDP_DST  = "udp_dst"
+	UDP_SRC  = "udp_src"
+	IPV4_DST = "ipv4_dst"
+	IPV4_SRC = "ipv4_src"
+	METADATA = "metadata"
+	OUTPUT   = "output"
+	// Action
+	POP_VLAN     = "pop_vlan"
+	PUSH_VLAN    = "push_vlan"
+	TRAP_TO_HOST = "trap_to_host"
+)
+
+type OpenOltFlowMgr struct {
+	techprofile   []*tp.TechProfileMgr
+	deviceHandler *DeviceHandler
+	resourceMgr   *rsrcMgr.OpenOltResourceMgr
+}
+
+func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
+	log.Info("Initializing flow manager")
+	var flowMgr OpenOltFlowMgr
+	flowMgr.deviceHandler = dh
+	flowMgr.resourceMgr = rsrcMgr
+	if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
+		log.Error("Error while populating tech profile mgr\n")
+		return nil
+	}
+	log.Info("Initialization of  flow manager success!!")
+	return &flowMgr
+}
+
+func (f *OpenOltFlowMgr) divideAndAddFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
+	var allocId []uint32
+	var gemPorts []uint32
+
+	log.Infow("Dividing flow", log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "portNo": portNo, "classifier": classifierInfo, "action": actionInfo})
+
+	log.Infow("sorting flow", log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "portNo": portNo,
+		"classifierInfo": classifierInfo, "actionInfo": actionInfo})
+
+	uni := getUniPortPath(intfId, onuId, uniId)
+	log.Debugw("Uni port name", log.Fields{"uni": uni})
+	allocId, gemPorts = f.createTcontGemports(intfId, onuId, uniId, uni, portNo, flow.GetTableId())
+	if allocId == nil || gemPorts == nil {
+		log.Error("alloc-id-gem-ports-unavailable")
+		return
+	}
+
+	/* Flows can't be added specific to gemport unless p-bits are received.
+	 * Hence adding flows for all gemports
+	 */
+	for _, gemPort := range gemPorts {
+		if ipProto, ok := classifierInfo[IP_PROTO]; ok {
+			if ipProto.(uint32) == IP_PROTO_DHCP {
+				log.Info("Adding DHCP flow")
+				f.addDHCPTrapFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
+			} else if ipProto == IP_PROTO_IGMP {
+				log.Info("igmp flow add ignored, not implemented yet")
+			} else {
+				log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
+				//return errors.New("Invalid-Classifier-to-handle")
+			}
+		} else if ethType, ok := classifierInfo[ETH_TYPE]; ok {
+			if ethType.(uint32) == EAP_ETH_TYPE {
+				log.Info("Adding EAPOL flow")
+				f.addEAPOLFlow(intfId, onuId, uniId, portNo, flow, allocId[0], gemPort, DEFAULT_MGMT_VLAN)
+				if vlan := getSubscriberVlan(fd.GetInPort(flow)); vlan != 0 {
+					f.addEAPOLFlow(intfId, onuId, uniId, portNo, flow, allocId[0], gemPort, vlan)
+				}
+				// Send Techprofile download event to child device in go routine as it takes time
+				go f.sendTPDownloadMsgToChild(intfId, onuId, uniId, uni)
+			}
+			if ethType == LLDP_ETH_TYPE {
+				log.Info("Adding LLDP flow")
+				addLLDPFlow(flow, portNo)
+			}
+		} else if _, ok := actionInfo[PUSH_VLAN]; ok {
+			log.Info("Adding upstream data rule")
+			f.addUpstreamDataFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
+		} else if _, ok := actionInfo[POP_VLAN]; ok {
+			log.Info("Adding Downstream data rule")
+			f.addDownstreamDataFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
+		} else {
+			log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
+		}
+	}
+}
+
+// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
+func (f *OpenOltFlowMgr) createTcontGemports(intfId uint32, onuId uint32, uniId uint32, uni string, uniPort uint32, tableID uint32) ([]uint32, []uint32) {
+	var allocID []uint32
+	var gemPortIDs []uint32
+	//If we already have allocated earlier for this onu, render them
+	if tcontId := f.resourceMgr.GetCurrentAllocIDForOnu(intfId, onuId); tcontId != 0 {
+		allocID = append(allocID, tcontId)
+	}
+	gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfId, onuId, uniId)
+	if len(allocID) != 0 && len(gemPortIDs) != 0 {
+		log.Debug("Rendered Tcont and GEM ports from resource manager", log.Fields{"intfId": intfId, "onuId": onuId, "uniPort": uniId,
+			"allocID": allocID, "gemPortIDs": gemPortIDs})
+		return allocID, gemPortIDs
+	}
+	log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfId, "onu": onuId, "uni": uniId})
+
+	//FIXME: If table id is <= 63 using 64 as table id
+	if tableID < tp.DEFAULT_TECH_PROFILE_TABLE_ID {
+		tableID = tp.DEFAULT_TECH_PROFILE_TABLE_ID
+	}
+	tpPath := f.getTPpath(intfId, uni)
+	// Check tech profile instance already exists for derived port name
+	tech_profile_instance, err := f.techprofile[intfId].GetTPInstanceFromKVStore(tableID, tpPath)
+	if err != nil { // This should not happen, something wrong in KV backend transaction
+		log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tableID": tableID, "path": tpPath})
+		return nil, nil
+	}
+	if tech_profile_instance == nil {
+		log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
+		tech_profile_instance = f.techprofile[intfId].CreateTechProfInstance(tableID, uni, intfId)
+		if tech_profile_instance == nil {
+			log.Error("Tech-profile-instance-creation-failed")
+			return nil, nil
+		}
+	} else {
+		log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
+	}
+	// Get upstream and downstream scheduler protos
+	us_scheduler := f.techprofile[intfId].GetUsScheduler(tech_profile_instance)
+	ds_scheduler := f.techprofile[intfId].GetDsScheduler(tech_profile_instance)
+	// Get TCONTS protos
+	tconts := f.techprofile[intfId].GetTconts(tech_profile_instance, us_scheduler, ds_scheduler)
+	if len(tconts) == 0 {
+		log.Error("TCONTS not found ")
+		return nil, nil
+	}
+	log.Debugw("Sending Create tcont to device",
+		log.Fields{"onu": onuId, "uni": uniId, "portNo": "", "tconts": tconts})
+	if _, err := f.deviceHandler.Client.CreateTconts(context.Background(),
+		&openolt_pb2.Tconts{IntfId: intfId,
+			OnuId:  onuId,
+			UniId:  uniId,
+			PortNo: uniPort,
+			Tconts: tconts}); err != nil {
+		log.Error("Error while creating TCONT in device")
+		return nil, nil
+	}
+	allocID = append(allocID, tech_profile_instance.UsScheduler.AllocID)
+	for _, gem := range tech_profile_instance.UpstreamGemPortAttributeList {
+		gemPortIDs = append(gemPortIDs, gem.GemportID)
+	}
+	log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
+	// Send Tconts and GEM ports to KV store
+	f.storeTcontsGEMPortsIntoKVStore(intfId, onuId, uniId, allocID, gemPortIDs)
+	return allocID, gemPortIDs
+}
+
+func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfId uint32, onuId uint32, uniId uint32, allocID []uint32, gemPortIDs []uint32) {
+
+	log.Debugw("Storing allocated Tconts and GEM ports into KV store",
+		log.Fields{"intfId": intfId, "onuId": onuId, "uniId": uniId, "allocID": allocID, "gemPortIDs": gemPortIDs})
+	/* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store  */
+	if err := f.resourceMgr.UpdateAllocIdsForOnu(intfId, onuId, uniId, allocID); err != nil {
+		log.Error("Errow while uploading allocID to KV store")
+	}
+	if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfId, onuId, uniId, gemPortIDs); err != nil {
+		log.Error("Errow while uploading GEMports to KV store")
+	}
+	if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfId, onuId, uniId); err != nil {
+		log.Error("Errow while uploading gemtopon map to KV store")
+	}
+	log.Debug("Stored tconts and GEM into KV store successfully")
+}
+
+func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
+	for _, techRange := range f.resourceMgr.DevInfo.Ranges {
+		for intfId := range techRange.IntfIds {
+			f.techprofile = append(f.techprofile, f.resourceMgr.ResourceMgrs[uint32(intfId)].TechProfileMgr)
+		}
+	}
+	//Make sure we have as many tech_profiles as there are pon ports on the device
+	if len(f.techprofile) != int(f.resourceMgr.DevInfo.GetPonPorts()) {
+		log.Errorw("Error while populating techprofile",
+			log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
+		return errors.New("Error while populating techprofile mgrs")
+	}
+	log.Infow("Populated techprofile per ponport successfully",
+		log.Fields{"numofTech": len(f.techprofile), "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
+	return nil
+}
+
+func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfid uint32, onuid uint32, uniid uint32, portno uint32, classifier map[string]interface{}, action map[string]interface{}, logicalflow *ofp.OfpFlowStats, allocid uint32, gemportid uint32) {
+
+	log.Info("Unimplemented")
+
+	return
+
+}
+
+func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfid uint32, onuid uint32, uniid uint32, portno uint32, classifier map[string]interface{}, action map[string]interface{}, logicalflow *ofp.OfpFlowStats, allocid uint32, gemportid uint32) {
+
+	log.Info("Unimplemented")
+	return
+
+}
+
+func (f *OpenOltFlowMgr) addDHCPTrapFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) {
+	return
+}
+
+// Add EAPOL to  device
+func (f *OpenOltFlowMgr) addEAPOLFlow(intfId uint32, onuId uint32, uniId uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32) {
+	log.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfId, "onuId": onuId, "portNo": portNo, "allocId": allocId, "gemPortId": gemPortId, "vlanId": vlanId, "flow": logicalFlow})
+
+	uplinkClassifier := make(map[string]interface{})
+	uplinkAction := make(map[string]interface{})
+	downlinkClassifier := make(map[string]interface{})
+	downlinkAction := make(map[string]interface{})
+	var upstreamFlow openolt_pb2.Flow
+	var downstreamFlow openolt_pb2.Flow
+
+	// Fill Classfier
+	uplinkClassifier[ETH_TYPE] = uint32(EAP_ETH_TYPE)
+	uplinkClassifier[PACKET_TAG_TYPE] = SINGLE_TAG
+	uplinkClassifier[VLAN_VID] = vlanId
+	// Fill action
+	uplinkAction[TRAP_TO_HOST] = true
+	flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortId)
+	//Add Uplink EAPOL Flow
+	uplinkFlowId, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, "")
+	if err != nil {
+		log.Errorw("Error allocating flowID for UL EAPOL", log.Fields{"intfId": intfId, "onuId": onuId, "flowStoreCookie": flowStoreCookie})
+	}
+	var classifierProto *openolt_pb2.Classifier
+	var actionProto *openolt_pb2.Action
+	log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowId})
+
+	if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
+		log.Error("Error in making classifier protobuf for ul flow")
+		return
+	}
+	log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
+	if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
+		log.Error("Error in making action protobuf for ul flow")
+		return
+	}
+	log.Debugw("Created action proto", log.Fields{"action": *actionProto})
+	upstreamFlow = openolt_pb2.Flow{AccessIntfId: int32(intfId),
+		OnuId:         int32(onuId),
+		UniId:         int32(uniId),
+		FlowId:        uplinkFlowId,
+		FlowType:      UPSTREAM,
+		AllocId:       int32(allocId),
+		NetworkIntfId: DEFAULT_NETWORK_INTERFACE_ID, // one NNI port is supported now
+		GemportId:     int32(gemPortId),
+		Classifier:    classifierProto,
+		Action:        actionProto,
+		Priority:      int32(logicalFlow.Priority),
+		Cookie:        logicalFlow.Cookie,
+		PortNo:        portNo}
+	if ok := f.addFlowToDevice(&upstreamFlow); ok {
+		log.Debug("EAPOL UL flow added to device successfully")
+		flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, "EAPOL")
+		if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
+			upstreamFlow.OnuId,
+			upstreamFlow.UniId,
+			upstreamFlow.FlowId, flowsToKVStore); err != nil {
+			log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
+			return
+		}
+	}
+
+	if vlanId == DEFAULT_MGMT_VLAN {
+		/* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
+		# requirement)
+		# On one of the platforms (Broadcom BAL), when same DL classifier
+		# vlan was used across multiple ONUs, eapol flow re-adds after
+		# flow delete (cases of onu reboot/disable) fails.
+		# In order to generate unique vlan, a combination of intf_id
+		# onu_id and uniId is used.
+		# uniId defaults to 0, so add 1 to it.
+		*/
+		log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanId})
+		specialVlanDlFlow := 4090 - intfId*onuId*(uniId+1)
+		// Assert that we do not generate invalid vlans under no condition
+		if specialVlanDlFlow <= 2 {
+			log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
+			return
+		}
+		log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
+		// Fill Classfier
+		downlinkClassifier[PACKET_TAG_TYPE] = SINGLE_TAG
+		downlinkClassifier[VLAN_VID] = uint32(specialVlanDlFlow)
+		// Fill action
+		downlinkAction[PUSH_VLAN] = true
+		downlinkAction[VLAN_VID] = vlanId
+		flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortId)
+		downlinkFlowId, err := f.resourceMgr.GetFlowID(intfId, onuId, uniId, flowStoreCookie, "")
+		if err != nil {
+			log.Errorw("Error allocating flowID for DL EAPOL",
+				log.Fields{"intfId": intfId, "onuId": onuId, "flowStoreCookie": flowStoreCookie})
+			return
+		}
+		log.Debugw("Creating DL EAPOL flow",
+			log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowId})
+		if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
+			log.Error("Error in making classifier protobuf for downlink flow")
+			return
+		}
+		if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
+			log.Error("Error in making action protobuf for dl flow")
+			return
+		}
+		// Downstream flow in grpc protobuf
+		downstreamFlow = openolt_pb2.Flow{AccessIntfId: int32(intfId),
+			OnuId:         int32(onuId),
+			UniId:         int32(uniId),
+			FlowId:        downlinkFlowId,
+			FlowType:      DOWNSTREAM,
+			AllocId:       int32(allocId),
+			NetworkIntfId: DEFAULT_NETWORK_INTERFACE_ID,
+			GemportId:     int32(gemPortId),
+			Classifier:    classifierProto,
+			Action:        actionProto,
+			Priority:      int32(logicalFlow.Priority),
+			Cookie:        logicalFlow.Cookie,
+			PortNo:        portNo}
+		if ok := f.addFlowToDevice(&downstreamFlow); ok {
+			log.Debug("EAPOL DL flow added to device successfully")
+			flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, "")
+			if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
+				downstreamFlow.OnuId,
+				downstreamFlow.UniId,
+				downstreamFlow.FlowId, flowsToKVStore); err != nil {
+				log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
+				return
+			}
+		}
+	} else {
+		log.Infow("EAPOL flow with non-default mgmt vlan is not supported", log.Fields{"vlanId": vlanId})
+		return
+	}
+	log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
+}
+
+func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openolt_pb2.Classifier {
+	var classifier openolt_pb2.Classifier
+	if etherType, ok := classifierInfo[ETH_TYPE]; ok {
+		classifier.EthType = etherType.(uint32)
+	}
+	if ipProto, ok := classifierInfo[IP_PROTO]; ok {
+		classifier.IpProto = ipProto.(uint32)
+	}
+	if vlanId, ok := classifierInfo[VLAN_VID]; ok {
+		classifier.OVid = vlanId.(uint32)
+	}
+	if metadata, ok := classifierInfo[METADATA]; ok {
+		classifier.IVid = metadata.(uint32)
+	}
+	if vlanPcp, ok := classifierInfo[VLAN_PCP]; ok {
+		classifier.OPbits = vlanPcp.(uint32)
+	}
+	if udpSrc, ok := classifierInfo[UDP_SRC]; ok {
+		classifier.SrcPort = udpSrc.(uint32)
+	}
+	if udpDst, ok := classifierInfo[UDP_DST]; ok {
+		classifier.DstPort = udpDst.(uint32)
+	}
+	if ipv4Dst, ok := classifierInfo[IPV4_DST]; ok {
+		classifier.DstIp = ipv4Dst.(uint32)
+	}
+	if ipv4Src, ok := classifierInfo[IPV4_SRC]; ok {
+		classifier.SrcIp = ipv4Src.(uint32)
+	}
+	if pktTagType, ok := classifierInfo[PACKET_TAG_TYPE]; ok {
+		if pktTagType.(string) == SINGLE_TAG {
+			classifier.PktTagType = SINGLE_TAG
+		} else if pktTagType.(string) == DOUBLE_TAG {
+			classifier.PktTagType = DOUBLE_TAG
+		} else if pktTagType.(string) == UNTAGGED {
+			classifier.PktTagType = UNTAGGED
+		} else {
+			log.Error("Invalid tag type in classifier") // should not hit
+			return nil
+		}
+	}
+	return &classifier
+}
+
+func makeOpenOltActionField(actionInfo map[string]interface{}) *openolt_pb2.Action {
+	var actionCmd openolt_pb2.ActionCmd
+	var action openolt_pb2.Action
+	action.Cmd = &actionCmd
+	if _, ok := actionInfo[POP_VLAN]; ok {
+		action.OVid = actionInfo[VLAN_VID].(uint32)
+		action.Cmd.RemoveOuterTag = true
+	} else if _, ok := actionInfo[PUSH_VLAN]; ok {
+		action.OVid = actionInfo[VLAN_VID].(uint32)
+		action.Cmd.AddOuterTag = true
+	} else if _, ok := actionInfo[TRAP_TO_HOST]; ok {
+		action.Cmd.TrapToHost = actionInfo[TRAP_TO_HOST].(bool)
+	} else {
+		log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
+		return nil
+	}
+	return &action
+}
+
+func (f *OpenOltFlowMgr) getTPpath(intfId uint32, uni string) string {
+	/*
+	   FIXME
+	   Should get Table id form the flow, as of now hardcoded to DEFAULT_TECH_PROFILE_TABLE_ID (64)
+	   'tp_path' contains the suffix part of the tech_profile_instance path. The prefix to the 'tp_path' should be set to
+	   TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
+	*/
+	return f.techprofile[intfId].GetTechProfileInstanceKVPath(tp.DEFAULT_TECH_PROFILE_TABLE_ID, uni)
+}
+
+func getFlowStoreCookie(classifier map[string]interface{}, gemPortId uint32) uint64 {
+	if len(classifier) == 0 { // should never happen
+		log.Error("Invalid classfier object")
+		return 0
+	}
+	var jsonData []byte
+	var flowString string
+	var err error
+	// TODO: Do we need to marshall ??
+	if jsonData, err = json.Marshal(classifier); err != nil {
+		log.Error("Failed to encode classifier")
+		return 0
+	}
+	flowString = string(jsonData)
+	if gemPortId != 0 {
+		flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortId))
+	}
+	h := md5.New()
+	h.Write([]byte(flowString))
+	hash := big.NewInt(0)
+	hash.SetBytes(h.Sum(nil))
+	return hash.Uint64()
+}
+
+func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]openolt_pb2.Flow {
+	var flows []openolt_pb2.Flow
+	/* FIXME: To be removed and identify way to get same flow ID for HSIA DL and UL flows
+	   To get existing flow matching flow catogery or cookie
+	*/
+	/*flow.Category = flowCategory
+	  flow.FlowStoreCookie = flowStoreCookie*/
+	flows = append(flows, *flow)
+	// Get existing flow for flowid  from KV store
+	//existingFlows := f.resourceMgr.GetFlowIDInfo(uint32(flow.AccessIntfId),uint32(flow.OnuId),uint32(flow.UniId),flow.FlowId)
+	/*existingFlows := nil
+	  if existingFlows != nil{
+	      log.Debugw("Flow exists for given flowID, appending it",log.Fields{"flowID":flow.FlowId})
+	      for _,f := range *existingFlows{
+	          flows = append(flows,f)
+	      }
+	  }*/
+	log.Debugw("Updated flows for given flowID", log.Fields{"updatedflow": flows, "flowid": flow.FlowId})
+	return &flows
+}
+
+func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfId int32, onuId int32, uniId int32, flowId uint32, flows *[]openolt_pb2.Flow) error {
+	log.Debugw("Storing flow into KV store", log.Fields{"flows": *flows})
+	/* FIXME: To implement API in resource mgr and invoke */
+	/*if err := f.resourceMgr.UpdateFlowIDInfo(intfId,onuId,uniId,flowId,flows); err != nil{
+	      log.Debug("Error while Storing flow into KV store")
+	      return err
+	  }
+	  log.Info("Stored flow into KV store successfully!")
+	*/
+	return nil
+}
+
+func (f *OpenOltFlowMgr) addFlowToDevice(deviceFlow *openolt_pb2.Flow) bool {
+	log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
+	_, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
+	if err != nil {
+		log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
+		return false
+	}
+	log.Debugw("Flow added to device successfuly ", log.Fields{"flow": *deviceFlow})
+	return true
+}
+
+/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
+ //update core flows_proxy : flows_proxy.update('/', flows)
+}
+
+func generateStoredId(flowId uint32, direction string)uint32{
+
+	if direction == UPSTREAM{
+		log.Debug("Upstream flow shifting flowid")
+		return ((0x1 << 15) | flowId)
+	}else if direction == DOWNSTREAM{
+		log.Debug("Downstream flow not shifting flowid")
+		return flowId
+	}else{
+		log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
+		return flowId
+	}
+}
+
+*/
+
+func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
+	log.Info("Unimplemented")
+}
+func getUniPortPath(intfId uint32, onuId uint32, uniId uint32) string {
+	return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfId, onuId, uniId)
+}
+
+func (f *OpenOltFlowMgr) getOnuChildDevice(intfId uint32, onuId uint32) *voltha.Device {
+	parentPortNo := IntfIdToPortNo(intfId, voltha.Port_PON_OLT)
+	ChildDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuId)
+	if ChildDevice == nil {
+		log.Errorw("could-not-find-child-device", log.Fields{"parent_port_no": parentPortNo, "onuId": onuId})
+		return nil
+	}
+	return ChildDevice
+}
+
+func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
+	log.Info("Unimplemented")
+	return nil
+}
+
+func getSubscriberVlan(inPort uint32) uint32 {
+	/* For EAPOL case we will use default VLAN , so will implement later if required */
+	log.Info("Unimplemented")
+	return 0
+}
+
+func (f *OpenOltFlowMgr) clear_flows_and_scheduler_for_logical_port(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
+	log.Info("Unimplemented")
+}
+
+func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats) {
+	classifierInfo := make(map[string]interface{}, 0)
+	actionInfo := make(map[string]interface{}, 0)
+	log.Debug("Adding Flow", log.Fields{"flow": flow})
+	for _, field := range fd.GetOfbFields(flow) {
+		if field.Type == fd.ETH_TYPE {
+			classifierInfo[ETH_TYPE] = field.GetEthType()
+			log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[ETH_TYPE].(uint32)})
+		} else if field.Type == fd.IP_PROTO {
+			classifierInfo[IP_PROTO] = field.GetIpProto()
+			log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IP_PROTO].(uint32)})
+		} else if field.Type == fd.IN_PORT {
+			classifierInfo[IN_PORT] = field.GetPort()
+			log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[IN_PORT].(uint32)})
+		} else if field.Type == fd.VLAN_VID {
+			classifierInfo[VLAN_VID] = field.GetVlanVid()
+			log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VLAN_VID].(uint32)})
+		} else if field.Type == fd.VLAN_PCP {
+			classifierInfo[VLAN_PCP] = field.GetVlanPcp()
+			log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VLAN_PCP].(uint32)})
+		} else if field.Type == fd.UDP_DST {
+			classifierInfo[UDP_DST] = field.GetUdpDst()
+			log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDP_DST].(uint32)})
+		} else if field.Type == fd.UDP_SRC {
+			classifierInfo[UDP_SRC] = field.GetUdpSrc()
+			log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDP_SRC].(uint32)})
+		} else if field.Type == fd.IPV4_DST {
+			classifierInfo[IPV4_DST] = field.GetIpv4Dst()
+			log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[IPV4_DST].(uint32)})
+		} else if field.Type == fd.IPV4_SRC {
+			classifierInfo[IPV4_SRC] = field.GetIpv4Src()
+			log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[IPV4_SRC].(uint32)})
+		} else if field.Type == fd.METADATA {
+			classifierInfo[METADATA] = field.GetTableMetadata()
+			log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
+		} else {
+			log.Errorw("Un supported field type", log.Fields{"type": field.Type})
+			return
+		}
+	}
+	for _, action := range fd.GetActions(flow) {
+		if action.Type == fd.OUTPUT {
+			if out := action.GetOutput(); out != nil {
+				actionInfo[OUTPUT] = out.GetPort()
+				log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
+			} else {
+				log.Error("Invalid output port in action")
+				return
+			}
+		} else if action.Type == fd.POP_VLAN {
+			if gotoTable := fd.GetGotoTableId(flow); gotoTable == 0 {
+				log.Infow("action-type-pop-vlan, being taken care of by ONU", log.Fields{"flow": flow})
+				actionInfo[POP_VLAN] = false
+				return
+			}
+			actionInfo[POP_VLAN] = true
+			log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[IN_PORT].(uint32)})
+		} else if action.Type == fd.PUSH_VLAN {
+			if out := action.GetPush(); out != nil {
+				if tpid := out.GetEthertype(); tpid != 0x8100 {
+					log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PUSH_VLAN].(int32)})
+				} else {
+					actionInfo[PUSH_VLAN] = true
+					actionInfo[TPID] = tpid
+					log.Debugw("action-type-push-vlan",
+						log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[IN_PORT].(uint32)})
+				}
+			}
+		} else if action.Type == fd.SET_FIELD {
+			if out := action.GetSetField(); out != nil {
+				if field := out.GetField(); field != nil {
+					if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
+						log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
+						return
+					}
+					/*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
+					if ofbField := field.GetOfbField(); ofbField != nil {
+						if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
+							if vlan := ofbField.GetVlanVid(); vlan != 0 {
+								actionInfo[VLAN_VID] = vlan & 0xfff
+								log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VLAN_VID].(uint32)})
+							} else {
+								log.Error("No Invalid vlan id in set vlan-vid action")
+							}
+						} else {
+							log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
+						}
+					}
+				}
+			}
+		} else {
+			log.Errorw("Un supported action type", log.Fields{"type": action.Type})
+			return
+		}
+	}
+	if gotoTable := fd.GetGotoTableId(flow); gotoTable != 0 {
+		if actionInfo[POP_VLAN] == nil {
+			log.Infow("Go to table - action-type-pop-vlan, being taken care of by ONU", log.Fields{"flow": flow})
+			return
+		}
+	}
+	/* NOTE: This condition will be true when core decompose and provides flows to respective devices separately */
+	if _, ok := actionInfo[OUTPUT]; ok == false {
+		log.Debug("action-go-to-table, get next flow for outport details")
+		if _, ok := classifierInfo[METADATA]; ok {
+			if next_flow := findNextFlow(flow); next_flow == nil {
+				log.Debugw("No next flow found ", log.Fields{"classifier": classifierInfo, "flow": flow})
+				return
+			} else {
+				actionInfo[OUTPUT] = fd.GetOutPort(next_flow)
+				log.Debugw("action-next-flow-outport", log.Fields{"actionInfo[OUTPUT]": actionInfo[OUTPUT].(uint32)})
+				for _, field := range fd.GetOfbFields(next_flow) {
+					if field.Type == fd.VLAN_VID {
+						classifierInfo[METADATA] = field.GetVlanVid() & 0xfff
+						log.Debugw("next-flow-classifier-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
+					}
+				}
+			}
+		}
+	}
+	log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[IN_PORT], "action_output": actionInfo[OUTPUT]})
+	portNo, intfId, onuId, uniId := ExtractAccessFromFlow(classifierInfo[IN_PORT].(uint32), actionInfo[OUTPUT].(uint32))
+	f.divideAndAddFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow)
+}
+
+func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfId uint32, onuId uint32, uniId uint32, uni string) bool {
+
+	onuDevice := f.getOnuChildDevice(intfId, onuId)
+	if onuDevice == nil {
+		log.Error("Error while fetching Child device from core", log.Fields{"onuId": onuId})
+		return false
+	}
+	log.Debugw("Retrived child device from OLT device handler", log.Fields{"device": *onuDevice})
+	tpPath := f.getTPpath(intfId, uni)
+	log.Infow("Load-tech-profile-request-to-brcm-handler", log.Fields{"path": tpPath})
+	/* TODO : "Send Event message to ONU device via proxy to download tech profile in go routine
+	            msg = {'proxy_address': onuDevice.proxyAddress, 'uniId': uniId,
+			  'event': 'download_tech_profile', 'event_data': tp_path}
+		    //Send the event message to the ONU adapter
+	            self.adapter_agent.publish_inter_adapter_message(onu_device.id,msg)
+	*/
+	return true
+
+}
