meclearning and port ingnored rest interface along with multicast groups

Change-Id: I3116ac96b27cf5b83b5f6f459049f789dfff4154
diff --git a/internal/pkg/application/dhcprelay.go b/internal/pkg/application/dhcprelay.go
index dd92383..e32a7d0 100644
--- a/internal/pkg/application/dhcprelay.go
+++ b/internal/pkg/application/dhcprelay.go
@@ -16,8 +16,8 @@
 package application
 
 import (
-	"encoding/hex"
 	"context"
+	"encoding/hex"
 	"errors"
 	"net"
 	"sync"
@@ -57,8 +57,8 @@
 
 // List of RemoteID types supported
 const (
-        MACAddress      RemoteIDType = "MAC_ADDRESS"
-        CustomRemotedID RemoteIDType = "Custom"
+	MACAddress      RemoteIDType = "MAC_ADDRESS"
+	CustomRemotedID RemoteIDType = "Custom"
 )
 
 // MaxLenDhcpv6DUID constant
@@ -679,7 +679,7 @@
 		}
 
 		if err := cntlr.GetController().PacketOutReq(device, vpv.Port, port, buff.Bytes(), false); err != nil {
-			logger.Errorw(ctx, "PacketOutReq Failed",  log.Fields{"Error" : err})
+			logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
 		}
 	}
 }
@@ -916,7 +916,7 @@
 	// Now the packet constructed is output towards the switch to be emitted on
 	// the NNI port
 	if err := cntlr.GetController().PacketOutReq(device, outport, port, buff.Bytes(), false); err != nil {
-		logger.Errorw(ctx, "PacketOutReq Failed",  log.Fields{"Error" : err})
+		logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
 	}
 	if vpv.DhcpRelay {
 		// Inform dhcp request information to dhcp server handler
@@ -1173,7 +1173,7 @@
 	// Now the packet constructed is output towards the switch to be emitted on
 	// the NNI port
 	if err := cntlr.GetController().PacketOutReq(device, outport, port, buff.Bytes(), false); err != nil {
-		logger.Errorw(ctx, "PacketOutReq Failed",  log.Fields{"Error" : err})
+		logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
 	}
 	if vpv.DhcpRelay {
 		// Inform dhcp request information to dhcp server handler
@@ -1345,20 +1345,20 @@
 }
 
 type DhcpAllocation struct {
-        SubscriberID        string           `json:"subscriberId"`
-        ConnectPoint        string           `json:"connectPoint"`
-        MacAddress          net.HardwareAddr `json:"macAddress"`
-        State               int              `json:"state"`
-        VlanID              int              `json:"vlanId"`
-        CircuitID           []byte           `json:"circuitId"`
-        IpAllocated         net.IP           `json:"ipAllocated"`
-        AllocationTimeStamp time.Time        `json:"allocationTimestamp"`
+	SubscriberID        string           `json:"subscriberId"`
+	ConnectPoint        string           `json:"connectPoint"`
+	MacAddress          net.HardwareAddr `json:"macAddress"`
+	State               int              `json:"state"`
+	VlanID              int              `json:"vlanId"`
+	CircuitID           []byte           `json:"circuitId"`
+	IpAllocated         net.IP           `json:"ipAllocated"`
+	AllocationTimeStamp time.Time        `json:"allocationTimestamp"`
 }
 
 // GetAllocations returns DhcpAllocation info for all devices or for a device ID
-func (va *VoltApplication) GetAllocations(cntx context.Context, deviceID string) ([]*DhcpAllocation, error) {
+func (va *VoltApplication) GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error) {
 	logger.Debugw(ctx, "GetAllocations", log.Fields{"DeviceID": deviceID})
-	var allocations []*DhcpAllocation
+	allocations := []DhcpAllocation{}
 	for _, drv := range dhcpNws.Networks {
 		drv.sessionLock.RLock()
 		for _, session := range drv.sessions {
@@ -1374,16 +1374,16 @@
 				// If deviceID is not provided, return all allocations
 				// If deviceID exists then filter on deviceID
 				if len(deviceID) == 0 || deviceID == vpv.Device {
-					allocation := &DhcpAllocation {
-							SubscriberID : subscriber,
-							ConnectPoint : vpv.Device,
-							MacAddress : vpv.MacAddr,
-							State : int(vpv.RelayState) ,
-							VlanID : int(vpv.SVlan) ,
-							CircuitID : vpv.CircuitID ,
-							IpAllocated : vpv.Ipv4Addr ,
-							AllocationTimeStamp : vpv.DhcpExpiryTime,
-							}
+					allocation := DhcpAllocation{
+						SubscriberID:        subscriber,
+						ConnectPoint:        vpv.Device,
+						MacAddress:          vpv.MacAddr,
+						State:               int(vpv.RelayState),
+						VlanID:              int(vpv.SVlan),
+						CircuitID:           vpv.CircuitID,
+						IpAllocated:         vpv.Ipv4Addr,
+						AllocationTimeStamp: vpv.DhcpExpiryTime,
+					}
 					logger.Debugw(ctx, "DHCP Allocation found", log.Fields{"DhcpAlloc": allocation})
 					allocations = append(allocations, allocation)
 				}
@@ -1393,3 +1393,97 @@
 	}
 	return allocations, nil
 }
+
+type MacLearnerInfo struct {
+	DeviceId   string `json:"deviceId"`
+	PortNumber string `json:"portNumber"`
+	VlanId     string `json:"vlanId"`
+	MacAddress string `json:"macAddress"`
+}
+
+func (va *VoltApplication) GetAllMacLearnerInfo() ([]MacLearnerInfo, error) {
+	logger.Info(ctx, "GetMacLearnerInfo")
+	macLearner := []MacLearnerInfo{}
+	for _, drv := range dhcpNws.Networks {
+		logger.Debugw(ctx, "drv found", log.Fields{"drv": drv})
+		drv.sessionLock.RLock()
+		for _, session := range drv.sessions {
+			vpv, ok := session.(*VoltPortVnet)
+			if ok {
+				macLearn := MacLearnerInfo{
+					DeviceId:   vpv.Device,
+					PortNumber: vpv.Port,
+					VlanId:     vpv.SVlan.String(),
+					MacAddress: vpv.MacAddr.String(),
+				}
+				logger.Debugw(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
+				macLearner = append(macLearner, macLearn)
+			}
+		}
+		drv.sessionLock.RUnlock()
+	}
+	return macLearner, nil
+}
+
+func (va *VoltApplication) GetMacLearnerInfo(cntx context.Context, deviceId, portNumber, vlanId string) (MacLearnerInfo, error) {
+	logger.Info(ctx, "GetMecLearnerInfo")
+	macLearn := MacLearnerInfo{}
+	for _, drv := range dhcpNws.Networks {
+		logger.Infow(ctx, "drv found", log.Fields{"drv": drv})
+		drv.sessionLock.RLock()
+		for _, session := range drv.sessions {
+			vpv, ok := session.(*VoltPortVnet)
+			if ok {
+				if deviceId == vpv.Device && portNumber == vpv.Port && vlanId == vpv.SVlan.String() {
+					macLearn = MacLearnerInfo{
+						DeviceId:   vpv.Device,
+						PortNumber: vpv.Port,
+						VlanId:     vpv.SVlan.String(),
+						MacAddress: vpv.MacAddr.String(),
+					}
+					logger.Infow(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
+				} else if deviceId == vpv.Device && portNumber == vpv.Port && vlanId == "" {
+					macLearn = MacLearnerInfo{
+						DeviceId:   vpv.Device,
+						PortNumber: vpv.Port,
+						VlanId:     vpv.SVlan.String(),
+						MacAddress: vpv.MacAddr.String(),
+					}
+					logger.Infow(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
+				}
+			}
+		}
+		drv.sessionLock.RUnlock()
+	}
+	return macLearn, nil
+}
+
+func (va *VoltApplication) GetIgnoredPorts() (map[string][]string, error) {
+	logger.Info(ctx, "GetIgnoredPorts")
+	IgnoredPorts := make(map[string][]string)
+	portIgnored := func(key, value interface{}) bool {
+		voltDevice := value.(*VoltDevice)
+		logger.Infow(ctx, "Inside GetIgnoredPorts method", log.Fields{"deviceName": voltDevice.Name})
+		voltDevice.Ports.Range(func(key, value interface{}) bool {
+			port := key.(string)
+			logger.Infow(ctx, "Inside GetIgnoredPorts method", log.Fields{"port": port})
+			//Obtain all VPVs associated with the port
+			vnets, ok := GetApplication().VnetsByPort.Load(port)
+			if !ok {
+				return true
+			}
+			for _, vpv := range vnets.([]*VoltPortVnet) {
+
+				if vpv.MacLearning == MacLearningNone {
+					IgnoredPorts[vpv.Device] = append(IgnoredPorts[vpv.Device], vpv.Port)
+				}
+			}
+			logger.Debugw(ctx, "Ignored Port", log.Fields{"Ignored Port": IgnoredPorts})
+			return true
+		})
+		return true
+	}
+	va.DevicesDisc.Range(portIgnored)
+	logger.Info(ctx, "GetIgnoredPorts completed")
+	return IgnoredPorts, nil
+}
diff --git a/internal/pkg/controller/controller.go b/internal/pkg/controller/controller.go
index ead1182..7f5d9f1 100644
--- a/internal/pkg/controller/controller.go
+++ b/internal/pkg/controller/controller.go
@@ -562,3 +562,68 @@
 	}
 	return flows, nil
 }
+func (v *VoltController) GetAllMeterInfo() (map[string][]*of.Meter, error) {
+	logger.Info(ctx, "Entering into GetAllMeterInfo method")
+	meters := map[string][]*of.Meter{}
+	for _, device := range v.devices {
+		logger.Infow(ctx, "Inside GetAllMeterInfo method", log.Fields{"deviceId": device.ID})
+		for _, meter := range device.meters {
+			meters[device.ID] = append(meters[device.ID], meter)
+		}
+		logger.Infow(ctx, "Inside GetAllMeterInfo method", log.Fields{"meters": meters})
+	}
+	return meters, nil
+}
+
+func (v *VoltController) GetMeterInfo(cntx context.Context, id uint32) (map[string]*of.Meter, error) {
+	logger.Info(ctx, "Entering into GetMeterInfo method")
+	meters := map[string]*of.Meter{}
+	for _, device := range v.devices {
+		logger.Infow(ctx, "Inside GetMeterInfo method", log.Fields{"deviceId": device.ID})
+		meter, err := device.GetMeter(id)
+		if err != nil {
+			logger.Errorw(ctx, "Failed to fetch the meter", log.Fields{"Reason": err.Error()})
+			return nil, err
+		}
+		meters[device.ID] = meter
+		logger.Infow(ctx, "Inside GetAllMeterInfo method", log.Fields{"Meter": meters})
+	}
+	return meters, nil
+}
+
+func (v *VoltController) GetGroupList() ([]*of.Group, error) {
+	logger.Info(ctx, "Entering into GetGroupList method")
+	groups := []*of.Group{}
+	for _, device := range v.devices {
+		device.groups.Range(func(key, value interface{}) bool {
+			groupID := key.(uint32)
+			logger.Infow(ctx, "Inside GetGroupList method", log.Fields{"groupID": groupID})
+			//Obtain all groups associated with the device
+			grps, ok := device.groups.Load(groupID)
+			if !ok {
+				return true
+			}
+			grp := grps.(*of.Group)
+			groups = append(groups, grp)
+			return true
+		})
+	}
+	logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
+	return groups, nil
+}
+
+func (v *VoltController) GetGroups(cntx context.Context, id uint32) (*of.Group, error) {
+
+	logger.Info(ctx, "Entering into GetGroupList method")
+	var groups *of.Group
+	for _, device := range v.devices {
+		logger.Infow(ctx, "Inside GetGroupList method", log.Fields{"groupID": id})
+		grps, ok := device.groups.Load(id)
+		if !ok {
+			return nil, errors.New("Group not found")
+		}
+		groups = grps.(*of.Group)
+		logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
+	}
+	return groups, nil
+}
diff --git a/internal/pkg/of/group.go b/internal/pkg/of/group.go
index 39a9a6d..14d73a7 100644
--- a/internal/pkg/of/group.go
+++ b/internal/pkg/of/group.go
@@ -11,14 +11,15 @@
 * 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 of
 
 import (
 	"voltha-go-controller/log"
+
 	ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
-//	"github.com/opencord/voltha-protos/v5/go/voltha"
+	//	"github.com/opencord/voltha-protos/v5/go/voltha"
 )
 
 // The commands on groups avialable. Add is not expected to be used.