/*
* 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 (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"reflect"
	"strconv"
	"sync"
	"time"

	//errorCodes "voltha-go-controller/internal/pkg/errorcodes"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"go.uber.org/atomic"

	"voltha-go-controller/database"
	"voltha-go-controller/internal/pkg/controller"

	errorCodes "voltha-go-controller/internal/pkg/errorcodes"
	"voltha-go-controller/internal/pkg/of"
	"voltha-go-controller/internal/pkg/util"
	"voltha-go-controller/log"
)

const (
	// ICMPv6ArpGroupID constant
	ICMPv6ArpGroupID uint32 = 1

	// Radisys vendor id constant
	Radisys string = "Radisys"

	// DPU_MGMT_TRAFFIC serviceType, vnetType constant
	DpuMgmtTraffic string = "DPU_MGMT_TRAFFIC"

	// DPU_ANCP_TRAFFIC serviceType, vnetType constant
	DpuAncpTraffic string = "DPU_ANCP_TRAFFIC"

	// FTTB_SUBSCRIBER_TRAFFIC serviceType, vnetType constant
	FttbSubscriberTraffic string = "FTTB_SUBSCRIBER_TRAFFIC"
)

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 {
	CtrlPktPbitRemark          map[of.PbitType]of.PbitType
	Name                       string
	VnetType                   string
	Encapsulation              string
	DevicesList                []string //List of serial number of devices on which this vnet is applied
	UsDhcpPbit                 []of.PbitType
	DsDhcpPbit                 []of.PbitType
	UsIGMPPbit                 []of.PbitType
	DsIGMPPbit                 []of.PbitType
	ONTEtherTypeClassification int
	MacLearning                MacLearningType
	UsPonCTagPriority          of.PbitType
	UsPonSTagPriority          of.PbitType
	DsPonCTagPriority          of.PbitType
	DsPonSTagPriority          of.PbitType
	SVlan                      of.VlanType
	CVlan                      of.VlanType
	UniVlan                    of.VlanType
	SVlanTpid                  layers.EthernetType
	VlanControl                VlanControl
	DhcpRelay                  bool
	ArpLearning                bool
	AllowTransparent           bool
	PppoeIa                    bool
}

// VnetOper structure
type VnetOper struct {
	PendingDeleteFlow     map[string]map[string]bool
	AssociatedPorts       map[string]bool `json:"-"`
	PendingDeviceToDelete string
	VnetLock              sync.RWMutex `json:"-"`
	VnetPortLock          sync.RWMutex `json:"-"`
	DeleteInProgress      bool
}

// VoltVnet sructure
type VoltVnet struct {
	Version string
	VnetConfig
	VnetOper
}

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(cntx context.Context, device string, port string) {
	logger.Infow(ctx, "Disassociate Port from Vnet", log.Fields{"Device": device, "Port": port})
	vv.VnetPortLock.Lock()
	delete(vv.AssociatedPorts, port)
	logger.Debugw(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.Debugw(ctx, "Deleting Vnet", log.Fields{"Name": vv.Name})
				GetApplication().deleteVnetConfig(vv)
				_ = db.DelVnet(cntx, 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(cntx context.Context) {
	if vv.DeleteInProgress {
		logger.Warnw(ctx, "Skipping Redis Update for Vnet, Vnet delete in progress", log.Fields{"Vnet": vv.Name, "SVlan": vv.SVlan})
		return
	}
	vv.ForceWriteToDb(cntx)
}

// ForceWriteToDb force commit a vnet to the DB
func (vv *VoltVnet) ForceWriteToDb(cntx context.Context) {
	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(cntx, vv.Name, string(b)); err != nil {
			logger.Warnw(ctx, "Add Vnet to DB failed", log.Fields{"Vnet": vv.Name, "SVlan": vv.SVlan, "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.
	logger.Debugw(ctx, "Get Vnet configuration", log.Fields{"SVlan": otag, "CVlan": itag, "UniVlan": utag})
	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 {
	logger.Debugw(ctx, "Get Vnet by Name", log.Fields{"Name": name})
	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) {
	logger.Debugw(ctx, "Store Vnet config", log.Fields{"Name": cfg.Name})
	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) {
	logger.Debugw(ctx, "Delete Vnet config", log.Fields{"Name": vnet.Name})
	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(cntx context.Context, cfg VnetConfig, oper *VnetOper) error {
	logger.Debugw(ctx, "Add Vnet config", log.Fields{"Name": cfg.Name})
	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.Infow(ctx, "Add Vnet : Profile Name already exists with OLT, update-the-profile", log.Fields{"SerialNum": serialNum})
				continue
			}
			devicesToHandle = append(devicesToHandle, serialNum)
		}
		if len(devicesToHandle) == 0 {
			logger.Warnw(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(cntx)

	logger.Debugw(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(cntx context.Context, name, deviceSerialNum string) error {
	logger.Debugw(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(cntx, vnet, deviceSerialNum)
		if len(vnet.DevicesList) == 0 {
			vnet.DeleteInProgress = true
			vnet.PendingDeviceToDelete = deviceSerialNum
			vnet.ForceWriteToDb(cntx)
			vnet.VnetPortLock.RLock()
			if len(vnet.PendingDeleteFlow) == 0 && !vnet.isAssociatedPortsPresent() {
				logger.Debugw(ctx, "Deleting Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
				va.deleteVnetConfig(vnet)
				_ = db.DelVnet(cntx, 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(cntx)
		}
	}
	// 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(cntx context.Context, vv *VoltVnet) error {
	va.storeVnetConfig(vv.VnetConfig, vv)
	vv.WriteToDb(cntx)
	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 {
	PendingDeleteFlow          map[string]bool
	servicesCount              *atomic.Uint64
	services                   sync.Map
	Device                     string
	Port                       string
	VnetName                   string
	VnetType                   string
	MvlanProfileName           string
	Version                    string
	DhcpExpiryTime             time.Time
	Dhcp6ExpiryTime            time.Time
	Ipv4Addr                   net.IP
	Ipv6Addr                   net.IP
	MacAddr                    net.HardwareAddr
	LearntMacAddr              net.HardwareAddr
	CircuitID                  []byte       //Will not be used
	RemoteID                   []byte       //Will not be used
	VpvLock                    sync.Mutex   `json:"-"`
	PendingFlowLock            sync.RWMutex `json:"-"`
	SchedID                    int
	ONTEtherTypeClassification int
	MacLearning                MacLearningType
	PonPort                    uint32
	McastUsMeterID             uint32
	McastTechProfileID         uint16
	McastPbit                  of.PbitType
	SVlanTpid                  layers.EthernetType
	DhcpPbit                   of.PbitType
	UsPonCTagPriority          of.PbitType
	UsPonSTagPriority          of.PbitType
	DsPonCTagPriority          of.PbitType
	DsPonSTagPriority          of.PbitType
	SVlan                      of.VlanType
	CVlan                      of.VlanType
	UniVlan                    of.VlanType
	VlanControl                VlanControl
	RelayState                 DhcpRelayState
	DhcpStatus                 DhcpStatus
	PPPoeState                 PppoeIaState
	RelayStatev6               Dhcpv6RelayState
	DHCPv6DUID                 [MaxLenDhcpv6DUID]byte
	DhcpRelay                  bool
	ArpRelay                   bool
	PppoeIa                    bool
	DeleteInProgress           bool
	Blocked                    bool
	AllowTransparent           bool
	IgmpEnabled                bool
	IgmpFlowsApplied           bool
	McastService               bool
	FlowsApplied               bool
	IsOption82Enabled          bool //Will not be used
}

// 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")
	vpv.servicesCount = atomic.NewUint64(0)
	vpv.SchedID = 0
	vpv.PendingDeleteFlow = make(map[string]bool)
	vpv.DhcpPbit = vnet.UsDhcpPbit[0]
	vpv.UsPonCTagPriority = vnet.UsPonCTagPriority
	vpv.UsPonSTagPriority = vnet.UsPonSTagPriority
	vpv.DsPonCTagPriority = vnet.UsPonCTagPriority
	vpv.DsPonSTagPriority = vnet.UsPonSTagPriority

	vpv.VnetType = vnet.VnetType
	return &vpv
}

func (vpv *VoltPortVnet) setDevice(device string) {
	logger.Debugw(ctx, "Set Device", log.Fields{"Device": device})
	if vpv.Device != device && vpv.Device != "" {
		GetApplication().DisassociateVpvsFromDevice(device, vpv)
		// TEMP:
		vpv.printAssociatedVPVs(false)
	}

	logger.Infow(ctx, "Associating VPV and Device", log.Fields{"Device": 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) {
	if vMap := GetApplication().GetAssociatedVpvsForDevice(vpv.Device, vpv.SVlan); vMap != nil {
		vMap.Range(func(key, value interface{}) bool {
			vpvEntry := key.(*VoltPortVnet)
			logger.Debugw(ctx, "Associated VPVs", log.Fields{"Device": vpv.Device, "Add": add, "SVlan": vpvEntry.SVlan, "CVlan": vpvEntry.CVlan, "UniVlan": vpvEntry.UniVlan})
			return true
		})
	}
}

// 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(cntx context.Context, res *layers.DHCPv4) {
	vpv.ProcessDhcpResult(cntx, res)
}

// Dhcpv6ResultInd for dhcpv6 result indication
func (vpv *VoltPortVnet) Dhcpv6ResultInd(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
	vpv.ProcessDhcpv6Result(cntx, ipv6Addr, leaseTime)
}

// GetNniVlans to get nni vlans
func (vpv *VoltPortVnet) GetNniVlans() (uint16, uint16) {
	logger.Debugw(ctx, "Get Nni Vlans", log.Fields{"vpv.VlanControl": vpv.VlanControl})
	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) {
	logger.Debugw(ctx, "Get Service", log.Fields{"name": name})
	service, ok := vpv.services.Load(name)
	if ok {
		return service.(*VoltService), ok
	}
	return nil, ok
}

// AddService to add service
func (vpv *VoltPortVnet) AddService(cntx context.Context, service *VoltService) {
	logger.Debugw(ctx, "Add Service", log.Fields{"ServiceName": service.Name})
	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(cntx context.Context, service *VoltService) {
	logger.Debugw(ctx, "Delete Service", log.Fields{"ServiceName": service.Name})
	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(cntx); err != nil {
			statusCode, statusMessage := errorCodes.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(cntx context.Context, res *layers.DHCPv4) {
	logger.Debug(ctx, "Process Dhcp Result")
	msgType := DhcpMsgType(res)
	switch msgType {
	case layers.DHCPMsgTypeAck:
		vpv.ProcessDhcpSuccess(cntx, res)
	case layers.DHCPMsgTypeNak:
		vpv.DhcpStatus = DhcpStatusNacked
	}
	vpv.WriteToDb(cntx)
}

// RangeOnServices to call a function on all services on the vpv
func (vpv *VoltPortVnet) RangeOnServices(cntx context.Context, callback func(cntx context.Context, key, value interface{}, flag bool) bool, flag bool) {
	vpv.services.Range(func(key, value interface{}) bool {
		return callback(cntx, key, value, flag)
	})
}

// 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(cntx context.Context, res *layers.DHCPv4) {
	logger.Info(ctx, "Process Dhcp Success")
	vpv.DhcpStatus = DhcpStatusAcked
	vpv.Ipv4Addr, _ = GetIpv4Addr(res)
	logger.Debugw(ctx, "Received IPv4 Address and Services Configured", log.Fields{"IP Address": vpv.Ipv4Addr.String(), "Count": vpv.servicesCount.Load()})

	vpv.RangeOnServices(cntx, vpv.updateIPv4AndProvisionFlows, false)
	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) {
	logger.Debug(ctx, "Process Dhcp v4 Options")
	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.Debugw(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(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
	logger.Debugw(ctx, "Process Dhcp v6 Result", log.Fields{"ipv6Addr": ipv6Addr, "leaseTime": leaseTime})
	// TODO: Status based hanlding of flows
	vpv.Dhcp6ExpiryTime = time.Now().Add((time.Duration(leaseTime) * time.Second))
	vpv.Ipv6Addr = ipv6Addr

	vpv.RangeOnServices(cntx, vpv.updateIPv6AndProvisionFlows, false)
	vpv.WriteToDb(cntx)
}

// AddSvcUsMeterToDevice to add service upstream meter info to device
func AddSvcUsMeterToDevice(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(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.Warnw(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(cntx context.Context, d *VoltDevice) {
	logger.Debugw(ctx, "Push Flows For Port Vnet", log.Fields{"Port": vpv.Port})
	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
	}

	//Disable the flag so that flows can be pushed again
	// vpv.IgmpFlowsApplied = false
	// vpv.DsFlowsApplied = false
	// vpv.UsFlowsApplied = false
	vpv.VpvLock.Lock()
	vpv.PortUpInd(cntx, d, vpv.Port, "", false)
	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(cntx context.Context, device *VoltDevice, port string, nniPort string, skipFlowPushToVoltha bool) {
	logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "nniPort": nniPort, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
	if vpv.DeleteInProgress {
		logger.Warnw(ctx, "Ignoring VPV Port UP Ind, VPV deletion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
		return
	}
	vpv.setDevice(device.Name)

	if nniPort != "" {
		err := vpv.ValidateNniPort(device, nniPort)
		if err != nil {
			logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is not configured", log.Fields{"Port": vpv.Port, "Device": device.Name, "NNI": nniPort, "Error": err})
			return
		}
	} else {
		nni, err := GetApplication().GetNniPort(device.Name)
		if nni == "" {
			logger.Warnw(ctx, "Ignoring Vnet Port UP indication: Default NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name, "Error": err})
			return
		}
	}

	if vpv.Blocked {
		logger.Warnw(ctx, "VPV Blocked 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 and DPU_MGMT Service
		if !vpv.McastService && vpv.VnetType != DpuMgmtTraffic {
			vpv.RangeOnServices(cntx, AddUsHsiaFlows, skipFlowPushToVoltha)
		}
		if vpv.VnetType == DpuMgmtTraffic {
			vpv.RangeOnServices(cntx, AddMeterToDevice, skipFlowPushToVoltha)
		}
		vpv.AddTrapFlows(cntx)
		if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
			logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
			/*In case of DPU_MGMT_TRAFFIC, need to install both US and DS traffic */
			if vpv.VnetType == DpuMgmtTraffic {
				vpv.RangeOnServices(cntx, AddUsHsiaFlows, skipFlowPushToVoltha)
			}
			// 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.RangeOnServices(cntx, AddDsHsiaFlows, skipFlowPushToVoltha)
			}
		}
	} 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.Debugw(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
		if !vpv.McastService {
			vpv.RangeOnServices(cntx, AddUsHsiaFlows, skipFlowPushToVoltha)
		}
		vpv.AddTrapFlows(cntx)
		if !vpv.McastService {
			vpv.RangeOnServices(cntx, AddDsHsiaFlows, skipFlowPushToVoltha)
		}
	}

	// Process IGMP proxy - install IGMP trap rules before DHCP trap rules
	if vpv.IgmpEnabled {
		logger.Debugw(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
		vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice, skipFlowPushToVoltha)
		if err := vpv.AddIgmpFlows(cntx); err != nil {
			statusCode, statusMessage := errorCodes.GetErrorInfo(err)
			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
		}

		if vpv.McastService {
			vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd, skipFlowPushToVoltha)
		}
	}

	vpv.WriteToDb(cntx)
}

// 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
// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool, delFlowsInDevice bool) {
	if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
		logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
		return
	}
	logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
		log.Fields{"service count": vpv.servicesCount.Load(), "Port": port})

	//vpv.RangeOnServices(cntx, DelAllFlows)
	vpv.DelTrapFlows(cntx)
	vpv.DelHsiaFlows(cntx, delFlowsInDevice)
	vpv.WriteToDb(cntx)
	vpv.ClearServiceCounters(cntx)
}

// 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(cntx context.Context, addr net.HardwareAddr) {
	logger.Infow(ctx, "Set Mac Addr", log.Fields{"MAC addr": addr.String(), "Port": vpv.Port})
	//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.Warnw(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.RangeOnServices(cntx, DelUsHsiaFlows, false)
			vpv.MacAddr = addr
			vpv.RangeOnServices(cntx, vpv.setLearntMAC, false)
			vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
			vpv.RangeOnServices(cntx, DelDsHsiaFlows, false)
			GetApplication().DeleteMacInPortMap(vpv.MacAddr)
		} else {
			vpv.MacAddr = addr
			vpv.RangeOnServices(cntx, vpv.setLearntMAC, false)
			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.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
		statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
		return
	}
	// Ds Hsia flows has to be pushed
	if vpv.FlowsApplied {
		// In case of DPU_MGMT_TRAFFIC install both US and DS Flows
		if vpv.VnetType == DpuMgmtTraffic {
			vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
		}
		// no HSIA flows for multicast service
		if !vpv.McastService {
			vpv.RangeOnServices(cntx, AddDsHsiaFlows, false)
		}
	}
	vpv.WriteToDb(cntx)
}

// 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 {
	logger.Debugw(ctx, "Matches Vlans", log.Fields{"Svlan": svlan, "Cvlan": cvlan, "Univlan": univlan})
	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 {
	logger.Debugw(ctx, "Matches Cvlans", log.Fields{"Cvlan": cvlan})
	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 {
	logger.Debugw(ctx, "Matches Priority", log.Fields{"Priority": priority})
	var service *VoltService
	pbitFound := false
	matchpbitsFunc := func(key, value interface{}) bool {
		svc := value.(*VoltService)
		for _, pbit := range svc.Pbits {
			if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
				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
}

func (vpv *VoltPortVnet) GetSvcFromVPV() *VoltService {
	var service *VoltService
	vpv.services.Range(func(key, value interface{}) bool {
		service = value.(*VoltService)
		logger.Debugw(ctx, "Get Service from VPV", log.Fields{"Service": value})
		return false
	})
	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 {
	logger.Debugw(ctx, "Get Remarked Priority", log.Fields{"Priority": priority})
	dsPbit := uint8(0)
	matchpbitsFunc := func(key, value interface{}) bool {
		svc := value.(*VoltService)
		if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
			logger.Warnw(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
}

func (vpv *VoltPortVnet) ValidateNniPort(device *VoltDevice, nniPortName string) error {
	devConfig := GetApplication().GetDeviceConfig(device.SerialNum)
	if devConfig == nil {
		return fmt.Errorf("device config not found for serial number %s", device.SerialNum)
	}

	var nniPort string
	var nniPortID uint32
	if nniPortID = device.GetPortIDFromPortName(nniPortName); nniPortID == 0 {
		logger.Errorw(ctx, "Port Not Found", log.Fields{"NNI Port": nniPortName})
		return errors.New("port not found for service")
	}
	if !device.IsPortNni(nniPortName) {
		logger.Errorw(ctx, "Port Not Found in device", log.Fields{"NNI Port": nniPortName})
		return fmt.Errorf("port not found in device")
	}

	nniPort = strconv.Itoa(int(nniPortID))
	if len(devConfig.NniPorts) > 0 {
		for _, port := range devConfig.NniPorts {
			if port == nniPort {
				logger.Debugw(ctx, "NNI port is configured from NB", log.Fields{"NB NniPorts": devConfig.NniPorts, "NniPort": nniPortName})
				return nil // Match found
			}
		}
	} else {
		if devConfig.UplinkPort == nniPort {
			logger.Debugw(ctx, "NNI port is configured as default from NB", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI Ports": device.NniPort})
			return nil // Match found
		}
	}
	return fmt.Errorf("nni port mismatch: NB NNI Port: %s, SB NNI Ports: %v", devConfig.UplinkPort, device.NniPort)
}

// AddSvc adds a service on the VNET on a port. The addition is
// triggered when NB requests for service addition
func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
	logger.Debugw(ctx, "Add Service to VPV", log.Fields{"ServiceName": svc.Name})
	//vpv.services = append(vpv.services, svc)
	vpv.AddService(cntx, 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
	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})
		}
	}

	voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
	if err != nil {
		logger.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
		// statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		// TODO-COMM: 		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
		return
	}
	if !svc.IsActivated {
		logger.Warnw(ctx, "Not pushing Service Flows: Service Not activated", log.Fields{"ServiceName": svc.Name})
		return
	}

	if svc.NniPort != "" {
		err := vpv.ValidateNniPort(voltDevice, svc.NniPort)
		if err != nil {
			logger.Warnw(ctx, "Not pushing service flows: NNI is not configured", log.Fields{"Port": vpv.Port, "Device": voltDevice.Name, "NNI": svc.NniPort, "Error": err})
			return
		}
	} else {
		nni, err := GetApplication().GetNniPort(voltDevice.Name)
		if nni == "" {
			logger.Warnw(ctx, "Not pushing service flows: Default NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": voltDevice.Name, "Error": err})
			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(cntx)
		} else {
			if err := svc.AddUsHsiaFlows(cntx, false); 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.Debugw(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
		if err := vpv.AddIgmpFlows(cntx); err != nil {
			statusCode, statusMessage := errorCodes.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.RangeOnServices(cntx, PostAccessConfigSuccessInd, false)
		}
	}
	vpv.WriteToDb(cntx)
}

// setLearntMAC to set learnt mac
func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	svc.SetMacAddr(vpv.MacAddr)
	svc.WriteToDb(cntx)
	return true
}

// PostAccessConfigSuccessInd for posting access config success indication
func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}, flag bool) bool {
	return true
}

// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
	svc.SetIpv4Addr(vpv.Ipv4Addr)
	svc.WriteToDb(cntx)

	return true
}

// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Updating Ipv6 address for service", log.Fields{"ServiceName": svc.Name})
	svc.SetIpv6Addr(vpv.Ipv6Addr)
	svc.WriteToDb(cntx)

	return true
}

// AddUsHsiaFlows to add upstream hsia flows
func AddUsHsiaFlows(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Add US Hsia Flows", log.Fields{"ServiceName": svc.Name})
	if err := svc.AddUsHsiaFlows(cntx, flag); 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(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Add DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
	if err := svc.AddDsHsiaFlows(cntx, flag); 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(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Received Cleared Flow Flags for service", log.Fields{"name": svc.Name})
	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(cntx)
	logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
	return true
}

// DelDsHsiaFlows to delete hsia flows
// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
func DelDsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Delete DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
	if err := svc.DelDsHsiaFlows(cntx, delFlowsInDevice); 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
// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
func DelUsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Delete US Hsia Flows", log.Fields{"ServiceName": svc.Name})
	if err := svc.DelUsHsiaFlows(cntx, delFlowsInDevice); 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(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Received Clear Service Counters", log.Fields{"ServiceName": svc.Name})
	//Delete the per service counter too
	GetApplication().ServiceCounters.Delete(svc.Name)
	if svc.IgmpEnabled && svc.EnableMulticastKPI {
		_ = db.DelAllServiceChannelCounter(cntx, svc.Name)
	}
	return true
}

// AddMeterToDevice to add meter config to device, used in FTTB case
func AddMeterToDevice(cntx context.Context, key, value interface{}, flag bool) bool {
	svc := value.(*VoltService)
	logger.Debugw(ctx, "Received Add Meter To Device", log.Fields{"ServiceName": svc.Name})
	if err := svc.AddMeterToDevice(cntx); err != nil {
		logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
	}
	return true
}

// AddTrapFlows - Adds US & DS Trap flows
func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
	logger.Debugw(ctx, "Received Add US & DS DHCP, IGMP Trap Flows", log.Fields{"FlowsApplied": vpv.FlowsApplied, "VgcRebooted": vgcRebooted})
	if !vpv.FlowsApplied || vgcRebooted {
		if vpv.DhcpRelay {
			if err := vpv.AddUsDhcpFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
			if err := vpv.AddDsDhcpFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
			logger.Debugw(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(cntx); err != nil {
				statusCode, statusMessage := errorCodes.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(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
			if err := vpv.AddDsPppoeFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
		}
		vpv.FlowsApplied = true
		vpv.WriteToDb(cntx)
	}
}

// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
	logger.Debugw(ctx, "Received Delete US & DS DHCP, IGMP Trap Flows", log.Fields{"FlowsApplied": vpv.FlowsApplied, "VgcRebooted": vgcRebooted})
	// Delete HSIA & DHCP flows before deleting IGMP flows
	if vpv.FlowsApplied || vgcRebooted {
		if vpv.DhcpRelay {
			if err := vpv.DelUsDhcpFlows(cntx); 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(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
			//vpv.updateICMPv6McGroup(false)
		} else if vpv.ArpRelay {
			if err := vpv.DelUsArpFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
		} else if vpv.PppoeIa {
			if err := vpv.DelUsPppoeFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
			if err := vpv.DelDsPppoeFlows(cntx); err != nil {
				statusCode, statusMessage := errorCodes.GetErrorInfo(err)
				vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
			}
		}
		vpv.FlowsApplied = false
		vpv.WriteToDb(cntx)
	}
	if err := vpv.DelIgmpFlows(cntx); 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(cntx context.Context, delFlowsInDevice bool) {
	logger.Debugw(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
	// no HSIA flows for multicast service
	if !vpv.McastService {
		vpv.RangeOnServices(cntx, DelUsHsiaFlows, delFlowsInDevice)
		vpv.RangeOnServices(cntx, DelDsHsiaFlows, delFlowsInDevice)
	}
}

// ClearServiceCounters - Removes all igmp counters for a service
func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
	//send flows deleted indication to submgr
	vpv.RangeOnServices(cntx, ClearServiceCounters, false)
}

// BuildDefaultDhcpTrapFlow to build the downstream dhcp flows
func (va *VoltApplication) BuildDefaultDhcpTrapFlow(ctx context.Context, device *VoltDevice, port string) (*of.VoltFlow, error) {
	logger.Infow(ctx, "Building NNI DS DHCP flow", log.Fields{"Port": port, "device": device.Name})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
	subFlow := of.NewVoltSubFlow()
	subFlow.SetTableID(0)

	subFlow.SetUdpv4Match()
	subFlow.SrcPort = 67
	subFlow.DstPort = 68

	nniport, err := GetApplication().GetPortID(port)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch port id %d for nni : %w", nniport, err)
	}
	subFlow.SetInPort(nniport)
	// PortName and PortID to be used for validation of port before flow pushing
	flow.PortID = nniport
	flow.PortName = port
	allowTransparent := 0

	ontEtherTypeClass := 0
	vlanControl := OLTSVlan
	uniVlan := of.VlanNone
	cVlan := of.VlanNone

	metadata := uint64(allowTransparent)<<56 | uint64(ontEtherTypeClass)<<36 | uint64(vlanControl)<<32 | uint64(uniVlan)<<16 | uint64(cVlan)
	subFlow.SetTableMetadata(metadata)
	subFlow.Priority = of.DhcpFlowPriority

	subFlow.SetReportToController()
	// | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
	subFlow.Cookie = uint64(cVlan)<<52 | uint64(nniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask

	flow.SubFlows[subFlow.Cookie] = subFlow
	logger.Infow(ctx, "Built NNI DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})

	return flow, nil
}

// AddDefaultDhcpTrapFlow function pushes the default DHCP flows to the VOLTHA via the controller
func (va *VoltApplication) AddDefaultDhcpTrapFlow(cntx context.Context, vd *VoltDevice, p *VoltPort) error {
	if vd.GlobalDhcpFlowAdded {
		logger.Info(ctx, "Global Dhcp flow already exists")
		return nil
	}

	flows, err := va.BuildDefaultDhcpTrapFlow(cntx, vd, p.Name)
	if err == nil {
		if err1 := va.PushTrapFlows(cntx, vd, p.Name, flows); err1 != nil {
			logger.Errorw(cntx, "Failure pushing nni trap flows", log.Fields{"device": vd.Name, "port": p.Name})
			return fmt.Errorf("failed to push trap flow for nni : %s, error : %w", p.Name, err1)
		}
	} else {
		logger.Errorw(cntx, "Failure building nni trap flows", log.Fields{"device": vd.Name, "port": p.Name})
		return fmt.Errorf("failed to build trap flow for nni : %s, error : %w", p.Name, err)
	}
	p.NniDhcpTrapFlowAdded = true
	if GetApplication().GetVendorID() != Radisys && va.IsDhcpTrapFlowAdded(cntx, vd) {
		logger.Debugw(ctx, "Global DHCP trap flow set", log.Fields{"device": vd.Name})
		vd.GlobalDhcpFlowAdded = true
	}
	return nil
}

func (va *VoltApplication) IsDhcpTrapFlowAdded(ctx context.Context, vd *VoltDevice) bool {
	if len(vd.NniPort) == 0 {
		return false
	}
	flag := true
	for _, nniPort := range vd.NniPort {
		if p := vd.GetPort(nniPort); p != nil {
			if !p.NniDhcpTrapFlowAdded {
				flag = false
			}
		} else {
			flag = false
		}
	}

	return flag
}

// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
	var vd *VoltDevice
	device := vpv.Device
	logger.Debugw(ctx, "Received Add US DHCP Flows", log.Fields{"Device": 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 {
		err := errorCodes.ErrDeviceNotFound
		return fmt.Errorf("us dhcp flow push failed - device not found for Port %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
	}

	flows, err := vpv.BuildUsDhcpFlows()
	if err == nil {
		logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
		if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
			// push ind here ABHI
			statusCode, statusMessage := errorCodes.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 := errorCodes.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(cntx context.Context) error {
	var vd *VoltDevice
	device := vpv.Device
	logger.Debugw(ctx, "Received Add DS DHCP Flows", log.Fields{"Device": 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 {
		err := errorCodes.ErrDeviceNotFound
		return fmt.Errorf("ds dhcp flow push failed - device not found for Port %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
	}

	if vd.GlobalDhcpFlowAdded {
		logger.Info(ctx, "Global Dhcp flow already exists")
		return nil
	}

	nniPorts := make([]string, 0)
	vpv.services.Range(func(key, value interface{}) bool {
		svc := value.(*VoltService)
		logger.Infow(ctx, "Found service on the vpv", log.Fields{"Name": svc.Name, "NNIPort": svc.NniPort})
		nniPorts = append(nniPorts, svc.NniPort)
		return true
	})

	if len(nniPorts) == 0 {
		vpv.BuildAndPushDSDhcpFlows(cntx, vd, "")
	} else {
		for _, nniPort := range nniPorts {
			vpv.BuildAndPushDSDhcpFlows(cntx, vd, nniPort)
		}
	}

	if GetApplication().GetVendorID() != Radisys {
		vd.GlobalDhcpFlowAdded = true
	}
	return nil
}

func (vpv *VoltPortVnet) BuildAndPushDSDhcpFlows(cntx context.Context, device *VoltDevice, nniPort string) {
	var err error
	var flows *of.VoltFlow
	flows, err = vpv.BuildDsDhcpFlows(nniPort)
	if err == nil {
		if err1 := vpv.PushFlows(cntx, device, flows); err1 != nil {
			statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
		}
	} else {
		statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
	}
}

// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
	logger.Info(ctx, "Received Delete DHCP Flows")
	if err := vpv.DelUsDhcpFlows(cntx); err != nil {
		statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
	}

	if err := vpv.DelDsDhcpFlows(cntx); err != nil {
		statusCode, statusMessage := errorCodes.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(cntx context.Context) error {
	logger.Debugw(ctx, "Received Delete US DHCP Flows", log.Fields{"Port": vpv.Port})
	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
	if err != nil {
		return err
	}

	err = vpv.delDhcp4Flows(cntx, device)
	if err != nil {
		statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
	}

	return nil
}

func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
	logger.Debugw(ctx, "Received US Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
	flows, err := vpv.BuildUsDhcpFlows()
	if err == nil {
		return vpv.RemoveFlows(cntx, device, flows)
	}
	return fmt.Errorf("US DHCP Flow Delete Failed : %w", 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(cntx context.Context) error {
	logger.Debugw(ctx, "Received Delete DS DHCP Flows", log.Fields{"Port": vpv.Port})
	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
	if err != nil {
		return err
	}
	err = vpv.delDsDhcp4Flows(cntx, device)
	if err != nil {
		statusCode, statusMessage := errorCodes.GetErrorInfo(err)
		vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
	}
	/*
		err = vpv.delDsDhcp6Flows(device)
		if err != nil {
			statusCode, statusMessage := errorCodes.GetErrorInfo(err)
			vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
		}*/
	return nil
}

func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
	logger.Debugw(ctx, "Received DS Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
	nniPorts := make([]string, 0)
	vpv.services.Range(func(key, value interface{}) bool {
		svc := value.(*VoltService)
		logger.Infow(ctx, "Found service on the vpv", log.Fields{"Name": svc.Name, "NNIPort": svc.NniPort})
		nniPorts = append(nniPorts, svc.NniPort)
		return true
	})

	if len(nniPorts) == 0 {
		if err := vpv.BuildAndRemoveDSDhcpFlows(cntx, device, ""); err != nil {
			return err
		}
	} else {
		for _, nniPort := range nniPorts {
			if err := vpv.BuildAndRemoveDSDhcpFlows(cntx, device, nniPort); err != nil {
				return err
			}
		}
	}
	return nil
}

func (vpv *VoltPortVnet) BuildAndRemoveDSDhcpFlows(cntx context.Context, device *VoltDevice, nniPort string) error {
	var err error
	var flows *of.VoltFlow
	flows, err = vpv.BuildDsDhcpFlows(nniPort)
	if err == nil {
		if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
			logger.Errorw(ctx, "DS DHCP Flow Remove Failed", log.Fields{"Reason": err.Error()})
			return fmt.Errorf("ds dhcp flow remove failed - Port %s, NNIPort %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, nniPort, vpv.SVlan, vpv.CVlan, vpv.UniVlan, vpv.Device, err)
		}
	} else {
		logger.Errorw(ctx, "DS DHCP Flow Build Failed", log.Fields{"Reason": err.Error()})
		return fmt.Errorf("ds dhcp flow build failed - Port %s, NNIPort %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, nniPort, vpv.SVlan, vpv.CVlan, vpv.UniVlan, vpv.Device, err)
	}
	return nil
}

/*
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(cntx context.Context) error {
	var vd *VoltDevice
	device := vpv.Device
	logger.Debugw(ctx, "Received Add US Arp Flows", log.Fields{"DeviceName": 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 {
		err := errorCodes.ErrDeviceNotFound
		return fmt.Errorf("US ARP Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
	}

	flows, err := vpv.BuildUsArpFlows()
	if err == nil {
		logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
		if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
			return fmt.Errorf("Pushing US ARP Flow Failed : %w", err1)
		}
	} else {
		return fmt.Errorf("US ARP Flow Add Failed : Device %s : %w", device, 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(cntx context.Context) error {
	logger.Debugw(ctx, "Delete US ARP Flows", log.Fields{"Port": vpv.Port})
	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
	if err != nil {
		return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
	}
	flows, err := vpv.BuildUsArpFlows()
	if err == nil {
		return vpv.RemoveFlows(cntx, device, flows)
	}
	return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
}

// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) 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 {
		err := errorCodes.ErrDeviceNotFound
		return fmt.Errorf("US PPPoE Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
	}

	if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
		logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})

		if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
			return fmt.Errorf("Pushing US PPPoE Flows Failed : %w", err1)
		}
	} else {
		return fmt.Errorf("US PPPoE Flow Add Failed : Device %s : %w", device, err)
	}
	return nil
}

// AddDsPppoeFlows to add downstream pppoe flows
func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) 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 {
		err := errorCodes.ErrDeviceNotFound
		return fmt.Errorf("DS PPPoE Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
	}

	flows, err := vpv.BuildDsPppoeFlows()
	if err == nil {
		if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
			return fmt.Errorf("Pushing DS PPPoE Flows Failed : %w", err1)
		}
	} else {
		return fmt.Errorf("DS PPPoE Flow Add Failed : Device %s : %w", device, 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(cntx context.Context) 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 fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
	}
	flows, err := vpv.BuildUsPppoeFlows()
	if err == nil {
		return vpv.RemoveFlows(cntx, device, flows)
	}
	return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, 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(cntx context.Context) error {
	logger.Infow(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 fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
	}
	flows, err := vpv.BuildDsPppoeFlows()
	if err == nil {
		return vpv.RemoveFlows(cntx, device, flows)
	}
	return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
}

// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
	logger.Debugw(ctx, "Received Add Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
	if !vpv.IgmpFlowsApplied || vgcRebooted {
		if vpv.MvlanProfileName == "" {
			logger.Warn(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
			return nil
		}
		device, err := GetApplication().GetDeviceFromPort(vpv.Port)
		if err != nil {
			return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, 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 := controller.GetController().AddFlows(cntx, vpv.Port, device.Name, flows, false); err1 != nil {
				return err1
			}
		} else {
			return fmt.Errorf("IGMP Flow Add Failed : %w", err)
		}
		vpv.IgmpFlowsApplied = true
		vpv.WriteToDb(cntx)
	}
	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(cntx context.Context) error {
	logger.Debugw(ctx, "Received Delete Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
	if vpv.IgmpFlowsApplied || vgcRebooted {
		device, err := GetApplication().GetDeviceFromPort(vpv.Port)
		if err != nil {
			return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
		}
		flows, err := vpv.BuildIgmpFlows()
		if err == nil {
			if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
				return err1
			}
		} else {
			return fmt.Errorf("IGMP Flow Delete Failed : %w", err)
		}
		vpv.IgmpFlowsApplied = false
		vpv.WriteToDb(cntx)
	}
	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) {
	logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)

	subFlow := of.NewVoltSubFlow()
	subFlow.SetTableID(0)

	if vpv.VnetType == DpuMgmtTraffic {
		subFlow.SetMatchVlan(vpv.CVlan)
		subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
		subFlow.SetPcp(vpv.UsPonSTagPriority)
		subFlow.SetSetVlan(vpv.SVlan)
	} else {
		subFlow.SetMatchVlan(vpv.UniVlan)
		subFlow.SetSetVlan(vpv.CVlan)
		subFlow.SetPcp(vpv.DhcpPbit)
	}
	subFlow.SetUdpv4Match()
	subFlow.DstPort = 67
	subFlow.SrcPort = 68
	uniport, err := GetApplication().GetPortID(vpv.Port)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch uni port %s from vpv : %w", vpv.Port, 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 {
		vs := value.(*VoltService)
		var writemetadata uint64
		if vpv.VnetType == DpuMgmtTraffic {
			writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
		} else {
			writemetadata = uint64(vs.TechProfileID) << 32
		}
		subFlow.SetWriteMetadata(writemetadata)
		subFlow.SetMeterID(vs.UsMeterID)
		return false
	})

	// metadata := uint64(uniport)
	// subFlow.SetWriteMetadata(metadata)
	allowTransparent := 0
	if vpv.AllowTransparent {
		allowTransparent = 1
	}
	if vpv.VnetType != DpuMgmtTraffic {
		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(nniPort string) (*of.VoltFlow, error) {
	logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr, "NNIPort": nniPort})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
	subFlow := of.NewVoltSubFlow()
	subFlow.SetTableID(0)
	// match on vlan only for fttb case
	if vpv.VnetType == DpuMgmtTraffic {
		subFlow.SetMatchVlan(vpv.SVlan)
	}
	subFlow.SetUdpv4Match()
	subFlow.SrcPort = 67
	subFlow.DstPort = 68
	uniport, _ := GetApplication().GetPortID(vpv.Port)

	device, err := GetApplication().GetDeviceFromPort(vpv.Port)
	if err != nil {
		return nil, fmt.Errorf("error getting device for vpv %s and port %s  : %w", vpv.VnetName, vpv.Port, err)
	}
	var inport uint32
	if nniPort != "" {
		if nniPortID := device.GetPortIDFromPortName(nniPort); nniPortID != 0 {
			inport = nniPortID
		} else {
			return nil, fmt.Errorf("error getting portID for NNI port %s : %w", nniPort, err)
		}
	} else {
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return nil, err
		}
		inport, _ = GetApplication().GetDevicePortID(device.Name, nniPort)
	}

	subFlow.SetInPort(inport)
	// 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
	}
	if vpv.VnetType != DpuMgmtTraffic {
		metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
		subFlow.SetTableMetadata(metadata)
		subFlow.Priority = of.DhcpFlowPriority
	}
	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

	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) {
	logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)

	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, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, 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 {
		logger.Errorw(ctx, "Failed to fetch nni port from vpv", log.Fields{"error": err, "device": vpv.Device})
		return nil, err
	}
	nniport, err := GetApplication().GetDevicePortID(vpv.Device, nni)
	if err != nil {
		logger.Errorw(ctx, "Failed to fetch port ID for nni", log.Fields{"error": err, "nni": nni})
		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) {
	logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)

	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, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, 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 {
	logger.Debugw(ctx, "Set Us Match Vlan", log.Fields{"Value": vpv.VlanControl})
	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) {
	logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
	flow := &of.VoltFlow{}
	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
	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().GetDevicePortID(vpv.Device, 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) {
	logger.Debugw(ctx, "Set Ds Match Vlan", log.Fields{"Vlan": vpv.VlanControl})
	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)

	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.Debugw(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(cntx context.Context) {
	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(cntx)
}

// ForceWriteToDb force commit a VPV to the DB
func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
	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(cntx, 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(cntx context.Context) {
	logger.Debugw(ctx, "Deleting VPV from DB", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan})
	_ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
}

// ClearAllServiceFlags to clear all service flags
func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
	vpv.RangeOnServices(cntx, ClearFlagsInService, false)
}

// ClearAllVpvFlags to clear all vpv flags
func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
	logger.Debugw(ctx, "Clear All Vpv Flags", log.Fields{"Port": vpv.Port, "Device": vpv.Device})
	vpv.PendingFlowLock.Lock()
	vpv.FlowsApplied = false
	vpv.IgmpFlowsApplied = false
	vpv.PendingDeleteFlow = make(map[string]bool)
	vpv.PendingFlowLock.Unlock()
	vpv.WriteToDb(cntx)
	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) {
	logger.Info(ctx, "Create Vpv From 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(cntx context.Context) {
	logger.Info(ctx, "Restore Vpvs From Db")
	// VNETS must be learnt first
	vpvs, _ := db.GetVpvs(cntx)
	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 {
	logger.Debugw(ctx, "Get Vnet By Port", log.Fields{"port": port, "svlan": svlan, "cvlan": cvlan, "univlan": univlan})
	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(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
	// The VNET is not on the port and is to be added
	logger.Infow(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(cntx, vs)

	if !vs.IsActivated {
		logger.Warn(ctx, "Not Checking port state: Service Not activated")
		// Process the PORT UP if the port is already up
		d, err := va.GetDeviceFromPort(port)
		if err == nil {
			vpv.setDevice(d.Name)
		}
		vpv.WriteToDb(cntx)
		return vpv
	}

	// 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 {
			logger.Debugw(ctx, "Checking UNI port state", log.Fields{"State": p.State})
			if d.State == controller.DeviceStateUP && p.State == PortStateUp {
				vpv.PortUpInd(cntx, d, port, vs.NniPort, false)
			}
		}
	}
	vpv.WriteToDb(cntx)
	return vpv
}

// DelVnetFromPort for deleting vnet from port
func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
	logger.Debugw(ctx, "Delete Vnet From Port", log.Fields{"Port": port, "VNET": vpv.Device})
	// 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 reflect.DeepEqual(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(cntx)

			va.VnetsByPort.Store(port, vpvs)
			vpv.DelTrapFlows(cntx)
			vpv.DelHsiaFlows(cntx, false)
			va.DisassociateVpvsFromDevice(vpv.Device, vpv)
			vpv.PendingFlowLock.RLock()
			if len(vpv.PendingDeleteFlow) == 0 {
				vpv.DelFromDb(cntx)
			}
			if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
				vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
			}
			vpv.PendingFlowLock.RUnlock()
			return
		}
	}
}

// RestoreVnetsFromDb to restore vnet from port
func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
	logger.Info(ctx, "Restore Vnets From Db")
	// VNETS must be learnt first
	vnets, _ := db.GetVnets(cntx)
	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(cntx, 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 {
	logger.Debugw(ctx, "Get Service From Cvlan", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
	// 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 d.IsPortNni(port) {
		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 HSIA Flow - cvlan == Svlan
			// In case of DHCP flow, match for cvlan as we are setting cvlan for DHCP flows
			if len(vlans) == 1 && (vlans[0] == vnet.CVlan || vlans[0] == of.VlanNone) && (service != nil && service.IsActivated) {
				return service
			}
		case OLTCVlanOLTSVlan:
			service = vnet.MatchesPriority(priority)
			if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
				return service
			}
		case OLTSVlan:
			// For OLTSVlan, vnet type FttbSubscriberTraffic should match on CVlan
			// if vnet type not FttbSubscriberTraffic, return only the active service attached to the VPV.
			if vnet.VnetType == FttbSubscriberTraffic && vnet.CVlan != vlans[0] {
				continue
			}
			service = vnet.GetSvcFromVPV()
			if service != nil && service.IsActivated {
				return service
			}
		default:
			logger.Warnw(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
	logger.Debugw(ctx, "Get Vnet From Fields", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
	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 d.IsPortNni(port) {
		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.Warnw(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) {
	logger.Debugw(ctx, "Get Vnet From Pkt", log.Fields{"Device": device, "Port": port})
	vlans := GetVlans(pkt)
	priority := GetPriority(pkt)
	return va.GetVnetFromFields(device, port, vlans, priority)
}

// PushDevFlowForVlan to push icmpv6 flows for vlan
func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
	logger.Debugw(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.Warnw(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
			return true
		}
		if device.State != controller.DeviceStateUP {
			logger.Warnw(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.Warnw(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.Debugw(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
		}
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return true
		}
		if portID, err := va.GetDevicePortID(device.Name, nniPort); err == nil {
			if state, _ := controller.GetController().GetPortState(device.Name, nniPort); state != controller.PortStateUp {
				logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
				return true
			}

			// Pushing ICMPv6 Flow
			flow := BuildICMPv6Flow(portID, vnet)
			err = controller.GetController().AddFlows(cntx, nniPort, device.Name, flow, false)
			if err != nil {
				logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
				return true
			}
			logger.Debugw(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})

			// Pushing ARP Flow
			flow = BuildDSArpFlow(portID, vnet)
			err = controller.GetController().AddFlows(cntx, nniPort, device.Name, flow, false)
			if err != nil {
				logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
				return true
			}
			logger.Debugw(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)
}

func (va *VoltApplication) PushTrapFlows(cntx context.Context, device *VoltDevice, nniPort string, flow *of.VoltFlow) error {
	logger.Debugw(ctx, "Push NNI DHCP Trap Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
	return controller.GetController().AddFlows(cntx, nniPort, device.Name, flow, false)
}

// PushDevFlowForDevice to push icmpv6 flows for device
func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
	logger.Debugw(ctx, "PushDevFlowForDevice", 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
		}
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return true
		}
		nniPortID, err := va.GetDevicePortID(device.Name, 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 = controller.GetController().AddFlows(cntx, nniPort, device.Name, flow, false)
		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 = controller.GetController().AddFlows(cntx, nniPort, device.Name, flow, false)
		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(cntx context.Context, vnet *VoltVnet) {
	logger.Debugw(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
			}
		}
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return true
		}
		if portID, err := va.GetDevicePortID(device.Name, nniPort); err == nil {
			if state, _ := controller.GetController().GetPortState(device.Name, nniPort); state != controller.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(cntx, 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(cntx, 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(cntx context.Context, device *VoltDevice) {
	logger.Debugw(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
		}
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return true
		}
		nniPortID, err := va.GetDevicePortID(device.Name, 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(cntx, 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(cntx, 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(cntx context.Context, 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
		}
		nniPort, err := GetApplication().GetNniPort(device.Name)
		if err != nil {
			logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
			return true
		}
		if portID, err := va.GetDevicePortID(device.Name, nniPort); err == nil {
			if state, _ := controller.GetController().GetPortState(device.Name, nniPort); state != controller.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(cntx, device, flow); err != nil {
				logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
			}
			logger.Debugw(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})

			flow = BuildDSArpFlow(portID, vnet)
			flow.ForceAction = true
			if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
				logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
			}
			logger.Debugw(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.Debugw(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.Debugw(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.Debug(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.Debug(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 := controller.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 {
	logger.Debugw(ctx, "Is Vlan Matching", log.Fields{"cvlan": cvlan, "svlan": svlan})
	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.Warnw(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(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
	logger.Debugw(ctx, "Push Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
	for cookie := range flow.SubFlows {
		cookie := strconv.FormatUint(cookie, 10)
		fe := &FlowEvent{
			eType:     EventTypeControlFlowAdded,
			cookie:    cookie,
			eventData: vpv,
		}
		device.RegisterFlowAddEvent(cookie, fe)
	}
	return controller.GetController().AddFlows(cntx, vpv.Port, device.Name, flow, false)
}

// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
	logger.Debugw(ctx, "Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrReason": errReason})
	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(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
	logger.Debugw(ctx, "Remove Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
	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 controller.GetController().DelFlows(cntx, vpv.Port, device.Name, flow, false)
}

// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
	logger.Debugw(ctx, "Check And Delete Vpv", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
	vpv.PendingFlowLock.RLock()
	defer vpv.PendingFlowLock.RUnlock()
	if !vpv.DeleteInProgress {
		logger.Warnw(ctx, "Skipping removing VPV from DB as VPV delete is in progress", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
		return
	}
	if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
		logger.Debugw(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(cntx)
		logger.Debugw(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(cntx context.Context, cookie string, device string) {
	vpv.PendingFlowLock.Lock()
	logger.Debugw(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})

	delete(vpv.PendingDeleteFlow, cookie)
	vpv.PendingFlowLock.Unlock()
	vpv.CheckAndDeleteVpv(cntx)
	vpv.WriteToDb(cntx)
}

// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
	vpv.PendingFlowLock.Lock()

	logger.Debugw(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(cntx)
	} else {
		vpv.PendingFlowLock.Unlock()
		vpv.WriteToDb(cntx)
	}
}

// RemoveFlows - Triggers flow deletion after registering for flow indication event
func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
	logger.Debugw(ctx, "Remove Flows", log.Fields{"PortName": flow.PortName, "DeviceName": device.Name})
	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(cntx)
	nniPort, err := GetApplication().GetNniPort(device.Name)
	if err != nil {
		logger.Errorw(ctx, "Error getting NNI port", log.Fields{"Error": err})
		return err
	}
	return controller.GetController().DelFlows(cntx, nniPort, device.Name, flow, false)
}

// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
	logger.Debugw(ctx, "Check And Delete Vnet", log.Fields{"Device": device, "Vnet": vv.Name})
	if !vv.DeleteInProgress {
		logger.Warnw(ctx, "Skipping removing Vnet from DB as Vnet delete is in progress", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
		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(cntx, vv.Name)
		logger.Debugw(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(cntx context.Context, cookie string, device string) {
	vv.VnetLock.Lock()
	defer vv.VnetLock.Unlock()

	logger.Debugw(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(cntx, device)
		}
	}
	vv.WriteToDb(cntx)
}

// FlowRemoveFailure - Process flow failure indication
func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
	vv.VnetLock.Lock()
	defer vv.VnetLock.Unlock()
	logger.Debugw(ctx, "Vnet Flow Remove Failure Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device, "ErrorCode": errorCode, "ErrorReason": errReason})

	if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
		if _, ok := flowMap[cookie]; ok {
			logger.Debugw(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(cntx, device)
			}
			return
		}
	}
	logger.Debugw(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"
	logger.Debugw(ctx, "Igmp Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})

	sendFlowFailureInd := func(key, value interface{}) bool {
		svc := value.(*VoltService)
		if svc.IgmpEnabled {
			svc.triggerServiceFailureInd(errorCode, errReason)
			return false
		}
		return true
	}
	logger.Debugw(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 {
	logger.Debugw(ctx, "Get Matching Mcast Service", log.Fields{"Port": port, "Device": device, "Cvlan": cvlan})
	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 d.IsPortNni(port) {
		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(cntx context.Context, device string) bool {
	logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": device})
	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(cntx, vd, flow); err != nil {
				logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
			}
		}
	}
	return true
}

// JSONMarshal wrapper function for json Marshal VoltVnet
func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
	return json.Marshal(VoltVnet{
		VnetConfig: vv.VnetConfig,
		Version:    vv.Version,
		VnetOper: VnetOper{
			PendingDeleteFlow:     vv.VnetOper.PendingDeleteFlow,
			DeleteInProgress:      vv.VnetOper.DeleteInProgress,
			PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
		},
	})
}

// JSONMarshal wrapper function for json Marshal VoltPortVnet
func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
	return json.Marshal(VoltPortVnet{
		Device:                     vpv.Device,
		Port:                       vpv.Port,
		PonPort:                    vpv.PonPort,
		VnetName:                   vpv.VnetName,
		SVlan:                      vpv.SVlan,
		CVlan:                      vpv.CVlan,
		UniVlan:                    vpv.UniVlan,
		SVlanTpid:                  vpv.SVlanTpid,
		DhcpRelay:                  vpv.DhcpRelay,
		ArpRelay:                   vpv.ArpRelay,
		PppoeIa:                    vpv.PppoeIa,
		MacLearning:                vpv.MacLearning,
		DhcpStatus:                 vpv.DhcpStatus,
		DhcpExpiryTime:             vpv.DhcpExpiryTime,
		Dhcp6ExpiryTime:            vpv.Dhcp6ExpiryTime,
		FlowsApplied:               vpv.FlowsApplied,
		Ipv4Addr:                   vpv.Ipv4Addr,
		Ipv6Addr:                   vpv.Ipv6Addr,
		MacAddr:                    vpv.MacAddr,
		LearntMacAddr:              vpv.LearntMacAddr,
		CircuitID:                  vpv.CircuitID,
		RemoteID:                   vpv.RemoteID,
		IsOption82Enabled:          vpv.IsOption82Enabled,
		RelayState:                 vpv.RelayState,
		PPPoeState:                 vpv.PPPoeState,
		RelayStatev6:               vpv.RelayStatev6,
		IgmpEnabled:                vpv.IgmpEnabled,
		IgmpFlowsApplied:           vpv.IgmpFlowsApplied,
		McastService:               vpv.McastService,
		ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
		VlanControl:                vpv.VlanControl,
		MvlanProfileName:           vpv.MvlanProfileName,
		Version:                    vpv.Version,
		McastTechProfileID:         vpv.McastTechProfileID,
		McastPbit:                  vpv.McastPbit,
		McastUsMeterID:             vpv.McastUsMeterID,
		AllowTransparent:           vpv.AllowTransparent,
		SchedID:                    vpv.SchedID,
		DHCPv6DUID:                 vpv.DHCPv6DUID,
		PendingDeleteFlow:          vpv.PendingDeleteFlow,
		DeleteInProgress:           vpv.DeleteInProgress,
		Blocked:                    vpv.Blocked,
		DhcpPbit:                   vpv.DhcpPbit,
	})
}

func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) (bool, string) {
	logger.Debugw(ctx, "Is Service Activated", log.Fields{"Name": vpv.Port})
	isActivated := false
	nniPort := ""
	vpv.services.Range(func(key, value interface{}) bool {
		svc := value.(*VoltService)
		if svc.IsActivated {
			logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
			isActivated = true
			nniPort = svc.NniPort
			return false //to exit loop
		}
		return true
	})
	return isActivated, nniPort
}
