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,
-	})
-}
diff --git a/internal/pkg/application/igmpgroup.go b/internal/pkg/application/igmpgroup.go
new file mode 100644
index 0000000..629d92c
--- /dev/null
+++ b/internal/pkg/application/igmpgroup.go
@@ -0,0 +1,650 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"encoding/json"
+	"net"
+	"sync"
+	"time"
+
+	"github.com/google/gopacket/layers"
+
+	"voltha-go-controller/database"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	"voltha-go-controller/log"
+)
+
+// 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)
+	}
+}
+
+// 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 ""
+}
+
+// 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
+}
+
+// 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})
+        }
+}
+
+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})
+        }
+}
+
+// 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)
+}
diff --git a/internal/pkg/application/igmpgroupchannel.go b/internal/pkg/application/igmpgroupchannel.go
new file mode 100644
index 0000000..ed39d23
--- /dev/null
+++ b/internal/pkg/application/igmpgroupchannel.go
@@ -0,0 +1,735 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"encoding/json"
+	"net"
+
+	"github.com/google/gopacket/layers"
+
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/internal/pkg/types"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/log"
+)
+
+// 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
+}
+
+
+// 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 (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
+}
+
+// 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})
+}
+
+// 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
+}
+
+// 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)
+        }
+}
+
+// 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)
+}
+
+// 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++
+        }
+}
+
diff --git a/internal/pkg/application/igmpgroupdevice.go b/internal/pkg/application/igmpgroupdevice.go
new file mode 100644
index 0000000..07c2f82
--- /dev/null
+++ b/internal/pkg/application/igmpgroupdevice.go
@@ -0,0 +1,715 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"encoding/json"
+	"net"
+	"sync"
+	"time"
+
+	"github.com/google/gopacket/layers"
+
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	"voltha-go-controller/log"
+)
+
+// 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)
+        }
+
+}
+
+
+// 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
+}
+
+// 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
+}
+
+
+// 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()})
+        }
+}
+
+
+// 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
+}
+
+// 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)
+}
+
+// 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()})
+}
+
+// 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
+        }
+}
+
+// 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)
+}
diff --git a/internal/pkg/application/igmpponportchannel.go b/internal/pkg/application/igmpponportchannel.go
new file mode 100644
index 0000000..6c31ad4
--- /dev/null
+++ b/internal/pkg/application/igmpponportchannel.go
@@ -0,0 +1,98 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"voltha-go-controller/internal/pkg/util"
+	"voltha-go-controller/log"
+)
+
+// 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
+}
diff --git a/internal/pkg/application/igmpport.go b/internal/pkg/application/igmpport.go
new file mode 100644
index 0000000..5fe88e0
--- /dev/null
+++ b/internal/pkg/application/igmpport.go
@@ -0,0 +1,122 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"encoding/json"
+	"net"
+
+	"voltha-go-controller/internal/pkg/of"
+        "voltha-go-controller/log"
+)
+
+// 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
+}
diff --git a/internal/pkg/application/igmpprofiles.go b/internal/pkg/application/igmpprofiles.go
new file mode 100644
index 0000000..b5b24d4
--- /dev/null
+++ b/internal/pkg/application/igmpprofiles.go
@@ -0,0 +1,1229 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package application
+
+import (
+	"encoding/json"
+	"errors"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/internal/pkg/types"
+	"voltha-go-controller/database"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	"voltha-go-controller/log"
+)
+
+// ------------------------------------------------------------
+// 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))
+}
+
+//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})
+
+}
+
+// IsStaticGroup to check if group is static
+func (mvp *MvlanProfile) IsStaticGroup(groupName string) bool {
+        return mvp.Groups[groupName].IsStatic
+}
+
+// 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
+}
+
+// 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
+}
+
+//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})
+                }
+        }
+}
+//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
+}
+
+
+// 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 ""
+}
+
+// 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
+}
+
+
+//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,
+        })
+}
+
+// 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
+}
+
+// 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
+}
+
+// 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
+}
+
+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
+}
+
+// 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
+        }
+}
+
+// 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
+}
