Ported PeerConnectivity onto ONOS next, and implemented a service that can

construct Interface objects based on PortAddresses from HostService.
This commit is contained in:
Jonathan Hart 2014-10-15 11:24:23 -07:00
parent dbdbdbb451
commit dc711bd59d
12 changed files with 628 additions and 126 deletions

View File

@ -2,35 +2,40 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.onlab.onos</groupId> <groupId>org.onlab.onos</groupId>
<artifactId>onos-apps</artifactId> <artifactId>onos-apps</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<artifactId>onos-app-sdnip</artifactId> <artifactId>onos-app-sdnip</artifactId>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<description>SDN-IP peering application</description> <description>SDN-IP peering application</description>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.codehaus.jackson</groupId> <groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId> <artifactId>jackson-core-asl</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.jackson</groupId> <groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId> <artifactId>jackson-mapper-asl</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>
<version>2.4.2</version> <version>2.4.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,59 @@
package org.onlab.onos.sdnip;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import org.apache.commons.lang.NotImplementedException;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.host.PortAddresses;
import org.onlab.onos.sdnip.config.Interface;
import org.onlab.packet.IpAddress;
import com.google.common.collect.Sets;
/**
* Provides IntefaceService using PortAddresses data from the HostService.
*/
public class HostServiceBasedInterfaceService implements InterfaceService {
private final HostService hostService;
public HostServiceBasedInterfaceService(HostService hostService) {
this.hostService = checkNotNull(hostService);
}
@Override
public Set<Interface> getInterfaces() {
Set<PortAddresses> addresses = hostService.getAddressBindings();
Set<Interface> interfaces = Sets.newHashSetWithExpectedSize(addresses.size());
for (PortAddresses a : addresses) {
interfaces.add(new Interface(a));
}
return interfaces;
}
@Override
public Interface getInterface(ConnectPoint connectPoint) {
checkNotNull(connectPoint);
PortAddresses portAddresses =
hostService.getAddressBindingsForPort(connectPoint);
if (!portAddresses.ips().isEmpty()) {
return new Interface(portAddresses);
}
return null;
}
@Override
public Interface getMatchingInterface(IpAddress ipAddress) {
// TODO implement
throw new NotImplementedException("getMatchingInteface is not yet implemented");
}
}

View File

@ -0,0 +1,37 @@
package org.onlab.onos.sdnip;
import java.util.Set;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.sdnip.config.Interface;
import org.onlab.packet.IpAddress;
/**
* Provides information about the interfaces in the network.
*/
public interface InterfaceService {
/**
* Retrieves the entire set of interfaces in the network.
*
* @return the set of interfaces
*/
Set<Interface> getInterfaces();
/**
* Retrieves the interface associated with the given connect point.
*
* @param connectPoint the connect point to retrieve interface information
* for
* @return the interface
*/
Interface getInterface(ConnectPoint connectPoint);
/**
* Retrieves the interface that matches the given IP address. Matching
* means that the IP address is in one of the interface's assigned subnets.
*
* @param ipAddress IP address to match
* @return the matching interface
*/
Interface getMatchingInterface(IpAddress ipAddress);
}

View File

@ -0,0 +1,343 @@
package org.onlab.onos.sdnip;
import java.util.List;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.sdnip.config.BgpPeer;
import org.onlab.onos.sdnip.config.BgpSpeaker;
import org.onlab.onos.sdnip.config.Interface;
import org.onlab.onos.sdnip.config.InterfaceAddress;
import org.onlab.onos.sdnip.config.SdnIpConfigService;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages the connectivity requirements between peers.
*/
public class PeerConnectivity {
private static final Logger log = LoggerFactory.getLogger(
PeerConnectivity.class);
// TODO these shouldn't be defined here
private static final short BGP_PORT = 179;
private static final int IPV4_BIT_LENGTH = 32;
private final SdnIpConfigService configInfoService;
private final InterfaceService interfaceService;
private final IntentService intentService;
// TODO this sucks.
private int intentId = 0;
public PeerConnectivity(SdnIpConfigService configInfoService,
InterfaceService interfaceService, IntentService intentService) {
this.configInfoService = configInfoService;
this.interfaceService = interfaceService;
this.intentService = intentService;
}
public void start() {
// TODO are any of these errors?
if (interfaceService.getInterfaces().isEmpty()) {
log.warn("The interface in configuration file is empty. "
+ "Thus, the SDN-IP application can not be started.");
} else if (configInfoService.getBgpPeers().isEmpty()) {
log.warn("The BGP peer in configuration file is empty."
+ "Thus, the SDN-IP application can not be started.");
} else if (configInfoService.getBgpSpeakers() == null) {
log.error("The BGP speaker in configuration file is empty. "
+ "Thus, the SDN-IP application can not be started.");
return;
}
setupBgpPaths();
setupIcmpPaths();
}
/**
* Sets up paths for all {@link BgpSpeaker}s and all external peers.
* <p/>
* Run a loop for all BGP speakers and a loop for all BGP peers outside.
* Push intents for paths from each BGP speaker to all peers. Push intents
* for paths from all peers to each BGP speaker.
*/
private void setupBgpPaths() {
for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers()
.values()) {
log.debug("Start to set up BGP paths for BGP speaker: {}",
bgpSpeaker);
ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
List<InterfaceAddress> interfaceAddresses =
bgpSpeaker.interfaceAddresses();
for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) {
log.debug("Start to set up BGP paths between BGP speaker: {} "
+ "to BGP peer: {}", bgpSpeaker, bgpPeer);
Interface peerInterface = interfaceService.getInterface(
bgpPeer.connectPoint());
if (peerInterface == null) {
log.error("Can not find the corresponding Interface from "
+ "configuration for BGP peer {}",
bgpPeer.ipAddress());
continue;
}
IpAddress bgpdAddress = null;
for (InterfaceAddress interfaceAddress : interfaceAddresses) {
if (interfaceAddress.connectPoint().equals(
peerInterface.connectPoint())) {
bgpdAddress = interfaceAddress.ipAddress();
break;
}
}
if (bgpdAddress == null) {
log.debug("There is no interface IP address for bgpPeer: {}"
+ " on interface {}", bgpPeer, bgpPeer.connectPoint());
return;
}
IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
// install intent for BGP path from BGPd to BGP peer matching
// destination TCP port 179
// TODO: The usage of PacketMatchBuilder will be improved, then we
// only need to new the PacketMatchBuilder once.
// By then, the code here will be improved accordingly.
/*PacketMatch packetMatch = new PacketMatchBuilder().setEtherType(
Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_TCP)
.setSrcIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstTcpPort(BGP_PORT)
.build();
*/
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_TCP)
.matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchTcpDst(BGP_PORT)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.build();
PointToPointIntent intentMatchDstTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intentMatchDstTcpPort);
log.debug("Submitted BGP path intent matching dst TCP port 179 "
+ "from BGPd {} to peer {}: {}",
bgpdAddress, bgpdPeerAddress, intentMatchDstTcpPort);
// install intent for BGP path from BGPd to BGP peer matching
// source TCP port 179
/*packetMatch = new PacketMatchBuilder().setEtherType(Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_TCP)
.setSrcIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.setSrcTcpPort(BGP_PORT)
.build();*/
selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_TCP)
.matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchTcpSrc(BGP_PORT)
.build();
PointToPointIntent intentMatchSrcTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intentMatchSrcTcpPort);
log.debug("Submitted BGP path intent matching src TCP port 179"
+ "from BGPd {} to peer {}: {}",
bgpdAddress, bgpdPeerAddress, intentMatchSrcTcpPort);
// install intent for reversed BGP path from BGP peer to BGPd
// matching destination TCP port 179
/*packetMatch = new PacketMatchBuilder().setEtherType(Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_TCP)
.setSrcIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstTcpPort(BGP_PORT)
.build();*/
selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_TCP)
.matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchTcpDst(BGP_PORT)
.build();
PointToPointIntent reversedIntentMatchDstTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntentMatchDstTcpPort);
log.debug("Submitted BGP path intent matching dst TCP port 179"
+ "from BGP peer {} to BGPd {} : {}",
bgpdPeerAddress, bgpdAddress, reversedIntentMatchDstTcpPort);
// install intent for reversed BGP path from BGP peer to BGPd
// matching source TCP port 179
/*packetMatch = new PacketMatchBuilder().setEtherType(Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_TCP)
.setSrcIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.setSrcTcpPort(BGP_PORT)
.build();*/
selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_TCP)
.matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchTcpSrc(BGP_PORT)
.build();
PointToPointIntent reversedIntentMatchSrcTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntentMatchSrcTcpPort);
log.debug("Submitted BGP path intent matching src TCP port 179"
+ "from BGP peer {} to BGPd {} : {}",
bgpdPeerAddress, bgpdAddress, reversedIntentMatchSrcTcpPort);
}
}
}
/**
* Sets up ICMP paths between each {@link BgpSpeaker} and all BGP peers
* located in other external networks.
* <p/>
* Run a loop for all BGP speakers and a loop for all BGP Peers. Push
* intents for paths from each BGP speaker to all peers. Push intents
* for paths from all peers to each BGP speaker.
*/
private void setupIcmpPaths() {
for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers()
.values()) {
log.debug("Start to set up ICMP paths for BGP speaker: {}",
bgpSpeaker);
ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
List<InterfaceAddress> interfaceAddresses = bgpSpeaker
.interfaceAddresses();
for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) {
Interface peerInterface = interfaceService.getInterface(
bgpPeer.connectPoint());
if (peerInterface == null) {
log.error("Can not find the corresponding Interface from "
+ "configuration for BGP peer {}",
bgpPeer.ipAddress());
continue;
}
IpAddress bgpdAddress = null;
for (InterfaceAddress interfaceAddress : interfaceAddresses) {
if (interfaceAddress.connectPoint().equals(
peerInterface.connectPoint())) {
bgpdAddress = interfaceAddress.ipAddress();
break;
}
}
if (bgpdAddress == null) {
log.debug("There is no IP address for bgpPeer: {} on "
+ "interface port: {}", bgpPeer,
bgpPeer.connectPoint());
return;
}
IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
// install intent for ICMP path from BGPd to BGP peer
/*PacketMatch packetMatch =
new PacketMatchBuilder().setEtherType(
Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_ICMP)
.setSrcIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.build();*/
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_ICMP)
.matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.build();
PointToPointIntent intent = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intent);
log.debug("Submitted ICMP path intent from BGPd {} to peer {} :"
+ " {}", bgpdAddress, bgpdPeerAddress, intent);
// install intent for reversed ICMP path from BGP peer to BGPd
/*packetMatch = new PacketMatchBuilder().setEtherType(
Ethernet.TYPE_IPV4)
.setIpProto(PROTOCOL_ICMP)
.setSrcIpNet(new Ip4Prefix(bgpdPeerAddress,
(short) Ip4Address.BIT_LENGTH))
.setDstIpNet(new Ip4Prefix(bgpdAddress,
(short) Ip4Address.BIT_LENGTH))
.build();*/
selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_ICMP)
.matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
.matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
.build();
PointToPointIntent reversedIntent = new PointToPointIntent(
nextIntentId(), selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntent);
log.debug("Submitted ICMP path intent from BGP peer {} to BGPd"
+ " {} : {}",
bgpdPeerAddress, bgpdAddress, reversedIntent);
}
}
}
private IntentId nextIntentId() {
return new IntentId(intentId++);
}
}

View File

@ -5,6 +5,10 @@ import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.sdnip.config.SdnIpConfigReader; import org.onlab.onos.sdnip.config.SdnIpConfigReader;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -16,7 +20,14 @@ public class SdnIp {
private final Logger log = getLogger(getClass()); private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
private SdnIpConfigReader config; private SdnIpConfigReader config;
private PeerConnectivity peerConnectivity;
@Activate @Activate
protected void activate() { protected void activate() {
@ -24,6 +35,12 @@ public class SdnIp {
config = new SdnIpConfigReader(); config = new SdnIpConfigReader();
config.init(); config.init();
InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService);
peerConnectivity = new PeerConnectivity(config, interfaceService, intentService);
peerConnectivity.start();
} }
@Deactivate @Deactivate

View File

@ -8,19 +8,20 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber; import org.onlab.onos.net.PortNumber;
import org.onlab.packet.IpAddress; import org.onlab.packet.IpAddress;
import com.google.common.base.MoreObjects;
/** /**
* Configuration details for a BGP peer. It contains the peer's IP address and * Configuration details for a BGP peer.
* an interface name which maps to the interface they are attached at.
*/ */
public class BgpPeer { public class BgpPeer {
private final ConnectPoint connectPoint; private final ConnectPoint connectPoint;
private final IpAddress ipAddress; private final IpAddress ipAddress;
/** /**
* Class constructor, taking the interface name and IP address of the peer. * Creates a new BgpPeer.
* *
* @param interfaceName the String name of the interface which can be used * @param dpid the DPID of the switch the peer is attached at, as a String
* to look up the interface this peer is attached at * @param port the port the peer is attached at
* @param ipAddress the IP address of the peer as a String * @param ipAddress the IP address of the peer as a String
*/ */
public BgpPeer(@JsonProperty("attachmentDpid") String dpid, public BgpPeer(@JsonProperty("attachmentDpid") String dpid,
@ -37,7 +38,7 @@ public class BgpPeer {
* *
* @return the connection point * @return the connection point
*/ */
public ConnectPoint getConnectPoint() { public ConnectPoint connectPoint() {
return connectPoint; return connectPoint;
} }
@ -46,7 +47,7 @@ public class BgpPeer {
* *
* @return the IP address * @return the IP address
*/ */
public IpAddress getIpAddress() { public IpAddress ipAddress() {
return ipAddress; return ipAddress;
} }
@ -69,4 +70,12 @@ public class BgpPeer {
return Objects.equals(this.connectPoint, that.connectPoint) return Objects.equals(this.connectPoint, that.connectPoint)
&& Objects.equals(this.ipAddress, that.ipAddress); && Objects.equals(this.ipAddress, that.ipAddress);
} }
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("connectPoint", connectPoint)
.add("ipAddress", ipAddress)
.toString();
}
} }

View File

@ -10,6 +10,8 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber; import org.onlab.onos.net.PortNumber;
import org.onlab.packet.MacAddress; import org.onlab.packet.MacAddress;
import com.google.common.base.MoreObjects;
/** /**
* Represents a BGP daemon in SDN network. * Represents a BGP daemon in SDN network.
* <p/> * <p/>
@ -23,28 +25,28 @@ import org.onlab.packet.MacAddress;
* used to reference this speaker in the configuration. * used to reference this speaker in the configuration.
*/ */
public class BgpSpeaker { public class BgpSpeaker {
private final String speakerName; private final String name;
private final ConnectPoint attachmentSwitchPort; private final ConnectPoint connectPoint;
private final MacAddress macAddress; private final MacAddress macAddress;
private List<InterfaceAddress> interfaceAddresses; private List<InterfaceAddress> interfaceAddresses;
/** /**
* Class constructor used by the JSON library to create an object. * Class constructor used by the JSON library to create an object.
* *
* @param speakerName the name of the BGP router inside SDN network * @param name the name of the BGP speaker inside SDN network
* @param attachmentDpid the DPID where the BGP router is attached to * @param attachmentDpid the DPID where the BGP speaker is attached to
* @param attachmentPort the port where the BGP router is attached to * @param attachmentPort the port where the BGP speaker is attached to
* @param macAddress the MAC address of the BGP router * @param macAddress the MAC address of the BGP speaker
*/ */
@JsonCreator @JsonCreator
public BgpSpeaker(@JsonProperty("name") String speakerName, public BgpSpeaker(@JsonProperty("name") String name,
@JsonProperty("attachmentDpid") String attachmentDpid, @JsonProperty("attachmentDpid") String attachmentDpid,
@JsonProperty("attachmentPort") int attachmentPort, @JsonProperty("attachmentPort") int attachmentPort,
@JsonProperty("macAddress") String macAddress) { @JsonProperty("macAddress") String macAddress) {
this.speakerName = speakerName; this.name = name;
this.macAddress = MacAddress.valueOf(macAddress); this.macAddress = MacAddress.valueOf(macAddress);
this.attachmentSwitchPort = new ConnectPoint( this.connectPoint = new ConnectPoint(
DeviceId.deviceId(SdnIpConfigReader.dpidToUri(attachmentDpid)), DeviceId.deviceId(SdnIpConfigReader.dpidToUri(attachmentDpid)),
PortNumber.portNumber(attachmentPort)); PortNumber.portNumber(attachmentPort));
} }
@ -67,25 +69,25 @@ public class BgpSpeaker {
* *
* @return the BGP speaker name * @return the BGP speaker name
*/ */
public String getSpeakerName() { public String name() {
return speakerName; return name;
} }
/** /**
* Gets the switch port where the BGP speaker is attached. * Gets the connect point where the BGP speaker is attached.
* *
* @return the switch port where the BGP speaker is attached * @return the connect point
*/ */
public ConnectPoint getAttachmentSwitchPort() { public ConnectPoint connectPoint() {
return attachmentSwitchPort; return connectPoint;
} }
/** /**
* Gets the MAC address of the BGP speaker. * Gets the MAC address of the BGP speaker.
* *
* @return the MAC address of the BGP speaker * @return the MAC address
*/ */
public MacAddress getMacAddress() { public MacAddress macAddress() {
return macAddress; return macAddress;
} }
@ -96,7 +98,7 @@ public class BgpSpeaker {
* @return a list of IP addresses of the BGP speaker configured on all * @return a list of IP addresses of the BGP speaker configured on all
* virtual interfaces * virtual interfaces
*/ */
public List<InterfaceAddress> getInterfaceAddresses() { public List<InterfaceAddress> interfaceAddresses() {
return interfaceAddresses; return interfaceAddresses;
} }
@ -108,17 +110,27 @@ public class BgpSpeaker {
BgpSpeaker otherBgpSpeaker = (BgpSpeaker) other; BgpSpeaker otherBgpSpeaker = (BgpSpeaker) other;
return speakerName.equals(otherBgpSpeaker.speakerName) && return name.equals(otherBgpSpeaker.name) &&
attachmentSwitchPort.equals( connectPoint.equals(
otherBgpSpeaker.attachmentSwitchPort) && otherBgpSpeaker.connectPoint) &&
macAddress.equals(otherBgpSpeaker.macAddress) && macAddress.equals(otherBgpSpeaker.macAddress) &&
interfaceAddresses.equals(otherBgpSpeaker.interfaceAddresses); interfaceAddresses.equals(otherBgpSpeaker.interfaceAddresses);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(speakerName, attachmentSwitchPort, macAddress, return Objects.hash(name, connectPoint, macAddress,
interfaceAddresses); interfaceAddresses);
} }
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("speakerName", name)
.add("connectPoint", connectPoint)
.add("macAddress", macAddress)
.add("interfaceAddresses", interfaceAddresses)
.toString();
}
} }

View File

@ -1,86 +1,78 @@
package org.onlab.onos.sdnip.config; package org.onlab.onos.sdnip.config;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
import org.onlab.onos.net.ConnectPoint; import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId; import org.onlab.onos.net.host.PortAddresses;
import org.onlab.onos.net.PortNumber;
import org.onlab.packet.IpPrefix; import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
/** /**
* Represents an interface, which is an external-facing switch port that * An Interface is a set of addresses that are logically mapped to a switch
* connects to another network. * port in the 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 { public class Interface {
private final String name; private final ConnectPoint connectPoint;
private final ConnectPoint switchPort; private final Set<IpPrefix> ipAddresses;
private final IpPrefix ip4Prefix; private final MacAddress macAddress;
/** /**
* Class constructor used by the JSON library to create an object. * Creates an Interface based on a connection point, a set of IP addresses
* and a MAC address.
* *
* @param name the name of the interface * @param connectPoint the connect point this interface is mapped to
* @param dpid the dpid of the switch * @param prefixAddress the IP addresses for the interface
* @param port the port on the switch * @param macAddress the MAC address of the interface
* @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(ConnectPoint connectPoint, Set<IpPrefix> prefixAddress,
public Interface(@JsonProperty("name") String name, MacAddress macAddress) {
@JsonProperty("dpid") String dpid, this.connectPoint = connectPoint;
@JsonProperty("port") int port, this.ipAddresses = Sets.newHashSet(prefixAddress);
@JsonProperty("ipAddress") String prefixAddress, this.macAddress = macAddress;
@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. * Creates an Interface based on a PortAddresses object.
* *
* @return the name of the interface * @param portAddresses the PortAddresses object to turn into an Interface
*/ */
public String getName() { public Interface(PortAddresses portAddresses) {
return name; connectPoint = portAddresses.connectPoint();
ipAddresses = Sets.newHashSet(portAddresses.ips());
macAddress = portAddresses.mac();
} }
/** /**
* Gets the {@link SwitchPort} that this interface maps to. * Retrieves the connection point that this interface maps to.
* *
* @return the switch port * @return the connection point
*/ */
public ConnectPoint getSwitchPort() { public ConnectPoint connectPoint() {
return switchPort; return connectPoint;
} }
/** /**
* Gets the IP prefix of the subnetwork which is logically assigned * Retrieves the set of IP addresses that are assigned to the interface.
* to the switch port.
* *
* @return the IP prefix * @return the set of IP addresses
*/ */
public IpPrefix getIp4Prefix() { public Set<IpPrefix> ips() {
return ip4Prefix; return ipAddresses;
} }
/**
* Retrieves the MAC address that is assigned to the interface.
*
* @return the MAC address
*/
public MacAddress mac() {
return macAddress;
}
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof Interface)) { if (!(other instanceof Interface)) {
@ -89,13 +81,22 @@ public class Interface {
Interface otherInterface = (Interface) other; Interface otherInterface = (Interface) other;
return name.equals(otherInterface.name) && return connectPoint.equals(otherInterface.connectPoint) &&
switchPort.equals(otherInterface.switchPort) && ipAddresses.equals(otherInterface.ipAddresses) &&
ip4Prefix.equals(otherInterface.ip4Prefix); macAddress.equals(otherInterface.macAddress);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(name, switchPort, ip4Prefix); return Objects.hash(connectPoint, ipAddresses, macAddress);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("connectPoint", connectPoint)
.add("ipAddresses", ipAddresses)
.add("macAddress", macAddress)
.toString();
} }
} }

View File

@ -8,6 +8,8 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber; import org.onlab.onos.net.PortNumber;
import org.onlab.packet.IpAddress; import org.onlab.packet.IpAddress;
import com.google.common.base.MoreObjects;
/** /**
* Represents an address of a {@link BgpSpeaker} configured on an * Represents an address of a {@link BgpSpeaker} configured on an
* {@link Interface}. * {@link Interface}.
@ -19,10 +21,10 @@ public class InterfaceAddress {
private final IpAddress ipAddress; private final IpAddress ipAddress;
/** /**
* Class constructor used by the JSON library to create an object. * Creates an InterfaceAddress object.
* *
* @param interfaceName the interface name for which an IP address of a BGP * @param dpid the DPID of the interface as a String
* router is configured * @param port the port of the interface
* @param ipAddress the IP address of a {@link BgpSpeaker} configured on * @param ipAddress the IP address of a {@link BgpSpeaker} configured on
* the interface * the interface
*/ */
@ -40,7 +42,7 @@ public class InterfaceAddress {
* *
* @return the connection point * @return the connection point
*/ */
public ConnectPoint getConnectPoint() { public ConnectPoint connectPoint() {
return connectPoint; return connectPoint;
} }
@ -49,7 +51,7 @@ public class InterfaceAddress {
* *
* @return the IP address * @return the IP address
*/ */
public IpAddress getIpAddress() { public IpAddress ipAddress() {
return ipAddress; return ipAddress;
} }
@ -72,4 +74,12 @@ public class InterfaceAddress {
return Objects.equals(this.connectPoint, that.connectPoint) return Objects.equals(this.connectPoint, that.connectPoint)
&& Objects.equals(this.ipAddress, that.ipAddress); && Objects.equals(this.ipAddress, that.ipAddress);
} }
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("connectPoint", connectPoint)
.add("ipAddress", ipAddress)
.toString();
}
} }

View File

@ -50,11 +50,11 @@ public class SdnIpConfigReader implements SdnIpConfigService {
}*/ }*/
bgpSpeakers = new ConcurrentHashMap<>(); bgpSpeakers = new ConcurrentHashMap<>();
for (BgpSpeaker speaker : config.getBgpSpeakers()) { for (BgpSpeaker speaker : config.getBgpSpeakers()) {
bgpSpeakers.put(speaker.getSpeakerName(), speaker); bgpSpeakers.put(speaker.name(), speaker);
} }
bgpPeers = new ConcurrentHashMap<>(); bgpPeers = new ConcurrentHashMap<>();
for (BgpPeer peer : config.getPeers()) { for (BgpPeer peer : config.getPeers()) {
bgpPeers.put(peer.getIpAddress(), peer); bgpPeers.put(peer.ipAddress(), peer);
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Error reading JSON file", e); log.error("Error reading JSON file", e);

View File

@ -161,10 +161,10 @@ public class FlowModBuilder {
switch (l3m.subtype()) { switch (l3m.subtype()) {
case IP_DST: case IP_DST:
ip = (ModIPInstruction) i; ip = (ModIPInstruction) i;
return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt())); return factory.actions().setNwDst(IPv4Address.of(ip.ip().toRealInt()));
case IP_SRC: case IP_SRC:
ip = (ModIPInstruction) i; ip = (ModIPInstruction) i;
return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt())); return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toRealInt()));
default: default:
log.warn("Unimplemented action type {}.", l3m.subtype()); log.warn("Unimplemented action type {}.", l3m.subtype());
break; break;
@ -220,21 +220,21 @@ public class FlowModBuilder {
case IPV4_DST: case IPV4_DST:
ip = (IPCriterion) c; ip = (IPCriterion) c;
if (ip.ip().isMasked()) { if (ip.ip().isMasked()) {
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()), Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
IPv4Address.of(ip.ip().netmask().toInt())); IPv4Address.of(ip.ip().netmask().toRealInt()));
mBuilder.setMasked(MatchField.IPV4_DST, maskedIp); mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
} else { } else {
mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt())); mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toRealInt()));
} }
break; break;
case IPV4_SRC: case IPV4_SRC:
ip = (IPCriterion) c; ip = (IPCriterion) c;
if (ip.ip().isMasked()) { if (ip.ip().isMasked()) {
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()), Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
IPv4Address.of(ip.ip().netmask().toInt())); IPv4Address.of(ip.ip().netmask().toRealInt()));
mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp); mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
} else { } else {
mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt())); mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toRealInt()));
} }
break; break;
case IP_PROTO: case IP_PROTO:

View File

@ -181,6 +181,15 @@ public final class IpAddress {
return address; return address;
} }
public int toRealInt() {
int val = 0;
for (int i = 0; i < octets.length; i++) {
val <<= 8;
val |= octets[i] & 0xff;
}
return val;
}
/** /**
* Helper for computing the mask value from CIDR. * Helper for computing the mask value from CIDR.
* *