Ported the unit tests for PeerConnectivityManager
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivityManager.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivityManager.java
new file mode 100644
index 0000000..3917f5a
--- /dev/null
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/PeerConnectivityManager.java
@@ -0,0 +1,290 @@
+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 PeerConnectivityManager {
+
+ private static final Logger log = LoggerFactory.getLogger(
+ PeerConnectivityManager.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 PeerConnectivityManager(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.
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), 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
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), 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
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), 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
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_TCP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), 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
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_ICMP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), 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
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPProtocol(IPv4.PROTOCOL_ICMP)
+ .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
+ .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), 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++);
+ }
+}