blob: 0fa6e14a7596fe4476df43a45cea2e06008d84e8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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
Luca Prete83bac342016-12-06 19:42:05 -080018import com.google.common.collect.ImmutableList;
Jonathan Hart51372182014-12-03 21:32:34 -080019import org.onlab.packet.Ethernet;
20import org.onlab.packet.IPv4;
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -080021import org.onlab.packet.IPv6;
Jonathan Hart41349e92015-02-09 14:14:02 -080022import org.onlab.packet.IpAddress;
Jonathan Hart51372182014-12-03 21:32:34 -080023import org.onlab.packet.IpPrefix;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070024import org.onlab.packet.TpPort;
Luca Prete8f2a3ce2016-03-29 16:13:01 -070025import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.core.ApplicationId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040027import org.onosproject.incubator.net.intf.Interface;
Jonathan Hartb14221c2016-03-07 09:55:50 -080028import org.onosproject.incubator.net.intf.InterfaceEvent;
29import org.onosproject.incubator.net.intf.InterfaceListener;
Jonathan Hart4cb39882015-08-12 23:50:55 -040030import org.onosproject.incubator.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.ConnectPoint;
Luca Prete83bac342016-12-06 19:42:05 -080032import org.onosproject.net.EncapsulationType;
33import org.onosproject.net.FilteredConnectPoint;
Jonathan Hart08105be2015-10-10 18:31:06 -070034import org.onosproject.net.config.NetworkConfigEvent;
35import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart9a426f82015-09-03 15:43:13 +020036import org.onosproject.net.config.NetworkConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.flow.DefaultTrafficSelector;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.TrafficSelector;
40import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart2a9ea492015-07-30 15:53:04 -070041import org.onosproject.net.host.InterfaceIpAddress;
Luca Prete83bac342016-12-06 19:42:05 -080042import org.onosproject.net.intent.ConnectivityIntent;
Luca Prete86ac7d12015-12-02 23:36:49 -080043import org.onosproject.net.intent.IntentUtils;
Jonathan Hart9a426f82015-09-03 15:43:13 +020044import org.onosproject.net.intent.Key;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.intent.PointToPointIntent;
Luca Prete83bac342016-12-06 19:42:05 -080046import org.onosproject.net.intent.constraint.EncapsulationConstraint;
Jonathan Hart470ed4f2017-01-31 16:52:28 -080047import org.onosproject.intentsync.IntentSynchronizationService;
Jonathan Hart4cb39882015-08-12 23:50:55 -040048import org.onosproject.routing.RoutingService;
49import org.onosproject.routing.config.BgpConfig;
Luca Prete83bac342016-12-06 19:42:05 -080050import org.onosproject.sdnip.config.SdnIpConfig;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070051import org.slf4j.Logger;
52import org.slf4j.LoggerFactory;
53
Jonathan Hart41349e92015-02-09 14:14:02 -080054import java.util.ArrayList;
55import java.util.Collection;
Jonathan Hartb14221c2016-03-07 09:55:50 -080056import java.util.Collections;
Jonathan Hart08105be2015-10-10 18:31:06 -070057import java.util.HashMap;
Jonathan Hart41349e92015-02-09 14:14:02 -080058import java.util.List;
Jonathan Hart08105be2015-10-10 18:31:06 -070059import java.util.Map;
Jonathan Hartb14221c2016-03-07 09:55:50 -080060import java.util.Set;
Jonathan Hart41349e92015-02-09 14:14:02 -080061
Jonathan Hart4cb39882015-08-12 23:50:55 -040062import static com.google.common.base.Preconditions.checkNotNull;
Luca Prete83bac342016-12-06 19:42:05 -080063import static org.onosproject.net.EncapsulationType.NONE;
Jonathan Hart4cb39882015-08-12 23:50:55 -040064
Jonathan Hartdc711bd2014-10-15 11:24:23 -070065/**
66 * Manages the connectivity requirements between peers.
67 */
Jonathan Hartce430a42014-10-16 20:44:29 -070068public class PeerConnectivityManager {
Pavlin Radoslavov2aa1f322015-03-11 17:59:44 -070069 private static final int PRIORITY_OFFSET = 1000;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070070
Jonathan Hart9a426f82015-09-03 15:43:13 +020071 private static final String SUFFIX_DST = "dst";
72 private static final String SUFFIX_SRC = "src";
73 private static final String SUFFIX_ICMP = "icmp";
74
Jonathan Hartdc711bd2014-10-15 11:24:23 -070075 private static final Logger log = LoggerFactory.getLogger(
Jonathan Hartce430a42014-10-16 20:44:29 -070076 PeerConnectivityManager.class);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070077
Jonathan Hart41349e92015-02-09 14:14:02 -080078 private static final short BGP_PORT = 179;
79
Jonathan Hart9a426f82015-09-03 15:43:13 +020080 private final IntentSynchronizationService intentSynchronizer;
Jonathan Hart4cb39882015-08-12 23:50:55 -040081 private final NetworkConfigService configService;
82 private final InterfaceService interfaceService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070083
Thomas Vachuskab97cf282014-10-20 23:31:12 -070084 private final ApplicationId appId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040085 private final ApplicationId routerAppId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070086
Jonathan Hart08105be2015-10-10 18:31:06 -070087 private final Map<Key, PointToPointIntent> peerIntents;
88
89 private final InternalNetworkConfigListener configListener
90 = new InternalNetworkConfigListener();
Jonathan Hart9a426f82015-09-03 15:43:13 +020091
Jonathan Hartb14221c2016-03-07 09:55:50 -080092 private final InternalInterfaceListener interfaceListener
93 = new InternalInterfaceListener();
94
Jonathan Hart31582d12014-10-22 13:52:41 -070095 /**
96 * Creates a new PeerConnectivityManager.
97 *
Jonathan Hart51372182014-12-03 21:32:34 -080098 * @param appId the application ID
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080099 * @param intentSynchronizer the intent synchronizer
Jonathan Hartb14221c2016-03-07 09:55:50 -0800100 * @param configService the network config service
Ray Milkey9b36d812015-09-09 15:24:54 -0700101 * @param routerAppId application ID
Jonathan Hartb14221c2016-03-07 09:55:50 -0800102 * @param interfaceService the interface service
Jonathan Hart31582d12014-10-22 13:52:41 -0700103 */
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700104 public PeerConnectivityManager(ApplicationId appId,
Jonathan Hart9a426f82015-09-03 15:43:13 +0200105 IntentSynchronizationService intentSynchronizer,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400106 NetworkConfigService configService,
107 ApplicationId routerAppId,
108 InterfaceService interfaceService) {
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700109 this.appId = appId;
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800110 this.intentSynchronizer = intentSynchronizer;
Jonathan Hart31582d12014-10-22 13:52:41 -0700111 this.configService = configService;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400112 this.routerAppId = routerAppId;
113 this.interfaceService = interfaceService;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200114
Jonathan Hart08105be2015-10-10 18:31:06 -0700115 peerIntents = new HashMap<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700116 }
117
Jonathan Hart31582d12014-10-22 13:52:41 -0700118 /**
119 * Starts the peer connectivity manager.
120 */
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700121 public void start() {
Jonathan Hart08105be2015-10-10 18:31:06 -0700122 configService.addListener(configListener);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800123 interfaceService.addListener(interfaceListener);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800124 setUpConnectivity();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700125 }
126
127 /**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800128 * Stops the peer connectivity manager.
129 */
130 public void stop() {
Jonathan Hart08105be2015-10-10 18:31:06 -0700131 configService.removeListener(configListener);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800132 interfaceService.removeListener(interfaceListener);
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800133 }
134
135 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800136 * Sets up paths to establish connectivity between all internal
Jonathan Hart4cb39882015-08-12 23:50:55 -0400137 * BGP speakers and external BGP peers.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700138 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800139 private void setUpConnectivity() {
Luca Prete83bac342016-12-06 19:42:05 -0800140 BgpConfig bgpConfig = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
141 SdnIpConfig sdnIpConfig = configService.getConfig(appId, SdnIpConfig.class);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400142
Jonathan Hartb14221c2016-03-07 09:55:50 -0800143 Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers;
Luca Prete83bac342016-12-06 19:42:05 -0800144 EncapsulationType encap;
Jonathan Hartb14221c2016-03-07 09:55:50 -0800145
Luca Prete83bac342016-12-06 19:42:05 -0800146 if (bgpConfig == null) {
147 log.debug("No BGP config available");
Jonathan Hartb14221c2016-03-07 09:55:50 -0800148 bgpSpeakers = Collections.emptySet();
149 } else {
Luca Prete83bac342016-12-06 19:42:05 -0800150 bgpSpeakers = bgpConfig.bgpSpeakers();
151 }
152
153 if (sdnIpConfig == null) {
154 log.debug("No SDN-IP config available");
155 encap = EncapsulationType.NONE;
156 } else {
157 encap = sdnIpConfig.encap();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400158 }
159
Jonathan Hart08105be2015-10-10 18:31:06 -0700160 Map<Key, PointToPointIntent> existingIntents = new HashMap<>(peerIntents);
161
Jonathan Hartb14221c2016-03-07 09:55:50 -0800162 for (BgpConfig.BgpSpeakerConfig bgpSpeaker : bgpSpeakers) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700163 log.debug("Start to set up BGP paths for BGP speaker: {}",
Jonathan Hart4cb39882015-08-12 23:50:55 -0400164 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700165
Luca Prete83bac342016-12-06 19:42:05 -0800166 buildSpeakerIntents(bgpSpeaker, encap).forEach(i -> {
Jonathan Hart08105be2015-10-10 18:31:06 -0700167 PointToPointIntent intent = existingIntents.remove(i.key());
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800168 if (intent == null || !IntentUtils.intentsAreEqual(i, intent)) {
Jonathan Hart08105be2015-10-10 18:31:06 -0700169 peerIntents.put(i.key(), i);
170 intentSynchronizer.submit(i);
171 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200172 });
Jonathan Hart9a426f82015-09-03 15:43:13 +0200173 }
Jonathan Hart08105be2015-10-10 18:31:06 -0700174
175 // Remove any remaining intents that we used to have that we don't need
176 // anymore
177 existingIntents.values().forEach(i -> {
178 peerIntents.remove(i.key());
179 intentSynchronizer.withdraw(i);
180 });
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700181 }
182
Luca Prete83bac342016-12-06 19:42:05 -0800183 private Collection<PointToPointIntent> buildSpeakerIntents(BgpConfig.BgpSpeakerConfig speaker,
184 EncapsulationType encap) {
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800185 List<PointToPointIntent> intents = new ArrayList<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700186
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700187 // Get the BGP Speaker VLAN Id
188 VlanId bgpSpeakerVlanId = speaker.vlan();
189
Jonathan Hart4cb39882015-08-12 23:50:55 -0400190 for (IpAddress peerAddress : speaker.peers()) {
191 Interface peeringInterface = interfaceService.getMatchingInterface(peerAddress);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700192
Jonathan Hart4cb39882015-08-12 23:50:55 -0400193 if (peeringInterface == null) {
194 log.debug("No peering interface found for peer {} on speaker {}",
195 peerAddress, speaker);
Jonathan Harte30fcda2015-08-06 16:22:34 -0700196 continue;
197 }
198
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700199 IpAddress bgpSpeakerAddress = null;
200 for (InterfaceIpAddress address : peeringInterface.ipAddressesList()) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400201 if (address.subnetAddress().contains(peerAddress)) {
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700202 bgpSpeakerAddress = address.ipAddress();
Jonathan Harte30fcda2015-08-06 16:22:34 -0700203 break;
Jonathan Hart2a9ea492015-07-30 15:53:04 -0700204 }
Jonathan Harte30fcda2015-08-06 16:22:34 -0700205 }
Jonathan Hart4cb39882015-08-12 23:50:55 -0400206
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700207 checkNotNull(bgpSpeakerAddress);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400208
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700209 VlanId peerVlanId = peeringInterface.vlan();
210
211 intents.addAll(buildIntents(speaker.connectPoint(), bgpSpeakerVlanId,
212 bgpSpeakerAddress,
213 peeringInterface.connectPoint(),
214 peerVlanId,
Luca Prete83bac342016-12-06 19:42:05 -0800215 peerAddress,
216 encap));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800217 }
218
Jonathan Hart4cb39882015-08-12 23:50:55 -0400219 return intents;
220 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800221
Jonathan Hart4cb39882015-08-12 23:50:55 -0400222 /**
Luca Pretee9511512016-05-13 10:30:19 -0700223 * Builds the required intents between a BGP speaker and an external router.
Jonathan Hart4cb39882015-08-12 23:50:55 -0400224 *
Luca Pretee9511512016-05-13 10:30:19 -0700225 * @param portOne the BGP speaker connect point
226 * @param vlanOne the BGP speaker VLAN
227 * @param ipOne the BGP speaker IP address
228 * @param portTwo the external BGP peer connect point
229 * @param vlanTwo the external BGP peer VLAN
230 * @param ipTwo the external BGP peer IP address
Luca Prete83bac342016-12-06 19:42:05 -0800231 * @param encap the encapsulation type
Jonathan Hart4cb39882015-08-12 23:50:55 -0400232 * @return the intents to install
233 */
234 private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700235 VlanId vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400236 IpAddress ipOne,
237 ConnectPoint portTwo,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700238 VlanId vlanTwo,
Luca Prete83bac342016-12-06 19:42:05 -0800239 IpAddress ipTwo,
240 EncapsulationType encap) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400241
242 List<PointToPointIntent> intents = new ArrayList<>();
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800243
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700244 TrafficTreatment.Builder treatmentToPeer = DefaultTrafficTreatment.builder();
245 TrafficTreatment.Builder treatmentToSpeaker = DefaultTrafficTreatment.builder();
246
Luca Prete83bac342016-12-06 19:42:05 -0800247 PointToPointIntent.Builder intentBuilder;
248
Jonathan Hart6ec68292014-11-14 15:09:30 -0800249 TrafficSelector selector;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200250 Key key;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800251
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800252 byte tcpProtocol;
253 byte icmpProtocol;
254
Jonathan Hart4cb39882015-08-12 23:50:55 -0400255 if (ipOne.isIp4()) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800256 tcpProtocol = IPv4.PROTOCOL_TCP;
257 icmpProtocol = IPv4.PROTOCOL_ICMP;
258 } else {
259 tcpProtocol = IPv6.PROTOCOL_TCP;
260 icmpProtocol = IPv6.PROTOCOL_ICMP6;
261 }
262
Luca Pretee9511512016-05-13 10:30:19 -0700263 // Add VLAN treatment for traffic going from BGP speaker to BGP peer
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700264 treatmentToPeer = applyVlanTreatment(vlanOne, vlanTwo, treatmentToPeer);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700265
Jonathan Hart51372182014-12-03 21:32:34 -0800266 // Path from BGP speaker to BGP peer matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800267 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700268 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400269 ipOne,
270 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700271 null,
272 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800273
Jonathan Hart9a426f82015-09-03 15:43:13 +0200274 key = buildKey(ipOne, ipTwo, SUFFIX_DST);
275
Luca Prete83bac342016-12-06 19:42:05 -0800276 intentBuilder = PointToPointIntent.builder()
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700277 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200278 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800279 .filteredIngressPoint(new FilteredConnectPoint(portOne))
280 .filteredEgressPoint(new FilteredConnectPoint(portTwo))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700281 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700282 .treatment(treatmentToPeer.build())
Luca Prete83bac342016-12-06 19:42:05 -0800283 .priority(PRIORITY_OFFSET);
284
285 encap(intentBuilder, encap);
286
287 intents.add(intentBuilder.build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800288
Jonathan Hart51372182014-12-03 21:32:34 -0800289 // Path from BGP speaker to BGP peer matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800290 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700291 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400292 ipOne,
293 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700294 BGP_PORT,
295 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800296
Jonathan Hart9a426f82015-09-03 15:43:13 +0200297 key = buildKey(ipOne, ipTwo, SUFFIX_SRC);
298
Luca Prete83bac342016-12-06 19:42:05 -0800299 intentBuilder = PointToPointIntent.builder()
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700300 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200301 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800302 .filteredIngressPoint(new FilteredConnectPoint(portOne))
303 .filteredEgressPoint(new FilteredConnectPoint(portTwo))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700304 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700305 .treatment(treatmentToPeer.build())
Luca Prete83bac342016-12-06 19:42:05 -0800306 .priority(PRIORITY_OFFSET);
307
308 encap(intentBuilder, encap);
309
310 intents.add(intentBuilder.build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800311
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700312 // ICMP path from BGP speaker to BGP peer
313 selector = buildSelector(icmpProtocol,
314 vlanOne,
315 ipOne,
316 ipTwo,
317 null,
318 null);
319
320 key = buildKey(ipOne, ipTwo, SUFFIX_ICMP);
321
Luca Prete83bac342016-12-06 19:42:05 -0800322 intentBuilder = PointToPointIntent.builder()
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700323 .appId(appId)
324 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800325 .filteredIngressPoint(new FilteredConnectPoint(portOne))
326 .filteredEgressPoint(new FilteredConnectPoint(portTwo))
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700327 .selector(selector)
328 .treatment(treatmentToPeer.build())
Luca Prete83bac342016-12-06 19:42:05 -0800329 .priority(PRIORITY_OFFSET);
330
331 encap(intentBuilder, encap);
332
333 intents.add(intentBuilder.build());
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700334
Luca Pretee9511512016-05-13 10:30:19 -0700335 // Add VLAN treatment for traffic going from BGP peer to BGP speaker
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700336 treatmentToSpeaker = applyVlanTreatment(vlanTwo, vlanOne, treatmentToSpeaker);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700337
Jonathan Hart51372182014-12-03 21:32:34 -0800338 // Path from BGP peer to BGP speaker matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800339 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700340 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400341 ipTwo,
342 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700343 null,
344 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800345
Jonathan Hart9a426f82015-09-03 15:43:13 +0200346 key = buildKey(ipTwo, ipOne, SUFFIX_DST);
347
Luca Prete83bac342016-12-06 19:42:05 -0800348 intentBuilder = PointToPointIntent.builder()
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700349 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200350 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800351 .filteredIngressPoint(new FilteredConnectPoint(portTwo))
352 .filteredEgressPoint(new FilteredConnectPoint(portOne))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700353 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700354 .treatment(treatmentToSpeaker.build())
Luca Prete83bac342016-12-06 19:42:05 -0800355 .priority(PRIORITY_OFFSET);
356
357 encap(intentBuilder, encap);
358
359 intents.add(intentBuilder.build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800360
Jonathan Hart51372182014-12-03 21:32:34 -0800361 // Path from BGP peer to BGP speaker matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800362 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700363 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400364 ipTwo,
365 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700366 BGP_PORT,
367 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800368
Jonathan Hart9a426f82015-09-03 15:43:13 +0200369 key = buildKey(ipTwo, ipOne, SUFFIX_SRC);
370
Luca Prete83bac342016-12-06 19:42:05 -0800371 intentBuilder = PointToPointIntent.builder()
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700372 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200373 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800374 .filteredIngressPoint(new FilteredConnectPoint(portTwo))
375 .filteredEgressPoint(new FilteredConnectPoint(portOne))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700376 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700377 .treatment(treatmentToSpeaker.build())
Luca Prete83bac342016-12-06 19:42:05 -0800378 .priority(PRIORITY_OFFSET);
379
380 encap(intentBuilder, encap);
381
382 intents.add(intentBuilder.build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800383
Jonathan Hart51372182014-12-03 21:32:34 -0800384 // ICMP path from BGP peer to BGP speaker
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800385 selector = buildSelector(icmpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700386 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400387 ipTwo,
388 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700389 null,
390 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800391
Jonathan Hart9a426f82015-09-03 15:43:13 +0200392 key = buildKey(ipTwo, ipOne, SUFFIX_ICMP);
393
Luca Prete83bac342016-12-06 19:42:05 -0800394 intentBuilder = PointToPointIntent.builder()
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700395 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200396 .key(key)
Luca Prete83bac342016-12-06 19:42:05 -0800397 .filteredIngressPoint(new FilteredConnectPoint(portTwo))
398 .filteredEgressPoint(new FilteredConnectPoint(portOne))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700399 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700400 .treatment(treatmentToSpeaker.build())
Luca Prete83bac342016-12-06 19:42:05 -0800401 .priority(PRIORITY_OFFSET);
402
403 encap(intentBuilder, encap);
404
405 intents.add(intentBuilder.build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800406
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800407 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800408 }
409
410 /**
411 * Builds a traffic selector based on the set of input parameters.
412 *
413 * @param ipProto IP protocol
414 * @param srcIp source IP address
415 * @param dstIp destination IP address
416 * @param srcTcpPort source TCP port, or null if shouldn't be set
417 * @param dstTcpPort destination TCP port, or null if shouldn't be set
418 * @return the new traffic selector
419 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700420 private TrafficSelector buildSelector(byte ipProto, VlanId ingressVlanId,
421 IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800422 IpAddress dstIp, Short srcTcpPort,
423 Short dstTcpPort) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100424 TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto);
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800425
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700426 // Match on VLAN Id if a VLAN Id configured on the ingress interface
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700427 if (!ingressVlanId.equals(VlanId.NONE)) {
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700428 builder.matchVlanId(ingressVlanId);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700429 }
430
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700431 if (dstIp.isIp4()) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100432 builder.matchEthType(Ethernet.TYPE_IPV4)
Luca Prete83bac342016-12-06 19:42:05 -0800433 .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
434 .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800435 } else {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100436 builder.matchEthType(Ethernet.TYPE_IPV6)
Luca Prete83bac342016-12-06 19:42:05 -0800437 .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
438 .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800439 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800440
441 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700442 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800443 }
444
445 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700446 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800447 }
448
449 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700450 }
451
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700452 /*
453 * Adds the VLAN Id treatment before building the intents, depending on how
454 * the VLAN Ids of the BGP speakers and the BGP peers are configured.
455 */
456 private TrafficTreatment.Builder applyVlanTreatment(VlanId vlanOne,
457 VlanId vlanTwo,
458 TrafficTreatment.Builder treatment) {
459 if (!vlanOne.equals(vlanTwo)) {
460 // VLANs are different. Do some VLAN treatment
461 if (vlanTwo.equals(VlanId.NONE)) {
462 // VLAN two is none. VLAN one is set. Do a pop
463 treatment.popVlan();
464 } else {
465 // Either both VLANs are set or vlanOne is not
466 if (vlanOne.equals(VlanId.NONE)) {
467 // VLAN one is none. VLAN two is set. Push the VLAN header
468 treatment.pushVlan();
469 }
470 // Set the VLAN Id to the egress VLAN Id
471 treatment.setVlanId(vlanTwo);
472 }
473 }
474 return treatment;
475 }
476
Jonathan Hart9a426f82015-09-03 15:43:13 +0200477 /**
478 * Builds an intent Key for a point-to-point intent based off the source
479 * and destination IP address, as well as a suffix String to distinguish
480 * between different types of intents between the same source and
481 * destination.
482 *
483 * @param srcIp source IP address
484 * @param dstIp destination IP address
485 * @param suffix suffix string
Jonathan Hart08105be2015-10-10 18:31:06 -0700486 * @return intent key
Jonathan Hart9a426f82015-09-03 15:43:13 +0200487 */
488 private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
489 String keyString = new StringBuilder()
490 .append(srcIp.toString())
491 .append("-")
492 .append(dstIp.toString())
493 .append("-")
494 .append(suffix)
495 .toString();
496
497 return Key.of(keyString, appId);
498 }
499
Luca Prete83bac342016-12-06 19:42:05 -0800500 /**
501 * Adds an encapsulation constraint to the builder given, if encap is not
502 * equal to NONE.
503 *
504 * @param builder the intent builder
505 * @param encap the encapsulation type
506 */
507 private static void encap(ConnectivityIntent.Builder builder,
508 EncapsulationType encap) {
509 if (!encap.equals(NONE)) {
510 builder.constraints(ImmutableList.of(
511 new EncapsulationConstraint(encap)));
512 }
513 }
514
Jonathan Hart08105be2015-10-10 18:31:06 -0700515 private class InternalNetworkConfigListener implements NetworkConfigListener {
516
517 @Override
518 public void event(NetworkConfigEvent event) {
519 switch (event.type()) {
520 case CONFIG_REGISTERED:
521 break;
522 case CONFIG_UNREGISTERED:
523 break;
524 case CONFIG_ADDED:
525 case CONFIG_UPDATED:
526 case CONFIG_REMOVED:
Luca Prete83bac342016-12-06 19:42:05 -0800527 if (event.configClass() == RoutingService.CONFIG_CLASS ||
528 event.configClass() == SdnIpConfig.class) {
Jonathan Hart08105be2015-10-10 18:31:06 -0700529 setUpConnectivity();
530 }
531 break;
532 default:
533 break;
534 }
535 }
536 }
537
Jonathan Hartb14221c2016-03-07 09:55:50 -0800538 private class InternalInterfaceListener implements InterfaceListener {
539 @Override
540 public void event(InterfaceEvent event) {
541 switch (event.type()) {
542 case INTERFACE_ADDED:
543 case INTERFACE_UPDATED:
544 case INTERFACE_REMOVED:
545 setUpConnectivity();
546 break;
547 default:
548 break;
549 }
550 }
551 }
552
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700553}