blob: 96bfecadc9ba5a5a33080a0de6478459cd3bfe8f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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 /**
205 * Builds the required intents between the two pairs of connect points and
206 * IP addresses.
207 *
208 * @param portOne the first connect point
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700209 * @param vlanOne the ingress VLAN
Jonathan Hart4cb39882015-08-12 23:50:55 -0400210 * @param ipOne the first IP address
211 * @param portTwo the second connect point
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700212 * @param vlanTwo the egress VLAN
Jonathan Hart4cb39882015-08-12 23:50:55 -0400213 * @param ipTwo the second IP address
214 * @return the intents to install
215 */
216 private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700217 VlanId vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400218 IpAddress ipOne,
219 ConnectPoint portTwo,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700220 VlanId vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400221 IpAddress ipTwo) {
222
223 List<PointToPointIntent> intents = new ArrayList<>();
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800224
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700225 TrafficTreatment.Builder treatmentToPeer = DefaultTrafficTreatment.builder();
226 TrafficTreatment.Builder treatmentToSpeaker = DefaultTrafficTreatment.builder();
227
Jonathan Hart6ec68292014-11-14 15:09:30 -0800228 TrafficSelector selector;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200229 Key key;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800230
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800231 byte tcpProtocol;
232 byte icmpProtocol;
233
Jonathan Hart4cb39882015-08-12 23:50:55 -0400234 if (ipOne.isIp4()) {
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800235 tcpProtocol = IPv4.PROTOCOL_TCP;
236 icmpProtocol = IPv4.PROTOCOL_ICMP;
237 } else {
238 tcpProtocol = IPv6.PROTOCOL_TCP;
239 icmpProtocol = IPv6.PROTOCOL_ICMP6;
240 }
241
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700242 // Add treatment for VLAN for traffic going from BGP speaker to BGP peer
243 if (!vlanTwo.equals(VlanId.NONE)) {
244 treatmentToPeer.setVlanId(vlanTwo);
245 }
246
Jonathan Hart51372182014-12-03 21:32:34 -0800247 // Path from BGP speaker to BGP peer matching destination TCP port 179
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700248
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800249 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700250 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400251 ipOne,
252 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700253 null,
254 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800255
Jonathan Hart9a426f82015-09-03 15:43:13 +0200256 key = buildKey(ipOne, ipTwo, SUFFIX_DST);
257
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700258 intents.add(PointToPointIntent.builder()
259 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200260 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700261 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700262 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400263 .ingressPoint(portOne)
264 .egressPoint(portTwo)
265 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700266 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800267
Jonathan Hart51372182014-12-03 21:32:34 -0800268 // Path from BGP speaker to BGP peer matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800269 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700270 vlanOne,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400271 ipOne,
272 ipTwo,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700273 BGP_PORT,
274 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800275
Jonathan Hart9a426f82015-09-03 15:43:13 +0200276 key = buildKey(ipOne, ipTwo, SUFFIX_SRC);
277
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700278 intents.add(PointToPointIntent.builder()
279 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200280 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700281 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700282 .treatment(treatmentToPeer.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400283 .ingressPoint(portOne)
284 .egressPoint(portTwo)
285 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700286 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800287
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700288 // ICMP path from BGP speaker to BGP peer
289 selector = buildSelector(icmpProtocol,
290 vlanOne,
291 ipOne,
292 ipTwo,
293 null,
294 null);
295
296 key = buildKey(ipOne, ipTwo, SUFFIX_ICMP);
297
298 intents.add(PointToPointIntent.builder()
299 .appId(appId)
300 .key(key)
301 .selector(selector)
302 .treatment(treatmentToPeer.build())
303 .ingressPoint(portOne)
304 .egressPoint(portTwo)
305 .priority(PRIORITY_OFFSET)
306 .build());
307
308 // Add treatment for VLAN for traffic going from BGP peer to BGP speaker
309 if (!vlanOne.equals(VlanId.NONE)) {
310 treatmentToSpeaker.setVlanId(vlanOne);
311 }
312
Jonathan Hart51372182014-12-03 21:32:34 -0800313 // Path from BGP peer to BGP speaker matching destination TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800314 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700315 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400316 ipTwo,
317 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700318 null,
319 BGP_PORT);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800320
Jonathan Hart9a426f82015-09-03 15:43:13 +0200321 key = buildKey(ipTwo, ipOne, SUFFIX_DST);
322
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700323 intents.add(PointToPointIntent.builder()
324 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200325 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700326 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700327 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400328 .ingressPoint(portTwo)
329 .egressPoint(portOne)
330 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700331 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800332
Jonathan Hart51372182014-12-03 21:32:34 -0800333 // Path from BGP peer to BGP speaker matching source TCP port 179
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800334 selector = buildSelector(tcpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700335 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400336 ipTwo,
337 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700338 BGP_PORT,
339 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800340
Jonathan Hart9a426f82015-09-03 15:43:13 +0200341 key = buildKey(ipTwo, ipOne, SUFFIX_SRC);
342
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700343 intents.add(PointToPointIntent.builder()
344 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200345 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700346 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700347 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400348 .ingressPoint(portTwo)
349 .egressPoint(portOne)
350 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700351 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800352
Jonathan Hart51372182014-12-03 21:32:34 -0800353 // ICMP path from BGP peer to BGP speaker
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800354 selector = buildSelector(icmpProtocol,
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700355 vlanTwo,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400356 ipTwo,
357 ipOne,
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700358 null,
359 null);
Jonathan Hart6ec68292014-11-14 15:09:30 -0800360
Jonathan Hart9a426f82015-09-03 15:43:13 +0200361 key = buildKey(ipTwo, ipOne, SUFFIX_ICMP);
362
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700363 intents.add(PointToPointIntent.builder()
364 .appId(appId)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200365 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700366 .selector(selector)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700367 .treatment(treatmentToSpeaker.build())
Jonathan Hart4cb39882015-08-12 23:50:55 -0400368 .ingressPoint(portTwo)
369 .egressPoint(portOne)
370 .priority(PRIORITY_OFFSET)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700371 .build());
Jonathan Hart6ec68292014-11-14 15:09:30 -0800372
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800373 return intents;
Jonathan Hart6ec68292014-11-14 15:09:30 -0800374 }
375
376 /**
377 * Builds a traffic selector based on the set of input parameters.
378 *
379 * @param ipProto IP protocol
380 * @param srcIp source IP address
381 * @param dstIp destination IP address
382 * @param srcTcpPort source TCP port, or null if shouldn't be set
383 * @param dstTcpPort destination TCP port, or null if shouldn't be set
384 * @return the new traffic selector
385 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700386 private TrafficSelector buildSelector(byte ipProto, VlanId ingressVlanId,
387 IpAddress srcIp,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800388 IpAddress dstIp, Short srcTcpPort,
389 Short dstTcpPort) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100390 TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto);
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800391
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700392 // Match on any VLAN Id if a VLAN Id configured on the ingress interface
393 if (!ingressVlanId.equals(VlanId.NONE)) {
394 builder.matchVlanId(VlanId.ANY);
395 }
396
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700397 if (dstIp.isIp4()) {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100398 builder.matchEthType(Ethernet.TYPE_IPV4)
399 .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400400 .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800401 } else {
Pier Luigi Ventreb38243f2015-11-11 13:01:37 +0100402 builder.matchEthType(Ethernet.TYPE_IPV6)
403 .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
Jonathan Hart4cb39882015-08-12 23:50:55 -0400404 .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
Kunihiro Ishiguro6e2ee152015-01-20 16:57:54 -0800405 }
Jonathan Hart6ec68292014-11-14 15:09:30 -0800406
407 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700408 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800409 }
410
411 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700412 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hart6ec68292014-11-14 15:09:30 -0800413 }
414
415 return builder.build();
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700416 }
417
Jonathan Hart9a426f82015-09-03 15:43:13 +0200418 /**
419 * Builds an intent Key for a point-to-point intent based off the source
420 * and destination IP address, as well as a suffix String to distinguish
421 * between different types of intents between the same source and
422 * destination.
423 *
424 * @param srcIp source IP address
425 * @param dstIp destination IP address
426 * @param suffix suffix string
Jonathan Hart08105be2015-10-10 18:31:06 -0700427 * @return intent key
Jonathan Hart9a426f82015-09-03 15:43:13 +0200428 */
429 private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
430 String keyString = new StringBuilder()
431 .append(srcIp.toString())
432 .append("-")
433 .append(dstIp.toString())
434 .append("-")
435 .append(suffix)
436 .toString();
437
438 return Key.of(keyString, appId);
439 }
440
Jonathan Hart08105be2015-10-10 18:31:06 -0700441 private class InternalNetworkConfigListener implements NetworkConfigListener {
442
443 @Override
444 public void event(NetworkConfigEvent event) {
445 switch (event.type()) {
446 case CONFIG_REGISTERED:
447 break;
448 case CONFIG_UNREGISTERED:
449 break;
450 case CONFIG_ADDED:
451 case CONFIG_UPDATED:
452 case CONFIG_REMOVED:
453 if (event.configClass() == RoutingService.CONFIG_CLASS) {
454 setUpConnectivity();
455 }
456 break;
457 default:
458 break;
459 }
460 }
461 }
462
Jonathan Hartb14221c2016-03-07 09:55:50 -0800463 private class InternalInterfaceListener implements InterfaceListener {
464 @Override
465 public void event(InterfaceEvent event) {
466 switch (event.type()) {
467 case INTERFACE_ADDED:
468 case INTERFACE_UPDATED:
469 case INTERFACE_REMOVED:
470 setUpConnectivity();
471 break;
472 default:
473 break;
474 }
475 }
476 }
477
Jonathan Hartdc711bd2014-10-15 11:24:23 -0700478}