diff --git a/internal/pkg/application/vnets.go b/internal/pkg/application/vnets.go
new file mode 100644
index 0000000..cf2d1fc
--- /dev/null
+++ b/internal/pkg/application/vnets.go
@@ -0,0 +1,3138 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package application
+
+import (
+	"encoding/json"
+	"errors"
+	"net"
+	infraerrorCodes "voltha-go-controller/internal/pkg/errorcodes"
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/google/gopacket"
+	"github.com/google/gopacket/layers"
+	"go.uber.org/atomic"
+
+	"voltha-go-controller/internal/pkg/controller"
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/database"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	errorCodes "voltha-go-controller/internal/pkg/errorcodes"
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+)
+
+const (
+	// ICMPv6ArpGroupID constant
+	ICMPv6ArpGroupID uint32 = 1
+
+	// Radisys vendor id constant
+	Radisys string = "Radisys"
+)
+
+var (
+	//BroadcastMAC - Broadcast MAC Address
+	BroadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
+)
+
+// NonZeroMacAddress utility to identify if the MAC address is non-zero.
+// We use zero MAC address as an unset MAC address
+func NonZeroMacAddress(h net.HardwareAddr) bool {
+	for i := 0; i < 6; i++ {
+		if h[i] != 0 {
+			return true
+		}
+	}
+	return false
+}
+
+// VNET package manages the different virtual networks that are part of the
+// the network. In the case of VOLT, the networks can be single tagged or
+// double tagged networks. In addition, the networks may be used for unicast
+// and multicast traffic. The unicast traffic further has two models, the
+// 1:1 and N:1 model. In case of a 1:1 model, the outer tag is same for many
+// subscribers and the inner tag is unique to each subscriber for the same
+// outer tag. The N:1 uses the same inner and outer tags, or for that matter
+// a single tag that can also be shared by subscribers. The VNET implementation
+// manages all these possibilities and the associated configuration.
+
+const (
+	// PbitMatchNone constant
+	PbitMatchNone of.PbitType = 8
+	// PbitMatchAll constant
+	PbitMatchAll of.PbitType = 0xFF
+)
+
+// SVlan        - Value of the outer tag if double tagged or the only tag if single
+//                tagged
+// SVlanTpid    - SVlan Tag Protocol Identifier
+// CVlan        - Value of the inner tag. Set to VlanNone if single tagged
+// DhcpRelay    - Set to true if the DHCP relay is enabled on the virtual network
+// MacLearning  - Set to true if the flows should include MAC address
+// UsDhcpPbit   - The pbit used for US DHCP packets
+// DsDhcpPbit   - The pbit used for DS DHCP packets
+
+// VnetConfig structure
+type VnetConfig struct {
+	Name                       string
+	SVlan                      of.VlanType
+	CVlan                      of.VlanType
+	UniVlan                    of.VlanType
+	SVlanTpid                  layers.EthernetType
+	DhcpRelay                  bool
+	ArpLearning                bool
+	MacLearning                MacLearningType
+	PppoeIa                    bool
+	ONTEtherTypeClassification int
+	VlanControl                VlanControl
+	Encapsulation              string
+	UsDhcpPbit                 []of.PbitType
+	DsDhcpPbit                 []of.PbitType
+	UsIGMPPbit                 []of.PbitType
+	DsIGMPPbit                 []of.PbitType
+	DevicesList                []string //List of serial number of devices on which this vnet is applied
+	AllowTransparent           bool
+	CtrlPktPbitRemark          map[of.PbitType]of.PbitType
+}
+
+// VnetOper structure
+type VnetOper struct {
+	PendingDeleteFlow     map[string]map[string]bool
+	DeleteInProgress      bool
+	PendingDeviceToDelete string
+	VnetLock              sync.RWMutex    `json:"-"`
+	VnetPortLock          sync.RWMutex    `json:"-"`
+	AssociatedPorts       map[string]bool `json:"-"`
+}
+
+// VoltVnet sructure
+type VoltVnet struct {
+	VnetConfig
+	VnetOper
+	Version string
+}
+
+const (
+	// EncapsulationPPPoEIA constant
+	EncapsulationPPPoEIA string = "PPPoE-IA"
+	// EncapsulationPPPoE constant
+	EncapsulationPPPoE string = "PPPoE"
+	// EncapsulationIPoE constant
+	EncapsulationIPoE string = "IPoE"
+)
+
+// NewVoltVnet is constructor for the VNET structure
+func NewVoltVnet(cfg VnetConfig) *VoltVnet {
+	var vv VoltVnet
+	vv.VnetConfig = cfg
+	if vv.PendingDeleteFlow == nil {
+		vv.PendingDeleteFlow = make(map[string]map[string]bool)
+	}
+	vv.DeleteInProgress = false
+	if cfg.Encapsulation == EncapsulationPPPoEIA {
+		vv.PppoeIa = true
+	}
+	vv.AssociatedPorts = make(map[string]bool)
+	return &vv
+}
+
+//associatePortToVnet - associate a port to Vnet
+func (vv *VoltVnet) associatePortToVnet(port string) {
+	vv.VnetPortLock.Lock()
+	if vv.AssociatedPorts == nil {
+		vv.AssociatedPorts = make(map[string]bool)
+	}
+	vv.AssociatedPorts[port] = true
+	vv.VnetPortLock.Unlock()
+}
+
+//disassociatePortFromVnet - disassociate a port from Vnet and return true if the association map is empty
+func (vv *VoltVnet) disassociatePortFromVnet(device string, port string) {
+	vv.VnetPortLock.Lock()
+	delete(vv.AssociatedPorts, port)
+	logger.Infow(ctx, "Disassociated Port from Vnet", log.Fields{"Device": device, "Port": port, "Vnet": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow, "AssociatedPorts": vv.AssociatedPorts, "DeleteFlag": vv.DeleteInProgress})
+	vv.VnetPortLock.Unlock()
+
+	if vv.DeleteInProgress {
+		if !vv.isAssociatedPortsPresent() {
+			if len(vv.PendingDeleteFlow[device]) == 0 {
+				logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vv.Name})
+				GetApplication().deleteVnetConfig(vv)
+				_ = db.DelVnet(vv.Name)
+			} else {
+				logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow})
+			}
+		} else {
+			vv.VnetPortLock.RLock()
+			logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts})
+			vv.VnetPortLock.RUnlock()
+		}
+	}
+}
+
+func (vv *VoltVnet) isAssociatedPortsPresent() bool {
+	vv.VnetPortLock.RLock()
+	defer vv.VnetPortLock.RUnlock()
+	return len(vv.AssociatedPorts) != 0
+}
+
+// WriteToDb commit the VNET to the database
+func (vv *VoltVnet) WriteToDb() {
+
+	if vv.DeleteInProgress {
+		logger.Warnw(ctx, "Skipping Redis Update for Vnet, Vnet delete in progress", log.Fields{"Vnet": vv.Name})
+		return
+	}
+	vv.ForceWriteToDb()
+}
+
+//ForceWriteToDb force commit a vnet to the DB
+func (vv *VoltVnet) ForceWriteToDb() {
+	vv.VnetPortLock.RLock()
+	defer vv.VnetPortLock.RUnlock()
+	vv.Version = database.PresentVersionMap[database.VnetPath]
+	logger.Debugw(ctx, "Updating VNET....", log.Fields{"vnet": vv})
+	if b, err := json.Marshal(vv); err == nil {
+		if err:= db.PutVnet(vv.Name, string(b)); err != nil {
+			logger.Warnw(ctx, "Add Vnet to DB failed", log.Fields{"vnet name": vv.Name, "Error": err})
+		}
+	}
+}
+
+// VnetKey creates the key using the two VLAN tags
+// We append the two VLAN tags to create a single key
+func VnetKey(otag of.VlanType, itag of.VlanType, utag of.VlanType) string {
+	return strconv.Itoa(int(otag)) + "-" + strconv.Itoa(int(itag)) + "-" + strconv.Itoa(int(utag))
+}
+
+// GetVnet get VNET configuration related functionality associated with VOLT application
+func (va *VoltApplication) GetVnet(otag of.VlanType, itag of.VlanType, utag of.VlanType) *VoltVnet {
+	// When matching VNET, it is expected to match first just the outer
+	// tag, and then the combination to make sure there is no conflict
+	// for the new configuration.
+	if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, of.VlanNone, utag)); ok {
+		return vnet.(*VoltVnet)
+	}
+	if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, itag, utag)); ok {
+		return vnet.(*VoltVnet)
+	}
+	return nil
+}
+
+// The VNET may also be assigned name for easier references. For now,
+// the VNET is mainly identified by the two VLANs.
+
+// GetVnetByName to get vnet by name
+func (va *VoltApplication) GetVnetByName(name string) *VoltVnet {
+	if vnet, ok := va.VnetsByName.Load(name); ok {
+		return vnet.(*VoltVnet)
+	}
+	return nil
+}
+
+// storeVnetConfig to store vnet config
+func (va *VoltApplication) storeVnetConfig(cfg VnetConfig, vv *VoltVnet) {
+
+	var vnetMap *util.ConcurrentMap
+
+	va.VnetsByTag.Store(VnetKey(cfg.SVlan, cfg.CVlan, cfg.UniVlan), vv)
+	va.VnetsByName.Store(cfg.Name, vv)
+
+	if vnetMapIntf, ok := va.VnetsBySvlan.Get(vv.SVlan); !ok {
+		vnetMap = util.NewConcurrentMap()
+	} else {
+		vnetMap = vnetMapIntf.(*util.ConcurrentMap)
+	}
+	vnetMap.Set(vv, true)
+	va.VnetsBySvlan.Set(vv.SVlan, vnetMap)
+}
+
+// deleteVnetConfig to delete vnet config
+func (va *VoltApplication) deleteVnetConfig(vnet *VoltVnet) {
+	va.VnetsByTag.Delete(VnetKey(vnet.SVlan, vnet.CVlan, vnet.UniVlan))
+	va.VnetsByName.Delete(vnet.Name)
+
+	if vnetMapIntf, ok := va.VnetsBySvlan.Get(vnet.SVlan); ok {
+		vnetMap := vnetMapIntf.(*util.ConcurrentMap)
+		vnetMap.Remove(vnet)
+		va.VnetsBySvlan.Set(vnet.SVlan, vnetMap)
+	}
+}
+
+// AddVnet to add a VNET to the list of VNETs configured.
+func (va *VoltApplication) AddVnet(cfg VnetConfig, oper *VnetOper) error {
+
+	AppMutex.VnetMutex.Lock()
+	var vv *VoltVnet
+	devicesToHandle := []string{}
+	vv = va.GetVnetByName(cfg.Name)
+	if vv != nil {
+		//Could be for another OLT or could be case of backup-restore
+		for _, serialNum := range cfg.DevicesList {
+			if isDeviceInList(serialNum, vv.DevicesList) {
+				//This is backup restore scenario, just update the profile
+				logger.Info(ctx, "Add Vnet : Profile Name already exists with OLT, update-the-profile")
+				continue
+			}
+			devicesToHandle = append(devicesToHandle, serialNum)
+		}
+		if len(devicesToHandle) == 0 {
+			logger.Debug(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
+			AppMutex.VnetMutex.Unlock()
+			return nil
+		}
+	}
+
+	if vv == nil {
+		vv = NewVoltVnet(cfg)
+		if oper != nil {
+			vv.PendingDeleteFlow = oper.PendingDeleteFlow
+			vv.DeleteInProgress = oper.DeleteInProgress
+			vv.AssociatedPorts = oper.AssociatedPorts
+			vv.PendingDeviceToDelete = oper.PendingDeviceToDelete
+		}
+		devicesToHandle = append(devicesToHandle, cfg.DevicesList...)
+	} else {
+		vv.DevicesList = append(vv.DevicesList, devicesToHandle...)
+	}
+
+	va.storeVnetConfig(cfg, vv)
+	vv.WriteToDb()
+
+	logger.Infow(ctx, "Added VNET TO DB", log.Fields{"cfg": cfg, "devicesToHandle": devicesToHandle})
+
+	//va.PushDevFlowForVlan(vv)
+	AppMutex.VnetMutex.Unlock()
+	return nil
+}
+
+// DelVnet to delete a VNET from the list of VNETs configured
+func (va *VoltApplication) DelVnet(name, deviceSerialNum string) error {
+	logger.Infow(ctx, "Deleting Vnet", log.Fields{"Vnet": name})
+	AppMutex.VnetMutex.Lock()
+	if vnetIntf, ok := va.VnetsByName.Load(name); ok {
+		vnet := vnetIntf.(*VoltVnet)
+		//Delete from mvp list
+		vnet.DevicesList = util.RemoveFromSlice(vnet.DevicesList, deviceSerialNum)
+
+		va.DeleteDevFlowForVlanFromDevice(vnet, deviceSerialNum)
+		if len(vnet.DevicesList) == 0 {
+			vnet.DeleteInProgress = true
+			vnet.PendingDeviceToDelete = deviceSerialNum
+			vnet.ForceWriteToDb()
+			vnet.VnetPortLock.RLock()
+			if len(vnet.PendingDeleteFlow) == 0 && !vnet.isAssociatedPortsPresent() {
+				logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
+				va.deleteVnetConfig(vnet)
+				_ = db.DelVnet(vnet.Name)
+			} else {
+				logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
+			}
+			vnet.VnetPortLock.RUnlock()
+		} else {
+			//Update the devicelist in db
+			vnet.WriteToDb()
+		}
+	}
+	//TODO: if no vnets are present on device remove icmpv6 group from device
+	AppMutex.VnetMutex.Unlock()
+	return nil
+}
+
+// UpdateVnet to update the VNET with associated service count
+func (va *VoltApplication) UpdateVnet(vv *VoltVnet) error {
+	va.storeVnetConfig(vv.VnetConfig, vv)
+	vv.WriteToDb()
+	logger.Infow(ctx, "Updated VNET TO DB", log.Fields{"vv": vv.VnetConfig})
+	return nil
+}
+
+// ------------------------------------------------------------
+// Manifestation of a VNET on a port is handled below
+// ------------------------------------------------------------
+//
+// The VNET on a port handles everything that is done for a VNET
+// such as DHCP relay state machine, MAC addresses, IP addresses
+// learnt, so on.
+
+// DhcpStatus type
+type DhcpStatus uint8
+
+const (
+	// DhcpStatusNone constant
+	DhcpStatusNone DhcpStatus = 0
+	// DhcpStatusAcked constant
+	DhcpStatusAcked DhcpStatus = 1
+	// DhcpStatusNacked constant
+	DhcpStatusNacked DhcpStatus = 2
+	// EthTypeNone constant
+	EthTypeNone int = 0
+	// EthTypeIPoE constant
+	EthTypeIPoE int = 1
+	// EthTypePPPoE constant
+	EthTypePPPoE int = 2
+)
+
+// VoltPortVnet structure
+type VoltPortVnet struct {
+	Device                     string
+	Port                       string
+	PonPort                    uint32
+	VnetName                   string
+	SVlan                      of.VlanType
+	CVlan                      of.VlanType
+	UniVlan                    of.VlanType
+	SVlanTpid                  layers.EthernetType
+	DhcpRelay                  bool
+	ArpRelay                   bool
+	PppoeIa                    bool
+	MacLearning                MacLearningType
+	DhcpStatus                 DhcpStatus
+	DhcpExpiryTime             time.Time
+	Dhcp6ExpiryTime            time.Time
+	FlowsApplied               bool
+	services                   sync.Map
+	servicesCount              *atomic.Uint64
+	Ipv4Addr                   net.IP
+	Ipv6Addr                   net.IP
+	MacAddr                    net.HardwareAddr
+	LearntMacAddr              net.HardwareAddr
+	CircuitID                  []byte //Will not be used
+	RemoteID                   []byte //Will not be used
+	IsOption82Disabled         bool   //Will not be used
+	RelayState                 DhcpRelayState
+	PPPoeState                 PppoeIaState
+	RelayStatev6               Dhcpv6RelayState
+	IgmpEnabled                bool
+	IgmpFlowsApplied           bool
+	McastService               bool
+	ONTEtherTypeClassification int
+	VlanControl                VlanControl
+	MvlanProfileName           string
+	Version                    string
+	McastTechProfileID         uint16
+	McastPbit                  of.PbitType
+	McastUsMeterID             uint32
+	AllowTransparent           bool
+	VpvLock                    sync.Mutex `json:"-"`
+	SchedID                    int
+	DHCPv6DUID                 [MaxLenDhcpv6DUID]byte
+	PendingFlowLock            sync.RWMutex `json:"-"`
+	PendingDeleteFlow          map[string]bool
+	DeleteInProgress           bool
+	Blocked                    bool
+	DhcpPbit                   of.PbitType
+}
+
+//VlanControl vlan control type
+type VlanControl uint8
+
+const (
+	// None constant
+	// ONU and OLT will passthrough UNIVLAN as is to BNG
+	None VlanControl = iota
+
+	// ONUCVlanOLTSVlan constant
+	// Tagged traffic, ONU will replace UNIVLAN with CVLAN and OLT will add SVLAN
+	// Untagged traffic, ONU will add CVLAN and OLT will add SVLAN
+	ONUCVlanOLTSVlan
+
+	// OLTCVlanOLTSVlan constant
+	// Tagged traffic, ONU will passthrough UNIVLAN as is to OLT and
+	// OLT will replace UNIVLAN with CVLAN and add SVLAN
+	OLTCVlanOLTSVlan
+
+	// ONUCVlan constant
+	// Tagged traffic, ONU will replace UNIVLAN with CVLAN
+	// Untagged traffic, ONU will add CVLAN
+	ONUCVlan
+
+	// OLTSVlan constant
+	// UnTagged traffic, OLT will add the SVLAN
+	OLTSVlan
+)
+
+// NewVoltPortVnet is constructor for VoltPortVnet
+func NewVoltPortVnet(vnet *VoltVnet) *VoltPortVnet {
+	var vpv VoltPortVnet
+
+	vpv.VnetName = vnet.Name
+	vpv.SVlan = vnet.SVlan
+	vpv.CVlan = vnet.CVlan
+	vpv.UniVlan = vnet.UniVlan
+	vpv.SVlanTpid = vnet.SVlanTpid
+	vpv.DhcpRelay = vnet.DhcpRelay
+	vpv.DhcpStatus = DhcpStatusNone
+	vpv.PPPoeState = PppoeIaStateNone
+	vpv.ArpRelay = vnet.ArpLearning
+	vpv.PppoeIa = vnet.PppoeIa
+	vpv.VlanControl = vnet.VlanControl
+	vpv.ONTEtherTypeClassification = vnet.ONTEtherTypeClassification
+	vpv.AllowTransparent = vnet.AllowTransparent
+	vpv.FlowsApplied = false
+	vpv.IgmpEnabled = false
+	vpv.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
+	vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
+	// for OLTCVLAN SVLAN=CVLAN, UNIVLAN can differ.
+	if vpv.VlanControl == ONUCVlan {
+		vpv.CVlan = vpv.SVlan
+	}
+	// for OLTSVLAN  CVLAN=UNIVLAN , SVLAN can differ,
+	// hence assigning UNIVLAN to CVLAN, so that ONU will transparently forward the packet.
+	if vpv.VlanControl == OLTSVlan {
+		vpv.CVlan = vpv.UniVlan
+	}
+	vpv.servicesCount = atomic.NewUint64(0)
+	vpv.SchedID = 0
+	vpv.PendingDeleteFlow = make(map[string]bool)
+	vpv.DhcpPbit = vnet.UsDhcpPbit[0]
+	return &vpv
+}
+
+func (vpv *VoltPortVnet) setDevice(device string) {
+
+	if vpv.Device != device && vpv.Device != "" {
+		GetApplication().DisassociateVpvsFromDevice(device, vpv)
+		//TEMP:
+		vpv.printAssociatedVPVs(false)
+	}
+
+	logger.Infow(ctx, "Associating VPV and Device", log.Fields{"Device": vpv.Device, "Port": vpv.Port, "SVlan": vpv.SVlan})
+
+	vpv.Device = device
+	GetApplication().AssociateVpvsToDevice(device, vpv)
+	//TEMP:
+	vpv.printAssociatedVPVs(true)
+}
+
+//TODO - Nav - Temp
+func (vpv *VoltPortVnet) printAssociatedVPVs(add bool) {
+	logger.Infow(ctx, "Start----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
+	if vMap := GetApplication().GetAssociatedVpvsForDevice(vpv.Device, vpv.SVlan); vMap != nil {
+		vMap.Range(func(key, value interface{}) bool {
+			vpvEntry := key.(*VoltPortVnet)
+			logger.Infow(ctx, "Associated VPVs", log.Fields{"SVlan": vpvEntry.SVlan, "CVlan": vpvEntry.CVlan, "UniVlan": vpvEntry.UniVlan})
+			return true
+		})
+	}
+	logger.Infow(ctx, "End----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
+
+}
+
+// GetCircuitID : The interface to be satisfied by the VoltPortVnet to be a DHCP relay
+// session is implemented below. The main functions still remain in
+// the service.go file.
+func (vpv *VoltPortVnet) GetCircuitID() []byte {
+	return []byte(vpv.CircuitID)
+}
+
+// GetRemoteID to get remote id
+func (vpv *VoltPortVnet) GetRemoteID() []byte {
+	return []byte(vpv.RemoteID)
+}
+
+// GetDhcpState to get dhcp state
+func (vpv *VoltPortVnet) GetDhcpState() DhcpRelayState {
+	return vpv.RelayState
+}
+
+// SetDhcpState to set the dhcp state
+func (vpv *VoltPortVnet) SetDhcpState(state DhcpRelayState) {
+	vpv.RelayState = state
+}
+
+// GetPppoeIaState to get pppoeia state
+func (vpv *VoltPortVnet) GetPppoeIaState() PppoeIaState {
+	return vpv.PPPoeState
+}
+
+// SetPppoeIaState to set pppoeia state
+func (vpv *VoltPortVnet) SetPppoeIaState(state PppoeIaState) {
+	vpv.PPPoeState = state
+}
+
+// GetDhcpv6State to get dhcpv6 state
+func (vpv *VoltPortVnet) GetDhcpv6State() Dhcpv6RelayState {
+	return vpv.RelayStatev6
+}
+
+// SetDhcpv6State to set dhcpv6 state
+func (vpv *VoltPortVnet) SetDhcpv6State(state Dhcpv6RelayState) {
+	vpv.RelayStatev6 = state
+}
+
+// DhcpResultInd for dhcp result indication
+func (vpv *VoltPortVnet) DhcpResultInd(res *layers.DHCPv4) {
+	vpv.ProcessDhcpResult(res)
+}
+
+// Dhcpv6ResultInd for dhcpv6 result indication
+func (vpv *VoltPortVnet) Dhcpv6ResultInd(ipv6Addr net.IP, leaseTime uint32) {
+	vpv.ProcessDhcpv6Result(ipv6Addr, leaseTime)
+}
+
+// GetNniVlans to get nni vlans
+func (vpv *VoltPortVnet) GetNniVlans() (uint16, uint16) {
+	switch vpv.VlanControl {
+	case ONUCVlanOLTSVlan,
+		OLTCVlanOLTSVlan:
+		return uint16(vpv.SVlan), uint16(vpv.CVlan)
+	case ONUCVlan,
+		None:
+		return uint16(vpv.SVlan), uint16(of.VlanNone)
+	case OLTSVlan:
+		return uint16(vpv.SVlan), uint16(of.VlanNone)
+	}
+	return uint16(of.VlanNone), uint16(of.VlanNone)
+}
+
+// GetService to get service
+func (vpv *VoltPortVnet) GetService(name string) (*VoltService, bool) {
+	service, ok := vpv.services.Load(name)
+	if ok {
+		return service.(*VoltService), ok
+	}
+	return nil, ok
+}
+
+// AddService to add service
+func (vpv *VoltPortVnet) AddService(service *VoltService) {
+	vpv.services.Store(service.Name, service)
+	vpv.servicesCount.Inc()
+	logger.Infow(ctx, "Service added/updated to VPV", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "Service": service.Name, "Count": vpv.servicesCount.Load()})
+}
+
+// DelService to delete service
+func (vpv *VoltPortVnet) DelService(service *VoltService) {
+	vpv.services.Delete(service.Name)
+	vpv.servicesCount.Dec()
+
+	// If the only Igmp Enabled service is removed, remove the Igmp trap flow along with it
+	if service.IgmpEnabled {
+		if err := vpv.DelIgmpFlows(); err != nil {
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		}
+
+		vpv.IgmpEnabled = false
+	}
+	logger.Infow(ctx, "Service deleted from VPV", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "Service": service.Name, "Count": vpv.servicesCount.Load()})
+}
+
+// ProcessDhcpResult to process dhcp results
+func (vpv *VoltPortVnet) ProcessDhcpResult(res *layers.DHCPv4) {
+	msgType := DhcpMsgType(res)
+	if msgType == layers.DHCPMsgTypeAck {
+		vpv.ProcessDhcpSuccess(res)
+	} else if msgType == layers.DHCPMsgTypeNak {
+		vpv.DhcpStatus = DhcpStatusNacked
+	}
+	vpv.WriteToDb()
+}
+
+// ProcessDhcpSuccess : Learn the IPv4 address allocated to the services and update the
+// the services with the same. This also calls for adding flows
+// for the services as the DHCP procedure is completed
+func (vpv *VoltPortVnet) ProcessDhcpSuccess(res *layers.DHCPv4) {
+	vpv.DhcpStatus = DhcpStatusAcked
+	vpv.Ipv4Addr, _ = GetIpv4Addr(res)
+	logger.Infow(ctx, "Received IPv4 Address", log.Fields{"IP Address": vpv.Ipv4Addr.String()})
+	logger.Infow(ctx, "Services Configured", log.Fields{"Count": vpv.servicesCount.Load()})
+
+	vpv.services.Range(vpv.updateIPv4AndProvisionFlows)
+	vpv.ProcessDhcpv4Options(res)
+}
+
+// ProcessDhcpv4Options : Currently we process lease time and store the validity of the
+// IP address allocated.
+func (vpv *VoltPortVnet) ProcessDhcpv4Options(res *layers.DHCPv4) {
+	for _, o := range res.Options {
+		switch o.Type {
+		case layers.DHCPOptLeaseTime:
+			leasetime := GetIPv4LeaseTime(o)
+			vpv.DhcpExpiryTime = time.Now().Add((time.Duration(leasetime) * time.Second))
+			logger.Infow(ctx, "Lease Expiry Set", log.Fields{"Time": vpv.DhcpExpiryTime})
+		}
+	}
+}
+
+// ProcessDhcpv6Result : Read the IPv6 address allocated to the device and store it on the
+// VNET. The same IPv6 address is also passed to the services. When a
+// service is fetched all the associated information such as MAC address,
+// IPv4 address and IPv6 addresses can be provided.
+func (vpv *VoltPortVnet) ProcessDhcpv6Result(ipv6Addr net.IP, leaseTime uint32) {
+	// TODO: Status based hanlding of flows
+	vpv.Dhcp6ExpiryTime = time.Now().Add((time.Duration(leaseTime) * time.Second))
+	vpv.Ipv6Addr = ipv6Addr
+
+	vpv.services.Range(vpv.updateIPv6AndProvisionFlows)
+	vpv.WriteToDb()
+}
+
+// AddSvcUsMeterToDevice to add service upstream meter info to device
+func AddSvcUsMeterToDevice(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	logger.Info(ctx, "Adding upstream meter profile to device", log.Fields{"ServiceName": svc.Name})
+	if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
+		GetApplication().AddMeterToDevice(svc.Port, device.Name, svc.UsMeterID, 0)
+		return true
+	}
+	logger.Errorw(ctx, "Dropping US Meter request: Device not found", log.Fields{"Service": svc})
+	return false
+}
+
+// PushFlowsForPortVnet - triggers flow construction and push for provided VPV
+func (vpv *VoltPortVnet) PushFlowsForPortVnet(d *VoltDevice) {
+
+	vp := d.GetPort(vpv.Port)
+
+	//Ignore if UNI port is not found or not UP
+	if vp == nil || vp.State != PortStateUp {
+		logger.Warnw(ctx, "Ignoring Vlan UP Ind for VPV: Port Not Found/Ready", log.Fields{"Port": vp})
+		return
+	}
+
+	if vpv.PonPort != 0xFF && vpv.PonPort != vp.PonPort {
+		logger.Errorw(ctx, "UNI port discovered on wrong PON Port. Dropping Flow Configuration for VPV", log.Fields{"Device": d.Name, "Port": vpv.Port, "DetectedPon": vp.PonPort, "ExpectedPon": vpv.PonPort, "Vnet": vpv.VnetName})
+		return
+	}
+
+	//Disable the flag so that flows can be pushed again
+	// vpv.IgmpFlowsApplied = false
+	// vpv.DsFlowsApplied = false
+	// vpv.UsFlowsApplied = false
+	vpv.VpvLock.Lock()
+	vpv.PortUpInd(d, vpv.Port)
+	vpv.VpvLock.Unlock()
+}
+
+// PortUpInd : When a port transistions to UP state, the indication is passed
+// on to this module via the application. We read the VNET configuration
+// again here to apply the latest configuration if the configuration
+// changed. Thus, a reboot of ONT forces the new configuration to get
+// applied.
+func (vpv *VoltPortVnet) PortUpInd(device *VoltDevice, port string) {
+
+	if vpv.DeleteInProgress {
+		logger.Errorw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
+		return
+	}
+	vpv.setDevice(device.Name)
+	logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
+
+	nni, _ := GetApplication().GetNniPort(device.Name)
+	if nni == "" {
+		logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name})
+		return
+	}
+
+	if vp := device.GetPort(port); vp != nil {
+
+		if vpv.PonPort != 0xFF && vpv.PonPort != vp.PonPort {
+			logger.Errorw(ctx, "UNI port discovered on wrong PON Port. Dropping Flow Config for VPV", log.Fields{"Device": device.Name, "Port": port, "DetectedPon": vp.PonPort, "ExpectedPon": vpv.PonPort, "Vnet": vpv.VnetName})
+			return
+		}
+	}
+
+	if vpv.Blocked {
+		logger.Errorw(ctx, "VPV Bocked for Processing. Ignoring flow push request", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
+		return
+	}
+
+	if vpv.DhcpRelay || vpv.ArpRelay || vpv.PppoeIa {
+		// If MAC Learning is true if no MAC is configured, push DS/US DHCP, US HSIA flows without MAC.
+		// DS HSIA flows are installed after learning the MAC.
+		logger.Infow(ctx, "Port Up - Trap Flows", log.Fields{"Device": device.Name, "Port": port})
+		// no HSIA flows for multicast service
+		if !vpv.McastService {
+			vpv.services.Range(AddUsHsiaFlows)
+		}
+		vpv.AddTrapFlows()
+		if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
+			logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
+			// US & DS DHCP, US HSIA flows are already installed
+			// install only DS HSIA flow here.
+			// no HSIA flows for multicast service
+			if !vpv.McastService {
+				vpv.services.Range(AddDsHsiaFlows)
+			}
+		}
+
+	} else {
+		// DHCP relay is not configured. This implies that the service must use
+		// 1:1 and does not require MAC learning. In a completely uncommon but
+		// plausible case, the MAC address can be learnt from N:1 without DHCP
+		// relay by configuring any unknown MAC address to be reported. This
+		// however is not seen as a real use case.
+		logger.Infow(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
+		if !vpv.McastService {
+			vpv.services.Range(AddUsHsiaFlows)
+		}
+		vpv.AddTrapFlows()
+		if !vpv.McastService {
+			vpv.services.Range(AddDsHsiaFlows)
+		}
+	}
+
+	// Process IGMP proxy - install IGMP trap rules before DHCP trap rules
+	if vpv.IgmpEnabled {
+		logger.Infow(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
+		vpv.services.Range(AddSvcUsMeterToDevice)
+		if err := vpv.AddIgmpFlows(); err != nil {
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		}
+
+		if vpv.McastService {
+			vpv.services.Range(PostAccessConfigSuccessInd)
+		}
+	}
+
+	vpv.WriteToDb()
+}
+
+// PortDownInd : When the port status changes to down, we delete all configured flows
+// The same indication is also passed to the services enqueued for them
+// to take appropriate actions
+func (vpv *VoltPortVnet) PortDownInd(device string, port string) {
+
+	logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
+		log.Fields{"service count": vpv.servicesCount.Load()})
+
+	//vpv.services.Range(DelAllFlows)
+	vpv.DelTrapFlows()
+	vpv.DelHsiaFlows()
+	vpv.WriteToDb()
+	vpv.ClearServiceCounters()
+}
+
+// SetMacAddr : The MAC address is set when a MAC address is learnt through the
+// packets received from the network. Currently, DHCP packets are
+// only packets we learn the MAC address from
+func (vpv *VoltPortVnet) SetMacAddr(addr net.HardwareAddr) {
+
+	//Store Learnt MAC address and return if MACLearning is not enabled
+	vpv.LearntMacAddr = addr
+	if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
+		(NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
+		return
+	}
+
+	// Compare the two MAC addresses to see if it is same
+	// If they are same, we just return. If not, we perform
+	// actions to address the change in MAC address
+	//if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
+	if !util.MacAddrsMatch(vpv.MacAddr, addr) {
+		expectedPort := GetApplication().GetMacInPortMap(addr)
+		if expectedPort != "" && expectedPort != vpv.Port {
+			logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
+				log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
+			return
+		}
+		if NonZeroMacAddress(vpv.MacAddr) {
+			logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
+
+			// The newly learnt MAC address is different than earlier one.
+			// The existing MAC based HSIA flows need to be undone as the device
+			// may have been changed
+			// Atleast one HSIA flow should be present in adapter to retain the TP and GEM
+			// hence delete one after the other
+			vpv.services.Range(DelUsHsiaFlows)
+			vpv.MacAddr = addr
+			vpv.services.Range(vpv.setLearntMAC)
+			vpv.services.Range(AddUsHsiaFlows)
+			vpv.services.Range(DelDsHsiaFlows)
+			GetApplication().DeleteMacInPortMap(vpv.MacAddr)
+		} else {
+			vpv.MacAddr = addr
+			vpv.services.Range(vpv.setLearntMAC)
+			logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
+		}
+		GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
+	} else {
+		logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
+	}
+
+	_, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		return
+	}
+	// Ds Hsia flows has to be pushed
+	if vpv.FlowsApplied {
+		// no HSIA flows for multicast service
+		if !vpv.McastService {
+			vpv.services.Range(AddDsHsiaFlows)
+		}
+	}
+	vpv.WriteToDb()
+}
+
+// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
+func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
+	if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
+		return false
+	}
+	return true
+}
+
+// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
+func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
+	if len(cvlan) != 1 && !vpv.AllowTransparent {
+		return false
+	}
+	if vpv.CVlan != cvlan[0] {
+		return false
+	}
+	return true
+}
+
+// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
+func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
+
+	var service *VoltService
+	pbitFound := false
+	matchpbitsFunc := func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		for _, pbit := range svc.Pbits {
+			if uint8(pbit) == priority {
+				logger.Infow(ctx, "Pbit match found with service",
+					log.Fields{"Pbit": priority, "serviceName": svc.Name})
+				pbitFound = true
+				service = svc
+				return false //Returning false to stop the Range loop
+			}
+		}
+		return true
+	}
+	_ = pbitFound
+	vpv.services.Range(matchpbitsFunc)
+	return service
+}
+
+// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
+func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
+
+	dsPbit := uint8(0)
+	matchpbitsFunc := func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
+			logger.Infow(ctx, "Pbit match found with service",
+				log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
+			dsPbit = uint8(remarkPbit)
+			return false //Returning false to stop the Range loop
+		}
+		// When no remarking info is available, remark the incoming pbit
+		// to highest pbit configured for the subscriber (across all subservices associated)
+		svcPbit := uint8(svc.Pbits[0])
+		if svcPbit > dsPbit {
+			dsPbit = svcPbit
+		}
+		return true
+	}
+	vpv.services.Range(matchpbitsFunc)
+	logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
+	return dsPbit
+}
+
+// AddSvc adds a service on the VNET on a port. The addition is
+// triggered when NB requests for service addition
+func (vpv *VoltPortVnet) AddSvc(svc *VoltService) {
+
+	//vpv.services = append(vpv.services, svc)
+	vpv.AddService(svc)
+	logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
+
+	// Learn the circuit-id and remote-id from the service
+	// TODO: There must be a better way of doing this. This
+	// may be explored
+	if svc.IgmpEnabled {
+		vpv.IgmpEnabled = true
+	}
+	// first time service activation MacLearning will have default value as None.
+	// to handle reciliency if anythng other then None we should retain it .
+	if svc.MacLearning == MacLearningNone {
+		if !vpv.DhcpRelay && !vpv.ArpRelay {
+			svc.MacLearning = MacLearningNone
+		} else if vpv.MacLearning == Learn {
+			svc.MacLearning = Learn
+		} else if vpv.MacLearning == ReLearn {
+			svc.MacLearning = ReLearn
+		}
+	}
+
+	//TODO: Temp Change - Need to address MAC Learning flow issues completely
+	if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
+		svc.MacAddr = vpv.MacAddr
+	} else if vpv.servicesCount.Load() == 1 {
+		vpv.MacAddr = svc.MacAddr
+	}
+
+	vpv.MacLearning = svc.MacLearning
+	vpv.PonPort = svc.PonPort
+	logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
+	//Reconfigure Vlans based on Vlan Control type
+	svc.VlanControl = vpv.VlanControl
+	// for OLTCVLAN SVLAN=CVLAN, UNIVLAN can differ.
+	if vpv.VlanControl == ONUCVlan {
+		svc.CVlan = svc.SVlan
+	}
+	// for OLTSVLAN  CVLAN=UNIVLAN , SVLAN can differ,
+	// hence assigning UNIVLAN to CVLAN, so that ONU will transparently forward the packet.
+	if vpv.VlanControl == OLTSVlan {
+		svc.CVlan = svc.UniVlan
+	}
+	if svc.McastService {
+		vpv.McastService = true
+		vpv.McastTechProfileID = svc.TechProfileID
+		//Assumption: Only one Pbit for mcast service
+		vpv.McastPbit = svc.Pbits[0]
+		vpv.McastUsMeterID = svc.UsMeterID
+		vpv.SchedID = svc.SchedID
+	}
+	svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
+	svc.AllowTransparent = vpv.AllowTransparent
+	svc.SVlanTpid = vpv.SVlanTpid
+
+	//Ensure configuring the mvlan profile only once
+	//One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
+	if svc.MvlanProfileName != "" {
+		if vpv.MvlanProfileName == "" {
+			vpv.MvlanProfileName = svc.MvlanProfileName
+		} else {
+			logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
+		}
+	}
+
+	_, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
+		//statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		//TODO-COMM: 		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		return
+	}
+
+	//Push Service Flows if DHCP relay is not configured
+	//or already DHCP flows are configured for the VPV
+	//to which the serivce is associated
+	if vpv.FlowsApplied {
+		if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
+			svc.AddHsiaFlows()
+		} else {
+			if err:= svc.AddUsHsiaFlows(); err != nil {
+				logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
+			}
+		}
+	}
+
+	//Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
+	// When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
+	// service with Igmp Enabled needs to be installed
+	if svc.IgmpEnabled && vpv.FlowsApplied {
+		logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
+		if err := vpv.AddIgmpFlows(); err != nil {
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		}
+
+		if vpv.McastService {
+			//For McastService, send Service Activated indication once IGMP US flow is pushed
+			vpv.services.Range(PostAccessConfigSuccessInd)
+		}
+	}
+	vpv.WriteToDb()
+}
+
+// setLearntMAC to set learnt mac
+func (vpv *VoltPortVnet) setLearntMAC(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	svc.SetMacAddr(vpv.MacAddr)
+	svc.WriteToDb()
+	return true
+}
+
+// PostAccessConfigSuccessInd for posting access config success indication
+func PostAccessConfigSuccessInd(key, value interface{}) bool {
+	return true
+}
+
+// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
+func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	logger.Info(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
+	svc.SetIpv4Addr(vpv.Ipv4Addr)
+	svc.WriteToDb()
+
+	return true
+}
+
+// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
+func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	svc.SetIpv6Addr(vpv.Ipv6Addr)
+	svc.WriteToDb()
+
+	return true
+}
+
+// AddUsHsiaFlows to add upstream hsia flows
+func AddUsHsiaFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	if err:= svc.AddUsHsiaFlows(); err != nil {
+		logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
+	}
+	return true
+}
+
+// AddDsHsiaFlows to add downstream hsia flows
+func AddDsHsiaFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	if err:= svc.AddDsHsiaFlows(); err != nil {
+		logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
+	}
+	return true
+}
+
+// ClearFlagsInService to clear the flags used in service
+func ClearFlagsInService(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	svc.ServiceLock.Lock()
+	svc.IgmpFlowsApplied = false
+	svc.DsDhcpFlowsApplied = false
+	svc.DsHSIAFlowsApplied = false
+	svc.Icmpv6FlowsApplied = false
+	svc.UsHSIAFlowsApplied = false
+	svc.UsDhcpFlowsApplied = false
+	svc.PendingFlows = make(map[string]bool)
+	svc.AssociatedFlows = make(map[string]bool)
+	svc.ServiceLock.Unlock()
+	svc.WriteToDb()
+	logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
+	return true
+}
+
+// DelDsHsiaFlows to delete hsia flows
+func DelDsHsiaFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	if err:= svc.DelDsHsiaFlows(); err != nil {
+		logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
+	}
+	return true
+}
+
+// DelUsHsiaFlows to delete upstream hsia flows
+func DelUsHsiaFlows(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	if err:= svc.DelUsHsiaFlows(); err != nil {
+		logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
+	}
+	return true
+}
+
+// ClearServiceCounters to clear the service counters
+func ClearServiceCounters(key, value interface{}) bool {
+	svc := value.(*VoltService)
+	//Delete the per service counter too
+	GetApplication().ServiceCounters.Delete(svc.Name)
+	if svc.IgmpEnabled && svc.EnableMulticastKPI {
+		_ = db.DelAllServiceChannelCounter(svc.Name)
+	}
+	return true
+}
+
+//AddTrapFlows - Adds US & DS Trap flows
+func (vpv *VoltPortVnet) AddTrapFlows() {
+
+	if !vpv.FlowsApplied || vgcRebooted {
+		if vpv.DhcpRelay {
+			if err := vpv.AddUsDhcpFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			if err := vpv.AddDsDhcpFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
+				log.Fields{"port": vpv.Port})
+			//vpv.updateICMPv6McGroup(true)
+		} else if vpv.ArpRelay {
+			if err := vpv.AddUsArpFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			logger.Info(ctx, "ARP trap rules not added in downstream direction")
+
+		} else if vpv.PppoeIa {
+			if err := vpv.AddUsPppoeFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			if err := vpv.AddDsPppoeFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+		}
+		vpv.FlowsApplied = true
+		vpv.WriteToDb()
+	}
+}
+
+//DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
+func (vpv *VoltPortVnet) DelTrapFlows() {
+
+	// Delete HSIA & DHCP flows before deleting IGMP flows
+	if vpv.FlowsApplied || vgcRebooted {
+		if vpv.DhcpRelay {
+			if err:= vpv.DelUsDhcpFlows(); err != nil {
+				logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
+					"UniVlan": vpv.UniVlan, "Error": err})
+			}
+			logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore  for ",
+				log.Fields{"port": vpv.Port})
+			if err := vpv.DelDsDhcpFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			//vpv.updateICMPv6McGroup(false)
+		} else if vpv.ArpRelay {
+			if err := vpv.DelUsArpFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+		} else if vpv.PppoeIa {
+			if err := vpv.DelUsPppoeFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+			if err := vpv.DelDsPppoeFlows(); err != nil {
+				statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+			}
+		}
+		vpv.FlowsApplied = false
+		vpv.WriteToDb()
+	}
+	if err:= vpv.DelIgmpFlows(); err != nil {
+		logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
+			"UniVlan": vpv.UniVlan, "Error": err})
+	}
+}
+
+// DelHsiaFlows deletes the service flows
+func (vpv *VoltPortVnet) DelHsiaFlows() {
+	// no HSIA flows for multicast service
+	if !vpv.McastService {
+		vpv.services.Range(DelUsHsiaFlows)
+		vpv.services.Range(DelDsHsiaFlows)
+	}
+}
+
+//ClearServiceCounters - Removes all igmp counters for a service
+func (vpv *VoltPortVnet) ClearServiceCounters() {
+	//send flows deleted indication to submgr
+	vpv.services.Range(ClearServiceCounters)
+}
+
+// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
+func (vpv *VoltPortVnet) AddUsDhcpFlows() error {
+	var vd *VoltDevice
+	device := vpv.Device
+
+	if vd = GetApplication().GetDevice(device); vd != nil {
+		if vd.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Skipping US DHCP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+			return nil
+		}
+	} else {
+		logger.Errorw(ctx, "US DHCP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+		return errorCodes.ErrDeviceNotFound
+	}
+
+	flows, err := vpv.BuildUsDhcpFlows()
+	if err == nil {
+		logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			//push ind here ABHI
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err1)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+		}
+	} else {
+		logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
+		//push ind here ABHI
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+	}
+	/*
+	flows, err = vpv.BuildUsDhcp6Flows()
+	if err == nil {
+		logger.Debugw(ctx, "Adding US DHCP6 flows", log.Fields{"Device": device})
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			//pussh ind here ABHI
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err1)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+		}
+	} else {
+		logger.Errorw(ctx, "US DHCP6 Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
+		//push ind here ABHI
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+	}*/
+	return nil
+}
+
+// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
+func (vpv *VoltPortVnet) AddDsDhcpFlows() error {
+
+	var vd *VoltDevice
+	device := vpv.Device
+
+	if vd = GetApplication().GetDevice(device); vd != nil {
+		if vd.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Skipping DS DHCP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+			return nil
+		}
+	} else {
+		logger.Errorw(ctx, "DS DHCP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+		return errorCodes.ErrDeviceNotFound
+	}
+	if GetApplication().GetVendorID() != Radisys && vd.GlobalDhcpFlowAdded {
+		return nil
+	}
+
+	flows, err := vpv.BuildDsDhcpFlows()
+	if err == nil {
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			//push ind here and procced
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err1)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+		}
+	} else {
+		logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
+		//send ind here and proceed
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+	}
+	/*
+	flows, err = vpv.BuildDsDhcp6Flows()
+	if err == nil {
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			//push ind and proceed
+			statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err1)
+			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+		}
+	} else {
+		logger.Errorw(ctx, "DS DHCP6 Flow Add Failed", log.Fields{"Reason": err.Error()})
+		//Send ind here and proceed
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+
+	}*/
+	if GetApplication().GetVendorID() != Radisys {
+		vd.GlobalDhcpFlowAdded = true
+	}
+	return nil
+}
+
+// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
+func (vpv *VoltPortVnet) DelDhcpFlows() {
+	if err := vpv.DelUsDhcpFlows(); err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}
+
+	if err := vpv.DelDsDhcpFlows(); err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}
+}
+
+// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelUsDhcpFlows() error {
+	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		return err
+	}
+
+	err = vpv.delDhcp4Flows(device)
+	if err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}
+	/*
+	err = vpv.delDhcp6Flows(device)
+	if err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}*/
+	return nil
+}
+
+func (vpv *VoltPortVnet) delDhcp4Flows(device *VoltDevice) error {
+	flows, err := vpv.BuildUsDhcpFlows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "US DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}
+/*
+func (vpv *VoltPortVnet) delDhcp6Flows(device *VoltDevice) error {
+	flows, err := vpv.BuildUsDhcp6Flows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "US DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+
+}*/
+
+// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelDsDhcpFlows() error {
+	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		return err
+	}
+	err = vpv.delDsDhcp4Flows(device)
+	if err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}
+	/*
+	err = vpv.delDsDhcp6Flows(device)
+	if err != nil {
+		statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
+		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
+	}*/
+	return nil
+}
+
+func (vpv *VoltPortVnet) delDsDhcp4Flows(device *VoltDevice) error {
+	flows, err := vpv.BuildDsDhcpFlows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "DS DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}
+
+/*
+func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
+	flows, err := vpv.BuildDsDhcp6Flows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}*/
+
+// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
+func (vpv *VoltPortVnet) AddUsArpFlows() error {
+
+	var vd *VoltDevice
+	device := vpv.Device
+	if vd = GetApplication().GetDevice(device); vd != nil {
+		if vd.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Skipping US ARP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+			return nil
+		}
+	} else {
+		logger.Errorw(ctx, "US ARP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+		return errorCodes.ErrDeviceNotFound
+	}
+
+	flows, err := vpv.BuildUsArpFlows()
+	if err == nil {
+		logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			return err1
+		}
+	} else {
+		logger.Errorw(ctx, "US ARP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
+		return err
+	}
+	return nil
+}
+
+// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelUsArpFlows() error {
+	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		return err
+	}
+	flows, err := vpv.BuildUsArpFlows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "US ARP Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}
+
+// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
+func (vpv *VoltPortVnet) AddUsPppoeFlows() error {
+	logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
+
+	var vd *VoltDevice
+	device := vpv.Device
+
+	if vd = GetApplication().GetDevice(device); vd != nil {
+		if vd.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Skipping US PPPoE Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+			return nil
+		}
+	} else {
+		logger.Errorw(ctx, "US PPPoE Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+		return errorCodes.ErrDeviceNotFound
+	}
+
+	if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
+		logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
+
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			return err1
+		}
+	} else {
+		logger.Errorw(ctx, "US PPPoE Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
+		return err
+	}
+	return nil
+}
+
+// AddDsPppoeFlows to add downstream pppoe flows
+func (vpv *VoltPortVnet) AddDsPppoeFlows() error {
+	logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
+	var vd *VoltDevice
+	device := vpv.Device
+
+	if vd = GetApplication().GetDevice(device); vd != nil {
+		if vd.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Skipping DS PPPoE Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+			return nil
+		}
+	} else {
+		logger.Errorw(ctx, "DS PPPoE Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
+		return errorCodes.ErrDeviceNotFound
+	}
+
+	flows, err := vpv.BuildDsPppoeFlows()
+	if err == nil {
+
+		if err1 := vpv.PushFlows(vd, flows); err1 != nil {
+			return err1
+		}
+	} else {
+		logger.Errorw(ctx, "DS PPPoE Flow Add Failed", log.Fields{"Reason": err.Error()})
+		return err
+	}
+	return nil
+}
+
+// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelUsPppoeFlows() error {
+	logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
+	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		return err
+	}
+	flows, err := vpv.BuildUsPppoeFlows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "US PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}
+
+// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelDsPppoeFlows() error {
+	logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
+	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+	if err != nil {
+		return err
+	}
+	flows, err := vpv.BuildDsPppoeFlows()
+	if err == nil {
+		return vpv.RemoveFlows(device, flows)
+	}
+	logger.Errorw(ctx, "DS PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
+	return err
+}
+
+// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
+func (vpv *VoltPortVnet) AddIgmpFlows() error {
+
+	if !vpv.IgmpFlowsApplied || vgcRebooted {
+		if vpv.MvlanProfileName == "" {
+			logger.Info(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
+			return nil
+		}
+		device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+		if err != nil {
+			logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
+			return err
+		} else if device.State != controller.DeviceStateUP {
+			logger.Warnw(ctx, "Device state Down. Ignoring US IGMP Flow Push", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan})
+			return nil
+		}
+		flows, err := vpv.BuildIgmpFlows()
+		if err == nil {
+			for cookie := range flows.SubFlows {
+				if vd := GetApplication().GetDevice(device.Name); vd != nil {
+					cookie := strconv.FormatUint(cookie, 10)
+					fe := &FlowEvent{
+						eType:     EventTypeUsIgmpFlowAdded,
+						cookie:    cookie,
+						eventData: vpv,
+					}
+					vd.RegisterFlowAddEvent(cookie, fe)
+				}
+			}
+			if err1 := cntlr.GetController().AddFlows(vpv.Port, device.Name, flows); err1 != nil {
+				return err1
+			}
+		} else {
+			logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
+			return err
+		}
+		vpv.IgmpFlowsApplied = true
+		vpv.WriteToDb()
+	}
+	return nil
+}
+
+// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
+// Write the status of the VPV to the DB once the delete is scheduled
+// for dispatch
+func (vpv *VoltPortVnet) DelIgmpFlows() error {
+
+	if vpv.IgmpFlowsApplied || vgcRebooted {
+		device, err := GetApplication().GetDeviceFromPort(vpv.Port)
+		if err != nil {
+			logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
+			return err
+		}
+		flows, err := vpv.BuildIgmpFlows()
+		if err == nil {
+			if err1 := vpv.RemoveFlows(device, flows); err1 != nil {
+				return err1
+			}
+		} else {
+			logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
+			return err
+		}
+		vpv.IgmpFlowsApplied = false
+		vpv.WriteToDb()
+	}
+	return nil
+}
+
+// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
+// The flows included by this function cover US only as the DS is
+// created either automatically by the VOLTHA or at the device level
+// earlier
+func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+
+	logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	if GetApplication().GetVendorID() == Radisys {
+		if err := vpv.setUsMatchVlan(subFlow); err != nil {
+			return nil, err
+		}
+	} else {
+		subFlow.SetMatchVlan(vpv.UniVlan)
+		subFlow.SetSetVlan(vpv.CVlan)
+	}
+	subFlow.SetUdpv4Match()
+	subFlow.SrcPort = 68
+	subFlow.DstPort = 67
+	uniport, err := GetApplication().GetPortID(vpv.Port)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to fetch uni port from vpv", log.Fields{"error": err, "port": vpv.Port})
+		return nil, err
+	}
+	subFlow.SetInPort(uniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	subFlow.SetReportToController()
+
+	// Set techprofile, meterid of first service
+	vpv.services.Range(func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		writemetadata := uint64(svc.TechProfileID) << 32
+		subFlow.SetWriteMetadata(writemetadata)
+		subFlow.SetMeterID(svc.UsMeterID)
+		return false
+	})
+
+	subFlow.SetPcp(vpv.DhcpPbit)
+	// metadata := uint64(uniport)
+	// subFlow.SetWriteMetadata(metadata)
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
+	subFlow.Priority = of.DhcpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// BuildDsDhcpFlows to build the downstream dhcp flows
+func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
+
+	logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+	// If dhcp trap rule is global rule, No need to match on vlan
+	if GetApplication().GetVendorID() == Radisys {
+		vpv.setDsMatchVlan(subFlow)
+	}
+	subFlow.SetUdpv4Match()
+	subFlow.SrcPort = 67
+	subFlow.DstPort = 68
+	uniport, _ := GetApplication().GetPortID(vpv.Port)
+	nni, err := GetApplication().GetNniPort(vpv.Device)
+	if err != nil {
+		return nil, err
+	}
+	nniport, err := GetApplication().GetPortID(nni)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(nniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	// metadata := uint64(uniport)
+	// subFlow.SetWriteMetadata(metadata)
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.SetReportToController()
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
+	subFlow.Priority = of.DhcpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
+
+	return flow, nil
+}
+
+// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
+// application.
+func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+
+	logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	subFlow.SetMatchVlan(vpv.UniVlan)
+	subFlow.SetSetVlan(vpv.CVlan)
+	subFlow.SetUdpv6Match()
+	subFlow.SrcPort = 546
+	subFlow.DstPort = 547
+	uniport, err := GetApplication().GetPortID(vpv.Port)
+	if err != nil {
+		return nil, err
+	}
+	// Set techprofile, meterid of first service
+	vpv.services.Range(func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		writemetadata := uint64(svc.TechProfileID) << 32
+		subFlow.SetWriteMetadata(writemetadata)
+		subFlow.SetMeterID(svc.UsMeterID)
+		return false
+	})
+	subFlow.SetInPort(uniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	//subFlow.SetMeterId(vpv.UsDhcpMeterId)
+	// metadata := uint64(uniport)
+	// subFlow.SetWriteMetadata(metadata)
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.SetReportToController()
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
+	subFlow.Priority = of.DhcpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
+// application.
+func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
+	logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
+
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	vpv.setDsMatchVlan(subFlow)
+	subFlow.SetUdpv6Match()
+	subFlow.SrcPort = 547
+	subFlow.DstPort = 547
+	uniport, _ := GetApplication().GetPortID(vpv.Port)
+	nni, err := GetApplication().GetNniPort(vpv.Device)
+	if err != nil {
+		return nil, err
+	}
+	nniport, err := GetApplication().GetPortID(nni)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(nniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	// metadata := uint64(uniport)
+	// subFlow.SetWriteMetadata(metadata)
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.SetReportToController()
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
+	subFlow.Priority = of.DhcpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// BuildUsArpFlows builds the US ARP relay flows for a subscriber
+// The flows included by this function cover US only as the DS is
+// created either automatically by the VOLTHA or at the device level
+// earlier
+func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+
+	logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
+		subFlow.SetMatchSrcMac(vpv.MacAddr)
+	}
+
+	subFlow.SetMatchDstMac(BroadcastMAC)
+	if err := vpv.setUsMatchVlan(subFlow); err != nil {
+		return nil, err
+	}
+	subFlow.SetArpMatch()
+	uniport, err := GetApplication().GetPortID(vpv.Port)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(uniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	subFlow.SetReportToController()
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(uniport)
+	subFlow.SetWriteMetadata(metadata)
+	metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
+	subFlow.Priority = of.ArpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// setUsMatchVlan to set upstream match vlan
+func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
+	switch vpv.VlanControl {
+	case None:
+		flow.SetMatchVlan(vpv.SVlan)
+	case ONUCVlanOLTSVlan:
+		flow.SetMatchVlan(vpv.CVlan)
+	case OLTCVlanOLTSVlan:
+		flow.SetMatchVlan(vpv.UniVlan)
+		//flow.SetSetVlan(vpv.CVlan)
+	case ONUCVlan:
+		flow.SetMatchVlan(vpv.SVlan)
+	case OLTSVlan:
+		flow.SetMatchVlan(vpv.UniVlan)
+		//flow.SetSetVlan(vpv.SVlan)
+	default:
+		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
+		return errorCodes.ErrInvalidParamInRequest
+	}
+	return nil
+}
+
+// BuildUsPppoeFlows to build upstream pppoe flows
+func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
+
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
+		subFlow.SetMatchSrcMac(vpv.MacAddr)
+	}
+
+	if err := vpv.setUsMatchVlan(subFlow); err != nil {
+		return nil, err
+	}
+	subFlow.SetPppoeDiscoveryMatch()
+	uniport, err := GetApplication().GetPortID(vpv.Port)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(uniport)
+	subFlow.SetReportToController()
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(uniport)
+	subFlow.SetWriteMetadata(metadata)
+
+	metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
+	subFlow.Priority = of.PppoeFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// BuildDsPppoeFlows to build downstream pppoe flows
+func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
+
+	logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+	vpv.setDsMatchVlan(subFlow)
+	subFlow.SetPppoeDiscoveryMatch()
+
+	if NonZeroMacAddress(vpv.MacAddr) {
+		subFlow.SetMatchDstMac(vpv.MacAddr)
+	}
+
+	uniport, _ := GetApplication().GetPortID(vpv.Port)
+	nni, err := GetApplication().GetNniPort(vpv.Device)
+	if err != nil {
+		return nil, err
+	}
+	nniport, err := GetApplication().GetPortID(nni)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(nniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+	metadata := uint64(uniport)
+	subFlow.SetWriteMetadata(metadata)
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.SetReportToController()
+	//| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
+	subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
+	subFlow.Priority = of.PppoeFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
+	return flow, nil
+}
+
+// setDsMatchVlan to set downstream match vlan
+func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
+	switch vpv.VlanControl {
+	case None:
+		flow.SetMatchVlan(vpv.SVlan)
+	case ONUCVlanOLTSVlan,
+		OLTCVlanOLTSVlan,
+		ONUCVlan,
+		OLTSVlan:
+		flow.SetMatchVlan(vpv.SVlan)
+	default:
+		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
+	}
+}
+
+// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
+// in the US direction.
+func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
+	logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
+	mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
+	if mvp == nil {
+		return nil, errors.New("Mvlan Profile configured not found")
+	}
+	mvlan := mvp.GetUsMatchVlan()
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+	subFlow.SetTableID(0)
+
+        if GetApplication().GetVendorID() == Radisys {
+                if err := vpv.setUsMatchVlan(subFlow); err != nil {
+                        return nil, err
+                }
+        } else {
+                subFlow.SetMatchVlan(vpv.UniVlan)
+                subFlow.SetSetVlan(vpv.CVlan)
+        }
+
+	uniport, err := GetApplication().GetPortID(vpv.Port)
+	if err != nil {
+		return nil, err
+	}
+	subFlow.SetInPort(uniport)
+	// PortName and PortID to be used for validation of port before flow pushing
+	flow.PortID = uniport
+	flow.PortName = vpv.Port
+
+	if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
+		subFlow.SetMatchSrcMac(vpv.MacAddr)
+	}
+	logger.Infow(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
+	//metadata := uint64(mvlan)
+
+	if vpv.McastService {
+		metadata := uint64(vpv.McastUsMeterID)
+		metadata = metadata | uint64(vpv.McastTechProfileID)<<32
+		subFlow.SetMatchPbit(vpv.McastPbit)
+		subFlow.SetMeterID(vpv.McastUsMeterID)
+		subFlow.SetWriteMetadata(metadata)
+	} else {
+		// Set techprofile, meterid of first service
+		vpv.services.Range(func(key, value interface{}) bool {
+			svc := value.(*VoltService)
+			writemetadata := uint64(svc.TechProfileID) << 32
+			subFlow.SetWriteMetadata(writemetadata)
+			subFlow.SetMeterID(svc.UsMeterID)
+			return false
+		})
+	}
+
+	allowTransparent := 0
+	if vpv.AllowTransparent {
+		allowTransparent = 1
+	}
+	metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
+	subFlow.SetTableMetadata(metadata)
+	subFlow.SetIgmpMatch()
+	subFlow.SetReportToController()
+	//| 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
+	subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
+	subFlow.Priority = of.IgmpFlowPriority
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
+	return flow, nil
+}
+
+// WriteToDb for writing to database
+func (vpv *VoltPortVnet) WriteToDb() {
+	if vpv.DeleteInProgress {
+		logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
+		return
+	}
+	vpv.ForceWriteToDb()
+}
+
+//ForceWriteToDb force commit a VPV to the DB
+func (vpv *VoltPortVnet) ForceWriteToDb() {
+	vpv.PendingFlowLock.RLock()
+	defer vpv.PendingFlowLock.RUnlock()
+	vpv.Version = database.PresentVersionMap[database.VpvPath]
+	if b, err := json.Marshal(vpv); err == nil {
+		if err := db.PutVpv(vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan), string(b)); err != nil {
+			logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
+				"UniVlan": vpv.UniVlan, "Error": err})
+		}
+	}
+}
+
+// DelFromDb for deleting from database
+func (vpv *VoltPortVnet) DelFromDb() {
+	logger.Debugw(ctx, "Deleting VPV from DB", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan})
+	_ = db.DelVpv(vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
+}
+
+// ClearAllServiceFlags to clear all service flags
+func (vpv *VoltPortVnet) ClearAllServiceFlags() {
+	vpv.services.Range(ClearFlagsInService)
+}
+
+// ClearAllVpvFlags to clear all vpv flags
+func (vpv *VoltPortVnet) ClearAllVpvFlags() {
+	vpv.PendingFlowLock.Lock()
+	vpv.FlowsApplied = false
+	vpv.IgmpFlowsApplied = false
+	vpv.PendingDeleteFlow = make(map[string]bool)
+	vpv.PendingFlowLock.Unlock()
+	vpv.WriteToDb()
+	logger.Debugw(ctx, "Cleared Flow Flags for VPV",
+		log.Fields{"device": vpv.Device, "port": vpv.Port,
+			"svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
+}
+
+// CreateVpvFromString to create vpv from string
+func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
+	var vpv VoltPortVnet
+	if err := json.Unmarshal(b, &vpv); err == nil {
+		vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
+		if !ok {
+			va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
+			vnetsByPortsSliceIntf = []*VoltPortVnet{}
+		}
+		vpv.servicesCount = atomic.NewUint64(0)
+		vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
+		vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
+		va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
+		va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
+		if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
+			vnet.associatePortToVnet(vpv.Port)
+		}
+
+		if vpv.DeleteInProgress {
+			va.VoltPortVnetsToDelete[&vpv] = true
+			logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
+		}
+		logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
+	}
+}
+
+// RestoreVpvsFromDb to restore vpvs from database
+func (va *VoltApplication) RestoreVpvsFromDb() {
+	// VNETS must be learnt first
+	vpvs, _ := db.GetVpvs()
+	for hash, vpv := range vpvs {
+		b, ok := vpv.Value.([]byte)
+		if !ok {
+			logger.Warn(ctx, "The value type is not []byte")
+			continue
+		}
+		va.CreateVpvFromString(b, hash)
+	}
+}
+
+// GetVnetByPort : VNET related functionality of VOLT Application here on.
+// Get the VNET from a port. The port identity is passed as device and port identities in string.
+// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
+// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
+func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
+	if _, ok := va.VnetsByPort.Load(port); !ok {
+		return nil
+	}
+	vpvs, _ := va.VnetsByPort.Load(port)
+	for _, vpv := range vpvs.([]*VoltPortVnet) {
+		if vpv.MatchesVlans(svlan, cvlan, univlan) {
+			return vpv
+		}
+	}
+	return nil
+}
+
+// AddVnetToPort to add vnet to port
+func (va *VoltApplication) AddVnetToPort(port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
+	// The VNET is not on the port and is to be added
+	logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
+	vpv := NewVoltPortVnet(vvnet)
+	vpv.MacLearning = vvnet.MacLearning
+	vpv.Port = port
+	vvnet.associatePortToVnet(port)
+	if _, ok := va.VnetsByPort.Load(port); !ok {
+		va.VnetsByPort.Store(port, []*VoltPortVnet{})
+	}
+	vpvsIntf, _ := va.VnetsByPort.Load(port)
+	vpvs := vpvsIntf.([]*VoltPortVnet)
+	vpvs = append(vpvs, vpv)
+	va.VnetsByPort.Store(port, vpvs)
+	va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
+
+	vpv.VpvLock.Lock()
+	defer vpv.VpvLock.Unlock()
+
+	// Add the service that is causing the VNET to be added to the port
+	vpv.AddSvc(vs)
+
+	// Process the PORT UP if the port is already up
+	d, err := va.GetDeviceFromPort(port)
+	if err == nil {
+		vpv.setDevice(d.Name)
+		p := d.GetPort(port)
+		if p != nil {
+
+			if vs.PonPort != 0xFF && vs.PonPort != p.PonPort {
+				logger.Errorw(ctx, "UNI port discovered on wrong PON Port. Dropping Flow Push for VPV", log.Fields{"Device": d.Name, "Port": port, "DetectedPon": p.PonPort, "ExpectedPon": vs.PonPort, "Vnet": vpv.VnetName})
+			} else {
+				logger.Infow(ctx, "Checking UNI port state", log.Fields{"State": p.State})
+				if d.State == controller.DeviceStateUP && p.State == PortStateUp {
+					vpv.PortUpInd(d, port)
+				}
+			}
+		}
+	}
+	vpv.WriteToDb()
+	return vpv
+}
+
+// DelVnetFromPort for deleting vnet from port
+func (va *VoltApplication) DelVnetFromPort(port string, vpv *VoltPortVnet) {
+
+	//Delete DHCP Session
+	delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
+
+	//Delete PPPoE session
+	delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
+
+	//Delete Mac from MacPortMap
+	va.DeleteMacInPortMap(vpv.MacAddr)
+
+	//Delete VPV
+	vpvsIntf, ok := va.VnetsByPort.Load(port)
+	if !ok {
+		return
+	}
+	vpvs := vpvsIntf.([]*VoltPortVnet)
+	for i, lvpv := range vpvs {
+		if lvpv == vpv {
+			logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
+				"UNIVLAN": vpv.UniVlan})
+
+			vpvs = append(vpvs[0:i], vpvs[i+1:]...)
+
+			vpv.DeleteInProgress = true
+			vpv.ForceWriteToDb()
+
+			va.VnetsByPort.Store(port, vpvs)
+			vpv.DelTrapFlows()
+			vpv.DelHsiaFlows()
+			va.DisassociateVpvsFromDevice(vpv.Device, vpv)
+			vpv.PendingFlowLock.RLock()
+			if len(vpv.PendingDeleteFlow) == 0 {
+				vpv.DelFromDb()
+			}
+			if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
+				vnet.disassociatePortFromVnet(vpv.Device, vpv.Port)
+			}
+			vpv.PendingFlowLock.RUnlock()
+			return
+		}
+	}
+}
+
+// RestoreVnetsFromDb to restore vnet from port
+func (va *VoltApplication) RestoreVnetsFromDb() {
+	// VNETS must be learnt first
+	vnets, _ := db.GetVnets()
+	for _, net := range vnets {
+		b, ok := net.Value.([]byte)
+		if !ok {
+			logger.Warn(ctx, "The value type is not []byte")
+			continue
+		}
+		var vnet VoltVnet
+		err := json.Unmarshal(b, &vnet)
+		if err != nil {
+			logger.Warn(ctx, "Unmarshal of VNET failed")
+			continue
+		}
+		logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
+		if err := va.AddVnet(vnet.VnetConfig, &vnet.VnetOper); err != nil {
+			logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
+		}
+
+		if vnet.DeleteInProgress {
+			va.VnetsToDelete[vnet.Name] = true
+			logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
+		}
+
+	}
+}
+
+// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
+// are used as the key to locate the service. If more than one service is on the
+// same port (essentially a UNI of ONU), the services must be separated by different
+// CVLANs
+func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
+	// Fetch the device first to make sure the device exists
+	dIntf, ok := va.DevicesDisc.Load(device)
+	if !ok {
+		return nil
+	}
+	d := dIntf.(*VoltDevice)
+
+	// If the port is NNI port, the services dont exist on it. The svc then
+	// must be obtained from a different context and is not included here
+	if port == d.NniPort {
+		return nil
+	}
+
+	//To return the matched service
+	var service *VoltService
+
+	// This is an access port and the port should have all the associated
+	// services which can be uniquely identified by the VLANs in the packet
+	vnets, ok := va.VnetsByPort.Load(port)
+
+	if !ok {
+		logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
+		return nil
+	}
+	logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
+	for _, vnet := range vnets.([]*VoltPortVnet) {
+		logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
+		switch vnet.VlanControl {
+		case ONUCVlanOLTSVlan:
+			service = vnet.MatchesPriority(priority)
+			if vnet.MatchesCvlan(vlans) && service != nil {
+				return service
+			}
+		case ONUCVlan,
+			None:
+			service = vnet.MatchesPriority(priority)
+			// In case of DHCP Flow - cvlan == VlanNone
+			// In case of HSIA Flow - cvlan == Svlan
+			if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
+				return service
+			}
+		case OLTCVlanOLTSVlan,
+			OLTSVlan:
+			service = vnet.MatchesPriority(priority)
+			if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
+				return service
+			}
+		default:
+			logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
+		}
+	}
+	return nil
+}
+
+// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
+// are used as the key to locate the service. If more than one service is on the
+// same port (essentially a UNI of ONU), the services must be separated by different
+// CVLANs
+func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
+	// Fetch the device first to make sure the device exists
+	dIntf, ok := va.DevicesDisc.Load(device)
+	if !ok {
+		return nil, nil
+	}
+	d := dIntf.(*VoltDevice)
+
+	// If the port is NNI port, the services dont exist on it. The svc then
+	// must be obtained from a different context and is not included here
+	if port == d.NniPort {
+		return nil, nil
+	}
+
+	//To return the matched service
+	var service *VoltService
+
+	// This is an access port and the port should have all the associated
+	// services which can be uniquely identified by the VLANs in the packet
+	if vnets, ok := va.VnetsByPort.Load(port); ok {
+		logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
+		for _, vnet := range vnets.([]*VoltPortVnet) {
+			logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
+			switch vnet.VlanControl {
+			case ONUCVlanOLTSVlan:
+				service = vnet.MatchesPriority(priority)
+				if vnet.MatchesCvlan(vlans) && service != nil {
+					return vnet, service
+				}
+			case ONUCVlan,
+				None:
+				service = vnet.MatchesPriority(priority)
+				if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
+					return vnet, service
+				}
+			case OLTCVlanOLTSVlan,
+				OLTSVlan:
+				service = vnet.MatchesPriority(priority)
+				if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
+					return vnet, service
+				}
+			default:
+				logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
+			}
+		}
+	}
+	return nil, nil
+}
+
+// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
+// are used as the key to locate the service. If more than one service is on the
+// same port (essentially a UNI of ONU), the services must be separated by different
+// CVLANs
+func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
+	vlans := GetVlans(pkt)
+	priority := GetPriority(pkt)
+	return va.GetVnetFromFields(device, port, vlans, priority)
+}
+
+// PushDevFlowForVlan to push icmpv6 flows for vlan
+func (va *VoltApplication) PushDevFlowForVlan(vnet *VoltVnet) {
+	logger.Infow(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+	pushflow := func(key interface{}, value interface{}) bool {
+		device := value.(*VoltDevice)
+		if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
+			logger.Info(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
+			return true
+		}
+		if device.State != controller.DeviceStateUP {
+			logger.Errorw(ctx, "Push Dev Flows Failed - Device state DOWN", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan, "device": device})
+			return true
+		}
+		if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
+			logger.Errorw(ctx, "Push Dev Flows Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
+			return true
+		}
+
+		if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
+			vnetList := vnetListIntf.(*util.ConcurrentMap)
+			vnetList.Set(vnet.Name, true)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+			logger.Infow(ctx, "Flow already pushed for these Vlans. Adding profile to list", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
+			return true
+		}
+		logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
+		err := ProcessIcmpv6McGroup(device.Name, false)
+		if err != nil {
+			logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
+			return true
+		}
+		if portID, err := va.GetPortID(device.NniPort); err == nil {
+			if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
+				logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
+				return true
+			}
+
+			//Pushing ICMPv6 Flow
+			flow := BuildICMPv6Flow(portID, vnet)
+			err = cntlr.GetController().AddFlows(device.NniPort, device.Name, flow)
+			if err != nil {
+				logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+				return true
+			}
+			logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
+
+			// Pushing ARP Flow
+			flow = BuildDSArpFlow(portID, vnet)
+			err = cntlr.GetController().AddFlows(device.NniPort, device.Name, flow)
+			if err != nil {
+				logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+				return true
+			}
+			logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
+
+			vnetList := util.NewConcurrentMap()
+			vnetList.Set(vnet.Name, true)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+		}
+		return true
+	}
+	va.DevicesDisc.Range(pushflow)
+}
+
+// PushDevFlowForDevice to push icmpv6 flows for device
+func (va *VoltApplication) PushDevFlowForDevice(device *VoltDevice) {
+	logger.Infow(ctx, "PushDevFlowForDevice", log.Fields{"device": device})
+
+	logger.Debugw(ctx, "Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
+	err := ProcessIcmpv6McGroup(device.Name, false)
+	if err != nil {
+		logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
+		return
+	}
+	pushicmpv6 := func(key, value interface{}) bool {
+		vnet := value.(*VoltVnet)
+		if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
+			vnetList := vnetListIntf.(*util.ConcurrentMap)
+			vnetList.Set(vnet.Name, true)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+			logger.Infow(ctx, "Flow already pushed for these Vlans. Adding profile to list", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
+			return true
+		}
+		nniPortID, err := va.GetPortID(device.NniPort)
+		if err != nil {
+			logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
+		}
+		if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
+			logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
+			return true
+		}
+		flow := BuildICMPv6Flow(nniPortID, vnet)
+		err = cntlr.GetController().AddFlows(device.NniPort, device.Name, flow)
+		if err != nil {
+			logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+			return true
+		}
+		logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
+
+		flow = BuildDSArpFlow(nniPortID, vnet)
+		err = cntlr.GetController().AddFlows(device.NniPort, device.Name, flow)
+		if err != nil {
+			logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+			return true
+		}
+		logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
+
+		vnetList := util.NewConcurrentMap()
+		vnetList.Set(vnet.Name, true)
+		device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+		return true
+	}
+	va.VnetsByName.Range(pushicmpv6)
+}
+
+// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
+func (va *VoltApplication) DeleteDevFlowForVlan(vnet *VoltVnet) {
+	logger.Infow(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+	delflows := func(key interface{}, value interface{}) bool {
+		device := value.(*VoltDevice)
+
+		if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
+			vnetList := vnetListIntf.(*util.ConcurrentMap)
+			vnetList.Remove(vnet.Name)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+			if vnetList.Length() != 0 {
+				logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
+				return true
+			}
+		}
+		if portID, err := va.GetPortID(device.NniPort); err == nil {
+			if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
+				logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
+				return true
+			}
+			//Pushing ICMPv6 Flow
+			flow := BuildICMPv6Flow(portID, vnet)
+			flow.ForceAction = true
+			err := vnet.RemoveFlows(device, flow)
+			if err != nil {
+				logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+				return true
+			}
+			logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
+
+			//Pushing ARP Flow
+			flow = BuildDSArpFlow(portID, vnet)
+			flow.ForceAction = true
+			err = vnet.RemoveFlows(device, flow)
+			if err != nil {
+				logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+				return true
+			}
+			logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
+
+			device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
+		}
+		return true
+	}
+	va.DevicesDisc.Range(delflows)
+}
+
+// DeleteDevFlowForDevice to delete icmpv6 flow for device
+func (va *VoltApplication) DeleteDevFlowForDevice(device *VoltDevice) {
+	logger.Infow(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
+	delicmpv6 := func(key, value interface{}) bool {
+		vnet := value.(*VoltVnet)
+		if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
+			vnetList := vnetListIntf.(*util.ConcurrentMap)
+			vnetList.Remove(vnet.Name)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+			if vnetList.Length() != 0 {
+				logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
+				return true
+			}
+		} else {
+			logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
+			return true
+		}
+		nniPortID, err := va.GetPortID(device.NniPort)
+		if err != nil {
+			logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
+		}
+		flow := BuildICMPv6Flow(nniPortID, vnet)
+		flow.ForceAction = true
+		err = vnet.RemoveFlows(device, flow)
+		if err != nil {
+			logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+			return true
+		}
+
+		flow = BuildDSArpFlow(nniPortID, vnet)
+		flow.ForceAction = true
+		err = vnet.RemoveFlows(device, flow)
+		if err != nil {
+			logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
+			return true
+		}
+
+		device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
+		logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
+		return true
+	}
+	va.VnetsByName.Range(delicmpv6)
+	logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
+	err := ProcessIcmpv6McGroup(device.Name, true)
+	if err != nil {
+		logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
+		return
+	}
+}
+
+// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
+func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(vnet *VoltVnet, deviceSerialNum string) {
+	logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+	delflows := func(key interface{}, value interface{}) bool {
+		device := value.(*VoltDevice)
+		if device.SerialNum != deviceSerialNum {
+			return true
+		}
+		if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
+			vnetList := vnetListIntf.(*util.ConcurrentMap)
+			vnetList.Remove(vnet.Name)
+			device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
+			if vnetList.Length() != 0 {
+				logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
+				return true
+			}
+		} else if !vgcRebooted && len(vnet.DevicesList) != 0 {
+			// Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
+			// DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
+			// The step will be as follow:
+			// 1. Deact Service
+			// 2. Pod Reboot
+			// 3. Pending Delete Service triggered
+			// 4. Del Service Ind followed by DelVnet req from NB
+			// 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
+			// hence the flow will not be cleared
+			logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
+			return true
+		}
+		if portID, err := va.GetPortID(device.NniPort); err == nil {
+			if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
+				logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
+				return false
+			}
+			flow := BuildICMPv6Flow(portID, vnet)
+			flow.ForceAction = true
+			if err := vnet.RemoveFlows(device, flow); err != nil {
+				logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
+			}
+			logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
+
+			flow = BuildDSArpFlow(portID, vnet)
+			flow.ForceAction = true
+			if err := vnet.RemoveFlows(device, flow); err != nil {
+				logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
+			}
+			logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
+			device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
+		}
+		return false
+	}
+	va.DevicesDisc.Range(delflows)
+}
+
+// BuildICMPv6Flow to Build DS flow for ICMPv6
+func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
+	logger.Info(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+
+	subFlow.SetICMPv6Match()
+	subFlow.SetMatchVlan(vnet.SVlan)
+	subFlow.SetInPort(inport)
+	subFlow.SetPopVlan()
+	subFlow.SetOutGroup(ICMPv6ArpGroupID)
+	subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
+	subFlow.Priority = of.McFlowPriority
+	var metadata uint64
+	if vnet.VlanControl == None {
+		metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
+	} else {
+		metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
+	}
+	subFlow.SetTableMetadata(metadata)
+	metadata = uint64(vnet.setPbitRemarking())
+
+	logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
+	subFlow.SetWriteMetadata(metadata)
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	return flow
+}
+
+//BuildDSArpFlow Builds DS flow for ARP
+func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
+	logger.Info(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
+
+	flow := &of.VoltFlow{}
+	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+	subFlow := of.NewVoltSubFlow()
+
+	BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
+	subFlow.SetArpMatch()
+	subFlow.SetMatchDstMac(BcastMAC)
+	subFlow.SetMatchVlan(vnet.SVlan)
+	subFlow.SetInPort(inport)
+	subFlow.SetPopVlan()
+	subFlow.SetOutGroup(ICMPv6ArpGroupID)
+
+	subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
+	subFlow.Priority = of.McFlowPriority
+
+	var metadata uint64
+	if vnet.VlanControl == None {
+		metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
+	} else {
+		metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
+	}
+	subFlow.SetTableMetadata(metadata)
+	metadata = uint64(vnet.setPbitRemarking())
+	subFlow.SetWriteMetadata(metadata)
+
+	flow.SubFlows[subFlow.Cookie] = subFlow
+	logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
+	return flow
+}
+
+// setPbitRemarking to set Pbit remarking
+func (vv *VoltVnet) setPbitRemarking() uint32 {
+
+	// 	                              Remarkable
+	// 	         Remarked Pbit          Pbit
+	// |-----------------------------| |------|
+	// |7| |6| |5| |4| |3| |2| |1| |0| 76543210
+	// 000 000 000 000 000 000 000 000 00000000
+
+	// Eg:
+	// For 6:3 & 7:1
+	// 001 011 000 000 000 000 000 000 11000000
+
+	var remarkable uint8
+	var remarked uint32
+	for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
+		remarkable = remarkable | 1<<refPbit
+		remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
+	}
+	return remarked<<8 | uint32(remarkable)
+}
+
+// ProcessIcmpv6McGroup to add icmpv6 multicast group
+func ProcessIcmpv6McGroup(device string, delete bool) error {
+
+	logger.Info(ctx, "Creating ICMPv6 MC Group")
+	va := GetApplication()
+	vd := va.GetDevice(device)
+	group := &of.Group{}
+	group.GroupID = ICMPv6ArpGroupID
+	group.Device = device
+	if delete {
+		if !vd.icmpv6GroupAdded {
+			logger.Info(ctx, "ICMPv6 MC Group is already deleted. Ignoring  icmpv6 group Delete")
+			return nil //TODO
+		}
+		vd.icmpv6GroupAdded = false
+		group.Command = of.GroupCommandDel
+		group.ForceAction = true
+	} else {
+		if vd.icmpv6GroupAdded {
+			logger.Info(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
+			return nil //TODO
+		}
+		vd.icmpv6GroupAdded = true
+		group.Command = of.GroupCommandAdd
+		receivers := GetApplication().GetIcmpv6Receivers(device)
+		group.Buckets = append(group.Buckets, receivers...)
+	}
+	logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
+	port, _ := GetApplication().GetNniPort(device)
+	err := cntlr.GetController().GroupUpdate(port, device, group)
+	return err
+}
+
+//isVlanMatching - checks is vlans matches with vpv based on vlan control
+func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
+
+	switch vpv.VlanControl {
+	case ONUCVlanOLTSVlan,
+		OLTCVlanOLTSVlan:
+		if vpv.SVlan == svlan && vpv.CVlan == cvlan {
+			return true
+		}
+	case ONUCVlan,
+		OLTSVlan,
+		None:
+		if vpv.SVlan == svlan {
+			return true
+		}
+	default:
+		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
+	}
+	return false
+}
+
+//PushFlows - Triggers flow addition after registering for flow indication event
+func (vpv *VoltPortVnet) PushFlows(device *VoltDevice, flow *of.VoltFlow) error {
+
+	for cookie := range flow.SubFlows {
+		cookie := strconv.FormatUint(cookie, 10)
+		fe := &FlowEvent{
+			eType:     EventTypeControlFlowAdded,
+			cookie:    cookie,
+			eventData: vpv,
+		}
+		device.RegisterFlowAddEvent(cookie, fe)
+	}
+	return cntlr.GetController().AddFlows(vpv.Port, device.Name, flow)
+}
+
+//FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
+func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
+
+	sendFlowFailureInd := func(key, value interface{}) bool {
+		//svc := value.(*VoltService)
+		//TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
+		return true
+	}
+	logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
+	vpv.services.Range(sendFlowFailureInd)
+}
+
+//RemoveFlows - Triggers flow deletion after registering for flow indication event
+func (vpv *VoltPortVnet) RemoveFlows(device *VoltDevice, flow *of.VoltFlow) error {
+
+	vpv.PendingFlowLock.Lock()
+	defer vpv.PendingFlowLock.Unlock()
+
+	for cookie := range flow.SubFlows {
+		cookie := strconv.FormatUint(cookie, 10)
+		fe := &FlowEvent{
+			eType:     EventTypeControlFlowRemoved,
+			device:    device.Name,
+			cookie:    cookie,
+			eventData: vpv,
+		}
+		device.RegisterFlowDelEvent(cookie, fe)
+		vpv.PendingDeleteFlow[cookie] = true
+	}
+	return cntlr.GetController().DelFlows(vpv.Port, device.Name, flow)
+}
+
+//CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
+func (vpv *VoltPortVnet) CheckAndDeleteVpv() {
+	vpv.PendingFlowLock.RLock()
+	defer vpv.PendingFlowLock.RUnlock()
+	if !vpv.DeleteInProgress {
+		return
+	}
+	if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
+		logger.Infow(ctx, "All Flows removed for VPV. Triggering VPV Deletion from DB", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
+		vpv.DelFromDb()
+		logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
+	}
+}
+
+//FlowRemoveSuccess - Process flow success indication
+func (vpv *VoltPortVnet) FlowRemoveSuccess(cookie string, device string) {
+	vpv.PendingFlowLock.Lock()
+	logger.Infow(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
+
+	delete(vpv.PendingDeleteFlow, cookie)
+	vpv.PendingFlowLock.Unlock()
+	vpv.CheckAndDeleteVpv()
+	vpv.WriteToDb()
+}
+
+//FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
+func (vpv *VoltPortVnet) FlowRemoveFailure(cookie string, device string, errorCode uint32, errReason string) {
+	vpv.PendingFlowLock.Lock()
+
+	logger.Errorw(ctx, "VPV Flow Remove Failure Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
+
+	sendFlowFailureInd := func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		svc.triggerServiceFailureInd(errorCode, errReason)
+		return true
+	}
+	logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
+	vpv.services.Range(sendFlowFailureInd)
+
+	if vpv.DeleteInProgress {
+		delete(vpv.PendingDeleteFlow, cookie)
+		vpv.PendingFlowLock.Unlock()
+		vpv.CheckAndDeleteVpv()
+	} else {
+		vpv.PendingFlowLock.Unlock()
+		vpv.WriteToDb()
+	}
+}
+
+//RemoveFlows - Triggers flow deletion after registering for flow indication event
+func (vv *VoltVnet) RemoveFlows(device *VoltDevice, flow *of.VoltFlow) error {
+
+	vv.VnetLock.Lock()
+	defer vv.VnetLock.Unlock()
+
+	var flowMap map[string]bool
+	var ok bool
+
+	for cookie := range flow.SubFlows {
+		cookie := strconv.FormatUint(cookie, 10)
+		fe := &FlowEvent{
+			eType:     EventTypeDeviceFlowRemoved,
+			device:    device.Name,
+			cookie:    cookie,
+			eventData: vv,
+		}
+		device.RegisterFlowDelEvent(cookie, fe)
+		if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
+			flowMap = make(map[string]bool)
+		}
+		flowMap[cookie] = true
+		vv.PendingDeleteFlow[device.Name] = flowMap
+	}
+	vv.WriteToDb()
+	return cntlr.GetController().DelFlows(device.NniPort, device.Name, flow)
+}
+
+//CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
+func (vv *VoltVnet) CheckAndDeleteVnet(device string) {
+	if !vv.DeleteInProgress {
+		return
+	}
+	vv.VnetPortLock.RLock()
+	if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
+		logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
+		GetApplication().deleteVnetConfig(vv)
+		_ = db.DelVnet(vv.Name)
+		logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
+	} else {
+		logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
+	}
+	vv.VnetPortLock.RUnlock()
+}
+
+//FlowRemoveSuccess - Process flow success indication
+func (vv *VoltVnet) FlowRemoveSuccess(cookie string, device string) {
+	vv.VnetLock.Lock()
+	defer vv.VnetLock.Unlock()
+
+	logger.Infow(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
+
+	if _, ok := vv.PendingDeleteFlow[device]; ok {
+		delete(vv.PendingDeleteFlow[device], cookie)
+	}
+
+	//Check and update success for pending disable request
+	if d := GetApplication().GetDevice(device); d != nil {
+		_, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
+		if !present && len(vv.PendingDeleteFlow[device]) == 0 {
+			vv.CheckAndDeleteVnet(device)
+		}
+	}
+	vv.WriteToDb()
+}
+
+//FlowRemoveFailure - Process flow failure indication
+func (vv *VoltVnet) FlowRemoveFailure(cookie string, device string, errorCode uint32, errReason string) {
+
+	vv.VnetLock.Lock()
+	defer vv.VnetLock.Unlock()
+
+	if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
+		if _, ok := flowMap[cookie]; ok {
+			logger.Errorw(ctx, "Device Flow Remove Failure Notification", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
+
+			if vv.DeleteInProgress {
+				delete(vv.PendingDeleteFlow[device], cookie)
+				vv.CheckAndDeleteVnet(device)
+			}
+			return
+		}
+	}
+	logger.Errorw(ctx, "Device Flow Remove Failure Notification for Unknown cookie", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
+}
+
+//IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
+func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
+
+	//Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
+	//When multiple Igmp-suported service enabled, comment "return false"
+
+	sendFlowFailureInd := func(key, value interface{}) bool {
+		svc := value.(*VoltService)
+		if svc.IgmpEnabled {
+			svc.triggerServiceFailureInd(errorCode, errReason)
+			return false
+		}
+		return true
+	}
+	logger.Errorw(ctx, "US IGMP Flow Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
+	vpv.services.Range(sendFlowFailureInd)
+}
+
+// GetMatchingMcastService to get matching multicast service
+func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
+
+	var service *VoltService
+	dIntf, ok := va.DevicesDisc.Load(device)
+	if !ok {
+		return nil
+	}
+	d := dIntf.(*VoltDevice)
+
+	// If the port is NNI port, the services dont exist on it. The svc then
+	// must be obtained from a different context and is not included here
+	if port == d.NniPort {
+		return nil
+	}
+
+	// This is an access port and the port should have all the associated
+	// services which can be uniquely identified by the VLANs in the packet
+	vnets, ok := va.VnetsByPort.Load(port)
+
+	if !ok {
+		logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
+		return nil
+	}
+	logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
+	getMcastService := func(key, value interface{}) bool {
+		srv := value.(*VoltService)
+		if srv.IgmpEnabled {
+			service = srv
+
+			//TODO: Current implementation supports only for single service with Igmp Enabled
+			//FIX-ME:  When multiple service suports Igmp, update of logic required
+			return false
+		}
+		return true
+	}
+
+	for _, vpv := range vnets.([]*VoltPortVnet) {
+		if vpv.CVlan == cvlan {
+			vpv.services.Range(getMcastService)
+			if service != nil {
+				break
+			}
+		}
+	}
+	return service
+}
+
+//TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
+func (vv *VoltVnet) TriggerAssociatedFlowDelete(device string) bool {
+	vv.VnetLock.Lock()
+	cookieList := []uint64{}
+	flowMap := vv.PendingDeleteFlow[device]
+
+	for cookie := range flowMap {
+		cookieList = append(cookieList, convertToUInt64(cookie))
+	}
+	vv.VnetLock.Unlock()
+
+	if len(cookieList) == 0 {
+		return false
+	}
+
+	for _, cookie := range cookieList {
+		if vd := GetApplication().GetDevice(device); vd != nil {
+			flow := &of.VoltFlow{}
+			flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
+			subFlow := of.NewVoltSubFlow()
+			subFlow.Cookie = cookie
+			flow.SubFlows[cookie] = subFlow
+			logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
+			if err := vv.RemoveFlows(vd, flow); err != nil {
+				logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
+			}
+		}
+	}
+	return true
+}
