blob: 6b35a55d5c23b60300d3c0d34cceb7f6458d0145 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present 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;
Luca Prete8f2a3ce2016-03-29 16:13:01 -070024import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.ApplicationId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040026import org.onosproject.incubator.net.intf.Interface;
Jonathan Hartb14221c2016-03-07 09:55:50 -080027import org.onosproject.incubator.net.intf.InterfaceEvent;
28import org.onosproject.incubator.net.intf.InterfaceListener;
Jonathan Hart4cb39882015-08-12 23:50:55 -040029import org.onosproject.incubator.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.ConnectPoint;
Jonathan Hart08105be2015-10-10 18:31:06 -070031import org.onosproject.net.config.NetworkConfigEvent;
32import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart9a426f82015-09-03 15:43:13 +020033import org.onosproject.net.config.NetworkConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart2a9ea492015-07-30 15:53:04 -070038import org.onosproject.net.host.InterfaceIpAddress;
Luca Prete86ac7d12015-12-02 23:36:49 -080039import org.onosproject.net.intent.IntentUtils;
Jonathan Hart9a426f82015-09-03 15:43:13 +020040import org.onosproject.net.intent.Key;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.intent.PointToPointIntent;
Jonathan Hart9a426f82015-09-03 15:43:13 +020042import org.onosproject.routing.IntentSynchronizationService;
Jonathan Hart4cb39882015-08-12 23:50:55 -040043import org.onosproject.routing.RoutingService;
44import org.onosproject.routing.config.BgpConfig;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070045import org.slf4j.Logger;
46import org.slf4j.LoggerFactory;
47
Jonathan Hart41349e92015-02-09 14:14:02 -080048import java.util.ArrayList;
49import java.util.Collection;
Jonathan Hartb14221c2016-03-07 09:55:50 -080050import java.util.Collections;
Jonathan Hart08105be2015-10-10 18:31:06 -070051import java.util.HashMap;
Jonathan Hart41349e92015-02-09 14:14:02 -080052import java.util.List;
Jonathan Hart08105be2015-10-10 18:31:06 -070053import java.util.Map;
Jonathan Hartb14221c2016-03-07 09:55:50 -080054import java.util.Set;
Jonathan Hart41349e92015-02-09 14:14:02 -080055
Jonathan Hart4cb39882015-08-12 23:50:55 -040056import static com.google.common.base.Preconditions.checkNotNull;
57
Jonathan Hartdc711bd2014-10-15 11:24:23 -070058/**
59 * Manages the connectivity requirements between peers.
60 */
Jonathan Hartce430a42014-10-16 20:44:29 -070061public class PeerConnectivityManager {
Pavlin Radoslavov2aa1f322015-03-11 17:59:44 -070062 private static final int PRIORITY_OFFSET = 1000;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070063
Jonathan Hart9a426f82015-09-03 15:43:13 +020064 private static final String SUFFIX_DST = "dst";
65 private static final String SUFFIX_SRC = "src";
66 private static final String SUFFIX_ICMP = "icmp";
67
Jonathan Hartdc711bd2014-10-15 11:24:23 -070068 private static final Logger log = LoggerFactory.getLogger(
Jonathan Hartce430a42014-10-16 20:44:29 -070069 PeerConnectivityManager.class);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070070
Jonathan Hart41349e92015-02-09 14:14:02 -080071 private static final short BGP_PORT = 179;
72
Jonathan Hart9a426f82015-09-03 15:43:13 +020073 private final IntentSynchronizationService intentSynchronizer;
Jonathan Hart4cb39882015-08-12 23:50:55 -040074 private final NetworkConfigService configService;
75 private final InterfaceService interfaceService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070076
Thomas Vachuskab97cf282014-10-20 23:31:12 -070077 private final ApplicationId appId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040078 private final ApplicationId routerAppId;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070079
Jonathan Hart08105be2015-10-10 18:31:06 -070080 private final Map<Key, PointToPointIntent> peerIntents;
81
82 private final InternalNetworkConfigListener configListener
83 = new InternalNetworkConfigListener();
Jonathan Hart9a426f82015-09-03 15:43:13 +020084
Jonathan Hartb14221c2016-03-07 09:55:50 -080085 private final InternalInterfaceListener interfaceListener
86 = new InternalInterfaceListener();
87
Jonathan Hart31582d12014-10-22 13:52:41 -070088 /**
89 * Creates a new PeerConnectivityManager.
90 *
Jonathan Hart51372182014-12-03 21:32:34 -080091 * @param appId the application ID
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -080092 * @param intentSynchronizer the intent synchronizer
Jonathan Hartb14221c2016-03-07 09:55:50 -080093 * @param configService the network config service
Ray Milkey9b36d812015-09-09 15:24:54 -070094 * @param routerAppId application ID
Jonathan Hartb14221c2016-03-07 09:55:50 -080095 * @param interfaceService the interface service
Jonathan Hart31582d12014-10-22 13:52:41 -070096 */
Thomas Vachuskab97cf282014-10-20 23:31:12 -070097 public PeerConnectivityManager(ApplicationId appId,
Jonathan Hart9a426f82015-09-03 15:43:13 +020098 IntentSynchronizationService intentSynchronizer,
Jonathan Hart4cb39882015-08-12 23:50:55 -040099 NetworkConfigService configService,
100 ApplicationId routerAppId,
101 InterfaceService interfaceService) {
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700102 this.appId = appId;
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800103 this.intentSynchronizer = intentSynchronizer;
Jonathan Hart31582d12014-10-22 13:52:41 -0700104 this.configService = configService;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400105 this.routerAppId = routerAppId;
106 this.interfaceService = interfaceService;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200107
Jonathan Hart08105be2015-10-10 18:31:06 -0700108 peerIntents = new HashMap<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700109 }
110
Jonathan Hart31582d12014-10-22 13:52:41 -0700111 /**
112 * Starts the peer connectivity manager.
113 */
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700114 public void start() {
Jonathan Hart08105be2015-10-10 18:31:06 -0700115 configService.addListener(configListener);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800116 interfaceService.addListener(interfaceListener);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800117 setUpConnectivity();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700118 }
119
120 /**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800121 * Stops the peer connectivity manager.
122 */
123 public void stop() {
Jonathan Hart08105be2015-10-10 18:31:06 -0700124 configService.removeListener(configListener);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800125 interfaceService.removeListener(interfaceListener);
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800126 }
127
128 /**
Jonathan Hart6ec68292014-11-14 15:09:30 -0800129 * Sets up paths to establish connectivity between all internal
Jonathan Hart4cb39882015-08-12 23:50:55 -0400130 * BGP speakers and external BGP peers.
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700131 */
Jonathan Hart6ec68292014-11-14 15:09:30 -0800132 private void setUpConnectivity() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400133 BgpConfig config = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
134
Jonathan Hartb14221c2016-03-07 09:55:50 -0800135 Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers;
136
Jonathan Hart4cb39882015-08-12 23:50:55 -0400137 if (config == null) {
Jonathan Hartb14221c2016-03-07 09:55:50 -0800138 log.warn("No BGP config available");
139 bgpSpeakers = Collections.emptySet();
140 } else {
141 bgpSpeakers = config.bgpSpeakers();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400142 }
143
Jonathan Hart08105be2015-10-10 18:31:06 -0700144 Map<Key, PointToPointIntent> existingIntents = new HashMap<>(peerIntents);
145
Jonathan Hartb14221c2016-03-07 09:55:50 -0800146 for (BgpConfig.BgpSpeakerConfig bgpSpeaker : bgpSpeakers) {
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700147 log.debug("Start to set up BGP paths for BGP speaker: {}",
Jonathan Hart4cb39882015-08-12 23:50:55 -0400148 bgpSpeaker);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700149
Jonathan Hart9a426f82015-09-03 15:43:13 +0200150 buildSpeakerIntents(bgpSpeaker).forEach(i -> {
Jonathan Hart08105be2015-10-10 18:31:06 -0700151 PointToPointIntent intent = existingIntents.remove(i.key());
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800152 if (intent == null || !IntentUtils.intentsAreEqual(i, intent)) {
Jonathan Hart08105be2015-10-10 18:31:06 -0700153 peerIntents.put(i.key(), i);
154 intentSynchronizer.submit(i);
155 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200156 });
Jonathan Hart9a426f82015-09-03 15:43:13 +0200157 }
Jonathan Hart08105be2015-10-10 18:31:06 -0700158
159 // Remove any remaining intents that we used to have that we don't need
160 // anymore
161 existingIntents.values().forEach(i -> {
162 peerIntents.remove(i.key());
163 intentSynchronizer.withdraw(i);
164 });
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700165 }
166
Jonathan Hart4cb39882015-08-12 23:50:55 -0400167 private Collection<PointToPointIntent> buildSpeakerIntents(BgpConfig.BgpSpeakerConfig speaker) {
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800168 List<PointToPointIntent> intents = new ArrayList<>();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700169
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700170 // Get the BGP Speaker VLAN Id
171 VlanId bgpSpeakerVlanId = speaker.vlan();
172
Jonathan Hart4cb39882015-08-12 23:50:55 -0400173 for (IpAddress peerAddress : speaker.peers()) {
174 Interface peeringInterface = interfaceService.getMatchingInterface(peerAddress);
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700175
Jonathan Hart4cb39882015-08-12 23:50:55 -0400176 if (peeringInterface == null) {
177 log.debug("No peering interface found for peer {} on speaker {}",
178 peerAddress, speaker);
Jonathan Harte30fcda2015-08-06 16:22:34 -0700179 continue;
180 }
181
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700182 IpAddress bgpSpeakerAddress = null;
183 for (InterfaceIpAddress address : peeringInterface.ipAddressesList()) {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400184 if (address.subnetAddress().contains(peerAddress)) {
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700185 bgpSpeakerAddress = address.ipAddress();
Jonathan Harte30fcda2015-08-06 16:22:34 -0700186 break;
Jonathan Hart2a9ea492015-07-30 15:53:04 -0700187 }
Jonathan Harte30fcda2015-08-06 16:22:34 -0700188 }
Jonathan Hart4cb39882015-08-12 23:50:55 -0400189
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700190 checkNotNull(bgpSpeakerAddress);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400191
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700192 VlanId peerVlanId = peeringInterface.vlan();
193
194 intents.addAll(buildIntents(speaker.connectPoint(), bgpSpeakerVlanId,
195 bgpSpeakerAddress,
196 peeringInterface.connectPoint(),
197 peerVlanId,
198 peerAddress));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800199 }
200
Jonathan Hart4cb39882015-08-12 23:50:55 -0400201 return intents;
202 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800203
Jonathan Hart4cb39882015-08-12 23:50:55 -0400204 /**
Luca Pretee9511512016-05-13 10:30:19 -0700205 * Builds the required intents between a BGP speaker and an external router.
Jonathan Hart4cb39882015-08-12 23:50:55 -0400206 *
Luca Pretee9511512016-05-13 10:30:19 -0700207 * @param portOne the BGP speaker connect point
208 * @param vlanOne the BGP speaker VLAN
209 * @param ipOne the BGP speaker IP address
210 * @param portTwo the external BGP peer connect point
211 * @param vlanTwo the external BGP peer VLAN
212 * @param ipTwo the external BGP peer IP address
Jonathan Hart4cb39882015-08-12 23:50:55 -0400213 * @return the intents to install
214 */
215 private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700216 VlanId vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400217 IpAddress ipOne,
218 ConnectPoint portTwo,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700219 VlanId vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400220 IpAddress ipTwo) {
221
222 List<PointToPointIntent> intents = new ArrayList<>();
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800223
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700224 TrafficTreatment.Builder treatmentToPeer = DefaultTrafficTreatment.builder();
225 TrafficTreatment.Builder treatmentToSpeaker = DefaultTrafficTreatment.builder();
226
Jonathan Hart6ec68292014-11-14 15:09:30 -0800227 TrafficSelector selector;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200228 Key key;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800229
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800230 byte tcpProtocol;
231 byte icmpProtocol;
232
Jonathan Hart4cb39882015-08-12 23:50:55 -0400233 if (ipOne.isIp4()) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800234 tcpProtocol = IPv4.PROTOCOL_TCP;
235 icmpProtocol = IPv4.PROTOCOL_ICMP;
236 } else {
237 tcpProtocol = IPv6.PROTOCOL_TCP;
238 icmpProtocol = IPv6.PROTOCOL_ICMP6;
239 }
240
Luca Pretee9511512016-05-13 10:30:19 -0700241 // Add VLAN treatment for traffic going from BGP speaker to BGP peer
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700242 treatmentToPeer = applyVlanTreatment(vlanOne, vlanTwo, treatmentToPeer);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700243
Jonathan Hart51372182014-12-03 21:32:34 -0800244 // Path from BGP speaker to BGP peer matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800245 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700246 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400247 ipOne,
248 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700249 null,
250 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800251
Jonathan Hart9a426f82015-09-03 15:43:13 +0200252 key = buildKey(ipOne, ipTwo, SUFFIX_DST);
253
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700254 intents.add(PointToPointIntent.builder()
255 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200256 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700257 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700258 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400259 .ingressPoint(portOne)
260 .egressPoint(portTwo)
261 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700262 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800263
Jonathan Hart51372182014-12-03 21:32:34 -0800264 // Path from BGP speaker to BGP peer matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800265 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700266 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400267 ipOne,
268 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700269 BGP_PORT,
270 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800271
Jonathan Hart9a426f82015-09-03 15:43:13 +0200272 key = buildKey(ipOne, ipTwo, SUFFIX_SRC);
273
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700274 intents.add(PointToPointIntent.builder()
275 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200276 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700277 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700278 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400279 .ingressPoint(portOne)
280 .egressPoint(portTwo)
281 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700282 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800283
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700284 // ICMP path from BGP speaker to BGP peer
285 selector = buildSelector(icmpProtocol,
286 vlanOne,
287 ipOne,
288 ipTwo,
289 null,
290 null);
291
292 key = buildKey(ipOne, ipTwo, SUFFIX_ICMP);
293
294 intents.add(PointToPointIntent.builder()
295 .appId(appId)
296 .key(key)
297 .selector(selector)
298 .treatment(treatmentToPeer.build())
299 .ingressPoint(portOne)
300 .egressPoint(portTwo)
301 .priority(PRIORITY_OFFSET)
302 .build());
303
Luca Pretee9511512016-05-13 10:30:19 -0700304 // Add VLAN treatment for traffic going from BGP peer to BGP speaker
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700305 treatmentToSpeaker = applyVlanTreatment(vlanTwo, vlanOne, treatmentToSpeaker);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700306
Jonathan Hart51372182014-12-03 21:32:34 -0800307 // Path from BGP peer to BGP speaker matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800308 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700309 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400310 ipTwo,
311 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700312 null,
313 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800314
Jonathan Hart9a426f82015-09-03 15:43:13 +0200315 key = buildKey(ipTwo, ipOne, SUFFIX_DST);
316
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700317 intents.add(PointToPointIntent.builder()
318 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200319 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700320 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700321 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400322 .ingressPoint(portTwo)
323 .egressPoint(portOne)
324 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700325 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800326
Jonathan Hart51372182014-12-03 21:32:34 -0800327 // Path from BGP peer to BGP speaker matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800328 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700329 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400330 ipTwo,
331 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700332 BGP_PORT,
333 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800334
Jonathan Hart9a426f82015-09-03 15:43:13 +0200335 key = buildKey(ipTwo, ipOne, SUFFIX_SRC);
336
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700337 intents.add(PointToPointIntent.builder()
338 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200339 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700340 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700341 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400342 .ingressPoint(portTwo)
343 .egressPoint(portOne)
344 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700345 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800346
Jonathan Hart51372182014-12-03 21:32:34 -0800347 // ICMP path from BGP peer to BGP speaker
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800348 selector = buildSelector(icmpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700349 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400350 ipTwo,
351 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700352 null,
353 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800354
Jonathan Hart9a426f82015-09-03 15:43:13 +0200355 key = buildKey(ipTwo, ipOne, SUFFIX_ICMP);
356
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700357 intents.add(PointToPointIntent.builder()
358 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200359 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700360 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700361 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400362 .ingressPoint(portTwo)
363 .egressPoint(portOne)
364 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700365 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800366
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800367 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800368 }
369
370 /**
371 * Builds a traffic selector based on the set of input parameters.
372 *
373 * @param ipProto IP protocol
374 * @param srcIp source IP address
375 * @param dstIp destination IP address
376 * @param srcTcpPort source TCP port, or null if shouldn't be set
377 * @param dstTcpPort destination TCP port, or null if shouldn't be set
378 * @return the new traffic selector
379 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700380 private TrafficSelector buildSelector(byte ipProto, VlanId ingressVlanId,
381 IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800382 IpAddress dstIp, Short srcTcpPort,
383 Short dstTcpPort) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100384 TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto);
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800385
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700386 // Match on VLAN Id if a VLAN Id configured on the ingress interface
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700387 if (!ingressVlanId.equals(VlanId.NONE)) {
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700388 builder.matchVlanId(ingressVlanId);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700389 }
390
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700391 if (dstIp.isIp4()) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100392 builder.matchEthType(Ethernet.TYPE_IPV4)
393 .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400394 .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800395 } else {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100396 builder.matchEthType(Ethernet.TYPE_IPV6)
397 .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400398 .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800399 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800400
401 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700402 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800403 }
404
405 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700406 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800407 }
408
409 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700410 }
411
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700412 /*
413 * Adds the VLAN Id treatment before building the intents, depending on how
414 * the VLAN Ids of the BGP speakers and the BGP peers are configured.
415 */
416 private TrafficTreatment.Builder applyVlanTreatment(VlanId vlanOne,
417 VlanId vlanTwo,
418 TrafficTreatment.Builder treatment) {
419 if (!vlanOne.equals(vlanTwo)) {
420 // VLANs are different. Do some VLAN treatment
421 if (vlanTwo.equals(VlanId.NONE)) {
422 // VLAN two is none. VLAN one is set. Do a pop
423 treatment.popVlan();
424 } else {
425 // Either both VLANs are set or vlanOne is not
426 if (vlanOne.equals(VlanId.NONE)) {
427 // VLAN one is none. VLAN two is set. Push the VLAN header
428 treatment.pushVlan();
429 }
430 // Set the VLAN Id to the egress VLAN Id
431 treatment.setVlanId(vlanTwo);
432 }
433 }
434 return treatment;
435 }
436
Jonathan Hart9a426f82015-09-03 15:43:13 +0200437 /**
438 * Builds an intent Key for a point-to-point intent based off the source
439 * and destination IP address, as well as a suffix String to distinguish
440 * between different types of intents between the same source and
441 * destination.
442 *
443 * @param srcIp source IP address
444 * @param dstIp destination IP address
445 * @param suffix suffix string
Jonathan Hart08105be2015-10-10 18:31:06 -0700446 * @return intent key
Jonathan Hart9a426f82015-09-03 15:43:13 +0200447 */
448 private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
449 String keyString = new StringBuilder()
450 .append(srcIp.toString())
451 .append("-")
452 .append(dstIp.toString())
453 .append("-")
454 .append(suffix)
455 .toString();
456
457 return Key.of(keyString, appId);
458 }
459
Jonathan Hart08105be2015-10-10 18:31:06 -0700460 private class InternalNetworkConfigListener implements NetworkConfigListener {
461
462 @Override
463 public void event(NetworkConfigEvent event) {
464 switch (event.type()) {
465 case CONFIG_REGISTERED:
466 break;
467 case CONFIG_UNREGISTERED:
468 break;
469 case CONFIG_ADDED:
470 case CONFIG_UPDATED:
471 case CONFIG_REMOVED:
472 if (event.configClass() == RoutingService.CONFIG_CLASS) {
473 setUpConnectivity();
474 }
475 break;
476 default:
477 break;
478 }
479 }
480 }
481
Jonathan Hartb14221c2016-03-07 09:55:50 -0800482 private class InternalInterfaceListener implements InterfaceListener {
483 @Override
484 public void event(InterfaceEvent event) {
485 switch (event.type()) {
486 case INTERFACE_ADDED:
487 case INTERFACE_UPDATED:
488 case INTERFACE_REMOVED:
489 setUpConnectivity();
490 break;
491 default:
492 break;
493 }
494 }
495 }
496
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700497}