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.
diff --git a/voltha-go-controller/nbi/rest.go b/voltha-go-controller/nbi/rest.go
index d1db3cc..50c5d94 100644
--- a/voltha-go-controller/nbi/rest.go
+++ b/voltha-go-controller/nbi/rest.go
@@ -11,7 +11,7 @@
 * 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 nbi
 
@@ -19,33 +19,43 @@
 	"context"
 	"net/http"
 
+	"voltha-go-controller/voltha-go-controller/onos_nbi"
+
 	"github.com/gorilla/mux"
 
 	"voltha-go-controller/log"
-	"voltha-go-controller/voltha-go-controller/onos_nbi"
 )
 
 var logger log.CLogger
 var ctx = context.TODO()
 
 const (
-	SubscribersPath string = "/subscribers/{id}"
-	ProfilesPath    string = "/profiles/{id}"
-	IgmpProxyPath   string = "/igmp-proxy/"
-	MulticastPath   string = "/multicast/"
-	FlowsPath       string = "/flows/"
-	DevicesPath       string = "/devices"
-	PortsPath       string = "/devices/ports"
-	FlowsPerDeviceIDPath string = "/flows/{deviceId}"
-	FlowPerDeviceIDFlowIDPath string = "/flows/{deviceId}/{flowId}"
-	PendingFlowsPath          string = "/flows/pending/"
-	ProgrammedSubscribersPath string = "/programmed-subscribers/"
-	ServiceDevicePortPath     string = "/services/{device}/{port}"
-	ServicePortNamePath       string = "/services/{portName}"
-	ServicePortStagCtagTpIDPath string = "/services/{portName}/{sTag}/{cTag}/{tpId}"
-	AllocationsPath             string = "/allocations/"
-	AllocationsDeviceIDPath     string = "/allocations/{deviceId}"
+	SubscribersPath                   string = "/subscribers/{id}"
+	ProfilesPath                      string = "/profiles/{id}"
+	IgmpProxyPath                     string = "/igmp-proxy/"
+	MulticastPath                     string = "/multicast/"
+	FlowsPath                         string = "/flows/"
+	DevicesPath                       string = "/devices"
+	PortsPath                         string = "/devices/ports"
+	FlowsPerDeviceIDPath              string = "/flows/{deviceId}"
+	FlowPerDeviceIDFlowIDPath         string = "/flows/{deviceId}/{flowId}"
+	PendingFlowsPath                  string = "/flows/pending/"
+	ProgrammedSubscribersPath         string = "/programmed-subscribers/"
+	ServiceDevicePortPath             string = "/services/{device}/{port}"
+	ServicePortNamePath               string = "/services/{portName}"
+	ServicePortStagCtagTpIDPath       string = "/services/{portName}/{sTag}/{cTag}/{tpId}"
+	AllocationsPath                   string = "/allocations/"
+	AllocationsDeviceIDPath           string = "/allocations/{deviceId}"
+	MecLearnerPath                    string = "/mapping/all"
+	MecLearnerDeviceIdAndPortNoPath   string = "/mapping/{deviceId}/{portNumber}"
+	MecLearnerDevicePortAndVlanIdPath string = "/mapping/{deviceId}/{portNumber}/{vlanId}"
+	PortIgnoredPath                   string = "/ports/ignored"
+	MetersParh                        string = "/meters"
+	MetersByIdPath                    string = "/meters/{id}"
+	GroupsPath                        string = "/groups"
+	GroupsByIdPath                    string = "/groups/{id}"
 )
+
 // RestStart to execute for API
 func RestStart() {
 	mu := mux.NewRouter()
@@ -54,20 +64,26 @@
 	mu.HandleFunc(ProfilesPath, (&ProfileHandle{}).ServeHTTP)
 	mu.HandleFunc(IgmpProxyPath, (&IgmpProxyHandle{}).ServeHTTP)
 	mu.HandleFunc(MulticastPath, (&MulticastHandle{}).ServeHTTP)
-
-        mu.HandleFunc(FlowsPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
-        mu.HandleFunc(FlowsPerDeviceIDPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
-        mu.HandleFunc(FlowPerDeviceIDFlowIDPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
-        mu.HandleFunc(PendingFlowsPath, (&onos_nbi.PendingFlowHandle{}).ServeHTTP)
-        mu.HandleFunc(ProgrammedSubscribersPath, (&onos_nbi.ServiceAdapter{}).ServeHTTP)
-        mu.HandleFunc(ServiceDevicePortPath, (&onos_nbi.ServiceAdapter{}).ServeHTTP)
-        mu.HandleFunc(ServicePortNamePath, (&onos_nbi.ServiceAdapter{}).ServeHTTPWithPortName)
-        mu.HandleFunc(ServicePortStagCtagTpIDPath, (&onos_nbi.ServiceAdapter{}).ServeHTTPWithPortName)
-        mu.HandleFunc(AllocationsPath, (&onos_nbi.DhcpRelayHandle{}).ServeHTTP)
-        mu.HandleFunc(AllocationsDeviceIDPath, (&onos_nbi.DhcpRelayHandle{}).ServeHTTP)
-        mu.HandleFunc(DevicesPath, (&onos_nbi.DeviceHandle{}).ServeHTTP)
-        mu.HandleFunc(PortsPath, (&onos_nbi.DevicePortHandle{}).ServeHTTP)
-
+	mu.HandleFunc(FlowsPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
+	mu.HandleFunc(FlowsPerDeviceIDPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
+	mu.HandleFunc(FlowPerDeviceIDFlowIDPath, (&onos_nbi.FlowHandle{}).ServeHTTP)
+	mu.HandleFunc(PendingFlowsPath, (&onos_nbi.PendingFlowHandle{}).ServeHTTP)
+	mu.HandleFunc(ProgrammedSubscribersPath, (&onos_nbi.ServiceAdapter{}).ServeHTTP)
+	mu.HandleFunc(ServiceDevicePortPath, (&onos_nbi.ServiceAdapter{}).ServeHTTP)
+	mu.HandleFunc(ServicePortNamePath, (&onos_nbi.ServiceAdapter{}).ServeHTTPWithPortName)
+	mu.HandleFunc(ServicePortStagCtagTpIDPath, (&onos_nbi.ServiceAdapter{}).ServeHTTPWithPortName)
+	mu.HandleFunc(AllocationsPath, (&onos_nbi.DhcpRelayHandle{}).ServeHTTP)
+	mu.HandleFunc(AllocationsDeviceIDPath, (&onos_nbi.DhcpRelayHandle{}).ServeHTTP)
+	mu.HandleFunc(DevicesPath, (&onos_nbi.DeviceHandle{}).ServeHTTP)
+	mu.HandleFunc(PortsPath, (&onos_nbi.DevicePortHandle{}).ServeHTTP)
+	mu.HandleFunc(MecLearnerPath, (&onos_nbi.MacLearnerHandle{}).ServeHTTP)
+	mu.HandleFunc(MecLearnerDeviceIdAndPortNoPath, (&onos_nbi.MacLearnerHandle{}).ServeHTTP)
+	mu.HandleFunc(MecLearnerDevicePortAndVlanIdPath, (&onos_nbi.MacLearnerHandle{}).ServeHTTP)
+	mu.HandleFunc(PortIgnoredPath, (&onos_nbi.PortIgnoredHandle{}).PortsIgnoredServeHTTP)
+	mu.HandleFunc(MetersParh, (&onos_nbi.MetersHandle{}).MeterServeHTTP)
+	mu.HandleFunc(MetersByIdPath, (&onos_nbi.MetersHandle{}).MeterServeHTTP)
+	mu.HandleFunc(GroupsPath, (&onos_nbi.GroupsHandle{}).GroupServeHTTP)
+	mu.HandleFunc(GroupsByIdPath, (&onos_nbi.GroupsHandle{}).GroupServeHTTP)
 	err := http.ListenAndServe(":8181", mu)
 	logger.Infow(ctx, "Rest Server Started", log.Fields{"Error": err})
 }
@@ -80,4 +96,3 @@
 		panic(err)
 	}
 }
-
diff --git a/voltha-go-controller/onos_nbi/groups.go b/voltha-go-controller/onos_nbi/groups.go
new file mode 100644
index 0000000..c992272
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/groups.go
@@ -0,0 +1,130 @@
+/*
+* 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 onos_nbi
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"strconv"
+	app "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/log"
+
+	"github.com/gorilla/mux"
+)
+
+type GroupsHandle struct {
+}
+
+func init() {
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.AddPackageWithDefaultParam()
+	if err != nil {
+		panic(err)
+	}
+}
+
+// ServeHTTP to serve http request
+func (gh *GroupsHandle) GroupServeHTTP(w http.ResponseWriter, r *http.Request) {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	vars := mux.Vars(r)
+	groupID := vars["id"]
+
+	switch r.Method {
+	case "GET":
+		if groupID != "" {
+			gh.GetGroupInfo(context.Background(), groupID, w, r)
+		} else {
+			gh.GetAllGroups(context.Background(), w, r)
+		}
+
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
+}
+
+func (gh *GroupsHandle) GetGroupInfo(cntx context.Context, groupId string, w http.ResponseWriter, r *http.Request) {
+
+	groupResp := GroupList{}
+	groupResp.Groups = []*GroupsInfo{}
+	grpId, err := strconv.ParseUint(groupId, 10, 32)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to parse string to uint32", log.Fields{"Reason": err.Error()})
+	}
+	id := uint32(grpId)
+
+	logger.Infow(ctx, "Inside GetGroupInfo method", log.Fields{"groupId": id})
+
+	Groups, err := app.GetController().GetGroups(ctx, id)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to fetch group info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusNotFound)
+		return
+	}
+
+	GroupResp := gh.convertGroupsToOnosGroup(Groups)
+	groupResp.Groups = append(groupResp.Groups, GroupResp)
+
+	GroupsRespJSON, err := json.Marshal(groupResp)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling group response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(GroupsRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending group response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}
+
+func (gh *GroupsHandle) GetAllGroups(cntx context.Context, w http.ResponseWriter, r *http.Request) {
+
+	logger.Info(cntx, "Inside GetAllGroups method")
+	groupListResp := GroupList{}
+	groupListResp.Groups = []*GroupsInfo{}
+
+	GroupsInfo, err := app.GetController().GetGroupList()
+	if err != nil {
+		logger.Errorw(ctx, "Failed to fetch group info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusNotFound)
+		return
+	}
+
+	for _, groups := range GroupsInfo {
+		grpResp := gh.convertGroupsToOnosGroup(groups)
+		groupListResp.Groups = append(groupListResp.Groups, grpResp)
+	}
+
+	GroupRespJSON, err := json.Marshal(groupListResp)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(GroupRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}
diff --git a/voltha-go-controller/onos_nbi/maclearning_info.go b/voltha-go-controller/onos_nbi/maclearning_info.go
new file mode 100644
index 0000000..18365bf
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/maclearning_info.go
@@ -0,0 +1,109 @@
+/*
+* 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 onos_nbi
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	app "voltha-go-controller/internal/pkg/application"
+	"voltha-go-controller/log"
+
+	"github.com/gorilla/mux"
+)
+
+type MacLearnerHandle struct {
+}
+
+func init() {
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.AddPackageWithDefaultParam()
+	if err != nil {
+		panic(err)
+	}
+}
+
+// ServeHTTP to serve http request
+func (mlh *MacLearnerHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	vars := mux.Vars(r)
+	deviceID := vars["deviceId"]
+	portNum := vars["portNumber"]
+	vlanId := vars["vlanId"]
+	switch r.Method {
+	case "GET":
+		if deviceID == "" && portNum == "" && vlanId == "" {
+			mlh.GetAllMacLearnerInfo(context.Background(), w, r)
+		} else {
+			mlh.GetMacLearnerInfo(context.Background(), deviceID, portNum, vlanId, w, r)
+		}
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
+}
+
+func (mlh *MacLearnerHandle) GetAllMacLearnerInfo(cntx context.Context, w http.ResponseWriter, r *http.Request) {
+
+	logger.Info(cntx, "Inside GetAllMacLearnerInfo method")
+	MacLearnerInfo, err := app.GetApplication().GetAllMacLearnerInfo()
+	if err != nil {
+		logger.Errorw(ctx, "Failed to get mac learning info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	MliRespJSON, err := json.Marshal(MacLearnerInfo)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling mac learner response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(MliRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending mac learner response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}
+
+func (mlh *MacLearnerHandle) GetMacLearnerInfo(cntx context.Context, deviceID, portNum, vlanId string, w http.ResponseWriter, r *http.Request) {
+
+	logger.Infow(cntx, "Inside GetMacLearnerInfo method", log.Fields{"deviceID": deviceID, "portNum": portNum, "vlanId": vlanId})
+	MacLearnerInfo, err := app.GetApplication().GetMacLearnerInfo(cntx, deviceID, portNum, vlanId)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to get mac learning info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	MliRespJSON, err := json.Marshal(MacLearnerInfo)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling mac learner response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(MliRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending mac learner response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}
diff --git a/voltha-go-controller/onos_nbi/meters.go b/voltha-go-controller/onos_nbi/meters.go
new file mode 100644
index 0000000..a5ae839
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/meters.go
@@ -0,0 +1,123 @@
+/*
+* 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 onos_nbi
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"strconv"
+	app "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/log"
+
+	"github.com/gorilla/mux"
+)
+
+type MetersHandle struct {
+}
+
+func init() {
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.AddPackageWithDefaultParam()
+	if err != nil {
+		panic(err)
+	}
+}
+
+// ServeHTTP to serve http request
+func (mh *MetersHandle) MeterServeHTTP(w http.ResponseWriter, r *http.Request) {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	vars := mux.Vars(r)
+	meterID := vars["id"]
+
+	switch r.Method {
+	case "GET":
+		if meterID != "" {
+			logger.Warnw(ctx, "Calling GetMeter method", log.Fields{"MeterId": meterID})
+			mh.GetMeter(context.Background(), meterID, w, r)
+		} else {
+			mh.GetAllMeters(context.Background(), w, r)
+		}
+
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
+}
+
+func (mh *MetersHandle) GetMeter(cntx context.Context, meterId string, w http.ResponseWriter, r *http.Request) {
+	logger.Info(cntx, "Inside GetMeter method")
+	meterListResp := MeterList{}
+	meterListResp.Meters = []Meters{}
+	mId, err := strconv.ParseUint(meterId, 10, 32)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to parse string to uint32", log.Fields{"Reason": err.Error()})
+	}
+	id := uint32(mId)
+	logger.Infow(ctx, "Meter Id", log.Fields{"metreId": id})
+	meterInfo, err := app.GetController().GetMeterInfo(cntx, id)
+	if err != nil {
+		logger.Errorw(ctx, "Failed to get meter info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusNotFound)
+	}
+
+	for deviceId, meter := range meterInfo {
+		meterResp := mh.MeterObjectMapping(meter, deviceId)
+		meterListResp.Meters = append(meterListResp.Meters, meterResp)
+	}
+	MeterRespJSON, err := json.Marshal(meterListResp)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(MeterRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+}
+
+func (mh *MetersHandle) GetAllMeters(cntx context.Context, w http.ResponseWriter, r *http.Request) {
+	logger.Info(cntx, "Inside GetAllMeters method")
+	metersList := MeterList{}
+	metersList.Meters = []Meters{}
+	meterInfo, err := app.GetController().GetAllMeterInfo()
+	if err != nil {
+		logger.Errorw(ctx, "Failed to get meter info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusNotFound)
+	}
+	for deviceId, meters := range meterInfo {
+		for _, meter := range meters {
+			mtr := mh.MeterObjectMapping(meter, deviceId)
+			metersList.Meters = append(metersList.Meters, mtr)
+		}
+	}
+	MeterRespJSON, err := json.Marshal(metersList)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(MeterRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending meter response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}
diff --git a/voltha-go-controller/onos_nbi/models.go b/voltha-go-controller/onos_nbi/models.go
index 9f83404..974eca3 100644
--- a/voltha-go-controller/onos_nbi/models.go
+++ b/voltha-go-controller/onos_nbi/models.go
@@ -12,211 +12,213 @@
 * 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 onos_nbi
 
 import (
+	"fmt"
 	"strconv"
-	"voltha-go-controller/internal/pkg/of"
 	app "voltha-go-controller/internal/pkg/application"
 	"voltha-go-controller/internal/pkg/controller"
+
+	"voltha-go-controller/internal/pkg/of"
 )
 
 const (
-        /** Switch input port. */
-        IN_PORT string = "IN_PORT"
+	/** Switch input port. */
+	IN_PORT string = "IN_PORT"
 
-        /** Switch physical input port. */
-        IN_PHY_PORT string = "IN_PHY_PORT"
+	/** Switch physical input port. */
+	IN_PHY_PORT string = "IN_PHY_PORT"
 
-        /** Metadata passed between tables. */
-        METADATA string = "METADATA"
+	/** Metadata passed between tables. */
+	METADATA string = "METADATA"
 
-        /** Ethernet destination address. */
-        ETH_DST string = "ETH_DST"
+	/** Ethernet destination address. */
+	ETH_DST string = "ETH_DST"
 
-        /** Ethernet destination address with masking. */
-        ETH_DST_MASKED = "ETH_DST_MASKED"
+	/** Ethernet destination address with masking. */
+	ETH_DST_MASKED = "ETH_DST_MASKED"
 
-        /** Ethernet source address. */
-        ETH_SRC string = "ETH_SRC"
+	/** Ethernet source address. */
+	ETH_SRC string = "ETH_SRC"
 
-        /** Ethernet source address with masking. */
-        ETH_SRC_MASKED string = "ETH_SRC_MASKED"
+	/** Ethernet source address with masking. */
+	ETH_SRC_MASKED string = "ETH_SRC_MASKED"
 
-        /** Ethernet frame type. */
-        ETH_TYPE string = "ETH_TYPE"
+	/** Ethernet frame type. */
+	ETH_TYPE string = "ETH_TYPE"
 
-        /** VLAN id. */
-        VLAN_VID string = "VLAN_VID"
+	/** VLAN id. */
+	VLAN_VID string = "VLAN_VID"
 
-        /** VLAN priority. */
-        VLAN_PCP string = "VLAN_PCP"
-        /**
-         * Inner VLAN id.
-         *
-         * Note: Some drivers may not support this.
-         */
-        INNER_VLAN_VID string = "INNER_VLAN_VID"
+	/** VLAN priority. */
+	VLAN_PCP string = "VLAN_PCP"
+	/**
+	 * Inner VLAN id.
+	 *
+	 * Note: Some drivers may not support this.
+	 */
+	INNER_VLAN_VID string = "INNER_VLAN_VID"
 
-        /**
-         * Inner VLAN pcp.
-         *
-         * Note: Some drivers may not support this.
-         */
-        INNER_VLAN_PCP string = "INNER_VLAN_PCP"
+	/**
+	 * Inner VLAN pcp.
+	 *
+	 * Note: Some drivers may not support this.
+	 */
+	INNER_VLAN_PCP string = "INNER_VLAN_PCP"
 
-        /** IP DSCP (6 bits in ToS field). */
-        IP_DSCP string = "IP_DSCP"
+	/** IP DSCP (6 bits in ToS field). */
+	IP_DSCP string = "IP_DSCP"
 
-        /** IP ECN (2 bits in ToS field). */
-        IP_ECN string = "IP_ECN"
+	/** IP ECN (2 bits in ToS field). */
+	IP_ECN string = "IP_ECN"
 
-        /** IP protocol. */
-        IP_PROTO string = "IP_PROTO"
+	/** IP protocol. */
+	IP_PROTO string = "IP_PROTO"
 
-        /** IPv4 source address. */
-        IPV4_SRC string = "IPV4_SRC"
+	/** IPv4 source address. */
+	IPV4_SRC string = "IPV4_SRC"
 
-        /** IPv4 destination address. */
-        IPV4_DST string = "IPV4_DST"
+	/** IPv4 destination address. */
+	IPV4_DST string = "IPV4_DST"
 
-        /** TCP source port. */
-        TCP_SRC string = "TCP_SRC"
+	/** TCP source port. */
+	TCP_SRC string = "TCP_SRC"
 
-        /** TCP source port with masking. */
-        TCP_SRC_MASKED string = "TCP_SRC_MASKED"
+	/** TCP source port with masking. */
+	TCP_SRC_MASKED string = "TCP_SRC_MASKED"
 
-        /** TCP destination port. */
-        TCP_DST string = "TCP_DST"
+	/** TCP destination port. */
+	TCP_DST string = "TCP_DST"
 
-        /** TCP destination port with masking. */
-        TCP_DST_MASKED string = "TCP_DST"
+	/** TCP destination port with masking. */
+	TCP_DST_MASKED string = "TCP_DST"
 
-        /** UDP source port. */
-        UDP_SRC string = "UDP_SRC"
+	/** UDP source port. */
+	UDP_SRC string = "UDP_SRC"
 
-        /** UDP source port with masking. */
-        UDP_SRC_MASKED string = "UDP_SRC_MASKED"
+	/** UDP source port with masking. */
+	UDP_SRC_MASKED string = "UDP_SRC_MASKED"
 
-        /** UDP destination port. */
-        UDP_DST string = "UDP_DST"
+	/** UDP destination port. */
+	UDP_DST string = "UDP_DST"
 
-        /** UDP destination port with masking. */
-        UDP_DST_MASKED string = "UDP_DST_MASKED"
+	/** UDP destination port with masking. */
+	UDP_DST_MASKED string = "UDP_DST_MASKED"
 
-        /** SCTP source port. */
-        SCTP_SRC string = "SCTP_SRC"
+	/** SCTP source port. */
+	SCTP_SRC string = "SCTP_SRC"
 
-        /** SCTP source port with masking. */
-        SCTP_SRC_MASKED string = "SCTP_SRC_MASKED"
+	/** SCTP source port with masking. */
+	SCTP_SRC_MASKED string = "SCTP_SRC_MASKED"
 
-        /** SCTP destination port. */
-        SCTP_DST string = "SCTP_DST"
+	/** SCTP destination port. */
+	SCTP_DST string = "SCTP_DST"
 
-        /** SCTP destination port with masking. */
-        SCTP_DST_MASKED string = "SCTP_DST_MASKED"
+	/** SCTP destination port with masking. */
+	SCTP_DST_MASKED string = "SCTP_DST_MASKED"
 
-        /** ICMP type. */
-        ICMPV4_TYPE string = "ICMPV4_TYPE"
+	/** ICMP type. */
+	ICMPV4_TYPE string = "ICMPV4_TYPE"
 
-        /** ICMP code. */
-        ICMPV4_CODE string = "ICMPV4_CODE"
+	/** ICMP code. */
+	ICMPV4_CODE string = "ICMPV4_CODE"
 
-        /** ARP opcode. */
-        ARP_OP string = "ARP_OP"
+	/** ARP opcode. */
+	ARP_OP string = "ARP_OP"
 
-        /** ARP source IPv4 address. */
-        ARP_SPA string = "ARP_SPA"
+	/** ARP source IPv4 address. */
+	ARP_SPA string = "ARP_SPA"
 
-        /** ARP target IPv4 address. */
-        ARP_TPA string = "ARP_TPA"
+	/** ARP target IPv4 address. */
+	ARP_TPA string = "ARP_TPA"
 
-        /** ARP source hardware address. */
-        ARP_THA string = "ARP_THA"
+	/** ARP source hardware address. */
+	ARP_THA string = "ARP_THA"
 
-        /** IPv6 source address. */
-        IPV6_SRC string = "IPV6_SRC"
+	/** IPv6 source address. */
+	IPV6_SRC string = "IPV6_SRC"
 
-        /** IPv6 destination address. */
-        IPV6_DST string = "IPV6_DST"
+	/** IPv6 destination address. */
+	IPV6_DST string = "IPV6_DST"
 
-        /** IPv6 Flow Label. */
-        IPV6_FLABEL string = "IPV6_FLABEL"
+	/** IPv6 Flow Label. */
+	IPV6_FLABEL string = "IPV6_FLABEL"
 
-        /** ICMPv6 type. */
-        ICMPV6_TYPE string = "ICMPV6_TYPE"
+	/** ICMPv6 type. */
+	ICMPV6_TYPE string = "ICMPV6_TYPE"
 
-        /** ICMPv6 code. */
-        ICMPV6_CODE string = "ICMPV6_CODE"
+	/** ICMPv6 code. */
+	ICMPV6_CODE string = "ICMPV6_CODE"
 
-        /** Target address for ND. */
-        IPV6_ND_TARGET string = "IPV6_ND_TARGET"
+	/** Target address for ND. */
+	IPV6_ND_TARGET string = "IPV6_ND_TARGET"
 
-        /** Source link-layer for ND. */
-        IPV6_ND_SLL string = "IPV6_ND_SLL"
+	/** Source link-layer for ND. */
+	IPV6_ND_SLL string = "IPV6_ND_SLL"
 
-        /** Target link-layer for ND. */
-        IPV6_ND_TLL string = "IPV6_ND_TLL"
+	/** Target link-layer for ND. */
+	IPV6_ND_TLL string = "IPV6_ND_TLL"
 
-        /** MPLS label. */
-        MPLS_LABEL string = "MPLS_LABEL"
+	/** MPLS label. */
+	MPLS_LABEL string = "MPLS_LABEL"
 
-        /** MPLS TC. */
-        MPLS_TC string = "MPLS_TC"
+	/** MPLS TC. */
+	MPLS_TC string = "MPLS_TC"
 
-        /**  MPLS BoS bit. */
-        MPLS_BOS string = "MPLS_BOS"
+	/**  MPLS BoS bit. */
+	MPLS_BOS string = "MPLS_BOS"
 
-        /** PBB I-SID. */
-        PBB_ISID string = "PBB_ISID"
+	/** PBB I-SID. */
+	PBB_ISID string = "PBB_ISID"
 
-        /** Logical Port Metadata. */
-        TUNNEL_ID string = "TUNNEL_ID"
+	/** Logical Port Metadata. */
+	TUNNEL_ID string = "TUNNEL_ID"
 
-        /** IPv6 Extension Header pseudo-field. */
-        IPV6_EXTHDR string = "IPV6_EXTHDR"
+	/** IPv6 Extension Header pseudo-field. */
+	IPV6_EXTHDR string = "IPV6_EXTHDR"
 
-        /** Unassigned value: 40. */
-        UNASSIGNED_40 string = "UNASSIGNED_40"
+	/** Unassigned value: 40. */
+	UNASSIGNED_40 string = "UNASSIGNED_40"
 
-        /** PBB UCA header field. */
-        PBB_UCA string = "PBB_UCA"
+	/** PBB UCA header field. */
+	PBB_UCA string = "PBB_UCA"
 
-        /** TCP flags. */
-        TCP_FLAGS string = "TCP_FLAGS"
+	/** TCP flags. */
+	TCP_FLAGS string = "TCP_FLAGS"
 
-        /** Output port from action set metadata. */
-        ACTSET_OUTPUT string = "ACTSET_OUTPUT"
+	/** Output port from action set metadata. */
+	ACTSET_OUTPUT string = "ACTSET_OUTPUT"
 
-        /** Packet type value. */
-        PACKET_TYPE string = "PACKET_TYPE"
+	/** Packet type value. */
+	PACKET_TYPE string = "PACKET_TYPE"
 
-        //
-        // NOTE: Everything below is defined elsewhere: ONOS-specific,
-        // extensions, etc.
-        //
-        /** Optical channel signal ID (lambda). */
-        OCH_SIGID string = "OCH_SIGID"
+	//
+	// NOTE: Everything below is defined elsewhere: ONOS-specific,
+	// extensions, etc.
+	//
+	/** Optical channel signal ID (lambda). */
+	OCH_SIGID string = "OCH_SIGID"
 
-        /** Optical channel signal type (fixed or flexible). */
-        OCH_SIGTYPE string = "OCH_SIGTYPE"
+	/** Optical channel signal type (fixed or flexible). */
+	OCH_SIGTYPE string = "OCH_SIGTYPE"
 
-        /** ODU (Optical channel Data Unit) signal ID. */
-        ODU_SIGID string = "ODU_SIGID"
+	/** ODU (Optical channel Data Unit) signal ID. */
+	ODU_SIGID string = "ODU_SIGID"
 
-        /** ODU (Optical channel Data Unit) signal type. */
-        ODU_SIGTYPE string = "ODU_SIGTYPE"
+	/** ODU (Optical channel Data Unit) signal type. */
+	ODU_SIGTYPE string = "ODU_SIGTYPE"
 
-        /** Protocol-independent. */
-        PROTOCOL_INDEPENDENT string = "PROTOCOL_INDEPENDENT"
+	/** Protocol-independent. */
+	PROTOCOL_INDEPENDENT string = "PROTOCOL_INDEPENDENT"
 
-        /** Extension criterion. */
-        EXTENSION string = "EXTENSION"
+	/** Extension criterion. */
+	EXTENSION string = "EXTENSION"
 
-        /** An empty criterion. */
-        DUMMY string = "DUMMY"
+	/** An empty criterion. */
+	DUMMY string = "DUMMY"
 
 	/* OUTPUT instruction */
 	OUTPUT string = "OUTPUT"
@@ -238,25 +240,35 @@
 
 	/* VLAN_SET operation */
 	VLAN_SET string = "VLAN_SET"
+
+	ALL string = "ALL"
+
+	ADDED string = "ADDED"
+
+	FAILED string = "FAILED"
+
+	PENDING string = "PENDING"
 )
 
 // Selector Critrtion structs
-type Criterion interface{
+type Criterion interface {
 	GetType() string
 }
 
 type PortSelector struct {
-	Type     string `json:"type"`
-	Port     int    `json:"port,omitempty"`
+	Type string `json:"type"`
+	Port int    `json:"port,omitempty"`
 }
 
 func (s PortSelector) GetType() string {
 	return s.Type
 }
+
 type EthTypeSelector struct {
-	Type     string `json:"type"`
-	EthType  string `json:"ethType,omitempty"`
+	Type    string `json:"type"`
+	EthType string `json:"ethType,omitempty"`
 }
+
 func (s EthTypeSelector) GetType() string {
 	return s.Type
 }
@@ -265,29 +277,32 @@
 	Type     string `json:"type"`
 	Protocol int    `json:"protocol,omitempty"`
 }
+
 func (s ProtocolSelector) GetType() string {
 	return s.Type
 }
 
 type UDPPortSelector struct {
-	Type     string `json:"type"`
-	UDPPort  int    `json:"udpPort,omitempty"`
+	Type    string `json:"type"`
+	UDPPort int    `json:"udpPort,omitempty"`
 }
+
 func (s UDPPortSelector) GetType() string {
 	return s.Type
 }
 
 type VlanSelector struct {
-	Type     string `json:"type"`
-	VlanID   int    `json:"vlanId,omitempty"`
+	Type   string `json:"type"`
+	VlanID int    `json:"vlanId,omitempty"`
 }
+
 func (s VlanSelector) GetType() string {
 	return s.Type
 }
 
 type EthSrcSelector struct {
-	Type     string `json:"type"`
-	EthSrc   string `json:"ethsrc,omitempty"`
+	Type   string `json:"type"`
+	EthSrc string `json:"ethsrc,omitempty"`
 }
 
 func (s EthSrcSelector) GetType() string {
@@ -295,8 +310,8 @@
 }
 
 type EthDstSelector struct {
-	Type     string `json:"type"`
-	DstSrc   string `json:"ethdst,omitempty"`
+	Type   string `json:"type"`
+	DstSrc string `json:"ethdst,omitempty"`
 }
 
 func (s EthDstSelector) GetType() string {
@@ -311,10 +326,11 @@
 func (s MetaDataSelector) GetType() string {
 	return s.Type
 }
+
 ///////// END of selector interfaces
 
 type SelectorInfo struct {
-	Criteria []Criterion  `json:"criteria"`
+	Criteria []Criterion `json:"criteria"`
 }
 
 // Instruction structs are defined here
@@ -332,8 +348,8 @@
 }
 
 type PushVlanInstruction struct {
-	Type string `json:"type"`
-	SubType string `json:"subtype"`
+	Type         string `json:"type"`
+	SubType      string `json:"subtype"`
 	EthernetType string `json:"ethernetType"`
 }
 
@@ -342,9 +358,9 @@
 }
 
 type VlanInstruction struct {
-	Type string `json:"type"`
+	Type    string `json:"type"`
 	SubType string `json:"subtype"`
-	VlanID int `json:"vlanId"`
+	VlanID  int    `json:"vlanId"`
 }
 
 func (i VlanInstruction) GetInstructionType() string {
@@ -352,7 +368,7 @@
 }
 
 type PopVlanInstruction struct {
-	Type string `json:"type"`
+	Type    string `json:"type"`
 	SubType string `json:"subtype"`
 }
 
@@ -361,7 +377,7 @@
 }
 
 type MeterInstruction struct {
-	Type string `json:"type"`
+	Type    string `json:"type"`
 	MeterID string `json:"meterId"`
 }
 
@@ -371,7 +387,7 @@
 
 type TreatmentInfo struct {
 	Instructions []Instruction `json:"instructions"`
-	Deferred []interface{} `json:"deferred"`
+	Deferred     []interface{} `json:"deferred"`
 }
 type Flow struct {
 	GroupID     int           `json:"groupId"`
@@ -397,7 +413,76 @@
 	Flows []Flow `json:"flows"`
 }
 
-func ConvertFlowToFlowEntry (subFlow *of.VoltSubFlow) FlowEntry {
+//Meter struct
+type Meters struct {
+	ID             string  `json:"id"`
+	Life           int     `json:"life"`
+	Packets        int     `json:"packets"`
+	Bytes          int     `json:"bytes"`
+	ReferenceCount int     `json:"referenceCount"`
+	Unit           string  `json:"unit"`
+	Burst          bool    `json:"burst"`
+	DeviceID       string  `json:"deviceId"`
+	AppID          string  `json:"appId"`
+	State          string  `json:"state"`
+	MeterBands     []Bands `json:"bands"`
+}
+
+type Bands struct {
+	Type      string `json:"type"`
+	Rate      int    `json:"rate"`
+	Packets   int    `json:"packets"`
+	Bytes     int    `json:"bytes"`
+	BurstSize int    `json:"burstSize"`
+	Prec      int    `json:"prec,omitempty"`
+}
+
+type GroupsInfo struct {
+	ID             int      `json:"id"`
+	State          string   `json:"state"`
+	Life           int      `json:"life"`
+	Packets        int      `json:"packets"`
+	Bytes          int      `json:"bytes"`
+	ReferenceCount int      `json:"referenceCount"`
+	Type           string   `json:"type"`
+	DeviceID       string   `json:"deviceId"`
+	AppID          string   `json:"appId"`
+	AppCookie      string   `json:"appCookie"`
+	Buckets        []Bucket `json:"buckets"`
+}
+
+type Bucket struct {
+	Type      string    `json:"type"`
+	Weight    int       `json:"weight"`
+	Packets   int       `json:"packets"`
+	Bytes     int       `json:"bytes"`
+	BucketID  int       `json:"bucketId"`
+	Treatment Treatment `json:"treatment"`
+}
+
+type Treatment struct {
+	Instructions []Instructions `json:"instructions"`
+	Deferred     []interface{}  `json:"deferred"`
+}
+
+type Instructions struct {
+	Type string `json:"type"`
+	Port string `json:"port"`
+}
+
+type MeterList struct {
+	Meters []Meters `json:"meters"`
+}
+
+type GroupList struct {
+	Groups []*GroupsInfo `json:"groups"`
+}
+
+type SubscribersList struct {
+	Subscribers []SubscriberInfo `json:"subscribers"`
+}
+
+func ConvertFlowToFlowEntry(subFlow *of.VoltSubFlow) FlowEntry {
 	var flowEntry FlowEntry
 	flowEntry.Flows = []Flow{}
 	flow := ConvertVoltSubFlowToOnosFlow(subFlow)
@@ -405,7 +490,7 @@
 	return flowEntry
 }
 
-func ConvertFlowsToFlowEntry (subFlows []*of.VoltSubFlow) FlowEntry {
+func ConvertFlowsToFlowEntry(subFlows []*of.VoltSubFlow) FlowEntry {
 	var flowEntry FlowEntry
 	flowEntry.Flows = []Flow{}
 	for _, subFlow := range subFlows {
@@ -424,81 +509,81 @@
 
 	// Fill Match criteria
 	if subFlow.InPort != 0 {
-		portSelector := PortSelector {
+		portSelector := PortSelector{
 			Type: IN_PORT,
 			Port: int(subFlow.InPort),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(portSelector))
 	}
 	if subFlow.MatchVlan != of.VlanNone {
-		vlanSelector := VlanSelector {
-			Type: VLAN_VID,
+		vlanSelector := VlanSelector{
+			Type:   VLAN_VID,
 			VlanID: int(subFlow.MatchVlan),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(vlanSelector))
 	}
 	if subFlow.SrcMacMatch {
-		ethSrcSelector := EthSrcSelector {
-			Type: ETH_SRC,
+		ethSrcSelector := EthSrcSelector{
+			Type:   ETH_SRC,
 			EthSrc: subFlow.SrcMacAddr.String(),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(ethSrcSelector))
 	}
 	if subFlow.DstMacMatch {
-		ethDstSelector := EthDstSelector {
-			Type: ETH_DST,
+		ethDstSelector := EthDstSelector{
+			Type:   ETH_DST,
 			DstSrc: subFlow.DstMacAddr.String(),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(ethDstSelector))
 	}
 	if subFlow.L3Protocol != of.EtherTypeAny {
-		ethTypeSelector := EthTypeSelector {
-			Type: ETH_TYPE,
-			EthType : strconv.FormatUint(uint64(subFlow.L3Protocol), 16) ,
+		ethTypeSelector := EthTypeSelector{
+			Type:    ETH_TYPE,
+			EthType: strconv.FormatUint(uint64(subFlow.L3Protocol), 16),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(ethTypeSelector))
 	}
 	if subFlow.L4Protocol != of.IPProtocolIgnore {
-		protocolSelector := ProtocolSelector {
-			Type: IP_PROTO,
-			Protocol : int(subFlow.L4Protocol),
+		protocolSelector := ProtocolSelector{
+			Type:     IP_PROTO,
+			Protocol: int(subFlow.L4Protocol),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(protocolSelector))
 	}
 	if subFlow.SrcPort != 0 {
-		udpPortSelector := UDPPortSelector {
-			Type: UDP_SRC,
-			UDPPort : int(subFlow.SrcPort) ,
+		udpPortSelector := UDPPortSelector{
+			Type:    UDP_SRC,
+			UDPPort: int(subFlow.SrcPort),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(udpPortSelector))
 	}
 	if subFlow.DstPort != 0 {
-		udpPortSelector := UDPPortSelector {
-			Type: UDP_DST,
-			UDPPort : int(subFlow.DstPort) ,
+		udpPortSelector := UDPPortSelector{
+			Type:    UDP_DST,
+			UDPPort: int(subFlow.DstPort),
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(udpPortSelector))
 	}
 	if subFlow.TableMetadata != 0 {
-		metaDataSelector := MetaDataSelector {
-			Type: METADATA,
-			Metadata : subFlow.TableMetadata,
+		metaDataSelector := MetaDataSelector{
+			Type:     METADATA,
+			Metadata: subFlow.TableMetadata,
 		}
 		flow.Selector.Criteria = append(flow.Selector.Criteria, Criterion(metaDataSelector))
 	}
 
 	// Fill actions
 	if subFlow.Output != 0 {
-		portInstruction := PortInstruction {
+		portInstruction := PortInstruction{
 			Type: OUTPUT,
 		}
 		switch subFlow.Output {
 		case of.OutputTypeToController:
 			portInstruction.Port = "CONTROLLER"
 		case of.OutputTypeToNetwork:
-			portInstruction.Port = strconv.FormatUint(uint64(subFlow.OutPort) , 10)
+			portInstruction.Port = strconv.FormatUint(uint64(subFlow.OutPort), 10)
 		case of.OutputTypeGoToTable:
-			portInstruction.Port = strconv.FormatUint(uint64(subFlow.GoToTableID) , 10)
+			portInstruction.Port = strconv.FormatUint(uint64(subFlow.GoToTableID), 10)
 		}
 		flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(portInstruction))
 	}
@@ -507,38 +592,38 @@
 			if vlan == of.VlanNone {
 				continue
 			}
-			pushVlanInstruction := PushVlanInstruction {
-				Type: L2MODIFICATION,
-				SubType: VLAN_PUSH,
-				EthernetType: "0x8100" ,
+			pushVlanInstruction := PushVlanInstruction{
+				Type:         L2MODIFICATION,
+				SubType:      VLAN_PUSH,
+				EthernetType: "0x8100",
 			}
 			flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(pushVlanInstruction))
-			vlanInstruction := VlanInstruction {
-				Type: L2MODIFICATION,
+			vlanInstruction := VlanInstruction{
+				Type:    L2MODIFICATION,
 				SubType: VLAN_ID,
-				VlanID: int(vlan),
+				VlanID:  int(vlan),
 			}
 			flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(vlanInstruction))
 		}
 	}
 	if subFlow.SetVlan != of.VlanNone {
-		vlanInstruction := VlanInstruction {
-			Type: L2MODIFICATION,
+		vlanInstruction := VlanInstruction{
+			Type:    L2MODIFICATION,
 			SubType: VLAN_SET,
-			VlanID: int(subFlow.SetVlan) ,
+			VlanID:  int(subFlow.SetVlan),
 		}
 		flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(vlanInstruction))
 	}
 	if subFlow.RemoveVlan != 0 {
-		popVlanInstruction := PopVlanInstruction {
-			Type: L2MODIFICATION,
+		popVlanInstruction := PopVlanInstruction{
+			Type:    L2MODIFICATION,
 			SubType: VLAN_POP,
 		}
 		flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(popVlanInstruction))
 	}
 	if subFlow.MeterID != 0 {
-		meterInstruction := MeterInstruction {
-			Type: METER,
+		meterInstruction := MeterInstruction{
+			Type:    METER,
 			MeterID: strconv.FormatUint(uint64(subFlow.MeterID), 10),
 		}
 		flow.Treatment.Instructions = append(flow.Treatment.Instructions, Instruction(meterInstruction))
@@ -546,36 +631,36 @@
 	return flow
 }
 
-func convertServiceToSubscriberInfo(svcs []*app.VoltService) []*SubscriberInfo {
-        var subs []*SubscriberInfo
-        for _, vs := range svcs {
+func convertServiceToSubscriberInfo(svcs []*app.VoltService) []SubscriberInfo {
+	subs := []SubscriberInfo{}
+	for _, vs := range svcs {
 		pbit := vs.GetServicePbit()
-                sub := &SubscriberInfo{
-                        Location : vs.Device,
-                        TagInfo : UniTagInformation {
-                                UniTagMatch: int(vs.UniVlan),
-                                PonCTag: int(vs.CVlan),
-                                PonSTag: int(vs.SVlan),
-                                UsPonCTagPriority: pbit,
-                                UsPonSTagPriority: pbit,
-                                DsPonCTagPriority: pbit,
-                                DsPonSTagPriority: pbit,
-                                TechnologyProfileID: int(vs.TechProfileID),
-                                UpstreamBandwidthProfile: vs.UsMeterProfile,
-                                DownstreamBandwidthProfile: vs.DsMeterProfile,
-                                UpstreamOltBandwidthProfile: vs.UsMeterProfile,
-                                DownstreamOltBandwidthProfile: vs.DsMeterProfile,
-                                ServiceName: vs.Name,
-                                EnableMacLearning: vs.MacLearning == app.Learn,
-                                ConfiguredMacAddress: vs.MacAddr.String(),
-                                IsDhcpRequired: vs.MacLearning == app.Learn,
-                                IsIgmpRequired: vs.IgmpEnabled,
-                                IsPppoeRequired: false,
-                        },
-                }
-                subs = append(subs, sub)
-        }
-        return subs
+		sub := SubscriberInfo{
+			Location: vs.Device,
+			TagInfo: UniTagInformation{
+				UniTagMatch:                   int(vs.UniVlan),
+				PonCTag:                       int(vs.CVlan),
+				PonSTag:                       int(vs.SVlan),
+				UsPonCTagPriority:             pbit,
+				UsPonSTagPriority:             pbit,
+				DsPonCTagPriority:             pbit,
+				DsPonSTagPriority:             pbit,
+				TechnologyProfileID:           int(vs.TechProfileID),
+				UpstreamBandwidthProfile:      vs.UsMeterProfile,
+				DownstreamBandwidthProfile:    vs.DsMeterProfile,
+				UpstreamOltBandwidthProfile:   vs.UsMeterProfile,
+				DownstreamOltBandwidthProfile: vs.DsMeterProfile,
+				ServiceName:                   vs.Name,
+				EnableMacLearning:             vs.MacLearning == app.Learn,
+				ConfiguredMacAddress:          vs.MacAddr.String(),
+				IsDhcpRequired:                vs.MacLearning == app.Learn,
+				IsIgmpRequired:                vs.IgmpEnabled,
+				IsPppoeRequired:               false,
+			},
+		}
+		subs = append(subs, sub)
+	}
+	return subs
 }
 
 type DeviceEntry struct {
@@ -583,18 +668,18 @@
 }
 
 type Device struct {
-	ID                      string `json:"id"`
-	Type                    string `json:"type"`
-	Available               bool   `json:"available"`
-	Role                    string `json:"role"`
-	Mfr                     string `json:"mfr"`
-	Hw                      string `json:"hw"`
-	Sw                      string `json:"sw"`
-	Serial                  string `json:"serial"`
-	Driver                  string `json:"driver"`
-	ChassisID               string `json:"chassisId"`
-	LastUpdate              string `json:"lastUpdate"`
-	HumanReadableLastUpdate string `json:"humanReadableLastUpdate"`
+	ID                      string            `json:"id"`
+	Type                    string            `json:"type"`
+	Available               bool              `json:"available"`
+	Role                    string            `json:"role"`
+	Mfr                     string            `json:"mfr"`
+	Hw                      string            `json:"hw"`
+	Sw                      string            `json:"sw"`
+	Serial                  string            `json:"serial"`
+	Driver                  string            `json:"driver"`
+	ChassisID               string            `json:"chassisId"`
+	LastUpdate              string            `json:"lastUpdate"`
+	HumanReadableLastUpdate string            `json:"humanReadableLastUpdate"`
 	Annotations             DeviceAnnotations `json:"annotations"`
 }
 type DeviceAnnotations struct {
@@ -618,23 +703,24 @@
 		device.Available = false
 	}
 	device.Serial = d.SerialNum
-	device.Mfr    = d.MfrDesc
-	device.Hw     = d.HwDesc
-	device.Sw     = d.SwDesc
+	device.Mfr = d.MfrDesc
+	device.Hw = d.HwDesc
+	device.Sw = d.SwDesc
 	device.LastUpdate = d.TimeStamp.String()
 	device.HumanReadableLastUpdate = d.TimeStamp.String()
 	return device
 }
+
 type PortEntry struct {
 	Ports []Port `json:"ports"`
 }
 
 type Port struct {
-	Element     string `json:"element"`
-	Port        string `json:"port"`
-	IsEnabled   bool   `json:"isEnabled"`
-	Type        string `json:"type"`
-	PortSpeed   int    `json:"portSpeed"`
+	Element     string          `json:"element"`
+	Port        string          `json:"port"`
+	IsEnabled   bool            `json:"isEnabled"`
+	Type        string          `json:"type"`
+	PortSpeed   int             `json:"portSpeed"`
 	Annotations PortAnnotations `json:"annotations"`
 }
 type PortAnnotations struct {
@@ -672,3 +758,69 @@
 	}
 	return port
 }
+func (gh *GroupsHandle) convertGroupsToOnosGroup(groupsInfo *of.Group) *GroupsInfo {
+	logger.Info(ctx, "Entering into convertGroupsToOnosGroup")
+	var groups *GroupsInfo
+	var bucket []Bucket
+	Instruction := []Instructions{}
+	if groupsInfo != nil {
+		for _, buckets := range groupsInfo.Buckets {
+			inst := Instructions{
+				Type: ALL,
+				Port: fmt.Sprint(buckets),
+			}
+			Instruction = append(Instruction, inst)
+			trtmt := Treatment{
+				Instructions: Instruction,
+			}
+			bkt := Bucket{
+				Type:      ALL,
+				Treatment: trtmt,
+			}
+			bucket = append(bucket, bkt)
+		}
+		if groupsInfo.State == of.GroupOperSuccess {
+			groups.State = ADDED
+		} else if groupsInfo.State == of.GroupOperFailure {
+			groups.State = FAILED
+		} else if groupsInfo.State == of.GroupOperPending {
+			groups.State = PENDING
+		}
+		groups = &GroupsInfo{
+			DeviceID: groupsInfo.Device,
+			ID:       int(groupsInfo.GroupID),
+			State:    groups.State,
+			Type:     ALL,
+			Buckets:  bucket,
+		}
+	}
+	return groups
+}
+
+func (mh *MetersHandle) MeterObjectMapping(meterInfo *of.Meter, deviceId string) Meters {
+	var meter Meters
+	var bd []Bands
+	for _, band := range meterInfo.Bands {
+		bnd := Bands{
+			Type:      fmt.Sprint(band.Type),
+			Rate:      int(band.Rate),
+			BurstSize: int(band.BurstSize),
+		}
+		bd = append(bd, bnd)
+	}
+	if meterInfo.State == of.MeterOperSuccess {
+		meter.State = ADDED
+	} else if meterInfo.State == of.MeterOperFailure {
+		meter.State = FAILED
+	} else if meterInfo.State == of.MeterOperPending {
+		meter.State = PENDING
+	}
+	meter = Meters{
+		ID:         fmt.Sprint(meterInfo.ID),
+		State:      meter.State,
+		DeviceID:   deviceId,
+		MeterBands: bd,
+	}
+	return meter
+
+}
diff --git a/voltha-go-controller/onos_nbi/oltapprestadapter.go b/voltha-go-controller/onos_nbi/oltapprestadapter.go
index c9821c6..986e487 100644
--- a/voltha-go-controller/onos_nbi/oltapprestadapter.go
+++ b/voltha-go-controller/onos_nbi/oltapprestadapter.go
@@ -11,21 +11,22 @@
 * 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 onos_nbi
 
 import (
-        "bytes"
-        "context"
-        "encoding/json"
-        "net/http"
+	"bytes"
+	"context"
+	"encoding/json"
+	"net/http"
 	"strconv"
 
-	"github.com/gorilla/mux"
+	app "voltha-go-controller/internal/pkg/application"
 	"voltha-go-controller/internal/pkg/of"
-        app "voltha-go-controller/internal/pkg/application"
-        "voltha-go-controller/log"
+	"voltha-go-controller/log"
+
+	"github.com/gorilla/mux"
 )
 
 const (
@@ -35,74 +36,75 @@
 	CTAG     string = "cTag"
 	TPID     string = "tpId"
 )
+
 // FlowHandle struct to handle flow related REST calls
 type SubscriberInfo struct {
-	Location string             `json:"location"`
-	TagInfo  UniTagInformation  `json:"tagInfo"`
+	Location string            `json:"location"`
+	TagInfo  UniTagInformation `json:"tagInfo"`
 }
 
 //UniTagInformation - Service information
 type UniTagInformation struct {
-        UniTagMatch                   int    `json:"uniTagMatch"`
-        PonCTag                       int    `json:"ponCTag"`
-        PonSTag                       int    `json:"ponSTag"`
-        UsPonCTagPriority             int    `json:"usPonCTagPriority"`
-        UsPonSTagPriority             int    `json:"usPonSTagPriority"`
-        DsPonCTagPriority             int    `json:"dsPonCTagPriority"`
-        DsPonSTagPriority             int    `json:"dsPonSTagPriority"`
-        TechnologyProfileID           int    `json:"technologyProfileId"`
-        UpstreamBandwidthProfile      string `json:"upstreamBandwidthProfile"`
-        DownstreamBandwidthProfile    string `json:"downstreamBandwidthProfile"`
-        UpstreamOltBandwidthProfile   string `json:"upstreamOltBandwidthProfile"`
-        DownstreamOltBandwidthProfile string `json:"downstreamOltBandwidthProfile"`
-        ServiceName                   string `json:"serviceName"`
-        EnableMacLearning             bool   `json:"enableMacLearning"`
-        ConfiguredMacAddress          string `json:"configuredMacAddress"`
-        IsDhcpRequired                bool   `json:"isDhcpRequired"`
-        IsIgmpRequired                bool   `json:"isIgmpRequired"`
-        IsPppoeRequired               bool   `json:"isPppoeRequired"`
+	UniTagMatch                   int    `json:"uniTagMatch"`
+	PonCTag                       int    `json:"ponCTag"`
+	PonSTag                       int    `json:"ponSTag"`
+	UsPonCTagPriority             int    `json:"usPonCTagPriority"`
+	UsPonSTagPriority             int    `json:"usPonSTagPriority"`
+	DsPonCTagPriority             int    `json:"dsPonCTagPriority"`
+	DsPonSTagPriority             int    `json:"dsPonSTagPriority"`
+	TechnologyProfileID           int    `json:"technologyProfileId"`
+	UpstreamBandwidthProfile      string `json:"upstreamBandwidthProfile"`
+	DownstreamBandwidthProfile    string `json:"downstreamBandwidthProfile"`
+	UpstreamOltBandwidthProfile   string `json:"upstreamOltBandwidthProfile"`
+	DownstreamOltBandwidthProfile string `json:"downstreamOltBandwidthProfile"`
+	ServiceName                   string `json:"serviceName"`
+	EnableMacLearning             bool   `json:"enableMacLearning"`
+	ConfiguredMacAddress          string `json:"configuredMacAddress"`
+	IsDhcpRequired                bool   `json:"isDhcpRequired"`
+	IsIgmpRequired                bool   `json:"isIgmpRequired"`
+	IsPppoeRequired               bool   `json:"isPppoeRequired"`
 }
 
 type ServiceAdapter struct {
 }
 
 func (sa *ServiceAdapter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-        logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
-        switch r.Method {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	switch r.Method {
 	case "POST":
 		sa.ActivateService(context.Background(), w, r)
 	case "DELETE":
 		sa.DeactivateService(context.Background(), w, r)
-        case "GET":
+	case "GET":
 		sa.GetProgrammedSubscribers(context.Background(), w, r)
-        default:
-                logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
-        }
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
 }
 
 func (sa *ServiceAdapter) ServeHTTPWithPortName(w http.ResponseWriter, r *http.Request) {
-        logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
-        switch r.Method {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	switch r.Method {
 	case "POST":
 		sa.ActivateServiceWithPortName(context.Background(), w, r)
 	case "DELETE":
 		sa.DeactivateServiceWithPortName(context.Background(), w, r)
-        default:
-                logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
-        }
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
 }
 
 func (sa *ServiceAdapter) ActivateService(cntx context.Context, w http.ResponseWriter, r *http.Request) {
-        vars := mux.Vars(r)
-        deviceID := vars[DEVICE]
-        portNo := vars["port"]
+	vars := mux.Vars(r)
+	deviceID := vars[DEVICE]
+	portNo := vars["port"]
 
-        // Get the payload to process the request
-        d := new(bytes.Buffer)
-        if _, err := d.ReadFrom(r.Body);  err != nil {
-                logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
-                return
-        }
+	// Get the payload to process the request
+	d := new(bytes.Buffer)
+	if _, err := d.ReadFrom(r.Body); err != nil {
+		logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
+		return
+	}
 
 	if len(deviceID) > 0 && len(portNo) > 0 {
 		app.GetApplication().ActivateService(cntx, deviceID, portNo, of.VlanNone, of.VlanNone, 0)
@@ -110,16 +112,16 @@
 }
 
 func (sa *ServiceAdapter) DeactivateService(cntx context.Context, w http.ResponseWriter, r *http.Request) {
-        vars := mux.Vars(r)
-        deviceID := vars[DEVICE]
-        portNo := vars["port"]
+	vars := mux.Vars(r)
+	deviceID := vars[DEVICE]
+	portNo := vars["port"]
 
-        // Get the payload to process the request
-        d := new(bytes.Buffer)
-        if _, err := d.ReadFrom(r.Body);  err != nil {
-                logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
-                return
-        }
+	// Get the payload to process the request
+	d := new(bytes.Buffer)
+	if _, err := d.ReadFrom(r.Body); err != nil {
+		logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
+		return
+	}
 
 	if len(deviceID) > 0 && len(portNo) > 0 {
 		app.GetApplication().DeactivateService(cntx, deviceID, portNo, of.VlanNone, of.VlanNone, 0)
@@ -127,11 +129,11 @@
 }
 
 func (sa *ServiceAdapter) ActivateServiceWithPortName(cntx context.Context, w http.ResponseWriter, r *http.Request) {
-        vars := mux.Vars(r)
-        portNo := vars[PORTNAME]
-        sTag := vars[STAG]
-        cTag := vars[CTAG]
-        tpID := vars[TPID]
+	vars := mux.Vars(r)
+	portNo := vars[PORTNAME]
+	sTag := vars[STAG]
+	cTag := vars[CTAG]
+	tpID := vars[TPID]
 	sVlan := of.VlanNone
 	cVlan := of.VlanNone
 	techProfile := uint16(0)
@@ -167,11 +169,11 @@
 }
 
 func (sa *ServiceAdapter) DeactivateServiceWithPortName(cntx context.Context, w http.ResponseWriter, r *http.Request) {
-        vars := mux.Vars(r)
-        portNo := vars[PORTNAME]
-        sTag := vars[STAG]
-        cTag := vars[CTAG]
-        tpID := vars[TPID]
+	vars := mux.Vars(r)
+	portNo := vars[PORTNAME]
+	sTag := vars[STAG]
+	cTag := vars[CTAG]
+	tpID := vars[TPID]
 	sVlan := of.VlanNone
 	cVlan := of.VlanNone
 	techProfile := uint16(0)
@@ -201,12 +203,12 @@
 		techProfile = uint16(tp)
 	}
 
-        // Get the payload to process the request
-        d := new(bytes.Buffer)
-        if _, err := d.ReadFrom(r.Body);  err != nil {
-                logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
-                return
-        }
+	// Get the payload to process the request
+	d := new(bytes.Buffer)
+	if _, err := d.ReadFrom(r.Body); err != nil {
+		logger.Warnw(ctx, "Error reading buffer", log.Fields{"Reason": err.Error()})
+		return
+	}
 
 	if len(portNo) > 0 {
 		app.GetApplication().DeactivateService(cntx, app.DeviceAny, portNo, sVlan, cVlan, techProfile)
@@ -215,15 +217,17 @@
 
 func (sa *ServiceAdapter) GetProgrammedSubscribers(cntx context.Context, w http.ResponseWriter, r *http.Request) {
 	vars := mux.Vars(r)
-        deviceID := vars[DEVICE]
-        portNo := vars["port"]
-
+	deviceID := vars[DEVICE]
+	portNo := vars["port"]
+	subsbr := SubscribersList{}
+	subsbr.Subscribers = []SubscriberInfo{}
 	svcs, err := app.GetApplication().GetProgrammedSubscribers(cntx, deviceID, portNo)
 	if err != nil {
 		logger.Errorw(ctx, "Failed to get subscribers", log.Fields{"Reason": err.Error()})
 	}
 	subs := convertServiceToSubscriberInfo(svcs)
-	subsJSON, err := json.Marshal(subs)
+	subsbr.Subscribers = subs
+	subsJSON, err := json.Marshal(subsbr)
 	if err != nil {
 		logger.Errorw(ctx, "Error occurred while marshaling subscriber response", log.Fields{"Error": err})
 		w.WriteHeader(http.StatusInternalServerError)
diff --git a/voltha-go-controller/onos_nbi/portIgnored.go b/voltha-go-controller/onos_nbi/portIgnored.go
new file mode 100644
index 0000000..499e97a
--- /dev/null
+++ b/voltha-go-controller/onos_nbi/portIgnored.go
@@ -0,0 +1,73 @@
+/*
+* 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 onos_nbi
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	app "voltha-go-controller/internal/pkg/application"
+	"voltha-go-controller/log"
+)
+
+type PortIgnoredHandle struct {
+}
+
+func init() {
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.AddPackageWithDefaultParam()
+	if err != nil {
+		panic(err)
+	}
+}
+
+func (pih *PortIgnoredHandle) PortsIgnoredServeHTTP(w http.ResponseWriter, r *http.Request) {
+	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
+	switch r.Method {
+	case "GET":
+		logger.Info(ctx, "calling GetIgnoredPortsInfo handler")
+		pih.GetIgnoredPortsInfo(context.Background(), w, r)
+
+	default:
+		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
+	}
+}
+
+func (pih *PortIgnoredHandle) GetIgnoredPortsInfo(cntx context.Context, w http.ResponseWriter, r *http.Request) {
+
+	PortIgnoredInfo, err := app.GetApplication().GetIgnoredPorts()
+	if err != nil {
+		logger.Errorw(ctx, "Failed to get ignored port info", log.Fields{"Reason": err.Error()})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	PortIgnoredRespJSON, err := json.Marshal(PortIgnoredInfo)
+	if err != nil {
+		logger.Errorw(ctx, "Error occurred while marshaling ignored port response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Add("Content-Type", "application/json")
+	_, err = w.Write(PortIgnoredRespJSON)
+	if err != nil {
+		logger.Errorw(ctx, "error in sending ignored port response", log.Fields{"Error": err})
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+
+}