[CORD-1880] Improve DHCP relay CLI

Change-Id: I38b8b0fdfefa8831c70c74708549fd6805f624bc
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
index 4d5d53d..0c031fd 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
@@ -17,7 +17,7 @@
 
 package org.onosproject.dhcprelay;
 
-import com.google.common.base.MoreObjects;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -39,6 +39,7 @@
 import org.onlab.packet.dhcp.DhcpOption;
 import org.onlab.packet.dhcp.DhcpRelayAgentOption;
 import org.onosproject.dhcprelay.api.DhcpHandler;
+import org.onosproject.dhcprelay.api.DhcpServerInfo;
 import org.onosproject.dhcprelay.config.DhcpServerConfig;
 import org.onosproject.dhcprelay.store.DhcpRecord;
 import org.onosproject.dhcprelay.store.DhcpRelayStore;
@@ -114,24 +115,8 @@
     protected HostProviderService providerService;
     private InternalHostListener hostListener = new InternalHostListener();
 
-    private Ip4Address dhcpServerIp = null;
-    // dhcp server may be connected directly to the SDN network or
-    // via an external gateway. When connected directly, the dhcpConnectPoint, dhcpConnectMac,
-    // and dhcpConnectVlan refer to the server. When connected via the gateway, they refer
-    // to the gateway.
-    private ConnectPoint dhcpServerConnectPoint = null;
-    private MacAddress dhcpConnectMac = null;
-    private VlanId dhcpConnectVlan = null;
-    private Ip4Address dhcpGatewayIp = null;
-    private Ip4Address relayAgentIp = null;
-
-    // Indirect case DHCP server
-    private Ip4Address indirectDhcpServerIp = null;
-    private ConnectPoint indirectDhcpServerConnectPoint = null;
-    private MacAddress indirectDhcpConnectMac = null;
-    private VlanId indirectDhcpConnectVlan = null;
-    private Ip4Address indirectDhcpGatewayIp = null;
-    private Ip4Address indirectRelayAgentIp = null;
+    private List<DhcpServerInfo> defaultServerInfoList = Lists.newArrayList();
+    private List<DhcpServerInfo> indirectServerInfoList = Lists.newArrayList();
 
     @Activate
     protected void activate() {
@@ -143,81 +128,42 @@
     protected void deactivate() {
         providerRegistry.unregister(this);
         hostService.removeListener(hostListener);
-        this.dhcpConnectMac = null;
-        this.dhcpConnectVlan = null;
-
-        if (dhcpGatewayIp != null) {
-            hostService.stopMonitoringIp(dhcpGatewayIp);
-        }
-        if (dhcpServerIp != null) {
-            hostService.stopMonitoringIp(dhcpServerIp);
-        }
-
-        if (indirectDhcpGatewayIp != null) {
-            hostService.stopMonitoringIp(indirectDhcpGatewayIp);
-        }
-        if (indirectDhcpServerIp != null) {
-            hostService.stopMonitoringIp(indirectDhcpServerIp);
-        }
-
-        hostService.removeListener(hostListener);
-        this.dhcpConnectMac = null;
-        this.dhcpConnectVlan = null;
-        this.indirectDhcpConnectMac = null;
-        this.indirectDhcpConnectVlan = null;
+        defaultServerInfoList.forEach(this::stopMonitoringIps);
+        defaultServerInfoList.clear();
+        indirectServerInfoList.forEach(this::stopMonitoringIps);
+        indirectServerInfoList.clear();
     }
 
-    @Override
-    public void setDhcpServerIp(IpAddress dhcpServerIp) {
-        checkNotNull(dhcpServerIp, "DHCP server IP can't be null");
-        checkState(dhcpServerIp.isIp4(), "Invalid server IP for DHCPv4 relay handler");
-        this.dhcpServerIp = dhcpServerIp.getIp4Address();
-    }
-
-    @Override
-    public void setDhcpServerConnectPoint(ConnectPoint dhcpServerConnectPoint) {
-        checkNotNull(dhcpServerConnectPoint, "Server connect point can't null");
-        this.dhcpServerConnectPoint = dhcpServerConnectPoint;
-    }
-
-    @Override
-    public void setDhcpConnectMac(MacAddress dhcpConnectMac) {
-        this.dhcpConnectMac = dhcpConnectMac;
-    }
-
-    @Override
-    public void setDhcpConnectVlan(VlanId dhcpConnectVlan) {
-        this.dhcpConnectVlan = dhcpConnectVlan;
-    }
-
-    @Override
-    public void setDhcpGatewayIp(IpAddress dhcpGatewayIp) {
-        if (dhcpGatewayIp != null) {
-            checkState(dhcpGatewayIp.isIp4(), "Invalid gateway IP for DHCPv4 relay handler");
-            this.dhcpGatewayIp = dhcpGatewayIp.getIp4Address();
-        } else {
-            // removes gateway config
-            this.dhcpGatewayIp = null;
-        }
-    }
-
-    @Override
-    public Optional<IpAddress> getDhcpServerIp() {
-        return Optional.ofNullable(dhcpServerIp);
-    }
-
-    @Override
-    public Optional<IpAddress> getDhcpGatewayIp() {
-        return Optional.ofNullable(dhcpGatewayIp);
-    }
-
-    @Override
-    public Optional<MacAddress> getDhcpConnectMac() {
-        return Optional.ofNullable(dhcpConnectMac);
+    private void stopMonitoringIps(DhcpServerInfo serverInfo) {
+        serverInfo.getDhcpGatewayIp4().ifPresent(gatewayIp -> {
+            hostService.stopMonitoringIp(gatewayIp);
+        });
+        serverInfo.getDhcpServerIp4().ifPresent(serverIp -> {
+            hostService.stopMonitoringIp(serverIp);
+        });
     }
 
     @Override
     public void setDefaultDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+        setDhcpServerConfigs(configs, defaultServerInfoList);
+    }
+
+    @Override
+    public void setIndirectDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+        setDhcpServerConfigs(configs, indirectServerInfoList);
+    }
+
+    @Override
+    public List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
+        return defaultServerInfoList;
+    }
+
+    @Override
+    public List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
+        return indirectServerInfoList;
+    }
+
+    public void setDhcpServerConfigs(Collection<DhcpServerConfig> configs, List<DhcpServerInfo> serverInfoList) {
         if (configs.size() == 0) {
             // no config to update
             return;
@@ -226,105 +172,62 @@
         // TODO: currently we pick up first DHCP server config.
         // Will use other server configs in the future for HA.
         DhcpServerConfig serverConfig = configs.iterator().next();
-        if (!serverConfig.getDhcpServerConnectPoint().isPresent()) {
-            log.warn("Connect point from server config not exists");
-            return;
-        }
+
         if (!serverConfig.getDhcpServerIp4().isPresent()) {
-            log.warn("IP from DHCP server config not exists");
-            return;
-        }
-        Ip4Address oldServerIp = this.dhcpServerIp;
-        Ip4Address oldGatewayIp = this.dhcpGatewayIp;
-
-        // stop monitoring gateway or server
-        if (oldGatewayIp != null) {
-            hostService.stopMonitoringIp(oldGatewayIp);
-        } else if (oldServerIp != null) {
-            hostService.stopMonitoringIp(oldServerIp);
-        }
-
-        this.dhcpServerConnectPoint = serverConfig.getDhcpServerConnectPoint().get();
-        this.dhcpServerIp = serverConfig.getDhcpServerIp4().get();
-        this.dhcpGatewayIp = serverConfig.getDhcpGatewayIp4().orElse(null);
-
-        // reset server mac and vlan
-        this.dhcpConnectMac = null;
-        this.dhcpConnectVlan = null;
-
-        log.info("DHCP server connect point: " + this.dhcpServerConnectPoint);
-        log.info("DHCP server IP: " + this.dhcpServerIp);
-
-        IpAddress ipToProbe = MoreObjects.firstNonNull(this.dhcpGatewayIp, this.dhcpServerIp);
-        String hostToProbe = this.dhcpGatewayIp != null ? "gateway" : "DHCP server";
-
-        if (ipToProbe == null) {
-            log.warn("Server IP not set, can't probe it");
+            // not a DHCPv4 config
             return;
         }
 
-        log.info("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
-        hostService.startMonitoringIp(ipToProbe);
+        if (!serverInfoList.isEmpty()) {
+            // remove old server info
+            DhcpServerInfo oldServerInfo = serverInfoList.remove(0);
 
-        Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
-        if (!hosts.isEmpty()) {
-            Host host = hosts.iterator().next();
-            this.dhcpConnectVlan = host.vlan();
-            this.dhcpConnectMac = host.mac();
+            // stop monitoring gateway or server
+            oldServerInfo.getDhcpGatewayIp4().ifPresent(gatewayIp -> {
+                hostService.stopMonitoringIp(gatewayIp);
+            });
+            oldServerInfo.getDhcpServerIp4().ifPresent(serverIp -> {
+                hostService.stopMonitoringIp(serverIp);
+            });
         }
 
-        this.relayAgentIp = serverConfig.getRelayAgentIp4().orElse(null);
-    }
-
-    @Override
-    public void setIndirectDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
-        if (configs.size() == 0) {
-            // no config to update
-            return;
-        }
-
-        // TODO: currently we pick up first indirect DHCP server config.
-        // Will use other server configs in the future for HA.
-        DhcpServerConfig serverConfig = configs.iterator().next();
-        checkState(serverConfig.getDhcpServerConnectPoint().isPresent(),
+        // Create new server info according to the config
+        DhcpServerInfo newServerInfo = new DhcpServerInfo(serverConfig,
+                                                          DhcpServerInfo.Version.DHCP_V4);
+        checkState(newServerInfo.getDhcpServerConnectPoint().isPresent(),
                    "Connect point not exists");
-        checkState(serverConfig.getDhcpServerIp4().isPresent(),
+        checkState(newServerInfo.getDhcpServerIp4().isPresent(),
                    "IP of DHCP server not exists");
-        Ip4Address oldServerIp = this.indirectDhcpServerIp;
-        Ip4Address oldGatewayIp = this.indirectDhcpGatewayIp;
 
-        // stop monitoring gateway or server
-        if (oldGatewayIp != null) {
-            hostService.stopMonitoringIp(oldGatewayIp);
-        } else if (oldServerIp != null) {
-            hostService.stopMonitoringIp(oldServerIp);
+        log.debug("DHCP server connect point: {}", newServerInfo.getDhcpServerConnectPoint().orElse(null));
+        log.debug("DHCP server IP: {}", newServerInfo.getDhcpServerIp4().orElse(null));
+
+        IpAddress ipToProbe;
+        if (newServerInfo.getDhcpGatewayIp4().isPresent()) {
+            ipToProbe = newServerInfo.getDhcpGatewayIp4().get();
+        } else {
+            ipToProbe = newServerInfo.getDhcpServerIp4().orElse(null);
         }
+        String hostToProbe = newServerInfo.getDhcpGatewayIp4()
+                .map(ip -> "gateway").orElse("server");
 
-        this.indirectDhcpServerConnectPoint = serverConfig.getDhcpServerConnectPoint().get();
-        this.indirectDhcpServerIp = serverConfig.getDhcpServerIp4().get();
-        this.indirectDhcpGatewayIp = serverConfig.getDhcpGatewayIp4().orElse(null);
-
-        // reset server mac and vlan
-        this.indirectDhcpConnectMac = null;
-        this.indirectDhcpConnectVlan = null;
-
-        log.info("Indirect DHCP server connect point: " + this.indirectDhcpServerConnectPoint);
-        log.info("Indirect DHCP server IP: " + this.indirectDhcpServerIp);
-
-        IpAddress ipToProbe = MoreObjects.firstNonNull(this.indirectDhcpGatewayIp, this.indirectDhcpServerIp);
-        String hostToProbe = this.indirectDhcpGatewayIp != null ? "gateway" : "DHCP server";
-
-        log.info("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
+        log.debug("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
         hostService.startMonitoringIp(ipToProbe);
 
         Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
         if (!hosts.isEmpty()) {
             Host host = hosts.iterator().next();
-            this.indirectDhcpConnectVlan = host.vlan();
-            this.indirectDhcpConnectMac = host.mac();
+            newServerInfo.setDhcpConnectVlan(host.vlan());
+            newServerInfo.setDhcpConnectMac(host.mac());
         }
+        // Add new server info
+        serverInfoList.add(0, newServerInfo);
 
-        this.indirectRelayAgentIp = serverConfig.getRelayAgentIp4().orElse(null);
+        // Remove duplicated server info
+        Set<DhcpServerInfo> nonDupServerInfoList = Sets.newLinkedHashSet();
+        nonDupServerInfoList.addAll(serverInfoList);
+        serverInfoList.clear();
+        serverInfoList.addAll(nonDupServerInfoList);
     }
 
     @Override
@@ -333,7 +236,7 @@
         checkState(payload instanceof DHCP, "Payload is not a DHCP");
         DHCP dhcpPayload = (DHCP) payload;
         if (!configured()) {
-            log.warn("Missing DHCP relay server config. Abort packet processing");
+            log.warn("Missing default DHCP relay server config. Abort packet processing");
             return;
         }
 
@@ -399,7 +302,7 @@
      * @return true if all information we need have been initialized
      */
     private boolean configured() {
-        return dhcpServerConnectPoint != null && dhcpServerIp != null;
+        return !defaultServerInfoList.isEmpty();
     }
 
     /**
@@ -424,15 +327,8 @@
      *
      * @return the Interface facing to the server; null if not found
      */
-    private Interface getServerInterface() {
-        if (dhcpServerConnectPoint == null || dhcpConnectVlan == null) {
-            return null;
-        }
-        return interfaceService.getInterfacesByPort(dhcpServerConnectPoint)
-                .stream()
-                .filter(iface -> interfaceContainsVlan(iface, dhcpConnectVlan))
-                .findFirst()
-                .orElse(null);
+    private Interface getDefaultServerInterface() {
+        return getServerInterface(defaultServerInfoList);
     }
 
     /**
@@ -442,12 +338,19 @@
      * @return the Interface facing to the server; null if not found
      */
     private Interface getIndirectServerInterface() {
-        if (indirectDhcpServerConnectPoint == null || indirectDhcpConnectVlan == null) {
-            return getServerInterface();
+        return getServerInterface(indirectServerInfoList);
+    }
+
+    private Interface getServerInterface(List<DhcpServerInfo> serverInfos) {
+        DhcpServerInfo serverInfo = serverInfos.get(0);
+        ConnectPoint dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+        VlanId dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+        if (dhcpServerConnectPoint == null || dhcpConnectVlan == null) {
+            return null;
         }
-        return interfaceService.getInterfacesByPort(indirectDhcpServerConnectPoint)
+        return interfaceService.getInterfacesByPort(dhcpServerConnectPoint)
                 .stream()
-                .filter(iface -> interfaceContainsVlan(iface, indirectDhcpConnectVlan))
+                .filter(iface -> interfaceContainsVlan(iface, dhcpConnectVlan))
                 .findFirst()
                 .orElse(null);
     }
@@ -484,6 +387,34 @@
         UDP udpPacket = (UDP) ipv4Packet.getPayload();
         DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
 
+
+        VlanId dhcpConnectVlan = null;
+        MacAddress dhcpConnectMac = null;
+        Ip4Address dhcpServerIp = null;
+        Ip4Address relayAgentIp = null;
+
+        VlanId indirectDhcpConnectVlan = null;
+        MacAddress indirectDhcpConnectMac = null;
+        Ip4Address indirectDhcpServerIp = null;
+        Ip4Address indirectRelayAgentIp = null;
+
+        if (!defaultServerInfoList.isEmpty()) {
+            DhcpServerInfo serverInfo = defaultServerInfoList.get(0);
+            dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+            dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+            relayAgentIp = serverInfo.getRelayAgentIp4().orElse(null);
+        }
+
+        if (!indirectServerInfoList.isEmpty()) {
+            DhcpServerInfo indirectServerInfo = indirectServerInfoList.get(0);
+            indirectDhcpConnectVlan = indirectServerInfo.getDhcpConnectVlan().orElse(null);
+            indirectDhcpConnectMac = indirectServerInfo.getDhcpConnectMac().orElse(null);
+            indirectDhcpServerIp = indirectServerInfo.getDhcpServerIp4().orElse(null);
+            indirectRelayAgentIp = indirectServerInfo.getRelayAgentIp4().orElse(null);
+        }
+
+
         Ip4Address clientInterfaceIp =
                 interfaceService.getInterfacesByPort(context.inPacket().receivedFrom())
                         .stream()
@@ -500,7 +431,7 @@
             return null;
         }
         boolean isDirectlyConnected = directlyConnected(dhcpPacket);
-        Interface serverInterface = isDirectlyConnected ? getServerInterface() : getIndirectServerInterface();
+        Interface serverInterface = isDirectlyConnected ? getDefaultServerInterface() : getIndirectServerInterface();
         if (serverInterface == null) {
             log.warn("Can't get {} server interface, ignore", isDirectlyConnected ? "direct" : "indirect");
             return null;
@@ -512,10 +443,8 @@
             return null;
         }
         if (dhcpConnectMac == null) {
-            log.warn("DHCP {} not yet resolved .. Aborting DHCP "
+            log.warn("DHCP Server/Gateway IP not yet resolved .. Aborting DHCP "
                              + "packet processing from client on port: {}",
-                     (dhcpGatewayIp == null) ? "server IP " + dhcpServerIp
-                             : "gateway IP " + dhcpGatewayIp,
                      context.inPacket().receivedFrom());
             return null;
         }
@@ -917,10 +846,12 @@
      * @param packet the packet
      */
     private void handleDhcpDiscoverAndRequest(Ethernet packet, DHCP dhcpPayload) {
-        ConnectPoint portToFotward = dhcpServerConnectPoint;
-        if (!directlyConnected(dhcpPayload) && indirectDhcpServerConnectPoint != null) {
-            portToFotward = indirectDhcpServerConnectPoint;
+        boolean direct = directlyConnected(dhcpPayload);
+        DhcpServerInfo serverInfo = defaultServerInfoList.get(0);
+        if (!direct && !indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
         }
+        ConnectPoint portToFotward = serverInfo.getDhcpServerConnectPoint().orElse(null);
         // send packet to dhcp server connect point.
         if (portToFotward != null) {
             TrafficTreatment t = DefaultTrafficTreatment.builder()
@@ -1040,6 +971,9 @@
     class InternalHostListener implements HostListener {
         @Override
         public void event(HostEvent event) {
+            if (!configured()) {
+                return;
+            }
             switch (event.type()) {
                 case HOST_ADDED:
                 case HOST_UPDATED:
@@ -1065,32 +999,54 @@
      * @param host the host
      */
     private void hostMoved(Host host) {
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp) &&
-                    !host.locations().contains(this.dhcpServerConnectPoint)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+        Set<ConnectPoint> hostConnectPoints = host.locations().stream()
+                .map(hl -> new ConnectPoint(hl.elementId(), hl.port()))
+                .collect(Collectors.toSet());
+        DhcpServerInfo serverInfo;
+        ConnectPoint dhcpServerConnectPoint;
+        Ip4Address dhcpGatewayIp;
+        Ip4Address dhcpServerIp;
+
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp) &&
-                    !host.locations().contains(this.dhcpServerConnectPoint)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+
+        if (!indirectServerInfoList.isEmpty()) {
+            // Indirect server
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
-        }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp) &&
-                    !host.locations().contains(this.indirectDhcpServerConnectPoint)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
-            }
-        }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp) &&
-                    !host.locations().contains(this.indirectDhcpServerConnectPoint)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
     }
@@ -1102,30 +1058,46 @@
      * @param host the host
      */
     private void hostUpdated(Host host) {
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp)) {
-                this.dhcpConnectMac = host.mac();
-                this.dhcpConnectVlan = host.vlan();
+        DhcpServerInfo serverInfo;
+        Ip4Address dhcpGatewayIp;
+        Ip4Address dhcpServerIp;
+
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
             }
         }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp)) {
-                this.dhcpConnectMac = host.mac();
-                this.dhcpConnectVlan = host.vlan();
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
             }
         }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp)) {
-                this.indirectDhcpConnectMac = host.mac();
-                this.indirectDhcpConnectVlan = host.vlan();
-            }
-        }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp)) {
-                this.indirectDhcpConnectMac = host.mac();
-                this.indirectDhcpConnectVlan = host.vlan();
-            }
-        }
+
     }
 
     /**
@@ -1135,28 +1107,44 @@
      * @param host the host
      */
     private void hostRemoved(Host host) {
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+        DhcpServerInfo serverInfo;
+        Ip4Address dhcpGatewayIp;
+        Ip4Address dhcpServerIp;
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp4().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp4().orElse(null);
+
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
-        }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
-            }
-        }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
     }
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
index f3ffab3..9dabfd9 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
@@ -17,9 +17,9 @@
 
 package org.onosproject.dhcprelay;
 
+import com.google.common.collect.Lists;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Deactivate;
-import com.google.common.base.MoreObjects;
 import com.google.common.collect.Sets;
 import com.google.common.collect.ImmutableSet;
 import org.apache.felix.scr.annotations.Component;
@@ -47,6 +47,7 @@
 import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
 import org.onlab.util.HexString;
 import org.onosproject.dhcprelay.api.DhcpHandler;
+import org.onosproject.dhcprelay.api.DhcpServerInfo;
 import org.onosproject.dhcprelay.store.DhcpRelayStore;
 import org.onosproject.net.host.HostProvider;
 import org.onosproject.net.host.HostProviderRegistry;
@@ -83,6 +84,7 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.ArrayList;
+import java.util.stream.Collectors;
 
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -134,6 +136,9 @@
     private Ip6Address indirectDhcpGatewayIp = null;
     private Ip6Address indirectRelayAgentIpFromCfg = null;
 
+    private List<DhcpServerInfo> defaultServerInfoList = Lists.newArrayList();
+    private List<DhcpServerInfo> indirectServerInfoList = Lists.newArrayList();
+
 
     // CLIENT message types
     public static final Set<Byte> MSG_TYPE_FROM_CLIENT =
@@ -159,115 +164,32 @@
     protected void deactivate() {
         providerRegistry.unregister(this);
         hostService.removeListener(hostListener);
-        this.dhcpConnectMac = null;
-        this.dhcpConnectVlan = null;
+        defaultServerInfoList.forEach(this::stopMonitoringIps);
+        defaultServerInfoList.clear();
+        indirectServerInfoList.forEach(this::stopMonitoringIps);
+        indirectServerInfoList.clear();
+    }
 
-        if (dhcpGatewayIp != null) {
-            hostService.stopMonitoringIp(dhcpGatewayIp);
-        } else if (dhcpServerIp != null) {
-            hostService.stopMonitoringIp(dhcpServerIp);
-        }
+    private void stopMonitoringIps(DhcpServerInfo serverInfo) {
+        serverInfo.getDhcpGatewayIp6().ifPresent(gatewayIp -> {
+            hostService.stopMonitoringIp(gatewayIp);
+        });
+        serverInfo.getDhcpServerIp6().ifPresent(serverIp -> {
+            hostService.stopMonitoringIp(serverIp);
+        });
     }
 
     @Override
-    public void setDhcpServerIp(IpAddress dhcpServerIp) {
-        checkNotNull(dhcpServerIp, "DHCP server IP can't be null");
-        checkState(dhcpServerIp.isIp6(), "Invalid server IP for DHCPv6 relay handler");
-        this.dhcpServerIp = dhcpServerIp.getIp6Address();
+    public List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
+        return defaultServerInfoList;
     }
 
     @Override
-    public void setDhcpServerConnectPoint(ConnectPoint dhcpServerConnectPoint) {
-        checkNotNull(dhcpServerConnectPoint, "Server connect point can't null");
-        this.dhcpServerConnectPoint = dhcpServerConnectPoint;
+    public List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
+        return indirectServerInfoList;
     }
 
     @Override
-    public void setDhcpConnectMac(MacAddress dhcpConnectMac) {
-        this.dhcpConnectMac = dhcpConnectMac;
-    }
-
-    @Override
-    public void setDhcpConnectVlan(VlanId dhcpConnectVlan) {
-        this.dhcpConnectVlan = dhcpConnectVlan;
-    }
-
-    @Override
-    public void setDhcpGatewayIp(IpAddress dhcpGatewayIp) {
-        if (dhcpGatewayIp != null) {
-            checkState(dhcpGatewayIp.isIp6(), "Invalid gateway IP for DHCPv6 relay handler");
-            this.dhcpGatewayIp = dhcpGatewayIp.getIp6Address();
-        } else {
-            // removes gateway config
-            this.dhcpGatewayIp = null;
-        }
-    }
-    @Override
-    public Optional<IpAddress> getDhcpServerIp() {
-        return Optional.ofNullable(dhcpServerIp);
-    }
-
-    @Override
-    public Optional<IpAddress> getDhcpGatewayIp() {
-        return Optional.ofNullable(dhcpGatewayIp);
-    }
-
-    @Override
-    public Optional<MacAddress> getDhcpConnectMac() {
-        return Optional.ofNullable(dhcpConnectMac);
-    }
-
-    // Indirect DHCP server
-
-    public void setIndirectDhcpServerIp(IpAddress dhcpServerIp) {
-        checkNotNull(dhcpServerIp, "DHCP indirect server IP can't be null");
-        checkState(dhcpServerIp.isIp6(), "Invalid indirect server IP for DHCPv6 relay handler");
-        this.indirectDhcpServerIp = dhcpServerIp.getIp6Address();
-    }
-
-
-    public void setIndirectDhcpServerConnectPoint(ConnectPoint dhcpServerConnectPoint) {
-        checkNotNull(dhcpServerConnectPoint, "Indirect Server connect point can't null");
-        this.indirectDhcpServerConnectPoint = dhcpServerConnectPoint;
-    }
-
-
-    public void setIndirectDhcpConnectMac(MacAddress dhcpConnectMac) {
-        this.indirectDhcpConnectMac = dhcpConnectMac;
-    }
-
-
-    public void setIndirectDhcpConnectVlan(VlanId dhcpConnectVlan) {
-        this.indirectDhcpConnectVlan = dhcpConnectVlan;
-    }
-
-
-    public void setIndirectDhcpGatewayIp(IpAddress dhcpGatewayIp) {
-        if (dhcpGatewayIp != null) {
-            checkState(dhcpGatewayIp.isIp6(), "Invalid indirect gateway IP for DHCPv6 relay handler");
-            this.indirectDhcpGatewayIp = dhcpGatewayIp.getIp6Address();
-        } else {
-            // removes gateway config
-            this.indirectDhcpGatewayIp = null;
-        }
-    }
-
-    public Optional<IpAddress> getIndirectDhcpServerIp() {
-        return Optional.ofNullable(indirectDhcpServerIp);
-    }
-
-
-    public Optional<IpAddress> getIndirectDhcpGatewayIp() {
-        return Optional.ofNullable(indirectDhcpGatewayIp);
-    }
-
-
-    public Optional<MacAddress> getIndirectDhcpConnectMac() {
-        return Optional.ofNullable(indirectDhcpConnectMac);
-    }
-
-
-    @Override
     public void processDhcpPacket(PacketContext context, BasePacket payload) {
         checkNotNull(payload, "DHCP6 payload can't be null");
         checkState(payload instanceof DHCP6, "Payload is not a DHCP6");
@@ -323,12 +245,7 @@
      * @return true if all information we need have been initialized
      */
     public boolean configured() {
-        log.warn("dhcpServerConnectPoint {} dhcpServerIp {}," +
-                        "  indirectDhcpServerConnectPoint {} indirectDhcpServerIp {}",
-                this.dhcpServerConnectPoint, this.dhcpServerIp,
-                this.indirectDhcpServerConnectPoint, this.indirectDhcpServerIp);
-        return (this.dhcpServerConnectPoint != null && this.dhcpServerIp != null) ||
-                (this.indirectDhcpServerConnectPoint != null && this.indirectDhcpServerIp != null);
+        return !defaultServerInfoList.isEmpty();
     }
 
     @Override
@@ -950,7 +867,6 @@
      */
     private InternalPacket processDhcp6PacketFromServer(PacketContext context,
                                                         Ethernet receivedPacket, Set<Interface> recevingInterfaces) {
-
         // get dhcp6 header.
         Ethernet etherReply = receivedPacket.duplicate();
         IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
@@ -1056,7 +972,7 @@
         return new InternalPacket(etherReply, clientConnectionPoint);
     }
 
-    // Returns the first v4 interface ip out of a set of interfaces or null.
+    // Returns the first v6 interface ip out of a set of interfaces or null.
     // Checks all interfaces, and ignores v6 interface ips
     private Ip6Address getRelayAgentIPv6Address(Set<Interface> intfs) {
         for (Interface intf : intfs) {
@@ -1072,6 +988,17 @@
 
     @Override
     public void setDefaultDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+        setDhcpServerConfigs(configs, defaultServerInfoList);
+        reloadServerSettings();
+    }
+
+    @Override
+    public void setIndirectDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+        setDhcpServerConfigs(configs, indirectServerInfoList);
+        reloadServerSettings();
+    }
+
+    public void setDhcpServerConfigs(Collection<DhcpServerConfig> configs, List<DhcpServerInfo> serverInfoList) {
         if (configs.size() == 0) {
             // no config to update
             return;
@@ -1080,111 +1007,62 @@
         // TODO: currently we pick up first DHCP server config.
         // Will use other server configs in the future for HA.
         DhcpServerConfig serverConfig = configs.iterator().next();
-        if (!serverConfig.getDhcpServerConnectPoint().isPresent()) {
-            log.warn("Connect point not exists");
-            return;
-        }
+
         if (!serverConfig.getDhcpServerIp6().isPresent()) {
-            log.warn("IP of DHCP6 server not exists");
-            return;
-        }
-        Ip6Address oldServerIp = this.dhcpServerIp;
-        Ip6Address oldGatewayIp = this.dhcpGatewayIp;
-
-        // stop monitoring gateway or server
-        if (oldGatewayIp != null) {
-            hostService.stopMonitoringIp(oldGatewayIp);
-        } else if (oldServerIp != null) {
-            hostService.stopMonitoringIp(oldServerIp);
-        }
-
-        this.dhcpServerConnectPoint = serverConfig.getDhcpServerConnectPoint().get();
-        this.dhcpServerIp = serverConfig.getDhcpServerIp6().get();
-        this.dhcpGatewayIp = serverConfig.getDhcpGatewayIp6().orElse(null);
-        this.relayAgentIpFromCfg = serverConfig.getRelayAgentIp6().orElse(null);
-
-
-        // reset server mac and vlan
-        this.dhcpConnectMac = null;
-        this.dhcpConnectVlan = null;
-
-        log.info("DHCP6 server connect point: " + this.dhcpServerConnectPoint);
-        log.info("DHCP6 server IP: " + this.dhcpServerIp);
-
-        IpAddress ipToProbe = MoreObjects.firstNonNull(this.dhcpGatewayIp, this.dhcpServerIp);
-        String hostToProbe = this.dhcpGatewayIp != null ? "gateway" : "DHCP6 server";
-
-        if (ipToProbe == null) {
-            log.warn("Server IP6 not set, can't probe it");
+            // not a DHCPv6 config
             return;
         }
 
-        log.info("Probing to resolve {} IP6 {}", hostToProbe, ipToProbe);
+        if (!serverInfoList.isEmpty()) {
+            // remove old server info
+            DhcpServerInfo oldServerInfo = serverInfoList.remove(0);
+
+            // stop monitoring gateway or server
+            oldServerInfo.getDhcpGatewayIp6().ifPresent(gatewayIp -> {
+                hostService.stopMonitoringIp(gatewayIp);
+            });
+            oldServerInfo.getDhcpServerIp6().ifPresent(serverIp -> {
+                hostService.stopMonitoringIp(serverIp);
+            });
+        }
+
+        // Create new server info according to the config
+        DhcpServerInfo newServerInfo = new DhcpServerInfo(serverConfig,
+                                                          DhcpServerInfo.Version.DHCP_V6);
+        checkState(newServerInfo.getDhcpServerConnectPoint().isPresent(),
+                   "Connect point not exists");
+        checkState(newServerInfo.getDhcpServerIp6().isPresent(),
+                   "IP of DHCP server not exists");
+
+        log.debug("DHCP server connect point: {}", newServerInfo.getDhcpServerConnectPoint().orElse(null));
+        log.debug("DHCP server IP: {}", newServerInfo.getDhcpServerIp6().orElse(null));
+
+        IpAddress ipToProbe;
+        if (newServerInfo.getDhcpGatewayIp6().isPresent()) {
+            ipToProbe = newServerInfo.getDhcpGatewayIp6().get();
+        } else {
+            ipToProbe = newServerInfo.getDhcpServerIp6().orElse(null);
+        }
+        String hostToProbe = newServerInfo.getDhcpGatewayIp6()
+                .map(ip -> "gateway").orElse("server");
+
+        log.debug("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
         hostService.startMonitoringIp(ipToProbe);
 
         Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
         if (!hosts.isEmpty()) {
             Host host = hosts.iterator().next();
-            this.dhcpConnectVlan = host.vlan();
-            this.dhcpConnectMac = host.mac();
+            newServerInfo.setDhcpConnectVlan(host.vlan());
+            newServerInfo.setDhcpConnectMac(host.mac());
         }
+        // Add new server info
+        serverInfoList.add(0, newServerInfo);
 
-    }
-
-    @Override
-    public void setIndirectDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
-        if (configs.size() == 0) {
-            // no config to update
-            return;
-        }
-
-        // TODO: currently we pick up Second DHCP server config for indirect.
-        // Will use other server configs in the future for HA.
-        DhcpServerConfig serverConfig = configs.iterator().next();
-        checkState(serverConfig.getDhcpServerConnectPoint().isPresent(),
-                "Connect point not exists");
-        checkState(serverConfig.getDhcpServerIp6().isPresent(),
-                "IP of DHCP6 server not exists");
-        Ip6Address oldServerIp = this.indirectDhcpServerIp;
-        Ip6Address oldGatewayIp = this.indirectDhcpGatewayIp;
-
-        // stop monitoring gateway or server
-        if (oldGatewayIp != null) {
-            hostService.stopMonitoringIp(oldGatewayIp);
-        } else if (oldServerIp != null) {
-            hostService.stopMonitoringIp(oldServerIp);
-        }
-
-        this.indirectDhcpServerConnectPoint = serverConfig.getDhcpServerConnectPoint().get();
-        this.indirectDhcpServerIp = serverConfig.getDhcpServerIp6().get();
-        this.indirectDhcpGatewayIp = serverConfig.getDhcpGatewayIp6().orElse(null);
-        this.indirectRelayAgentIpFromCfg = serverConfig.getRelayAgentIp6().orElse(null);
-
-
-        // reset server mac and vlan
-        this.indirectDhcpConnectMac = null;
-        this.indirectDhcpConnectVlan = null;
-
-        log.info("DHCP6 server connect point: " + this.indirectDhcpServerConnectPoint);
-        log.info("DHCP6 server IP: " + this.indirectDhcpServerIp);
-
-        IpAddress ipToProbe = MoreObjects.firstNonNull(this.indirectDhcpGatewayIp, this.indirectDhcpServerIp);
-        String hostToProbe = this.indirectDhcpGatewayIp != null ? "gateway" : "DHCP6 server";
-
-        if (ipToProbe == null) {
-            log.warn("Server IP6 not set, can't probe it");
-            return;
-        }
-
-        log.info("Probing to resolve {} IP6 {}", hostToProbe, ipToProbe);
-        hostService.startMonitoringIp(ipToProbe);
-
-        Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
-        if (!hosts.isEmpty()) {
-            Host host = hosts.iterator().next();
-            this.indirectDhcpConnectVlan = host.vlan();
-            this.indirectDhcpConnectMac = host.mac();
-        }
+        // Remove duplicated server info
+        Set<DhcpServerInfo> nonDupServerInfoList = Sets.newLinkedHashSet();
+        nonDupServerInfoList.addAll(serverInfoList);
+        serverInfoList.clear();
+        serverInfoList.addAll(nonDupServerInfoList);
     }
 
     class InternalHostListener implements HostListener {
@@ -1215,37 +1093,62 @@
      * @param host the host
      */
     private void hostMoved(Host host) {
-        if (this.dhcpServerConnectPoint == null && this.indirectDhcpServerConnectPoint == null) {
-            return;
-        }
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp) &&
-                    !host.locations().contains(this.dhcpServerConnectPoint)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+        Set<ConnectPoint> hostConnectPoints = host.locations().stream()
+                .map(hl -> new ConnectPoint(hl.elementId(), hl.port()))
+                .collect(Collectors.toSet());
+        DhcpServerInfo serverInfo;
+        ConnectPoint dhcpServerConnectPoint;
+        Ip6Address dhcpGatewayIp;
+        Ip6Address dhcpServerIp;
+
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            if (dhcpServerConnectPoint == null) {
+                return;
+            }
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp) &&
-                    !host.locations().contains(this.dhcpServerConnectPoint)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            if (dhcpServerConnectPoint == null) {
+                return;
+            }
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp) &&
+                        !hostConnectPoints.contains(dhcpServerConnectPoint)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp) &&
-                    !host.locations().contains(this.indirectDhcpServerConnectPoint)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
-            }
-        }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp) &&
-                    !host.locations().contains(this.indirectDhcpServerConnectPoint)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
-            }
-        }
+        reloadServerSettings();
     }
 
     /**
@@ -1255,30 +1158,45 @@
      * @param host the host
      */
     private void hostUpdated(Host host) {
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp)) {
-                this.dhcpConnectMac = host.mac();
-                this.dhcpConnectVlan = host.vlan();
+        DhcpServerInfo serverInfo;
+        Ip6Address dhcpGatewayIp;
+        Ip6Address dhcpServerIp;
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
             }
         }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp)) {
-                this.dhcpConnectMac = host.mac();
-                this.dhcpConnectVlan = host.vlan();
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
+            }
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectMac(host.mac());
+                    serverInfo.setDhcpConnectVlan(host.vlan());
+                }
             }
         }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp)) {
-                this.indirectDhcpConnectMac = host.mac();
-                this.indirectDhcpConnectVlan = host.vlan();
-            }
-        }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp)) {
-                this.indirectDhcpConnectMac = host.mac();
-                this.indirectDhcpConnectVlan = host.vlan();
-            }
-        }
+        reloadServerSettings();
     }
 
     /**
@@ -1288,31 +1206,69 @@
      * @param host the host
      */
     private void hostRemoved(Host host) {
-        if (this.dhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.dhcpGatewayIp)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+        DhcpServerInfo serverInfo;
+        Ip6Address dhcpGatewayIp;
+        Ip6Address dhcpServerIp;
+
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
-            //return;
-        }
-        if (this.dhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.dhcpServerIp)) {
-                this.dhcpConnectMac = null;
-                this.dhcpConnectVlan = null;
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
         }
-        if (this.indirectDhcpGatewayIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpGatewayIp)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+
+            if (dhcpGatewayIp != null) {
+                if (host.ipAddresses().contains(dhcpGatewayIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
             }
-            //return;
+            if (dhcpServerIp != null) {
+                if (host.ipAddresses().contains(dhcpServerIp)) {
+                    serverInfo.setDhcpConnectVlan(null);
+                    serverInfo.setDhcpConnectMac(null);
+                }
+            }
         }
-        if (this.indirectDhcpServerIp != null) {
-            if (host.ipAddresses().contains(this.indirectDhcpServerIp)) {
-                this.indirectDhcpConnectMac = null;
-                this.indirectDhcpConnectVlan = null;
-            }
+        reloadServerSettings();
+    }
+
+    private void reloadServerSettings() {
+        DhcpServerInfo serverInfo;
+        if (!defaultServerInfoList.isEmpty()) {
+            serverInfo = defaultServerInfoList.get(0);
+            this.dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
+            this.dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            this.dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            this.dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            this.dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+        }
+
+        if (!indirectServerInfoList.isEmpty()) {
+            serverInfo = indirectServerInfoList.get(0);
+            this.indirectDhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
+            this.indirectDhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
+            this.indirectDhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
+            this.indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+            this.indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+            this.indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6().orElse(null);
         }
     }
     /**
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
index 2e6ce09..e1f9939 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
@@ -55,6 +55,7 @@
 import org.onosproject.core.CoreService;
 import org.onosproject.dhcprelay.api.DhcpHandler;
 import org.onosproject.dhcprelay.api.DhcpRelayService;
+import org.onosproject.dhcprelay.api.DhcpServerInfo;
 import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
 import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
 import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
@@ -485,6 +486,22 @@
                 .findFirst();
     }
 
+    @Override
+    public List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
+        return ImmutableList.<DhcpServerInfo>builder()
+                .addAll(v4Handler.getDefaultDhcpServerInfoList())
+                .addAll(v6Handler.getDefaultDhcpServerInfoList())
+                .build();
+    }
+
+    @Override
+    public List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
+        return ImmutableList.<DhcpServerInfo>builder()
+                .addAll(v4Handler.getIndirectDhcpServerInfoList())
+                .addAll(v6Handler.getIndirectDhcpServerInfoList())
+                .build();
+    }
+
     /**
      * Gets DHCP data from a packet.
      *
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
index 7f5dd46..2efeca4 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
@@ -26,6 +26,8 @@
 import org.onosproject.net.packet.PacketContext;
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 
 /**
@@ -47,7 +49,9 @@
      * @deprecated 1.12 get the address from config service
      */
     @Deprecated
-    Optional<IpAddress> getDhcpServerIp();
+    default Optional<IpAddress> getDhcpServerIp() {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Gets DHCP gateway IP.
@@ -56,7 +60,9 @@
      * @deprecated 1.12 get the address from config service
      */
     @Deprecated
-    Optional<IpAddress> getDhcpGatewayIp();
+    default Optional<IpAddress> getDhcpGatewayIp() {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Gets DHCP connect Mac address.
@@ -65,7 +71,9 @@
      * @deprecated 1.12 get host mac from host service
      */
     @Deprecated
-    Optional<MacAddress> getDhcpConnectMac();
+    default Optional<MacAddress> getDhcpConnectMac() {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Sets DHCP gateway IP.
@@ -74,7 +82,9 @@
      * @deprecated 1.12 use setDefaultDhcpServerConfigs or setindirectDhcpServerConfigs
      */
     @Deprecated
-    void setDhcpGatewayIp(IpAddress dhcpGatewayIp);
+    default void setDhcpGatewayIp(IpAddress dhcpGatewayIp) {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Sets DHCP connect vlan.
@@ -83,7 +93,9 @@
      * @deprecated 1.12 use setDefaultDhcpServerConfigs or setindirectDhcpServerConfigs
      */
     @Deprecated
-    void setDhcpConnectVlan(VlanId dhcpConnectVlan);
+    default void setDhcpConnectVlan(VlanId dhcpConnectVlan) {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Sets DHCP connect Mac address.
@@ -92,7 +104,9 @@
      * @deprecated 1.12 use setDefaultDhcpServerConfigs or setindirectDhcpServerConfigs
      */
     @Deprecated
-    void setDhcpConnectMac(MacAddress dhcpConnectMac);
+    default void setDhcpConnectMac(MacAddress dhcpConnectMac) {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Sets DHCP server connect point.
@@ -101,7 +115,9 @@
      * @deprecated 1.12 use setDefaultDhcpServerConfigs or setindirectDhcpServerConfigs
      */
     @Deprecated
-    void setDhcpServerConnectPoint(ConnectPoint dhcpServerConnectPoint);
+    default void setDhcpServerConnectPoint(ConnectPoint dhcpServerConnectPoint) {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
 
     /**
      * Sets DHCP server IP.
@@ -110,7 +126,27 @@
      * @deprecated 1.12 use setDefaultDhcpServerConfigs or setindirectDhcpServerConfigs
      */
     @Deprecated
-    void setDhcpServerIp(IpAddress dhcpServerIp);
+    default void setDhcpServerIp(IpAddress dhcpServerIp) {
+        throw new UnsupportedOperationException("Method deprecated");
+    }
+
+    /**
+     * Gets list of default DHCP server information.
+     *
+     * @return list of default DHCP server information
+     */
+    default List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Gets list of indirect DHCP server information.
+     *
+     * @return list of indirect DHCP server information
+     */
+    default List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
+        return Collections.emptyList();
+    }
 
     /**
      * Sets DHCP server config for default case.
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
index 9bad009..2711a08 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
@@ -22,6 +22,7 @@
 import org.onosproject.net.HostId;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 
 public interface DhcpRelayService {
@@ -44,6 +45,22 @@
      * Gets mac address of DHCP server.
      *
      * @return the mac address of DHCP server; empty if not exist
+     * @deprecated 1.12, use get DHCP server configs method
      */
+    @Deprecated
     Optional<MacAddress> getDhcpServerMacAddress();
+
+    /**
+     * Gets list of default DHCP server information.
+     *
+     * @return list of default DHCP server information
+     */
+    List<DhcpServerInfo> getDefaultDhcpServerInfoList();
+
+    /**
+     * Gets list of indirect DHCP server information.
+     *
+     * @return list of indirect DHCP server information
+     */
+    List<DhcpServerInfo> getIndirectDhcpServerInfoList();
 }
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpServerInfo.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpServerInfo.java
new file mode 100644
index 0000000..81a2411
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpServerInfo.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2017-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 org.onosproject.dhcprelay.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.dhcprelay.config.DhcpServerConfig;
+
+import java.util.Optional;
+
+/**
+ * class contains DHCP server information.
+ */
+public class DhcpServerInfo extends DhcpServerConfig {
+    public enum Version {
+        DHCP_V4,
+        DHCP_V6
+    }
+    private MacAddress dhcpConnectMac;
+    private VlanId dhcpConnectVlan;
+    private Version version;
+
+    /**
+     * Creates DHCP server information from config.
+     *
+     * @param config DHCP server config
+     * @param version DHCP version for the server
+     */
+    public DhcpServerInfo(DhcpServerConfig config, Version version) {
+        this.connectPoint = config.getDhcpServerConnectPoint().orElse(null);
+        this.version = version;
+
+        switch (version) {
+            case DHCP_V4:
+                this.serverIp4Addr = config.getDhcpServerIp4().orElse(null);
+                this.gatewayIp4Addr = config.getDhcpGatewayIp4().orElse(null);
+                this.relayAgentIp4Addr = config.getRelayAgentIp4().orElse(null);
+                break;
+            case DHCP_V6:
+                this.serverIp6Addr = config.getDhcpServerIp6().orElse(null);
+                this.gatewayIp6Addr = config.getDhcpGatewayIp6().orElse(null);
+                this.relayAgentIp6Addr = config.getRelayAgentIp6().orElse(null);
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Sets DHCP server or gateway mac address.
+     *
+     * @param dhcpConnectMac the mac address
+     */
+    public void setDhcpConnectMac(MacAddress dhcpConnectMac) {
+        this.dhcpConnectMac = dhcpConnectMac;
+    }
+
+    /**
+     * Sets DHCP server or gateway vlan id.
+     *
+     * @param dhcpConnectVlan the vlan id
+     */
+    public void setDhcpConnectVlan(VlanId dhcpConnectVlan) {
+        this.dhcpConnectVlan = dhcpConnectVlan;
+    }
+
+    /**
+     * Gets DHCP server or gateway mac address.
+     *
+     * @return the mac address
+     */
+    public Optional<MacAddress> getDhcpConnectMac() {
+        return Optional.ofNullable(dhcpConnectMac);
+    }
+
+    /**
+     * Gets DHCP server or gateway vlan id.
+     *
+     * @return the vlan id.
+     */
+    public Optional<VlanId> getDhcpConnectVlan() {
+        return Optional.ofNullable(dhcpConnectVlan);
+    }
+
+    /**
+     * Get DHCP version of the DHCP server.
+     *
+     * @return the version; can be DHCP_V4 or DHCP_V6
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    @Override
+    public String toString() {
+        MoreObjects.ToStringHelper toStringHelper = MoreObjects.toStringHelper(this);
+        toStringHelper
+                .add("dhcpConnectMac", dhcpConnectMac)
+                .add("dhcpConnectVlan", dhcpConnectVlan)
+                .add("connectPoint", connectPoint)
+                .add("version", version);
+        switch (version) {
+            case DHCP_V4:
+                toStringHelper
+                        .add("serverIp4Addr", serverIp4Addr)
+                        .add("gatewayIp4Addr", gatewayIp4Addr)
+                        .add("relayAgentIp4Addr", relayAgentIp4Addr);
+                break;
+            case DHCP_V6:
+                toStringHelper
+                        .add("serverIp6Addr", serverIp6Addr)
+                        .add("gatewayIp6Addr", gatewayIp6Addr)
+                        .add("relayAgentIp6Addr", relayAgentIp6Addr);
+                break;
+            default:
+                break;
+        }
+        return toStringHelper.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof DhcpServerInfo)) {
+            return false;
+        }
+        DhcpServerInfo that = (DhcpServerInfo) o;
+        return super.equals(o) &&
+                Objects.equal(dhcpConnectMac, that.dhcpConnectMac) &&
+                Objects.equal(dhcpConnectVlan, that.dhcpConnectVlan) &&
+                version == that.version;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(super.hashCode(), dhcpConnectMac, dhcpConnectVlan, version);
+    }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
index d4ea1d8..acf8f79 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
@@ -17,26 +17,20 @@
 package org.onosproject.dhcprelay.cli;
 
 import org.apache.karaf.shell.commands.Command;
-import org.onlab.packet.Ip4Address;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onlab.util.Tools;
 import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
-import org.onosproject.dhcprelay.DhcpRelayManager;
+import org.onosproject.dhcprelay.api.DhcpServerInfo;
 import org.onosproject.dhcprelay.api.DhcpRelayService;
-import org.onosproject.dhcprelay.config.DhcpServerConfig;
 import org.onosproject.dhcprelay.store.DhcpRecord;
-import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
-import org.onosproject.net.config.NetworkConfigRegistry;
 import org.onosproject.net.host.HostService;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.function.Predicate;
 
 /**
@@ -47,46 +41,37 @@
     private static final String HEADER = "DHCP relay records ([D]: Directly connected):";
     private static final String NO_RECORDS = "No DHCP relay record found";
     private static final String HOST = "id=%s/%s, locations=%s%s, last-seen=%s, IPv4=%s, IPv6=%s";
-    private static final String DHCP_SERVER_GW = "DHCP Server: %s, %s via %s (Mac: %s)";
-    private static final String DHCP_SERVER = "DHCP Server: %s, %s (Mac: %s)";
+    private static final String DHCP_SERVER_GW = "DHCP Server: %s, %s via %s (Mac: %s, relay IP overwrite: %s)";
+    private static final String DHCP_SERVER = "DHCP Server: %s, %s (Mac: %s, relay IP overwrite: %s)";
     private static final String MISSING_SERVER_CFG = "DHCP Server info not available";
     private static final String DIRECTLY = "[D]";
     private static final String EMPTY = "";
     private static final String NA = "N/A";
     private static final String STATUS_FMT = "[%s, %s]";
     private static final String STATUS_FMT_NH = "[%s via %s, %s]";
+    private static final String DEFAULT_SERVERS = "Default DHCP servers:";
+    private static final String INDIRECT_SERVERS = "Indirect DHCP servers:";
 
     private static final DhcpRelayService DHCP_RELAY_SERVICE = get(DhcpRelayService.class);
-    private static final NetworkConfigRegistry CFG_SERVICE = get(NetworkConfigRegistry.class);
     private static final HostService HOST_SERVICE = get(HostService.class);
-    private static final CoreService CORE_SERVICE = get(CoreService.class);
-    private static final ApplicationId APP_ID =
-            CORE_SERVICE.getAppId(DhcpRelayManager.DHCP_RELAY_APP);
-
 
     @Override
     protected void execute() {
-        // TODO: add indirect config
-        DefaultDhcpRelayConfig cfg = CFG_SERVICE.getConfig(APP_ID, DefaultDhcpRelayConfig.class);
-        if (cfg == null || cfg.dhcpServerConfigs().size() == 0) {
+        List<DhcpServerInfo> defaultDhcpServerInfoList = DHCP_RELAY_SERVICE.getDefaultDhcpServerInfoList();
+        List<DhcpServerInfo> indirectDhcpServerInfoList = DHCP_RELAY_SERVICE.getIndirectDhcpServerInfoList();
+
+        if (defaultDhcpServerInfoList.isEmpty() && indirectDhcpServerInfoList.isEmpty()) {
             print(MISSING_SERVER_CFG);
             return;
         }
 
-        // DHCP server information
-        // TODO: currently we pick up first DHCP server config.
-        // Will use other server configs in the future.
-        DhcpServerConfig serverConfig = cfg.dhcpServerConfigs().get(0);
-
-        ConnectPoint connectPoint = serverConfig.getDhcpServerConnectPoint().orElse(null);
-        Ip4Address gatewayAddress = serverConfig.getDhcpGatewayIp4().orElse(null);
-        Ip4Address serverIp = serverConfig.getDhcpServerIp4().orElse(null);
-        String serverMac = DHCP_RELAY_SERVICE.getDhcpServerMacAddress()
-                .map(MacAddress::toString).orElse(NA);
-        if (gatewayAddress != null) {
-            print(DHCP_SERVER_GW, connectPoint, serverIp, gatewayAddress, serverMac);
-        } else {
-            print(DHCP_SERVER, connectPoint, serverIp, serverMac);
+        if (!defaultDhcpServerInfoList.isEmpty()) {
+            print(DEFAULT_SERVERS);
+            listServers(defaultDhcpServerInfoList);
+        }
+        if (!indirectDhcpServerInfoList.isEmpty()) {
+            print(INDIRECT_SERVERS);
+            listServers(indirectDhcpServerInfoList);
         }
 
         // DHCP records
@@ -106,6 +91,44 @@
                                         ip6State(record)));
     }
 
+    private void listServers(List<DhcpServerInfo> dhcpServerInfoList) {
+        dhcpServerInfoList.forEach(dhcpServerInfo -> {
+            String connectPoint = dhcpServerInfo.getDhcpServerConnectPoint()
+                    .map(Object::toString).orElse(NA);
+            String serverMac = dhcpServerInfo.getDhcpConnectMac()
+                    .map(Object::toString).orElse(NA);
+            String gatewayAddress;
+            String serverIp;
+            String relayAgentIp;
+
+            switch (dhcpServerInfo.getVersion()) {
+                case DHCP_V4:
+                    gatewayAddress = dhcpServerInfo.getDhcpGatewayIp4()
+                            .map(Object::toString).orElse(null);
+                    serverIp = dhcpServerInfo.getDhcpServerIp4()
+                            .map(Object::toString).orElse(NA);
+                    relayAgentIp = dhcpServerInfo.getRelayAgentIp4()
+                            .map(Object::toString).orElse(NA);
+                    break;
+                case DHCP_V6:
+                    gatewayAddress = dhcpServerInfo.getDhcpGatewayIp6()
+                            .map(Object::toString).orElse(null);
+                    serverIp = dhcpServerInfo.getDhcpServerIp6()
+                            .map(Object::toString).orElse(NA);
+                    relayAgentIp = dhcpServerInfo.getRelayAgentIp6()
+                            .map(Object::toString).orElse(NA);
+                    break;
+                default:
+                    return;
+            }
+            if (gatewayAddress != null) {
+                print(DHCP_SERVER_GW, connectPoint, serverIp, gatewayAddress, serverMac, relayAgentIp);
+            } else {
+                print(DHCP_SERVER, connectPoint, serverIp, serverMac, relayAgentIp);
+            }
+        });
+    }
+
     private String ip4State(DhcpRecord record) {
         String nextHopIp = findNextHopIp(IpAddress::isIp4,
                                          record.nextHop().orElse(null),
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/config/DhcpServerConfig.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/config/DhcpServerConfig.java
index a5c304b..19d8ed2 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/config/DhcpServerConfig.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/config/DhcpServerConfig.java
@@ -19,6 +19,7 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.base.Objects;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpAddress;
@@ -35,13 +36,13 @@
     private static final String DHCP_GATEWAY_IP = "gatewayIps";
     private static final String RELAY_AGENT_IP = "relayAgentIps";
 
-    private ConnectPoint connectPoint;
-    private Ip4Address serverIp4Addr;
-    private Ip4Address gatewayIp4Addr;
-    private Ip4Address relayAgentIp4Addr;
-    private Ip6Address serverIp6Addr;
-    private Ip6Address gatewayIp6Addr;
-    private Ip6Address relayAgentIp6Addr;
+    protected ConnectPoint connectPoint;
+    protected Ip4Address serverIp4Addr;
+    protected Ip4Address gatewayIp4Addr;
+    protected Ip4Address relayAgentIp4Addr;
+    protected Ip6Address serverIp6Addr;
+    protected Ip6Address gatewayIp6Addr;
+    protected Ip6Address relayAgentIp6Addr;
 
     protected DhcpServerConfig() {
         // empty config not allowed here
@@ -183,4 +184,29 @@
     public Optional<Ip6Address> getRelayAgentIp6() {
         return Optional.ofNullable(relayAgentIp6Addr);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        DhcpServerConfig that = (DhcpServerConfig) o;
+        return Objects.equal(connectPoint, that.connectPoint) &&
+                Objects.equal(serverIp4Addr, that.serverIp4Addr) &&
+                Objects.equal(gatewayIp4Addr, that.gatewayIp4Addr) &&
+                Objects.equal(relayAgentIp4Addr, that.relayAgentIp4Addr) &&
+                Objects.equal(serverIp6Addr, that.serverIp6Addr) &&
+                Objects.equal(gatewayIp6Addr, that.gatewayIp6Addr) &&
+                Objects.equal(relayAgentIp6Addr, that.relayAgentIp6Addr);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(connectPoint, serverIp4Addr, gatewayIp4Addr,
+                                relayAgentIp4Addr, serverIp6Addr, gatewayIp6Addr,
+                                relayAgentIp6Addr);
+    }
 }