blob: 77ec36a335e54aff780503d1543a0b5107fd77b6 [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 Hartce430a42014-10-16 20:44:29 -070017
Sho SHIMIZU891162b2016-06-06 16:32:01 -070018import com.google.common.collect.ImmutableList;
Jonathan Harte30fcda2015-08-06 16:22:34 -070019import com.google.common.collect.Sets;
Jonathan Hartce430a42014-10-16 20:44:29 -070020import org.junit.Before;
Jonathan Hartce430a42014-10-16 20:44:29 -070021import org.junit.Test;
Jonathan Hart51372182014-12-03 21:32:34 -080022import org.onlab.packet.Ethernet;
23import org.onlab.packet.IPv4;
24import org.onlab.packet.IpAddress;
25import org.onlab.packet.IpPrefix;
26import org.onlab.packet.MacAddress;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070027import org.onlab.packet.TpPort;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080028import org.onlab.packet.VlanId;
Jonathan Hart9a426f82015-09-03 15:43:13 +020029import org.onosproject.TestApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.core.ApplicationId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040031import org.onosproject.incubator.net.intf.Interface;
Jonathan Hartb14221c2016-03-07 09:55:50 -080032import org.onosproject.incubator.net.intf.InterfaceListener;
Jonathan Hart4cb39882015-08-12 23:50:55 -040033import org.onosproject.incubator.net.intf.InterfaceService;
Thomas Vachuska2048c1f2017-05-10 19:32:22 -070034import org.onosproject.intentsync.IntentSynchronizationService;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.DeviceId;
Luca Prete83bac342016-12-06 19:42:05 -080037import org.onosproject.net.EncapsulationType;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.PortNumber;
Jonathan Hart08105be2015-10-10 18:31:06 -070039import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart9a426f82015-09-03 15:43:13 +020040import org.onosproject.net.config.NetworkConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.flow.DefaultTrafficSelector;
42import org.onosproject.net.flow.DefaultTrafficTreatment;
43import org.onosproject.net.flow.TrafficSelector;
44import org.onosproject.net.flow.TrafficTreatment;
45import org.onosproject.net.host.InterfaceIpAddress;
46import org.onosproject.net.intent.AbstractIntentTest;
47import org.onosproject.net.intent.Intent;
Jonathan Hart9a426f82015-09-03 15:43:13 +020048import org.onosproject.net.intent.Key;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.intent.PointToPointIntent;
Jonathan Hart4cb39882015-08-12 23:50:55 -040050import org.onosproject.routing.config.BgpConfig;
Luca Prete83bac342016-12-06 19:42:05 -080051import org.onosproject.sdnip.config.SdnIpConfig;
Jonathan Hartce430a42014-10-16 20:44:29 -070052
Jonathan Harte30fcda2015-08-06 16:22:34 -070053import java.util.ArrayList;
54import java.util.Collections;
55import java.util.HashMap;
Jonathan Harte30fcda2015-08-06 16:22:34 -070056import java.util.List;
57import java.util.Map;
Jonathan Harta8625482015-09-08 16:14:56 -070058import java.util.Optional;
Jonathan Hart4cb39882015-08-12 23:50:55 -040059import java.util.Set;
Jonathan Hart552e31f2015-02-06 11:11:59 -080060
Thomas Vachuska2048c1f2017-05-10 19:32:22 -070061import static org.easymock.EasyMock.*;
Jonathan Hart33b81f22016-02-05 09:25:50 -080062import static org.onosproject.routing.TestIntentServiceHelper.eqExceptId;
Jonathan Hartce430a42014-10-16 20:44:29 -070063
64/**
Jonathan Hart51372182014-12-03 21:32:34 -080065 * Unit tests for PeerConnectivityManager.
Jonathan Hartce430a42014-10-16 20:44:29 -070066 */
Brian O'Connor520c0522014-11-23 23:50:47 -080067public class PeerConnectivityManagerTest extends AbstractIntentTest {
Jonathan Hartce430a42014-10-16 20:44:29 -070068
Jonathan Hart9a426f82015-09-03 15:43:13 +020069 private static final ApplicationId APPID = TestApplicationId.create("foo");
Thomas Vachuskab97cf282014-10-20 23:31:12 -070070
Jonathan Hart4cb39882015-08-12 23:50:55 -040071 private static final ApplicationId CONFIG_APP_ID = APPID;
72
Jonathan Hartce430a42014-10-16 20:44:29 -070073 private PeerConnectivityManager peerConnectivityManager;
Jonathan Hart9a426f82015-09-03 15:43:13 +020074 private IntentSynchronizationService intentSynchronizer;
Jonathan Hart4cb39882015-08-12 23:50:55 -040075 private InterfaceService interfaceService;
76 private NetworkConfigService networkConfigService;
Jonathan Hartce430a42014-10-16 20:44:29 -070077
Jonathan Hart4cb39882015-08-12 23:50:55 -040078 private Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers;
Jonathan Hartce430a42014-10-16 20:44:29 -070079 private Map<String, Interface> interfaces;
Jonathan Hartce430a42014-10-16 20:44:29 -070080
Jonathan Hart4cb39882015-08-12 23:50:55 -040081 private BgpConfig bgpConfig;
82
Luca Prete83bac342016-12-06 19:42:05 -080083 private SdnIpConfig sdnIpConfig;
84
Jonathan Hartce430a42014-10-16 20:44:29 -070085 private List<PointToPointIntent> intentList;
86
Jonathan Hartce430a42014-10-16 20:44:29 -070087 private final DeviceId deviceId1 =
Jonathan Hart3d8ff282016-09-06 10:59:41 -070088 DeviceId.deviceId("of:0000000000000001");
Jonathan Hartce430a42014-10-16 20:44:29 -070089 private final DeviceId deviceId2 =
Jonathan Hart3d8ff282016-09-06 10:59:41 -070090 DeviceId.deviceId("of:0000000000000002");
Luca Prete8f2a3ce2016-03-29 16:13:01 -070091 private final DeviceId deviceId3 =
Jonathan Hart3d8ff282016-09-06 10:59:41 -070092 DeviceId.deviceId("of:0000000000000003");
Jonathan Hartce430a42014-10-16 20:44:29 -070093
94 // Interfaces connected to BGP speakers
95 private final ConnectPoint s1Eth100 =
96 new ConnectPoint(deviceId1, PortNumber.portNumber(100));
Luca Prete8f2a3ce2016-03-29 16:13:01 -070097 private final ConnectPoint s2Eth100 =
98 new ConnectPoint(deviceId2, PortNumber.portNumber(100));
99 private final ConnectPoint s3Eth100 =
100 new ConnectPoint(deviceId3, PortNumber.portNumber(100));
Jonathan Hartce430a42014-10-16 20:44:29 -0700101
102 // Interfaces connected to BGP peers
103 private final ConnectPoint s1Eth1 =
104 new ConnectPoint(deviceId1, PortNumber.portNumber(1));
105 private final ConnectPoint s2Eth1 =
106 new ConnectPoint(deviceId2, PortNumber.portNumber(1));
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700107 private final ConnectPoint s3Eth1 =
108 new ConnectPoint(deviceId3, PortNumber.portNumber(1));
Jonathan Hartce430a42014-10-16 20:44:29 -0700109
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700110 private static final VlanId NO_VLAN = VlanId.NONE;
111 private static final VlanId VLAN10 = VlanId.vlanId(Short.valueOf("10"));
112 private static final VlanId VLAN20 = VlanId.vlanId(Short.valueOf("20"));
113 private static final VlanId VLAN30 = VlanId.vlanId(Short.valueOf("30"));
Jonathan Hartce430a42014-10-16 20:44:29 -0700114
115 @Before
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700116 public void setUp() {
Brian O'Connor520c0522014-11-23 23:50:47 -0800117 super.setUp();
Jonathan Hartb14221c2016-03-07 09:55:50 -0800118
Jonathan Hart4cb39882015-08-12 23:50:55 -0400119 interfaceService = createMock(InterfaceService.class);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800120 interfaceService.addListener(anyObject(InterfaceListener.class));
121 expectLastCall().anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400122 networkConfigService = createMock(NetworkConfigService.class);
Jonathan Hart08105be2015-10-10 18:31:06 -0700123 networkConfigService.addListener(anyObject(NetworkConfigListener.class));
124 expectLastCall().anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400125 bgpConfig = createMock(BgpConfig.class);
Luca Prete83bac342016-12-06 19:42:05 -0800126 sdnIpConfig = createMock(SdnIpConfig.class);
Jonathan Hart90a02c22015-02-13 11:52:07 -0800127
Jonathan Hart4cb39882015-08-12 23:50:55 -0400128 // These will set expectations on routingConfig and interfaceService
129 bgpSpeakers = setUpBgpSpeakers();
Jonathan Hartce430a42014-10-16 20:44:29 -0700130 interfaces = Collections.unmodifiableMap(setUpInterfaces());
Jonathan Hartce430a42014-10-16 20:44:29 -0700131
132 initPeerConnectivity();
133 intentList = setUpIntentList();
134 }
135
136 /**
137 * Sets up BGP speakers.
138 *
139 * @return configured BGP speakers as a map from speaker name to speaker
140 */
Jonathan Hart4cb39882015-08-12 23:50:55 -0400141 private Set<BgpConfig.BgpSpeakerConfig> setUpBgpSpeakers() {
Jonathan Hartce430a42014-10-16 20:44:29 -0700142
Jonathan Hart4cb39882015-08-12 23:50:55 -0400143 BgpConfig.BgpSpeakerConfig speaker1 = new BgpConfig.BgpSpeakerConfig(
Jonathan Harta8625482015-09-08 16:14:56 -0700144 Optional.empty(),
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700145 NO_VLAN, s1Eth100,
146 Collections.singleton(IpAddress.valueOf("192.168.10.1")));
Jonathan Hartce430a42014-10-16 20:44:29 -0700147
Jonathan Hart4cb39882015-08-12 23:50:55 -0400148 BgpConfig.BgpSpeakerConfig speaker2 = new BgpConfig.BgpSpeakerConfig(
Jonathan Harta8625482015-09-08 16:14:56 -0700149 Optional.empty(),
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700150 NO_VLAN, s1Eth100,
151 Sets.newHashSet(IpAddress.valueOf("192.168.20.1"),
Jonathan Hart4cb39882015-08-12 23:50:55 -0400152 IpAddress.valueOf("192.168.30.1")));
Jonathan Hartce430a42014-10-16 20:44:29 -0700153
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700154 BgpConfig.BgpSpeakerConfig speaker3 = new BgpConfig.BgpSpeakerConfig(
155 Optional.empty(),
156 VLAN30, s3Eth100,
157 Sets.newHashSet(IpAddress.valueOf("192.168.40.1"),
158 IpAddress.valueOf("192.168.50.1")));
159
Jonathan Hart4cb39882015-08-12 23:50:55 -0400160 Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers = Sets.newHashSet();
161 bgpSpeakers.add(speaker1);
162 bgpSpeakers.add(speaker2);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700163 bgpSpeakers.add(speaker3);
Jonathan Hartce430a42014-10-16 20:44:29 -0700164
Jonathan Hart4cb39882015-08-12 23:50:55 -0400165 return bgpSpeakers;
Jonathan Hartce430a42014-10-16 20:44:29 -0700166 }
167
168 /**
169 * Sets up logical interfaces, which emulate the configured interfaces
Luca Prete83bac342016-12-06 19:42:05 -0800170 * in the SDN-IP application.
Jonathan Hartce430a42014-10-16 20:44:29 -0700171 *
Jonathan Hart9a426f82015-09-03 15:43:13 +0200172 * @return configured interfaces as a map from interface name to Interface
Jonathan Hartce430a42014-10-16 20:44:29 -0700173 */
174 private Map<String, Interface> setUpInterfaces() {
175
Jonathan Hart9a426f82015-09-03 15:43:13 +0200176 Map<String, Interface> configuredInterfaces = new HashMap<>();
Jonathan Hartce430a42014-10-16 20:44:29 -0700177
178 String interfaceSw1Eth1 = "s1-eth1";
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700179 InterfaceIpAddress ia1 =
Jonathan Harte30fcda2015-08-06 16:22:34 -0700180 new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700181 IpPrefix.valueOf("192.168.10.0/24"));
Jonathan Hartb14221c2016-03-07 09:55:50 -0800182 Interface intfsw1eth1 = new Interface(interfaceSw1Eth1, s1Eth1,
Jonathan Hart00cddda2016-02-16 10:30:37 -0800183 Collections.singletonList(ia1),
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800184 MacAddress.valueOf("00:00:00:00:00:01"),
185 VlanId.NONE);
Jonathan Hartce430a42014-10-16 20:44:29 -0700186
187 configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700188
Jonathan Hartce430a42014-10-16 20:44:29 -0700189 String interfaceSw2Eth1 = "s2-eth1";
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700190 InterfaceIpAddress ia2 =
Jonathan Harte30fcda2015-08-06 16:22:34 -0700191 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700192 IpPrefix.valueOf("192.168.20.0/24"));
Jonathan Hartb14221c2016-03-07 09:55:50 -0800193 Interface intfsw2eth1 = new Interface(interfaceSw2Eth1, s2Eth1,
Jonathan Hart00cddda2016-02-16 10:30:37 -0800194 Collections.singletonList(ia2),
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800195 MacAddress.valueOf("00:00:00:00:00:02"),
196 VlanId.NONE);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700197
Jonathan Hartce430a42014-10-16 20:44:29 -0700198 configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1);
199
Jonathan Harte30fcda2015-08-06 16:22:34 -0700200 String interfaceSw2Eth1intf2 = "s2-eth1_2";
201 InterfaceIpAddress ia3 =
202 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
203 IpPrefix.valueOf("192.168.30.0/24"));
Jonathan Hartb14221c2016-03-07 09:55:50 -0800204 Interface intfsw2eth1intf2 = new Interface(interfaceSw2Eth1intf2, s2Eth1,
Jonathan Hart00cddda2016-02-16 10:30:37 -0800205 Collections.singletonList(ia3),
Jonathan Harte30fcda2015-08-06 16:22:34 -0700206 MacAddress.valueOf("00:00:00:00:00:03"),
207 VlanId.NONE);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700208
Jonathan Harte30fcda2015-08-06 16:22:34 -0700209 configuredInterfaces.put(interfaceSw2Eth1intf2, intfsw2eth1intf2);
210
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700211 String interfaceSw3Eth1 = "s3-eth1";
212 InterfaceIpAddress ia4 =
213 new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
214 IpPrefix.valueOf("192.168.40.0/24"));
Sho SHIMIZU891162b2016-06-06 16:32:01 -0700215 Interface intfsw3eth1 = new Interface(Interface.NO_INTERFACE_NAME,
216 s3Eth1,
217 ImmutableList.of(ia4),
218 MacAddress.valueOf("00:00:00:00:00:04"),
219 VLAN10);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700220
221 configuredInterfaces.put(interfaceSw3Eth1, intfsw3eth1);
222
223 String interfaceSw3Eth1intf2 = "s3-eth1_2";
224 InterfaceIpAddress ia5 =
225 new InterfaceIpAddress(IpAddress.valueOf("192.168.50.101"),
226 IpPrefix.valueOf("192.168.50.0/24"));
Sho SHIMIZU891162b2016-06-06 16:32:01 -0700227 Interface intfsw3eth1intf2 = new Interface(Interface.NO_INTERFACE_NAME,
228 s3Eth1,
229 ImmutableList.of(ia5),
230 MacAddress.valueOf("00:00:00:00:00:05"),
231 VLAN20);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700232
233 configuredInterfaces.put(interfaceSw3Eth1intf2, intfsw3eth1intf2);
234
Jonathan Hart4cb39882015-08-12 23:50:55 -0400235 expect(interfaceService.getInterfacesByPort(s1Eth1))
236 .andReturn(Collections.singleton(intfsw1eth1)).anyTimes();
237 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
238 .andReturn(Collections.singleton(intfsw1eth1)).anyTimes();
239 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
Jonathan Hartce430a42014-10-16 20:44:29 -0700240 .andReturn(intfsw1eth1).anyTimes();
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700241
Jonathan Hart4cb39882015-08-12 23:50:55 -0400242 expect(interfaceService.getInterfacesByPort(s2Eth1))
243 .andReturn(Collections.singleton(intfsw2eth1)).anyTimes();
244 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
245 .andReturn(Collections.singleton(intfsw2eth1)).anyTimes();
246 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
Jonathan Hartce430a42014-10-16 20:44:29 -0700247 .andReturn(intfsw2eth1).anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400248
249 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
250 .andReturn(Collections.singleton(intfsw2eth1intf2)).anyTimes();
251 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
Jonathan Harte30fcda2015-08-06 16:22:34 -0700252 .andReturn(intfsw2eth1intf2).anyTimes();
Jonathan Hartce430a42014-10-16 20:44:29 -0700253
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700254 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.40.101")))
255 .andReturn(Collections.singleton(intfsw3eth1)).anyTimes();
256 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.40.1")))
257 .andReturn(intfsw3eth1).anyTimes();
258
259 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.50.101")))
260 .andReturn(Collections.singleton(intfsw3eth1intf2)).anyTimes();
261 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.50.1")))
262 .andReturn(intfsw3eth1intf2).anyTimes();
263
Jonathan Hartce430a42014-10-16 20:44:29 -0700264 // Non-existent interface used during one of the tests
Jonathan Hart4cb39882015-08-12 23:50:55 -0400265 expect(interfaceService.getInterfacesByPort(new ConnectPoint(
Jonathan Hart3d8ff282016-09-06 10:59:41 -0700266 DeviceId.deviceId("of:0000000000000100"),
Jonathan Hart4cb39882015-08-12 23:50:55 -0400267 PortNumber.portNumber(1))))
Jonathan Hartce430a42014-10-16 20:44:29 -0700268 .andReturn(null).anyTimes();
269
Jonathan Hart4cb39882015-08-12 23:50:55 -0400270 expect(interfaceService.getInterfaces()).andReturn(
Jonathan Hartce430a42014-10-16 20:44:29 -0700271 Sets.newHashSet(configuredInterfaces.values())).anyTimes();
Jonathan Hartce430a42014-10-16 20:44:29 -0700272
273 return configuredInterfaces;
274 }
275
276 /**
Jonathan Hartce430a42014-10-16 20:44:29 -0700277 * Sets up expected point to point intent list.
278 *
279 * @return point to point intent list
280 */
281 private List<PointToPointIntent> setUpIntentList() {
Jonathan Hart90a02c22015-02-13 11:52:07 -0800282 intentList = new ArrayList<>();
Jonathan Hartce430a42014-10-16 20:44:29 -0700283
284 setUpBgpIntents();
285 setUpIcmpIntents();
286
287 return intentList;
Jonathan Hartce430a42014-10-16 20:44:29 -0700288 }
289
290 /**
291 * Constructs a BGP intent and put it into the intentList.
292 * <p/>
293 * The purpose of this method is too simplify the setUpBgpIntents() method,
294 * and to make the setUpBgpIntents() easy to read.
295 *
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700296 * @param srcVlanId ingress VlanId
297 * @param dstVlanId egress VlanId
Jonathan Hartce430a42014-10-16 20:44:29 -0700298 * @param srcPrefix source IP prefix to match
299 * @param dstPrefix destination IP prefix to match
300 * @param srcTcpPort source TCP port to match
301 * @param dstTcpPort destination TCP port to match
302 * @param srcConnectPoint source connect point for PointToPointIntent
303 * @param dstConnectPoint destination connect point for PointToPointIntent
304 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700305 private void bgpPathintentConstructor(VlanId srcVlanId, VlanId dstVlanId,
306 String srcPrefix, String dstPrefix,
307 Short srcTcpPort, Short dstTcpPort,
308 ConnectPoint srcConnectPoint,
309 ConnectPoint dstConnectPoint) {
Jonathan Hartce430a42014-10-16 20:44:29 -0700310
311 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
312 .matchEthType(Ethernet.TYPE_IPV4)
313 .matchIPProtocol(IPv4.PROTOCOL_TCP)
314 .matchIPSrc(IpPrefix.valueOf(srcPrefix))
315 .matchIPDst(IpPrefix.valueOf(dstPrefix));
316
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700317 if (!srcVlanId.equals(VlanId.NONE)) {
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700318 builder.matchVlanId(srcVlanId);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700319 }
320
321 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
322
323 if (!dstVlanId.equals(VlanId.NONE)) {
324 treatment.setVlanId(dstVlanId);
325 }
326
Jonathan Hartce430a42014-10-16 20:44:29 -0700327 if (srcTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700328 builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
Jonathan Hartce430a42014-10-16 20:44:29 -0700329 }
330 if (dstTcpPort != null) {
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700331 builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
Jonathan Hartce430a42014-10-16 20:44:29 -0700332 }
333
Jonathan Hart9a426f82015-09-03 15:43:13 +0200334 Key key = Key.of(srcPrefix.split("/")[0] + "-" + dstPrefix.split("/")[0]
335 + "-" + ((srcTcpPort == null) ? "dst" : "src"), APPID);
336
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700337 PointToPointIntent intent = PointToPointIntent.builder()
338 .appId(APPID)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200339 .key(key)
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700340 .selector(builder.build())
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700341 .treatment(treatment.build())
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700342 .ingressPoint(srcConnectPoint)
343 .egressPoint(dstConnectPoint)
344 .build();
Jonathan Hartce430a42014-10-16 20:44:29 -0700345
346 intentList.add(intent);
347 }
348
349 /**
350 * Sets up intents for BGP paths.
351 */
352 private void setUpBgpIntents() {
353
Jonathan Hart41349e92015-02-09 14:14:02 -0800354 Short bgpPort = 179;
Jonathan Hartce430a42014-10-16 20:44:29 -0700355
356 // Start to build intents between BGP speaker1 and BGP peer1
357 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700358 NO_VLAN, NO_VLAN,
359 "192.168.10.101/32", "192.168.10.1/32",
360 null, bgpPort,
Jonathan Hartce430a42014-10-16 20:44:29 -0700361 s1Eth100, s1Eth1);
362 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700363 NO_VLAN, NO_VLAN,
364 "192.168.10.101/32", "192.168.10.1/32",
365 bgpPort, null,
Jonathan Hartce430a42014-10-16 20:44:29 -0700366 s1Eth100, s1Eth1);
367
368 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700369 NO_VLAN, NO_VLAN,
370 "192.168.10.1/32", "192.168.10.101/32",
371 null, bgpPort,
Jonathan Hartce430a42014-10-16 20:44:29 -0700372 s1Eth1, s1Eth100);
373 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700374 NO_VLAN, NO_VLAN,
375 "192.168.10.1/32", "192.168.10.101/32",
376 bgpPort, null,
Jonathan Hartce430a42014-10-16 20:44:29 -0700377 s1Eth1, s1Eth100);
378
379 // Start to build intents between BGP speaker1 and BGP peer2
380 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700381 NO_VLAN, NO_VLAN,
382 "192.168.20.101/32", "192.168.20.1/32",
383 null, bgpPort,
Jonathan Hartce430a42014-10-16 20:44:29 -0700384 s1Eth100, s2Eth1);
385 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700386 NO_VLAN, NO_VLAN,
387 "192.168.20.101/32", "192.168.20.1/32",
388 bgpPort, null,
Jonathan Hartce430a42014-10-16 20:44:29 -0700389 s1Eth100, s2Eth1);
390
391 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700392 NO_VLAN, NO_VLAN,
393 "192.168.20.1/32", "192.168.20.101/32",
394 null, bgpPort,
Jonathan Hartce430a42014-10-16 20:44:29 -0700395 s2Eth1, s1Eth100);
396 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700397 NO_VLAN, NO_VLAN,
398 "192.168.20.1/32", "192.168.20.101/32",
399 bgpPort, null,
Jonathan Hartce430a42014-10-16 20:44:29 -0700400 s2Eth1, s1Eth100);
401
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700402 // Start to build intents between BGP speaker2 and BGP peer1
Jonathan Hartce430a42014-10-16 20:44:29 -0700403 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700404 NO_VLAN, NO_VLAN,
405 "192.168.30.101/32", "192.168.30.1/32",
406 null, bgpPort,
Jonathan Harte30fcda2015-08-06 16:22:34 -0700407 s1Eth100, s2Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700408 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700409 NO_VLAN, NO_VLAN,
410 "192.168.30.101/32", "192.168.30.1/32",
411 bgpPort, null,
Jonathan Harte30fcda2015-08-06 16:22:34 -0700412 s1Eth100, s2Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700413
414 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700415 NO_VLAN, NO_VLAN,
416 "192.168.30.1/32", "192.168.30.101/32",
417 null, bgpPort,
Jonathan Harte30fcda2015-08-06 16:22:34 -0700418 s2Eth1, s1Eth100);
Jonathan Hartce430a42014-10-16 20:44:29 -0700419 bgpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700420 NO_VLAN, NO_VLAN,
421 "192.168.30.1/32", "192.168.30.101/32",
422 bgpPort, null,
Jonathan Harte30fcda2015-08-06 16:22:34 -0700423 s2Eth1, s1Eth100);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700424
425 // Start to build intents between BGP speaker3 and BGP peer4
426 bgpPathintentConstructor(
427 VLAN30, VLAN10,
428 "192.168.40.101/32", "192.168.40.1/32",
429 null, bgpPort,
430 s3Eth100, s3Eth1);
431 bgpPathintentConstructor(
432 VLAN30, VLAN10,
433 "192.168.40.101/32", "192.168.40.1/32",
434 bgpPort, null,
435 s3Eth100, s3Eth1);
436
437 bgpPathintentConstructor(
438 VLAN10, VLAN30,
439 "192.168.40.1/32", "192.168.40.101/32",
440 null, bgpPort,
441 s3Eth1, s3Eth100);
442 bgpPathintentConstructor(
443 VLAN10, VLAN30,
444 "192.168.40.1/32", "192.168.40.101/32",
445 bgpPort, null,
446 s3Eth1, s3Eth100);
447
448 // Start to build intents between BGP speaker3 and BGP peer5
449 bgpPathintentConstructor(
450 VLAN30, VLAN20,
451 "192.168.50.101/32", "192.168.50.1/32",
452 null, bgpPort,
453 s3Eth100, s3Eth1);
454 bgpPathintentConstructor(
455 VLAN30, VLAN20,
456 "192.168.50.101/32", "192.168.50.1/32",
457 bgpPort, null,
458 s3Eth100, s3Eth1);
459
460 bgpPathintentConstructor(
461 VLAN20, VLAN30,
462 "192.168.50.1/32", "192.168.50.101/32",
463 null, bgpPort,
464 s3Eth1, s3Eth100);
465 bgpPathintentConstructor(
466 VLAN20, VLAN30,
467 "192.168.50.1/32", "192.168.50.101/32",
468 bgpPort, null,
469 s3Eth1, s3Eth100);
Jonathan Hartce430a42014-10-16 20:44:29 -0700470 }
471
472 /**
473 * Constructs a BGP intent and put it into the intentList.
474 * <p/>
475 * The purpose of this method is too simplify the setUpBgpIntents() method,
476 * and to make the setUpBgpIntents() easy to read.
477 *
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700478 * @param srcVlanId ingress VlanId
479 * @param dstVlanId egress VlanId
Jonathan Hartce430a42014-10-16 20:44:29 -0700480 * @param srcPrefix source IP prefix to match
481 * @param dstPrefix destination IP prefix to match
482 * @param srcConnectPoint source connect point for PointToPointIntent
483 * @param dstConnectPoint destination connect point for PointToPointIntent
484 */
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700485 private void icmpPathintentConstructor(VlanId srcVlanId, VlanId dstVlanId,
486 String srcPrefix, String dstPrefix,
487 ConnectPoint srcConnectPoint,
488 ConnectPoint dstConnectPoint) {
Jonathan Hartce430a42014-10-16 20:44:29 -0700489
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700490 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
Jonathan Hartce430a42014-10-16 20:44:29 -0700491 .matchEthType(Ethernet.TYPE_IPV4)
492 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
493 .matchIPSrc(IpPrefix.valueOf(srcPrefix))
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700494 .matchIPDst(IpPrefix.valueOf(dstPrefix));
495
496 if (!srcVlanId.equals(VlanId.NONE)) {
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700497 builder.matchVlanId(srcVlanId);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700498 }
499
500 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
501
502 if (!dstVlanId.equals(VlanId.NONE)) {
503 treatment.setVlanId(dstVlanId);
504 }
Jonathan Hartce430a42014-10-16 20:44:29 -0700505
Jonathan Hart9a426f82015-09-03 15:43:13 +0200506 Key key = Key.of(srcPrefix.split("/")[0] + "-" + dstPrefix.split("/")[0]
507 + "-" + "icmp", APPID);
508
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700509 PointToPointIntent intent = PointToPointIntent.builder()
510 .appId(APPID)
Jonathan Hart9a426f82015-09-03 15:43:13 +0200511 .key(key)
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700512 .selector(builder.build())
513 .treatment(treatment.build())
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700514 .ingressPoint(srcConnectPoint)
515 .egressPoint(dstConnectPoint)
516 .build();
Jonathan Hartce430a42014-10-16 20:44:29 -0700517
518 intentList.add(intent);
519 }
520
521 /**
522 * Sets up intents for ICMP paths.
523 */
524 private void setUpIcmpIntents() {
Jonathan Hartce430a42014-10-16 20:44:29 -0700525 // Start to build intents between BGP speaker1 and BGP peer1
526 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700527 NO_VLAN, NO_VLAN,
528 "192.168.10.101/32", "192.168.10.1/32",
529 s1Eth100, s1Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700530 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700531 NO_VLAN, NO_VLAN,
532 "192.168.10.1/32", "192.168.10.101/32",
533 s1Eth1, s1Eth100);
Jonathan Hartce430a42014-10-16 20:44:29 -0700534
535 // Start to build intents between BGP speaker1 and BGP peer2
536 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700537 NO_VLAN, NO_VLAN,
538 "192.168.20.101/32", "192.168.20.1/32",
539 s1Eth100, s2Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700540 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700541 NO_VLAN, NO_VLAN,
542 "192.168.20.1/32", "192.168.20.101/32",
543 s2Eth1, s1Eth100);
Jonathan Hartce430a42014-10-16 20:44:29 -0700544
Jonathan Hartce430a42014-10-16 20:44:29 -0700545 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700546 NO_VLAN, NO_VLAN,
547 "192.168.30.101/32", "192.168.30.1/32",
548 s1Eth100, s2Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700549 icmpPathintentConstructor(
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700550 NO_VLAN, NO_VLAN,
551 "192.168.30.1/32", "192.168.30.101/32",
552 s2Eth1, s1Eth100);
553
554 // Start to build intents between BGP speaker3 and BGP peer 4
555 icmpPathintentConstructor(
556 VLAN10, VLAN30,
557 "192.168.40.1/32", "192.168.40.101/32",
558 s3Eth1, s3Eth100);
559 icmpPathintentConstructor(
560 VLAN30, VLAN10,
561 "192.168.40.101/32", "192.168.40.1/32",
562 s3Eth100, s3Eth1);
563
564 // Start to build intents between BGP speaker3 and BGP peer 5
565 icmpPathintentConstructor(
566 VLAN20, VLAN30,
567 "192.168.50.1/32", "192.168.50.101/32",
568 s3Eth1, s3Eth100);
569 icmpPathintentConstructor(
570 VLAN30, VLAN20,
571 "192.168.50.101/32", "192.168.50.1/32",
572 s3Eth100, s3Eth1);
Jonathan Hartce430a42014-10-16 20:44:29 -0700573 }
574
575 /**
576 * Initializes peer connectivity testing environment.
577 */
Jonathan Hartde6e2032016-04-15 13:28:02 -0700578 private void initPeerConnectivity() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400579 expect(bgpConfig.bgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
580 replay(bgpConfig);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200581 expect(networkConfigService.getConfig(APPID, BgpConfig.class))
582 .andReturn(bgpConfig).anyTimes();
Luca Prete83bac342016-12-06 19:42:05 -0800583
584 expect(sdnIpConfig.encap()).andReturn(EncapsulationType.NONE).anyTimes();
585 replay(sdnIpConfig);
586 expect(networkConfigService.getConfig(APPID, SdnIpConfig.class))
587 .andReturn(sdnIpConfig).anyTimes();
588
Jonathan Hart4cb39882015-08-12 23:50:55 -0400589 replay(networkConfigService);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400590 replay(interfaceService);
Jonathan Hartce430a42014-10-16 20:44:29 -0700591
Jonathan Hart9a426f82015-09-03 15:43:13 +0200592 intentSynchronizer = createMock(IntentSynchronizationService.class);
593 replay(intentSynchronizer);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800594
595 peerConnectivityManager =
596 new PeerConnectivityManager(APPID, intentSynchronizer,
Jonathan Hart4cb39882015-08-12 23:50:55 -0400597 networkConfigService,
598 CONFIG_APP_ID,
599 interfaceService);
Jonathan Hartce430a42014-10-16 20:44:29 -0700600 }
601
Jonathan Hartce430a42014-10-16 20:44:29 -0700602 /**
603 * Tests whether peer connectivity manager can set up correct BGP and
604 * ICMP intents according to specific configuration.
605 * <p/>
606 * Two tricky cases included in the configuration are: 2 peers on a same
607 * switch port, peer on the same switch with BGPd.
608 */
609 @Test
610 public void testConnectionSetup() {
Jonathan Hart9a426f82015-09-03 15:43:13 +0200611 reset(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700612
Pavlin Radoslavovdde22ae2014-11-24 11:47:17 -0800613 // Setup the expected intents
Pavlin Radoslavovdde22ae2014-11-24 11:47:17 -0800614 for (Intent intent : intentList) {
Jonathan Hart9a426f82015-09-03 15:43:13 +0200615 intentSynchronizer.submit(eqExceptId(intent));
Jonathan Hartce430a42014-10-16 20:44:29 -0700616 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200617 replay(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700618
619 // Running the interface to be tested.
620 peerConnectivityManager.start();
621
Jonathan Hart9a426f82015-09-03 15:43:13 +0200622 verify(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700623 }
624
625 /**
626 * Tests a corner case, when there are no interfaces in the configuration.
627 */
628 @Test
629 public void testNullInterfaces() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400630 reset(interfaceService);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800631 interfaceService.addListener(anyObject(InterfaceListener.class));
632 expectLastCall().anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400633
634 expect(interfaceService.getInterfaces()).andReturn(
Jonathan Hart9a426f82015-09-03 15:43:13 +0200635 Sets.newHashSet()).anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400636 expect(interfaceService.getInterfacesByPort(s2Eth1))
637 .andReturn(Collections.emptySet()).anyTimes();
638 expect(interfaceService.getInterfacesByPort(s1Eth1))
639 .andReturn(Collections.emptySet()).anyTimes();
640 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
641 .andReturn(Collections.emptySet()).anyTimes();
642 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
Jonathan Hartce430a42014-10-16 20:44:29 -0700643 .andReturn(null).anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400644 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
645 .andReturn(Collections.emptySet()).anyTimes();
646 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
Jonathan Harte30fcda2015-08-06 16:22:34 -0700647 .andReturn(null).anyTimes();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400648 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
649 .andReturn(Collections.emptySet()).anyTimes();
650 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
Jonathan Harte30fcda2015-08-06 16:22:34 -0700651 .andReturn(null).anyTimes();
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700652 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.40.101")))
653 .andReturn(Collections.emptySet()).anyTimes();
654 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.40.1")))
655 .andReturn(null).anyTimes();
656 expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.50.101")))
657 .andReturn(Collections.emptySet()).anyTimes();
658 expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.50.1")))
659 .andReturn(null).anyTimes();
Jonathan Hartce430a42014-10-16 20:44:29 -0700660
Jonathan Hart4cb39882015-08-12 23:50:55 -0400661 replay(interfaceService);
Jonathan Hartce430a42014-10-16 20:44:29 -0700662
Jonathan Hart9a426f82015-09-03 15:43:13 +0200663 reset(intentSynchronizer);
664 replay(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700665 peerConnectivityManager.start();
Jonathan Hart9a426f82015-09-03 15:43:13 +0200666 verify(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700667 }
668
669 /**
670 * Tests a corner case, when there is no BGP speakers in the configuration.
671 */
672 @Test
673 public void testNullBgpSpeakers() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400674 reset(bgpConfig);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400675 expect(bgpConfig.bgpSpeakers()).andReturn(Collections.emptySet()).anyTimes();
676 replay(bgpConfig);
Jonathan Hartce430a42014-10-16 20:44:29 -0700677
Luca Prete83bac342016-12-06 19:42:05 -0800678 reset(sdnIpConfig);
679 expect(sdnIpConfig.encap()).andReturn(EncapsulationType.NONE).anyTimes();
680 replay(sdnIpConfig);
681
Jonathan Hartde6e2032016-04-15 13:28:02 -0700682 // We don't expect any intents in this case
Jonathan Hart9a426f82015-09-03 15:43:13 +0200683 reset(intentSynchronizer);
684 replay(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700685 peerConnectivityManager.start();
Jonathan Hart9a426f82015-09-03 15:43:13 +0200686 verify(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700687 }
688
689 /**
690 * Tests a corner case, when there is no Interface configured for one BGP
691 * peer.
692 */
693 @Test
694 public void testNoPeerInterface() {
Jonathan Hartde6e2032016-04-15 13:28:02 -0700695 IpAddress ip = IpAddress.valueOf("1.1.1.1");
696 bgpSpeakers.clear();
697 bgpSpeakers.add(new BgpConfig.BgpSpeakerConfig(Optional.of("foo"),
698 VlanId.NONE, s1Eth100, Collections.singleton(ip)));
699 reset(interfaceService);
700 interfaceService.addListener(anyObject(InterfaceListener.class));
701 expect(interfaceService.getMatchingInterface(ip)).andReturn(null).anyTimes();
702 replay(interfaceService);
703
704 // We don't expect any intents in this case
705 reset(intentSynchronizer);
706 replay(intentSynchronizer);
707 peerConnectivityManager.start();
708 verify(intentSynchronizer);
Jonathan Hartce430a42014-10-16 20:44:29 -0700709 }
710
Jonathan Hartce430a42014-10-16 20:44:29 -0700711}