blob: 8a68db20255f0e635705bca14f751ceb2ccf216c [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
242 if (!vlanOne.equals(vlanTwo)) {
243 if (vlanTwo.equals(VlanId.NONE)) {
244 treatmentToPeer.popVlan();
245 } else {
246 treatmentToPeer.setVlanId(vlanTwo);
247 }
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700248 }
249
Jonathan Hart51372182014-12-03 21:32:34 -0800250 // Path from BGP speaker to BGP peer matching destination TCP port 179
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700251
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800252 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700253 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400254 ipOne,
255 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700256 null,
257 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800258
Jonathan Hart9a426f82015-09-03 15:43:13 +0200259 key = buildKey(ipOne, ipTwo, SUFFIX_DST);
260
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700261 intents.add(PointToPointIntent.builder()
262 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200263 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700264 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700265 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400266 .ingressPoint(portOne)
267 .egressPoint(portTwo)
268 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700269 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800270
Jonathan Hart51372182014-12-03 21:32:34 -0800271 // Path from BGP speaker to BGP peer matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800272 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700273 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400274 ipOne,
275 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700276 BGP_PORT,
277 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800278
Jonathan Hart9a426f82015-09-03 15:43:13 +0200279 key = buildKey(ipOne, ipTwo, SUFFIX_SRC);
280
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700281 intents.add(PointToPointIntent.builder()
282 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200283 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700284 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700285 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400286 .ingressPoint(portOne)
287 .egressPoint(portTwo)
288 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700289 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800290
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700291 // ICMP path from BGP speaker to BGP peer
292 selector = buildSelector(icmpProtocol,
293 vlanOne,
294 ipOne,
295 ipTwo,
296 null,
297 null);
298
299 key = buildKey(ipOne, ipTwo, SUFFIX_ICMP);
300
301 intents.add(PointToPointIntent.builder()
302 .appId(appId)
303 .key(key)
304 .selector(selector)
305 .treatment(treatmentToPeer.build())
306 .ingressPoint(portOne)
307 .egressPoint(portTwo)
308 .priority(PRIORITY_OFFSET)
309 .build());
310
Luca Pretee9511512016-05-13 10:30:19 -0700311 // Add VLAN treatment for traffic going from BGP peer to BGP speaker
312 if (!vlanTwo.equals(vlanOne)) {
313 if (vlanOne.equals(VlanId.NONE)) {
314 treatmentToSpeaker.popVlan();
315 } else {
316 treatmentToSpeaker.setVlanId(vlanOne);
317 }
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700318 }
319
Jonathan Hart51372182014-12-03 21:32:34 -0800320 // Path from BGP peer to BGP speaker matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800321 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700322 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400323 ipTwo,
324 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700325 null,
326 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800327
Jonathan Hart9a426f82015-09-03 15:43:13 +0200328 key = buildKey(ipTwo, ipOne, SUFFIX_DST);
329
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700330 intents.add(PointToPointIntent.builder()
331 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200332 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700333 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700334 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400335 .ingressPoint(portTwo)
336 .egressPoint(portOne)
337 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700338 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800339
Jonathan Hart51372182014-12-03 21:32:34 -0800340 // Path from BGP peer to BGP speaker matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800341 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700342 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400343 ipTwo,
344 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700345 BGP_PORT,
346 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800347
Jonathan Hart9a426f82015-09-03 15:43:13 +0200348 key = buildKey(ipTwo, ipOne, SUFFIX_SRC);
349
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700350 intents.add(PointToPointIntent.builder()
351 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200352 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700353 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700354 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400355 .ingressPoint(portTwo)
356 .egressPoint(portOne)
357 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700358 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800359
Jonathan Hart51372182014-12-03 21:32:34 -0800360 // ICMP path from BGP peer to BGP speaker
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800361 selector = buildSelector(icmpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700362 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400363 ipTwo,
364 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700365 null,
366 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800367
Jonathan Hart9a426f82015-09-03 15:43:13 +0200368 key = buildKey(ipTwo, ipOne, SUFFIX_ICMP);
369
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700370 intents.add(PointToPointIntent.builder()
371 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200372 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700373 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700374 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400375 .ingressPoint(portTwo)
376 .egressPoint(portOne)
377 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700378 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800379
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800380 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800381 }
382
383 /**
384 * Builds a traffic selector based on the set of input parameters.
385 *
386 * @param ipProto IP protocol
387 * @param srcIp source IP address
388 * @param dstIp destination IP address
389 * @param srcTcpPort source TCP port, or null if shouldn't be set
390 * @param dstTcpPort destination TCP port, or null if shouldn't be set
391 * @return the new traffic selector
392 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700393 private TrafficSelector buildSelector(byte ipProto, VlanId ingressVlanId,
394 IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800395 IpAddress dstIp, Short srcTcpPort,
396 Short dstTcpPort) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100397 TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto);
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800398
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700399 // Match on any VLAN Id if a VLAN Id configured on the ingress interface
400 if (!ingressVlanId.equals(VlanId.NONE)) {
401 builder.matchVlanId(VlanId.ANY);
402 }
403
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700404 if (dstIp.isIp4()) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100405 builder.matchEthType(Ethernet.TYPE_IPV4)
406 .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400407 .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800408 } else {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100409 builder.matchEthType(Ethernet.TYPE_IPV6)
410 .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400411 .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800412 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800413
414 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700415 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800416 }
417
418 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700419 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800420 }
421
422 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700423 }
424
Jonathan Hart9a426f82015-09-03 15:43:13 +0200425 /**
426 * Builds an intent Key for a point-to-point intent based off the source
427 * and destination IP address, as well as a suffix String to distinguish
428 * between different types of intents between the same source and
429 * destination.
430 *
431 * @param srcIp source IP address
432 * @param dstIp destination IP address
433 * @param suffix suffix string
Jonathan Hart08105be2015-10-10 18:31:06 -0700434 * @return intent key
Jonathan Hart9a426f82015-09-03 15:43:13 +0200435 */
436 private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
437 String keyString = new StringBuilder()
438 .append(srcIp.toString())
439 .append("-")
440 .append(dstIp.toString())
441 .append("-")
442 .append(suffix)
443 .toString();
444
445 return Key.of(keyString, appId);
446 }
447
Jonathan Hart08105be2015-10-10 18:31:06 -0700448 private class InternalNetworkConfigListener implements NetworkConfigListener {
449
450 @Override
451 public void event(NetworkConfigEvent event) {
452 switch (event.type()) {
453 case CONFIG_REGISTERED:
454 break;
455 case CONFIG_UNREGISTERED:
456 break;
457 case CONFIG_ADDED:
458 case CONFIG_UPDATED:
459 case CONFIG_REMOVED:
460 if (event.configClass() == RoutingService.CONFIG_CLASS) {
461 setUpConnectivity();
462 }
463 break;
464 default:
465 break;
466 }
467 }
468 }
469
Jonathan Hartb14221c2016-03-07 09:55:50 -0800470 private class InternalInterfaceListener implements InterfaceListener {
471 @Override
472 public void event(InterfaceEvent event) {
473 switch (event.type()) {
474 case INTERFACE_ADDED:
475 case INTERFACE_UPDATED:
476 case INTERFACE_REMOVED:
477 setUpConnectivity();
478 break;
479 default:
480 break;
481 }
482 }
483 }
484
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700485}