Jonathan Hart

Ported the configuration reader for the SDN-IP specific configuration

......@@ -5,6 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.onos.sdnip.config.SdnIpConfigReader;
import org.slf4j.Logger;
/**
......@@ -15,9 +16,14 @@ public class SdnIp {
private final Logger log = getLogger(getClass());
private SdnIpConfigReader config;
@Activate
protected void activate() {
log.debug("SDN-IP started");
config = new SdnIpConfigReader();
config.init();
}
@Deactivate
......
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);
}
}
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);
}
}
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;
}
}
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);
}
}
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);
}
}
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(":", "");
}
}
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);
}
/**
* SDN-IP configuration.
*/
package org.onlab.onos.sdnip.config;
\ No newline at end of file
......@@ -163,4 +163,10 @@
<bundle>mvn:org.onlab.onos/onos-app-config/1.0.0-SNAPSHOT</bundle>
</feature>
<feature name="onos-app-sdnip" version="1.0.0"
description="SDN-IP peering application">
<feature>onos-api</feature>
<bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle>
</feature>
</features>
......