blob: 2fccbdcf8ef6f1701061e227f779ff3bf48b9b96 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Jonathan Hartdc711bd2014-10-15 11:24:23 -070016package org.onlab.onos.sdnip;
17
Jonathan Hart6ec68292014-11-14 15:09:30 -080018import java.util.ArrayList;
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080019import java.util.Collection;
Jonathan Hart31582d12014-10-22 13:52:41 -070020import java.util.List;
21
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070022import org.onlab.onos.core.ApplicationId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070023import org.onlab.onos.net.ConnectPoint;
24import org.onlab.onos.net.flow.DefaultTrafficSelector;
25import org.onlab.onos.net.flow.DefaultTrafficTreatment;
26import org.onlab.onos.net.flow.TrafficSelector;
27import org.onlab.onos.net.flow.TrafficTreatment;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070028import org.onlab.onos.net.intent.PointToPointIntent;
Jonathan Hart31582d12014-10-22 13:52:41 -070029import org.onlab.onos.sdnip.bgp.BgpConstants;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070030import org.onlab.onos.sdnip.config.BgpPeer;
31import org.onlab.onos.sdnip.config.BgpSpeaker;
32import org.onlab.onos.sdnip.config.Interface;
33import org.onlab.onos.sdnip.config.InterfaceAddress;
Jonathan Hart9965d772014-12-02 10:28:34 -080034import org.onlab.onos.sdnip.config.SdnIpConfigurationService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070035import org.onlab.packet.Ethernet;
36import org.onlab.packet.IPv4;
37import org.onlab.packet.IpAddress;
38import org.onlab.packet.IpPrefix;
39import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42/**
43 * Manages the connectivity requirements between peers.
44 */
Jonathan Hartce430a42014-10-16 20:44:29 -070045public class PeerConnectivityManager {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070046
47 private static final Logger log = LoggerFactory.getLogger(
Jonathan Hartce430a42014-10-16 20:44:29 -070048 PeerConnectivityManager.class);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070049
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080050 private final IntentSynchronizer intentSynchronizer;
Jonathan Hart9965d772014-12-02 10:28:34 -080051 private final SdnIpConfigurationService configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070052 private final InterfaceService interfaceService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070053
Thomas Vachuskab97cf282014-10-20 23:31:12 -070054 private final ApplicationId appId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070055
Jonathan Hart31582d12014-10-22 13:52:41 -070056 /**
57 * Creates a new PeerConnectivityManager.
58 *
59 * @param appId the application ID
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080060 * @param intentSynchronizer the intent synchronizer
Jonathan Hart31582d12014-10-22 13:52:41 -070061 * @param configService the SDN-IP config service
62 * @param interfaceService the interface service
Jonathan Hart31582d12014-10-22 13:52:41 -070063 */
Thomas Vachuskab97cf282014-10-20 23:31:12 -070064 public PeerConnectivityManager(ApplicationId appId,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080065 IntentSynchronizer intentSynchronizer,
Jonathan Hart9965d772014-12-02 10:28:34 -080066 SdnIpConfigurationService configService,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080067 InterfaceService interfaceService) {
Thomas Vachuskab97cf282014-10-20 23:31:12 -070068 this.appId = appId;
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080069 this.intentSynchronizer = intentSynchronizer;
Jonathan Hart31582d12014-10-22 13:52:41 -070070 this.configService = configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070071 this.interfaceService = interfaceService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070072 }
73
Jonathan Hart31582d12014-10-22 13:52:41 -070074 /**
75 * Starts the peer connectivity manager.
76 */
Jonathan Hartdc711bd2014-10-15 11:24:23 -070077 public void start() {
78 // TODO are any of these errors?
79 if (interfaceService.getInterfaces().isEmpty()) {
80
81 log.warn("The interface in configuration file is empty. "
Thomas Vachuskab97cf282014-10-20 23:31:12 -070082 + "Thus, the SDN-IP application can not be started.");
Jonathan Hart31582d12014-10-22 13:52:41 -070083 } else if (configService.getBgpPeers().isEmpty()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070084
85 log.warn("The BGP peer in configuration file is empty."
Thomas Vachuskab97cf282014-10-20 23:31:12 -070086 + "Thus, the SDN-IP application can not be started.");
Jonathan Hart31582d12014-10-22 13:52:41 -070087 } else if (configService.getBgpSpeakers() == null) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070088
89 log.error("The BGP speaker in configuration file is empty. "
Thomas Vachuskab97cf282014-10-20 23:31:12 -070090 + "Thus, the SDN-IP application can not be started.");
Jonathan Hartdc711bd2014-10-15 11:24:23 -070091 return;
92 }
93
Jonathan Hart6ec68292014-11-14 15:09:30 -080094 setUpConnectivity();
Jonathan Hartdc711bd2014-10-15 11:24:23 -070095 }
96
97 /**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080098 * Stops the peer connectivity manager.
99 */
100 public void stop() {
101 // TODO: Implement it
102 }
103
104 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800105 * Sets up paths to establish connectivity between all internal
106 * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700107 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800108 private void setUpConnectivity() {
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800109 List<PointToPointIntent> intents = new ArrayList<>();
110
Jonathan Hart31582d12014-10-22 13:52:41 -0700111 for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700112 .values()) {
113 log.debug("Start to set up BGP paths for BGP speaker: {}",
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700114 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700115
Jonathan Hart31582d12014-10-22 13:52:41 -0700116 for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700117
118 log.debug("Start to set up BGP paths between BGP speaker: {} "
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700119 + "to BGP peer: {}", bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700120
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800121 intents.addAll(buildPeerIntents(bgpSpeaker, bgpPeer));
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700122 }
123 }
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800124
125 // Submit all the intents.
126 intentSynchronizer.submitPeerIntents(intents);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700127 }
128
129 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800130 * Builds the required intents between a given internal BGP speaker and
131 * external BGP peer.
132 *
133 * @param bgpSpeaker the BGP speaker
134 * @param bgpPeer the BGP peer
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800135 * @return the intents to install
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700136 */
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800137 private Collection<PointToPointIntent> buildPeerIntents(
138 BgpSpeaker bgpSpeaker,
139 BgpPeer bgpPeer) {
140 List<PointToPointIntent> intents = new ArrayList<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700141
Jonathan Hart6ec68292014-11-14 15:09:30 -0800142 ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700143
Jonathan Hart6ec68292014-11-14 15:09:30 -0800144 List<InterfaceAddress> interfaceAddresses =
145 bgpSpeaker.interfaceAddresses();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700146
Jonathan Hart6ec68292014-11-14 15:09:30 -0800147 Interface peerInterface = interfaceService.getInterface(
148 bgpPeer.connectPoint());
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700149
Jonathan Hart6ec68292014-11-14 15:09:30 -0800150 if (peerInterface == null) {
151 log.error("No interface found for peer {}", bgpPeer.ipAddress());
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800152 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800153 }
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700154
Jonathan Hart6ec68292014-11-14 15:09:30 -0800155 IpAddress bgpdAddress = null;
156 for (InterfaceAddress interfaceAddress : interfaceAddresses) {
157 if (interfaceAddress.connectPoint().equals(
158 peerInterface.connectPoint())) {
159 bgpdAddress = interfaceAddress.ipAddress();
160 break;
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700161 }
162 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800163 if (bgpdAddress == null) {
164 log.debug("No IP address found for peer {} on interface {}",
165 bgpPeer, bgpPeer.connectPoint());
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800166 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800167 }
168
169 IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
170 ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
171
172 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
173 .build();
174
175 TrafficSelector selector;
176
177 // install intent for BGP path from BGPd to BGP peer matching
178 // destination TCP port 179
179 selector = buildSelector(IPv4.PROTOCOL_TCP,
180 bgpdAddress,
181 bgpdPeerAddress,
182 null,
183 (short) BgpConstants.BGP_PORT);
184
185 intents.add(new PointToPointIntent(appId, selector, treatment,
186 bgpdConnectPoint, bgpdPeerConnectPoint));
187
188 // install intent for BGP path from BGPd to BGP peer matching
189 // source TCP port 179
190 selector = buildSelector(IPv4.PROTOCOL_TCP,
191 bgpdAddress,
192 bgpdPeerAddress,
193 (short) BgpConstants.BGP_PORT,
194 null);
195
196 intents.add(new PointToPointIntent(appId, selector, treatment,
197 bgpdConnectPoint, bgpdPeerConnectPoint));
198
199 // install intent for reversed BGP path from BGP peer to BGPd
200 // matching destination TCP port 179
201 selector = buildSelector(IPv4.PROTOCOL_TCP,
202 bgpdPeerAddress,
203 bgpdAddress,
204 null,
205 (short) BgpConstants.BGP_PORT);
206
207 intents.add(new PointToPointIntent(appId, selector, treatment,
208 bgpdPeerConnectPoint, bgpdConnectPoint));
209
210 // install intent for reversed BGP path from BGP peer to BGPd
211 // matching source TCP port 179
212 selector = buildSelector(IPv4.PROTOCOL_TCP,
213 bgpdPeerAddress,
214 bgpdAddress,
215 (short) BgpConstants.BGP_PORT,
216 null);
217
218 intents.add(new PointToPointIntent(appId, selector, treatment,
219 bgpdPeerConnectPoint, bgpdConnectPoint));
220
221 // install intent for ICMP path from BGPd to BGP peer
222 selector = buildSelector(IPv4.PROTOCOL_ICMP,
223 bgpdAddress,
224 bgpdPeerAddress,
225 null,
226 null);
227
228 intents.add(new PointToPointIntent(appId, selector, treatment,
229 bgpdConnectPoint, bgpdPeerConnectPoint));
230
231 // install intent for reversed ICMP path from BGP peer to BGPd
232 selector = buildSelector(IPv4.PROTOCOL_ICMP,
233 bgpdPeerAddress,
234 bgpdAddress,
235 null,
236 null);
237
238 intents.add(new PointToPointIntent(appId, selector, treatment,
239 bgpdPeerConnectPoint, bgpdConnectPoint));
240
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800241 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800242 }
243
244 /**
245 * Builds a traffic selector based on the set of input parameters.
246 *
247 * @param ipProto IP protocol
248 * @param srcIp source IP address
249 * @param dstIp destination IP address
250 * @param srcTcpPort source TCP port, or null if shouldn't be set
251 * @param dstTcpPort destination TCP port, or null if shouldn't be set
252 * @return the new traffic selector
253 */
254 private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800255 IpAddress dstIp, Short srcTcpPort,
256 Short dstTcpPort) {
Jonathan Hart6ec68292014-11-14 15:09:30 -0800257 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
258 .matchEthType(Ethernet.TYPE_IPV4)
259 .matchIPProtocol(ipProto)
260 .matchIPSrc(IpPrefix.valueOf(srcIp,
261 IpPrefix.MAX_INET_MASK_LENGTH))
262 .matchIPDst(IpPrefix.valueOf(dstIp,
263 IpPrefix.MAX_INET_MASK_LENGTH));
264
265 if (srcTcpPort != null) {
266 builder.matchTcpSrc(srcTcpPort);
267 }
268
269 if (dstTcpPort != null) {
270 builder.matchTcpDst(dstTcpPort);
271 }
272
273 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700274 }
275
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700276}