diff --git a/internal/pkg/application/igmp.go b/internal/pkg/application/igmp.go
index ba3f8fe..32eed0d 100644
--- a/internal/pkg/application/igmp.go
+++ b/internal/pkg/application/igmp.go
@@ -21,7 +21,6 @@
 	"net"
 	"reflect"
 	"voltha-go-controller/internal/pkg/types"
-	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -32,7 +31,6 @@
 	cntlr "voltha-go-controller/internal/pkg/controller"
 	"voltha-go-controller/database"
 	"voltha-go-controller/internal/pkg/of"
-	"voltha-go-controller/internal/pkg/util"
 	"voltha-go-controller/log"
 )
 
@@ -82,25 +80,6 @@
 	QueryExpiredDescription string = "igmp query expired"
 )
 
-// IgmpProfile structure
-type IgmpProfile struct {
-	ProfileID          string
-	UnsolicitedTimeOut uint32 //In seconds
-	MaxResp            uint32
-	KeepAliveInterval  uint32
-	KeepAliveCount     uint32
-	LastQueryInterval  uint32
-	LastQueryCount     uint32
-	FastLeave          bool
-	PeriodicQuery      bool
-	IgmpCos            uint8
-	WithRAUpLink       bool
-	WithRADownLink     bool
-	IgmpVerToServer    string
-	IgmpSourceIP       net.IP
-	Version            string
-}
-
 // McastConfig structure
 type McastConfig struct {
 	OltSerialNum   string
@@ -116,6 +95,8 @@
 var (
 	// NullIPAddr is null ip address var
 	NullIPAddr = net.ParseIP("0.0.0.0")
+	// AllSystemsMulticastGroupIP
+	AllSystemsMulticastGroupIP = net.ParseIP("224.0.0.1")
 	// igmpSrcMac for the proxy
 	igmpSrcMac string
 )
@@ -438,1509 +419,6 @@
 	return false
 }
 
-// IgmpGroupPort : IGMP port implements a port which is associated with an IGMP
-// version and the list of sources it implements for a given IGMP
-// channel. We may improve this to have all IGMP channels so that
-// we can implement per subscriber IGMP channel registration limits
-// As a rule a single port cannot have both include and exclude
-// lists. If we receive a include list we should purge the other
-// list which is TODO
-type IgmpGroupPort struct {
-	Port              string
-	CVlan             uint16
-	Pbit              uint8
-	Version           uint8
-	Exclude           bool
-	ExcludeList       []net.IP
-	IncludeList       []net.IP
-	QueryTimeoutCount uint32
-	PonPortID         uint32
-}
-
-// NewIgmpGroupPort is constructor for a port
-func NewIgmpGroupPort(port string, cvlan uint16, pbit uint8, version uint8, incl bool, ponPortID uint32) *IgmpGroupPort {
-	var igp IgmpGroupPort
-	igp.Port = port
-	igp.CVlan = cvlan
-	igp.Pbit = pbit
-	igp.Version = version
-	igp.Exclude = !incl
-	igp.QueryTimeoutCount = 0
-	igp.PonPortID = ponPortID
-	return &igp
-}
-
-// InclSourceIsIn checks if a source is in include list
-func (igp *IgmpGroupPort) InclSourceIsIn(src net.IP) bool {
-	return IsIPPresent(src, igp.IncludeList)
-}
-
-// ExclSourceIsIn checks if a source is in exclude list
-func (igp *IgmpGroupPort) ExclSourceIsIn(src net.IP) bool {
-	return IsIPPresent(src, igp.ExcludeList)
-}
-
-// AddInclSource adds a source is in include list
-func (igp *IgmpGroupPort) AddInclSource(src net.IP) {
-	logger.Debugw(ctx, "Adding Include Source", log.Fields{"Port": igp.Port, "Src": src})
-	igp.IncludeList = append(igp.IncludeList, src)
-}
-
-// AddExclSource adds a source is in exclude list
-func (igp *IgmpGroupPort) AddExclSource(src net.IP) {
-	logger.Debugw(ctx, "Adding Exclude Source", log.Fields{"Port": igp.Port, "Src": src})
-	igp.ExcludeList = append(igp.ExcludeList, src)
-}
-
-// DelInclSource deletes a source is in include list
-func (igp *IgmpGroupPort) DelInclSource(src net.IP) {
-	logger.Debugw(ctx, "Deleting Include Source", log.Fields{"Port": igp.Port, "Src": src})
-	for i, addr := range igp.IncludeList {
-		if addr.Equal(src) {
-			igp.IncludeList = append(igp.IncludeList[:i], igp.IncludeList[i+1:]...)
-			return
-		}
-	}
-}
-
-// DelExclSource deletes a source is in exclude list
-func (igp *IgmpGroupPort) DelExclSource(src net.IP) {
-	logger.Debugw(ctx, "Deleting Exclude Source", log.Fields{"Port": igp.Port, "Src": src})
-	for i, addr := range igp.ExcludeList {
-		if addr.Equal(src) {
-			igp.ExcludeList = append(igp.ExcludeList[:i], igp.ExcludeList[i+1:]...)
-			return
-		}
-	}
-}
-
-// WriteToDb is utility to write IGMP Group Port Info to database
-func (igp *IgmpGroupPort) WriteToDb(mvlan of.VlanType, gip net.IP, device string) error {
-	b, err := json.Marshal(igp)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutIgmpRcvr(mvlan, gip, device, igp.Port, string(b)); err1 != nil {
-		return err1
-	}
-	return nil
-}
-
-// NewIgmpGroupPortFromBytes create the IGMP group port from a byte slice
-func NewIgmpGroupPortFromBytes(b []byte) (*IgmpGroupPort, error) {
-	var igp IgmpGroupPort
-	if err := json.Unmarshal(b, &igp); err != nil {
-		logger.Warnw(ctx, "Decode of port failed", log.Fields{"str": string(b)})
-		return nil, err
-	}
-	return &igp, nil
-}
-
-// IgmpGroupChannel structure
-type IgmpGroupChannel struct {
-	Device       string
-	GroupID      uint32
-	GroupName    string
-	GroupAddr    net.IP
-	Mvlan        of.VlanType
-	Exclude      int
-	ExcludeList  []net.IP
-	IncludeList  []net.IP
-	Version      uint8
-	ServVersion  *uint8                    `json:"-"`
-	CurReceivers map[string]*IgmpGroupPort `json:"-"`
-	NewReceivers map[string]*IgmpGroupPort `json:"-"`
-	proxyCfg     **IgmpProfile
-	IgmpProxyIP  **net.IP                  `json:"-"`
-}
-
-// NewIgmpGroupChannel is constructor for a channel. The default IGMP version is set to 3
-// as the protocol defines the way to manage backward compatibility
-// The implementation handles simultaneous presense of lower versioned
-// receivers
-func NewIgmpGroupChannel(igd *IgmpGroupDevice, groupAddr net.IP, version uint8) *IgmpGroupChannel {
-	var igc IgmpGroupChannel
-	igc.Device = igd.Device
-	igc.GroupID = igd.GroupID
-	igc.GroupName = igd.GroupName
-	igc.GroupAddr = groupAddr
-	igc.Mvlan = igd.Mvlan
-	igc.Version = version
-	igc.CurReceivers = make(map[string]*IgmpGroupPort)
-	igc.NewReceivers = make(map[string]*IgmpGroupPort)
-	igc.proxyCfg = &igd.proxyCfg
-	igc.IgmpProxyIP = &igd.IgmpProxyIP
-	igc.ServVersion = igd.ServVersion
-	return &igc
-}
-
-// NewIgmpGroupChannelFromBytes create the IGMP group channel from a byte slice
-func NewIgmpGroupChannelFromBytes(b []byte) (*IgmpGroupChannel, error) {
-	var igc IgmpGroupChannel
-	if err := json.Unmarshal(b, &igc); err != nil {
-		return nil, err
-	}
-	igc.CurReceivers = make(map[string]*IgmpGroupPort)
-	igc.NewReceivers = make(map[string]*IgmpGroupPort)
-	return &igc, nil
-}
-
-// RestorePorts to restore ports
-func (igc *IgmpGroupChannel) RestorePorts() {
-
-	igc.migrateIgmpPorts()
-	ports, _ := db.GetIgmpRcvrs(igc.Mvlan, igc.GroupAddr, igc.Device)
-	for _, port := range ports {
-		b, ok := port.Value.([]byte)
-		if !ok {
-			logger.Warn(ctx, "The value type is not []byte")
-			continue
-		}
-		if igp, err := NewIgmpGroupPortFromBytes(b); err == nil {
-			igc.NewReceivers[igp.Port] = igp
-			logger.Infow(ctx, "Group Port Restored", log.Fields{"IGP": igp})
-		} else {
-			logger.Warn(ctx, "Failed to decode port from DB")
-		}
-	}
-	if err := igc.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-	}
-}
-
-// WriteToDb is utility to write IGMPGroupChannel Info to database
-func (igc *IgmpGroupChannel) WriteToDb() error {
-	b, err := json.Marshal(igc)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutIgmpChannel(igc.Mvlan, igc.GroupName, igc.Device, igc.GroupAddr, string(b)); err1 != nil {
-		return err1
-	}
-	logger.Info(ctx, "IGC Updated")
-	return nil
-}
-
-// UniPortList : UNI Port list per channle has stores the UNI port list for this
-// channel.
-type UniPortList struct {
-	UNIList *util.ConcurrentMap // [UNIPort] UNIPort
-}
-
-// NewUniPortsList is Constructor for UniPortList structure
-func NewUniPortsList() *UniPortList {
-	var uniPortsList UniPortList
-
-	uniPortsList.UNIList = util.NewConcurrentMap()
-	return &uniPortsList
-}
-
-// GetUniPortCount returns the number of UNI ports subscribed to
-// current channel.
-func (uniPortsList *UniPortList) GetUniPortCount() uint64 {
-	return uniPortsList.UNIList.Length()
-}
-
-// PonPortChannels : PON port channel map keeps the active channel list and its
-// count for this group.
-type PonPortChannels struct {
-	ChannelList *util.ConcurrentMap // [channelIP]*UniPortList
-}
-
-// NewPonPortChannels is constructor for PonPortChannel.
-func NewPonPortChannels() *PonPortChannels {
-	var ponPortChannel PonPortChannels
-
-	ponPortChannel.ChannelList = util.NewConcurrentMap()
-	return &ponPortChannel
-}
-
-// GetActiveChannelCount returns the number of active channel count
-// for this pon port in the current group.
-func (ponPortChannels *PonPortChannels) GetActiveChannelCount() uint32 {
-	return uint32(ponPortChannels.ChannelList.Length())
-}
-
-// AddChannelToMap Adds new channel to the pon port map
-func (ponPortChannels *PonPortChannels) AddChannelToMap(uniPort, channel string) bool {
-
-	isNewChannel := bool(false)
-	uniList, ok := ponPortChannels.ChannelList.Get(channel)
-	if !ok {
-		// Channel doesn't exists. Adding new channel.
-		uniList = NewUniPortsList()
-		isNewChannel = true
-	}
-	uniList.(*UniPortList).UNIList.Set(uniPort, uniPort)
-	ponPortChannels.ChannelList.Set(channel, uniList)
-	return isNewChannel
-}
-
-// RemoveChannelFromMap Removed channel from the pon port map
-func (ponPortChannels *PonPortChannels) RemoveChannelFromMap(uniPort, channel string) bool {
-
-	isDeleted := bool(false)
-	uniList, ok := ponPortChannels.ChannelList.Get(channel)
-	if ok {
-		uniList.(*UniPortList).UNIList.Remove(uniPort)
-		if uniList.(*UniPortList).UNIList.Length() == 0 {
-			// Last port from the channel is removed.
-			// Removing channel from PON port map.
-			ponPortChannels.ChannelList.Remove(channel)
-			isDeleted = true
-		} else {
-			ponPortChannels.ChannelList.Set(channel, uniList)
-		}
-	} else {
-		logger.Warnw(ctx, "Channel doesn't exists in the active channels list", log.Fields{"Channel": channel})
-		return isDeleted
-	}
-	return isDeleted
-}
-
-// IgmpGroupDevice : IGMP Group Device manages the IGMP group for all listerns on
-// a single OLT. It aggregates reports received on a single group
-// and performs the count. It is responsible for sending upstream
-// report when the first listener joins and is responsible for
-// sending responses to upstream queries
-type IgmpGroupDevice struct {
-	Device            string
-	SerialNo          string
-	GroupID           uint32
-	GroupName         string
-	GroupAddr         net.IP
-	RecvVersion       uint8
-	ServVersion       *uint8
-	RecvVersionExpiry time.Time
-	ServVersionExpiry time.Time
-	Mvlan             of.VlanType
-	PonVlan           of.VlanType
-	IsPonVlanPresent  bool
-	GroupInstalled    bool
-	GroupChannels     sync.Map            `json:"-"` // [ipAddr]*IgmpGroupChannel
-	PortChannelMap    sync.Map            `json:"-"` // [portName][]net.IP
-	PonPortChannelMap *util.ConcurrentMap `json:"-"` // [ponPortId]*PonPortChannels
-	proxyCfg          *IgmpProfile                   // IgmpSrcIp from IgmpProfile is not used, it is kept for backward compatibility
-	IgmpProxyIP       *net.IP             `json:"-"`
-	NextQueryTime     time.Time
-	QueryExpiryTime   time.Time
-}
-
-// NewIgmpGroupDevice is constructor for a device. The default IGMP version is set to 3
-// as the protocol defines the way to manage backward compatibility
-// The implementation handles simultaneous presense of lower versioned
-// receivers
-func NewIgmpGroupDevice(name string, ig *IgmpGroup, id uint32, version uint8) *IgmpGroupDevice {
-	var igd IgmpGroupDevice
-	igd.Device = name
-	igd.GroupID = id
-	igd.GroupName = ig.GroupName
-	igd.GroupAddr = ig.GroupAddr
-	igd.Mvlan = ig.Mvlan
-	igd.PonVlan = ig.PonVlan
-	igd.IsPonVlanPresent = ig.IsPonVlanPresent
-	igd.GroupInstalled = false
-	igd.RecvVersion = version
-	igd.RecvVersionExpiry = time.Now()
-	igd.ServVersionExpiry = time.Now()
-	igd.PonPortChannelMap = util.NewConcurrentMap()
-
-	va := GetApplication()
-	if vd := va.GetDevice(igd.Device); vd != nil {
-		igd.SerialNo = vd.SerialNum
-	} else {
-		logger.Errorw(ctx, "Volt Device not found.  log.Fields", log.Fields{"igd.Device": igd.Device})
-		return nil
-	}
-	mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
-	igd.ServVersion = mvp.IgmpServVersion[igd.SerialNo]
-
-	var mcastCfg *McastConfig
-	igd.proxyCfg, igd.IgmpProxyIP, mcastCfg = getIgmpProxyCfgAndIP(ig.Mvlan, igd.SerialNo)
-
-	// mvlan profile id + olt serial number---igmp group id
-	//igmpgroup id
-	igd.NextQueryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-	igd.QueryExpiryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-
-	if mcastCfg != nil {
-		mcastCfg.IgmpGroupDevices.Store(id, &igd)
-		logger.Debugw(ctx, "Igd added to mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": id})
-	}
-	return &igd
-}
-
-// IgmpGroupDeviceReInit is re-initializer for a device. The default IGMP version is set to 3
-// as the protocol defines the way to manage backward compatibility
-func (igd *IgmpGroupDevice) IgmpGroupDeviceReInit(ig *IgmpGroup) {
-
-	logger.Infow(ctx, "Reinitialize Igmp Group Device", log.Fields{"Device": igd.Device, "GroupID": ig.GroupID, "OldName": igd.GroupName, "Name": ig.GroupName, "OldAddr": igd.GroupAddr.String(), "GroupAddr": ig.GroupAddr.String()})
-
-	if (igd.GroupName != ig.GroupName) || !igd.GroupAddr.Equal(ig.GroupAddr) {
-		_ = db.DelIgmpDevice(igd.Mvlan, igd.GroupName, igd.GroupAddr, igd.Device)
-		igd.GroupName = ig.GroupName
-		igd.GroupAddr = ig.GroupAddr
-	}
-	igd.RecvVersionExpiry = time.Now()
-	igd.ServVersionExpiry = time.Now()
-	igd.PonPortChannelMap = util.NewConcurrentMap()
-
-	var mcastCfg *McastConfig
-	igd.proxyCfg, igd.IgmpProxyIP, mcastCfg = getIgmpProxyCfgAndIP(ig.Mvlan, igd.SerialNo)
-
-	igd.NextQueryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-	igd.QueryExpiryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-
-	if mcastCfg != nil {
-		mcastCfg.IgmpGroupDevices.Store(ig.GroupID, igd)
-		logger.Debugw(ctx, "Igd added to mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": ig.GroupID})
-	}
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-}
-
-func getIgmpProxyCfgAndIP(mvlan of.VlanType, serialNo string) (*IgmpProfile, *net.IP, *McastConfig) {
-	va := GetApplication()
-	mVLANProfileID := va.GetMvlanProfileByTag(mvlan).Name
-	var mcastCfg *McastConfig
-	if mcastCfg = va.GetMcastConfig(serialNo, mVLANProfileID); mcastCfg == nil || (mcastCfg != nil && mcastCfg.IgmpProfileID == "") {
-		logger.Debugw(ctx, "Default IGMP config to be used", log.Fields{"mVLANProfileID": mVLANProfileID, "OltSerialNo": serialNo})
-		igmpProf := va.getIgmpProfileMap(DefaultIgmpProfID)
-		return igmpProf, &igmpProf.IgmpSourceIP, mcastCfg
-	}
-	return va.getIgmpProfileMap(mcastCfg.IgmpProfileID), &mcastCfg.IgmpProxyIP, mcastCfg
-}
-
-// updateGroupName to update the group name
-func (igd *IgmpGroupDevice) updateGroupName(newGroupName string) {
-
-	oldName := igd.GroupName
-	igd.GroupName = newGroupName
-	updateGroupName := func(key, value interface{}) bool {
-		igc := value.(*IgmpGroupChannel)
-		igc.GroupName = newGroupName
-		if err := igc.WriteToDb(); err != nil {
-			logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-		}
-		_ = db.DelIgmpChannel(igc.Mvlan, oldName, igc.Device, igc.GroupAddr)
-		return true
-	}
-	igd.GroupChannels.Range(updateGroupName)
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-	_ = db.DelIgmpDevice(igd.Mvlan, oldName, igd.GroupAddr, igd.Device)
-}
-
-// NewIgmpGroupDeviceFromBytes is to create the IGMP group port from a byte slice
-func NewIgmpGroupDeviceFromBytes(b []byte) (*IgmpGroupDevice, error) {
-	var igd IgmpGroupDevice
-	if err := json.Unmarshal(b, &igd); err != nil {
-		return nil, err
-	}
-	return &igd, nil
-}
-
-// GetKey to get group name as key
-func (igd *IgmpGroupDevice) GetKey() string {
-
-	if !net.ParseIP("0.0.0.0").Equal(igd.GroupAddr) {
-		return igd.GroupName + "_" + igd.GroupAddr.String()
-	}
-	return igd.GroupName
-
-}
-
-// RestoreChannel to restore channel
-func (igd *IgmpGroupDevice) RestoreChannel(igmpGroupChannel []byte) {
-
-	if igc, err := NewIgmpGroupChannelFromBytes(igmpGroupChannel); err == nil {
-		igc.ServVersion = igd.ServVersion
-		igc.IgmpProxyIP = &igd.IgmpProxyIP
-		igc.proxyCfg = &igd.proxyCfg
-		igd.GroupChannels.Store(igc.GroupAddr.String(), igc)
-		igc.RestorePorts()
-
-		for port, igp := range igc.NewReceivers {
-			ipsList := []net.IP{}
-			ipsIntf, _ := igd.PortChannelMap.Load(port)
-			if ipsIntf != nil {
-				ipsList = ipsIntf.([]net.IP)
-			}
-
-			ipsList = append(ipsList, igc.GroupAddr)
-			igd.PortChannelMap.Store(port, ipsList)
-			logger.Infow(ctx, "Group Channels Restored", log.Fields{"IGC": igc})
-			igd.AddChannelToChannelsPerPon(port, igc.GroupAddr, igp.PonPortID)
-		}
-	} else {
-		logger.Warnw(ctx, "Failed to decode port from DB", log.Fields{"err": err})
-	}
-	logger.Info(ctx, "Group Device & Channels Restored")
-	igd.PortChannelMap.Range(printPortChannel)
-	igd.GroupChannels.Range(printChannel)
-
-}
-
-// RestoreChannels to restore channels
-func (igd *IgmpGroupDevice) RestoreChannels() {
-
-	igd.migrateIgmpChannels()
-	channels, _ := db.GetIgmpChannels(igd.Mvlan, igd.GroupName, igd.Device)
-	for _, channel := range channels {
-
-		b, ok := channel.Value.([]byte)
-		if !ok {
-			logger.Warn(ctx, "The value type is not []byte")
-			continue
-		}
-		igd.RestoreChannel(b)
-	}
-
-}
-
-// printChannel to print channel info
-func printChannel(key interface{}, value interface{}) bool {
-	logger.Infow(ctx, "ChannelMap", log.Fields{"Channel": key.(string), "Igc": value.(*IgmpGroupChannel)})
-	return true
-}
-
-// printPortChannel to print port channel
-func printPortChannel(key interface{}, value interface{}) bool {
-	logger.Infow(ctx, "PortChannelMap", log.Fields{"Port": key.(string), "List": value.([]net.IP)})
-	return true
-}
-
-// WriteToDb is utility to write IGMP Group Device Info to the database
-func (igd *IgmpGroupDevice) WriteToDb() error {
-	b, err := json.Marshal(igd)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutIgmpDevice(igd.Mvlan, igd.GroupName, igd.GroupAddr, igd.Device, string(b)); err1 != nil {
-		return err1
-	}
-	logger.Info(ctx, "IGD Updated")
-	return nil
-}
-
-// Tick processes timing tick used to run timers within the device
-func (igd *IgmpGroupDevice) Tick() uint8 {
-	/* Not using RecvVersionExpiry as it is not used anywhere
-	if time.Now().After(igd.RecvVersionExpiry) {
-		igd.RecvVersion = IgmpVersion3
-		return true
-	}
-	*/
-	return 0
-}
-
-// GetSubscriberCountForChannelAndPonPort Gets the active subscriber count
-// for the given channel for one particular PON port
-func (igd *IgmpGroupDevice) GetSubscriberCountForChannelAndPonPort(ponPortID uint32, channelIP net.IP) uint64 {
-	if portMapIntf, ok := igd.PonPortChannelMap.Get(ponPortID); ok {
-		portChannelMap := portMapIntf.(*PonPortChannels)
-
-		if channel, present := portChannelMap.ChannelList.Get(channelIP.String()); present {
-			return channel.(*UniPortList).UNIList.Length()
-		}
-	} else {
-		logger.Warnw(ctx, "PON port not found in PortChannelMap", log.Fields{"PON": ponPortID, "channel": channelIP})
-	}
-	return 0
-}
-
-// AddChannelToChannelsPerPon Adds the new channel into the per Pon channel list
-func (igd *IgmpGroupDevice) AddChannelToChannelsPerPon(uniPort string, channelIP net.IP, ponPortID uint32) bool {
-	logger.Debugw(ctx, "Adding channel to ActiveChannelsPerPon list", log.Fields{"PonPort": ponPortID, "channelIP": channelIP})
-
-	isNewChannel := bool(false)
-	isNewReceiver := false
-	if port, ok := igd.PonPortChannelMap.Get(ponPortID); !ok {
-		// PON port not exists in igd. adding it.
-		isNewReceiver = true
-		ponPortChannels := NewPonPortChannels()
-		isNewChannel = ponPortChannels.AddChannelToMap(uniPort, channelIP.String())
-		igd.PonPortChannelMap.Set(ponPortID, ponPortChannels)
-	} else {
-		// PON port exists in igd. Appending the channel list
-		// in the PON port.
-		isNewChannel = port.(*PonPortChannels).AddChannelToMap(uniPort, channelIP.String())
-		igd.PonPortChannelMap.Set(ponPortID, port)
-		count := port.(*PonPortChannels).GetActiveChannelCount()
-
-		logger.Debugw(ctx, "activeChannelCount", log.Fields{"count": count})
-	}
-	GetApplication().UpdateActiveChannelCountForPonPort(igd.Device, uniPort, ponPortID, true, isNewChannel, igd)
-	return isNewReceiver
-}
-
-// RemoveChannelFromChannelsPerPon removes the channel from the per pon channel list.
-func (igd *IgmpGroupDevice) RemoveChannelFromChannelsPerPon(uniPort string, channelIP net.IP, ponPortID uint32) bool {
-	logger.Debugw(ctx, "Removing channel from ActiveChannelsPerPon list", log.Fields{"PonPort": ponPortID, "channelIP": channelIP})
-	var deleted bool
-	ponRemoved := false
-
-	if port, ok := igd.PonPortChannelMap.Get(ponPortID); ok {
-		channelPortMap := port.(*PonPortChannels)
-		deleted = channelPortMap.RemoveChannelFromMap(uniPort, channelIP.String())
-		if deleted && channelPortMap.ChannelList.Length() == 0 {
-			igd.PonPortChannelMap.Remove(ponPortID)
-			ponRemoved = true
-		}
-		GetApplication().UpdateActiveChannelCountForPonPort(igd.Device, uniPort, ponPortID, false, deleted, igd)
-	} else {
-		logger.Warnw(ctx, "PON port doesn't exists in the igd", log.Fields{"PonPortID": ponPortID})
-	}
-	return ponRemoved
-}
-
-// InclSourceIsIn checks if a source is in include list
-func (igc *IgmpGroupChannel) InclSourceIsIn(src net.IP) bool {
-	return IsIPPresent(src, igc.IncludeList)
-}
-
-// ExclSourceIsIn checks if a source is in exclude list
-func (igc *IgmpGroupChannel) ExclSourceIsIn(src net.IP) bool {
-	return IsIPPresent(src, igc.ExcludeList)
-}
-
-// AddInclSource adds a source is in include list
-func (igc *IgmpGroupChannel) AddInclSource(src net.IP) {
-	logger.Debugw(ctx, "Adding Include Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Src": src})
-	igc.IncludeList = append(igc.IncludeList, src)
-}
-
-// AddExclSource adds a source is in exclude list
-func (igc *IgmpGroupChannel) AddExclSource(src net.IP) {
-	logger.Debugw(ctx, "Adding Exclude Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Src": src})
-	igc.ExcludeList = append(igc.ExcludeList, src)
-}
-
-// UpdateExclSource update excl source list for the given channel
-func (igc *IgmpGroupChannel) UpdateExclSource(srcList []net.IP) bool {
-
-	logger.Debugw(ctx, "Updating Exclude Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Current List": igc.ExcludeList, "Incoming List": srcList})
-	if !igc.IsExclListChanged(srcList) {
-		return false
-	}
-
-	if igc.NumReceivers() == 1 {
-		igc.ExcludeList = srcList
-	} else {
-		igc.ExcludeList = igc.computeExclList(srcList)
-	}
-
-	logger.Debugw(ctx, "Updated Exclude Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Updated Excl List": igc.ExcludeList})
-	return true
-}
-
-// computeExclList computes intersection of pervious & current src list
-func (igc *IgmpGroupChannel) computeExclList(srcList []net.IP) []net.IP {
-
-	updatedSrcList := []net.IP{}
-	for _, src := range srcList {
-		for _, excl := range igc.ExcludeList {
-			if src.Equal(excl) {
-				updatedSrcList = append(updatedSrcList, src)
-			}
-		}
-	}
-	return updatedSrcList
-}
-
-// IsExclListChanged checks if excl list has been updated
-func (igc *IgmpGroupChannel) IsExclListChanged(srcList []net.IP) bool {
-
-	srcPresent := false
-	if len(igc.ExcludeList) != len(srcList) {
-		return true
-	}
-
-	for _, src := range srcList {
-		for _, excl := range igc.ExcludeList {
-			srcPresent = false
-			if src.Equal(excl) {
-				srcPresent = true
-				break
-			}
-		}
-		if !srcPresent {
-			return true
-		}
-	}
-	return false
-}
-
-// DelInclSource deletes a source is in include list
-func (igc *IgmpGroupChannel) DelInclSource(src net.IP) {
-	mvp := GetApplication().GetMvlanProfileByTag(igc.Mvlan)
-	/* If the SSM proxy is configured, then we can del the src ip from igc as whatever is in proxy that is final list */
-	if _, ok := mvp.Proxy[igc.GroupName]; !ok {
-		logger.Debugw(ctx, "Deleting Include Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Src": src})
-		for _, igp := range igc.CurReceivers {
-			if igp.InclSourceIsIn(src) {
-				logger.Infow(ctx, "Skipping deletion: Source Present for another Receiver", log.Fields{"Receiver": igp.Port})
-				return
-			}
-		}
-		for _, igp := range igc.NewReceivers {
-			if igp.InclSourceIsIn(src) {
-				logger.Infow(ctx, "Skipping deletion: Source Present for another Receiver", log.Fields{"Receiver": igp.Port})
-				return
-			}
-		}
-	} else {
-		logger.Debug(ctx, "Proxy configured, not Deleting Include Source for Channel")
-	}
-	for i, addr := range igc.IncludeList {
-		if addr.Equal(src) {
-			igc.IncludeList = append(igc.IncludeList[:i], igc.IncludeList[i+1:]...)
-			return
-		}
-	}
-}
-
-// DelExclSource deletes a source is in exclude list
-func (igc *IgmpGroupChannel) DelExclSource(src net.IP) {
-	logger.Debugw(ctx, "Deleting Exclude Source for Channel", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device, "Src": src})
-
-	for _, igp := range igc.CurReceivers {
-		if igp.ExclSourceIsIn(src) {
-			logger.Infow(ctx, "Skipping deletion: Source Present for another Receiver", log.Fields{"Receiver": igp.Port})
-			return
-		}
-	}
-	for _, igp := range igc.NewReceivers {
-		if igp.ExclSourceIsIn(src) {
-			logger.Infow(ctx, "Skipping deletion: Source Present for another Receiver", log.Fields{"Receiver": igp.Port})
-			return
-		}
-	}
-	for i, addr := range igc.ExcludeList {
-		if addr.Equal(src) {
-			igc.ExcludeList = append(igc.ExcludeList[:i], igc.ExcludeList[i+1:]...)
-			return
-		}
-	}
-}
-
-// ProcessSources process the received list of either included sources or the excluded sources
-// The return value indicate sif the group is modified and needs to be informed
-// to the upstream multicast servers
-func (igc *IgmpGroupChannel) ProcessSources(port string, ip []net.IP, incl bool) (bool, bool) {
-	groupChanged := false
-	groupExclUpdated := false
-	receiverSrcListEmpty := false
-	// If the version type is 2, there isn't anything to process here
-	if igc.Version == IgmpVersion2 && *igc.ServVersion == IgmpVersion2 {
-		return false, false
-	}
-
-	igp := igc.GetReceiver(port)
-	if igp == nil {
-		logger.Warnw(ctx, "Receiver not found", log.Fields{"Port": port})
-		return false, false
-	}
-	mvp := GetApplication().GetMvlanProfileByTag(igc.Mvlan)
-	if incl {
-		for _, src := range ip {
-
-			if igp.ExclSourceIsIn(src) {
-				igp.DelExclSource(src)
-				if igc.ExclSourceIsIn(src) {
-					igc.DelExclSource(src)
-					groupChanged = true
-				}
-			}
-
-			// If the source is not in the list of include sources for the port
-			// add it. If so, check also if it is in list of include sources
-			// at the device level.
-			if !igp.InclSourceIsIn(src) {
-				igp.AddInclSource(src)
-				if !igc.InclSourceIsIn(src) {
-					igc.AddInclSource(src)
-					groupChanged = true
-				}
-			}
-		}
-		/* If any of the existing ip in the source list is removed we need to remove from the list in igp and igc */
-		if _, ok := mvp.Proxy[igc.GroupName]; ok {
-			/* If we get leave message from any subscriber, we do not have to delete the entries in the src list
-			   Only if ther is any modification in the src list by proxy config update only then we need to update */
-			if len(ip) != 0 && len(ip) != len(igc.IncludeList) {
-				for i := len(igc.IncludeList) - 1; i >= 0; i-- {
-					src := igc.IncludeList[i]
-					if !IsIPPresent(src, ip) {
-						igp.DelInclSource(src)
-						igc.DelInclSource(src)
-						groupChanged = true
-					}
-				}
-			}
-		}
-	} else {
-		for _, src := range ip {
-
-			if igp.InclSourceIsIn(src) {
-				igp.DelInclSource(src)
-				if igc.InclSourceIsIn(src) {
-					igc.DelInclSource(src)
-					groupChanged = true
-				}
-				if len(igp.IncludeList) == 0 {
-					receiverSrcListEmpty = true
-				}
-			}
-
-			// If the source is not in the list of exclude sources for the port
-			// add it. If so, check also if it is in list of include sources
-			// at the device level.
-			if !igp.ExclSourceIsIn(src) {
-				igp.AddExclSource(src)
-				/* If there is any update in the src list of proxy we need to update the igc */
-				if _, ok := mvp.Proxy[igc.GroupName]; ok {
-					if !igc.ExclSourceIsIn(src) {
-						igc.AddExclSource(src)
-						groupChanged = true
-					}
-				}
-			}
-		}
-		/* If any of the existing ip in the source list is removed we need to remove from the list in igp and igc */
-		if _, ok := mvp.Proxy[igc.GroupName]; ok {
-			if len(ip) != len(igc.ExcludeList) {
-				for i := len(igc.ExcludeList) - 1; i >= 0; i-- {
-					src := igc.ExcludeList[i]
-					if !IsIPPresent(src, ip) {
-						igp.DelExclSource(src)
-						igc.DelExclSource(src)
-						groupChanged = true
-					}
-				}
-			}
-		}
-		groupExclUpdated = igc.UpdateExclSource(ip)
-	}
-	if err := igp.WriteToDb(igc.Mvlan, igc.GroupAddr, igc.Device); err != nil {
-		logger.Errorw(ctx, "Igmp group port Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-	}
-	return (groupChanged || groupExclUpdated), receiverSrcListEmpty
-}
-
-// GetReceiver to get receiver info
-func (igc *IgmpGroupChannel) GetReceiver(port string) *IgmpGroupPort {
-	igp := igc.NewReceivers[port]
-	if igp == nil {
-		igp = igc.CurReceivers[port]
-	}
-	return igp
-}
-
-// AddReceiver add the receiver to the device and perform other actions such as adding the group
-// to the physical device, add members, add flows to point the MC packets to the
-// group. Also, send a IGMP report upstream if there is a change in the group
-func (igd *IgmpGroupDevice) AddReceiver(port string, groupAddr net.IP,
-	group *layers.IGMPv3GroupRecord, version uint8, cvlan uint16, pbit uint8, ponPortID uint32) {
-
-	var igc *IgmpGroupChannel
-	logger.Debugw(ctx, "Processing receiver for device", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})
-
-	igcIntf, ok := igd.GroupChannels.Load(groupAddr.String())
-	if !ok {
-		igc = NewIgmpGroupChannel(igd, groupAddr, version)
-		igd.GroupChannels.Store(groupAddr.String(), igc)
-	} else {
-		igc = igcIntf.(*IgmpGroupChannel)
-	}
-
-	if !igd.GroupInstalled {
-		igd.AddNewReceiver(port, groupAddr, group, cvlan, pbit, ponPortID)
-		return
-	}
-
-	isNewReceiver := igc.AddReceiver(port, group, cvlan, pbit)
-	if isNewReceiver {
-		ipsList := []net.IP{}
-		ipsIntf, _ := igd.PortChannelMap.Load(port)
-		if ipsIntf != nil {
-			ipsList = ipsIntf.([]net.IP)
-		}
-		ipsList = append(ipsList, groupAddr)
-		igd.PortChannelMap.Store(port, ipsList)
-		logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "AddedChannelList": ipsList, "Addr": groupAddr})
-
-		isNewPonReceiver := igd.AddChannelToChannelsPerPon(port, groupAddr, ponPortID)
-		//Modify group only if this is the first time the port is subscribing for the group
-		if isNewPonReceiver {
-			igd.ModMcGroup()
-		}
-	}
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-}
-
-// AddNewReceiver to add new receiver
-func (igd *IgmpGroupDevice) AddNewReceiver(port string, groupAddr net.IP, group *layers.IGMPv3GroupRecord, cvlan uint16, pbit uint8, ponPortID uint32) {
-
-	logger.Debugw(ctx, "Adding New Device Receiver", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})
-	igcIntf, _ := igd.GroupChannels.Load(groupAddr.String())
-	if igcIntf == nil {
-		logger.Warnw(ctx, "No Group Channel present for given channel", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})
-		return
-	}
-
-	igc := igcIntf.(*IgmpGroupChannel)
-	ipsList := []net.IP{}
-	ipsIntf, _ := igd.PortChannelMap.Load(port)
-	if ipsIntf != nil {
-		ipsList = ipsIntf.([]net.IP)
-	}
-	ipsList = append(ipsList, groupAddr)
-	igd.PortChannelMap.Store(port, ipsList)
-	igd.AddChannelToChannelsPerPon(port, groupAddr, ponPortID)
-	logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "NewChannelList": ipsList, "Addr": groupAddr})
-
-	igd.AddMcGroup()
-	igc.AddReceiver(port, group, cvlan, pbit)
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-}
-
-// AddReceiver add the receiver to the device and perform other actions such as adding the group
-// to the physical device, add members, add flows to point the MC packets to the
-// group. Also, send a IGMP report upstream if there is a change in the group
-func (igc *IgmpGroupChannel) AddReceiver(port string, group *layers.IGMPv3GroupRecord, cvlan uint16, pbit uint8) bool {
-
-	var igp *IgmpGroupPort
-	var groupModified = false
-	var isNewReceiver = false
-
-	var ip []net.IP
-	incl := false
-	mvp := GetApplication().GetMvlanProfileByTag(igc.Mvlan)
-	if _, ok := mvp.Proxy[igc.GroupName]; ok {
-		if mvp.Proxy[igc.GroupName].Mode == common.Include {
-			incl = true
-		}
-		ip = mvp.Proxy[igc.GroupName].SourceList
-	} else if group != nil {
-		incl = isIncl(group.Type)
-		ip = group.SourceAddresses
-	}
-	logger.Debugw(ctx, "Attempting to add receiver", log.Fields{"Version": igc.Version, "Port": port, "Incl": incl, "srcIp": ip})
-
-	//logger.Infow(ctx, "Receivers", log.Fields{"New": igc.NewReceivers, "Current": igc.CurReceivers})
-	logger.Debugw(ctx, "Receiver Group", log.Fields{"Igd GId": igc.GroupID})
-	logger.Debugw(ctx, "Receiver Channel", log.Fields{"Igd addr": igc.GroupAddr})
-	logger.Debugw(ctx, "Receiver Mvlan", log.Fields{"Igd mvlan": igc.Mvlan})
-	logger.Debugw(ctx, "Receiver Sources", log.Fields{"Igd addr": ip})
-
-	ponPortID := GetApplication().GetPonPortID(igc.Device, port)
-
-	// Process the IGMP receiver. If it is already in, we should only process the changes
-	// to source list.
-	var newRcvExists bool
-	igp, newRcvExists = igc.NewReceivers[port]
-	if !newRcvExists {
-		// Add the receiver to the list of receivers and make the necessary group modification
-		// if this is the first time the receiver is added
-		var curRcvExists bool
-		if igp, curRcvExists = igc.CurReceivers[port]; curRcvExists {
-			logger.Debugw(ctx, "Existing IGMP receiver", log.Fields{"Group": igc.GroupAddr.String(), "Port": port})
-			delete(igc.CurReceivers, port)
-			igp.QueryTimeoutCount = 0
-			igc.NewReceivers[port] = igp
-		} else {
-			// New receiver who wasn't part of earlier list
-			// Need to send out IGMP group modification for this port
-			igp = NewIgmpGroupPort(port, cvlan, pbit, igc.Version, incl, uint32(ponPortID))
-			igc.NewReceivers[port] = igp
-			isNewReceiver = true
-			logger.Debugw(ctx, "New IGMP receiver", log.Fields{"Group": igc.GroupAddr.String(), "Port": port})
-			if len(igc.NewReceivers) == 1 && len(igc.CurReceivers) == 0 {
-				groupModified = true
-				igc.AddMcFlow()
-				logger.Debugw(ctx, "Added New Flow", log.Fields{"Group": igc.GroupAddr.String(), "Port": port})
-			}
-			if !incl {
-				igc.Exclude++
-			}
-		}
-	}
-
-	// Process the include/exclude list which may end up modifying the group
-	if change, _ := igc.ProcessSources(port, ip, incl); change {
-		groupModified = true
-	}
-	igc.ProcessMode(port, incl)
-
-	// If the group is modified as this is the first receiver or due to include/exclude list modification
-	// send a report to the upstream multicast servers
-	if groupModified {
-		logger.Debug(ctx, "Group Modified and IGMP report sent to the upstream server")
-		igc.SendReport(false)
-	} else if newRcvExists {
-		return false
-	}
-
-	logger.Debugw(ctx, "Channel Receiver Added", log.Fields{"Group Channel": igc.GroupAddr, "Group Port": igp})
-
-	if err := igc.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-	}
-	if err := igp.WriteToDb(igc.Mvlan, igc.GroupAddr, igc.Device); err != nil {
-		logger.Errorw(ctx, "Igmp group port Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-	}
-	return isNewReceiver
-}
-
-// DelReceiver is called when Query expiry happened for a receiver. This removes the receiver from the
-// the group
-func (igc *IgmpGroupChannel) DelReceiver(port string, incl bool, srcList []net.IP) bool {
-	// The receiver may exist either in NewReceiver list or
-	// the CurReceivers list. Find and remove it from either
-	// of the lists.
-	logger.Debugw(ctx, "Deleting Receiver from Channel", log.Fields{"Port": port, "SrcList": srcList, "Incl": incl})
-	logger.Debugw(ctx, "New Receivers", log.Fields{"New": igc.NewReceivers})
-	logger.Debugw(ctx, "Current Receivers", log.Fields{"Current": igc.CurReceivers})
-
-	receiversUpdated := false
-	groupModified, receiverSrcListEmpty := igc.ProcessSources(port, srcList, incl)
-
-	if len(srcList) == 0 || len(igc.IncludeList) == 0 || receiverSrcListEmpty {
-		if igp, ok := igc.NewReceivers[port]; ok {
-			logger.Debug(ctx, "Deleting from NewReceivers")
-			delete(igc.NewReceivers, port)
-			receiversUpdated = true
-			if igp.Exclude {
-				igc.Exclude--
-			}
-		} else {
-			if igp, ok1 := igc.CurReceivers[port]; ok1 {
-				logger.Debug(ctx, "Deleting from CurReceivers")
-				delete(igc.CurReceivers, port)
-				receiversUpdated = true
-				if igp.Exclude {
-					igc.Exclude--
-				}
-			} else {
-				logger.Debug(ctx, "Receiver doesnot exist. Dropping Igmp leave")
-				return false
-			}
-		}
-		_ = db.DelIgmpRcvr(igc.Mvlan, igc.GroupAddr, igc.Device, port)
-	}
-
-	if igc.NumReceivers() == 0 {
-		igc.DelMcFlow()
-		mvp := GetApplication().GetMvlanProfileByTag(igc.Mvlan)
-		/* If proxy is configured and NumReceivers is 0, then we can reset the igc src list so that we send leave */
-		if _, ok := mvp.Proxy[igc.GroupName]; ok {
-			igc.IncludeList = []net.IP{}
-		}
-		igc.SendLeaveToServer()
-		logger.Debugw(ctx, "Deleted the receiver Flow", log.Fields{"Num Receivers": igc.NumReceivers()})
-		return true
-	}
-	if groupModified {
-		igc.SendReport(false)
-		logger.Infow(ctx, "Updated SourceList for Channel", log.Fields{"Current": igc.CurReceivers, "New": igc.NewReceivers})
-	}
-	if err := igc.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-	}
-	logger.Infow(ctx, "Updated Receiver info for Channel", log.Fields{"Current": igc.CurReceivers, "New": igc.NewReceivers})
-
-	return receiversUpdated
-}
-
-// NumReceivers to get number of receivers
-func (igd *IgmpGroupDevice) NumReceivers() int {
-	var numReceivers int
-	len := func(key interface{}, value interface{}) bool {
-		numReceivers++
-		return true
-	}
-	igd.PortChannelMap.Range(len)
-	return numReceivers
-}
-
-// DelReceiver is called when Query expiry happened for a receiver. This removes the receiver from the
-// the group
-func (igd *IgmpGroupDevice) DelReceiver(groupAddr net.IP, port string, group *layers.IGMPv3GroupRecord, ponPortID uint32) {
-
-	logger.Debugw(ctx, "Deleting Receiver for Device", log.Fields{"port": port, "GroupIP": groupAddr.String()})
-	var igc *IgmpGroupChannel
-	var igcIntf interface{}
-	var ok bool
-	var srcList []net.IP
-	incl := false
-	mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
-
-	if _, ok := mvp.Proxy[igd.GroupName]; ok {
-		incl = true
-	} else if group != nil {
-		srcList = group.SourceAddresses
-		incl = isIncl(group.Type)
-	}
-
-	if igcIntf, ok = igd.GroupChannels.Load(groupAddr.String()); !ok {
-		logger.Warnw(ctx, "Igmp Channel for group IP doesnt exist", log.Fields{"GroupAddr": groupAddr.String()})
-		return
-	}
-	igc = igcIntf.(*IgmpGroupChannel)
-	if ok := igc.DelReceiver(port, incl, srcList); !ok {
-		return
-	}
-
-	if igc.NumReceivers() == 0 {
-		igd.DelIgmpGroupChannel(igc)
-	}
-	igd.DelPortFromChannel(port, groupAddr)
-	isGroupModified := igd.RemoveChannelFromChannelsPerPon(port, groupAddr, ponPortID)
-
-	//Remove port from receiver if port has no subscription to any of the group channels
-	if isGroupModified {
-		igd.ModMcGroup()
-	}
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-}
-
-// DelChannelReceiver is called when Query expiry happened for a receiver. This removes the receiver from the
-// the group
-func (igd *IgmpGroupDevice) DelChannelReceiver(groupAddr net.IP) map[string]*IgmpGroupPort {
-
-	portsRemoved := make(map[string]*IgmpGroupPort)
-	groupModified := false
-	// ifEmpty := true
-	igcIntf, _ := igd.GroupChannels.Load(groupAddr.String())
-
-	if igcIntf == nil {
-		return portsRemoved
-	}
-	igc := igcIntf.(*IgmpGroupChannel)
-
-	for port, igp := range igc.NewReceivers {
-		_ = db.DelIgmpRcvr(igc.Mvlan, igc.GroupAddr, igc.Device, port) //TODO: Y not here
-		igd.DelPortFromChannel(port, igc.GroupAddr)
-		ponPortID := GetApplication().GetPonPortID(igd.Device, port)
-		groupModified = igd.RemoveChannelFromChannelsPerPon(port, igc.GroupAddr, ponPortID)
-		delete(igc.NewReceivers, port)
-		portsRemoved[port] = igp
-	}
-	for port, igp := range igc.CurReceivers {
-		_ = db.DelIgmpRcvr(igc.Mvlan, igc.GroupAddr, igc.Device, port)
-		igd.DelPortFromChannel(port, igc.GroupAddr)
-		ponPortID := GetApplication().GetPonPortID(igd.Device, port)
-		groupModified = igd.RemoveChannelFromChannelsPerPon(port, igc.GroupAddr, ponPortID)
-		delete(igc.CurReceivers, port)
-		portsRemoved[port] = igp
-	}
-
-	igc.DelMcFlow()
-	igd.DelIgmpGroupChannel(igc)
-	igc.Exclude = 0
-	igc.SendLeaveToServer()
-
-	if groupModified {
-		igd.ModMcGroup()
-	}
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-	logger.Debugw(ctx, "Deleted the receiver Flow", log.Fields{"Num Receivers": igc.NumReceivers()})
-	return portsRemoved
-}
-
-// DelIgmpGroupChannel to delete igmp group channel
-func (igd *IgmpGroupDevice) DelIgmpGroupChannel(igc *IgmpGroupChannel) {
-
-	if igc.NumReceivers() != 0 {
-		igc.DelAllReceivers()
-	}
-	_ = db.DelIgmpChannel(igc.Mvlan, igc.GroupName, igc.Device, igc.GroupAddr)
-	igd.GroupChannels.Delete(igc.GroupAddr.String())
-	logger.Infow(ctx, "Deleted the Channel from Device", log.Fields{"Channel": igc.GroupAddr.String()})
-	isLenZero := true
-	checkIfEmpty := func(key interface{}, value interface{}) bool {
-		isLenZero = false
-		return false
-	}
-	igd.GroupChannels.Range(checkIfEmpty)
-	if isLenZero {
-		logger.Infow(ctx, "No more active channels. Deleting MC Group", log.Fields{"Device": igd.Device, "Group": igd.GroupName})
-		igd.DelMcGroup(false)
-	}
-}
-
-// func (igd *IgmpGroupDevice) DelIgmpChannel(igc *IgmpGroupChannel) {
-// 	db.DelIgmpChannel(igc.GroupName, igc.Device, igc.GroupAddr)
-// 	delete(igd.GroupChannels, igc.GroupAddr.String())
-// 	logger.Debugw(ctx, "Deleted the Channel", log.Fields{"Num Receivers": igc.NumReceivers()})
-// }
-
-// DelPortFromChannel to delete port from channel
-func (igd *IgmpGroupDevice) DelPortFromChannel(port string, groupAddr net.IP) bool {
-	ipsList := []net.IP{}
-	ipsListIntf, _ := igd.PortChannelMap.Load(port)
-	if ipsListIntf != nil {
-		ipsList = ipsListIntf.([]net.IP)
-	}
-	for i, addr := range ipsList {
-		if addr.Equal(groupAddr) {
-			ipsList = append(ipsList[:i], ipsList[i+1:]...)
-			//Remove port from receiver if port has no subscription to any of the group channels
-			if len(ipsList) == 0 {
-				igd.PortChannelMap.Delete(port)
-			} else {
-				//Update the map with modified ips list
-				igd.PortChannelMap.Store(port, ipsList)
-			}
-			logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "DelChannelList": ipsList, "Addr": groupAddr.String()})
-			return true
-		}
-	}
-	return false
-}
-
-// DelIgmpGroup deletes all devices for the provided igmp group
-func (ig *IgmpGroup) DelIgmpGroup() {
-	logger.Infow(ctx, "Deleting All Device for Group", log.Fields{"Group": ig.GroupName})
-	for _, igd := range ig.Devices {
-		ig.DelIgmpGroupDevice(igd)
-	}
-	GetApplication().DelIgmpGroup(ig)
-}
-
-// DelAllChannels deletes all receiver for the provided igmp device
-func (igd *IgmpGroupDevice) DelAllChannels() {
-	logger.Infow(ctx, "Deleting All Channel for Device", log.Fields{"Device": igd.Device, "Group": igd.GroupName})
-	delGroupChannels := func(key interface{}, value interface{}) bool {
-		igc := value.(*IgmpGroupChannel)
-		igd.DelIgmpGroupChannel(igc)
-		return true
-	}
-	igd.GroupChannels.Range(delGroupChannels)
-}
-
-// DelAllReceivers deletes all receiver for the provided igmp device
-func (igc *IgmpGroupChannel) DelAllReceivers() {
-	logger.Infow(ctx, "Deleting All Receiver for Channel", log.Fields{"Device": igc.Device, "Channel": igc.GroupAddr.String()})
-	_ = db.DelAllIgmpRcvr(igc.Mvlan, igc.GroupAddr, igc.Device)
-	igc.Exclude = 0
-	igc.DelMcFlow()
-	igc.SendLeaveToServer()
-	logger.Infow(ctx, "MC Flow deleted and Leave sent", log.Fields{"Channel": igc.GroupAddr.String(), "Device": igc.Device})
-}
-
-// ProcessQuery process query received from the upstream IGMP server
-func (igd *IgmpGroupDevice) ProcessQuery(groupAddr net.IP, ver uint8) {
-	logger.Debugw(ctx, "Received Query From Server", log.Fields{"Version": ver})
-	if ver != *igd.ServVersion {
-		igd.ServVersionExpiry = time.Now().Add(time.Duration(2*igd.proxyCfg.KeepAliveInterval) * time.Second)
-		*igd.ServVersion = ver
-		mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
-		if err := mvp.WriteToDb(); err != nil {
-			logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
-		}
-	}
-	if igc, ok := igd.GroupChannels.Load(groupAddr.String()); ok {
-		igc.(*IgmpGroupChannel).SendReport(true)
-		return
-	}
-	logger.Infow(ctx, "No Members for Channel. Dropping Igmp Query", log.Fields{"Group": igd.GroupName, "Channel": groupAddr.String()})
-}
-
-// Igmpv2ReportPacket build an IGMPv2 Report for the upstream servers
-func (igc *IgmpGroupChannel) Igmpv2ReportPacket() ([]byte, error) {
-	logger.Debugw(ctx, "Buidling IGMP version 2 Report", log.Fields{"Device": igc.Device})
-	return IgmpReportv2Packet(igc.GroupAddr, igc.Mvlan, (*igc.proxyCfg).IgmpCos, **igc.IgmpProxyIP)
-}
-
-// Igmpv3ReportPacket build an IGMPv3 Report for the upstream servers
-func (igc *IgmpGroupChannel) Igmpv3ReportPacket() ([]byte, error) {
-	logger.Debugw(ctx, "Buidling IGMP version 3 Report", log.Fields{"Device": igc.Device, "Exclude": igc.Exclude})
-	if igc.Exclude > 0 {
-		return Igmpv3ReportPacket(igc.GroupAddr, igc.Mvlan, (*igc.proxyCfg).IgmpCos, **igc.IgmpProxyIP, false, igc.ExcludeList)
-	}
-	return Igmpv3ReportPacket(igc.GroupAddr, igc.Mvlan, (*igc.proxyCfg).IgmpCos, **igc.IgmpProxyIP, true, igc.IncludeList)
-}
-
-// SendReport send a consolidated report to the server
-func (igc *IgmpGroupChannel) SendReport(isQuery bool) {
-	var report []byte
-	var err error
-	logger.Debugw(ctx, "Checking Version", log.Fields{"IGC Version": igc.Version, "Proxy Version": (*igc.proxyCfg).IgmpVerToServer,
-		"Result": (getVersion((*igc.proxyCfg).IgmpVerToServer) == IgmpVersion2)})
-
-	/**
-	                               +------------------------------------------------------------------------+
-	                               |         IGMP version(towards BNG) Configured at VGC                    |
-	                               +-------------------------------+----------------------------------------+
-	                               |                  v2           |                 v3                     |
-	+===================+==========+===============================+========================================+
-	| Received From RG  | V2 Join  | Process and Send as V2 to BNG | Process, Convert to v3 and Send to BNG |
-	|                   |          |                               | Process, Send as v2, if the BNG is v2  |
-	+===================+----------+-------------------------------+----------------------------------------+
-	                    | V3 Join  | Process and Send as V2 to BNG | Process, Send v3 to BNG                |
-	                    |          |                               | Process, Convert, Send as v2, if the   |
-	                    |          |                               | BNG is v2                              |
-	+===================+==========+===============================+========================================+
-	| Received From BNG | V2 Query | V2 response to BNG            | V2 response to BNG                     |
-	+===================+----------+-------------------------------+----------------------------------------+
-	                    | V3 Query | Discard                       | V3 response to BNG                     |
-	                    +==========+===============================+========================================+
-	*/
-	// igc.Version: 	igmp version received from RG.
-	// igc.ServVersion: igmp version received from BNG or IgmpVerToServer present in proxy igmp conf.
-
-	if isQuery && *igc.ServVersion == IgmpVersion3 && getVersion((*igc.proxyCfg).IgmpVerToServer) == IgmpVersion2 {
-		// This is the last scenario where we must discard the query processing.
-		logger.Debug(ctx, "Dropping query packet since the server verion is v3 but igmp proxy version is v2")
-		return
-	}
-
-	if *igc.ServVersion == IgmpVersion2 || getVersion((*igc.proxyCfg).IgmpVerToServer) == IgmpVersion2 {
-		report, err = igc.Igmpv2ReportPacket()
-	} else {
-		report, err = igc.Igmpv3ReportPacket()
-	}
-	if err != nil {
-		logger.Warnw(ctx, "Error Preparing Report", log.Fields{"Device": igc.Device, "Ver": igc.Version, "Reason": err.Error()})
-		return
-	}
-	nni, err := GetApplication().GetNniPort(igc.Device)
-	if err == nil {
-		_ = cntlr.GetController().PacketOutReq(igc.Device, nni, nni, report, false)
-	} else {
-		logger.Warnw(ctx, "Didn't find NNI port", log.Fields{"Device": igc.Device})
-	}
-}
-
-// AddMcFlow adds flow to the device when the first receiver joins
-func (igc *IgmpGroupChannel) AddMcFlow() {
-	flow, err := igc.BuildMcFlow()
-	if err != nil {
-		logger.Warnw(ctx, "MC Flow Build Failed", log.Fields{"Reason": err.Error()})
-		return
-	}
-	port, _ := GetApplication().GetNniPort(igc.Device)
-	_ = cntlr.GetController().AddFlows(port, igc.Device, flow)
-}
-
-// DelMcFlow deletes flow from the device when the last receiver leaves
-func (igc *IgmpGroupChannel) DelMcFlow() {
-	flow, err := igc.BuildMcFlow()
-	if err != nil {
-		logger.Warnw(ctx, "MC Flow Build Failed", log.Fields{"Reason": err.Error()})
-		return
-	}
-	flow.ForceAction = true
-	device := GetApplication().GetDevice(igc.Device)
-
-	if mvpIntf, _ := GetApplication().MvlanProfilesByTag.Load(igc.Mvlan); mvpIntf != nil {
-		mvp := mvpIntf.(*MvlanProfile)
-		err := mvp.DelFlows(device, flow)
-		if err != nil {
-			logger.Warnw(ctx, "Delering IGMP Flow for device failed ", log.Fields{"Device": device, "err": err})
-		}
-	}
-}
-
-// BuildMcFlow builds the flow using which it is added/deleted
-func (igc *IgmpGroupChannel) BuildMcFlow() (*of.VoltFlow, error) {
-	flow := &of.VoltFlow{}
-	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
-	//va := GetApplication()
-	logger.Infow(ctx, "Building Mcast flow", log.Fields{"Mcast Group": igc.GroupAddr.String(), "Mvlan": igc.Mvlan.String()})
-	uintGroupAddr := ipv4ToUint(igc.GroupAddr)
-	subFlow := of.NewVoltSubFlow()
-	subFlow.SetMatchVlan(igc.Mvlan)
-	subFlow.SetIpv4Match()
-	subFlow.SetMatchDstIpv4(igc.GroupAddr)
-	mvp := GetApplication().GetMvlanProfileByTag(igc.Mvlan)
-	//nni, err := va.GetNniPort(igc.Device)
-	//if err != nil {
-	//	return nil, err
-	//}
-	//inport, err := va.GetPortID(nni)
-	//if err != nil {
-	//	return nil, err
-	//}
-	//subFlow.SetInPort(inport)
-	subFlow.SetOutGroup(igc.GroupID)
-	cookiePort := uintGroupAddr
-	subFlow.Cookie = uint64(cookiePort)<<32 | uint64(igc.Mvlan)
-	subFlow.Priority = of.McFlowPriority
-	metadata := uint64(mvp.PonVlan)
-	subFlow.SetTableMetadata(metadata)
-
-	flow.SubFlows[subFlow.Cookie] = subFlow
-	logger.Infow(ctx, "Built Mcast flow", log.Fields{"cookie": subFlow.Cookie, "subflow": subFlow})
-	return flow, nil
-}
-
-//DelFlows - Triggers flow deletion after registering for flow indication event
-func (mvp *MvlanProfile) DelFlows(device *VoltDevice, flow *of.VoltFlow) error {
-	mvp.mvpFlowLock.Lock()
-	defer mvp.mvpFlowLock.Unlock()
-
-	var flowMap map[string]bool
-	var ok bool
-
-	for cookie := range flow.SubFlows {
-		cookie := strconv.FormatUint(cookie, 10)
-		fe := &FlowEvent{
-			eType:     EventTypeMcastFlowRemoved,
-			device:    device.Name,
-			cookie:    cookie,
-			eventData: mvp,
-		}
-		device.RegisterFlowDelEvent(cookie, fe)
-
-		if flowMap, ok = mvp.PendingDeleteFlow[device.Name]; !ok {
-			flowMap = make(map[string]bool)
-		}
-		flowMap[cookie] = true
-		mvp.PendingDeleteFlow[device.Name] = flowMap
-	}
-	if err := mvp.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
-	}
-	return cntlr.GetController().DelFlows(device.NniPort, device.Name, flow)
-}
-
-//FlowRemoveSuccess - Process flow success indication
-func (mvp *MvlanProfile) FlowRemoveSuccess(cookie string, device string) {
-	mvp.mvpFlowLock.Lock()
-	defer mvp.mvpFlowLock.Unlock()
-
-	logger.Infow(ctx, "Mvlan Flow Remove Success Notification", log.Fields{"MvlanProfile": mvp.Name, "Cookie": cookie, "Device": device})
-
-	if _, ok := mvp.PendingDeleteFlow[device]; ok {
-		delete(mvp.PendingDeleteFlow[device], cookie)
-	}
-
-	if err := mvp.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
-	}
-}
-
-//FlowRemoveFailure - Process flow failure indication
-func (mvp *MvlanProfile) FlowRemoveFailure(cookie string, device string, errorCode uint32, errReason string) {
-
-	mvp.mvpFlowLock.Lock()
-	defer mvp.mvpFlowLock.Unlock()
-
-	if flowMap, ok := mvp.PendingDeleteFlow[device]; ok {
-		if _, ok := flowMap[cookie]; ok {
-			logger.Errorw(ctx, "Mvlan Flow Remove Failure Notification", log.Fields{"MvlanProfile": mvp.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
-			return
-		}
-	}
-	logger.Errorw(ctx, "Mvlan Flow Del Failure Notification for Unknown cookie", log.Fields{"MvlanProfile": mvp.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
-
-}
-
-// AddMcGroup add the new group on the device when a receiver joins the group
-func (igd *IgmpGroupDevice) AddMcGroup() {
-	if !igd.GroupInstalled {
-		group := &of.Group{}
-		group.Command = of.GroupCommandAdd
-		group.GroupID = igd.GroupID
-		group.Device = igd.Device
-		group.SetVlan = igd.PonVlan
-		group.IsPonVlanPresent = igd.IsPonVlanPresent
-
-		addbuckets := func(key interface{}, value interface{}) bool {
-			port := key.(string)
-			var portID uint32
-			if d := GetApplication().GetDevice(group.Device); d != nil {
-				GetApplication().portLock.Lock()
-				p := d.GetPort(port)
-				GetApplication().portLock.Unlock()
-				portID = p.ID
-			}
-			//ponPortID := key.(uint32)
-			if portID != 0xFF {
-				group.Buckets = append(group.Buckets, portID)
-			}
-			return true
-		}
-		igd.PortChannelMap.Range(addbuckets)
-
-		port, _ := GetApplication().GetNniPort(igd.Device)
-		_ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
-		igd.GroupInstalled = true
-	}
-}
-
-// ModMcGroup updates the group on the device when either a receiver leaves
-// or joins the group
-func (igd *IgmpGroupDevice) ModMcGroup() {
-	if igd.GroupInstalled {
-		group := &of.Group{}
-		group.Command = of.GroupCommandMod
-		group.GroupID = igd.GroupID
-		group.Device = igd.Device
-		group.SetVlan = igd.PonVlan
-		group.IsPonVlanPresent = igd.IsPonVlanPresent
-
-		addbuckets := func(key interface{}, value interface{}) bool {
-                       port := key.(string)
-                       var portID uint32
-                       if d := GetApplication().GetDevice(group.Device); d != nil {
-                               GetApplication().portLock.Lock()
-                               p := d.GetPort(port)
-                               GetApplication().portLock.Unlock()
-                               portID = p.ID
-                       }
-                       //ponPortID := key.(uint32)
-                       if portID != 0xFF {
-                               group.Buckets = append(group.Buckets, portID)
-			}
-			return true
-		}
-		igd.PortChannelMap.Range(addbuckets)
-
-		port, _ := GetApplication().GetNniPort(igd.Device)
-		_ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
-	} else {
-		logger.Warnw(ctx, "Update Group Failed. Group not yet created", log.Fields{"Igd": igd.Device})
-	}
-}
-
-// DelMcGroup : The group is deleted when the last receiver leaves the group
-func (igd *IgmpGroupDevice) DelMcGroup(forceDelete bool) {
-
-	logger.Infow(ctx, "Delete Mc Group Request", log.Fields{"Device": igd.Device, "GroupID": igd.GroupID, "ForceFlag": forceDelete, "GroupInstalled": igd.GroupInstalled})
-	/*
-	if !forceDelete && !checkIfForceGroupRemove(igd.Device) {
-		if success := AddToPendingPool(igd.Device, igd.getKey()); success {
-			return
-		}
-	}*/
-	if igd.GroupInstalled {
-		logger.Debugw(ctx, "Deleting Group", log.Fields{"Device": igd.Device, "Id": igd.GroupID})
-		group := &of.Group{}
-		group.Command = of.GroupCommandDel
-		group.GroupID = igd.GroupID
-		group.Device = igd.Device
-		group.ForceAction = true
-
-		port, _ := GetApplication().GetNniPort(igd.Device)
-		_ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
-		igd.GroupInstalled = false
-	}
-}
-
 //AddToPendingPool - adds Igmp Device obj to pending pool
 func AddToPendingPool(device string, groupKey string) bool {
 
@@ -1969,83 +447,6 @@
 	return false
 }*/
 
-// IgmpLeaveToServer sends IGMP leave to server. Called when the last receiver leaves the group
-func (igc *IgmpGroupChannel) IgmpLeaveToServer() {
-	if leave, err := IgmpLeavePacket(igc.GroupAddr, igc.Mvlan, (*igc.proxyCfg).IgmpCos, **igc.IgmpProxyIP); err == nil {
-		nni, err1 := GetApplication().GetNniPort(igc.Device)
-		if err1 == nil {
-			_ = cntlr.GetController().PacketOutReq(igc.Device, nni, nni, leave, false)
-		}
-	}
-}
-
-// SendLeaveToServer delete the group when the last receiver leaves the group
-func (igc *IgmpGroupChannel) SendLeaveToServer() {
-	/**
-	                               +-------------------------------------------------------------------------+
-	                               |         IGMP version(towards BNG) Configured at VGC                     |
-	                               +-------------------------------+-----------------------------------------+
-	                               |                  v2           |                 v3                      |
-	+===================+==========+===============================+=========================================+
-	| Received From RG  | V2 Leave | Process and Send as V2 to BNG | Process, Convert to V3 and Send to BNG/ |
-	|                   |          |                               | Process, Send as V2, if the BNG is V2   |
-	+===================+----------+-------------------------------+-----------------------------------------+
-	                    | V3 Leave | Process and Send as V2 to BNG | Process, Send V3 to BNG                 |
-	                    |          |                               | Process, Convert, Send as V2, if the    |
-	                    |          |                               | BNG is v2                               |
-	                    +==========+===============================+=========================================+
-	*/
-	// igc.Version: 	igmp version received from RG.
-	// igc.ServVersion: igmp version received from BNG or IgmpVerToServer present in proxy igmp conf.
-
-	logger.Debugw(ctx, "Sending IGMP leave upstream", log.Fields{"Device": igc.Device})
-	if *igc.ServVersion == IgmpVersion2 || getVersion((*igc.proxyCfg).IgmpVerToServer) == IgmpVersion2 {
-		igc.IgmpLeaveToServer()
-	} else {
-		igc.SendReport(false)
-	}
-}
-
-// QueryExpiry processes query expiry. Upon expiry, take stock of the situation
-// add either retain/release the group based on number of receivers left
-func (igd *IgmpGroupDevice) QueryExpiry() {
-	logger.Debugw(ctx, "Query Expiry", log.Fields{"Device": igd.Device})
-
-
-	// Delete the IGMP flow added for this port if port state is down or query count exceeded
-	handleQueryExp := func(key interface{}, value interface{}) bool {
-		igc := value.(*IgmpGroupChannel)
-		for portKey, port := range igc.CurReceivers {
-
-			if portKey == StaticPort {
-				continue
-			}
-
-			logger.Warnw(ctx, "Expired Receiver Port", log.Fields{"PortKey": portKey, "IGP": port, "GroupAddr": igc.GroupAddr,
-				"Count": port.QueryTimeoutCount})
-			state, err := cntlr.GetController().GetPortState(igc.Device, portKey)
-			logger.Debugw(ctx, "Expired Member Port State", log.Fields{"state": state})
-			ponPortID := GetApplication().GetPonPortID(igd.Device, portKey)
-			if err == nil && state == cntlr.PortStateDown {
-				igd.DelReceiver(igc.GroupAddr, portKey, nil, ponPortID)
-			}
-
-			port.QueryTimeoutCount++
-			logger.Debugw(ctx, "Expired Port TimeoutCount", log.Fields{"count": port.QueryTimeoutCount})
-			if port.QueryTimeoutCount >= (*igc.proxyCfg).KeepAliveCount {
-				logger.Errorw(ctx, "Expiry Timeout count exceeded. Trigger delete receiver", log.Fields{"PortKey": portKey,
-					"GroupAddr": igc.GroupAddr, "Count": port.QueryTimeoutCount})
-				igd.DelReceiver(igc.GroupAddr, portKey, nil, ponPortID)
-				SendQueryExpiredEventGroupSpecific(portKey, igd, igc)
-			} else {
-				_ = port.WriteToDb(igc.Mvlan, igc.GroupAddr, igc.Device)
-			}
-		}
-		return true
-	}
-	igd.GroupChannels.Range(handleQueryExp)
-}
-
 // SendQueryExpiredEventGroupSpecific to send group specific query expired event.
 func SendQueryExpiredEventGroupSpecific(portKey string, igd *IgmpGroupDevice, igc *IgmpGroupChannel) {
 
@@ -2102,609 +503,6 @@
 
 }
 
-// NumReceivers returns total number of receivers left on the group
-func (igc *IgmpGroupChannel) NumReceivers() uint32 {
-	return uint32(len(igc.CurReceivers) + len(igc.NewReceivers))
-}
-
-// SendQuery sends query to the receivers for counting purpose
-func (igc *IgmpGroupChannel) SendQuery() {
-	//var b []byte
-	//var err error
-	for portKey, port := range igc.NewReceivers {
-		igc.CurReceivers[portKey] = port
-	}
-
-	igc.NewReceivers = make(map[string]*IgmpGroupPort)
-
-	logger.Debugw(ctx, "Sending Query to receivers", log.Fields{"Receivers": igc.CurReceivers})
-	for port, groupPort := range igc.CurReceivers {
-		if port == StaticPort {
-			continue
-		}
-		if queryPkt, err := igc.buildQuery(igc.GroupAddr, of.VlanType(groupPort.CVlan), groupPort.Pbit); err == nil {
-			_ = cntlr.GetController().PacketOutReq(igc.Device, port, port, queryPkt, false)
-			logger.Debugw(ctx, "Query Sent", log.Fields{"Device": igc.Device, "Port": port, "Packet": queryPkt})
-		} else {
-			logger.Warnw(ctx, "Query Creation Failed", log.Fields{"Reason": err.Error()})
-		}
-	}
-
-}
-
-// buildQuery to build query packet
-func (igc *IgmpGroupChannel) buildQuery(groupAddr net.IP, cVlan of.VlanType, pbit uint8) ([]byte, error) {
-	if igc.Version == IgmpVersion2 {
-		return Igmpv2QueryPacket(igc.GroupAddr, cVlan, **igc.IgmpProxyIP, pbit, (*igc.proxyCfg).MaxResp)
-	}
-	return Igmpv3QueryPacket(igc.GroupAddr, cVlan, **igc.IgmpProxyIP, pbit, (*igc.proxyCfg).MaxResp)
-}
-
-// IgmpGroup implements a single MCIP that may have multiple receivers
-// connected via multiple devices (OLTs). The IGMP group is stored on the
-// VOLT application.
-type IgmpGroup struct {
-	GroupID               uint32
-	Mvlan                 of.VlanType
-	PonVlan               of.VlanType
-	GroupName             string
-	GroupAddr             net.IP
-	Devices               map[string]*IgmpGroupDevice `json:"-"`
-	PendingGroupForDevice map[string]time.Time        //map [deviceId, timestamp]  (ExpiryTime  = leave time + 15mins)
-	Version               string
-	IsPonVlanPresent      bool
-	IsChannelBasedGroup   bool
-	PendingPoolLock       sync.RWMutex
-	IsGroupStatic         bool
-	IgmpGroupLock         sync.RWMutex
-}
-
-// NewIgmpGroup is constructor for an IGMP group
-func NewIgmpGroup(name string, vlan of.VlanType) *IgmpGroup {
-	ig := IgmpGroup{}
-	ig.GroupName = name
-	ig.Mvlan = vlan
-	ig.Devices = make(map[string]*IgmpGroupDevice)
-	ig.PendingGroupForDevice = make(map[string]time.Time)
-	return &ig
-}
-
-// IgmpGroupInit to initialize igmp group members
-func (ig *IgmpGroup) IgmpGroupInit(name string, gip net.IP, mvp *MvlanProfile) {
-	ig.GroupName = name
-	ig.Mvlan = mvp.Mvlan
-	ig.PonVlan = mvp.PonVlan
-	ig.IsPonVlanPresent = mvp.IsPonVlanPresent
-	ig.Devices = make(map[string]*IgmpGroupDevice)
-	ig.PendingGroupForDevice = make(map[string]time.Time)
-	ig.IsChannelBasedGroup = mvp.IsChannelBasedGroup
-	ig.IsGroupStatic = mvp.Groups[name].IsStatic
-	if ig.IsChannelBasedGroup {
-		ig.GroupAddr = gip
-	} else {
-		ig.GroupAddr = net.ParseIP("0.0.0.0")
-	}
-}
-
-// IgmpGroupReInit to re-initialize igmp group members
-func (ig *IgmpGroup) IgmpGroupReInit(name string, gip net.IP) {
-
-	logger.Infow(ctx, "Reinitialize Igmp Group", log.Fields{"GroupID": ig.GroupID, "OldName": ig.GroupName, "Name": name, "OldAddr": ig.GroupAddr.String(), "GroupAddr": gip.String()})
-
-	ig.GroupName = name
-	if ig.IsChannelBasedGroup {
-		ig.GroupAddr = gip
-	} else {
-		ig.GroupAddr = net.ParseIP("0.0.0.0")
-	}
-
-	for _, igd := range ig.Devices {
-		igd.IgmpGroupDeviceReInit(ig)
-	}
-}
-
-// IsStaticGroup to check if group is static
-func (mvp *MvlanProfile) IsStaticGroup(groupName string) bool {
-	return mvp.Groups[groupName].IsStatic
-}
-
-// updateGroupName to update group name
-func (ig *IgmpGroup) updateGroupName(newGroupName string) {
-	if !ig.IsChannelBasedGroup {
-		logger.Errorw(ctx, "Group name update not supported for GroupChannel based group", log.Fields{"Ig": ig})
-		return
-	}
-	oldKey := ig.getKey()
-	ig.GroupName = newGroupName
-	for _, igd := range ig.Devices {
-		igd.updateGroupName(newGroupName)
-	}
-	if err := ig.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group Write to DB failed", log.Fields{"groupName": ig.GroupName})
-	}
-	if !ig.IsChannelBasedGroup {
-		_ = db.DelIgmpGroup(oldKey)
-	}
-}
-
-//HandleGroupMigration - handles migration of group members between static & dynamic
-func (ig *IgmpGroup) HandleGroupMigration(deviceID string, groupAddr net.IP) {
-
-	var group *layers.IGMPv3GroupRecord
-	app := GetApplication()
-	if deviceID == "" {
-		logger.Infow(ctx, "Handle Group Migration Request for all devices", log.Fields{"DeviceID": deviceID, "GroupAddr": groupAddr, "IG": ig.GroupName, "Mvlan": ig.Mvlan})
-		for device := range ig.Devices {
-			ig.HandleGroupMigration(device, groupAddr)
-		}
-	} else {
-		logger.Infow(ctx, "Handle Group Migration Request", log.Fields{"DeviceID": deviceID, "GroupAddr": groupAddr, "IG": ig.GroupName})
-		var newIg *IgmpGroup
-		receivers := ig.DelIgmpChannel(deviceID, groupAddr)
-		if ig.NumDevicesActive() == 0 {
-			app.DelIgmpGroup(ig)
-		}
-		if newIg = app.GetIgmpGroup(ig.Mvlan, groupAddr); newIg == nil {
-			logger.Infow(ctx, "IG Group doesn't exist, creating new group", log.Fields{"DeviceID": deviceID, "GroupAddr": groupAddr, "IG": ig.GroupName, "Mvlan": ig.Mvlan})
-			if newIg = app.AddIgmpGroup(app.GetMvlanProfileByTag(ig.Mvlan).Name, groupAddr, deviceID); newIg == nil {
-				logger.Errorw(ctx, "Group Creation failed during group migration", log.Fields{"DeviceID": deviceID, "GroupAddr": groupAddr})
-				return
-			}
-		}
-		mvp := app.GetMvlanProfileByTag(ig.Mvlan)
-		isStaticGroup := mvp.IsStaticGroup(ig.GroupName)
-		logger.Infow(ctx, "Existing receivers for old group", log.Fields{"Receivers": receivers})
-		newIg.IgmpGroupLock.Lock()
-		for port, igp := range receivers {
-			if !isStaticGroup && port == StaticPort {
-				continue
-			}
-			group = nil
-			var reqType layers.IGMPv3GroupRecordType
-			srcAddresses := []net.IP{}
-			if igp.Version == IgmpVersion3 {
-				if igp.Exclude {
-					srcAddresses = append(srcAddresses, igp.ExcludeList...)
-					reqType = layers.IGMPIsEx
-				} else {
-					srcAddresses = append(srcAddresses, igp.IncludeList...)
-					reqType = layers.IGMPIsIn
-				}
-				group = &layers.IGMPv3GroupRecord{
-					SourceAddresses: srcAddresses,
-					Type:            reqType,
-				}
-			}
-			logger.Infow(ctx, "Adding receiver to new group", log.Fields{"DeviceID": deviceID, "GroupAddr": groupAddr, "newIg": newIg.GroupName, "IGP": igp})
-			ponPort := GetApplication().GetPonPortID(deviceID, port)
-			newIg.AddReceiver(deviceID, port, groupAddr, group, igp.Version, igp.CVlan, igp.Pbit, ponPort)
-		}
-		newIg.IgmpGroupLock.Unlock()
-	}
-}
-
-// AddIgmpGroupDevice add a device to the group which happens when the first receiver of the device
-// is added to the IGMP group.
-func (ig *IgmpGroup) AddIgmpGroupDevice(device string, id uint32, version uint8) *IgmpGroupDevice {
-	logger.Infow(ctx, "Adding Device to IGMP group", log.Fields{"Device": device, "GroupName": ig.GroupName})
-	igd := NewIgmpGroupDevice(device, ig, id, version)
-	ig.Devices[device] = igd
-	if err := igd.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-	}
-	return igd
-}
-
-// DelIgmpGroupDevice delete the device from the group which happens when we receive a leave or when
-// there is not response for IGMP query from the receiver
-func (ig *IgmpGroup) DelIgmpGroupDevice(igd *IgmpGroupDevice) {
-	logger.Infow(ctx, "Deleting Device from IGMP group", log.Fields{"Device": igd.Device, "Name": ig.GroupName})
-	va := GetApplication()
-	countersToBeUpdated := false
-	if igd.NumReceivers() != 0 {
-		countersToBeUpdated = true
-	}
-	igd.DelAllChannels()
-
-	//Clear all internal maps so that the groups can be reused
-	igd.PortChannelMap.Range(func(key, value interface{}) bool {
-
-		//Update the counters only if not already updated
-		//(i.e) 1. In case of channel remove during Mvlan Update
-		if countersToBeUpdated {
-			port := key.(string)
-			channelList := value.([]net.IP)
-			ponPortID := va.GetPonPortID(igd.Device, port)
-
-			for _, channel := range channelList {
-				igd.RemoveChannelFromChannelsPerPon(port, channel, ponPortID)
-			}
-		}
-
-		igd.PortChannelMap.Delete(key)
-		return true
-	})
-	igd.PonPortChannelMap = util.NewConcurrentMap()
-
-	if mcastCfg := va.GetMcastConfig(igd.SerialNo, va.GetMvlanProfileByTag(igd.Mvlan).Name); mcastCfg != nil {
-		mcastCfg.IgmpGroupDevices.Delete(igd.GroupID)
-		logger.Debugw(ctx, "Igd deleted from mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": igd.GroupID})
-	}
-	if !igd.GroupInstalled {
-		_ = db.DelIgmpDevice(igd.Mvlan, ig.GroupName, ig.GroupAddr, igd.Device)
-		delete(ig.Devices, igd.Device)
-	}
-}
-
-// AddReceiver delete the device from the group which happens when we receive a leave or when
-// there is not response for IGMP query from the receiver
-func (ig *IgmpGroup) AddReceiver(device string, port string, groupIP net.IP,
-	group *layers.IGMPv3GroupRecord, ver uint8, cvlan uint16, pbit uint8, ponPort uint32) {
-
-	logger.Debugw(ctx, "Adding Receiver", log.Fields{"Port": port})
-	if igd, ok := ig.getIgmpGroupDevice(device); !ok {
-		igd = ig.AddIgmpGroupDevice(device, ig.GroupID, ver)
-		igd.AddReceiver(port, groupIP, group, ver, cvlan, pbit, ponPort)
-	} else {
-		logger.Infow(ctx, "IGMP Group Receiver", log.Fields{"IGD": igd.Device})
-		igd.AddReceiver(port, groupIP, group, ver, cvlan, pbit, ponPort)
-	}
-}
-
-func (ig *IgmpGroup) getIgmpGroupDevice(device string) (*IgmpGroupDevice, bool) {
-	ig.PendingPoolLock.Lock()
-	defer ig.PendingPoolLock.Unlock()
-
-	if _, ok := ig.PendingGroupForDevice[device]; ok {
-		logger.Infow(ctx, "Removing the IgmpGroupDevice from pending pool", log.Fields{"GroupID": ig.GroupID, "Device": device, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr.String()})
-		delete(ig.PendingGroupForDevice, device)
-		if err := ig.WriteToDb(); err != nil {
-			logger.Errorw(ctx, "Igmp group Write to DB failed", log.Fields{"groupName": ig.GroupName})
-		}
-	}
-	igd, ok := ig.Devices[device]
-	return igd, ok
-}
-
-// DelReceiveronDownInd deletes a receiver which is the combination of device (OLT)
-// and port on Port Down event
-func (ig *IgmpGroup) DelReceiveronDownInd(device string, port string, ponPortID uint32) {
-	logger.Debugw(ctx, "Deleting Receiver for Group", log.Fields{"Device": device, "port": port})
-
-	mvp := GetApplication().GetMvlanProfileByTag(ig.Mvlan)
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-	igd, ok := ig.Devices[device]
-	if !ok {
-		logger.Infow(ctx, "IGMP Group device was not found for ", log.Fields{"Device": device})
-		return
-	}
-	ipsList := []net.IP{}
-	ipsListIntf, ok := igd.PortChannelMap.Load(port)
-	if ok {
-		ipsList = append(ipsList, ipsListIntf.([]net.IP)...)
-	}
-	logger.Infow(ctx, "Port Channel List", log.Fields{"Port": port, "IPsList": ipsList})
-	igd.PortChannelMap.Range(printPortChannel)
-
-
-	for _, groupAddr := range ipsList {
-		logger.Debugw(ctx, "Port Channels", log.Fields{"Port": port, "IPsList": ipsList, "GroupAddr": groupAddr, "Len": len(ipsList)})
-		igd.DelReceiver(groupAddr, port, nil, ponPortID)
-	}
-
-	if igd.NumReceivers() == 0 {
-		ig.DelIgmpGroupDevice(igd)
-	}
-}
-
-// DelReceiver deletes a receiver which is the combination of device (OLT)
-// and port
-func (ig *IgmpGroup) DelReceiver(device string, port string, groupAddr net.IP, group *layers.IGMPv3GroupRecord, ponPortID uint32) {
-	logger.Debugw(ctx, "Deleting Receiver for Group", log.Fields{"Device": device, "port": port, "GroupIP": groupAddr.String()})
-	if igd, ok := ig.Devices[device]; ok {
-		//igd.DelReceiverForGroupAddr(groupAddr, port)
-		igd.DelReceiver(groupAddr, port, group, ponPortID)
-		if igd.NumReceivers() == 0 {
-			ig.DelIgmpGroupDevice(igd)
-		}
-	}
-}
-
-// GetAllIgmpChannelForDevice - Returns all channels with active members associated to the Igmp Group for the given device
-func (ig *IgmpGroup) GetAllIgmpChannelForDevice(deviceID string) map[string]string {
-
-	if deviceID == "" {
-		return ig.GetAllIgmpChannel()
-	}
-
-	allChannels := make(map[string]string)
-	igd := ig.Devices[deviceID]
-	getAllChannels := func(key interface{}, value interface{}) bool {
-		channels := key.(string)
-		allChannels[channels] = channels //same value as only key is required
-		return true
-	}
-	igd.GroupChannels.Range(getAllChannels)
-
-	return allChannels
-}
-
-// GetAllIgmpChannel - Returns all channels with active members associated to the Igmp Group
-func (ig *IgmpGroup) GetAllIgmpChannel() map[string]string {
-	allChannels := make(map[string]string)
-	for _, igd := range ig.Devices {
-		getAllChannels := func(key interface{}, value interface{}) bool {
-			channels := key.(string)
-			allChannels[channels] = channels
-			return true
-		}
-		igd.GroupChannels.Range(getAllChannels)
-	}
-	return allChannels
-}
-
-// DelIgmpChannel deletes all receivers for the provided igmp group channel for the given device
-func (ig *IgmpGroup) DelIgmpChannel(deviceID string, groupAddr net.IP) map[string]*IgmpGroupPort {
-	logger.Infow(ctx, "Deleting Channel from devices", log.Fields{"Device": deviceID, "Group": ig.GroupName, "Channel": groupAddr.String()})
-	if deviceID == "" {
-		for device := range ig.Devices {
-			ig.DelIgmpChannel(device, groupAddr)
-		}
-		return nil
-	}
-	igd := ig.Devices[deviceID]
-	receivers := igd.DelChannelReceiver(groupAddr)
-	if igd.NumReceivers() == 0 {
-		ig.DelIgmpGroupDevice(igd)
-	}
-	return receivers
-}
-
-// IsNewReceiver checks if the received port is new receiver or existing one.
-// Returns true if new receiver.
-func (ig *IgmpGroup) IsNewReceiver(device, uniPortID string, groupAddr net.IP) bool {
-	if ig == nil {
-		// IGMP group does not exists. So considering it as new receiver.
-		return true
-	}
-	logger.Debugw(ctx, "IGMP Group", log.Fields{"channel": groupAddr, "groupName": ig.GroupName}) // TODO: Remove me
-	igd, exists := ig.Devices[device]
-	if !exists || !igd.GroupInstalled {
-		// IGMP group not exists OR Group is not created in the device.
-		// So this is a new receiver.
-		logger.Debugw(ctx, "igd not exists or group is not created in device", log.Fields{"exists": exists}) // TODO: Remove me
-		return true
-	}
-	if igc, ok := igd.GroupChannels.Load(groupAddr.String()); ok {
-		logger.Debugw(ctx, "IGMP Channel receivers", log.Fields{"igc-receivers": igc.(*IgmpGroupChannel).CurReceivers}) // TODO: Remove me
-		_, rcvrExistCur := igc.(*IgmpGroupChannel).CurReceivers[uniPortID]
-		_, rcvrExistNew := igc.(*IgmpGroupChannel).NewReceivers[uniPortID]
-		if rcvrExistCur || rcvrExistNew {
-			// Existing receiver
-			return false
-		}
-	}
-	return true
-}
-
-// Tick for Addition of groups to an MVLAN profile
-func (ig *IgmpGroup) Tick() {
-	now := time.Now()
-	for _, igd := range ig.Devices {
-		var igdChangeCnt uint8
-
-		if _, ok := GetApplication().DevicesDisc.Load(igd.Device); !ok {
-			logger.Info(ctx, "Skipping Query and Expiry check since Device is unavailable")
-			continue
-		}
-		if now.After(igd.NextQueryTime) {
-			// Set the next query time and the query expiry time to
-			// KeepAliveInterval and MaxResp seconds after current time
-			igd.NextQueryTime = now.Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-			igd.QueryExpiryTime = now.Add(time.Duration(igd.proxyCfg.MaxResp) * time.Second)
-			logger.Debugw(ctx, "Query Start", log.Fields{"NextQuery": igd.NextQueryTime, "Expiry": igd.QueryExpiryTime})
-			igdChangeCnt++
-			logger.Debugw(ctx, "Sending Query to device", log.Fields{"Device": igd.Device})
-			sendQueryForAllChannels := func(key interface{}, value interface{}) bool {
-				igc := value.(*IgmpGroupChannel)
-				//TODO - Do generic query to avoid multiple msgs
-				igc.SendQuery()
-				return true
-			}
-			igd.GroupChannels.Range(sendQueryForAllChannels)
-		}
-		if now.After(igd.QueryExpiryTime) {
-			igd.QueryExpiry()
-			// This will keep it quiet till the next query time and then
-			// it will be reset to a value after the query initiation time
-			igd.QueryExpiryTime = igd.NextQueryTime
-			logger.Debugw(ctx, "Expiry", log.Fields{"NextQuery": igd.NextQueryTime, "Expiry": igd.QueryExpiryTime})
-			igdChangeCnt++
-			if igd.NumReceivers() == 0 {
-				ig.DelIgmpGroupDevice(igd)
-				continue
-			}
-		}
-
-		igdChangeCnt += igd.Tick()
-
-		if igdChangeCnt > 0 {
-			if err := igd.WriteToDb(); err != nil {
-				logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device,
-							"GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-			}
-		}
-	}
-}
-
-// QueryExpiry processes expiry of query sent to the receivers. Up on
-// expiry, process the consolidated response for each of the devices participating
-// in the MC stream. When a device has no receivers, the device is deleted
-// from the group.
-func (ig *IgmpGroup) QueryExpiry() {
-	for _, igd := range ig.Devices {
-		if _, ok := GetApplication().DevicesDisc.Load(igd.Device); ok {
-			igd.QueryExpiry()
-			if igd.NumReceivers() == 0 {
-				ig.DelIgmpGroupDevice(igd)
-			}
-
-		} else {
-			logger.Info(ctx, "Skipping Expiry since Device is unavailable")
-		}
-	}
-}
-
-// Hash : The IGMP group hash is used to distribute the processing of timers so that
-// the processing is spread across doesn't spike at one instant. This also
-// ensures that there is sufficient responsiveness to other requests happening
-// simultaneously.
-func (ig *IgmpGroup) Hash() uint16 {
-	mvp := GetApplication().GetMvlanProfileByTag(ig.Mvlan)
-
-	if mvp == nil {
-		return 0
-	}
-
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-	group := mvp.Groups[ig.GroupName]
-
-	//Case where mvlan update in-progress
-	if group == nil || len(group.McIPs) == 0 {
-		return 0
-	}
-	groupIP := group.McIPs[0]
-	return uint16(groupIP[2])<<8 + uint16(groupIP[3])
-}
-
-// NumDevicesAll returns the number of devices (OLT) active on the IGMP group. When
-// the last device leaves the IGMP group is removed. If this is not done,
-// the number of IGMP groups only keep increasing and can impact CPU when
-// the system runs for a very long duration
-func (ig *IgmpGroup) NumDevicesAll() int {
-	return len(ig.Devices)
-}
-
-// NumDevicesActive returns the number of devices (OLT) active on the IGMP group. When
-// the last device leaves the IGMP group is removed. If this is not done,
-// the number of IGMP groups only keep increasing and can impact CPU when
-// the system runs for a very long duration
-func (ig *IgmpGroup) NumDevicesActive() int {
-	count := 0
-	for _, igd := range ig.Devices {
-		if igd.NumReceivers() == 0 && igd.GroupInstalled {
-			continue
-		}
-		count++
-	}
-	return count
-}
-
-// NumReceivers to return receiver list
-func (ig *IgmpGroup) NumReceivers() map[string]int {
-	receiverList := make(map[string]int)
-	for device, igd := range ig.Devices {
-		receiverList[device] = igd.NumReceivers()
-	}
-	return receiverList
-}
-
-// RestoreDevices : IGMP group write to DB
-func (ig *IgmpGroup) RestoreDevices() {
-
-	ig.migrateIgmpDevices()
-	devices, _ := db.GetIgmpDevices(ig.Mvlan, ig.GroupName, ig.GroupAddr)
-	for _, device := range devices {
-		b, ok := device.Value.([]byte)
-		if !ok {
-			logger.Warn(ctx, "The value type is not []byte")
-			continue
-		}
-		if igd, err := NewIgmpGroupDeviceFromBytes(b); err == nil {
-			igd.PonPortChannelMap = util.NewConcurrentMap()
-			// Update the proxy config pointers.
-			var mcastCfg *McastConfig
-			igd.proxyCfg, igd.IgmpProxyIP, mcastCfg = getIgmpProxyCfgAndIP(ig.Mvlan, igd.SerialNo)
-			if mcastCfg != nil {
-				mcastCfg.IgmpGroupDevices.Store(igd.GroupID, igd)
-				logger.Debugw(ctx, "Igd added to mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": igd.GroupID})
-			}
-
-			mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
-			igd.ServVersion = mvp.IgmpServVersion[igd.SerialNo]
-
-			// During vgc upgrade from old version, igd.NextQueryTime and igd.QueryExpiryTime will not be present in db.
-			// hence they are initialized with current time offset.
-			emptyTime := time.Time{}
-			if emptyTime == igd.NextQueryTime {
-				logger.Debugw(ctx, "VGC igd upgrade", log.Fields{"igd grp name": igd.GroupName})
-				igd.NextQueryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-				igd.QueryExpiryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
-				if err := igd.WriteToDb(); err != nil {
-					logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device,
-								"GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
-				}
-			}
-
-			ig.Devices[igd.Device] = igd
-			if ig.IsChannelBasedGroup {
-				channel, _ := db.GetIgmpChannel(igd.Mvlan, igd.GroupName, igd.Device, igd.GroupAddr)
-				igd.RestoreChannel([]byte(channel))
-			} else {
-				igd.RestoreChannels()
-			}
-			igd.PortChannelMap.Range(printPortChannel)
-			logger.Infow(ctx, "Group Device Restored", log.Fields{"IGD": igd})
-		} else {
-			logger.Warnw(ctx, "Unable to decode device from database", log.Fields{"str": string(b)})
-		}
-	}
-}
-
-// getKey to return group key
-func (ig *IgmpGroup) getKey() string {
-	profile, ok := GetApplication().MvlanProfilesByTag.Load(ig.Mvlan)
-	if ok {
-		mvp := profile.(*MvlanProfile)
-		return mvp.generateGroupKey(ig.GroupName, ig.GroupAddr.String())
-	}
-	return ""
-}
-
-/*
-// getKey to return group key
-func (igd *IgmpGroupDevice) getKey() string {
-	profile, ok := GetApplication().MvlanProfilesByTag.Load(igd.Mvlan)
-	if ok {
-		mvp := profile.(*MvlanProfile)
-		return mvp.generateGroupKey(igd.GroupName, igd.GroupAddr.String())
-	}
-	return ""
-}*/
-
-// generateGroupKey to generate group key
-func (mvp *MvlanProfile) generateGroupKey(name string, ipAddr string) string {
-	if mvp.IsChannelBasedGroup {
-		return mvp.Mvlan.String() + "_" + ipAddr
-	}
-	return mvp.Mvlan.String() + "_" + name
-}
-
-// WriteToDb is utility to write Igmp Group Info to database
-func (ig *IgmpGroup) WriteToDb() error {
-	ig.Version = database.PresentVersionMap[database.IgmpGroupPath]
-	b, err := json.Marshal(ig)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutIgmpGroup(ig.getKey(), string(b)); err1 != nil {
-		return err1
-	}
-	return nil
-}
-
 // RestoreIgmpGroupsFromDb to restore igmp groups from database
 func (va *VoltApplication) RestoreIgmpGroupsFromDb() {
 
@@ -2806,51 +604,6 @@
 	return nil
 }
 
-// GetStaticGroupName to get static igmp group
-func (mvp *MvlanProfile) GetStaticGroupName(gip net.IP) string {
-	for _, mvg := range mvp.Groups {
-		if mvg.IsStatic {
-			if doesIPMatch(gip, mvg.McIPs) {
-				return mvg.Name
-			}
-		}
-	}
-	return ""
-}
-
-// GetStaticIgmpGroup to get static igmp group
-func (mvp *MvlanProfile) GetStaticIgmpGroup(gip net.IP) *IgmpGroup {
-
-	staticGroupName := mvp.GetStaticGroupName(gip)
-	grpKey := mvp.generateGroupKey(staticGroupName, gip.String())
-	logger.Debugw(ctx, "Get Static IGMP Group", log.Fields{"Group": grpKey})
-	ig, ok := GetApplication().IgmpGroups.Load(grpKey)
-	if ok {
-		logger.Debugw(ctx, "Get Static IGMP Group Success", log.Fields{"Group": grpKey})
-		return ig.(*IgmpGroup)
-	}
-	return nil
-}
-
-// UpdateIgmpGroup : When the pending group is allocated to new
-func (ig *IgmpGroup) UpdateIgmpGroup(oldKey, newKey string) {
-
-	//If the group is allocated to same McastGroup, no need to update the
-	//IgmpGroups map
-	if oldKey == newKey {
-		return
-	}
-	logger.Infow(ctx, "Updating Igmp Group with new MVP Group Info", log.Fields{"OldKey": oldKey, "NewKey": newKey, "GroupID": ig.GroupID})
-
-	GetApplication().IgmpGroups.Delete(oldKey)
-	_ = db.DelIgmpGroup(oldKey)
-
-	GetApplication().IgmpGroups.Store(newKey, ig)
-	if err := ig.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group Write to DB failed", log.Fields{"groupName": ig.GroupName})
-	}
-}
-
 // DelIgmpGroup : When the last subscriber leaves the IGMP group across all the devices
 // the IGMP group is removed.
 func (va *VoltApplication) DelIgmpGroup(ig *IgmpGroup) {
@@ -3414,267 +1167,6 @@
 	va.IgmpTasks.AddTask(pt)
 }
 
-// ------------------------------------------------------------
-// MVLAN related implemnetation
-//
-// Each MVLAN is configured with groups of multicast IPs. The idea of
-// groups is to be able to group some multicast channels into an individual
-// PON group and have a unique multicast GEM port for that set. However, in
-// the current implementation, the concept of grouping is not fully utilized.
-
-// MvlanGroup structure
-// A set of MC IPs form a group
-
-// MCGroupProxy identifies source specific multicast(SSM) config.
-type MCGroupProxy struct {
-	// Mode represents source list include/exclude
-	Mode common.MulticastSrcListMode
-	// SourceList represents list of multicast server IP addresses.
-	SourceList []net.IP
-}
-
-// MvlanGroup identifies MC group info
-type MvlanGroup struct {
-	Name     string
-	Wildcard bool
-	McIPs    []string
-	IsStatic bool
-}
-
-// OperInProgress type
-type OperInProgress uint8
-
-const (
-	// UpdateInProgress constant
-	UpdateInProgress OperInProgress = 2
-	// NoOp constant
-	NoOp OperInProgress = 1
-	// Nil constant
-	Nil OperInProgress = 0
-)
-
-// MvlanProfile : A set of groups of MC IPs for a MVLAN profile. It is assumed that
-// the MVLAN IP is not repeated within multiples groups and across
-// MVLAN profiles. The first match is used up on search to lcoate the
-// MVLAN profile for an MC IP
-type MvlanProfile struct {
-	Name                string
-	Mvlan               of.VlanType
-	PonVlan             of.VlanType
-	Groups              map[string]*MvlanGroup
-	Proxy               map[string]*MCGroupProxy
-	Version             string
-	IsPonVlanPresent    bool
-	IsChannelBasedGroup bool
-	DevicesList         map[string]OperInProgress //device serial number //here
-	oldGroups           map[string]*MvlanGroup
-	oldProxy            map[string]*MCGroupProxy
-	MaxActiveChannels   uint32
-	PendingDeleteFlow   map[string]map[string]bool
-	DeleteInProgress    bool
-	IgmpServVersion     map[string]*uint8
-	mvpLock             sync.RWMutex
-	mvpFlowLock         sync.RWMutex
-}
-
-// NewMvlanProfile is constructor for MVLAN profile.
-func NewMvlanProfile(name string, mvlan of.VlanType, ponVlan of.VlanType, isChannelBasedGroup bool, OLTSerialNums []string, actChannelPerPon uint32) *MvlanProfile {
-	var mvp MvlanProfile
-	mvp.Name = name
-	mvp.Mvlan = mvlan
-	mvp.PonVlan = ponVlan
-	mvp.mvpLock = sync.RWMutex{}
-	mvp.Groups = make(map[string]*MvlanGroup)
-	mvp.Proxy = make(map[string]*MCGroupProxy)
-	mvp.DevicesList = make(map[string]OperInProgress)
-	mvp.PendingDeleteFlow = make(map[string]map[string]bool)
-	mvp.IsChannelBasedGroup = isChannelBasedGroup
-	mvp.MaxActiveChannels = actChannelPerPon
-	mvp.DeleteInProgress = false
-	mvp.IgmpServVersion = make(map[string]*uint8)
-
-	if (ponVlan != of.VlanNone) && (ponVlan != 0) {
-		mvp.IsPonVlanPresent = true
-	}
-	return &mvp
-}
-
-// AddMvlanProxy for addition of groups to an MVLAN profile
-func (mvp *MvlanProfile) AddMvlanProxy(name string, proxyInfo common.MulticastGroupProxy) {
-	proxy := &MCGroupProxy{}
-	proxy.Mode = proxyInfo.Mode
-	proxy.SourceList = util.GetExpIPList(proxyInfo.SourceList)
-
-	if _, ok := mvp.Proxy[name]; !ok {
-		logger.Debugw(ctx, "Added MVLAN Proxy", log.Fields{"Name": name, "Proxy": proxy})
-	} else {
-		logger.Debugw(ctx, "Updated MVLAN Proxy", log.Fields{"Name": name, "Proxy": proxy})
-	}
-	if proxyInfo.IsStatic == common.IsStaticYes {
-		mvp.Groups[name].IsStatic = true
-	}
-	mvp.Proxy[name] = proxy
-}
-
-// AddMvlanGroup for addition of groups to an MVLAN profile
-func (mvp *MvlanProfile) AddMvlanGroup(name string, ips []string) {
-	mvg := &MvlanGroup{}
-	mvg.Name = name
-	mvg.Wildcard = len(ips) == 0
-	mvg.McIPs = ips
-	mvg.IsStatic = false
-	if _, ok := mvp.Groups[name]; !ok {
-		logger.Debugw(ctx, "Added MVLAN Group", log.Fields{"VLAN": mvp.Mvlan, "Name": name, "mvg": mvg, "IPs": mvg.McIPs})
-	} else {
-		logger.Debugw(ctx, "Updated MVLAN Group", log.Fields{"VLAN": mvp.Mvlan, "Name": name})
-	}
-	mvp.Groups[name] = mvg
-}
-
-// GetUsMatchVlan provides mvlan for US Match parameter
-func (mvp *MvlanProfile) GetUsMatchVlan() of.VlanType {
-	if mvp.IsPonVlanPresent {
-		return mvp.PonVlan
-	}
-	return mvp.Mvlan
-}
-
-// WriteToDb is utility to write Mvlan Profile Info to database
-func (mvp *MvlanProfile) WriteToDb() error {
-
-	if mvp.DeleteInProgress {
-		logger.Warnw(ctx, "Skipping Redis Update for MvlanProfile, MvlanProfile delete in progress", log.Fields{"Mvlan": mvp.Mvlan})
-		return nil
-	}
-
-	mvp.Version = database.PresentVersionMap[database.MvlanPath]
-	b, err := json.Marshal(mvp)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutMvlan(uint16(mvp.Mvlan), string(b)); err1 != nil {
-		return err1
-	}
-	return nil
-}
-
-//isChannelStatic - Returns true if the given channel is part of static group in the Mvlan Profile
-func (mvp *MvlanProfile) isChannelStatic(channel net.IP) bool {
-	for _, mvg := range mvp.Groups {
-		if mvg.IsStatic {
-			if isChannelStatic := doesIPMatch(channel, mvg.McIPs); isChannelStatic {
-				return true
-			}
-		}
-	}
-	return false
-}
-
-//containsStaticChannels - Returns if any static channels is part of the Mvlan Profile
-func (mvp *MvlanProfile) containsStaticChannels() bool {
-	for _, mvg := range mvp.Groups {
-		if mvg.IsStatic && len(mvg.McIPs) != 0 {
-			return true
-		}
-	}
-	return false
-}
-
-//getAllStaticChannels - Returns all static channels in the Mvlan Profile
-func (mvp *MvlanProfile) getAllStaticChannels() ([]net.IP, bool) {
-	channelList := []net.IP{}
-	containsStatic := false
-	for _, mvg := range mvp.Groups {
-		if mvg.IsStatic {
-			staticChannels, _ := mvg.getAllChannels()
-			channelList = append(channelList, staticChannels...)
-		}
-	}
-	if len(channelList) > 0 {
-		containsStatic = true
-	}
-	return channelList, containsStatic
-}
-
-//getAllOldGroupStaticChannels - Returns all static channels in the Mvlan Profile
-func (mvp *MvlanProfile) getAllOldGroupStaticChannels() ([]net.IP, bool) {
-	channelList := []net.IP{}
-	containsStatic := false
-	for _, mvg := range mvp.oldGroups {
-		if mvg.IsStatic {
-			staticChannels, _ := mvg.getAllChannels()
-			channelList = append(channelList, staticChannels...)
-		}
-	}
-	if len(channelList) > 0 {
-		containsStatic = true
-	}
-	return channelList, containsStatic
-}
-
-//getAllChannels - Returns all channels in the Mvlan Profile
-func (mvg *MvlanGroup) getAllChannels() ([]net.IP, bool) {
-	channelList := []net.IP{}
-
-	if mvg == nil || len(mvg.McIPs) == 0 {
-		return []net.IP{}, false
-	}
-
-	grpChannelOrRange := mvg.McIPs
-	for _, channelOrRange := range grpChannelOrRange {
-		if strings.Contains(channelOrRange, "-") {
-			var splits = strings.Split(channelOrRange, "-")
-			ipStart := util.IP2LongConv(net.ParseIP(splits[0]))
-			ipEnd := util.IP2LongConv(net.ParseIP(splits[1]))
-
-			for i := ipStart; i <= ipEnd; i++ {
-				channelList = append(channelList, util.Long2ipConv(i))
-			}
-		} else {
-			channelList = append(channelList, net.ParseIP(channelOrRange))
-		}
-	}
-	return channelList, true
-}
-
-//SetUpdateStatus - Sets profile update status for devices
-func (mvp *MvlanProfile) SetUpdateStatus(serialNum string, status OperInProgress) {
-	if serialNum != "" {
-		mvp.DevicesList[serialNum] = status
-		return
-	}
-
-	for srNo := range mvp.DevicesList {
-		mvp.DevicesList[srNo] = status
-	}
-}
-
-//isUpdateInProgress - checking is update is in progress for the mvlan profile
-func (mvp *MvlanProfile) isUpdateInProgress() bool {
-
-	for srNo := range mvp.DevicesList {
-		if mvp.DevicesList[srNo] == UpdateInProgress {
-			return true
-		}
-	}
-	return false
-}
-
-//IsUpdateInProgressForDevice - Checks is Mvlan Profile update is is progress for the given device
-func (mvp *MvlanProfile) IsUpdateInProgressForDevice(device string) bool {
-	if vd := GetApplication().GetDevice(device); vd != nil {
-		if mvp.DevicesList[vd.SerialNum] == UpdateInProgress {
-			return true
-		}
-	}
-	return false
-}
-
-// DelFromDb to delere mvlan from database
-func (mvp *MvlanProfile) DelFromDb() {
-	_ = db.DelMvlan(uint16(mvp.Mvlan))
-}
-
 // storeMvlansMap to store mvlan map
 func (va *VoltApplication) storeMvlansMap(mvlan of.VlanType, name string, mvp *MvlanProfile) {
 	va.MvlanProfilesByTag.Store(mvlan, mvp)
@@ -4061,409 +1553,6 @@
 	return nil
 }
 
-//pushIgmpMcastFlows - Adds all IGMP related flows (generic DS flow & static group flows)
-func (mvp *MvlanProfile) pushIgmpMcastFlows(OLTSerialNum string) {
-
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-
-	if mvp.DevicesList[OLTSerialNum] == Nil {
-		logger.Infow(ctx, "Mvlan Profile not configure for device", log.Fields{"Device": OLTSerialNum, "Mvlan": mvp.Mvlan})
-		return
-	}
-
-	d := GetApplication().GetDeviceBySerialNo(OLTSerialNum)
-	if d == nil {
-		logger.Warnw(ctx, "Skipping Igmp & Mcast Flow processing: Device Not Found", log.Fields{"Device_SrNo": OLTSerialNum, "Mvlan": mvp.Mvlan})
-		return
-	}
-
-	p := d.GetPort(d.NniPort)
-
-	if p != nil && p.State == PortStateUp {
-		logger.Infow(ctx, "NNI Port Status is: UP & Vlan Enabled", log.Fields{"Device": d, "port": p})
-
-		//Push Igmp DS Control Flows
-		err := mvp.ApplyIgmpDSFlowForMvp(d.Name)
-		if err != nil {
-			logger.Errorw(ctx, "DS IGMP Flow Add Failed for device",
-				log.Fields{"Reason": err.Error(), "device": d.Name})
-		}
-
-		//Trigger Join for static channels
-		if channelList, containsStatic := mvp.getAllStaticChannels(); containsStatic {
-			mvp.ProcessStaticGroup(d.Name, channelList, true)
-		} else {
-			logger.Infow(ctx, "No Static Channels Present", log.Fields{"mvp": mvp.Name, "Mvlan": mvp.Mvlan})
-		}
-	}
-}
-
-/*
-//pushIgmpMcastFlowsToAllOlt - Adds all IGMP related flows (generic DS flow & static group flows) to all OLTs
-func (mvp *MvlanProfile) pushIgmpMcastFlowsToAllOlt() {
-
-	//for all devices apply igmp DS trap flow rules
-	pushIgmpFlows := func(key interface{}, value interface{}) bool {
-		d := value.(*VoltDevice)
-		p := d.GetPort(d.NniPort)
-			if p != nil && p.State == PortStateUp {
-				logger.Infow(ctx, "NNI Port Status is: UP & Vlan Enabled", log.Fields{"Device": d, "port": p})
-
-				//Push Igmp DS Control Flows
-				err := mvp.ApplyIgmpDSFlowForMvp(d.Name)
-				if err != nil {
-					logger.Errorw(ctx, "DS IGMP Flow Add Failed for device",
-						log.Fields{"Reason": err.Error(), "device": d.Name})
-				}
-
-				//Trigger Join for static channels
-				if channelList, containsStatic := mvp.getAllStaticChannels(); containsStatic {
-					mvp.ProcessStaticGroup(d.Name, channelList, true)
-				} else {
-					logger.Infow(ctx, "No Static Channels Present", log.Fields{"mvp": mvp.Name, "Mvlan": mvp.Mvlan})
-				}
-			}
-		return true
-	}
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-	GetApplication().DevicesDisc.Range(pushIgmpFlows)
-}
-
-//removeIgmpFlows - Removes all IGMP related flows (generic DS flow)
-func (mvp *MvlanProfile) removeIgmpFlows(oltSerialNum string) {
-
-	if d := GetApplication().GetDeviceBySerialNo(oltSerialNum); d != nil {
-		p := d.GetPort(d.NniPort)
-		if p != nil {
-			logger.Infow(ctx, "NNI Port Status is: UP", log.Fields{"Device": d, "port": p})
-			err := mvp.RemoveIgmpDSFlowForMvp(d.Name)
-			if err != nil {
-				logger.Errorw(ctx, "DS IGMP Flow Del Failed", log.Fields{"Reason": err.Error(), "device": d.Name})
-			}
-		}
-	}
-}*/
-
-//removeIgmpMcastFlows - Removes all IGMP related flows (generic DS flow & static group flows)
-func (mvp *MvlanProfile) removeIgmpMcastFlows(oltSerialNum string) {
-
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-
-	if d := GetApplication().GetDeviceBySerialNo(oltSerialNum); d != nil {
-		p := d.GetPort(d.NniPort)
-		if p != nil {
-			logger.Infow(ctx, "NNI Port Status is: UP", log.Fields{"Device": d, "port": p})
-
-			// ***Do not change the order***
-			// When Vlan is disabled, the process end is determined by the DS Igmp flag in device
-
-			//Trigger Leave for static channels
-			if channelList, containsStatic := mvp.getAllStaticChannels(); containsStatic {
-				mvp.ProcessStaticGroup(d.Name, channelList, false)
-			} else {
-				logger.Infow(ctx, "No Static Channels Present", log.Fields{"mvp": mvp.Name, "Mvlan": mvp.Mvlan})
-			}
-
-			//Remove all dynamic members for the Mvlan Profile
-			GetApplication().IgmpGroups.Range(func(key, value interface{}) bool {
-				ig := value.(*IgmpGroup)
-				if ig.Mvlan == mvp.Mvlan {
-					igd := ig.Devices[d.Name]
-					ig.DelIgmpGroupDevice(igd)
-					if ig.NumDevicesActive() == 0 {
-						GetApplication().DelIgmpGroup(ig)
-					}
-				}
-				return true
-			})
-
-			//Remove DS Igmp trap flow
-			err := mvp.RemoveIgmpDSFlowForMvp(d.Name)
-			if err != nil {
-				logger.Errorw(ctx, "DS IGMP Flow Del Failed", log.Fields{"Reason": err.Error(), "device": d.Name})
-			}
-		}
-	}
-}
-
-// ApplyIgmpDSFlowForMvp to apply Igmp DS flow for mvlan.
-func (mvp *MvlanProfile) ApplyIgmpDSFlowForMvp(device string) error {
-	va := GetApplication()
-	dIntf, ok := va.DevicesDisc.Load(device)
-	if !ok {
-		return errors.New("Device Doesn't Exist")
-	}
-	d := dIntf.(*VoltDevice)
-	mvlan := mvp.Mvlan
-
-	flowAlreadyApplied, ok := d.IgmpDsFlowAppliedForMvlan[uint16(mvlan)]
-	if !ok || !flowAlreadyApplied {
-		flows, err := mvp.BuildIgmpDSFlows(device)
-		if err == nil {
-			err = cntlr.GetController().AddFlows(d.NniPort, device, flows)
-			if err != nil {
-				logger.Warnw(ctx, "Configuring IGMP Flow for device failed ", log.Fields{"Device": device, "err": err})
-				return err
-			}
-			d.IgmpDsFlowAppliedForMvlan[uint16(mvlan)] = true
-			logger.Infow(ctx, "Updating voltDevice that IGMP DS flow as \"added\" for ",
-				log.Fields{"device": d.SerialNum, "mvlan": mvlan})
-		} else {
-			logger.Errorw(ctx, "DS IGMP Flow Add Failed", log.Fields{"Reason": err.Error(), "Mvlan": mvlan})
-		}
-	}
-
-	return nil
-}
-
-// RemoveIgmpDSFlowForMvp to remove Igmp DS flow for mvlan.
-func (mvp *MvlanProfile) RemoveIgmpDSFlowForMvp(device string) error {
-
-	va := GetApplication()
-	mvlan := mvp.Mvlan
-
-	dIntf, ok := va.DevicesDisc.Load(device)
-	if !ok {
-		return errors.New("Device Doesn't Exist")
-	}
-	d := dIntf.(*VoltDevice)
-	/* No need of strict check during DS IGMP deletion
-	flowAlreadyApplied, ok := d.IgmpDsFlowAppliedForMvlan[uint16(mvlan)]
-	if ok && flowAlreadyApplied
-	*/
-	flows, err := mvp.BuildIgmpDSFlows(device)
-	if err == nil {
-		flows.ForceAction = true
-
-		err = mvp.DelFlows(d, flows)
-		if err != nil {
-			logger.Warnw(ctx, "De-Configuring IGMP Flow for device failed ", log.Fields{"Device": device, "err": err})
-			return err
-		}
-		d.IgmpDsFlowAppliedForMvlan[uint16(mvlan)] = false
-		logger.Infow(ctx, "Updating voltDevice that IGMP DS flow as \"removed\" for ",
-			log.Fields{"device": d.SerialNum, "mvlan": mvlan})
-	} else {
-		logger.Errorw(ctx, "DS IGMP Flow Del Failed", log.Fields{"Reason": err.Error()})
-	}
-
-	return nil
-}
-
-// BuildIgmpDSFlows to build Igmp DS flows for NNI port
-func (mvp *MvlanProfile) BuildIgmpDSFlows(device string) (*of.VoltFlow, error) {
-	dIntf, ok := GetApplication().DevicesDisc.Load(device)
-	if !ok {
-		return nil, errors.New("Device Doesn't Exist")
-	}
-	d := dIntf.(*VoltDevice)
-
-	logger.Infow(ctx, "Building DS IGMP Flow for NNI port", log.Fields{"vs": d.NniPort, "Mvlan": mvp.Mvlan})
-	flow := &of.VoltFlow{}
-	flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
-	subFlow := of.NewVoltSubFlow()
-	subFlow.SetTableID(0)
-	subFlow.SetMatchVlan(mvp.Mvlan)
-
-	nniPort, err := GetApplication().GetNniPort(device)
-	if err != nil {
-		return nil, err
-	}
-	nniPortID, err1 := GetApplication().GetPortID(nniPort)
-	if err1 != nil {
-		return nil, errors.New("Unknown NNI outport")
-	}
-	subFlow.SetInPort(nniPortID)
-	subFlow.SetIgmpMatch()
-	subFlow.SetReportToController()
-	subFlow.Cookie = uint64(nniPortID)<<32 | uint64(mvp.Mvlan)
-	subFlow.Priority = of.IgmpFlowPriority
-
-	flow.SubFlows[subFlow.Cookie] = subFlow
-	logger.Infow(ctx, "Built DS IGMP flow", log.Fields{"cookie": subFlow.Cookie, "subflow": subFlow})
-	return flow, nil
-}
-
-//updateStaticGroups - Generates static joins & leaves for newly added and removed static channels respectively
-func (mvp *MvlanProfile) updateStaticGroups(deviceID string, added []net.IP, removed []net.IP) {
-
-	//Update static group configs for all associated devices
-	updateGroups := func(key interface{}, value interface{}) bool {
-		d := value.(*VoltDevice)
-
-		if mvp.DevicesList[d.SerialNum] == Nil {
-			logger.Infow(ctx, "Mvlan Profile not configure for device", log.Fields{"Device": d, "Profile Device List": mvp.DevicesList})
-			return true
-		}
-		//TODO if mvp.IsChannelBasedGroup {
-		mvp.ProcessStaticGroup(d.Name, added, true)
-		mvp.ProcessStaticGroup(d.Name, removed, false)
-		//}
-		return true
-	}
-
-	if deviceID != "" {
-		vd := GetApplication().GetDevice(deviceID)
-		updateGroups(deviceID, vd)
-	} else {
-		GetApplication().DevicesDisc.Range(updateGroups)
-	}
-}
-
-//updateDynamicGroups - Generates joins with updated sources for existing channels
-func (mvp *MvlanProfile) updateDynamicGroups(deviceID string, added []net.IP, removed []net.IP) {
-
-	//mvlan := mvp.Mvlan
-	va := GetApplication()
-
-	updateGroups := func(key interface{}, value interface{}) bool {
-		d := value.(*VoltDevice)
-
-		if mvp.DevicesList[d.SerialNum] == Nil {
-			logger.Infow(ctx, "Mvlan Profile not configure for device", log.Fields{"Device": d, "Profile Device List": mvp.DevicesList})
-			return true
-		}
-		for _, groupAddr := range added {
-
-			_, gName := va.GetMvlanProfileForMcIP(mvp.Name, groupAddr)
-			grpKey := mvp.generateGroupKey(gName, groupAddr.String())
-			logger.Debugw(ctx, "IGMP Group", log.Fields{"Group": grpKey, "groupAddr": groupAddr})
-			if igIntf, ok := va.IgmpGroups.Load(grpKey); ok {
-				ig := igIntf.(*IgmpGroup)
-				if igd, ok := ig.getIgmpGroupDevice(d.Name); ok {
-					if igcIntf, ok := igd.GroupChannels.Load(groupAddr.String()); ok {
-						igc := igcIntf.(*IgmpGroupChannel)
-						incl := false
-						var ip []net.IP
-						var groupModified = false
-						if _, ok := mvp.Proxy[igc.GroupName]; ok {
-							if mvp.Proxy[igc.GroupName].Mode == common.Include {
-								incl = true
-							}
-							ip = mvp.Proxy[igc.GroupName].SourceList
-						}
-						for port, igp := range igc.NewReceivers {
-							// Process the include/exclude list which may end up modifying the group
-							if change, _ := igc.ProcessSources(port, ip, incl); change {
-								groupModified = true
-							}
-							igc.ProcessMode(port, incl)
-
-							if err := igp.WriteToDb(igc.Mvlan, igc.GroupAddr, igc.Device); err != nil {
-								logger.Errorw(ctx, "Igmp group port Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-							}
-						}
-						// If the group is modified as this is the first receiver or due to include/exclude list modification
-						// send a report to the upstream multicast servers
-						if groupModified {
-							logger.Debug(ctx, "Group Modified and IGMP report sent to the upstream server")
-							igc.SendReport(false)
-						}
-						if err := igc.WriteToDb(); err != nil {
-							logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
-						}
-					}
-				}
-			}
-		}
-
-		return true
-	}
-
-	if deviceID != "" {
-		vd := GetApplication().GetDevice(deviceID)
-		updateGroups(deviceID, vd)
-	} else {
-		GetApplication().DevicesDisc.Range(updateGroups)
-	}
-}
-
-//GroupsUpdated - Handles removing of Igmp Groups, flows & group table entries for
-//channels removed as part of update
-func (mvp *MvlanProfile) GroupsUpdated(deviceID string) {
-
-	deleteChannelIfRemoved := func(key interface{}, value interface{}) bool {
-		ig := value.(*IgmpGroup)
-
-		if ig.Mvlan != mvp.Mvlan {
-			return true
-		}
-		grpName := ig.GroupName
-		logger.Infow(ctx, "###Update Cycle", log.Fields{"IG": ig.GroupName, "Addr": ig.GroupAddr})
-		//Check if group exists and remove the entire group object otherwise
-		if currentChannels := mvp.Groups[grpName]; currentChannels != nil {
-
-			if mvp.IsChannelBasedGroup {
-				channelPresent := doesIPMatch(ig.GroupAddr, currentChannels.McIPs)
-				if channelPresent || mvp.isChannelStatic(ig.GroupAddr) {
-					return true
-				}
-			} else {
-				allExistingChannels := ig.GetAllIgmpChannelForDevice(deviceID)
-				for channel := range allExistingChannels {
-					channelIP := net.ParseIP(channel)
-					channelPresent := mvp.IsChannelPresent(channelIP, currentChannels.McIPs, mvp.IsStaticGroup(ig.GroupName))
-					if channelPresent {
-						staticChannel := mvp.isChannelStatic(channelIP)
-						logger.Infow(ctx, "###Channel Comparision", log.Fields{"staticChannel": staticChannel, "Group": mvp.IsStaticGroup(ig.GroupName), "Channel": channel})
-						// Logic:
-						// If channel is Static & existing Group is also static - No migration required
-						// If channel is not Static & existing Group is also not static - No migration required
-
-						// If channel is Static and existing Group is not static - Migrate (from dynamic to static)
-						//    (Channel already part of dynamic, added to static)
-
-						// If channel is not Static but existing Group is static - Migrate (from static to dynamic)
-						//    (Channel removed from satic but part of dynamic)
-						if (staticChannel != mvp.IsStaticGroup(ig.GroupName)) || (ig.IsGroupStatic != mvp.IsStaticGroup(ig.GroupName)) { // Equivalent of XOR
-							ig.HandleGroupMigration(deviceID, channelIP)
-						} else {
-							if (ig.IsGroupStatic) && mvp.IsStaticGroup(ig.GroupName) {
-								if ig.GroupName != mvp.GetStaticGroupName(channelIP) {
-									ig.HandleGroupMigration(deviceID, channelIP)
-								}
-							}
-							continue
-						}
-					} else {
-						logger.Debugw(ctx, "Channel Removed", log.Fields{"Channel": channel, "Group": grpName})
-						ig.DelIgmpChannel(deviceID, net.ParseIP(channel))
-						if ig.NumDevicesActive() == 0 {
-							GetApplication().DelIgmpGroup(ig)
-						}
-					}
-				}
-				ig.IsGroupStatic = mvp.IsStaticGroup(ig.GroupName)
-				if err := ig.WriteToDb(); err != nil {
-					logger.Errorw(ctx, "Igmp group Write to DB failed", log.Fields{"groupName": ig.GroupName})
-				}
-				return true
-			}
-		}
-		logger.Debugw(ctx, "Group Removed", log.Fields{"Channel": ig.GroupAddr, "Group": grpName, "ChannelBasedGroup": ig.IsChannelBasedGroup})
-		ig.DelIgmpGroup()
-		logger.Debugw(ctx, "Removed Igmp Group", log.Fields{"Channel": ig.GroupAddr, "Group": grpName})
-		return true
-	}
-	GetApplication().IgmpGroups.Range(deleteChannelIfRemoved)
-}
-
-// IsChannelPresent to check if channel is present
-func (mvp *MvlanProfile) IsChannelPresent(channelIP net.IP, groupChannelList []string, IsStaticGroup bool) bool {
-	// Only in case of static group, migration need to be supported.
-	// Dynamic to dynamic group migration not supported currently
-	if doesIPMatch(channelIP, groupChannelList) || mvp.isChannelStatic(channelIP) {
-		return true
-	} else if IsStaticGroup {
-		return (mvp.GetMvlanGroup(channelIP) != "")
-	}
-
-	return false
-}
-
 // GetMvlanProfileForMcIP - Get an MVLAN profile for a given MC IP. This is used when an
 // IGMP report is received from the PON port. The MVLAN profile
 // located is used to idnetify the MC VLAN used in upstream for
@@ -4480,27 +1569,6 @@
 	return nil, ""
 }
 
-// GetMvlanGroup to get mvlan group
-func (mvp *MvlanProfile) GetMvlanGroup(ip net.IP) string {
-	//Check for Static Group First
-	if mvp.containsStaticChannels() {
-		grpName := mvp.GetStaticGroupName(ip)
-		if grpName != "" {
-			return grpName
-		}
-	}
-
-	for _, mvg := range mvp.Groups {
-		if mvg.Wildcard {
-			return mvg.Name
-		}
-		if doesIPMatch(ip, mvg.McIPs) {
-			return mvg.Name
-		}
-	}
-	return ""
-}
-
 // IgmpTick for igmp tick info
 func (va *VoltApplication) IgmpTick() {
 	tickCount++
@@ -4557,40 +1625,6 @@
 	return nil
 }
 
-func newIgmpProfile(igmpProfileConfig *common.IGMPConfig) *IgmpProfile {
-	var igmpProfile IgmpProfile
-	igmpProfile.ProfileID = igmpProfileConfig.ProfileID
-	igmpProfile.UnsolicitedTimeOut = uint32(igmpProfileConfig.UnsolicitedTimeOut)
-	igmpProfile.MaxResp = uint32(igmpProfileConfig.MaxResp)
-
-	keepAliveInterval := uint32(igmpProfileConfig.KeepAliveInterval)
-
-	//KeepAliveInterval should have a min of 10 seconds
-	if keepAliveInterval < MinKeepAliveInterval {
-		keepAliveInterval = MinKeepAliveInterval
-		logger.Infow(ctx, "Auto adjust keepAliveInterval - Value < 10", log.Fields{"Received": igmpProfileConfig.KeepAliveInterval, "Configured": keepAliveInterval})
-	}
-	igmpProfile.KeepAliveInterval = keepAliveInterval
-
-	igmpProfile.KeepAliveCount = uint32(igmpProfileConfig.KeepAliveCount)
-	igmpProfile.LastQueryInterval = uint32(igmpProfileConfig.LastQueryInterval)
-	igmpProfile.LastQueryCount = uint32(igmpProfileConfig.LastQueryCount)
-	igmpProfile.FastLeave = *igmpProfileConfig.FastLeave
-	igmpProfile.PeriodicQuery = *igmpProfileConfig.PeriodicQuery
-	igmpProfile.IgmpCos = uint8(igmpProfileConfig.IgmpCos)
-	igmpProfile.WithRAUpLink = *igmpProfileConfig.WithRAUpLink
-	igmpProfile.WithRADownLink = *igmpProfileConfig.WithRADownLink
-
-	if igmpProfileConfig.IgmpVerToServer == "2" || igmpProfileConfig.IgmpVerToServer == "v2" {
-		igmpProfile.IgmpVerToServer = "2"
-	} else {
-		igmpProfile.IgmpVerToServer = "3"
-	}
-	igmpProfile.IgmpSourceIP = net.ParseIP(igmpProfileConfig.IgmpSourceIP)
-
-	return &igmpProfile
-}
-
 // checkIgmpProfileMap to get Igmp Profile. If not found return nil
 func (va *VoltApplication) checkIgmpProfileMap(name string) *IgmpProfile {
 	if igmpProfileIntf, ok := va.IgmpProfilesByName.Load(name); ok {
@@ -4599,26 +1633,6 @@
 	return nil
 }
 
-// newDefaultIgmpProfile Igmp profiles with default values
-func newDefaultIgmpProfile() *IgmpProfile {
-	return &IgmpProfile{
-		ProfileID:          DefaultIgmpProfID,
-		UnsolicitedTimeOut: 60,
-		MaxResp:            10, // seconds
-		KeepAliveInterval:  60, // seconds
-		KeepAliveCount:     3,  // TODO - May not be needed
-		LastQueryInterval:  0,  // TODO - May not be needed
-		LastQueryCount:     0,  // TODO - May not be needed
-		FastLeave:          true,
-		PeriodicQuery:      false, // TODO - May not be needed
-		IgmpCos:            7,     //p-bit value included in the IGMP packet
-		WithRAUpLink:       false, // TODO - May not be needed
-		WithRADownLink:     false, // TODO - May not be needed
-		IgmpVerToServer:    "3",
-		IgmpSourceIP:       net.ParseIP("172.27.0.1"), // This will be replaced by configuration
-	}
-}
-
 func (va *VoltApplication) resetIgmpProfileToDefault() {
 	igmpProf := va.getIgmpProfileMap(DefaultIgmpProfID)
 	defIgmpProf := newDefaultIgmpProfile()
@@ -4663,19 +1677,6 @@
 	va.IgmpProfilesByName.Delete(name)
 }
 
-// WriteToDb is utility to write Igmp Config Info to database
-func (igmpProfile *IgmpProfile) WriteToDb() error {
-	igmpProfile.Version = database.PresentVersionMap[database.IgmpProfPath]
-	b, err := json.Marshal(igmpProfile)
-	if err != nil {
-		return err
-	}
-	if err1 := db.PutIgmpProfile(igmpProfile.ProfileID, string(b)); err1 != nil {
-		return err1
-	}
-	return nil
-}
-
 //DelIgmpProfile for addition of IGMP Profile
 func (va *VoltApplication) DelIgmpProfile(igmpProfileConfig *common.IGMPConfig) error {
 	// Deletion of default igmp profile is blocked from submgr. Keeping additional check for safety.
@@ -4775,21 +1776,6 @@
 	igmpSrcMac = srcMac
 }
 
-// removeIPFromList to remove ip from the list
-func removeIPFromList(s []net.IP, value net.IP) []net.IP {
-	i := 0
-	for i = 0; i < len(s); i++ {
-		if s[i].Equal(value) {
-			break
-		}
-	}
-	if i != len(s) {
-		//It means value is found in the slice
-		return append(s[0:i], s[i+1:]...)
-	}
-	return s
-}
-
 // DelMvlanProfile for deletion of a MVLAN group
 func (va *VoltApplication) DelMvlanProfile(name string) error {
 	if mvpIntf, ok := va.MvlanProfilesByName.Load(name); ok {
@@ -4834,7 +1820,7 @@
 // sendGeneralQuery to send general query
 func sendGeneralQuery(device string, port string, cVlan of.VlanType, pbit uint8, proxyCfg *IgmpProfile, proxyIP *net.IP) {
 
-	if queryPkt, err := Igmpv2QueryPacket(NullIPAddr, cVlan, *proxyIP, pbit, proxyCfg.MaxResp); err == nil {
+	if queryPkt, err := Igmpv2QueryPacket(AllSystemsMulticastGroupIP, cVlan, *proxyIP, pbit, proxyCfg.MaxResp); err == nil {
 		if err := cntlr.GetController().PacketOutReq(device, port, port, queryPkt, false); err != nil {
 			logger.Warnw(ctx, "General Igmpv2 Query Failed to send", log.Fields{"Device": device, "Port": port, "Packet": queryPkt, "Pbit": pbit})
 		} else {
@@ -4842,7 +1828,7 @@
 		}
 	}
 	if getVersion(proxyCfg.IgmpVerToServer) == IgmpVersion3 {
-		if queryPkt, err := Igmpv3QueryPacket(NullIPAddr, cVlan, *proxyIP, pbit, proxyCfg.MaxResp); err == nil {
+		if queryPkt, err := Igmpv3QueryPacket(AllSystemsMulticastGroupIP, cVlan, *proxyIP, pbit, proxyCfg.MaxResp); err == nil {
 			if err := cntlr.GetController().PacketOutReq(device, port, port, queryPkt, false); err != nil {
 				logger.Warnw(ctx, "General Igmpv3 Query Failed to send", log.Fields{"Device": device, "Port": port, "Packet": queryPkt, "Pbit": pbit})
 			} else {
@@ -4870,425 +1856,3 @@
 	}
 	va.IgmpGroups.Range(del)
 }
-
-// doesIPMatch to check if ip match with any ip from the list
-func doesIPMatch(ip net.IP, ipsOrRange []string) bool {
-	for _, ipOrRange := range ipsOrRange {
-		if strings.Contains(ipOrRange, "-") {
-			var splits = strings.Split(ipOrRange, "-")
-			ipStart := util.IP2LongConv(net.ParseIP(splits[0]))
-			ipEnd := util.IP2LongConv(net.ParseIP(splits[1]))
-			if ipEnd < ipStart {
-				return false
-			}
-			ipInt := util.IP2LongConv(ip)
-			if ipInt >= ipStart && ipInt <= ipEnd {
-				return true
-			}
-		} else if ip.Equal(net.ParseIP(ipOrRange)) {
-			return true
-		}
-	}
-	return false
-}
-
-// ProcessStaticGroup - Process Static Join/Leave Req for static channels
-func (mvp *MvlanProfile) ProcessStaticGroup(device string, groupAddresses []net.IP, isJoin bool) {
-
-	logger.Debugw(ctx, "Received Static Group Request", log.Fields{"Device": device, "Join": isJoin, "Group Address List": groupAddresses})
-
-	mvlan := mvp.Mvlan
-	va := GetApplication()
-
-	//TODO - Handle bulk add of groupAddr
-	for _, groupAddr := range groupAddresses {
-
-		ig := mvp.GetStaticIgmpGroup(groupAddr)
-		if isJoin {
-			vd := va.GetDevice(device)
-			igmpProf, _, _ := getIgmpProxyCfgAndIP(mvlan, vd.SerialNum)
-			ver := igmpProf.IgmpVerToServer
-
-			if ig == nil {
-				// First time group Creation: Create the IGMP group and then add the receiver to the group
-				logger.Infow(ctx, "Static IGMP Add received for new group", log.Fields{"Addr": groupAddr, "Port": StaticPort})
-				if ig := GetApplication().AddIgmpGroup(mvp.Name, groupAddr, device); ig != nil {
-					ig.IgmpGroupLock.Lock()
-					ig.AddReceiver(device, StaticPort, groupAddr, nil, getVersion(ver),
-						0, 0, 0xFF)
-					ig.IgmpGroupLock.Unlock()
-				} else {
-					logger.Warnw(ctx, "Static IGMP Group Creation Failed", log.Fields{"Addr": groupAddr})
-				}
-			} else {
-				//Converting existing dynamic group to static group
-				if !mvp.IsStaticGroup(ig.GroupName) {
-					ig.updateGroupName(ig.GroupName)
-				}
-				// Update case: If the IGMP group is already created. just add the receiver
-				logger.Infow(ctx, "Static IGMP Add received for existing group", log.Fields{"Addr": groupAddr, "Port": StaticPort})
-				ig.IgmpGroupLock.Lock()
-				ig.AddReceiver(device, StaticPort, groupAddr, nil, getVersion(ver),
-					0, 0, 0xFF)
-				ig.IgmpGroupLock.Unlock()
-			}
-		} else if ig != nil {
-			logger.Infow(ctx, "Static IGMP Del received for existing group", log.Fields{"Addr": groupAddr, "Port": StaticPort})
-
-			if ig.IsChannelBasedGroup {
-				grpName := mvp.GetMvlanGroup(ig.GroupAddr)
-				if grpName != "" {
-					ig.IgmpGroupLock.Lock()
-					ig.DelReceiver(device, StaticPort, groupAddr, nil, 0xFF)
-					ig.IgmpGroupLock.Unlock()
-					ig.updateGroupName(grpName)
-				} else {
-					ig.DelIgmpGroup()
-				}
-			} else {
-				ig.IgmpGroupLock.Lock()
-				ig.DelReceiver(device, StaticPort, groupAddr, nil, 0xFF)
-				ig.IgmpGroupLock.Unlock()
-			}
-			if ig.NumDevicesActive() == 0 {
-				GetApplication().DelIgmpGroup(ig)
-			}
-		} else {
-			logger.Warnw(ctx, "Static IGMP Del received for unknown group", log.Fields{"Addr": groupAddr})
-		}
-	}
-}
-
-//getStaticChannelDiff - return the static channel newly added and removed from existing static group
-func (mvp *MvlanProfile) getStaticChannelDiff() (newlyAdded []net.IP, removed []net.IP, common []net.IP) {
-
-	var commonChannels []net.IP
-	newChannelList, _ := mvp.getAllStaticChannels()
-	existingChannelList, _ := mvp.getAllOldGroupStaticChannels()
-	if len(existingChannelList) == 0 {
-		return newChannelList, []net.IP{}, []net.IP{}
-	}
-	for _, newChannel := range append([]net.IP{}, newChannelList...) {
-		for _, existChannel := range append([]net.IP{}, existingChannelList...) {
-
-			//Remove common channels between existing and new list
-			// The remaining in the below slices give the results
-			// Remaining in newChannelList: Newly added
-			// Remaining in existingChannelList: Removed channels
-			if existChannel.Equal(newChannel) {
-				existingChannelList = removeIPFromList(existingChannelList, existChannel)
-				newChannelList = removeIPFromList(newChannelList, newChannel)
-				commonChannels = append(commonChannels, newChannel)
-				logger.Infow(ctx, "#############Channel: "+existChannel.String()+" New: "+newChannel.String(), log.Fields{"Added": newChannelList, "Removed": existingChannelList})
-				break
-			}
-		}
-	}
-	return newChannelList, existingChannelList, commonChannels
-}
-
-//getGroupChannelDiff - return the channel newly added and removed from existing group
-func (mvp *MvlanProfile) getGroupChannelDiff(newGroup *MvlanGroup, oldGroup *MvlanGroup) (newlyAdded []net.IP, removed []net.IP, common []net.IP) {
-
-	var commonChannels []net.IP
-	newChannelList, _ := newGroup.getAllChannels()
-	existingChannelList, _ := oldGroup.getAllChannels()
-	if len(existingChannelList) == 0 {
-		return newChannelList, []net.IP{}, []net.IP{}
-	}
-	for _, newChannel := range append([]net.IP{}, newChannelList...) {
-		for _, existChannel := range append([]net.IP{}, existingChannelList...) {
-
-			//Remove common channels between existing and new list
-			// The remaining in the below slices give the results
-			// Remaining in newChannelList: Newly added
-			// Remaining in existingChannelList: Removed channels
-			if existChannel.Equal(newChannel) {
-				existingChannelList = removeIPFromList(existingChannelList, existChannel)
-				newChannelList = removeIPFromList(newChannelList, newChannel)
-				commonChannels = append(commonChannels, newChannel)
-				logger.Infow(ctx, "#############Channel: "+existChannel.String()+" New: "+newChannel.String(), log.Fields{"Added": newChannelList, "Removed": existingChannelList})
-				break
-			}
-		}
-	}
-	return newChannelList, existingChannelList, commonChannels
-}
-
-// UpdateProfile - Updates the group & member info w.r.t the mvlan profile for the given device
-func (mvp *MvlanProfile) UpdateProfile(deviceID string) {
-	logger.Infow(ctx, "Update Mvlan Profile task triggered", log.Fields{"Mvlan": mvp.Mvlan})
-	var removedStaticChannels []net.IP
-	addedStaticChannels := []net.IP{}
-	/* Taking mvpLock to protect the mvp groups and proxy */
-	mvp.mvpLock.RLock()
-	defer mvp.mvpLock.RUnlock()
-
-	serialNo := ""
-	if deviceID != "" {
-		if vd := GetApplication().GetDevice(deviceID); vd != nil {
-			serialNo = vd.SerialNum
-			if mvp.DevicesList[serialNo] != UpdateInProgress {
-				logger.Warnw(ctx, "Exiting Update Task since device not present in MvlanProfile", log.Fields{"Device": deviceID, "SerialNum": vd.SerialNum, "MvlanProfile": mvp})
-				return
-			}
-		} else {
-			logger.Errorw(ctx, "Volt Device not found. Stopping Update Mvlan Profile processing for device", log.Fields{"SerialNo": deviceID, "MvlanProfile": mvp})
-			return
-		}
-	}
-
-	//Update the groups based on static channels added & removed
-	if mvp.containsStaticChannels() {
-		addedStaticChannels, removedStaticChannels, _ = mvp.getStaticChannelDiff()
-		logger.Debugw(ctx, "Update Task - Static Group Changes", log.Fields{"Added": addedStaticChannels, "Removed": removedStaticChannels})
-
-		if len(addedStaticChannels) > 0 || len(removedStaticChannels) > 0 {
-			mvp.updateStaticGroups(deviceID, []net.IP{}, removedStaticChannels)
-		}
-	}
-	mvp.GroupsUpdated(deviceID)
-	if len(addedStaticChannels) > 0 {
-		mvp.updateStaticGroups(deviceID, addedStaticChannels, []net.IP{})
-	}
-
-	/* Need to handle if SSM params are modified for groups */
-	for key := range mvp.Groups {
-		_, _, commonChannels := mvp.getGroupChannelDiff(mvp.Groups[key], mvp.oldGroups[key])
-		if mvp.checkStaticGrpSSMProxyDiff(mvp.oldProxy[key], mvp.Proxy[key]) {
-			if mvp.Groups[key].IsStatic {
-				/* Static group proxy modified, need to trigger membership report with new mode/src-list for existing channels */
-				mvp.updateStaticGroups(deviceID, commonChannels, []net.IP{})
-			} else {
-				/* Dynamic group proxy modified, need to trigger membership report with new mode/src-list for existing channels */
-				mvp.updateDynamicGroups(deviceID, commonChannels, []net.IP{})
-			}
-		}
-	}
-
-	mvp.SetUpdateStatus(serialNo, NoOp)
-
-	if deviceID == "" || !mvp.isUpdateInProgress() {
-		mvp.oldGroups = nil
-	}
-	if err := mvp.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
-	}
-	logger.Debugw(ctx, "Updated MVLAN Profile", log.Fields{"VLAN": mvp.Mvlan, "Name": mvp.Name, "Grp IPs": mvp.Groups})
-}
-
-//checkStaticGrpSSMProxyDiff- return true if the proxy of oldGroup is modified in newGroup
-func (mvp *MvlanProfile) checkStaticGrpSSMProxyDiff(oldProxy *MCGroupProxy, newProxy *MCGroupProxy) bool {
-
-	if oldProxy == nil && newProxy == nil {
-		return false
-	}
-	if (oldProxy == nil && newProxy != nil) ||
-		(oldProxy != nil && newProxy == nil) {
-		return true
-	}
-
-	if oldProxy.Mode != newProxy.Mode {
-		return true
-	}
-
-	oldSrcLst := oldProxy.SourceList
-	newSrcLst := newProxy.SourceList
-	oLen := len(oldSrcLst)
-	nLen := len(newSrcLst)
-	if oLen != nLen {
-		return true
-	}
-
-	visited := make([]bool, nLen)
-
-	/* check if any new IPs added in the src list, return true if present */
-	for i := 0; i < nLen; i++ {
-		found := false
-		element := newSrcLst[i]
-		for j := 0; j < oLen; j++ {
-			if visited[j] {
-				continue
-			}
-			if element.Equal(oldSrcLst[j]) {
-				visited[j] = true
-				found = true
-				break
-			}
-		}
-		if !found {
-			return true
-		}
-	}
-
-	visited = make([]bool, nLen)
-	/* check if any IPs removed from existing  src list, return true if removed */
-	for i := 0; i < oLen; i++ {
-		found := false
-		element := oldSrcLst[i]
-		for j := 0; j < nLen; j++ {
-			if visited[j] {
-				continue
-			}
-			if element.Equal(newSrcLst[j]) {
-				visited[j] = true
-				found = true
-				break
-			}
-		}
-		if !found {
-			return true
-		}
-	}
-	return false
-}
-
-// ProcessMode process the received mode and updated the igp
-func (igc *IgmpGroupChannel) ProcessMode(port string, incl bool) {
-	/* Update the mode in igp if the mode has changed */
-	igp := igc.GetReceiver(port)
-	if igp.Exclude && incl {
-		igp.Exclude = !incl
-		if igc.Exclude > 0 {
-			igc.Exclude--
-		}
-	} else if !incl && !igp.Exclude {
-		igp.Exclude = !incl
-		igc.Exclude++
-	}
-}
-
-func (ig *IgmpGroup) removeExpiredGroupFromDevice() {
-	ig.PendingPoolLock.Lock()
-	defer ig.PendingPoolLock.Unlock()
-
-	for device, timer := range ig.PendingGroupForDevice {
-
-		// To ensure no race-condition between the expiry time and the new Join,
-		// ensure the group exists in pending pool before deletion
-		groupExistsInPendingPool := true
-
-		if !time.Now().After(timer) {
-			continue
-		}
-
-		// Check if the IgmpGroup obj has no active member across any device
-		// If Yes, then this group is part of global pending pool (IgmpPendingPool), hence if expired,
-		// Remove only the IgmpGroup obj referenced to this device from global pool also.
-		if ig.NumDevicesActive() == 0 {
-			groupExistsInPendingPool = GetApplication().RemoveGroupFromPendingPool(device, ig)
-		}
-
-		// Remove the group entry from device and remove the IgmpDev Obj
-		// from IgmpGrp Pending pool
-		if groupExistsInPendingPool {
-			ig.DeleteIgmpGroupDevice(device)
-		}
-	}
-}
-
-//DeleteIgmpGroupDevice - removes the IgmpGroupDevice obj from IgmpGroup and database
-func (ig *IgmpGroup) DeleteIgmpGroupDevice(device string) {
-
-	logger.Infow(ctx, "Deleting IgmpGroupDevice from IG Pending Pool", log.Fields{"Device": device, "GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr.String(), "PendingDevices": len(ig.Devices)})
-
-	igd := ig.Devices[device]
-	igd.DelMcGroup(true)
-	delete(ig.Devices, device)
-	delete(ig.PendingGroupForDevice, device)
-	_ = db.DelIgmpDevice(igd.Mvlan, igd.GroupName, igd.GroupAddr, igd.Device)
-
-	//If the group is not associated to any other device, then the entire Igmp Group obj itself can be removed
-	if ig.NumDevicesAll() == 0 {
-		logger.Infow(ctx, "Deleting IgmpGroup as all pending groups has expired", log.Fields{"Device": device, "GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr.String(), "PendingDevices": len(ig.Devices)})
-		GetApplication().DelIgmpGroup(ig)
-		return
-	}
-	if err := ig.WriteToDb(); err != nil {
-		logger.Errorw(ctx, "Igmp group Write to DB failed", log.Fields{"groupName": ig.GroupName})
-	}
-}
-
-//UpdateActiveChannelSubscriberAlarm - Updates the Active Channel Subscriber Alarm
-func (mvp *MvlanProfile) UpdateActiveChannelSubscriberAlarm() {
-	va := GetApplication()
-	logger.Debugw(ctx, "Update of Active Channel Subscriber Alarm", log.Fields{"Mvlan": mvp.Mvlan})
-	for srNo := range mvp.DevicesList {
-		d := va.GetDeviceBySerialNo(srNo)
-		if d == nil {
-			logger.Warnw(ctx, "Device info not found", log.Fields{"Device_SrNo": srNo, "Mvlan": mvp.Mvlan})
-			return
-		}
-		d.Ports.Range(func(key, value interface{}) bool {
-			//port := key.(string)
-			vp := value.(*VoltPort)
-			if vp.Type != VoltPortTypeAccess {
-				return true
-			}
-			if mvp.MaxActiveChannels > vp.ActiveChannels && vp.ChannelPerSubAlarmRaised {
-				serviceName := GetMcastServiceForSubAlarm(vp, mvp)
-				logger.Debugw(ctx, "Clearing-SendActiveChannelPerSubscriberAlarm-due-to-update", log.Fields{"ActiveChannels": vp.ActiveChannels, "ServiceName": serviceName})
-				vp.ChannelPerSubAlarmRaised = false
-			} else if mvp.MaxActiveChannels < vp.ActiveChannels && !vp.ChannelPerSubAlarmRaised {
-				/* When the max active channel count is reduced via update, we raise an alarm.
-				   But the previous excess channels still exist until a leave or expiry */
-				serviceName := GetMcastServiceForSubAlarm(vp, mvp)
-				logger.Debugw(ctx, "Raising-SendActiveChannelPerSubscriberAlarm-due-to-update", log.Fields{"ActiveChannels": vp.ActiveChannels, "ServiceName": serviceName})
-				vp.ChannelPerSubAlarmRaised = true
-			}
-			return true
-		})
-	}
-}
-
-//TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
-func (mvp *MvlanProfile) TriggerAssociatedFlowDelete(device string) bool {
-	mvp.mvpFlowLock.Lock()
-
-	cookieList := []uint64{}
-	flowMap := mvp.PendingDeleteFlow[device]
-
-	for cookie := range flowMap {
-		cookieList = append(cookieList, convertToUInt64(cookie))
-	}
-	mvp.mvpFlowLock.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, "Mvlan": mvp.Mvlan.String(), "Cookie": cookie})
-			err := mvp.DelFlows(vd, flow)
-			if err != nil {
-				logger.Warnw(ctx, "De-Configuring IGMP Flow for device failed ", log.Fields{"Device": device, "err": err})
-			}
-		}
-	}
-	return true
-}
-
-// JsonMarshal wrapper function for json Marshal MvlanProfile
-func (mvp *MvlanProfile) JsonMarshal() ([]byte, error) {
-	return json.Marshal(MvlanProfile{
-		Name:                mvp.Name,
-		Mvlan:               mvp.Mvlan,
-		PonVlan:             mvp.PonVlan,
-		Groups:              mvp.Groups,
-		Proxy:               mvp.Proxy,
-		Version:             mvp.Version,
-		IsPonVlanPresent:    mvp.IsPonVlanPresent,
-		IsChannelBasedGroup: mvp.IsChannelBasedGroup,
-		DevicesList:         mvp.DevicesList,
-		MaxActiveChannels:   mvp.MaxActiveChannels,
-		PendingDeleteFlow:   mvp.PendingDeleteFlow,
-		DeleteInProgress:    mvp.DeleteInProgress,
-		IgmpServVersion:     mvp.IgmpServVersion,
-	})
-}
