blob: 56db046806a633a89757ea00ec8e64d8ec2e75a7 [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 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -080099 * Sets up paths to establish connectivity between all internal
100 * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700101 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800102 private void setUpConnectivity() {
Jonathan Hart31582d12014-10-22 13:52:41 -0700103 for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700104 .values()) {
105 log.debug("Start to set up BGP paths for BGP speaker: {}",
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700106 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700107
Jonathan Hart31582d12014-10-22 13:52:41 -0700108 for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700109
110 log.debug("Start to set up BGP paths between BGP speaker: {} "
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700111 + "to BGP peer: {}", bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700112
Jonathan Hart6ec68292014-11-14 15:09:30 -0800113 buildPeerIntents(bgpSpeaker, bgpPeer);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700114 }
115 }
116 }
117
118 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800119 * Builds the required intents between a given internal BGP speaker and
120 * external BGP peer.
121 *
122 * @param bgpSpeaker the BGP speaker
123 * @param bgpPeer the BGP peer
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700124 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800125 private void buildPeerIntents(BgpSpeaker bgpSpeaker, BgpPeer bgpPeer) {
126 List<Intent> intents = new ArrayList<Intent>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700127
Jonathan Hart6ec68292014-11-14 15:09:30 -0800128 ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700129
Jonathan Hart6ec68292014-11-14 15:09:30 -0800130 List<InterfaceAddress> interfaceAddresses =
131 bgpSpeaker.interfaceAddresses();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700132
Jonathan Hart6ec68292014-11-14 15:09:30 -0800133 Interface peerInterface = interfaceService.getInterface(
134 bgpPeer.connectPoint());
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700135
Jonathan Hart6ec68292014-11-14 15:09:30 -0800136 if (peerInterface == null) {
137 log.error("No interface found for peer {}", bgpPeer.ipAddress());
138 return;
139 }
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700140
Jonathan Hart6ec68292014-11-14 15:09:30 -0800141 IpAddress bgpdAddress = null;
142 for (InterfaceAddress interfaceAddress : interfaceAddresses) {
143 if (interfaceAddress.connectPoint().equals(
144 peerInterface.connectPoint())) {
145 bgpdAddress = interfaceAddress.ipAddress();
146 break;
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700147 }
148 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800149 if (bgpdAddress == null) {
150 log.debug("No IP address found for peer {} on interface {}",
151 bgpPeer, bgpPeer.connectPoint());
152 return;
153 }
154
155 IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
156 ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
157
158 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
159 .build();
160
161 TrafficSelector selector;
162
163 // install intent for BGP path from BGPd to BGP peer matching
164 // destination TCP port 179
165 selector = buildSelector(IPv4.PROTOCOL_TCP,
166 bgpdAddress,
167 bgpdPeerAddress,
168 null,
169 (short) BgpConstants.BGP_PORT);
170
171 intents.add(new PointToPointIntent(appId, selector, treatment,
172 bgpdConnectPoint, bgpdPeerConnectPoint));
173
174 // install intent for BGP path from BGPd to BGP peer matching
175 // source TCP port 179
176 selector = buildSelector(IPv4.PROTOCOL_TCP,
177 bgpdAddress,
178 bgpdPeerAddress,
179 (short) BgpConstants.BGP_PORT,
180 null);
181
182 intents.add(new PointToPointIntent(appId, selector, treatment,
183 bgpdConnectPoint, bgpdPeerConnectPoint));
184
185 // install intent for reversed BGP path from BGP peer to BGPd
186 // matching destination TCP port 179
187 selector = buildSelector(IPv4.PROTOCOL_TCP,
188 bgpdPeerAddress,
189 bgpdAddress,
190 null,
191 (short) BgpConstants.BGP_PORT);
192
193 intents.add(new PointToPointIntent(appId, selector, treatment,
194 bgpdPeerConnectPoint, bgpdConnectPoint));
195
196 // install intent for reversed BGP path from BGP peer to BGPd
197 // matching source TCP port 179
198 selector = buildSelector(IPv4.PROTOCOL_TCP,
199 bgpdPeerAddress,
200 bgpdAddress,
201 (short) BgpConstants.BGP_PORT,
202 null);
203
204 intents.add(new PointToPointIntent(appId, selector, treatment,
205 bgpdPeerConnectPoint, bgpdConnectPoint));
206
207 // install intent for ICMP path from BGPd to BGP peer
208 selector = buildSelector(IPv4.PROTOCOL_ICMP,
209 bgpdAddress,
210 bgpdPeerAddress,
211 null,
212 null);
213
214 intents.add(new PointToPointIntent(appId, selector, treatment,
215 bgpdConnectPoint, bgpdPeerConnectPoint));
216
217 // install intent for reversed ICMP path from BGP peer to BGPd
218 selector = buildSelector(IPv4.PROTOCOL_ICMP,
219 bgpdPeerAddress,
220 bgpdAddress,
221 null,
222 null);
223
224 intents.add(new PointToPointIntent(appId, selector, treatment,
225 bgpdPeerConnectPoint, bgpdConnectPoint));
226
227 // Submit all the intents.
228 // TODO submit as a batch
229 for (Intent intent : intents) {
230 intentService.submit(intent);
231 }
232 }
233
234 /**
235 * Builds a traffic selector based on the set of input parameters.
236 *
237 * @param ipProto IP protocol
238 * @param srcIp source IP address
239 * @param dstIp destination IP address
240 * @param srcTcpPort source TCP port, or null if shouldn't be set
241 * @param dstTcpPort destination TCP port, or null if shouldn't be set
242 * @return the new traffic selector
243 */
244 private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
245 IpAddress dstIp, Short srcTcpPort, Short dstTcpPort) {
246 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
247 .matchEthType(Ethernet.TYPE_IPV4)
248 .matchIPProtocol(ipProto)
249 .matchIPSrc(IpPrefix.valueOf(srcIp,
250 IpPrefix.MAX_INET_MASK_LENGTH))
251 .matchIPDst(IpPrefix.valueOf(dstIp,
252 IpPrefix.MAX_INET_MASK_LENGTH));
253
254 if (srcTcpPort != null) {
255 builder.matchTcpSrc(srcTcpPort);
256 }
257
258 if (dstTcpPort != null) {
259 builder.matchTcpDst(dstTcpPort);
260 }
261
262 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700263 }
264
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700265}