eb7a39366d7f71f263e4a9df8902ded5be5bec6d
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
4  * 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
7  *
8  *     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.
15  */
16 package org.onosproject.net.intent.impl.compiler;
17
18 import org.hamcrest.Matchers;
19 import org.junit.Test;
20 import org.onosproject.TestApplicationId;
21 import org.onosproject.core.ApplicationId;
22 import org.onosproject.net.ConnectPoint;
23 import org.onosproject.net.DeviceId;
24 import org.onosproject.net.ElementId;
25 import org.onosproject.net.Path;
26 import org.onosproject.net.device.DeviceServiceAdapter;
27 import org.onosproject.net.flow.TrafficSelector;
28 import org.onosproject.net.flow.TrafficTreatment;
29 import org.onosproject.net.intent.AbstractIntentTest;
30 import org.onosproject.net.intent.Intent;
31 import org.onosproject.net.intent.IntentTestsMocks;
32 import org.onosproject.net.intent.LinkCollectionIntent;
33 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
34 import org.onosproject.net.topology.LinkWeight;
35 import org.onosproject.net.topology.PathService;
36
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Set;
40
41 import static org.hamcrest.CoreMatchers.instanceOf;
42 import static org.hamcrest.CoreMatchers.notNullValue;
43 import static org.hamcrest.MatcherAssert.assertThat;
44 import static org.hamcrest.Matchers.hasSize;
45 import static org.hamcrest.Matchers.is;
46 import static org.onosproject.net.NetTestTools.connectPoint;
47 import static org.onosproject.net.NetTestTools.createPath;
48 import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
49
50 /**
51  * Unit tests for the MultiPointToSinglePoint intent compiler.
52  */
53 public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTest {
54
55     private static final ApplicationId APPID = new TestApplicationId("foo");
56
57     private TrafficSelector selector = new IntentTestsMocks.MockSelector();
58     private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
59
60     /**
61      * Mock path service for creating paths within the test.
62      */
63     private static class MockPathService implements PathService {
64
65         final String[] pathHops;
66
67         /**
68          * Constructor that provides a set of hops to mock.
69          *
70          * @param pathHops path hops to mock
71          */
72         MockPathService(String[] pathHops) {
73             this.pathHops = pathHops;
74         }
75
76         @Override
77         public Set<Path> getPaths(ElementId src, ElementId dst) {
78             Set<Path> result = new HashSet<>();
79
80             String[] allHops = new String[pathHops.length + 1];
81             allHops[0] = src.toString();
82             if (pathHops.length != 0) {
83                 System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
84             }
85             result.add(createPath(allHops));
86
87             return result;
88         }
89
90         @Override
91         public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
92             return null;
93         }
94     }
95
96     /**
97      * Mocks the device service so that a device appears available in the test.
98      */
99     private static class MockDeviceService extends DeviceServiceAdapter {
100         @Override
101         public boolean isAvailable(DeviceId deviceId) {
102             return true;
103         }
104     }
105
106     /**
107      * Creates a MultiPointToSinglePoint intent for a group of ingress points
108      * and an egress point.
109      *
110      * @param ingressIds array of ingress device ids
111      * @param egressId   device id of the egress point
112      * @return MultiPointToSinglePoint intent
113      */
114     private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
115         Set<ConnectPoint> ingressPoints = new HashSet<>();
116         ConnectPoint egressPoint = connectPoint(egressId, 2);
117
118         for (String ingressId : ingressIds) {
119             ingressPoints.add(connectPoint(ingressId, 1));
120         }
121
122         return MultiPointToSinglePointIntent.builder()
123                 .appId(APPID)
124                 .selector(selector)
125                 .treatment(treatment)
126                 .ingressPoints(ingressPoints)
127                 .egressPoint(egressPoint)
128                 .build();
129     }
130
131     /**
132      * Creates a compiler for MultiPointToSinglePoint intents.
133      *
134      * @param hops hops to use while computing paths for this intent
135      * @return MultiPointToSinglePoint intent
136      */
137     private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops) {
138         MultiPointToSinglePointIntentCompiler compiler =
139                 new MultiPointToSinglePointIntentCompiler();
140         compiler.pathService = new MockPathService(hops);
141         compiler.deviceService = new MockDeviceService();
142         return compiler;
143     }
144
145     /**
146      * Tests a single ingress point with 8 hops to its egress point.
147      */
148     @Test
149     public void testSingleLongPathCompilation() {
150
151         String[] ingress = {"ingress"};
152         String egress = "egress";
153
154         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
155         assertThat(intent, is(notNullValue()));
156
157         String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8",
158                 egress};
159         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
160         assertThat(compiler, is(notNullValue()));
161
162         List<Intent> result = compiler.compile(intent, null, null);
163         assertThat(result, is(Matchers.notNullValue()));
164         assertThat(result, hasSize(1));
165         Intent resultIntent = result.get(0);
166         assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
167
168         if (resultIntent instanceof LinkCollectionIntent) {
169             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
170             assertThat(linkIntent.links(), hasSize(9));
171             assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
172             assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
173             assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
174             assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
175             assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
176             assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
177             assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
178         }
179     }
180
181     /**
182      * Tests a simple topology where two ingress points share some path segments
183      * and some path segments are not shared.
184      */
185     @Test
186     public void testTwoIngressCompilation() {
187         String[] ingress = {"ingress1", "ingress2"};
188         String egress = "egress";
189
190         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
191         assertThat(intent, is(notNullValue()));
192
193         final String[] hops = {"inner1", "inner2", egress};
194         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
195         assertThat(compiler, is(notNullValue()));
196
197         List<Intent> result = compiler.compile(intent, null, null);
198         assertThat(result, is(notNullValue()));
199         assertThat(result, hasSize(1));
200         Intent resultIntent = result.get(0);
201         assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
202
203         if (resultIntent instanceof LinkCollectionIntent) {
204             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
205             assertThat(linkIntent.links(), hasSize(4));
206             assertThat(linkIntent.links(), linksHasPath("ingress1", "inner1"));
207             assertThat(linkIntent.links(), linksHasPath("ingress2", "inner1"));
208             assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
209             assertThat(linkIntent.links(), linksHasPath("inner2", "egress"));
210         }
211     }
212
213     /**
214      * Tests a large number of ingress points that share a common path to the
215      * egress point.
216      */
217     @Test
218     public void testMultiIngressCompilation() {
219         String[] ingress = {"i1", "i2", "i3", "i4", "i5",
220                 "i6", "i7", "i8", "i9", "i10"};
221         String egress = "e";
222
223         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
224         assertThat(intent, is(notNullValue()));
225
226         final String[] hops = {"n1", egress};
227         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
228         assertThat(compiler, is(notNullValue()));
229
230         List<Intent> result = compiler.compile(intent, null, null);
231         assertThat(result, is(notNullValue()));
232         assertThat(result, hasSize(1));
233         Intent resultIntent = result.get(0);
234         assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
235
236         if (resultIntent instanceof LinkCollectionIntent) {
237             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
238             assertThat(linkIntent.links(), hasSize(ingress.length + 1));
239             for (String ingressToCheck : ingress) {
240                 assertThat(linkIntent.links(),
241                            linksHasPath(ingressToCheck,
242                                         "n1"));
243             }
244             assertThat(linkIntent.links(), linksHasPath("n1", egress));
245         }
246     }
247
248     /**
249      * Tests ingress and egress on the same device.
250      */
251     @Test
252     public void testSameDeviceCompilation() {
253         String[] ingress = {"i1", "i2"};
254         String egress = "i1";
255
256         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
257         assertThat(intent, is(notNullValue()));
258
259         final String[] hops = {"i1", "i2"};
260         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
261         assertThat(compiler, is(notNullValue()));
262
263         List<Intent> result = compiler.compile(intent, null, null);
264         assertThat(result, is(notNullValue()));
265         assertThat(result, hasSize(1));
266         Intent resultIntent = result.get(0);
267         assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
268
269         if (resultIntent instanceof LinkCollectionIntent) {
270             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
271             assertThat(linkIntent.links(), hasSize(ingress.length));
272
273             assertThat(linkIntent.links(), linksHasPath("i2", "i1"));
274         }
275     }
276 }