blob: ce859457ec9ec5b1088f58da21d3cacffc82bc50 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.sdnip;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070017
Jonathan Hart51372182014-12-03 21:32:34 -080018import org.onlab.packet.Ethernet;
19import org.onlab.packet.IPv4;
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -080020import org.onlab.packet.IPv6;
Jonathan Hart41349e92015-02-09 14:14:02 -080021import org.onlab.packet.IpAddress;
Jonathan Hart51372182014-12-03 21:32:34 -080022import org.onlab.packet.IpPrefix;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070023import org.onlab.packet.TpPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.core.ApplicationId;
25import org.onosproject.net.ConnectPoint;
26import org.onosproject.net.flow.DefaultTrafficSelector;
27import org.onosproject.net.flow.DefaultTrafficTreatment;
28import org.onosproject.net.flow.TrafficSelector;
29import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart2a9ea492015-07-30 15:53:04 -070030import org.onosproject.net.host.InterfaceIpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.intent.PointToPointIntent;
Jonathan Hart2da1e602015-02-18 19:09:24 -080032import org.onosproject.routing.config.BgpPeer;
33import org.onosproject.routing.config.BgpSpeaker;
34import org.onosproject.routing.config.Interface;
35import org.onosproject.routing.config.InterfaceAddress;
36import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
Jonathan Hart41349e92015-02-09 14:14:02 -080040import java.util.ArrayList;
41import java.util.Collection;
42import java.util.List;
43
Jonathan Hartdc711bd2014-10-15 11:24:23 -070044/**
45 * Manages the connectivity requirements between peers.
46 */
Jonathan Hartce430a42014-10-16 20:44:29 -070047public class PeerConnectivityManager {
Pavlin Radoslavov2aa1f322015-03-11 17:59:44 -070048 private static final int PRIORITY_OFFSET = 1000;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070049
50 private static final Logger log = LoggerFactory.getLogger(
Jonathan Hartce430a42014-10-16 20:44:29 -070051 PeerConnectivityManager.class);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070052
Jonathan Hart41349e92015-02-09 14:14:02 -080053 private static final short BGP_PORT = 179;
54
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080055 private final IntentSynchronizer intentSynchronizer;
Jonathan Hart90a02c22015-02-13 11:52:07 -080056 private final RoutingConfigurationService configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070057
Thomas Vachuskab97cf282014-10-20 23:31:12 -070058 private final ApplicationId appId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070059
Jonathan Hart31582d12014-10-22 13:52:41 -070060 /**
61 * Creates a new PeerConnectivityManager.
62 *
Jonathan Hart51372182014-12-03 21:32:34 -080063 * @param appId the application ID
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080064 * @param intentSynchronizer the intent synchronizer
Jonathan Hart51372182014-12-03 21:32:34 -080065 * @param configService the SDN-IP config service
Jonathan Hart31582d12014-10-22 13:52:41 -070066 */
Thomas Vachuskab97cf282014-10-20 23:31:12 -070067 public PeerConnectivityManager(ApplicationId appId,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080068 IntentSynchronizer intentSynchronizer,
Jonathan Hart90a02c22015-02-13 11:52:07 -080069 RoutingConfigurationService configService) {
Thomas Vachuskab97cf282014-10-20 23:31:12 -070070 this.appId = appId;
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080071 this.intentSynchronizer = intentSynchronizer;
Jonathan Hart31582d12014-10-22 13:52:41 -070072 this.configService = configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070073 }
74
Jonathan Hart31582d12014-10-22 13:52:41 -070075 /**
76 * Starts the peer connectivity manager.
77 */
Jonathan Hartdc711bd2014-10-15 11:24:23 -070078 public void start() {
Jonathan Hart90a02c22015-02-13 11:52:07 -080079 if (configService.getInterfaces().isEmpty()) {
Jonathan Hart51372182014-12-03 21:32:34 -080080 log.warn("No interfaces found in configuration file");
Jonathan Hartde089122014-12-03 22:33:14 -080081 }
82
83 if (configService.getBgpPeers().isEmpty()) {
Jonathan Hart51372182014-12-03 21:32:34 -080084 log.warn("No BGP peers found in configuration file");
Jonathan Hartde089122014-12-03 22:33:14 -080085 }
86
87 if (configService.getBgpSpeakers().isEmpty()) {
Jonathan Hart51372182014-12-03 21:32:34 -080088 log.error("No BGP speakers found in configuration file");
Jonathan Hartdc711bd2014-10-15 11:24:23 -070089 }
90
Jonathan Hart6ec68292014-11-14 15:09:30 -080091 setUpConnectivity();
Jonathan Hartdc711bd2014-10-15 11:24:23 -070092 }
93
94 /**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080095 * Stops the peer connectivity manager.
96 */
97 public void stop() {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080098 }
99
100 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800101 * Sets up paths to establish connectivity between all internal
102 * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700103 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800104 private void setUpConnectivity() {
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800105 List<PointToPointIntent> intents = new ArrayList<>();
106
Jonathan Hart31582d12014-10-22 13:52:41 -0700107 for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700108 .values()) {
109 log.debug("Start to set up BGP paths for BGP speaker: {}",
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700110 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700111
Jonathan Hart31582d12014-10-22 13:52:41 -0700112 for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700113
114 log.debug("Start to set up BGP paths between BGP speaker: {} "
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700115 + "to BGP peer: {}", bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700116
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800117 intents.addAll(buildPeerIntents(bgpSpeaker, bgpPeer));
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700118 }
119 }
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800120
121 // Submit all the intents.
122 intentSynchronizer.submitPeerIntents(intents);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700123 }
124
125 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800126 * Builds the required intents between a given internal BGP speaker and
127 * external BGP peer.
128 *
129 * @param bgpSpeaker the BGP speaker
130 * @param bgpPeer the BGP peer
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800131 * @return the intents to install
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700132 */
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800133 private Collection<PointToPointIntent> buildPeerIntents(
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700134 BgpSpeaker bgpSpeaker,
135 BgpPeer bgpPeer) {
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800136 List<PointToPointIntent> intents = new ArrayList<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700137
Jonathan Hart6ec68292014-11-14 15:09:30 -0800138 ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700139
Jonathan Hart6ec68292014-11-14 15:09:30 -0800140 List<InterfaceAddress> interfaceAddresses =
141 bgpSpeaker.interfaceAddresses();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700142
Jonathan Hart6ec68292014-11-14 15:09:30 -0800143 IpAddress bgpdAddress = null;
144 for (InterfaceAddress interfaceAddress : interfaceAddresses) {
Jonathan Harte30fcda2015-08-06 16:22:34 -0700145 Interface peerInterface = configService.getInterface(interfaceAddress.ipAddress());
146 if (peerInterface == null) {
147 continue;
148 }
149
150 for (InterfaceIpAddress interfaceIpAddress : peerInterface.ipAddresses()) {
151 // Only add intents where the peer and ONOS's addresses are
152 // in the same subnet
153 if (interfaceIpAddress.subnetAddress().contains(bgpPeer.ipAddress())) {
154 bgpdAddress = interfaceAddress.ipAddress();
155 break;
Jonathan Hart2a9ea492015-07-30 15:53:04 -0700156 }
Jonathan Harte30fcda2015-08-06 16:22:34 -0700157 }
158 if (bgpdAddress != null) {
Jonathan Hart6ec68292014-11-14 15:09:30 -0800159 break;
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700160 }
161 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800162 if (bgpdAddress == null) {
163 log.debug("No IP address found for peer {} on interface {}",
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700164 bgpPeer, bgpPeer.connectPoint());
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800165 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800166 }
167
168 IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
Jonathan Harte30fcda2015-08-06 16:22:34 -0700169 ConnectPoint bgpdPeerConnectPoint = bgpPeer.connectPoint();
Jonathan Hart6ec68292014-11-14 15:09:30 -0800170
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800171 if (bgpdAddress.version() != bgpdPeerAddress.version()) {
172 return intents;
173 }
174
Brian O'Connor6b528132015-03-10 16:39:52 -0700175 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
Jonathan Hart6ec68292014-11-14 15:09:30 -0800176
177 TrafficSelector selector;
178
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800179 byte tcpProtocol;
180 byte icmpProtocol;
181
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700182 if (bgpdAddress.isIp4()) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800183 tcpProtocol = IPv4.PROTOCOL_TCP;
184 icmpProtocol = IPv4.PROTOCOL_ICMP;
185 } else {
186 tcpProtocol = IPv6.PROTOCOL_TCP;
187 icmpProtocol = IPv6.PROTOCOL_ICMP6;
188 }
189
Jonathan Hart51372182014-12-03 21:32:34 -0800190 // Path from BGP speaker to BGP peer matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800191 selector = buildSelector(tcpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700192 bgpdAddress,
193 bgpdPeerAddress,
194 null,
195 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800196
Pavlin Radoslavov2aa1f322015-03-11 17:59:44 -0700197 int priority = PRIORITY_OFFSET;
198
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700199 intents.add(PointToPointIntent.builder()
200 .appId(appId)
201 .selector(selector)
202 .treatment(treatment)
203 .ingressPoint(bgpdConnectPoint)
204 .egressPoint(bgpdPeerConnectPoint)
205 .priority(priority)
206 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800207
Jonathan Hart51372182014-12-03 21:32:34 -0800208 // Path from BGP speaker to BGP peer matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800209 selector = buildSelector(tcpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700210 bgpdAddress,
211 bgpdPeerAddress,
212 BGP_PORT,
213 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800214
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700215 intents.add(PointToPointIntent.builder()
216 .appId(appId)
217 .selector(selector)
218 .treatment(treatment)
219 .ingressPoint(bgpdConnectPoint)
220 .egressPoint(bgpdPeerConnectPoint)
221 .priority(priority)
222 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800223
Jonathan Hart51372182014-12-03 21:32:34 -0800224 // Path from BGP peer to BGP speaker matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800225 selector = buildSelector(tcpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700226 bgpdPeerAddress,
227 bgpdAddress,
228 null,
229 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800230
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700231 intents.add(PointToPointIntent.builder()
232 .appId(appId)
233 .selector(selector)
234 .treatment(treatment)
235 .ingressPoint(bgpdPeerConnectPoint)
236 .egressPoint(bgpdConnectPoint)
237 .priority(priority)
238 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800239
Jonathan Hart51372182014-12-03 21:32:34 -0800240 // Path from BGP peer to BGP speaker matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800241 selector = buildSelector(tcpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700242 bgpdPeerAddress,
243 bgpdAddress,
244 BGP_PORT,
245 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800246
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700247 intents.add(PointToPointIntent.builder()
248 .appId(appId)
249 .selector(selector)
250 .treatment(treatment)
251 .ingressPoint(bgpdPeerConnectPoint)
252 .egressPoint(bgpdConnectPoint)
253 .priority(priority)
254 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800255
Jonathan Hart51372182014-12-03 21:32:34 -0800256 // ICMP path from BGP speaker to BGP peer
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800257 selector = buildSelector(icmpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700258 bgpdAddress,
259 bgpdPeerAddress,
260 null,
261 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800262
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700263 intents.add(PointToPointIntent.builder()
264 .appId(appId)
265 .selector(selector)
266 .treatment(treatment)
267 .ingressPoint(bgpdConnectPoint)
268 .egressPoint(bgpdPeerConnectPoint)
269 .priority(priority)
270 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800271
Jonathan Hart51372182014-12-03 21:32:34 -0800272 // ICMP path from BGP peer to BGP speaker
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800273 selector = buildSelector(icmpProtocol,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700274 bgpdPeerAddress,
275 bgpdAddress,
276 null,
277 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800278
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700279 intents.add(PointToPointIntent.builder()
280 .appId(appId)
281 .selector(selector)
282 .treatment(treatment)
283 .ingressPoint(bgpdPeerConnectPoint)
284 .egressPoint(bgpdConnectPoint)
285 .priority(priority)
286 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800287
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800288 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800289 }
290
291 /**
292 * Builds a traffic selector based on the set of input parameters.
293 *
294 * @param ipProto IP protocol
295 * @param srcIp source IP address
296 * @param dstIp destination IP address
297 * @param srcTcpPort source TCP port, or null if shouldn't be set
298 * @param dstTcpPort destination TCP port, or null if shouldn't be set
299 * @return the new traffic selector
300 */
301 private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800302 IpAddress dstIp, Short srcTcpPort,
303 Short dstTcpPort) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800304 TrafficSelector.Builder builder = null;
305
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700306 if (dstIp.isIp4()) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800307 builder = DefaultTrafficSelector.builder()
308 .matchEthType(Ethernet.TYPE_IPV4)
309 .matchIPProtocol(ipProto)
310 .matchIPSrc(IpPrefix.valueOf(srcIp,
311 IpPrefix.MAX_INET_MASK_LENGTH))
312 .matchIPDst(IpPrefix.valueOf(dstIp,
313 IpPrefix.MAX_INET_MASK_LENGTH));
314 } else {
315 builder = DefaultTrafficSelector.builder()
316 .matchEthType(Ethernet.TYPE_IPV6)
317 .matchIPProtocol(ipProto)
318 .matchIPv6Src(IpPrefix.valueOf(srcIp,
319 IpPrefix.MAX_INET6_MASK_LENGTH))
320 .matchIPv6Dst(IpPrefix.valueOf(dstIp,
321 IpPrefix.MAX_INET6_MASK_LENGTH));
322 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800323
324 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700325 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800326 }
327
328 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700329 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800330 }
331
332 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700333 }
334
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700335}