blob: a691ade2e0d7a89c357cd2b122b089e16c18ad34 [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;
Jonathan Hart31582d12014-10-22 13:52:41 -070019import java.util.List;
20
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070021import org.onlab.onos.core.ApplicationId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070022import org.onlab.onos.net.ConnectPoint;
23import org.onlab.onos.net.flow.DefaultTrafficSelector;
24import org.onlab.onos.net.flow.DefaultTrafficTreatment;
25import org.onlab.onos.net.flow.TrafficSelector;
26import org.onlab.onos.net.flow.TrafficTreatment;
Jonathan Hart6ec68292014-11-14 15:09:30 -080027import org.onlab.onos.net.intent.Intent;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070028import org.onlab.onos.net.intent.IntentService;
29import org.onlab.onos.net.intent.PointToPointIntent;
Jonathan Hart31582d12014-10-22 13:52:41 -070030import org.onlab.onos.sdnip.bgp.BgpConstants;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070031import org.onlab.onos.sdnip.config.BgpPeer;
32import org.onlab.onos.sdnip.config.BgpSpeaker;
33import org.onlab.onos.sdnip.config.Interface;
34import org.onlab.onos.sdnip.config.InterfaceAddress;
35import org.onlab.onos.sdnip.config.SdnIpConfigService;
36import org.onlab.packet.Ethernet;
37import org.onlab.packet.IPv4;
38import org.onlab.packet.IpAddress;
39import org.onlab.packet.IpPrefix;
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43/**
44 * Manages the connectivity requirements between peers.
45 */
Jonathan Hartce430a42014-10-16 20:44:29 -070046public class PeerConnectivityManager {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070047
48 private static final Logger log = LoggerFactory.getLogger(
Jonathan Hartce430a42014-10-16 20:44:29 -070049 PeerConnectivityManager.class);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070050
Jonathan Hart31582d12014-10-22 13:52:41 -070051 private final SdnIpConfigService configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070052 private final InterfaceService interfaceService;
53 private final IntentService intentService;
54
Thomas Vachuskab97cf282014-10-20 23:31:12 -070055 private final ApplicationId appId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070056
Jonathan Hart31582d12014-10-22 13:52:41 -070057 /**
58 * Creates a new PeerConnectivityManager.
59 *
60 * @param appId the application ID
61 * @param configService the SDN-IP config service
62 * @param interfaceService the interface service
63 * @param intentService the intent service
64 */
Thomas Vachuskab97cf282014-10-20 23:31:12 -070065 public PeerConnectivityManager(ApplicationId appId,
Jonathan Hart31582d12014-10-22 13:52:41 -070066 SdnIpConfigService configService,
Thomas Vachuskab97cf282014-10-20 23:31:12 -070067 InterfaceService interfaceService,
68 IntentService intentService) {
69 this.appId = appId;
Jonathan Hart31582d12014-10-22 13:52:41 -070070 this.configService = configService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070071 this.interfaceService = interfaceService;
72 this.intentService = intentService;
73 }
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() {
79 // TODO are any of these errors?
80 if (interfaceService.getInterfaces().isEmpty()) {
81
82 log.warn("The interface in configuration file is empty. "
Thomas Vachuskab97cf282014-10-20 23:31:12 -070083 + "Thus, the SDN-IP application can not be started.");
Jonathan Hart31582d12014-10-22 13:52:41 -070084 } else if (configService.getBgpPeers().isEmpty()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070085
86 log.warn("The BGP peer in configuration file is empty."
Thomas Vachuskab97cf282014-10-20 23:31:12 -070087 + "Thus, the SDN-IP application can not be started.");
Jonathan Hart31582d12014-10-22 13:52:41 -070088 } else if (configService.getBgpSpeakers() == null) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -070089
90 log.error("The BGP speaker in configuration file is empty. "
Thomas Vachuskab97cf282014-10-20 23:31:12 -070091 + "Thus, the SDN-IP application can not be started.");
Jonathan Hartdc711bd2014-10-15 11:24:23 -070092 return;
93 }
94
Jonathan Hart6ec68292014-11-14 15:09:30 -080095 setUpConnectivity();
Jonathan Hartdc711bd2014-10-15 11:24:23 -070096 }
97
98 /**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080099 * Stops the peer connectivity manager.
100 */
101 public void stop() {
102 // TODO: Implement it
103 }
104
105 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800106 * Sets up paths to establish connectivity between all internal
107 * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700108 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800109 private void setUpConnectivity() {
Jonathan Hart31582d12014-10-22 13:52:41 -0700110 for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700111 .values()) {
112 log.debug("Start to set up BGP paths for BGP speaker: {}",
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700113 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700114
Jonathan Hart31582d12014-10-22 13:52:41 -0700115 for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700116
117 log.debug("Start to set up BGP paths between BGP speaker: {} "
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700118 + "to BGP peer: {}", bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700119
Jonathan Hart6ec68292014-11-14 15:09:30 -0800120 buildPeerIntents(bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700121 }
122 }
123 }
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
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700131 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800132 private void buildPeerIntents(BgpSpeaker bgpSpeaker, BgpPeer bgpPeer) {
133 List<Intent> intents = new ArrayList<Intent>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700134
Jonathan Hart6ec68292014-11-14 15:09:30 -0800135 ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700136
Jonathan Hart6ec68292014-11-14 15:09:30 -0800137 List<InterfaceAddress> interfaceAddresses =
138 bgpSpeaker.interfaceAddresses();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700139
Jonathan Hart6ec68292014-11-14 15:09:30 -0800140 Interface peerInterface = interfaceService.getInterface(
141 bgpPeer.connectPoint());
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700142
Jonathan Hart6ec68292014-11-14 15:09:30 -0800143 if (peerInterface == null) {
144 log.error("No interface found for peer {}", bgpPeer.ipAddress());
145 return;
146 }
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700147
Jonathan Hart6ec68292014-11-14 15:09:30 -0800148 IpAddress bgpdAddress = null;
149 for (InterfaceAddress interfaceAddress : interfaceAddresses) {
150 if (interfaceAddress.connectPoint().equals(
151 peerInterface.connectPoint())) {
152 bgpdAddress = interfaceAddress.ipAddress();
153 break;
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700154 }
155 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800156 if (bgpdAddress == null) {
157 log.debug("No IP address found for peer {} on interface {}",
158 bgpPeer, bgpPeer.connectPoint());
159 return;
160 }
161
162 IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
163 ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
164
165 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
166 .build();
167
168 TrafficSelector selector;
169
170 // install intent for BGP path from BGPd to BGP peer matching
171 // destination TCP port 179
172 selector = buildSelector(IPv4.PROTOCOL_TCP,
173 bgpdAddress,
174 bgpdPeerAddress,
175 null,
176 (short) BgpConstants.BGP_PORT);
177
178 intents.add(new PointToPointIntent(appId, selector, treatment,
179 bgpdConnectPoint, bgpdPeerConnectPoint));
180
181 // install intent for BGP path from BGPd to BGP peer matching
182 // source TCP port 179
183 selector = buildSelector(IPv4.PROTOCOL_TCP,
184 bgpdAddress,
185 bgpdPeerAddress,
186 (short) BgpConstants.BGP_PORT,
187 null);
188
189 intents.add(new PointToPointIntent(appId, selector, treatment,
190 bgpdConnectPoint, bgpdPeerConnectPoint));
191
192 // install intent for reversed BGP path from BGP peer to BGPd
193 // matching destination TCP port 179
194 selector = buildSelector(IPv4.PROTOCOL_TCP,
195 bgpdPeerAddress,
196 bgpdAddress,
197 null,
198 (short) BgpConstants.BGP_PORT);
199
200 intents.add(new PointToPointIntent(appId, selector, treatment,
201 bgpdPeerConnectPoint, bgpdConnectPoint));
202
203 // install intent for reversed BGP path from BGP peer to BGPd
204 // matching source TCP port 179
205 selector = buildSelector(IPv4.PROTOCOL_TCP,
206 bgpdPeerAddress,
207 bgpdAddress,
208 (short) BgpConstants.BGP_PORT,
209 null);
210
211 intents.add(new PointToPointIntent(appId, selector, treatment,
212 bgpdPeerConnectPoint, bgpdConnectPoint));
213
214 // install intent for ICMP path from BGPd to BGP peer
215 selector = buildSelector(IPv4.PROTOCOL_ICMP,
216 bgpdAddress,
217 bgpdPeerAddress,
218 null,
219 null);
220
221 intents.add(new PointToPointIntent(appId, selector, treatment,
222 bgpdConnectPoint, bgpdPeerConnectPoint));
223
224 // install intent for reversed ICMP path from BGP peer to BGPd
225 selector = buildSelector(IPv4.PROTOCOL_ICMP,
226 bgpdPeerAddress,
227 bgpdAddress,
228 null,
229 null);
230
231 intents.add(new PointToPointIntent(appId, selector, treatment,
232 bgpdPeerConnectPoint, bgpdConnectPoint));
233
234 // Submit all the intents.
235 // TODO submit as a batch
236 for (Intent intent : intents) {
237 intentService.submit(intent);
238 }
239 }
240
241 /**
242 * Builds a traffic selector based on the set of input parameters.
243 *
244 * @param ipProto IP protocol
245 * @param srcIp source IP address
246 * @param dstIp destination IP address
247 * @param srcTcpPort source TCP port, or null if shouldn't be set
248 * @param dstTcpPort destination TCP port, or null if shouldn't be set
249 * @return the new traffic selector
250 */
251 private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
252 IpAddress dstIp, Short srcTcpPort, Short dstTcpPort) {
253 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
254 .matchEthType(Ethernet.TYPE_IPV4)
255 .matchIPProtocol(ipProto)
256 .matchIPSrc(IpPrefix.valueOf(srcIp,
257 IpPrefix.MAX_INET_MASK_LENGTH))
258 .matchIPDst(IpPrefix.valueOf(dstIp,
259 IpPrefix.MAX_INET_MASK_LENGTH));
260
261 if (srcTcpPort != null) {
262 builder.matchTcpSrc(srcTcpPort);
263 }
264
265 if (dstTcpPort != null) {
266 builder.matchTcpDst(dstTcpPort);
267 }
268
269 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700270 }
271
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700272}