alshabib

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

...@@ -25,10 +25,10 @@ import org.slf4j.LoggerFactory; ...@@ -25,10 +25,10 @@ import org.slf4j.LoggerFactory;
25 /** 25 /**
26 * Manages the connectivity requirements between peers. 26 * Manages the connectivity requirements between peers.
27 */ 27 */
28 -public class PeerConnectivity { 28 +public class PeerConnectivityManager {
29 29
30 private static final Logger log = LoggerFactory.getLogger( 30 private static final Logger log = LoggerFactory.getLogger(
31 - PeerConnectivity.class); 31 + PeerConnectivityManager.class);
32 32
33 // TODO these shouldn't be defined here 33 // TODO these shouldn't be defined here
34 private static final short BGP_PORT = 179; 34 private static final short BGP_PORT = 179;
...@@ -41,7 +41,7 @@ public class PeerConnectivity { ...@@ -41,7 +41,7 @@ public class PeerConnectivity {
41 // TODO this sucks. 41 // TODO this sucks.
42 private int intentId = 0; 42 private int intentId = 0;
43 43
44 - public PeerConnectivity(SdnIpConfigService configInfoService, 44 + public PeerConnectivityManager(SdnIpConfigService configInfoService,
45 InterfaceService interfaceService, IntentService intentService) { 45 InterfaceService interfaceService, IntentService intentService) {
46 this.configInfoService = configInfoService; 46 this.configInfoService = configInfoService;
47 this.interfaceService = interfaceService; 47 this.interfaceService = interfaceService;
......
...@@ -36,7 +36,7 @@ public class SdnIp implements SdnIpService { ...@@ -36,7 +36,7 @@ public class SdnIp implements SdnIpService {
36 protected HostService hostService; 36 protected HostService hostService;
37 37
38 private SdnIpConfigReader config; 38 private SdnIpConfigReader config;
39 - private PeerConnectivity peerConnectivity; 39 + private PeerConnectivityManager peerConnectivity;
40 private Router router; 40 private Router router;
41 private BgpSessionManager bgpSessionManager; 41 private BgpSessionManager bgpSessionManager;
42 42
...@@ -49,7 +49,7 @@ public class SdnIp implements SdnIpService { ...@@ -49,7 +49,7 @@ public class SdnIp implements SdnIpService {
49 49
50 InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService); 50 InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService);
51 51
52 - peerConnectivity = new PeerConnectivity(config, interfaceService, intentService); 52 + peerConnectivity = new PeerConnectivityManager(config, interfaceService, intentService);
53 peerConnectivity.start(); 53 peerConnectivity.start();
54 54
55 router = new Router(intentService, hostService, config, interfaceService); 55 router = new Router(intentService, hostService, config, interfaceService);
...@@ -79,4 +79,8 @@ public class SdnIp implements SdnIpService { ...@@ -79,4 +79,8 @@ public class SdnIp implements SdnIpService {
79 public Collection<RouteEntry> getRoutes() { 79 public Collection<RouteEntry> getRoutes() {
80 return router.getRoutes(); 80 return router.getRoutes();
81 } 81 }
82 +
83 + static String dpidToUri(String dpid) {
84 + return "of:" + dpid.replace(":", "");
85 + }
82 } 86 }
......
1 +package org.onlab.onos.sdnip;
2 +
3 +import static org.easymock.EasyMock.createMock;
4 +import static org.easymock.EasyMock.expect;
5 +import static org.easymock.EasyMock.replay;
6 +import static org.easymock.EasyMock.reportMatcher;
7 +import static org.easymock.EasyMock.reset;
8 +import static org.easymock.EasyMock.verify;
9 +
10 +import java.util.ArrayList;
11 +import java.util.Collections;
12 +import java.util.HashMap;
13 +import java.util.LinkedList;
14 +import java.util.List;
15 +import java.util.Map;
16 +
17 +import org.easymock.IArgumentMatcher;
18 +import org.junit.Before;
19 +import org.junit.Ignore;
20 +import org.junit.Test;
21 +import org.onlab.onos.net.ConnectPoint;
22 +import org.onlab.onos.net.DeviceId;
23 +import org.onlab.onos.net.PortNumber;
24 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
25 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
26 +import org.onlab.onos.net.flow.TrafficSelector;
27 +import org.onlab.onos.net.flow.TrafficTreatment;
28 +import org.onlab.onos.net.intent.IntentId;
29 +import org.onlab.onos.net.intent.IntentService;
30 +import org.onlab.onos.net.intent.PointToPointIntent;
31 +import org.onlab.onos.sdnip.bgp.BgpConstants;
32 +import org.onlab.onos.sdnip.config.BgpPeer;
33 +import org.onlab.onos.sdnip.config.BgpSpeaker;
34 +import org.onlab.onos.sdnip.config.Interface;
35 +import org.onlab.onos.sdnip.config.InterfaceAddress;
36 +import org.onlab.onos.sdnip.config.SdnIpConfigService;
37 +import org.onlab.packet.Ethernet;
38 +import org.onlab.packet.IPv4;
39 +import org.onlab.packet.IpAddress;
40 +import org.onlab.packet.IpPrefix;
41 +import org.onlab.packet.MacAddress;
42 +
43 +import com.google.common.collect.Sets;
44 +
45 +/**
46 + * Unit tests for PeerConnectivityManager interface.
47 + */
48 +public class PeerConnectivityManagerTest {
49 +
50 + private PeerConnectivityManager peerConnectivityManager;
51 + private IntentService intentService;
52 + private SdnIpConfigService configInfoService;
53 + private InterfaceService interfaceService;
54 +
55 + private Map<String, BgpSpeaker> bgpSpeakers;
56 + private Map<String, Interface> interfaces;
57 + private Map<IpAddress, BgpPeer> peers;
58 +
59 + private Map<String, BgpSpeaker> configuredBgpSpeakers;
60 + private Map<String, Interface> configuredInterfaces;
61 + private Map<IpAddress, BgpPeer> configuredPeers;
62 + private List<PointToPointIntent> intentList;
63 +
64 + private final String dpid1 = "00:00:00:00:00:00:00:01";
65 + private final String dpid2 = "00:00:00:00:00:00:00:02";
66 +
67 + private final DeviceId deviceId1 =
68 + DeviceId.deviceId(SdnIp.dpidToUri(dpid1));
69 + private final DeviceId deviceId2 =
70 + DeviceId.deviceId(SdnIp.dpidToUri(dpid2));
71 +
72 + // Interfaces connected to BGP speakers
73 + private final ConnectPoint s1Eth100 =
74 + new ConnectPoint(deviceId1, PortNumber.portNumber(100));
75 + private final ConnectPoint s2Eth100 =
76 + new ConnectPoint(deviceId2, PortNumber.portNumber(100));
77 +
78 + // Interfaces connected to BGP peers
79 + private final ConnectPoint s1Eth1 =
80 + new ConnectPoint(deviceId1, PortNumber.portNumber(1));
81 + private final ConnectPoint s2Eth1 =
82 + new ConnectPoint(deviceId2, PortNumber.portNumber(1));
83 +
84 + // We don't compare the intent ID so all expected intents can use the same ID
85 + private final IntentId testIntentId = new IntentId(0);
86 +
87 + private final TrafficTreatment noTreatment =
88 + DefaultTrafficTreatment.builder().build();
89 +
90 + @Before
91 + public void setUp() throws Exception {
92 + bgpSpeakers = Collections.unmodifiableMap(setUpBgpSpeakers());
93 + interfaces = Collections.unmodifiableMap(setUpInterfaces());
94 + peers = Collections.unmodifiableMap(setUpPeers());
95 +
96 + initPeerConnectivity();
97 + intentList = setUpIntentList();
98 + }
99 +
100 + /**
101 + * Sets up BGP speakers.
102 + *
103 + * @return configured BGP speakers as a map from speaker name to speaker
104 + */
105 + private Map<String, BgpSpeaker> setUpBgpSpeakers() {
106 +
107 + configuredBgpSpeakers = new HashMap<>();
108 +
109 + BgpSpeaker bgpSpeaker1 = new BgpSpeaker(
110 + "bgpSpeaker1",
111 + "00:00:00:00:00:00:00:01", 100,
112 + "00:00:00:00:00:01");
113 + List<InterfaceAddress> interfaceAddresses1 =
114 + new LinkedList<InterfaceAddress>();
115 + interfaceAddresses1.add(new InterfaceAddress(dpid1, 1, "192.168.10.101"));
116 + interfaceAddresses1.add(new InterfaceAddress(dpid2, 1, "192.168.20.101"));
117 + bgpSpeaker1.setInterfaceAddresses(interfaceAddresses1);
118 + configuredBgpSpeakers.put(bgpSpeaker1.name(), bgpSpeaker1);
119 +
120 + // BGP speaker2 is attached to the same switch port with speaker1
121 + BgpSpeaker bgpSpeaker2 = new BgpSpeaker(
122 + "bgpSpeaker2",
123 + "00:00:00:00:00:00:00:01", 100,
124 + "00:00:00:00:00:02");
125 + List<InterfaceAddress> interfaceAddresses2 =
126 + new LinkedList<InterfaceAddress>();
127 + interfaceAddresses2.add(new InterfaceAddress(dpid1, 1, "192.168.10.102"));
128 + interfaceAddresses2.add(new InterfaceAddress(dpid2, 1, "192.168.20.102"));
129 + bgpSpeaker2.setInterfaceAddresses(interfaceAddresses2);
130 + configuredBgpSpeakers.put(bgpSpeaker2.name(), bgpSpeaker2);
131 +
132 + BgpSpeaker bgpSpeaker3 = new BgpSpeaker(
133 + "bgpSpeaker3",
134 + "00:00:00:00:00:00:00:02", 100,
135 + "00:00:00:00:00:03");
136 + List<InterfaceAddress> interfaceAddresses3 =
137 + new LinkedList<InterfaceAddress>();
138 + interfaceAddresses3.add(new InterfaceAddress(dpid1, 1, "192.168.10.103"));
139 + interfaceAddresses3.add(new InterfaceAddress(dpid2, 1, "192.168.20.103"));
140 + bgpSpeaker3.setInterfaceAddresses(interfaceAddresses3);
141 + configuredBgpSpeakers.put(bgpSpeaker3.name(), bgpSpeaker3);
142 +
143 + return configuredBgpSpeakers;
144 + }
145 +
146 + /**
147 + * Sets up logical interfaces, which emulate the configured interfaces
148 + * in SDN-IP application.
149 + *
150 + * @return configured interfaces as a MAP from Interface name to Interface
151 + */
152 + private Map<String, Interface> setUpInterfaces() {
153 +
154 + configuredInterfaces = new HashMap<>();
155 +
156 + String interfaceSw1Eth1 = "s1-eth1";
157 + Interface intfsw1eth1 = new Interface(s1Eth1,
158 + Collections.singleton(IpPrefix.valueOf("192.168.10.0/24")),
159 + MacAddress.valueOf("00:00:00:00:00:01"));
160 +
161 + configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1);
162 + String interfaceSw2Eth1 = "s2-eth1";
163 + Interface intfsw2eth1 = new Interface(s2Eth1,
164 + Collections.singleton(IpPrefix.valueOf("192.168.20.0/24")),
165 + MacAddress.valueOf("00:00:00:00:00:02"));
166 + configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1);
167 +
168 + interfaceService = createMock(InterfaceService.class);
169 +
170 + expect(interfaceService.getInterface(s1Eth1))
171 + .andReturn(intfsw1eth1).anyTimes();
172 + expect(interfaceService.getInterface(s2Eth1))
173 + .andReturn(intfsw2eth1).anyTimes();
174 +
175 + // Non-existent interface used during one of the tests
176 + expect(interfaceService.getInterface(new ConnectPoint(
177 + DeviceId.deviceId(SdnIp.dpidToUri("00:00:00:00:00:00:01:00")),
178 + PortNumber.portNumber(1))))
179 + .andReturn(null).anyTimes();
180 +
181 + expect(interfaceService.getInterfaces()).andReturn(
182 + Sets.newHashSet(configuredInterfaces.values())).anyTimes();
183 + replay(interfaceService);
184 +
185 + return configuredInterfaces;
186 + }
187 +
188 + /**
189 + * Sets up BGP daemon peers.
190 + *
191 + * @return configured BGP peers as a MAP from peer IP address to BgpPeer
192 + */
193 + private Map<IpAddress, BgpPeer> setUpPeers() {
194 +
195 + configuredPeers = new HashMap<>();
196 +
197 + String peerSw1Eth1 = "192.168.10.1";
198 + configuredPeers.put(IpAddress.valueOf(peerSw1Eth1),
199 + new BgpPeer(dpid1, 1, peerSw1Eth1));
200 +
201 + // Two BGP peers are connected to switch 2 port 1.
202 + String peer1Sw2Eth1 = "192.168.20.1";
203 + configuredPeers.put(IpAddress.valueOf(peer1Sw2Eth1),
204 + new BgpPeer(dpid2, 1, peer1Sw2Eth1));
205 +
206 + String peer2Sw2Eth1 = "192.168.20.2";
207 + configuredPeers.put(IpAddress.valueOf(peer2Sw2Eth1),
208 + new BgpPeer(dpid2, 1, peer2Sw2Eth1));
209 +
210 + return configuredPeers;
211 + }
212 +
213 + /**
214 + * Sets up expected point to point intent list.
215 + *
216 + * @return point to point intent list
217 + */
218 + private List<PointToPointIntent> setUpIntentList() {
219 +
220 + intentList = new ArrayList<PointToPointIntent>();
221 +
222 + setUpBgpIntents();
223 + setUpIcmpIntents();
224 +
225 + return intentList;
226 +
227 + }
228 +
229 + /**
230 + * Constructs a BGP intent and put it into the intentList.
231 + * <p/>
232 + * The purpose of this method is too simplify the setUpBgpIntents() method,
233 + * and to make the setUpBgpIntents() easy to read.
234 + *
235 + * @param srcPrefix source IP prefix to match
236 + * @param dstPrefix destination IP prefix to match
237 + * @param srcTcpPort source TCP port to match
238 + * @param dstTcpPort destination TCP port to match
239 + * @param srcConnectPoint source connect point for PointToPointIntent
240 + * @param dstConnectPoint destination connect point for PointToPointIntent
241 + */
242 + private void bgpPathintentConstructor(String srcPrefix, String dstPrefix,
243 + Short srcTcpPort, Short dstTcpPort,
244 + ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) {
245 +
246 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
247 + .matchEthType(Ethernet.TYPE_IPV4)
248 + .matchIPProtocol(IPv4.PROTOCOL_TCP)
249 + .matchIPSrc(IpPrefix.valueOf(srcPrefix))
250 + .matchIPDst(IpPrefix.valueOf(dstPrefix));
251 +
252 + if (srcTcpPort != null) {
253 + builder.matchTcpSrc(srcTcpPort);
254 + }
255 + if (dstTcpPort != null) {
256 + builder.matchTcpDst(dstTcpPort);
257 + }
258 +
259 + PointToPointIntent intent = new PointToPointIntent(
260 + testIntentId, builder.build(), noTreatment,
261 + srcConnectPoint, dstConnectPoint);
262 +
263 + intentList.add(intent);
264 + }
265 +
266 + /**
267 + * Sets up intents for BGP paths.
268 + */
269 + private void setUpBgpIntents() {
270 +
271 + Short bgpPort = Short.valueOf((short) BgpConstants.BGP_PORT);
272 +
273 + // Start to build intents between BGP speaker1 and BGP peer1
274 + bgpPathintentConstructor(
275 + "192.168.10.101/32", "192.168.10.1/32", null, bgpPort,
276 + s1Eth100, s1Eth1);
277 + bgpPathintentConstructor(
278 + "192.168.10.101/32", "192.168.10.1/32", bgpPort, null,
279 + s1Eth100, s1Eth1);
280 +
281 + bgpPathintentConstructor(
282 + "192.168.10.1/32", "192.168.10.101/32", null, bgpPort,
283 + s1Eth1, s1Eth100);
284 + bgpPathintentConstructor(
285 + "192.168.10.1/32", "192.168.10.101/32", bgpPort, null,
286 + s1Eth1, s1Eth100);
287 +
288 + // Start to build intents between BGP speaker1 and BGP peer2
289 + bgpPathintentConstructor(
290 + "192.168.20.101/32", "192.168.20.1/32", null, bgpPort,
291 + s1Eth100, s2Eth1);
292 + bgpPathintentConstructor(
293 + "192.168.20.101/32", "192.168.20.1/32", bgpPort, null,
294 + s1Eth100, s2Eth1);
295 +
296 + bgpPathintentConstructor(
297 + "192.168.20.1/32", "192.168.20.101/32", null, bgpPort,
298 + s2Eth1, s1Eth100);
299 + bgpPathintentConstructor(
300 + "192.168.20.1/32", "192.168.20.101/32", bgpPort, null,
301 + s2Eth1, s1Eth100);
302 +
303 + // Start to build intents between BGP speaker1 and BGP peer3
304 + bgpPathintentConstructor(
305 + "192.168.20.101/32", "192.168.20.2/32", null, bgpPort,
306 + s1Eth100, s2Eth1);
307 + bgpPathintentConstructor(
308 + "192.168.20.101/32", "192.168.20.2/32", bgpPort, null,
309 + s1Eth100, s2Eth1);
310 +
311 + bgpPathintentConstructor(
312 + "192.168.20.2/32", "192.168.20.101/32", null, bgpPort,
313 + s2Eth1, s1Eth100);
314 + bgpPathintentConstructor(
315 + "192.168.20.2/32", "192.168.20.101/32", bgpPort, null,
316 + s2Eth1, s1Eth100);
317 +
318 + //
319 + // Start to build intents between BGP speaker2 and BGP peer1
320 + bgpPathintentConstructor(
321 + "192.168.10.102/32", "192.168.10.1/32", null, bgpPort,
322 + s1Eth100, s1Eth1);
323 + bgpPathintentConstructor(
324 + "192.168.10.102/32", "192.168.10.1/32", bgpPort, null,
325 + s1Eth100, s1Eth1);
326 +
327 + bgpPathintentConstructor(
328 + "192.168.10.1/32", "192.168.10.102/32", null, bgpPort,
329 + s1Eth1, s1Eth100);
330 + bgpPathintentConstructor(
331 + "192.168.10.1/32", "192.168.10.102/32", bgpPort, null,
332 + s1Eth1, s1Eth100);
333 + // Start to build intents between BGP speaker2 and BGP peer2
334 + bgpPathintentConstructor(
335 + "192.168.20.102/32", "192.168.20.1/32", null, bgpPort,
336 + s1Eth100, s2Eth1);
337 + bgpPathintentConstructor(
338 + "192.168.20.102/32", "192.168.20.1/32", bgpPort, null,
339 + s1Eth100, s2Eth1);
340 +
341 + bgpPathintentConstructor(
342 + "192.168.20.1/32", "192.168.20.102/32", null, bgpPort,
343 + s2Eth1, s1Eth100);
344 + bgpPathintentConstructor(
345 + "192.168.20.1/32", "192.168.20.102/32", bgpPort, null,
346 + s2Eth1, s1Eth100);
347 +
348 + // Start to build intents between BGP speaker2 and BGP peer3
349 + bgpPathintentConstructor(
350 + "192.168.20.102/32", "192.168.20.2/32", null, bgpPort,
351 + s1Eth100, s2Eth1);
352 + bgpPathintentConstructor(
353 + "192.168.20.102/32", "192.168.20.2/32", bgpPort, null,
354 + s1Eth100, s2Eth1);
355 +
356 + bgpPathintentConstructor(
357 + "192.168.20.2/32", "192.168.20.102/32", null, bgpPort,
358 + s2Eth1, s1Eth100);
359 + bgpPathintentConstructor(
360 + "192.168.20.2/32", "192.168.20.102/32", bgpPort, null,
361 + s2Eth1, s1Eth100);
362 +
363 + //
364 + // Start to build intents between BGP speaker3 and BGP peer1
365 + bgpPathintentConstructor(
366 + "192.168.10.103/32", "192.168.10.1/32", null, bgpPort,
367 + s2Eth100, s1Eth1);
368 + bgpPathintentConstructor(
369 + "192.168.10.103/32", "192.168.10.1/32", bgpPort, null,
370 + s2Eth100, s1Eth1);
371 +
372 + bgpPathintentConstructor(
373 + "192.168.10.1/32", "192.168.10.103/32", null, bgpPort,
374 + s1Eth1, s2Eth100);
375 + bgpPathintentConstructor(
376 + "192.168.10.1/32", "192.168.10.103/32", bgpPort, null,
377 + s1Eth1, s2Eth100);
378 +
379 + // Start to build intents between BGP speaker3 and BGP peer2
380 + bgpPathintentConstructor(
381 + "192.168.20.103/32", "192.168.20.1/32", null, bgpPort,
382 + s2Eth100, s2Eth1);
383 + bgpPathintentConstructor(
384 + "192.168.20.103/32", "192.168.20.1/32", bgpPort, null,
385 + s2Eth100, s2Eth1);
386 +
387 + bgpPathintentConstructor(
388 + "192.168.20.1/32", "192.168.20.103/32", null, bgpPort,
389 + s2Eth1, s2Eth100);
390 + bgpPathintentConstructor(
391 + "192.168.20.1/32", "192.168.20.103/32", bgpPort, null,
392 + s2Eth1, s2Eth100);
393 +
394 + // Start to build intents between BGP speaker3 and BGP peer3
395 + bgpPathintentConstructor(
396 + "192.168.20.103/32", "192.168.20.2/32", null, bgpPort,
397 + s2Eth100, s2Eth1);
398 + bgpPathintentConstructor(
399 + "192.168.20.103/32", "192.168.20.2/32", bgpPort, null,
400 + s2Eth100, s2Eth1);
401 +
402 + bgpPathintentConstructor(
403 + "192.168.20.2/32", "192.168.20.103/32", null, bgpPort,
404 + s2Eth1, s2Eth100);
405 + bgpPathintentConstructor(
406 + "192.168.20.2/32", "192.168.20.103/32", bgpPort, null,
407 + s2Eth1, s2Eth100);
408 + }
409 +
410 + /**
411 + * Constructs a BGP intent and put it into the intentList.
412 + * <p/>
413 + * The purpose of this method is too simplify the setUpBgpIntents() method,
414 + * and to make the setUpBgpIntents() easy to read.
415 + *
416 + * @param srcPrefix source IP prefix to match
417 + * @param dstPrefix destination IP prefix to match
418 + * @param srcConnectPoint source connect point for PointToPointIntent
419 + * @param dstConnectPoint destination connect point for PointToPointIntent
420 + */
421 + private void icmpPathintentConstructor(String srcPrefix, String dstPrefix,
422 + ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) {
423 +
424 + TrafficSelector selector = DefaultTrafficSelector.builder()
425 + .matchEthType(Ethernet.TYPE_IPV4)
426 + .matchIPProtocol(IPv4.PROTOCOL_ICMP)
427 + .matchIPSrc(IpPrefix.valueOf(srcPrefix))
428 + .matchIPDst(IpPrefix.valueOf(dstPrefix))
429 + .build();
430 +
431 + PointToPointIntent intent = new PointToPointIntent(
432 + testIntentId, selector, noTreatment,
433 + srcConnectPoint, dstConnectPoint);
434 +
435 + intentList.add(intent);
436 + }
437 +
438 + /**
439 + * Sets up intents for ICMP paths.
440 + */
441 + private void setUpIcmpIntents() {
442 +
443 + // Start to build intents between BGP speaker1 and BGP peer1
444 + icmpPathintentConstructor(
445 + "192.168.10.101/32", "192.168.10.1/32", s1Eth100, s1Eth1);
446 + icmpPathintentConstructor(
447 + "192.168.10.1/32", "192.168.10.101/32", s1Eth1, s1Eth100);
448 +
449 + // Start to build intents between BGP speaker1 and BGP peer2
450 + icmpPathintentConstructor(
451 + "192.168.20.101/32", "192.168.20.1/32", s1Eth100, s2Eth1);
452 + icmpPathintentConstructor(
453 + "192.168.20.1/32", "192.168.20.101/32", s2Eth1, s1Eth100);
454 +
455 + // Start to build intents between BGP speaker1 and BGP peer3
456 + icmpPathintentConstructor(
457 + "192.168.20.101/32", "192.168.20.2/32", s1Eth100, s2Eth1);
458 + icmpPathintentConstructor(
459 + "192.168.20.2/32", "192.168.20.101/32", s2Eth1, s1Eth100);
460 +
461 + //
462 + // Start to build intents between BGP speaker2 and BGP peer1
463 + icmpPathintentConstructor(
464 + "192.168.10.102/32", "192.168.10.1/32", s1Eth100, s1Eth1);
465 + icmpPathintentConstructor(
466 + "192.168.10.1/32", "192.168.10.102/32", s1Eth1, s1Eth100);
467 +
468 + // Start to build intents between BGP speaker2 and BGP peer2
469 + icmpPathintentConstructor(
470 + "192.168.20.102/32", "192.168.20.1/32", s1Eth100, s2Eth1);
471 + icmpPathintentConstructor(
472 + "192.168.20.1/32", "192.168.20.102/32", s2Eth1, s1Eth100);
473 +
474 + // Start to build intents between BGP speaker2 and BGP peer3
475 + icmpPathintentConstructor(
476 + "192.168.20.102/32", "192.168.20.2/32", s1Eth100, s2Eth1);
477 + icmpPathintentConstructor(
478 + "192.168.20.2/32", "192.168.20.102/32", s2Eth1, s1Eth100);
479 +
480 + //
481 + // Start to build intents between BGP speaker3 and BGP peer1
482 + icmpPathintentConstructor(
483 + "192.168.10.103/32", "192.168.10.1/32", s2Eth100, s1Eth1);
484 + icmpPathintentConstructor(
485 + "192.168.10.1/32", "192.168.10.103/32", s1Eth1, s2Eth100);
486 +
487 + // Start to build intents between BGP speaker3 and BGP peer2
488 + icmpPathintentConstructor(
489 + "192.168.20.103/32", "192.168.20.1/32", s2Eth100, s2Eth1);
490 + icmpPathintentConstructor(
491 + "192.168.20.1/32", "192.168.20.103/32", s2Eth1, s2Eth100);
492 +
493 + // Start to build intents between BGP speaker3 and BGP peer3
494 + icmpPathintentConstructor(
495 + "192.168.20.103/32", "192.168.20.2/32", s2Eth100, s2Eth1);
496 + icmpPathintentConstructor(
497 + "192.168.20.2/32", "192.168.20.103/32", s2Eth1, s2Eth100);
498 +
499 + }
500 +
501 + /**
502 + * Initializes peer connectivity testing environment.
503 + */
504 + private void initPeerConnectivity() {
505 +
506 + configInfoService = createMock(SdnIpConfigService.class);
507 + expect(configInfoService.getBgpPeers()).andReturn(peers).anyTimes();
508 + expect(configInfoService.getBgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
509 + replay(configInfoService);
510 +
511 + intentService = createMock(IntentService.class);
512 + replay(intentService);
513 +
514 + peerConnectivityManager = new PeerConnectivityManager(configInfoService,
515 + interfaceService, intentService);
516 + }
517 +
518 + /*
519 + * EasyMock matcher that matches {@link PointToPointIntent}s but
520 + * ignores the {@link IntentId} when matching.
521 + * <p/>
522 + * The normal intent equals method tests that the intent IDs are equal,
523 + * however in these tests we can't know what the intent IDs will be in
524 + * advance, so we can't set up expected intents with the correct IDs. Thus,
525 + * the solution is to use an EasyMock matcher that verifies that all the
526 + * value properties of the provided intent match the expected values, but
527 + * ignores the intent ID when testing equality.
528 + */
529 + private static final class IdAgnosticPointToPointIntentMatcher implements
530 + IArgumentMatcher {
531 +
532 + private final PointToPointIntent intent;
533 + private String providedIntentString;
534 +
535 + /**
536 + * Constructor taking the expected intent to match against.
537 + *
538 + * @param intent the expected intent
539 + */
540 + public IdAgnosticPointToPointIntentMatcher(PointToPointIntent intent) {
541 + this.intent = intent;
542 + }
543 +
544 + @Override
545 + public void appendTo(StringBuffer strBuffer) {
546 + strBuffer.append("PointToPointIntentMatcher unable to match: "
547 + + providedIntentString);
548 + }
549 +
550 + @Override
551 + public boolean matches(Object object) {
552 + if (!(object instanceof PointToPointIntent)) {
553 + return false;
554 + }
555 +
556 + PointToPointIntent providedIntent = (PointToPointIntent) object;
557 + providedIntentString = providedIntent.toString();
558 +
559 + PointToPointIntent matchIntent =
560 + new PointToPointIntent(providedIntent.id(),
561 + intent.selector(), intent.treatment(),
562 + intent.ingressPoint(), intent.egressPoint());
563 +
564 + return matchIntent.equals(providedIntent);
565 + }
566 + }
567 +
568 + /**
569 + * Matcher method to set an expected intent to match against (ignoring the
570 + * the intent ID).
571 + *
572 + * @param intent the expected intent
573 + * @return something of type PointToPointIntent
574 + */
575 + private static PointToPointIntent eqExceptId(
576 + PointToPointIntent intent) {
577 + reportMatcher(new IdAgnosticPointToPointIntentMatcher(intent));
578 + return null;
579 + }
580 +
581 + /**
582 + * Tests whether peer connectivity manager can set up correct BGP and
583 + * ICMP intents according to specific configuration.
584 + * <p/>
585 + * Two tricky cases included in the configuration are: 2 peers on a same
586 + * switch port, peer on the same switch with BGPd.
587 + */
588 + @Test
589 + public void testConnectionSetup() {
590 +
591 + reset(intentService);
592 +
593 + // Sets up the expected PointToPoint intents.
594 + for (int i = 0; i < intentList.size(); i++) {
595 + intentService.submit(eqExceptId(intentList.get(i)));
596 + }
597 +
598 + replay(intentService);
599 +
600 + // Running the interface to be tested.
601 + peerConnectivityManager.start();
602 +
603 + verify(intentService);
604 +
605 + }
606 +
607 + /**
608 + * Tests a corner case, when there are no interfaces in the configuration.
609 + */
610 + @Test
611 + public void testNullInterfaces() {
612 + reset(interfaceService);
613 + expect(interfaceService.getInterfaces()).andReturn(
614 + Sets.<Interface>newHashSet()).anyTimes();
615 + expect(interfaceService.getInterface(s2Eth1))
616 + .andReturn(null).anyTimes();
617 + expect(interfaceService.getInterface(s1Eth1))
618 + .andReturn(null).anyTimes();
619 + replay(interfaceService);
620 +
621 + reset(configInfoService);
622 + expect(configInfoService.getBgpPeers()).andReturn(peers).anyTimes();
623 + expect(configInfoService.getBgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
624 + replay(configInfoService);
625 +
626 + reset(intentService);
627 + replay(intentService);
628 + peerConnectivityManager.start();
629 + verify(intentService);
630 + }
631 +
632 + /**
633 + * Tests a corner case, when there are no BGP peers in the configuration.
634 + */
635 + @Test
636 + public void testNullBgpPeers() {
637 + reset(interfaceService);
638 + expect(interfaceService.getInterfaces()).andReturn(
639 + Sets.newHashSet(interfaces.values())).anyTimes();
640 + replay(interfaceService);
641 +
642 + reset(configInfoService);
643 + expect(configInfoService.getBgpPeers()).andReturn(
644 + new HashMap<IpAddress, BgpPeer>()).anyTimes();
645 + expect(configInfoService.getBgpSpeakers()).andReturn(
646 + bgpSpeakers).anyTimes();
647 + replay(configInfoService);
648 +
649 + reset(intentService);
650 + replay(intentService);
651 + peerConnectivityManager.start();
652 + verify(intentService);
653 + }
654 +
655 + /**
656 + * Tests a corner case, when there is no BGP speakers in the configuration.
657 + */
658 + @Test
659 + public void testNullBgpSpeakers() {
660 + reset(interfaceService);
661 + expect(interfaceService.getInterfaces()).andReturn(
662 + Sets.newHashSet(interfaces.values())).anyTimes();
663 + replay(interfaceService);
664 +
665 + reset(configInfoService);
666 + expect(configInfoService.getBgpPeers()).andReturn(
667 + peers).anyTimes();
668 + expect(configInfoService.getBgpSpeakers()).andReturn(
669 + null).anyTimes();
670 + replay(configInfoService);
671 +
672 + reset(intentService);
673 + replay(intentService);
674 + peerConnectivityManager.start();
675 + verify(intentService);
676 + }
677 +
678 + /**
679 + * Tests a corner case, when there is no Interface configured for one BGP
680 + * peer.
681 + */
682 + @Test
683 + public void testNoPeerInterface() {
684 + String peerSw100Eth1 = "192.168.200.1";
685 + configuredPeers.put(IpAddress.valueOf(peerSw100Eth1),
686 + new BgpPeer("00:00:00:00:00:00:01:00", 1, peerSw100Eth1));
687 + testConnectionSetup();
688 + }
689 +
690 + /**
691 + * Tests a corner case, when there is no Interface configured for one BGP
692 + * speaker.
693 + * TODO: we should add a configuration correctness checking module/method
694 + * before testing this corner case.
695 + */
696 + @Ignore
697 + @Test
698 + public void testNoSpeakerInterface() {
699 + BgpSpeaker bgpSpeaker100 = new BgpSpeaker(
700 + "bgpSpeaker100",
701 + "00:00:00:00:00:00:01:00", 100,
702 + "00:00:00:00:01:00");
703 + List<InterfaceAddress> interfaceAddresses100 =
704 + new LinkedList<InterfaceAddress>();
705 + interfaceAddresses100.add(new InterfaceAddress(dpid1, 1, "192.168.10.201"));
706 + interfaceAddresses100.add(new InterfaceAddress(dpid2, 1, "192.168.20.201"));
707 + bgpSpeaker100.setInterfaceAddresses(interfaceAddresses100);
708 + configuredBgpSpeakers.put(bgpSpeaker100.name(), bgpSpeaker100);
709 + testConnectionSetup();
710 + }
711 +}
...@@ -7,6 +7,8 @@ import org.onlab.onos.net.Provided; ...@@ -7,6 +7,8 @@ import org.onlab.onos.net.Provided;
7 */ 7 */
8 public interface Topology extends Provided { 8 public interface Topology extends Provided {
9 9
10 + // FIXME: Following is not true right now. It is actually System.nanoTime(),
11 + // which has no relation to epoch time, wall clock, etc.
10 /** 12 /**
11 * Returns the time, specified in milliseconds since start of epoch, 13 * Returns the time, specified in milliseconds since start of epoch,
12 * when the topology became active and made available. 14 * when the topology became active and made available.
......
...@@ -52,6 +52,12 @@ ...@@ -52,6 +52,12 @@
52 <artifactId>easymock</artifactId> 52 <artifactId>easymock</artifactId>
53 <scope>test</scope> 53 <scope>test</scope>
54 </dependency> 54 </dependency>
55 + <dependency>
56 + <groupId>org.onlab.onos</groupId>
57 + <artifactId>onos-api</artifactId>
58 + <classifier>tests</classifier>
59 + <scope>test</scope>
60 + </dependency>
55 </dependencies> 61 </dependencies>
56 62
57 </project> 63 </project>
......
...@@ -3,7 +3,7 @@ package org.onlab.onos.store.flow; ...@@ -3,7 +3,7 @@ package org.onlab.onos.store.flow;
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 4
5 /** 5 /**
6 - * Service to return where the Replica should be placed. 6 + * Service to return where the replica should be placed.
7 */ 7 */
8 public interface ReplicaInfoService { 8 public interface ReplicaInfoService {
9 9
...@@ -15,4 +15,19 @@ public interface ReplicaInfoService { ...@@ -15,4 +15,19 @@ public interface ReplicaInfoService {
15 * @return placement information 15 * @return placement information
16 */ 16 */
17 ReplicaInfo getReplicaInfoFor(DeviceId deviceId); 17 ReplicaInfo getReplicaInfoFor(DeviceId deviceId);
18 +
19 + /**
20 + * Adds the specified replica placement info change listener.
21 + *
22 + * @param listener the replica placement info change listener
23 + */
24 + void addListener(ReplicaInfoEventListener listener);
25 +
26 + /**
27 + * Removes the specified replica placement info change listener.
28 + *
29 + * @param listener the replica placement info change listener
30 + */
31 + void removeListener(ReplicaInfoEventListener listener);
32 +
18 } 33 }
......
1 package org.onlab.onos.store.flow.impl; 1 package org.onlab.onos.store.flow.impl;
2 2
3 +import static com.google.common.base.Preconditions.checkNotNull;
3 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
4 import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED; 5 import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED;
5 6
...@@ -66,6 +67,16 @@ public class ReplicaInfoManager implements ReplicaInfoService { ...@@ -66,6 +67,16 @@ public class ReplicaInfoManager implements ReplicaInfoService {
66 Collections.<NodeId>emptyList()); 67 Collections.<NodeId>emptyList());
67 } 68 }
68 69
70 + @Override
71 + public void addListener(ReplicaInfoEventListener listener) {
72 + listenerRegistry.addListener(checkNotNull(listener));
73 + }
74 +
75 + @Override
76 + public void removeListener(ReplicaInfoEventListener listener) {
77 + listenerRegistry.removeListener(checkNotNull(listener));
78 + }
79 +
69 final class InternalMastershipListener implements MastershipListener { 80 final class InternalMastershipListener implements MastershipListener {
70 81
71 @Override 82 @Override
......
1 +package org.onlab.onos.store.flow.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkState;
4 +import static org.junit.Assert.*;
5 +
6 +import java.util.Collections;
7 +import java.util.Map;
8 +import java.util.concurrent.CountDownLatch;
9 +import java.util.concurrent.TimeUnit;
10 +
11 +import org.junit.After;
12 +import org.junit.Before;
13 +import org.junit.Test;
14 +import org.onlab.onos.cluster.NodeId;
15 +import org.onlab.onos.event.AbstractListenerRegistry;
16 +import org.onlab.onos.event.DefaultEventSinkRegistry;
17 +import org.onlab.onos.event.Event;
18 +import org.onlab.onos.event.EventDeliveryService;
19 +import org.onlab.onos.event.EventSink;
20 +import org.onlab.onos.mastership.MastershipEvent;
21 +import org.onlab.onos.mastership.MastershipEvent.Type;
22 +import org.onlab.onos.mastership.MastershipListener;
23 +import org.onlab.onos.mastership.MastershipService;
24 +import org.onlab.onos.mastership.MastershipServiceAdapter;
25 +import org.onlab.onos.net.DeviceId;
26 +import org.onlab.onos.store.flow.ReplicaInfo;
27 +import org.onlab.onos.store.flow.ReplicaInfoEvent;
28 +import org.onlab.onos.store.flow.ReplicaInfoEventListener;
29 +import org.onlab.onos.store.flow.ReplicaInfoService;
30 +
31 +import com.google.common.base.Optional;
32 +import com.google.common.collect.Maps;
33 +
34 +public class ReplicaInfoManagerTest {
35 +
36 +
37 + private static final DeviceId DID1 = DeviceId.deviceId("of:1");
38 + private static final DeviceId DID2 = DeviceId.deviceId("of:2");
39 + private static final NodeId NID1 = new NodeId("foo");
40 +
41 + private ReplicaInfoManager mgr;
42 + private ReplicaInfoService service;
43 +
44 + private AbstractListenerRegistry<MastershipEvent, MastershipListener>
45 + mastershipListenerRegistry;
46 + private TestEventDispatcher eventDispatcher;
47 +
48 +
49 + @Before
50 + public void setUp() throws Exception {
51 + mastershipListenerRegistry = new AbstractListenerRegistry<>();
52 +
53 + mgr = new ReplicaInfoManager();
54 + service = mgr;
55 +
56 + eventDispatcher = new TestEventDispatcher();
57 + mgr.eventDispatcher = eventDispatcher;
58 + mgr.mastershipService = new TestMastershipService();
59 +
60 + // register dummy mastership event source
61 + mgr.eventDispatcher.addSink(MastershipEvent.class, mastershipListenerRegistry);
62 +
63 + mgr.activate();
64 + }
65 +
66 + @After
67 + public void tearDown() throws Exception {
68 + mgr.deactivate();
69 + }
70 +
71 + @Test
72 + public void testGetReplicaInfoFor() {
73 + ReplicaInfo info1 = service.getReplicaInfoFor(DID1);
74 + assertEquals(Optional.of(NID1), info1.master());
75 + // backups are always empty for now
76 + assertEquals(Collections.emptyList(), info1.backups());
77 +
78 + ReplicaInfo info2 = service.getReplicaInfoFor(DID2);
79 + assertEquals("There's no master", Optional.absent(), info2.master());
80 + // backups are always empty for now
81 + assertEquals(Collections.emptyList(), info2.backups());
82 + }
83 +
84 + @Test
85 + public void testReplicaInfoEvent() throws InterruptedException {
86 + final CountDownLatch latch = new CountDownLatch(1);
87 + service.addListener(new MasterNodeCheck(latch, DID1, NID1));
88 +
89 + // fake MastershipEvent
90 + eventDispatcher.post(new MastershipEvent(Type.MASTER_CHANGED, DID1, NID1));
91 +
92 + assertTrue(latch.await(1, TimeUnit.SECONDS));
93 + }
94 +
95 +
96 + private final class MasterNodeCheck implements ReplicaInfoEventListener {
97 + private final CountDownLatch latch;
98 + private Optional<NodeId> expectedMaster;
99 + private DeviceId expectedDevice;
100 +
101 +
102 + MasterNodeCheck(CountDownLatch latch, DeviceId did,
103 + NodeId nid) {
104 + this.latch = latch;
105 + this.expectedMaster = Optional.fromNullable(nid);
106 + this.expectedDevice = did;
107 + }
108 +
109 + @Override
110 + public void event(ReplicaInfoEvent event) {
111 + assertEquals(expectedDevice, event.subject());
112 + assertEquals(expectedMaster, event.replicaInfo().master());
113 + // backups are always empty for now
114 + assertEquals(Collections.emptyList(), event.replicaInfo().backups());
115 + latch.countDown();
116 + }
117 + }
118 +
119 +
120 + private final class TestMastershipService
121 + extends MastershipServiceAdapter
122 + implements MastershipService {
123 +
124 + private Map<DeviceId, NodeId> masters;
125 +
126 + TestMastershipService() {
127 + masters = Maps.newHashMap();
128 + masters.put(DID1, NID1);
129 + // DID2 has no master
130 + }
131 +
132 + @Override
133 + public NodeId getMasterFor(DeviceId deviceId) {
134 + return masters.get(deviceId);
135 + }
136 +
137 + @Override
138 + public void addListener(MastershipListener listener) {
139 + mastershipListenerRegistry.addListener(listener);
140 + }
141 +
142 + @Override
143 + public void removeListener(MastershipListener listener) {
144 + mastershipListenerRegistry.removeListener(listener);
145 + }
146 + }
147 +
148 +
149 + // code clone
150 + /**
151 + * Implements event delivery system that delivers events synchronously, or
152 + * in-line with the post method invocation.
153 + */
154 + private static class TestEventDispatcher extends DefaultEventSinkRegistry
155 + implements EventDeliveryService {
156 +
157 + @SuppressWarnings({ "rawtypes", "unchecked" })
158 + @Override
159 + public void post(Event event) {
160 + EventSink sink = getSink(event.getClass());
161 + checkState(sink != null, "No sink for event %s", event);
162 + sink.process(event);
163 + }
164 + }
165 +}
...@@ -172,7 +172,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr ...@@ -172,7 +172,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
172 */ 172 */
173 private List<PortDescription> buildPortDescriptions( 173 private List<PortDescription> buildPortDescriptions(
174 List<OFPortDesc> ports) { 174 List<OFPortDesc> ports) {
175 - final List<PortDescription> portDescs = new ArrayList<>(); 175 + final List<PortDescription> portDescs = new ArrayList<>(ports.size());
176 for (OFPortDesc port : ports) { 176 for (OFPortDesc port : ports) {
177 portDescs.add(buildPortDescription(port)); 177 portDescs.add(buildPortDescription(port));
178 } 178 }
......