blob: a7388d15b348fc278df8313148a44d884210d09e [file] [log] [blame]
Charles Chan6c624992017-08-18 17:11:34 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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
17package org.onosproject.segmentrouting;
18
Charles Chan910be6a2017-08-23 14:46:43 -070019import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
Charles Chan6c624992017-08-18 17:11:34 -070021import com.google.common.collect.Maps;
22import com.google.common.collect.Sets;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.packet.IpAddress;
26import org.onlab.packet.IpPrefix;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Charles Chan910be6a2017-08-23 14:46:43 -070029import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chan6c624992017-08-18 17:11:34 -070030import org.onosproject.net.ConnectPoint;
Charles Chanf0ae41e2017-08-23 13:55:39 -070031import org.onosproject.net.DefaultHost;
Charles Chan6c624992017-08-18 17:11:34 -070032import org.onosproject.net.DeviceId;
33import org.onosproject.net.Host;
Charles Chanf0ae41e2017-08-23 13:55:39 -070034import org.onosproject.net.HostId;
35import org.onosproject.net.HostLocation;
Charles Chan910be6a2017-08-23 14:46:43 -070036import org.onosproject.net.PortNumber;
Charles Chan6c624992017-08-18 17:11:34 -070037import org.onosproject.net.config.NetworkConfigRegistryAdapter;
38import org.onosproject.net.flow.TrafficTreatment;
Charles Chan910be6a2017-08-23 14:46:43 -070039import org.onosproject.net.host.HostEvent;
40import org.onosproject.net.host.HostService;
Charles Chan6c624992017-08-18 17:11:34 -070041import org.onosproject.net.intf.Interface;
Charles Chanf0ae41e2017-08-23 13:55:39 -070042import org.onosproject.net.provider.ProviderId;
Charles Chan6c624992017-08-18 17:11:34 -070043import org.onosproject.routeservice.ResolvedRoute;
44import org.onosproject.routeservice.Route;
45import org.onosproject.routeservice.RouteEvent;
Charles Chan6c624992017-08-18 17:11:34 -070046import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan910be6a2017-08-23 14:46:43 -070047import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chand66d6712018-03-29 16:03:41 -070048import org.onosproject.store.service.StorageService;
49import org.onosproject.store.service.TestConsistentMap;
Charles Chan6c624992017-08-18 17:11:34 -070050
51import java.util.Map;
52import java.util.Set;
53
Charles Chand66d6712018-03-29 16:03:41 -070054import static org.easymock.EasyMock.expect;
Charles Chan06f626c2018-02-05 17:20:05 -080055import static org.easymock.EasyMock.reset;
Charles Chan6c624992017-08-18 17:11:34 -070056import static org.junit.Assert.*;
Charles Chan06f626c2018-02-05 17:20:05 -080057import static org.easymock.EasyMock.createMock;
58import static org.easymock.EasyMock.expectLastCall;
59import static org.easymock.EasyMock.replay;
60import static org.easymock.EasyMock.verify;
Charles Chan6c624992017-08-18 17:11:34 -070061
62/**
63 * Unit test for {@link RouteHandler}.
64 */
65public class RouteHandlerTest {
Charles Chan06f626c2018-02-05 17:20:05 -080066 private SegmentRoutingManager srManager;
Charles Chan6c624992017-08-18 17:11:34 -070067 private RouteHandler routeHandler;
Charles Chan910be6a2017-08-23 14:46:43 -070068 private HostService hostService;
Charles Chan6c624992017-08-18 17:11:34 -070069
70 // Mocked routing and bridging tables
71 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
72 Maps.newConcurrentMap();
73 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
74 Maps.newConcurrentMap();
75 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
76 // Mocked Next Id
77 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
78
79 private static final IpPrefix P1 = IpPrefix.valueOf("10.0.0.0/24");
Charles Chan910be6a2017-08-23 14:46:43 -070080
81 // Single homed router 1
Charles Chan6c624992017-08-18 17:11:34 -070082 private static final IpAddress N1 = IpAddress.valueOf("10.0.1.254");
83 private static final MacAddress M1 = MacAddress.valueOf("00:00:00:00:00:01");
84 private static final VlanId V1 = VlanId.vlanId((short) 1);
85 private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
86 private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
Charles Chanf0ae41e2017-08-23 13:55:39 -070087 private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1);
Charles Chan6c624992017-08-18 17:11:34 -070088
Charles Chan910be6a2017-08-23 14:46:43 -070089 // Single homed router 2
Charles Chan6c624992017-08-18 17:11:34 -070090 private static final IpAddress N2 = IpAddress.valueOf("10.0.2.254");
91 private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
92 private static final VlanId V2 = VlanId.vlanId((short) 2);
Charles Chan910be6a2017-08-23 14:46:43 -070093 private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/2");
Charles Chan6c624992017-08-18 17:11:34 -070094 private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
Charles Chanf0ae41e2017-08-23 13:55:39 -070095 private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2);
Charles Chan6c624992017-08-18 17:11:34 -070096
Charles Chan910be6a2017-08-23 14:46:43 -070097 // Dual homed router 1
98 private static final IpAddress N3 = IpAddress.valueOf("10.0.3.254");
99 private static final MacAddress M3 = MacAddress.valueOf("00:00:00:00:00:03");
100 private static final VlanId V3 = VlanId.vlanId((short) 3);
101 private static final Route R3 = new Route(Route.Source.STATIC, P1, N3);
102 private static final ResolvedRoute RR3 = new ResolvedRoute(R3, M3, V3);
Charles Chan6c624992017-08-18 17:11:34 -0700103
Charles Chan910be6a2017-08-23 14:46:43 -0700104 // Hosts
Charles Chanf0ae41e2017-08-23 13:55:39 -0700105 private static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(M1, V1), M1, V1,
106 Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N1), false);
107 private static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(M2, V2), M2, V2,
108 Sets.newHashSet(new HostLocation(CP2, 0)), Sets.newHashSet(N2), false);
Charles Chan910be6a2017-08-23 14:46:43 -0700109 private static final Host H3D = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
110 Sets.newHashSet(new HostLocation(CP1, 0), new HostLocation(CP2, 0)), Sets.newHashSet(N3), false);
111 private static final Host H3S = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
112 Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N3), false);
113
114 // Pair Local Port
115 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf0ae41e2017-08-23 13:55:39 -0700116
Charles Chan6c624992017-08-18 17:11:34 -0700117 // A set of hosts
Charles Chan910be6a2017-08-23 14:46:43 -0700118 private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2, H3D);
119 private static final Set<Host> HOSTS_ONE_FAIL = Sets.newHashSet(H1, H2, H3S);
120 private static final Set<Host> HOSTS_BOTH_FAIL = Sets.newHashSet(H1, H2);
Charles Chan6c624992017-08-18 17:11:34 -0700121 // A set of devices of which we have mastership
Charles Chan910be6a2017-08-23 14:46:43 -0700122 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
Charles Chan6c624992017-08-18 17:11:34 -0700123 // A set of interfaces
124 private static final Set<Interface> INTERFACES = Sets.newHashSet();
Charles Chan6c624992017-08-18 17:11:34 -0700125
126 @Before
127 public void setUp() throws Exception {
Charles Chan910be6a2017-08-23 14:46:43 -0700128 ObjectMapper mapper = new ObjectMapper();
129 ConfigApplyDelegate delegate = config -> { };
130
131 SegmentRoutingDeviceConfig dev1Config = new SegmentRoutingDeviceConfig();
132 JsonNode dev1Tree = mapper.createObjectNode();
133 dev1Config.init(CP1.deviceId(), "host-handler-test", dev1Tree, mapper, delegate);
134 dev1Config.setPairDeviceId(CP2.deviceId()).setPairLocalPort(P9);
135
136 SegmentRoutingDeviceConfig dev2Config = new SegmentRoutingDeviceConfig();
137 JsonNode dev2Tree = mapper.createObjectNode();
138 dev2Config.init(CP2.deviceId(), "host-handler-test", dev2Tree, mapper, delegate);
139 dev2Config.setPairDeviceId(CP1.deviceId()).setPairLocalPort(P9);
Charles Chan6c624992017-08-18 17:11:34 -0700140
141 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
Charles Chan910be6a2017-08-23 14:46:43 -0700142 mockNetworkConfigRegistry.applyConfig(dev1Config);
143 mockNetworkConfigRegistry.applyConfig(dev2Config);
Charles Chan6c624992017-08-18 17:11:34 -0700144
145 // Initialize Segment Routing Manager
Charles Chan06f626c2018-02-05 17:20:05 -0800146 srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chand66d6712018-03-29 16:03:41 -0700147 srManager.storageService = createMock(StorageService.class);
148 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
149 replay(srManager.storageService);
Charles Chan6c624992017-08-18 17:11:34 -0700150 srManager.cfgService = new NetworkConfigRegistryAdapter();
Charles Chan06f626c2018-02-05 17:20:05 -0800151 srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
Charles Chan6c624992017-08-18 17:11:34 -0700152 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
153 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanc4d68882018-03-15 16:41:10 -0700154 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700155 srManager.interfaceService = new MockInterfaceService(INTERFACES);
156 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
Charles Chan910be6a2017-08-23 14:46:43 -0700157 hostService = new MockHostService(HOSTS);
158 srManager.hostService = hostService;
Charles Chan6c624992017-08-18 17:11:34 -0700159 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chan910be6a2017-08-23 14:46:43 -0700160 srManager.routeService = new MockRouteService(ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700161
Charles Chan910be6a2017-08-23 14:46:43 -0700162 routeHandler = new RouteHandler(srManager) {
163 // routeEventCache is not necessary for unit tests
164 @Override
165 void enqueueRouteEvent(RouteEvent routeEvent) {
166 dequeueRouteEvent(routeEvent);
167 }
168 };
Charles Chan6c624992017-08-18 17:11:34 -0700169
170 ROUTING_TABLE.clear();
171 BRIDGING_TABLE.clear();
172 SUBNET_TABLE.clear();
173 }
174
175 @Test
176 public void init() throws Exception {
Charles Chan910be6a2017-08-23 14:46:43 -0700177 MockRoutingTableKey rtk = new MockRoutingTableKey(CP1.deviceId(), P1);
178 MockRoutingTableValue rtv = new MockRoutingTableValue(CP1.port(), M1, V1);
179 ROUTING_TABLE.put(rtk, rtv);
180
Charles Chan6c624992017-08-18 17:11:34 -0700181 routeHandler.init(CP1.deviceId());
182
183 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700184 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
185 assertEquals(M1, rtv1.macAddress);
186 assertEquals(V1, rtv1.vlanId);
187 assertEquals(CP1.port(), rtv1.portNumber);
188
Charles Chan6c624992017-08-18 17:11:34 -0700189 assertEquals(1, SUBNET_TABLE.size());
190 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
191 }
192
193 @Test
194 public void processRouteAdded() throws Exception {
Charles Chan06f626c2018-02-05 17:20:05 -0800195 reset(srManager.deviceConfiguration);
196 srManager.deviceConfiguration.addSubnet(CP1, P1);
197 expectLastCall().once();
198 replay(srManager.deviceConfiguration);
199
Charles Chan910be6a2017-08-23 14:46:43 -0700200 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700201 routeHandler.processRouteAdded(re);
202
203 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700204 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
205 assertEquals(M1, rtv1.macAddress);
206 assertEquals(V1, rtv1.vlanId);
207 assertEquals(CP1.port(), rtv1.portNumber);
208
Charles Chan6c624992017-08-18 17:11:34 -0700209 assertEquals(1, SUBNET_TABLE.size());
210 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800211
212 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700213 }
214
215 @Test
216 public void processRouteUpdated() throws Exception {
217 processRouteAdded();
218
Charles Chan06f626c2018-02-05 17:20:05 -0800219 reset(srManager.deviceConfiguration);
220 srManager.deviceConfiguration.removeSubnet(CP1, P1);
221 expectLastCall().once();
222 srManager.deviceConfiguration.addSubnet(CP2, P1);
223 expectLastCall().once();
224 replay(srManager.deviceConfiguration);
225
Charles Chan910be6a2017-08-23 14:46:43 -0700226 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1, Sets.newHashSet(RR2),
227 Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700228 routeHandler.processRouteUpdated(re);
229
Charles Chan06f626c2018-02-05 17:20:05 -0800230 // Note: We shouldn't remove the old nexthop during the occasion of route update
231 // since the populate subnet will take care of it and point it to an ECMP group
232 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700233 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
Charles Chanf0ae41e2017-08-23 13:55:39 -0700234 assertEquals(M2, rtv2.macAddress);
235 assertEquals(V2, rtv2.vlanId);
236 assertEquals(CP2.port(), rtv2.portNumber);
237
Charles Chan6c624992017-08-18 17:11:34 -0700238 assertEquals(1, SUBNET_TABLE.size());
239 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800240
241 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700242 }
243
244 @Test
245 public void processRouteRemoved() throws Exception {
246 processRouteAdded();
247
Charles Chan06f626c2018-02-05 17:20:05 -0800248 reset(srManager.deviceConfiguration);
249 srManager.deviceConfiguration.removeSubnet(CP1, P1);
250 expectLastCall().once();
251 replay(srManager.deviceConfiguration);
252
Charles Chan910be6a2017-08-23 14:46:43 -0700253 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1));
254 routeHandler.processRouteRemoved(re);
255
256 assertEquals(0, ROUTING_TABLE.size());
257 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800258
259 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700260 }
261
262 @Test
263 public void testTwoSingleHomedAdded() throws Exception {
Charles Chan06f626c2018-02-05 17:20:05 -0800264 reset(srManager.deviceConfiguration);
265 srManager.deviceConfiguration.addSubnet(CP1, P1);
266 expectLastCall().once();
267 srManager.deviceConfiguration.addSubnet(CP2, P1);
268 expectLastCall().once();
269 replay(srManager.deviceConfiguration);
270
Charles Chan910be6a2017-08-23 14:46:43 -0700271 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
272 routeHandler.processRouteAdded(re);
273
274 assertEquals(2, ROUTING_TABLE.size());
275 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
276 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
277 assertEquals(M1, rtv1.macAddress);
278 assertEquals(M2, rtv2.macAddress);
279 assertEquals(V1, rtv1.vlanId);
280 assertEquals(V2, rtv2.vlanId);
281 assertEquals(CP1.port(), rtv1.portNumber);
282 assertEquals(CP2.port(), rtv2.portNumber);
283
284 assertEquals(2, SUBNET_TABLE.size());
285 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
286 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800287
288 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700289 }
290
291 @Test
292 public void testOneDualHomedAdded() throws Exception {
Charles Chan06f626c2018-02-05 17:20:05 -0800293 reset(srManager.deviceConfiguration);
294 srManager.deviceConfiguration.addSubnet(CP1, P1);
295 expectLastCall().once();
296 srManager.deviceConfiguration.addSubnet(CP2, P1);
297 expectLastCall().once();
298 replay(srManager.deviceConfiguration);
299
Charles Chan910be6a2017-08-23 14:46:43 -0700300 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
301 routeHandler.processRouteAdded(re);
302
303 assertEquals(2, ROUTING_TABLE.size());
304 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
305 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
306 assertEquals(M3, rtv1.macAddress);
307 assertEquals(M3, rtv2.macAddress);
308 assertEquals(V3, rtv1.vlanId);
309 assertEquals(V3, rtv2.vlanId);
310 assertEquals(CP1.port(), rtv1.portNumber);
311 assertEquals(CP2.port(), rtv2.portNumber);
312
313 assertEquals(2, SUBNET_TABLE.size());
314 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
315 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800316
317 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700318 }
319
320 @Test
321 public void testOneSingleHomedToTwoSingleHomed() throws Exception {
322 processRouteAdded();
323
Charles Chan06f626c2018-02-05 17:20:05 -0800324 reset(srManager.deviceConfiguration);
325 srManager.deviceConfiguration.addSubnet(CP2, P1);
326 expectLastCall().once();
327 replay(srManager.deviceConfiguration);
328
Charles Chan910be6a2017-08-23 14:46:43 -0700329 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
330 Sets.newHashSet(RR1, RR2), Sets.newHashSet(RR1));
331 routeHandler.processAlternativeRoutesChanged(re);
332
333 assertEquals(2, ROUTING_TABLE.size());
334 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
335 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
336 assertEquals(M1, rtv1.macAddress);
337 assertEquals(M2, rtv2.macAddress);
338 assertEquals(V1, rtv1.vlanId);
339 assertEquals(V2, rtv2.vlanId);
340 assertEquals(CP1.port(), rtv1.portNumber);
341 assertEquals(CP2.port(), rtv2.portNumber);
342
343 assertEquals(2, SUBNET_TABLE.size());
344 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
345 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800346
347 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700348 }
349
350 @Test
351 public void testTwoSingleHomedToOneSingleHomed() throws Exception {
352 testTwoSingleHomedAdded();
353
Charles Chan06f626c2018-02-05 17:20:05 -0800354 reset(srManager.deviceConfiguration);
355 srManager.deviceConfiguration.removeSubnet(CP2, P1);
356 expectLastCall().once();
357 replay(srManager.deviceConfiguration);
358
Charles Chan910be6a2017-08-23 14:46:43 -0700359 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
360 Sets.newHashSet(RR1), Sets.newHashSet(RR1, RR2));
361 routeHandler.processAlternativeRoutesChanged(re);
362
Charles Chan06f626c2018-02-05 17:20:05 -0800363 // Note: We shouldn't remove the old nexthop during the occasion of route update
364 // since the populate subnet will take care of it and point it to an ECMP group
365 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700366 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
367 assertEquals(M1, rtv1.macAddress);
368 assertEquals(V1, rtv1.vlanId);
369 assertEquals(CP1.port(), rtv1.portNumber);
370
371 assertEquals(1, SUBNET_TABLE.size());
372 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800373
374 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700375 }
376
Charles Chan06f626c2018-02-05 17:20:05 -0800377 // TODO Add test cases for two single homed next hop at same location
378
Charles Chan910be6a2017-08-23 14:46:43 -0700379 @Test
380 public void testDualHomedSingleLocationFail() throws Exception {
381 testOneDualHomedAdded();
382
383 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
384 routeHandler.processHostMovedEvent(he);
385
386 assertEquals(2, ROUTING_TABLE.size());
387 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
388 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
389 assertEquals(M3, rtv1.macAddress);
390 assertEquals(M3, rtv2.macAddress);
391 assertEquals(V3, rtv1.vlanId);
392 assertEquals(V3, rtv2.vlanId);
393 assertEquals(CP1.port(), rtv1.portNumber);
394 assertEquals(P9, rtv2.portNumber);
395
396 // ECMP route table hasn't changed
397 assertEquals(2, SUBNET_TABLE.size());
398 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
399 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
400 }
401
402 @Test
403 public void testDualHomedBothLocationFail() throws Exception {
404 testDualHomedSingleLocationFail();
405
406 hostService = new MockHostService(HOSTS_ONE_FAIL);
407
Charles Chan06f626c2018-02-05 17:20:05 -0800408 reset(srManager.deviceConfiguration);
409 srManager.deviceConfiguration.removeSubnet(CP1, P1);
410 expectLastCall().once();
411 srManager.deviceConfiguration.removeSubnet(CP2, P1);
412 expectLastCall().once();
413 replay(srManager.deviceConfiguration);
414
Charles Chan910be6a2017-08-23 14:46:43 -0700415 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
416 routeHandler.processRouteRemoved(re);
417
418 assertEquals(0, ROUTING_TABLE.size());
419 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800420
421 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700422 }
423
424 @Test
425 public void testTwoSingleHomedRemoved() throws Exception {
426 testTwoSingleHomedAdded();
427
428 hostService = new MockHostService(HOSTS_BOTH_FAIL);
429
Charles Chan06f626c2018-02-05 17:20:05 -0800430 reset(srManager.deviceConfiguration);
431 srManager.deviceConfiguration.removeSubnet(CP1, P1);
432 expectLastCall().once();
433 srManager.deviceConfiguration.removeSubnet(CP2, P1);
434 expectLastCall().once();
435 replay(srManager.deviceConfiguration);
436
Charles Chan910be6a2017-08-23 14:46:43 -0700437 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1, RR2));
438 routeHandler.processRouteRemoved(re);
439
440 assertEquals(0, ROUTING_TABLE.size());
441 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800442
443 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700444 }
445
446 @Test
447 public void testOneDualHomeRemoved() throws Exception {
448 testOneDualHomedAdded();
449
Charles Chan06f626c2018-02-05 17:20:05 -0800450 reset(srManager.deviceConfiguration);
451 srManager.deviceConfiguration.removeSubnet(CP1, P1);
452 expectLastCall().once();
453 srManager.deviceConfiguration.removeSubnet(CP2, P1);
454 expectLastCall().once();
455 replay(srManager.deviceConfiguration);
456
Charles Chan910be6a2017-08-23 14:46:43 -0700457 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
Charles Chan6c624992017-08-18 17:11:34 -0700458 routeHandler.processRouteRemoved(re);
459
460 assertEquals(0, ROUTING_TABLE.size());
461 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800462
463 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700464 }
Charles Chan6c624992017-08-18 17:11:34 -0700465}