diff options
Diffstat (limited to 'framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java')
-rw-r--r-- | framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java new file mode 100644 index 00000000..459db2b7 --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java @@ -0,0 +1,319 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sdnip; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv4; +import org.onlab.packet.IPv6; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onlab.packet.TpPort; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.intf.InterfaceService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.host.InterfaceIpAddress; +import org.onosproject.net.intent.PointToPointIntent; +import org.onosproject.routing.RoutingService; +import org.onosproject.routing.config.BgpConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Manages the connectivity requirements between peers. + */ +public class PeerConnectivityManager { + private static final int PRIORITY_OFFSET = 1000; + + private static final Logger log = LoggerFactory.getLogger( + PeerConnectivityManager.class); + + private static final short BGP_PORT = 179; + + private final IntentSynchronizer intentSynchronizer; + private final NetworkConfigService configService; + private final InterfaceService interfaceService; + + private final ApplicationId appId; + private final ApplicationId routerAppId; + + /** + * Creates a new PeerConnectivityManager. + * + * @param appId the application ID + * @param intentSynchronizer the intent synchronizer + * @param configService the SDN-IP config service + * @param interfaceService the interface service + * @param routerAppId application ID + */ + public PeerConnectivityManager(ApplicationId appId, + IntentSynchronizer intentSynchronizer, + NetworkConfigService configService, + ApplicationId routerAppId, + InterfaceService interfaceService) { + this.appId = appId; + this.intentSynchronizer = intentSynchronizer; + this.configService = configService; + this.routerAppId = routerAppId; + this.interfaceService = interfaceService; + } + + /** + * Starts the peer connectivity manager. + */ + public void start() { + setUpConnectivity(); + } + + /** + * Stops the peer connectivity manager. + */ + public void stop() { + } + + /** + * Sets up paths to establish connectivity between all internal + * BGP speakers and external BGP peers. + */ + private void setUpConnectivity() { + List<PointToPointIntent> intents = new ArrayList<>(); + + BgpConfig config = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS); + + if (config == null) { + log.warn("No BgpConfig found"); + return; + } + + for (BgpConfig.BgpSpeakerConfig bgpSpeaker : config.bgpSpeakers()) { + log.debug("Start to set up BGP paths for BGP speaker: {}", + bgpSpeaker); + + intents.addAll(buildSpeakerIntents(bgpSpeaker)); + } + + // Submit all the intents. + intentSynchronizer.submitPeerIntents(intents); + } + + private Collection<PointToPointIntent> buildSpeakerIntents(BgpConfig.BgpSpeakerConfig speaker) { + List<PointToPointIntent> intents = new ArrayList<>(); + + for (IpAddress peerAddress : speaker.peers()) { + Interface peeringInterface = interfaceService.getMatchingInterface(peerAddress); + + if (peeringInterface == null) { + log.debug("No peering interface found for peer {} on speaker {}", + peerAddress, speaker); + continue; + } + + IpAddress peeringAddress = null; + for (InterfaceIpAddress address : peeringInterface.ipAddresses()) { + if (address.subnetAddress().contains(peerAddress)) { + peeringAddress = address.ipAddress(); + break; + } + } + + checkNotNull(peeringAddress); + + intents.addAll(buildIntents(speaker.connectPoint(), peeringAddress, + peeringInterface.connectPoint(), peerAddress)); + } + + return intents; + } + + /** + * Builds the required intents between the two pairs of connect points and + * IP addresses. + * + * @param portOne the first connect point + * @param ipOne the first IP address + * @param portTwo the second connect point + * @param ipTwo the second IP address + * @return the intents to install + */ + private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne, + IpAddress ipOne, + ConnectPoint portTwo, + IpAddress ipTwo) { + + List<PointToPointIntent> intents = new ArrayList<>(); + + TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment(); + + TrafficSelector selector; + + byte tcpProtocol; + byte icmpProtocol; + + if (ipOne.isIp4()) { + tcpProtocol = IPv4.PROTOCOL_TCP; + icmpProtocol = IPv4.PROTOCOL_ICMP; + } else { + tcpProtocol = IPv6.PROTOCOL_TCP; + icmpProtocol = IPv6.PROTOCOL_ICMP6; + } + + // Path from BGP speaker to BGP peer matching destination TCP port 179 + selector = buildSelector(tcpProtocol, + ipOne, + ipTwo, + null, + BGP_PORT); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portOne) + .egressPoint(portTwo) + .priority(PRIORITY_OFFSET) + .build()); + + // Path from BGP speaker to BGP peer matching source TCP port 179 + selector = buildSelector(tcpProtocol, + ipOne, + ipTwo, + BGP_PORT, + null); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portOne) + .egressPoint(portTwo) + .priority(PRIORITY_OFFSET) + .build()); + + // Path from BGP peer to BGP speaker matching destination TCP port 179 + selector = buildSelector(tcpProtocol, + ipTwo, + ipOne, + null, + BGP_PORT); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portTwo) + .egressPoint(portOne) + .priority(PRIORITY_OFFSET) + .build()); + + // Path from BGP peer to BGP speaker matching source TCP port 179 + selector = buildSelector(tcpProtocol, + ipTwo, + ipOne, + BGP_PORT, + null); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portTwo) + .egressPoint(portOne) + .priority(PRIORITY_OFFSET) + .build()); + + // ICMP path from BGP speaker to BGP peer + selector = buildSelector(icmpProtocol, + ipOne, + ipTwo, + null, + null); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portOne) + .egressPoint(portTwo) + .priority(PRIORITY_OFFSET) + .build()); + + // ICMP path from BGP peer to BGP speaker + selector = buildSelector(icmpProtocol, + ipTwo, + ipOne, + null, + null); + + intents.add(PointToPointIntent.builder() + .appId(appId) + .selector(selector) + .treatment(treatment) + .ingressPoint(portTwo) + .egressPoint(portOne) + .priority(PRIORITY_OFFSET) + .build()); + + return intents; + } + + /** + * Builds a traffic selector based on the set of input parameters. + * + * @param ipProto IP protocol + * @param srcIp source IP address + * @param dstIp destination IP address + * @param srcTcpPort source TCP port, or null if shouldn't be set + * @param dstTcpPort destination TCP port, or null if shouldn't be set + * @return the new traffic selector + */ + private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp, + IpAddress dstIp, Short srcTcpPort, + Short dstTcpPort) { + TrafficSelector.Builder builder = DefaultTrafficSelector.builder() + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(ipProto); + + if (dstIp.isIp4()) { + builder.matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH)) + .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH)); + } else { + builder.matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH)) + .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH)); + } + + if (srcTcpPort != null) { + builder.matchTcpSrc(TpPort.tpPort(srcTcpPort)); + } + + if (dstTcpPort != null) { + builder.matchTcpDst(TpPort.tpPort(dstTcpPort)); + } + + return builder.build(); + } + +} |