/*
* Copyright 2022-present Open Networking Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
 */

package application

import (
	"context"
	"encoding/json"
	"errors"
	"net"
	"strconv"
	"strings"
	"sync"

	"voltha-go-controller/database"
	cntlr "voltha-go-controller/internal/pkg/controller"
	"voltha-go-controller/internal/pkg/of"
	common "voltha-go-controller/internal/pkg/types"
	"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
	McIPs    []string
	Wildcard bool
	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 {
	Groups              map[string]*MvlanGroup
	Proxy               map[string]*MCGroupProxy
	oldGroups           map[string]*MvlanGroup
	oldProxy            map[string]*MCGroupProxy
	IgmpServVersion     map[string]*uint8
	PendingDeleteFlow   map[string]map[string]bool
	DevicesList         map[string]OperInProgress //device serial number //here
	Version             string
	Name                string
	mvpLock             sync.RWMutex
	mvpFlowLock         sync.RWMutex
	MaxActiveChannels   uint32
	Mvlan               of.VlanType
	PonVlan             of.VlanType
	IsPonVlanPresent    bool
	IsChannelBasedGroup bool
	DeleteInProgress    bool
}

// 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(cntx context.Context) 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(cntx, 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(cntx context.Context) {
	_ = db.DelMvlan(cntx, uint16(mvp.Mvlan))
}

// DelFlows - Triggers flow deletion after registering for flow indication event
func (mvp *MvlanProfile) DelFlows(cntx context.Context, 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(cntx); err != nil {
		logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
	}
	return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow, false)
}

// FlowRemoveSuccess - Process flow success indication
func (mvp *MvlanProfile) FlowRemoveSuccess(cntx context.Context, 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(cntx); 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(cntx context.Context, 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(cntx, 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(cntx, 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(cntx context.Context, 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(cntx, 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(cntx, igd)
					if ig.NumDevicesActive() == 0 {
						GetApplication().DelIgmpGroup(cntx, ig)
					}
				}
				return true
			})

			//Remove DS Igmp trap flow
			err := mvp.RemoveIgmpDSFlowForMvp(cntx, 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(cntx context.Context, 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(cntx, 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(cntx context.Context, 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(cntx, 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(cntx context.Context, 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(cntx, d.Name, added, true)
		mvp.ProcessStaticGroup(cntx, 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(cntx context.Context, 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(cntx, 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(cntx, port, ip, incl); change {
								groupModified = true
							}
							igc.ProcessMode(port, incl)

							if err := igp.WriteToDb(cntx, 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(cntx); 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(cntx context.Context, 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 Comparison", 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(cntx, deviceID, channelIP)
						} else {
							if (ig.IsGroupStatic) && mvp.IsStaticGroup(ig.GroupName) {
								if ig.GroupName != mvp.GetStaticGroupName(channelIP) {
									ig.HandleGroupMigration(cntx, deviceID, channelIP)
								}
							}
							continue
						}
					} else {
						logger.Debugw(ctx, "Channel Removed", log.Fields{"Channel": channel, "Group": grpName})
						ig.DelIgmpChannel(cntx, deviceID, net.ParseIP(channel))
						if ig.NumDevicesActive() == 0 {
							GetApplication().DelIgmpGroup(cntx, ig)
						}
					}
				}
				ig.IsGroupStatic = mvp.IsStaticGroup(ig.GroupName)
				if err := ig.WriteToDb(cntx); 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(cntx)
		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(cntx context.Context, 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(cntx, mvp.Name, groupAddr, device); ig != nil {
					ig.IgmpGroupLock.Lock()
					ig.AddReceiver(cntx, 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(cntx, 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(cntx, 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(cntx, device, StaticPort, groupAddr, nil, 0xFF)
					ig.IgmpGroupLock.Unlock()
					ig.updateGroupName(cntx, grpName)
				} else {
					ig.DelIgmpGroup(cntx)
				}
			} else {
				ig.IgmpGroupLock.Lock()
				ig.DelReceiver(cntx, device, StaticPort, groupAddr, nil, 0xFF)
				ig.IgmpGroupLock.Unlock()
			}
			if ig.NumDevicesActive() == 0 {
				GetApplication().DelIgmpGroup(cntx, 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(cntx context.Context, 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(cntx, deviceID, []net.IP{}, removedStaticChannels)
		}
	}
	mvp.GroupsUpdated(cntx, deviceID)
	if len(addedStaticChannels) > 0 {
		mvp.updateStaticGroups(cntx, 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(cntx, deviceID, commonChannels, []net.IP{})
			} else {
				/* Dynamic group proxy modified, need to trigger membership report with new mode/src-list for existing channels */
				mvp.updateDynamicGroups(cntx, deviceID, commonChannels, []net.IP{})
			}
		}
	}

	mvp.SetUpdateStatus(serialNo, NoOp)

	if deviceID == "" || !mvp.isUpdateInProgress() {
		mvp.oldGroups = nil
	}
	if err := mvp.WriteToDb(cntx); 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(cntx context.Context, 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(cntx, 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
	IgmpVerToServer    string
	Version            string
	IgmpSourceIP       net.IP
	UnsolicitedTimeOut uint32 //In seconds
	MaxResp            uint32
	KeepAliveInterval  uint32
	KeepAliveCount     uint32
	LastQueryInterval  uint32
	LastQueryCount     uint32
	IgmpCos            uint8
	FastLeave          bool
	PeriodicQuery      bool
	WithRAUpLink       bool
	WithRADownLink     bool
}

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(cntx context.Context) error {
	igmpProfile.Version = database.PresentVersionMap[database.IgmpProfPath]
	b, err := json.Marshal(igmpProfile)
	if err != nil {
		return err
	}
	if err1 := db.PutIgmpProfile(cntx, igmpProfile.ProfileID, string(b)); err1 != nil {
		return err1
	}
	return nil
}
