diff --git a/internal/pkg/application/pppoeia.go b/internal/pkg/application/pppoeia.go
new file mode 100644
index 0000000..8b5a214
--- /dev/null
+++ b/internal/pkg/application/pppoeia.go
@@ -0,0 +1,618 @@
+/*
+* 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"
+	"errors"
+	"net"
+	"time"
+
+	"github.com/google/gopacket"
+	"github.com/google/gopacket/layers"
+
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+)
+
+// PppoeIaState type
+type PppoeIaState uint8
+
+const (
+	// PppoeIaStateNone constant
+	PppoeIaStateNone PppoeIaState = iota
+	// PppoeIaStatePADI constant
+	PppoeIaStatePADI
+	// PppoeIaStatePADO constant
+	PppoeIaStatePADO
+	// PppoeIaStatePADR constant
+	PppoeIaStatePADR
+	// PppoeIaStatePADS constant
+	PppoeIaStatePADS
+	// PppoeIaStatePADT constant
+	PppoeIaStatePADT
+)
+
+const (
+	// PPPoEVendorID constant
+	PPPoEVendorID uint32 = 0x0DE9
+	// TYPECIRCUITID constant
+	TYPECIRCUITID byte = 0x01
+	// TYPEREMOTEID constant
+	TYPEREMOTEID byte = 0x02
+	// TYPEMINDATAUS constant
+	TYPEMINDATAUS byte = 0x83
+	// TYPEMINDATADS constant
+	TYPEMINDATADS byte = 0x84
+	// TYPEMAXDATAUS constant
+	TYPEMAXDATAUS byte = 0x87
+	// TYPEMAXDATADS constant
+	TYPEMAXDATADS byte = 0x88
+)
+
+var (
+	// DSLATTRVendorID is PPPoEVendorID in byte format
+	DSLATTRVendorID = util.Uint32ToByte(PPPoEVendorID)
+)
+
+// IPppoeIaSession interface
+type IPppoeIaSession interface {
+	GetCircuitID() []byte
+	GetRemoteID() []byte
+	GetNniVlans() (uint16, uint16)
+	GetPppoeIaState() PppoeIaState
+	SetPppoeIaState(PppoeIaState)
+	SetMacAddr(net.HardwareAddr)
+}
+
+// PppoeIaRelayVnet : The PppoeIa relay sessions are stored in a map to be retrieved from when
+// a response is received from the network. The map uses the VLANs and the
+// the MAC address as key to finding the service
+// PppoeIa Relay Virtual Network hosts a set of PppoeIa relay sessions that belong
+// to the network. It supports two VLANs as its identify. If a single VLAN or
+// no VLAN is to be used, those two should be passed as 4096 (VlanNone)
+type PppoeIaRelayVnet struct {
+	OuterVlan uint16
+	InnerVlan uint16
+	sessions  *util.ConcurrentMap //map[[6]byte]IPppoeIaSession
+}
+
+// PppoeIaNetworks : PppoeIa Networks hosts different PppoeIa networks that in turn hold the PppoeIa
+// sessions
+type PppoeIaNetworks struct {
+	Networks *util.ConcurrentMap //map[uint32]*PppoeIaRelayVnet
+}
+
+// NewPppoeIaRelayVnet is constructor for a PppoeIa Relay Virtual network
+func NewPppoeIaRelayVnet(outerVlan uint16, innerVlan uint16) *PppoeIaRelayVnet {
+	var drv PppoeIaRelayVnet
+
+	drv.OuterVlan = outerVlan
+	drv.InnerVlan = innerVlan
+	drv.sessions = util.NewConcurrentMap() //make(map[[6]byte]IPppoeIaSession)
+	return &drv
+}
+
+// AddPppoeIaRelayVnet add pppoeia relay vnet
+func (dn *PppoeIaNetworks) AddPppoeIaRelayVnet(outerVlan uint16, innerVlan uint16) *PppoeIaRelayVnet {
+	comboVlan := uint32(outerVlan)<<16 + uint32(innerVlan)
+	if drv, ok := dn.Networks.Get(comboVlan); ok {
+		return drv.(*PppoeIaRelayVnet)
+	}
+	drv := NewPppoeIaRelayVnet(outerVlan, innerVlan)
+	dn.Networks.Set(comboVlan, drv)
+	return drv
+}
+
+// NewPppoeIaNetworks is constructor for PppoeIa network
+func NewPppoeIaNetworks() *PppoeIaNetworks {
+	var dn PppoeIaNetworks
+	dn.Networks = util.NewConcurrentMap() //make(map[uint32]*PppoeIaRelayVnet)
+	return &dn
+}
+
+// AddPppoeIaSession to add pppoeia session
+func (dn *PppoeIaNetworks) AddPppoeIaSession(pkt gopacket.Packet, session IPppoeIaSession) {
+	var key [6]byte
+	ethl := pkt.Layer(layers.LayerTypeEthernet)
+	eth, _ := ethl.(*layers.Ethernet)
+	addr := eth.SrcMAC
+	copy(key[:], addr[0:6])
+	drv := dn.AddPppoeIaRelayVnet(session.GetNniVlans())
+	drv.sessions.Set(key, session)
+}
+
+// DelPppoeIaSession to delete pppoeia session
+func (dn *PppoeIaNetworks) DelPppoeIaSession(pkt gopacket.Packet, session IPppoeIaSession) {
+	var key [6]byte
+	ethl := pkt.Layer(layers.LayerTypeEthernet)
+	eth, _ := ethl.(*layers.Ethernet)
+	addr := eth.SrcMAC
+	if len(addr) != 6 {
+		logger.Errorw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
+		return
+	}
+	copy(key[:], addr[0:6])
+	drv := dn.AddPppoeIaRelayVnet(session.GetNniVlans())
+	drv.sessions.Remove(key)
+}
+
+// delPppoeIaSessions to delete pppoeia sessions
+func delPppoeIaSessions(addr net.HardwareAddr, outervlan of.VlanType, innervlan of.VlanType) {
+
+	var key [6]byte
+	if addr == nil || !NonZeroMacAddress(addr) {
+		logger.Warnw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
+		return
+	}
+	copy(key[:], addr[0:6])
+	drv := pppoeIaNws.AddPppoeIaRelayVnet(uint16(outervlan), uint16(innervlan))
+	drv.sessions.Remove(key)
+	logger.Infow(ctx, "PppoeIa Sessions deleted", log.Fields{"MAC": addr})
+}
+
+// GetPppoeIaSession to get pppoeia sessions
+func (dn *PppoeIaNetworks) GetPppoeIaSession(outerVlan uint16, innerVlan uint16, addr net.HardwareAddr) (IPppoeIaSession, error) {
+	var key [6]byte
+	if len(addr) != 6 {
+		logger.Errorw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
+		return nil, errors.New("Invalid MAC address")
+	}
+	copy(key[:], addr[0:6])
+	drv := dn.AddPppoeIaRelayVnet(outerVlan, innerVlan)
+	logger.Infow(ctx, "Key for PPPoE session", log.Fields{"Key": key})
+	if session, ok := drv.sessions.Get(key); ok {
+		return session.(IPppoeIaSession), nil
+	}
+	return nil, ErrSessionDoNotExist
+}
+
+// GetVnetForNni to get vnet for nni port
+func GetVnetForNni(addr net.HardwareAddr, cvlan of.VlanType, svlan of.VlanType, pbit uint8) (*VoltPortVnet, error) {
+
+	var err error
+	var session IPppoeIaSession
+	logger.Infow(ctx, "Mac Obtained MAC: ", log.Fields{"Addr": addr})
+	if session, err = pppoeIaNws.GetPppoeIaSession(uint16(svlan), uint16(cvlan), addr); err != nil {
+		logger.Errorw(ctx, "PPPoE Session retrieval failed", log.Fields{"Error": err})
+		if err == ErrSessionDoNotExist {
+			logger.Info(ctx, "Finding matching VPV from packet")
+			vpvs, err1 := GetApplication().GetVpvsForDsPkt(cvlan, svlan, addr, pbit)
+			if len(vpvs) == 1 {
+				return vpvs[0], nil
+			}
+			return nil, err1
+		}
+		return nil, err
+	}
+
+	if session != nil {
+		vpv, ok := session.(*VoltPortVnet)
+
+		if ok {
+			logger.Infow(ctx, "Session Exist: VPV found", log.Fields{"VPV": vpv})
+			return vpv, nil
+		}
+	}
+	logger.Error(ctx, "PPPoE Session retrieved of wrong type")
+	return nil, errors.New("The session retrieved of wrong type")
+}
+
+// AddIaOption : Addition of PppoeIa Option 82 which codes circuit-id and remote-id
+// into the packet. This happens as the request is relayed to the
+// PppoeIa servers on the NNI
+func AddIaOption(svc *VoltService, pppoe *layers.PPPoE) {
+
+	//NOTE : both cID and rID should not be empty if this function is called
+	var data []byte
+	cID := svc.GetCircuitID()
+	rID := svc.RemoteID
+
+	if len(cID) != 0 || len(rID) != 0 || svc.isDataRateAttrPresent() {
+		data = append(data, DSLATTRVendorID...)
+	}
+
+	logger.Debugw(ctx, "Vendor Info", log.Fields{"Data": data})
+
+	if len(cID) != 0 {
+		data = append(data, TYPECIRCUITID)
+		data = append(data, byte(len(cID)))
+		data = append(data, cID...)
+	}
+	if len(rID) != 0 {
+		data = append(data, TYPEREMOTEID)
+		data = append(data, byte(len(rID)))
+		data = append(data, rID...)
+	}
+
+	if svc.isDataRateAttrPresent() {
+		minDrUs := util.Uint32ToByte(svc.MinDataRateUs)
+		data = append(data, TYPEMINDATAUS)
+		data = append(data, byte(len(minDrUs)))
+		data = append(data, minDrUs...)
+
+		minDrDs := util.Uint32ToByte(svc.MinDataRateDs)
+		data = append(data, TYPEMINDATADS)
+		data = append(data, byte(len(minDrDs)))
+		data = append(data, minDrDs...)
+
+		maxDrUs := util.Uint32ToByte(svc.MaxDataRateUs)
+		data = append(data, TYPEMAXDATAUS)
+		data = append(data, byte(len(maxDrUs)))
+		data = append(data, maxDrUs...)
+
+		maxDrDs := util.Uint32ToByte(svc.MaxDataRateDs)
+		data = append(data, TYPEMAXDATADS)
+		data = append(data, byte(len(maxDrDs)))
+		data = append(data, maxDrDs...)
+	}
+	option := layers.NewPPPoEOption(layers.PPPoEOptVendorSpecific, data)
+	pppoe.Options = append(pppoe.Options, option)
+}
+
+// DelIaOption for deletion of IA option from the packet received on the NNI interface.
+func DelIaOption(pppoe *layers.PPPoE) {
+	for index, option := range pppoe.Options {
+		if option.Type == layers.PPPoEOptVendorSpecific {
+			pppoe.Options = append(pppoe.Options[0:index], pppoe.Options[index+1:]...)
+			return
+		}
+	}
+}
+
+// ProcessDsPppoeIaPacket : This function processes DS PppoeIa packet received on the NNI port.
+// The services are attached to the access ports. Thus, the PppoeIa
+// session is derived from the list of PppoeIa sessions stored in the
+// common map. The key for retrieval includes the VLAN tags in the
+// the packet and the MAC address of the client.
+func (va *VoltApplication) ProcessDsPppoeIaPacket(device string, port string, pkt gopacket.Packet) {
+
+	// Retrieve the layers to build the outgoing packet. It is not
+	// possible to add/remove layers to the existing packet and thus
+	// the lyayers are extracted to build the outgoing packet
+	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
+	pppoe := pkt.Layer(layers.LayerTypePPPoE).(*layers.PPPoE)
+
+	logger.Infow(ctx, "Processing Southbound DS PppoeIa packet", log.Fields{"Port": port, "Type": pppoe.Code})
+
+	// Retrieve the priority and drop eligible flags from the
+	// packet received
+	var priority uint8
+	var dropEligible bool
+	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
+	if dot1ql != nil {
+		dot1q := dot1ql.(*layers.Dot1Q)
+		priority = dot1q.Priority
+		dropEligible = dot1q.DropEligible
+	}
+
+	pktInnerlan, pktOuterlan := GetVlansFromPacket(pkt)
+	vpv, err := GetVnetForNni(eth.DstMAC, pktInnerlan, pktOuterlan, priority)
+	if err != nil {
+		logger.Errorw(ctx, "VNET couldn't be found for NNI", log.Fields{"Error": err})
+		return
+	}
+
+	// Do not modify pppoe header if vnet's mac_learning type is not PPPoE-IA.
+	if vpv.PppoeIa {
+		// Delete the IA option that may be included in the response
+		DelIaOption(pppoe)
+		if pppoe.Code == layers.PPPoECodePADO {
+			vpv.SetPppoeIaState(PppoeIaStatePADO)
+		} else if pppoe.Code == layers.PPPoECodePADS {
+			vpv.SetPppoeIaState(PppoeIaStatePADS)
+		} else if pppoe.Code == layers.PPPoECodePADT {
+			vpv.SetPppoeIaState(PppoeIaStatePADT)
+		}
+		vpv.WriteToDb()
+	}
+	// Create the outgoing bufer and set the checksum in the packet
+	buff := gopacket.NewSerializeBuffer()
+	opts := gopacket.SerializeOptions{
+		FixLengths:       true,
+		ComputeChecksums: true,
+	}
+
+	cTagType := layers.EthernetTypePPPoEDiscovery
+	eth.EthernetType = layers.EthernetTypeDot1Q
+	priority = vpv.GetRemarkedPriority(priority)
+
+	var pktLayers []gopacket.SerializableLayer
+	pktLayers = append(pktLayers, eth)
+
+	var qVlans []of.VlanType
+	var qVlanLayers []gopacket.SerializableLayer
+
+	if vpv.AllowTransparent {
+		vlanThreshold := 2
+		// In case of ONU_CVLAN or OLT_SVLAN, the DS pkts have single configured vlan
+		// In case of ONU_CVLAN_OLT_SVLAN or OLT_CVLAN_OLT_SVLAN, the DS pkts have 2 configured vlan
+		// Based on that, the no. of vlans should be ignored to get only transparent vlans
+		if vpv.VlanControl == ONUCVlan || vpv.VlanControl == OLTSVlan || vpv.VlanControl == None {
+			vlanThreshold = 1
+		}
+		nxtLayer := layers.EthernetTypeDot1Q
+		if vlans := GetVlans(pkt); len(vlans) > vlanThreshold {
+			qVlans = vlans[vlanThreshold:]
+			cTagType = layers.EthernetTypeDot1Q
+		}
+		for i, qVlan := range qVlans {
+			vlan := uint16(qVlan)
+			if i == (len(qVlans) - 1) {
+				nxtLayer = layers.EthernetTypePPPoEDiscovery
+			}
+			qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
+			qVlanLayers = append(qVlanLayers, qdot1q)
+		}
+	}
+
+	switch vpv.VlanControl {
+	case ONUCVlanOLTSVlan:
+		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: uint16(vpv.CVlan), DropEligible: dropEligible, Type: cTagType}
+		pktLayers = append(pktLayers, cdot1q)
+	case ONUCVlan,
+		None:
+		sdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: uint16(vpv.SVlan), DropEligible: dropEligible, Type: cTagType}
+		pktLayers = append(pktLayers, sdot1q)
+	case OLTCVlanOLTSVlan,
+		OLTSVlan:
+		udot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: uint16(vpv.UniVlan), DropEligible: dropEligible, Type: cTagType}
+		pktLayers = append(pktLayers, udot1q)
+	default:
+		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
+		return
+	}
+
+	pktLayers = append(pktLayers, qVlanLayers...)
+	pktLayers = append(pktLayers, pppoe)
+
+	logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
+	if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
+		logger.Errorw(ctx, "Packet Serialization Failed", log.Fields{"Reason": err.Error()})
+		return
+	}
+
+	if err := cntlr.GetController().PacketOutReq(device, vpv.Port, port, buff.Bytes(), false); err != nil {
+		logger.Warnw(ctx, "PacketOutReq Failed", log.Fields{"Device": device, "Error": err})
+	}
+}
+
+// ProcessUsPppoeIaPacket : The US PppoeIa packet is identified the PppoeIa OP in the packet. A request is considered upstream
+// and the service associated with the packet is located by the port and VLANs in the packet
+func (va *VoltApplication) ProcessUsPppoeIaPacket(device string, port string, pkt gopacket.Packet) {
+	// We received the packet on an access port and the service for the packet can be
+	// gotten from the port and the packet
+	vpv, svc := va.GetVnetFromPkt(device, port, pkt)
+	if vpv == nil {
+		logger.Errorw(ctx, "VNET couldn't be found from packet", log.Fields{"Device": device, "Port": port})
+		return
+	}
+
+	outport, _ := va.GetNniPort(device)
+	if outport == "" || outport == "0" {
+		logger.Errorw(ctx, "NNI Port not found for device. Dropping Packet", log.Fields{"NNI": outport})
+		return
+	}
+
+	//Add PPPoE session for reference so that the DS pkts can be processed and re-directed
+	pppoeIaNws.AddPppoeIaSession(pkt, vpv)
+
+	// Extract the layers in the packet to prepare the outgoing packet
+	// We use the layers to build the outgoing packet from scratch as
+	// the packet received can't be modified to add/remove layers
+	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
+	pppoe := pkt.Layer(layers.LayerTypePPPoE).(*layers.PPPoE)
+	msgType := pppoe.Code
+	logger.Infow(ctx, "Processing Southbound US PppoeIa packet", log.Fields{"Device": device, "Port": port, "Type": pppoe.Code})
+
+	AddIaOption(svc, pppoe)
+
+	// Learn the 8021P values from the packet received
+	var priority uint8
+	dropEligible := false
+	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
+	if dot1ql != nil {
+		dot1q := dot1ql.(*layers.Dot1Q)
+		priority = dot1q.Priority
+		dropEligible = dot1q.DropEligible
+	}
+
+	if vpv.PppoeIa {
+		//Maintain the session MAC as learnt MAC, since MAC is required for deletion of PPPoE session
+		if msgType == layers.PPPoECodePADI || msgType == layers.PPPoECodePADR {
+			if !util.MacAddrsMatch(vpv.MacAddr, eth.SrcMAC) {
+				expectedPort := va.GetMacInPortMap(eth.SrcMAC)
+				if expectedPort != "" && expectedPort != vpv.Port {
+					logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-pppoe-message",
+						log.Fields{"MsgType": msgType, "ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": eth.SrcMAC.String()})
+					return
+				}
+			}
+			vpv.SetMacAddr(eth.SrcMAC)
+		}
+
+		if pppoe.Code == layers.PPPoECodePADI {
+			vpv.SetPppoeIaState(PppoeIaStatePADI)
+		} else if pppoe.Code == layers.PPPoECodePADR {
+			vpv.SetPppoeIaState(PppoeIaStatePADR)
+		}
+		vpv.WriteToDb()
+	}
+
+	buff := gopacket.NewSerializeBuffer()
+	opts := gopacket.SerializeOptions{
+		FixLengths:       true,
+		ComputeChecksums: true,
+	}
+
+	cTagType := layers.EthernetTypePPPoEDiscovery
+	outerVlan, innerVlan := vpv.GetNniVlans()
+	logger.Debugw(ctx, "Vnet Vlans", log.Fields{"Svlan": outerVlan, "Cvlan": innerVlan})
+	eth.EthernetType = vpv.SVlanTpid
+
+	var pktLayers []gopacket.SerializableLayer
+	pktLayers = append(pktLayers, eth)
+
+	var qVlans []of.VlanType
+	var qVlanLayers []gopacket.SerializableLayer
+
+	if vpv.AllowTransparent {
+		nxtLayer := layers.EthernetTypeDot1Q
+		if vlans := GetVlans(pkt); len(vlans) > 1 {
+			qVlans = vlans[1:]
+			logger.Debugw(ctx, "Q Vlans", log.Fields{"Vlan List": qVlans})
+			cTagType = layers.EthernetTypeDot1Q
+		}
+		for i, qVlan := range qVlans {
+			vlan := uint16(qVlan)
+			if i == (len(qVlans) - 1) {
+				nxtLayer = layers.EthernetTypePPPoEDiscovery
+			}
+			qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
+			qVlanLayers = append(qVlanLayers, qdot1q)
+		}
+	}
+
+	switch vpv.VlanControl {
+	case ONUCVlanOLTSVlan,
+		OLTCVlanOLTSVlan:
+		sdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: layers.EthernetTypeDot1Q}
+		pktLayers = append(pktLayers, sdot1q)
+		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: innerVlan, DropEligible: dropEligible, Type: cTagType}
+		pktLayers = append(pktLayers, cdot1q)
+	case ONUCVlan,
+		OLTSVlan,
+		None:
+		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: cTagType}
+		pktLayers = append(pktLayers, cdot1q)
+	default:
+		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
+		return
+	}
+
+	pktLayers = append(pktLayers, qVlanLayers...)
+	pktLayers = append(pktLayers, pppoe)
+	logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
+	if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
+		return
+	}
+
+	// Now the packet constructed is output towards the switch to be emitted on
+	// the NNI port
+	if err := cntlr.GetController().PacketOutReq(device, outport, port, buff.Bytes(), false); err != nil {
+		logger.Warnw(ctx, "PacketOutReq Failed", log.Fields{"Device": device, "Error": err})
+	}
+
+}
+
+// ProcessPPPoEIaPacket to process Pppoeia packet
+func (va *VoltApplication) ProcessPPPoEIaPacket(device string, port string, pkt gopacket.Packet) {
+	// Make some error checks before proceeding
+	pppoel := pkt.Layer(layers.LayerTypePPPoE)
+	if pppoel == nil {
+		return
+	}
+	_, ok := pppoel.(*layers.PPPoE)
+	if !ok {
+		return
+	}
+
+	// Let us assess the direction of the packet. We can do so by the port
+	// which is more reliable or do by the PPPoE code which is less reliable
+	isUs := true
+	if nni, _ := GetApplication().GetNniPort(device); nni == port {
+		isUs = false
+	}
+
+	// This is a valid PPPoE packet and can be processed
+	if isUs {
+		// This is treated as an upstream packet in the VOLT application
+		// as VOLT serves access subscribers who use DHCP to acquire IP
+		// address and these packets go upstream to the network
+		va.ProcessUsPppoeIaPacket(device, port, pkt)
+	} else {
+		// This is a downstream packet
+		va.ProcessDsPppoeIaPacket(device, port, pkt)
+	}
+}
+
+// ProcessPPPoEPacket to process Pppoe packet
+func (va *VoltApplication) ProcessPPPoEPacket(device string, port string, pkt gopacket.Packet) {
+	dpt := NewPppoeIaPacketTask(pkt, device, port)
+	va.pppoeTasks.AddTask(dpt)
+}
+
+// pppoeIaNws : The DHCP relay application is maintained within the structures below
+var pppoeIaNws *PppoeIaNetworks
+
+func init() {
+	pppoeIaNws = NewPppoeIaNetworks()
+	RegisterPacketHandler(PPPOE, ProcessPPPoEPacket)
+}
+
+// ProcessPPPoEPacket : CallBack function registered with application to handle PPPoE packetIn
+func ProcessPPPoEPacket(device string, port string, pkt gopacket.Packet) {
+	GetApplication().ProcessPPPoEPacket(device, port, pkt)
+}
+
+// PppoeIaPacketTask : Task to add or delete flows of a service
+type PppoeIaPacketTask struct {
+	taskID    uint8
+	ctx       context.Context
+	pkt       gopacket.Packet
+	device    string
+	port      string
+	timestamp string
+}
+
+// NewPppoeIaPacketTask constructor for PppoeIaPacketTask
+func NewPppoeIaPacketTask(pkt gopacket.Packet, dev string, port string) *PppoeIaPacketTask {
+	var dpt PppoeIaPacketTask
+	dpt.pkt = pkt
+	dpt.device = dev
+	dpt.port = port
+	dpt.timestamp = (time.Now()).Format(time.RFC3339Nano)
+	return &dpt
+}
+
+// Name to return name for PppoeIaPacketTask
+func (dpt *PppoeIaPacketTask) Name() string {
+	return "DHCP Packet Task"
+}
+
+// TaskID to return task id for PppoeIaPacketTask
+func (dpt *PppoeIaPacketTask) TaskID() uint8 {
+	return dpt.taskID
+}
+
+// Timestamp to return timestamp for PppoeIaPacketTask
+func (dpt *PppoeIaPacketTask) Timestamp() string {
+	return dpt.timestamp
+}
+
+// Stop to stop the PppoeIaPacketTask
+func (dpt *PppoeIaPacketTask) Stop() {
+}
+
+// Start to start PppoeIaPacketTask
+func (dpt *PppoeIaPacketTask) Start(ctx context.Context, taskID uint8) error {
+	dpt.taskID = taskID
+	dpt.ctx = ctx
+	GetApplication().ProcessPPPoEIaPacket(dpt.device, dpt.port, dpt.pkt)
+	return nil
+}
