/*
* 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
}
