diff --git a/apps/sdnip/pom.xml b/apps/sdnip/pom.xml index 99960a4fdb..c8db20d7ac 100644 --- a/apps/sdnip/pom.xml +++ b/apps/sdnip/pom.xml @@ -2,35 +2,40 @@ - 4.0.0 + 4.0.0 - - org.onlab.onos - onos-apps - 1.0.0-SNAPSHOT - ../pom.xml - + + org.onlab.onos + onos-apps + 1.0.0-SNAPSHOT + ../pom.xml + - onos-app-sdnip - bundle + onos-app-sdnip + bundle - SDN-IP peering application + SDN-IP peering application - - - org.codehaus.jackson - jackson-core-asl - - - org.codehaus.jackson - jackson-mapper-asl - - - com.fasterxml.jackson.core - jackson-annotations - 2.4.2 - provided - - + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-mapper-asl + + + com.fasterxml.jackson.core + jackson-annotations + 2.4.2 + provided + + + + com.google.guava + guava + + diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/HostServiceBasedInterfaceService.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/HostServiceBasedInterfaceService.java new file mode 100644 index 0000000000..d6ad3c404c --- /dev/null +++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/HostServiceBasedInterfaceService.java @@ -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 getInterfaces() { + Set addresses = hostService.getAddressBindings(); + Set 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"); + } + +} diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/InterfaceService.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/InterfaceService.java new file mode 100644 index 0000000000..f9e881f321 --- /dev/null +++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/InterfaceService.java @@ -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 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); +} diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivity.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivity.java new file mode 100644 index 0000000000..75ffd98cc6 --- /dev/null +++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivity.java @@ -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. + *

+ * 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 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. + *

+ * 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 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++); + } +} diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/SdnIp.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/SdnIp.java index a15faefec4..25b13f1ca4 100644 --- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/SdnIp.java +++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/SdnIp.java @@ -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 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 index 9d014d05c1..3e89c5864b 100644 --- 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 @@ -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(); + } } 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 index c7c2edd0de..248fc1d7c5 100644 --- 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 @@ -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. *

@@ -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 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 getInterfaceAddresses() { + public List 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(); + } } 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 index 33287addaf..88de952581 100644 --- 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 @@ -1,86 +1,78 @@ 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. - *

- * 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. - *

- * 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 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 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 ips() { + return ipAddresses; } + /** + * Retrieves the MAC address that is assigned to the interface. + * + * @return the MAC address + */ + public MacAddress mac() { + return macAddress; + } + @Override public boolean equals(Object other) { if (!(other instanceof Interface)) { @@ -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(); } } 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 index 4b423a78b8..1ae204f3b8 100644 --- 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 @@ -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(); + } } 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 index f98cd15159..50034ed540 100644 --- 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 @@ -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); diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java index 9568f1f8ba..c1c56c3196 100644 --- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java +++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java @@ -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 maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()), - IPv4Address.of(ip.ip().netmask().toInt())); + Masked 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 maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()), - IPv4Address.of(ip.ip().netmask().toInt())); + Masked 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: diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java index 44a018e044..fef0cfdf10 100644 --- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java +++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java @@ -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. *