Jonathan Hart

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

construct Interface objects based on PortAddresses from HostService.
......@@ -31,6 +31,11 @@
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>
......
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");
}
}
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);
}
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++);
}
}
......@@ -5,6 +5,10 @@ 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.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.slf4j.Logger;
......@@ -16,7 +20,14 @@ public class SdnIp {
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 PeerConnectivity peerConnectivity;
@Activate
protected void activate() {
......@@ -24,6 +35,12 @@ public class SdnIp {
config = new SdnIpConfigReader();
config.init();
InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService);
peerConnectivity = new PeerConnectivity(config, interfaceService, intentService);
peerConnectivity.start();
}
@Deactivate
......
......@@ -8,19 +8,20 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
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
* an interface name which maps to the interface they are attached at.
* Configuration details for a BGP peer.
*/
public class BgpPeer {
private final ConnectPoint connectPoint;
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
* to look up the interface this peer is attached at
* @param dpid the DPID of the switch the peer is attached at, as a String
* @param port the port the peer is attached at
* @param ipAddress the IP address of the peer as a String
*/
public BgpPeer(@JsonProperty("attachmentDpid") String dpid,
......@@ -37,7 +38,7 @@ public class BgpPeer {
*
* @return the connection point
*/
public ConnectPoint getConnectPoint() {
public ConnectPoint connectPoint() {
return connectPoint;
}
......@@ -46,7 +47,7 @@ public class BgpPeer {
*
* @return the IP address
*/
public IpAddress getIpAddress() {
public IpAddress ipAddress() {
return ipAddress;
}
......@@ -69,4 +70,12 @@ public class BgpPeer {
return Objects.equals(this.connectPoint, that.connectPoint)
&& Objects.equals(this.ipAddress, that.ipAddress);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("connectPoint", connectPoint)
.add("ipAddress", ipAddress)
.toString();
}
}
......
......@@ -10,6 +10,8 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.packet.MacAddress;
import com.google.common.base.MoreObjects;
/**
* Represents a BGP daemon in SDN network.
* <p/>
......@@ -23,28 +25,28 @@ import org.onlab.packet.MacAddress;
* used to reference this speaker in the configuration.
*/
public class BgpSpeaker {
private final String speakerName;
private final ConnectPoint attachmentSwitchPort;
private final String name;
private final ConnectPoint connectPoint;
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
* @param name the name of the BGP speaker inside SDN network
* @param attachmentDpid the DPID where the BGP speaker is attached to
* @param attachmentPort the port where the BGP speaker is attached to
* @param macAddress the MAC address of the BGP speaker
*/
@JsonCreator
public BgpSpeaker(@JsonProperty("name") String speakerName,
public BgpSpeaker(@JsonProperty("name") String name,
@JsonProperty("attachmentDpid") String attachmentDpid,
@JsonProperty("attachmentPort") int attachmentPort,
@JsonProperty("macAddress") String macAddress) {
this.speakerName = speakerName;
this.name = name;
this.macAddress = MacAddress.valueOf(macAddress);
this.attachmentSwitchPort = new ConnectPoint(
this.connectPoint = new ConnectPoint(
DeviceId.deviceId(SdnIpConfigReader.dpidToUri(attachmentDpid)),
PortNumber.portNumber(attachmentPort));
}
......@@ -67,25 +69,25 @@ public class BgpSpeaker {
*
* @return the BGP speaker name
*/
public String getSpeakerName() {
return speakerName;
public String name() {
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() {
return attachmentSwitchPort;
public ConnectPoint connectPoint() {
return connectPoint;
}
/**
* 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;
}
......@@ -96,7 +98,7 @@ public class BgpSpeaker {
* @return a list of IP addresses of the BGP speaker configured on all
* virtual interfaces
*/
public List<InterfaceAddress> getInterfaceAddresses() {
public List<InterfaceAddress> interfaceAddresses() {
return interfaceAddresses;
}
......@@ -108,17 +110,27 @@ public class BgpSpeaker {
BgpSpeaker otherBgpSpeaker = (BgpSpeaker) other;
return speakerName.equals(otherBgpSpeaker.speakerName) &&
attachmentSwitchPort.equals(
otherBgpSpeaker.attachmentSwitchPort) &&
return name.equals(otherBgpSpeaker.name) &&
connectPoint.equals(
otherBgpSpeaker.connectPoint) &&
macAddress.equals(otherBgpSpeaker.macAddress) &&
interfaceAddresses.equals(otherBgpSpeaker.interfaceAddresses);
}
@Override
public int hashCode() {
return Objects.hash(speakerName, attachmentSwitchPort, macAddress,
return Objects.hash(name, connectPoint, macAddress,
interfaceAddresses);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("speakerName", name)
.add("connectPoint", connectPoint)
.add("macAddress", macAddress)
.add("interfaceAddresses", interfaceAddresses)
.toString();
}
}
......
package org.onlab.onos.sdnip.config;
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.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.host.PortAddresses;
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
* 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}.
* An Interface is a set of addresses that are logically mapped to a switch
* port in the network.
*/
public class Interface {
private final String name;
private final ConnectPoint switchPort;
private final IpPrefix ip4Prefix;
private final ConnectPoint connectPoint;
private final Set<IpPrefix> ipAddresses;
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 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
* @param connectPoint the connect point this interface is mapped to
* @param prefixAddress the IP addresses for the interface
* @param macAddress the MAC address of the interface
*/
@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);
public Interface(ConnectPoint connectPoint, Set<IpPrefix> prefixAddress,
MacAddress macAddress) {
this.connectPoint = connectPoint;
this.ipAddresses = Sets.newHashSet(prefixAddress);
this.macAddress = macAddress;
}
/**
* 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() {
return name;
public Interface(PortAddresses portAddresses) {
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() {
return switchPort;
public ConnectPoint connectPoint() {
return connectPoint;
}
/**
* Gets the IP prefix of the subnetwork which is logically assigned
* to the switch port.
* Retrieves the set of IP addresses that are assigned to the interface.
*
* @return the IP prefix
* @return the set of IP addresses
*/
public IpPrefix getIp4Prefix() {
return ip4Prefix;
public Set<IpPrefix> ips() {
return ipAddresses;
}
/**
* Retrieves the MAC address that is assigned to the interface.
*
* @return the MAC address
*/
public MacAddress mac() {
return macAddress;
}
@Override
......@@ -89,13 +81,22 @@ public class Interface {
Interface otherInterface = (Interface) other;
return name.equals(otherInterface.name) &&
switchPort.equals(otherInterface.switchPort) &&
ip4Prefix.equals(otherInterface.ip4Prefix);
return connectPoint.equals(otherInterface.connectPoint) &&
ipAddresses.equals(otherInterface.ipAddresses) &&
macAddress.equals(otherInterface.macAddress);
}
@Override
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();
}
}
......
......@@ -8,6 +8,8 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.packet.IpAddress;
import com.google.common.base.MoreObjects;
/**
* Represents an address of a {@link BgpSpeaker} configured on an
* {@link Interface}.
......@@ -19,10 +21,10 @@ public class InterfaceAddress {
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
* router is configured
* @param dpid the DPID of the interface as a String
* @param port the port of the interface
* @param ipAddress the IP address of a {@link BgpSpeaker} configured on
* the interface
*/
......@@ -40,7 +42,7 @@ public class InterfaceAddress {
*
* @return the connection point
*/
public ConnectPoint getConnectPoint() {
public ConnectPoint connectPoint() {
return connectPoint;
}
......@@ -49,7 +51,7 @@ public class InterfaceAddress {
*
* @return the IP address
*/
public IpAddress getIpAddress() {
public IpAddress ipAddress() {
return ipAddress;
}
......@@ -72,4 +74,12 @@ public class InterfaceAddress {
return Objects.equals(this.connectPoint, that.connectPoint)
&& Objects.equals(this.ipAddress, that.ipAddress);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("connectPoint", connectPoint)
.add("ipAddress", ipAddress)
.toString();
}
}
......
......@@ -50,11 +50,11 @@ public class SdnIpConfigReader implements SdnIpConfigService {
}*/
bgpSpeakers = new ConcurrentHashMap<>();
for (BgpSpeaker speaker : config.getBgpSpeakers()) {
bgpSpeakers.put(speaker.getSpeakerName(), speaker);
bgpSpeakers.put(speaker.name(), speaker);
}
bgpPeers = new ConcurrentHashMap<>();
for (BgpPeer peer : config.getPeers()) {
bgpPeers.put(peer.getIpAddress(), peer);
bgpPeers.put(peer.ipAddress(), peer);
}
} catch (IOException e) {
log.error("Error reading JSON file", e);
......
......@@ -161,10 +161,10 @@ public class FlowModBuilder {
switch (l3m.subtype()) {
case IP_DST:
ip = (ModIPInstruction) i;
return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
return factory.actions().setNwDst(IPv4Address.of(ip.ip().toRealInt()));
case IP_SRC:
ip = (ModIPInstruction) i;
return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toRealInt()));
default:
log.warn("Unimplemented action type {}.", l3m.subtype());
break;
......@@ -220,21 +220,21 @@ public class FlowModBuilder {
case IPV4_DST:
ip = (IPCriterion) c;
if (ip.ip().isMasked()) {
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
IPv4Address.of(ip.ip().netmask().toInt()));
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
IPv4Address.of(ip.ip().netmask().toRealInt()));
mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
} else {
mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt()));
mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toRealInt()));
}
break;
case IPV4_SRC:
ip = (IPCriterion) c;
if (ip.ip().isMasked()) {
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
IPv4Address.of(ip.ip().netmask().toInt()));
Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
IPv4Address.of(ip.ip().netmask().toRealInt()));
mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
} else {
mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt()));
mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toRealInt()));
}
break;
case IP_PROTO:
......
......@@ -181,6 +181,15 @@ public final class IpAddress {
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.
*
......