blob: e09aaa796b7e15853b2e6dc97475ae98101e6da4 [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 Chan5eec3b12019-04-18 14:30:41 -070021import com.google.common.collect.Lists;
Charles Chan6c624992017-08-18 17:11:34 -070022import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
24import org.junit.Before;
25import org.junit.Test;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.IpPrefix;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
Charles Chan910be6a2017-08-23 14:46:43 -070030import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chan6c624992017-08-18 17:11:34 -070031import org.onosproject.net.ConnectPoint;
Charles Chanf0ae41e2017-08-23 13:55:39 -070032import org.onosproject.net.DefaultHost;
Charles Chan6c624992017-08-18 17:11:34 -070033import org.onosproject.net.DeviceId;
34import org.onosproject.net.Host;
Charles Chanf0ae41e2017-08-23 13:55:39 -070035import org.onosproject.net.HostId;
36import org.onosproject.net.HostLocation;
Charles Chan910be6a2017-08-23 14:46:43 -070037import org.onosproject.net.PortNumber;
Charles Chan6c624992017-08-18 17:11:34 -070038import org.onosproject.net.config.NetworkConfigRegistryAdapter;
39import org.onosproject.net.flow.TrafficTreatment;
Charles Chan910be6a2017-08-23 14:46:43 -070040import org.onosproject.net.host.HostEvent;
41import org.onosproject.net.host.HostService;
Charles Chan12a8a842020-02-14 13:23:57 -080042import org.onosproject.net.host.InterfaceIpAddress;
Charles Chan6c624992017-08-18 17:11:34 -070043import org.onosproject.net.intf.Interface;
Charles Chanf0ae41e2017-08-23 13:55:39 -070044import org.onosproject.net.provider.ProviderId;
Charles Chan6c624992017-08-18 17:11:34 -070045import org.onosproject.routeservice.ResolvedRoute;
46import org.onosproject.routeservice.Route;
47import org.onosproject.routeservice.RouteEvent;
Charles Chan910be6a2017-08-23 14:46:43 -070048import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chan12a8a842020-02-14 13:23:57 -080049import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
Charles Chand66d6712018-03-29 16:03:41 -070050import org.onosproject.store.service.StorageService;
51import org.onosproject.store.service.TestConsistentMap;
pierf331a492020-01-07 15:39:39 +010052import org.onosproject.store.service.TestConsistentMultimap;
Charles Chan6c624992017-08-18 17:11:34 -070053
Charles Chanfab61472021-06-14 23:31:23 -070054import java.util.List;
Charles Chan6c624992017-08-18 17:11:34 -070055import java.util.Map;
56import java.util.Set;
57
Charles Chand66d6712018-03-29 16:03:41 -070058import static org.easymock.EasyMock.expect;
Charles Chan06f626c2018-02-05 17:20:05 -080059import static org.easymock.EasyMock.reset;
Charles Chan6c624992017-08-18 17:11:34 -070060import static org.junit.Assert.*;
Charles Chan06f626c2018-02-05 17:20:05 -080061import static org.easymock.EasyMock.createMock;
62import static org.easymock.EasyMock.expectLastCall;
63import static org.easymock.EasyMock.replay;
64import static org.easymock.EasyMock.verify;
Charles Chan6c624992017-08-18 17:11:34 -070065
66/**
67 * Unit test for {@link RouteHandler}.
68 */
69public class RouteHandlerTest {
Charles Chanfab61472021-06-14 23:31:23 -070070 private MockSegmentRoutingManager srManager;
Charles Chan6c624992017-08-18 17:11:34 -070071 private RouteHandler routeHandler;
Charles Chan910be6a2017-08-23 14:46:43 -070072 private HostService hostService;
Charles Chan6c624992017-08-18 17:11:34 -070073
74 // Mocked routing and bridging tables
75 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
76 Maps.newConcurrentMap();
77 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
78 Maps.newConcurrentMap();
79 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
80 // Mocked Next Id
81 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan7d20a4e2018-04-13 14:01:49 -040082 private static final Map<IpPrefix, Set<ResolvedRoute>> ROUTE_STORE = Maps.newConcurrentMap();
Charles Chan6c624992017-08-18 17:11:34 -070083
84 private static final IpPrefix P1 = IpPrefix.valueOf("10.0.0.0/24");
Charles Chan910be6a2017-08-23 14:46:43 -070085
86 // Single homed router 1
Charles Chan12a8a842020-02-14 13:23:57 -080087 private static final IpAddress N1 = IpAddress.valueOf("10.0.1.1");
Charles Chan6c624992017-08-18 17:11:34 -070088 private static final MacAddress M1 = MacAddress.valueOf("00:00:00:00:00:01");
89 private static final VlanId V1 = VlanId.vlanId((short) 1);
90 private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
91 private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
Charles Chanf0ae41e2017-08-23 13:55:39 -070092 private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1);
Charles Chan12a8a842020-02-14 13:23:57 -080093 private static final Route DHCP_R1 = new Route(Route.Source.DHCP, P1, N1);
94 private static final ResolvedRoute DHCP_RR1 = new ResolvedRoute(DHCP_R1, M1, V1);
Charles Chan6c624992017-08-18 17:11:34 -070095
Charles Chan910be6a2017-08-23 14:46:43 -070096 // Single homed router 2
Charles Chan12a8a842020-02-14 13:23:57 -080097 private static final IpAddress N2 = IpAddress.valueOf("10.0.2.1");
Charles Chan6c624992017-08-18 17:11:34 -070098 private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
99 private static final VlanId V2 = VlanId.vlanId((short) 2);
Charles Chan910be6a2017-08-23 14:46:43 -0700100 private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/2");
Charles Chan6c624992017-08-18 17:11:34 -0700101 private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
Charles Chanf0ae41e2017-08-23 13:55:39 -0700102 private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2);
Charles Chan6c624992017-08-18 17:11:34 -0700103
Charles Chan910be6a2017-08-23 14:46:43 -0700104 // Dual homed router 1
Charles Chan12a8a842020-02-14 13:23:57 -0800105 private static final IpAddress N3 = IpAddress.valueOf("10.0.3.1");
Charles Chan910be6a2017-08-23 14:46:43 -0700106 private static final MacAddress M3 = MacAddress.valueOf("00:00:00:00:00:03");
107 private static final VlanId V3 = VlanId.vlanId((short) 3);
108 private static final Route R3 = new Route(Route.Source.STATIC, P1, N3);
109 private static final ResolvedRoute RR3 = new ResolvedRoute(R3, M3, V3);
Charles Chan12a8a842020-02-14 13:23:57 -0800110 private static final Route DHCP_R3 = new Route(Route.Source.DHCP, P1, N3);
111 private static final ResolvedRoute DHCP_RR3 = new ResolvedRoute(DHCP_R3, M3, V3);
Charles Chan6c624992017-08-18 17:11:34 -0700112
Charles Chan482b6422018-04-09 11:52:08 -0400113 // Single homed router 3
Charles Chan12a8a842020-02-14 13:23:57 -0800114 private static final IpAddress N4 = IpAddress.valueOf("10.0.4.1");
Charles Chan482b6422018-04-09 11:52:08 -0400115 private static final MacAddress M4 = MacAddress.valueOf("00:00:00:00:00:04");
116 private static final VlanId V4 = VlanId.vlanId((short) 4);
117 private static final ConnectPoint CP4 = ConnectPoint.deviceConnectPoint("of:0000000000000004/4");
118 private static final Route R4 = new Route(Route.Source.STATIC, P1, N4);
119 private static final ResolvedRoute RR4 = new ResolvedRoute(R4, M4, V4);
120
Charles Chan910be6a2017-08-23 14:46:43 -0700121 // Hosts
Charles Chanf0ae41e2017-08-23 13:55:39 -0700122 private static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(M1, V1), M1, V1,
123 Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N1), false);
124 private static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(M2, V2), M2, V2,
125 Sets.newHashSet(new HostLocation(CP2, 0)), Sets.newHashSet(N2), false);
Charles Chan910be6a2017-08-23 14:46:43 -0700126 private static final Host H3D = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
127 Sets.newHashSet(new HostLocation(CP1, 0), new HostLocation(CP2, 0)), Sets.newHashSet(N3), false);
128 private static final Host H3S = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
129 Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N3), false);
Charles Chan482b6422018-04-09 11:52:08 -0400130 private static final Host H4 = new DefaultHost(ProviderId.NONE, HostId.hostId(M4, V4), M4, V4,
131 Sets.newHashSet(new HostLocation(CP4, 0)), Sets.newHashSet(N4), false);
Charles Chan910be6a2017-08-23 14:46:43 -0700132
133 // Pair Local Port
134 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf0ae41e2017-08-23 13:55:39 -0700135
Charles Chan6c624992017-08-18 17:11:34 -0700136 // A set of hosts
Charles Chan482b6422018-04-09 11:52:08 -0400137 private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2, H3D, H4);
Charles Chan910be6a2017-08-23 14:46:43 -0700138 private static final Set<Host> HOSTS_ONE_FAIL = Sets.newHashSet(H1, H2, H3S);
139 private static final Set<Host> HOSTS_BOTH_FAIL = Sets.newHashSet(H1, H2);
Charles Chan6c624992017-08-18 17:11:34 -0700140 // A set of devices of which we have mastership
Charles Chan910be6a2017-08-23 14:46:43 -0700141 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
Charles Chan6c624992017-08-18 17:11:34 -0700142 // A set of interfaces
Charles Chan12a8a842020-02-14 13:23:57 -0800143 private static final InterfaceIpAddress IF_IP1 =
144 new InterfaceIpAddress(IpAddress.valueOf("10.0.1.254"), IpPrefix.valueOf("10.0.1.254/24"));
145 private static final InterfaceIpAddress IF_IP3 =
146 new InterfaceIpAddress(IpAddress.valueOf("10.0.3.254"), IpPrefix.valueOf("10.0.3.254/24"));
147 private static final Interface IF_CP1 = new Interface("if-cp1", CP1, Lists.newArrayList(IF_IP1, IF_IP3),
148 null, null, null, null, null);
149 private static final Interface IF_CP2 = new Interface("if-cp2", CP2, Lists.newArrayList(IF_IP1, IF_IP3),
150 null, null, null, null, null);
151 private static final Set<Interface> INTERFACES = Sets.newHashSet(IF_CP1, IF_CP2);
Charles Chan6c624992017-08-18 17:11:34 -0700152
Charles Chanfab61472021-06-14 23:31:23 -0700153 // Route MAC
154 private static final MacAddress ROUTER_MAC_1 = MacAddress.valueOf("00:AA:00:00:00:01");
155 private static final MacAddress ROUTER_MAC_2 = MacAddress.valueOf("00:AA:00:00:00:01");
156 private static final Map<DeviceId, MacAddress> ROUTER_MACS = Map.of(
157 CP1.deviceId(), ROUTER_MAC_1,
158 CP2.deviceId(), ROUTER_MAC_2
159 );
160
Charles Chan6c624992017-08-18 17:11:34 -0700161 @Before
Charles Chan482b6422018-04-09 11:52:08 -0400162 public void setUp() {
Charles Chan910be6a2017-08-23 14:46:43 -0700163 ObjectMapper mapper = new ObjectMapper();
164 ConfigApplyDelegate delegate = config -> { };
165
166 SegmentRoutingDeviceConfig dev1Config = new SegmentRoutingDeviceConfig();
167 JsonNode dev1Tree = mapper.createObjectNode();
168 dev1Config.init(CP1.deviceId(), "host-handler-test", dev1Tree, mapper, delegate);
169 dev1Config.setPairDeviceId(CP2.deviceId()).setPairLocalPort(P9);
170
171 SegmentRoutingDeviceConfig dev2Config = new SegmentRoutingDeviceConfig();
172 JsonNode dev2Tree = mapper.createObjectNode();
173 dev2Config.init(CP2.deviceId(), "host-handler-test", dev2Tree, mapper, delegate);
174 dev2Config.setPairDeviceId(CP1.deviceId()).setPairLocalPort(P9);
Charles Chan6c624992017-08-18 17:11:34 -0700175
176 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
Charles Chan910be6a2017-08-23 14:46:43 -0700177 mockNetworkConfigRegistry.applyConfig(dev1Config);
178 mockNetworkConfigRegistry.applyConfig(dev2Config);
Charles Chan6c624992017-08-18 17:11:34 -0700179
180 // Initialize Segment Routing Manager
Charles Chanfab61472021-06-14 23:31:23 -0700181 srManager = new MockSegmentRoutingManager(NEXT_TABLE, ROUTER_MACS);
Charles Chand66d6712018-03-29 16:03:41 -0700182 srManager.storageService = createMock(StorageService.class);
183 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
pierf331a492020-01-07 15:39:39 +0100184 expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
185 new TestConsistentMultimap.Builder<>()).anyTimes();
Charles Chand66d6712018-03-29 16:03:41 -0700186 replay(srManager.storageService);
Charles Chan6c624992017-08-18 17:11:34 -0700187 srManager.cfgService = new NetworkConfigRegistryAdapter();
Charles Chan06f626c2018-02-05 17:20:05 -0800188 srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
Charles Chan6c624992017-08-18 17:11:34 -0700189 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
190 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanc4d68882018-03-15 16:41:10 -0700191 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700192 srManager.interfaceService = new MockInterfaceService(INTERFACES);
193 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
Charles Chan910be6a2017-08-23 14:46:43 -0700194 hostService = new MockHostService(HOSTS);
195 srManager.hostService = hostService;
Charles Chan6c624992017-08-18 17:11:34 -0700196 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chan7d20a4e2018-04-13 14:01:49 -0400197 srManager.routeService = new MockRouteService(ROUTE_STORE);
Charles Chan12a8a842020-02-14 13:23:57 -0800198 srManager.phasedRecoveryService = createMock(PhasedRecoveryService.class);
199 expect(srManager.phasedRecoveryService.isEnabled()).andReturn(true).anyTimes();
200 replay(srManager.phasedRecoveryService);
Charles Chan6c624992017-08-18 17:11:34 -0700201
Charles Chanfbcb8812018-04-18 18:41:05 -0700202 routeHandler = new RouteHandler(srManager);
Charles Chan6c624992017-08-18 17:11:34 -0700203
204 ROUTING_TABLE.clear();
205 BRIDGING_TABLE.clear();
206 SUBNET_TABLE.clear();
207 }
208
209 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400210 public void init() {
Charles Chan7d20a4e2018-04-13 14:01:49 -0400211 ROUTE_STORE.put(P1, Sets.newHashSet(RR1));
Charles Chan910be6a2017-08-23 14:46:43 -0700212
Charles Chan6c624992017-08-18 17:11:34 -0700213 routeHandler.init(CP1.deviceId());
214
215 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700216 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
217 assertEquals(M1, rtv1.macAddress);
218 assertEquals(V1, rtv1.vlanId);
219 assertEquals(CP1.port(), rtv1.portNumber);
220
Charles Chan6c624992017-08-18 17:11:34 -0700221 assertEquals(1, SUBNET_TABLE.size());
Charles Chan6c624992017-08-18 17:11:34 -0700222 }
223
224 @Test
Charles Chan7d20a4e2018-04-13 14:01:49 -0400225 public void initTwoNextHops() {
226 ROUTE_STORE.put(P1, Sets.newHashSet(RR1, RR2));
227
228 routeHandler.init(CP1.deviceId());
229
230 assertEquals(2, ROUTING_TABLE.size());
231 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
232 assertEquals(M1, rtv1.macAddress);
233 assertEquals(V1, rtv1.vlanId);
234 assertEquals(CP1.port(), rtv1.portNumber);
235 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
236 assertEquals(M2, rtv2.macAddress);
237 assertEquals(V2, rtv2.vlanId);
238 assertEquals(CP2.port(), rtv2.portNumber);
239
240 assertEquals(2, SUBNET_TABLE.size());
Charles Chan12a8a842020-02-14 13:23:57 -0800241 }
242
243 // Only one of two dual-homed next hops present.
244 // Expect one routing table to be programmed with direct flow.
245 // The other is not programmed, not even for subnet
246 @Test
247 public void initDhcpRouteSingleDualHomeNextHop() {
248 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
249
250 routeHandler.init(CP1.deviceId());
251
252 assertEquals(1, ROUTING_TABLE.size());
253 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
254 assertEquals(M1, rtv1.macAddress);
255 assertEquals(V1, rtv1.vlanId);
256 assertEquals(CP1.port(), rtv1.portNumber);
257
258 assertEquals(1, SUBNET_TABLE.size());
259 }
260
Charles Chanfab61472021-06-14 23:31:23 -0700261 // Only one of two dual-homed next hops present.
262 // Expect one routing table to be programmed with direct flow.
263 // The other is pointing to pair port
264 @Test
265 public void initDhcpRouteSingleDualHomeNextHopSingleLeafPair() {
266 srManager.setInfraDeviceIds(List.of());
267
268 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
269
270 routeHandler.init(CP1.deviceId());
271
272 assertEquals(2, ROUTING_TABLE.size());
273 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
274 assertEquals(M1, rtv1.macAddress);
275 assertEquals(V1, rtv1.vlanId);
276 assertEquals(CP1.port(), rtv1.portNumber);
277
278 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
279 assertEquals(ROUTER_MAC_1, rtv2.macAddress);
280 assertEquals(V1, rtv2.vlanId);
281 assertEquals(P9, rtv2.portNumber);
282
283 assertEquals(1, SUBNET_TABLE.size());
284 }
285
Charles Chan12a8a842020-02-14 13:23:57 -0800286 // Both dual-homed next hops present.
287 // Expect both routing table to be programmed with direct flow
288 @Test
289 public void initDhcpRouteBothDualHomeNextHop() {
290 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
291
292 routeHandler.init(CP1.deviceId());
293
294 assertEquals(2, ROUTING_TABLE.size());
295 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
296 assertEquals(M3, rtv1.macAddress);
297 assertEquals(V3, rtv1.vlanId);
298 assertEquals(CP1.port(), rtv1.portNumber);
299
300 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
301 assertEquals(M3, rtv2.macAddress);
302 assertEquals(V3, rtv2.vlanId);
303 assertEquals(CP2.port(), rtv2.portNumber);
304
305 assertEquals(2, SUBNET_TABLE.size());
Charles Chan7d20a4e2018-04-13 14:01:49 -0400306 }
307
308 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700309 public void initDhcpRouteBothDualHomeNextHopSingleLeafPair() {
310 srManager.setInfraDeviceIds(List.of());
311
312 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
313
314 routeHandler.init(CP1.deviceId());
315
316 assertEquals(2, ROUTING_TABLE.size());
317 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
318 assertEquals(M3, rtv1.macAddress);
319 assertEquals(V3, rtv1.vlanId);
320 assertEquals(CP1.port(), rtv1.portNumber);
321
322 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
323 assertEquals(M3, rtv2.macAddress);
324 assertEquals(V3, rtv2.vlanId);
325 assertEquals(CP2.port(), rtv2.portNumber);
326
327 assertEquals(2, SUBNET_TABLE.size());
328 }
329
330
331 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400332 public void processRouteAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800333 reset(srManager.deviceConfiguration);
334 srManager.deviceConfiguration.addSubnet(CP1, P1);
335 expectLastCall().once();
336 replay(srManager.deviceConfiguration);
337
Charles Chan910be6a2017-08-23 14:46:43 -0700338 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700339 routeHandler.processRouteAdded(re);
340
341 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700342 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
343 assertEquals(M1, rtv1.macAddress);
344 assertEquals(V1, rtv1.vlanId);
345 assertEquals(CP1.port(), rtv1.portNumber);
346
Charles Chan6c624992017-08-18 17:11:34 -0700347 assertEquals(1, SUBNET_TABLE.size());
348 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800349
350 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700351 }
352
353 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400354 public void processRouteUpdated() {
Charles Chan6c624992017-08-18 17:11:34 -0700355 processRouteAdded();
356
Charles Chan06f626c2018-02-05 17:20:05 -0800357 reset(srManager.deviceConfiguration);
358 srManager.deviceConfiguration.removeSubnet(CP1, P1);
359 expectLastCall().once();
360 srManager.deviceConfiguration.addSubnet(CP2, P1);
361 expectLastCall().once();
362 replay(srManager.deviceConfiguration);
363
Charles Chan910be6a2017-08-23 14:46:43 -0700364 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1, Sets.newHashSet(RR2),
365 Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700366 routeHandler.processRouteUpdated(re);
367
Charles Chan06f626c2018-02-05 17:20:05 -0800368 // Note: We shouldn't remove the old nexthop during the occasion of route update
369 // since the populate subnet will take care of it and point it to an ECMP group
370 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700371 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
Charles Chanf0ae41e2017-08-23 13:55:39 -0700372 assertEquals(M2, rtv2.macAddress);
373 assertEquals(V2, rtv2.vlanId);
374 assertEquals(CP2.port(), rtv2.portNumber);
375
Charles Chan6c624992017-08-18 17:11:34 -0700376 assertEquals(1, SUBNET_TABLE.size());
377 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800378
379 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700380 }
381
382 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400383 public void processRouteRemoved() {
Charles Chan6c624992017-08-18 17:11:34 -0700384 processRouteAdded();
385
Charles Chan06f626c2018-02-05 17:20:05 -0800386 reset(srManager.deviceConfiguration);
387 srManager.deviceConfiguration.removeSubnet(CP1, P1);
388 expectLastCall().once();
389 replay(srManager.deviceConfiguration);
390
Charles Chan910be6a2017-08-23 14:46:43 -0700391 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1));
392 routeHandler.processRouteRemoved(re);
393
394 assertEquals(0, ROUTING_TABLE.size());
395 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800396
397 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700398 }
399
400 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400401 public void testTwoSingleHomedAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800402 reset(srManager.deviceConfiguration);
403 srManager.deviceConfiguration.addSubnet(CP1, P1);
404 expectLastCall().once();
405 srManager.deviceConfiguration.addSubnet(CP2, P1);
406 expectLastCall().once();
407 replay(srManager.deviceConfiguration);
408
Charles Chan910be6a2017-08-23 14:46:43 -0700409 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
410 routeHandler.processRouteAdded(re);
411
412 assertEquals(2, ROUTING_TABLE.size());
413 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
414 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
415 assertEquals(M1, rtv1.macAddress);
416 assertEquals(M2, rtv2.macAddress);
417 assertEquals(V1, rtv1.vlanId);
418 assertEquals(V2, rtv2.vlanId);
419 assertEquals(CP1.port(), rtv1.portNumber);
420 assertEquals(CP2.port(), rtv2.portNumber);
421
422 assertEquals(2, SUBNET_TABLE.size());
423 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
424 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800425
426 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700427 }
428
429 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400430 public void testOneDualHomedAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800431 reset(srManager.deviceConfiguration);
432 srManager.deviceConfiguration.addSubnet(CP1, P1);
433 expectLastCall().once();
434 srManager.deviceConfiguration.addSubnet(CP2, P1);
435 expectLastCall().once();
436 replay(srManager.deviceConfiguration);
437
Charles Chan910be6a2017-08-23 14:46:43 -0700438 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
439 routeHandler.processRouteAdded(re);
440
441 assertEquals(2, ROUTING_TABLE.size());
442 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
443 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
444 assertEquals(M3, rtv1.macAddress);
445 assertEquals(M3, rtv2.macAddress);
446 assertEquals(V3, rtv1.vlanId);
447 assertEquals(V3, rtv2.vlanId);
448 assertEquals(CP1.port(), rtv1.portNumber);
449 assertEquals(CP2.port(), rtv2.portNumber);
450
451 assertEquals(2, SUBNET_TABLE.size());
452 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
453 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800454
455 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700456 }
457
458 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700459 public void testOneDualHomedAddedSingleLeafPair() {
460 srManager.setInfraDeviceIds(List.of());
461
462 reset(srManager.deviceConfiguration);
463 srManager.deviceConfiguration.addSubnet(CP1, P1);
464 expectLastCall().once();
465 srManager.deviceConfiguration.addSubnet(CP2, P1);
466 expectLastCall().once();
467 replay(srManager.deviceConfiguration);
468
469 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
470 routeHandler.processRouteAdded(re);
471
472 assertEquals(2, ROUTING_TABLE.size());
473 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
474 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
475 assertEquals(M3, rtv1.macAddress);
476 assertEquals(M3, rtv2.macAddress);
477 assertEquals(V3, rtv1.vlanId);
478 assertEquals(V3, rtv2.vlanId);
479 assertEquals(CP1.port(), rtv1.portNumber);
480 assertEquals(CP2.port(), rtv2.portNumber);
481
482 assertEquals(2, SUBNET_TABLE.size());
483 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
484 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
485
486 verify(srManager.deviceConfiguration);
487 }
488
489 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400490 public void testOneSingleHomedToTwoSingleHomed() {
Charles Chan910be6a2017-08-23 14:46:43 -0700491 processRouteAdded();
492
Charles Chan06f626c2018-02-05 17:20:05 -0800493 reset(srManager.deviceConfiguration);
494 srManager.deviceConfiguration.addSubnet(CP2, P1);
495 expectLastCall().once();
496 replay(srManager.deviceConfiguration);
497
Charles Chan910be6a2017-08-23 14:46:43 -0700498 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
499 Sets.newHashSet(RR1, RR2), Sets.newHashSet(RR1));
500 routeHandler.processAlternativeRoutesChanged(re);
501
502 assertEquals(2, ROUTING_TABLE.size());
503 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
504 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
505 assertEquals(M1, rtv1.macAddress);
506 assertEquals(M2, rtv2.macAddress);
507 assertEquals(V1, rtv1.vlanId);
508 assertEquals(V2, rtv2.vlanId);
509 assertEquals(CP1.port(), rtv1.portNumber);
510 assertEquals(CP2.port(), rtv2.portNumber);
511
512 assertEquals(2, SUBNET_TABLE.size());
513 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
514 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800515
516 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700517 }
518
519 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400520 public void testTwoSingleHomedToOneSingleHomed() {
Charles Chan910be6a2017-08-23 14:46:43 -0700521 testTwoSingleHomedAdded();
522
Charles Chan06f626c2018-02-05 17:20:05 -0800523 reset(srManager.deviceConfiguration);
524 srManager.deviceConfiguration.removeSubnet(CP2, P1);
525 expectLastCall().once();
526 replay(srManager.deviceConfiguration);
527
Charles Chan910be6a2017-08-23 14:46:43 -0700528 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
529 Sets.newHashSet(RR1), Sets.newHashSet(RR1, RR2));
530 routeHandler.processAlternativeRoutesChanged(re);
531
Charles Chan06f626c2018-02-05 17:20:05 -0800532 // Note: We shouldn't remove the old nexthop during the occasion of route update
533 // since the populate subnet will take care of it and point it to an ECMP group
534 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700535 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
536 assertEquals(M1, rtv1.macAddress);
537 assertEquals(V1, rtv1.vlanId);
538 assertEquals(CP1.port(), rtv1.portNumber);
539
540 assertEquals(1, SUBNET_TABLE.size());
541 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800542
543 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700544 }
545
Charles Chan06f626c2018-02-05 17:20:05 -0800546 // TODO Add test cases for two single homed next hop at same location
547
Charles Chan910be6a2017-08-23 14:46:43 -0700548 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400549 public void testDualHomedSingleLocationFail() {
Charles Chan910be6a2017-08-23 14:46:43 -0700550 testOneDualHomedAdded();
551
Charles Chan7d20a4e2018-04-13 14:01:49 -0400552 ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
553
Charles Chan07203792018-07-17 16:33:11 -0700554 reset(srManager.deviceConfiguration);
Charles Chan5eec3b12019-04-18 14:30:41 -0700555 expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
556 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
Charles Chan07203792018-07-17 16:33:11 -0700557 srManager.deviceConfiguration.removeSubnet(CP2, P1);
558 expectLastCall().once();
559 replay(srManager.deviceConfiguration);
560
Charles Chan910be6a2017-08-23 14:46:43 -0700561 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
562 routeHandler.processHostMovedEvent(he);
563
Charles Chan4dcd5102019-02-28 15:40:57 -0800564 // We do not remove the route on CP2. Instead, we let the subnet population overrides it
565 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700566 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
Charles Chan910be6a2017-08-23 14:46:43 -0700567 assertEquals(M3, rtv1.macAddress);
Charles Chan910be6a2017-08-23 14:46:43 -0700568 assertEquals(V3, rtv1.vlanId);
Charles Chan910be6a2017-08-23 14:46:43 -0700569 assertEquals(CP1.port(), rtv1.portNumber);
Charles Chan910be6a2017-08-23 14:46:43 -0700570
Charles Chanfab61472021-06-14 23:31:23 -0700571 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
572 assertEquals(M3, rtv2.macAddress);
573 assertEquals(V3, rtv2.vlanId);
574 assertEquals(CP2.port(), rtv2.portNumber);
575
576 // ECMP route table hasn't changed
577 assertEquals(1, SUBNET_TABLE.size());
578 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
579
580 verify(srManager.deviceConfiguration);
581 }
582
583 @Test
584 public void testDualHomedSingleLocationFailSingleLeafPair() {
585 srManager.setInfraDeviceIds(List.of());
586
587 testOneDualHomedAddedSingleLeafPair();
588
589 ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
590
591 reset(srManager.deviceConfiguration);
592 expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
593 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
594 srManager.deviceConfiguration.removeSubnet(CP2, P1);
595 expectLastCall().once();
596 replay(srManager.deviceConfiguration);
597
598 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
599 routeHandler.processHostMovedEvent(he);
600
601 // We do not remove the route on CP2. Instead, we let the subnet population overrides it
602 assertEquals(2, ROUTING_TABLE.size());
603 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
604 assertEquals(M3, rtv1.macAddress);
605 assertEquals(V3, rtv1.vlanId);
606 assertEquals(CP1.port(), rtv1.portNumber);
607
608 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
609 assertEquals(ROUTER_MAC_1, rtv2.macAddress);
610 assertEquals(V3, rtv2.vlanId);
611 assertEquals(P9, rtv2.portNumber);
612
Charles Chan910be6a2017-08-23 14:46:43 -0700613 // ECMP route table hasn't changed
Charles Chan07203792018-07-17 16:33:11 -0700614 assertEquals(1, SUBNET_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700615 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan07203792018-07-17 16:33:11 -0700616
617 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700618 }
619
620 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400621 public void testDualHomedBothLocationFail() {
Charles Chan910be6a2017-08-23 14:46:43 -0700622 testDualHomedSingleLocationFail();
623
624 hostService = new MockHostService(HOSTS_ONE_FAIL);
625
Charles Chan06f626c2018-02-05 17:20:05 -0800626 reset(srManager.deviceConfiguration);
627 srManager.deviceConfiguration.removeSubnet(CP1, P1);
628 expectLastCall().once();
629 srManager.deviceConfiguration.removeSubnet(CP2, P1);
630 expectLastCall().once();
631 replay(srManager.deviceConfiguration);
632
Charles Chan910be6a2017-08-23 14:46:43 -0700633 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
634 routeHandler.processRouteRemoved(re);
635
636 assertEquals(0, ROUTING_TABLE.size());
637 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800638
639 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700640 }
641
642 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700643 public void testDualHomedBothLocationFaiSingleLeafPair() {
644 srManager.setInfraDeviceIds(List.of());
645
646 testDualHomedSingleLocationFailSingleLeafPair();
647
648 hostService = new MockHostService(HOSTS_ONE_FAIL);
649
650 reset(srManager.deviceConfiguration);
651 srManager.deviceConfiguration.removeSubnet(CP1, P1);
652 expectLastCall().once();
653 srManager.deviceConfiguration.removeSubnet(CP2, P1);
654 expectLastCall().once();
655 replay(srManager.deviceConfiguration);
656
657 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
658 routeHandler.processRouteRemoved(re);
659
660 assertEquals(0, ROUTING_TABLE.size());
661 assertEquals(0, SUBNET_TABLE.size());
662
663 verify(srManager.deviceConfiguration);
664 }
665
666 @Test
Charles Chan07203792018-07-17 16:33:11 -0700667 public void testSingleHomedToDualHomed() {
668 testDualHomedSingleLocationFail();
669
670 reset(srManager.deviceConfiguration);
Charles Chan5eec3b12019-04-18 14:30:41 -0700671 expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
672 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
Charles Chan07203792018-07-17 16:33:11 -0700673 srManager.deviceConfiguration.addSubnet(CP2, P1);
674 expectLastCall().once();
675 replay(srManager.deviceConfiguration);
676
677 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
678 routeHandler.processHostMovedEvent(he);
679
680 assertEquals(2, ROUTING_TABLE.size());
681 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
682 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
683 assertEquals(M3, rtv1.macAddress);
684 assertEquals(M3, rtv2.macAddress);
685 assertEquals(V3, rtv1.vlanId);
686 assertEquals(V3, rtv2.vlanId);
687 assertEquals(CP1.port(), rtv1.portNumber);
688 assertEquals(CP2.port(), rtv2.portNumber);
689
690 assertEquals(2, SUBNET_TABLE.size());
691 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
692 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
693
694 verify(srManager.deviceConfiguration);
695 }
696
697 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700698 public void testSingleHomedToDualHomedSingleLeafPair() {
699 srManager.setInfraDeviceIds(List.of());
700
701 testDualHomedSingleLocationFailSingleLeafPair();
702
703 reset(srManager.deviceConfiguration);
704 expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
705 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
706 srManager.deviceConfiguration.addSubnet(CP2, P1);
707 expectLastCall().once();
708 replay(srManager.deviceConfiguration);
709
710 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
711 routeHandler.processHostMovedEvent(he);
712
713 assertEquals(2, ROUTING_TABLE.size());
714 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
715 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
716 assertEquals(M3, rtv1.macAddress);
717 assertEquals(M3, rtv2.macAddress);
718 assertEquals(V3, rtv1.vlanId);
719 assertEquals(V3, rtv2.vlanId);
720 assertEquals(CP1.port(), rtv1.portNumber);
721 assertEquals(CP2.port(), rtv2.portNumber);
722
723 assertEquals(2, SUBNET_TABLE.size());
724 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
725 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
726
727 verify(srManager.deviceConfiguration);
728 }
729
730 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400731 public void testTwoSingleHomedRemoved() {
Charles Chan910be6a2017-08-23 14:46:43 -0700732 testTwoSingleHomedAdded();
733
734 hostService = new MockHostService(HOSTS_BOTH_FAIL);
735
Charles Chan06f626c2018-02-05 17:20:05 -0800736 reset(srManager.deviceConfiguration);
737 srManager.deviceConfiguration.removeSubnet(CP1, P1);
738 expectLastCall().once();
739 srManager.deviceConfiguration.removeSubnet(CP2, P1);
740 expectLastCall().once();
741 replay(srManager.deviceConfiguration);
742
Charles Chan910be6a2017-08-23 14:46:43 -0700743 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1, RR2));
744 routeHandler.processRouteRemoved(re);
745
746 assertEquals(0, ROUTING_TABLE.size());
747 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800748
749 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700750 }
751
752 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400753 public void testOneDualHomeRemoved() {
Charles Chan910be6a2017-08-23 14:46:43 -0700754 testOneDualHomedAdded();
755
Charles Chan06f626c2018-02-05 17:20:05 -0800756 reset(srManager.deviceConfiguration);
757 srManager.deviceConfiguration.removeSubnet(CP1, P1);
758 expectLastCall().once();
759 srManager.deviceConfiguration.removeSubnet(CP2, P1);
760 expectLastCall().once();
761 replay(srManager.deviceConfiguration);
762
Charles Chan910be6a2017-08-23 14:46:43 -0700763 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
Charles Chan6c624992017-08-18 17:11:34 -0700764 routeHandler.processRouteRemoved(re);
765
766 assertEquals(0, ROUTING_TABLE.size());
767 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800768
769 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700770 }
Charles Chan482b6422018-04-09 11:52:08 -0400771
772 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700773 public void testOneDualHomeRemovedSingleLeafPair() {
774 srManager.setInfraDeviceIds(List.of());
775
776 testOneDualHomedAddedSingleLeafPair();
777
778 reset(srManager.deviceConfiguration);
779 srManager.deviceConfiguration.removeSubnet(CP1, P1);
780 expectLastCall().once();
781 srManager.deviceConfiguration.removeSubnet(CP2, P1);
782 expectLastCall().once();
783 replay(srManager.deviceConfiguration);
784
785 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
786 routeHandler.processRouteRemoved(re);
787
788 assertEquals(0, ROUTING_TABLE.size());
789 assertEquals(0, SUBNET_TABLE.size());
790
791 verify(srManager.deviceConfiguration);
792 }
793
794 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400795 public void testMoreThanTwoNextHop() {
796 // next hop = CP1, CP2
797 reset(srManager.deviceConfiguration);
798 srManager.deviceConfiguration.addSubnet(CP1, P1);
799 srManager.deviceConfiguration.addSubnet(CP2, P1);
800 expectLastCall().once();
801 replay(srManager.deviceConfiguration);
802
803 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
804 routeHandler.processRouteAdded(re);
805
806 assertEquals(2, ROUTING_TABLE.size());
807 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
808 assertEquals(M1, rtv1.macAddress);
809 assertEquals(V1, rtv1.vlanId);
810 assertEquals(CP1.port(), rtv1.portNumber);
811 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
812 assertEquals(M2, rtv2.macAddress);
813 assertEquals(V2, rtv2.vlanId);
814 assertEquals(CP2.port(), rtv2.portNumber);
815
816 assertEquals(2, SUBNET_TABLE.size());
817 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
818 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
819
820 verify(srManager.deviceConfiguration);
821
822 // next hop = CP1, CP2, CP4 (invalid)
823 re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
824 Sets.newHashSet(RR1, RR2, RR4), Sets.newHashSet(RR1, RR2));
825 routeHandler.processAlternativeRoutesChanged(re);
826
827 assertEquals(2, ROUTING_TABLE.size());
828 rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
829 assertEquals(M1, rtv1.macAddress);
830 assertEquals(V1, rtv1.vlanId);
831 assertEquals(CP1.port(), rtv1.portNumber);
832 rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
833 assertEquals(M2, rtv2.macAddress);
834 assertEquals(V2, rtv2.vlanId);
835 assertEquals(CP2.port(), rtv2.portNumber);
836
837 assertEquals(2, SUBNET_TABLE.size());
838 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
839 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
840
841 // next hop = CP2, CP4
842 reset(srManager.deviceConfiguration);
843 srManager.deviceConfiguration.addSubnet(CP2, P1);
844 srManager.deviceConfiguration.addSubnet(CP4, P1);
845 expectLastCall().once();
846 replay(srManager.deviceConfiguration);
847
848 re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
849 Sets.newHashSet(RR2, RR4), Sets.newHashSet(RR1, RR2, RR4));
850 routeHandler.processAlternativeRoutesChanged(re);
851
852 assertEquals(2, ROUTING_TABLE.size());
853 rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
854 assertEquals(M2, rtv1.macAddress);
855 assertEquals(V2, rtv1.vlanId);
856 assertEquals(CP2.port(), rtv1.portNumber);
857 rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1));
858 assertEquals(M4, rtv2.macAddress);
859 assertEquals(V4, rtv2.vlanId);
860 assertEquals(CP4.port(), rtv2.portNumber);
861
862 assertEquals(2, SUBNET_TABLE.size());
863 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
864 assertTrue(SUBNET_TABLE.get(CP4).contains(P1));
865
866 verify(srManager.deviceConfiguration);
867 }
Ruchi Sahota71bcb4e2019-01-28 01:08:18 +0000868}