Ported the configuration reader for the SDN-IP specific configuration
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpPeer.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpPeer.java
new file mode 100644
index 0000000..9d014d0
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpPeer.java
@@ -0,0 +1,72 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.Objects;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Configuration details for a BGP peer. It contains the peer's IP address and
+ * an interface name which maps to the interface they are attached at.
+ */
+public class BgpPeer {
+    private final ConnectPoint connectPoint;
+    private final IpAddress ipAddress;
+
+    /**
+     * Class constructor, taking the interface name and IP address of the peer.
+     *
+     * @param interfaceName the String name of the interface which can be used
+     * to look up the interface this peer is attached at
+     * @param ipAddress the IP address of the peer as a String
+     */
+    public BgpPeer(@JsonProperty("attachmentDpid") String dpid,
+                   @JsonProperty("attachmentPort") int port,
+                   @JsonProperty("ipAddress") String ipAddress) {
+        this.connectPoint = new ConnectPoint(
+                DeviceId.deviceId(SdnIpConfigReader.dpidToUri(dpid)),
+                PortNumber.portNumber(port));
+        this.ipAddress = IpAddress.valueOf(ipAddress);
+    }
+
+    /**
+     * Gets the connection point of the peer.
+     *
+     * @return the connection point
+     */
+    public ConnectPoint getConnectPoint() {
+        return connectPoint;
+    }
+
+    /**
+     * Gets the IP address of the peer.
+     *
+     * @return the IP address
+     */
+    public IpAddress getIpAddress() {
+        return ipAddress;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(connectPoint, ipAddress);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof BgpPeer)) {
+            return false;
+        }
+
+        BgpPeer that = (BgpPeer) obj;
+        return Objects.equals(this.connectPoint, that.connectPoint)
+                && Objects.equals(this.ipAddress, that.ipAddress);
+    }
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpSpeaker.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpSpeaker.java
new file mode 100644
index 0000000..c7c2edd
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/BgpSpeaker.java
@@ -0,0 +1,124 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.packet.MacAddress;
+
+/**
+ * Represents a BGP daemon in SDN network.
+ * <p/>
+ * Each BGP speaker has a attachment point, which includes a switch DPID and a
+ * switch port. Each BGP speaker has one MAC address and several IP addresses,
+ * which are used to peer with BGP peers outside the SDN network. For each
+ * peer outside the SDN network, we configure a different IP address to BGP
+ * speaker inside the SDN network.
+ * <p/>
+ * Each BGP speaker has a name, which is a unique identifying String that is
+ * used to reference this speaker in the configuration.
+ */
+public class BgpSpeaker {
+    private final String speakerName;
+    private final ConnectPoint attachmentSwitchPort;
+    private final MacAddress macAddress;
+    private List<InterfaceAddress> interfaceAddresses;
+
+    /**
+     * Class constructor used by the JSON library to create an object.
+     *
+     * @param speakerName the name of the BGP router inside SDN network
+     * @param attachmentDpid the DPID where the BGP router is attached to
+     * @param attachmentPort the port where the BGP router is attached to
+     * @param macAddress the MAC address of the BGP router
+     */
+    @JsonCreator
+    public BgpSpeaker(@JsonProperty("name") String speakerName,
+            @JsonProperty("attachmentDpid") String attachmentDpid,
+            @JsonProperty("attachmentPort") int attachmentPort,
+            @JsonProperty("macAddress") String macAddress) {
+
+        this.speakerName = speakerName;
+        this.macAddress = MacAddress.valueOf(macAddress);
+        this.attachmentSwitchPort = new ConnectPoint(
+                DeviceId.deviceId(SdnIpConfigReader.dpidToUri(attachmentDpid)),
+                PortNumber.portNumber(attachmentPort));
+    }
+
+    /**
+     * Sets the addresses we configured for the BGP speaker on all virtual
+     * {@link Interface}s.
+     *
+     * @param interfaceAddresses a list of IP addresses of the BGP speaker
+     * configured on all virtual interfaces
+     */
+    @JsonProperty("interfaceAddresses")
+    public void setInterfaceAddresses(
+            List<InterfaceAddress> interfaceAddresses) {
+        this.interfaceAddresses = interfaceAddresses;
+    }
+
+    /**
+     * Gets the BGP speaker name.
+     *
+     * @return the BGP speaker name
+     */
+    public String getSpeakerName() {
+        return speakerName;
+    }
+
+    /**
+     * Gets the switch port where the BGP speaker is attached.
+     *
+     * @return the switch port where the BGP speaker is attached
+     */
+    public ConnectPoint getAttachmentSwitchPort() {
+        return attachmentSwitchPort;
+    }
+
+    /**
+     * Gets the MAC address of the BGP speaker.
+     *
+     * @return the MAC address of the BGP speaker
+     */
+    public MacAddress getMacAddress() {
+        return macAddress;
+    }
+
+    /**
+     * Gets all IP addresses configured on all {@link Interface}s of the
+     * BGP speaker.
+     *
+     * @return a list of IP addresses of the BGP speaker configured on all
+     * virtual interfaces
+     */
+    public List<InterfaceAddress> getInterfaceAddresses() {
+        return interfaceAddresses;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof BgpSpeaker)) {
+            return false;
+        }
+
+        BgpSpeaker otherBgpSpeaker = (BgpSpeaker) other;
+
+        return  speakerName.equals(otherBgpSpeaker.speakerName) &&
+                attachmentSwitchPort.equals(
+                        otherBgpSpeaker.attachmentSwitchPort) &&
+                macAddress.equals(otherBgpSpeaker.macAddress) &&
+                interfaceAddresses.equals(otherBgpSpeaker.interfaceAddresses);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(speakerName, attachmentSwitchPort, macAddress,
+                interfaceAddresses);
+
+    }
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Configuration.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Configuration.java
new file mode 100644
index 0000000..e6ed36a
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Configuration.java
@@ -0,0 +1,64 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Contains the configuration data for SDN-IP that has been read from a
+ * JSON-formatted configuration file.
+ */
+public class Configuration {
+    // We call the BGP routers in our SDN network the BGP speakers, and call
+    // the BGP routers outside our SDN network the BGP peers.
+    private List<BgpSpeaker> bgpSpeakers;
+    private List<BgpPeer> peers;
+
+    /**
+     * Default constructor.
+     */
+    public Configuration() {
+    }
+
+    /**
+     * Gets a list of bgpSpeakers in the system, represented by
+     * {@link BgpSpeaker} objects.
+     *
+     * @return the list of BGP speakers
+     */
+    public List<BgpSpeaker> getBgpSpeakers() {
+        return Collections.unmodifiableList(bgpSpeakers);
+    }
+
+    /**
+     * Sets a list of bgpSpeakers in the system.
+     *
+     * @param bgpSpeakers the list of BGP speakers
+     */
+    @JsonProperty("bgpSpeakers")
+    public void setBgpSpeakers(List<BgpSpeaker> bgpSpeakers) {
+        this.bgpSpeakers = bgpSpeakers;
+    }
+
+    /**
+     * Gets a list of BGP peers we are configured to peer with. Peers are
+     * represented by {@link BgpPeer} objects.
+     *
+     * @return the list of BGP peers
+     */
+    public List<BgpPeer> getPeers() {
+        return Collections.unmodifiableList(peers);
+    }
+
+    /**
+     * Sets a list of BGP peers we are configured to peer with.
+     *
+     * @param peers the list of BGP peers
+     */
+    @JsonProperty("bgpPeers")
+    public void setPeers(List<BgpPeer> peers) {
+        this.peers = peers;
+    }
+
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Interface.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Interface.java
new file mode 100644
index 0000000..33287ad
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/Interface.java
@@ -0,0 +1,101 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.Objects;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Represents an interface, which is an external-facing switch port that
+ * connects to another network.
+ * <p/>
+ * SDN-IP treats external-facing ports similarly to router ports. Logically, it
+ * assigns an IP subnetwork prefix and several IP addresses to each port which
+ * are used for communication with the BGP peers located in other networks, for
+ * example, the BGP peering sessions. The peers in other networks will be
+ * configured to peer with the IP addresses (logically) assigned to the
+ * interface. The logical {@code Interface} construct maps on to a physical
+ * port in the data plane, which of course has no notion of IP addresses.
+ * <p/>
+ * Each interface has a name, which is a unique identifying String that is used
+ * to reference this interface in the configuration (for example, to map
+ * {@link BgpPeer}s to {@code Interfaces}.
+ */
+public class Interface {
+    private final String name;
+    private final ConnectPoint switchPort;
+    private final IpPrefix ip4Prefix;
+
+    /**
+     * Class constructor used by the JSON library to create an object.
+     *
+     * @param name the name of the interface
+     * @param dpid the dpid of the switch
+     * @param port the port on the switch
+     * @param prefixAddress the network prefix address logically assigned to the
+     * interface
+     * @param prefixLength the length of the network prefix of the IP address
+     */
+    @JsonCreator
+    public Interface(@JsonProperty("name") String name,
+                     @JsonProperty("dpid") String dpid,
+                     @JsonProperty("port") int port,
+                     @JsonProperty("ipAddress") String prefixAddress,
+                     @JsonProperty("prefixLength") short prefixLength) {
+        this.name = name;
+        this.switchPort = new ConnectPoint(
+                DeviceId.deviceId(SdnIpConfigReader.dpidToUri(dpid)),
+                PortNumber.portNumber(port));
+        this.ip4Prefix = IpPrefix.valueOf(prefixAddress + "/" + prefixLength);
+    }
+
+    /**
+     * Gets the name of the interface.
+     *
+     * @return the name of the interface
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the {@link SwitchPort} that this interface maps to.
+     *
+     * @return the switch port
+     */
+    public ConnectPoint getSwitchPort() {
+        return switchPort;
+    }
+
+    /**
+     * Gets the IP prefix of the subnetwork which is logically assigned
+     * to the switch port.
+     *
+     * @return the IP prefix
+     */
+   public IpPrefix getIp4Prefix() {
+        return ip4Prefix;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof Interface)) {
+            return false;
+        }
+
+        Interface otherInterface = (Interface) other;
+
+        return  name.equals(otherInterface.name) &&
+                switchPort.equals(otherInterface.switchPort) &&
+                ip4Prefix.equals(otherInterface.ip4Prefix);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, switchPort, ip4Prefix);
+    }
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/InterfaceAddress.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/InterfaceAddress.java
new file mode 100644
index 0000000..4b423a7
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/InterfaceAddress.java
@@ -0,0 +1,75 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.Objects;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Represents an address of a {@link BgpSpeaker} configured on an
+ * {@link Interface}.
+ * <p/>
+ * Each InterfaceAddress includes the interface name and an IP address.
+ */
+public class InterfaceAddress {
+    private final ConnectPoint connectPoint;
+    private final IpAddress ipAddress;
+
+    /**
+     * Class constructor used by the JSON library to create an object.
+     *
+     * @param interfaceName the interface name for which an IP address of a BGP
+     * router is configured
+     * @param ipAddress the IP address of a {@link BgpSpeaker} configured on
+     * the interface
+     */
+    public InterfaceAddress(@JsonProperty("interfaceDpid") String dpid,
+                            @JsonProperty("interfacePort") int port,
+                            @JsonProperty("ipAddress") String ipAddress) {
+        this.connectPoint = new ConnectPoint(
+                DeviceId.deviceId(SdnIpConfigReader.dpidToUri(dpid)),
+                PortNumber.portNumber(port));
+        this.ipAddress = IpAddress.valueOf(ipAddress);
+    }
+
+    /**
+     * Gets the connection point of the peer.
+     *
+     * @return the connection point
+     */
+    public ConnectPoint getConnectPoint() {
+        return connectPoint;
+    }
+
+    /**
+     * Gets the IP address of a BGP speaker configured on an {@link Interface}.
+     *
+     * @return the IP address
+     */
+    public IpAddress getIpAddress() {
+        return ipAddress;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(connectPoint, ipAddress);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof InterfaceAddress)) {
+            return false;
+        }
+
+        InterfaceAddress that = (InterfaceAddress) obj;
+        return Objects.equals(this.connectPoint, that.connectPoint)
+                && Objects.equals(this.ipAddress, that.ipAddress);
+    }
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigReader.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigReader.java
new file mode 100644
index 0000000..f98cd15
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigReader.java
@@ -0,0 +1,132 @@
+package org.onlab.onos.sdnip.config;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.onlab.packet.IpAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SDN-IP Config Reader provides IConfigInfoService
+ * by reading from an SDN-IP configuration file.
+ * It must be enabled on the nodes within the cluster
+ * not running SDN-IP.
+ * <p/>
+ * TODO: As a long term solution, a module providing
+ * general network configuration to ONOS nodes should be used.
+ */
+public class SdnIpConfigReader implements SdnIpConfigService {
+
+    private static final Logger log = LoggerFactory.getLogger(SdnIpConfigReader.class);
+
+    private static final String DEFAULT_CONFIG_FILE = "config/sdnip.json";
+    private String configFileName = DEFAULT_CONFIG_FILE;
+    //private Map<String, Interface> interfaces;
+    // We call the BGP routers in our SDN network the BGP speakers, and call
+    // the BGP routers outside our SDN network the BGP peers.
+    private Map<String, BgpSpeaker> bgpSpeakers;
+    private Map<IpAddress, BgpPeer> bgpPeers;
+    //private InvertedRadixTree<Interface> interfaceRoutes;
+
+    /**
+     * Reads the info contained in the configuration file.
+     *
+     * @param configFilename The name of configuration file for SDN-IP application.
+     */
+    private void readConfiguration(String configFilename) {
+        File gatewaysFile = new File(configFilename);
+        ObjectMapper mapper = new ObjectMapper();
+
+        try {
+            Configuration config = mapper.readValue(gatewaysFile, Configuration.class);
+            /*interfaces = new ConcurrentHashMap<>();
+            for (Interface intf : config.getInterfaces()) {
+                interfaces.put(intf.getName(), intf);
+            }*/
+            bgpSpeakers = new ConcurrentHashMap<>();
+            for (BgpSpeaker speaker : config.getBgpSpeakers()) {
+                bgpSpeakers.put(speaker.getSpeakerName(), speaker);
+            }
+            bgpPeers = new ConcurrentHashMap<>();
+            for (BgpPeer peer : config.getPeers()) {
+                bgpPeers.put(peer.getIpAddress(), peer);
+            }
+        } catch (IOException e) {
+            log.error("Error reading JSON file", e);
+            //throw new ConfigurationRuntimeException("Error in JSON file", e);
+        }
+
+        // Populate the interface InvertedRadixTree
+        /*for (Interface intf : interfaces.values()) {
+            Ip4Prefix prefix = intf.getIp4Prefix();
+            String binaryString = RouteEntry.createBinaryString(prefix);
+            interfaceRoutes.put(binaryString, intf);
+        }*/
+    }
+
+    /**
+     * To find the Interface which has longest matchable IP prefix (sub-network
+     *  prefix) to next hop IP address.
+     *
+     * @param address the IP address of next hop router
+     * @return the Interface which has longest matchable IP prefix
+     */
+    /*private Interface longestInterfacePrefixMatch(IpAddress address) {
+        Ip4Prefix prefixToSearchFor =
+            new Ip4Prefix(address, (short) Ip4Address.BIT_LENGTH);
+        String binaryString = RouteEntry.createBinaryString(prefixToSearchFor);
+
+        Iterator<Interface> it =
+            interfaceRoutes.getValuesForKeysPrefixing(binaryString).iterator();
+        Interface intf = null;
+        // Find the last prefix, which will be the longest prefix
+        while (it.hasNext()) {
+            intf = it.next();
+        }
+
+        return intf;
+    }*/
+
+    /*@Override
+    public Interface getOutgoingInterface(IpAddress dstIpAddress) {
+        return longestInterfacePrefixMatch(dstIpAddress);
+    }*/
+
+    public void init() {
+        //interfaceRoutes = new ConcurrentInvertedRadixTree<>(
+                //new DefaultByteArrayNodeFactory());
+
+        // Reading config values
+        /*String configFilenameParameter = context.getConfigParams(this).get("configfile");
+        if (configFilenameParameter != null) {
+            currentConfigFilename = configFilenameParameter;
+        }*/
+        log.debug("Config file set to {}", configFileName);
+
+        readConfiguration(configFileName);
+    }
+
+    /*@Override
+    public Map<String, Interface> getInterfaces() {
+        return Collections.unmodifiableMap(interfaces);
+    }*/
+
+    @Override
+    public Map<String, BgpSpeaker> getBgpSpeakers() {
+        return Collections.unmodifiableMap(bgpSpeakers);
+    }
+
+    @Override
+    public Map<IpAddress, BgpPeer> getBgpPeers() {
+        return Collections.unmodifiableMap(bgpPeers);
+    }
+
+    static String dpidToUri(String dpid) {
+        return "of:" + dpid.replace(":", "");
+    }
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigService.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigService.java
new file mode 100644
index 0000000..62b2ae3
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/SdnIpConfigService.java
@@ -0,0 +1,45 @@
+package org.onlab.onos.sdnip.config;
+
+import java.util.Map;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Provides information about the layer 3 properties of the network.
+ * This is based on IP addresses configured on ports in the network.
+ */
+public interface SdnIpConfigService {
+
+    /**
+     * Gets the list of virtual external-facing interfaces.
+     *
+     * @return the map of interface names to interface objects
+     */
+    //public Map<String, Interface> getInterfaces();
+
+    /**
+     * Gets the list of BGP speakers inside the SDN network.
+     *
+     * @return the map of BGP speaker names to BGP speaker objects
+     */
+    public Map<String, BgpSpeaker> getBgpSpeakers();
+
+    /**
+     * Gets the list of configured BGP peers.
+     *
+     * @return the map from peer IP address to BgpPeer object
+     */
+    public Map<IpAddress, BgpPeer> getBgpPeers();
+
+    /**
+     * Gets the Interface object for the interface that packets
+     * to dstIpAddress will be sent out of. Returns null if dstIpAddress is not
+     * in a directly connected network, or if no interfaces are configured.
+     *
+     * @param dstIpAddress destination IP address that we want to match to
+     *                     an outgoing interface
+     * @return the Interface object if one is found, otherwise null
+     */
+    //public Interface getOutgoingInterface(IpAddress dstIpAddress);
+
+}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/package-info.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/package-info.java
new file mode 100644
index 0000000..1103dbc
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/config/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * SDN-IP configuration.
+ */
+package org.onlab.onos.sdnip.config;
\ No newline at end of file