blob: 2ab4d01c5e3bdf0268d2abb763aa9bef6195093d [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);
pierventre37dcf4c2021-09-16 18:43:06 +0200140 // A set of devices of which we have leadership
141 private static final Set<DeviceId> LED_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);
pierventre37dcf4c2021-09-16 18:43:06 +0200183 expect(srManager.storageService.consistentMapBuilder()).andReturn(
184 new TestConsistentMap.Builder<>()).anyTimes();
pierf331a492020-01-07 15:39:39 +0100185 expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
186 new TestConsistentMultimap.Builder<>()).anyTimes();
Charles Chand66d6712018-03-29 16:03:41 -0700187 replay(srManager.storageService);
Charles Chan6c624992017-08-18 17:11:34 -0700188 srManager.cfgService = new NetworkConfigRegistryAdapter();
Charles Chan06f626c2018-02-05 17:20:05 -0800189 srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
Charles Chan6c624992017-08-18 17:11:34 -0700190 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
191 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
pierventre37dcf4c2021-09-16 18:43:06 +0200192 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE,
193 LED_DEVICES);
Charles Chan6c624992017-08-18 17:11:34 -0700194 srManager.interfaceService = new MockInterfaceService(INTERFACES);
Charles Chan910be6a2017-08-23 14:46:43 -0700195 hostService = new MockHostService(HOSTS);
196 srManager.hostService = hostService;
Charles Chan6c624992017-08-18 17:11:34 -0700197 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chan7d20a4e2018-04-13 14:01:49 -0400198 srManager.routeService = new MockRouteService(ROUTE_STORE);
Charles Chan12a8a842020-02-14 13:23:57 -0800199 srManager.phasedRecoveryService = createMock(PhasedRecoveryService.class);
200 expect(srManager.phasedRecoveryService.isEnabled()).andReturn(true).anyTimes();
201 replay(srManager.phasedRecoveryService);
Charles Chan6c624992017-08-18 17:11:34 -0700202
Charles Chanfbcb8812018-04-18 18:41:05 -0700203 routeHandler = new RouteHandler(srManager);
Charles Chan6c624992017-08-18 17:11:34 -0700204
205 ROUTING_TABLE.clear();
206 BRIDGING_TABLE.clear();
207 SUBNET_TABLE.clear();
208 }
209
210 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400211 public void init() {
Charles Chan7d20a4e2018-04-13 14:01:49 -0400212 ROUTE_STORE.put(P1, Sets.newHashSet(RR1));
Charles Chan910be6a2017-08-23 14:46:43 -0700213
Charles Chan6c624992017-08-18 17:11:34 -0700214 routeHandler.init(CP1.deviceId());
215
216 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700217 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
218 assertEquals(M1, rtv1.macAddress);
219 assertEquals(V1, rtv1.vlanId);
220 assertEquals(CP1.port(), rtv1.portNumber);
221
Charles Chan6c624992017-08-18 17:11:34 -0700222 assertEquals(1, SUBNET_TABLE.size());
Charles Chan6c624992017-08-18 17:11:34 -0700223 }
224
225 @Test
Charles Chan7d20a4e2018-04-13 14:01:49 -0400226 public void initTwoNextHops() {
227 ROUTE_STORE.put(P1, Sets.newHashSet(RR1, RR2));
228
229 routeHandler.init(CP1.deviceId());
230
231 assertEquals(2, ROUTING_TABLE.size());
232 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
233 assertEquals(M1, rtv1.macAddress);
234 assertEquals(V1, rtv1.vlanId);
235 assertEquals(CP1.port(), rtv1.portNumber);
236 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
237 assertEquals(M2, rtv2.macAddress);
238 assertEquals(V2, rtv2.vlanId);
239 assertEquals(CP2.port(), rtv2.portNumber);
240
241 assertEquals(2, SUBNET_TABLE.size());
Charles Chan12a8a842020-02-14 13:23:57 -0800242 }
243
244 // Only one of two dual-homed next hops present.
245 // Expect one routing table to be programmed with direct flow.
246 // The other is not programmed, not even for subnet
247 @Test
248 public void initDhcpRouteSingleDualHomeNextHop() {
249 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
250
251 routeHandler.init(CP1.deviceId());
252
253 assertEquals(1, ROUTING_TABLE.size());
254 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
255 assertEquals(M1, rtv1.macAddress);
256 assertEquals(V1, rtv1.vlanId);
257 assertEquals(CP1.port(), rtv1.portNumber);
258
259 assertEquals(1, SUBNET_TABLE.size());
260 }
261
Charles Chanfab61472021-06-14 23:31:23 -0700262 // Only one of two dual-homed next hops present.
263 // Expect one routing table to be programmed with direct flow.
264 // The other is pointing to pair port
265 @Test
266 public void initDhcpRouteSingleDualHomeNextHopSingleLeafPair() {
267 srManager.setInfraDeviceIds(List.of());
268
269 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
270
271 routeHandler.init(CP1.deviceId());
272
273 assertEquals(2, ROUTING_TABLE.size());
274 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
275 assertEquals(M1, rtv1.macAddress);
276 assertEquals(V1, rtv1.vlanId);
277 assertEquals(CP1.port(), rtv1.portNumber);
278
279 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
280 assertEquals(ROUTER_MAC_1, rtv2.macAddress);
281 assertEquals(V1, rtv2.vlanId);
282 assertEquals(P9, rtv2.portNumber);
283
284 assertEquals(1, SUBNET_TABLE.size());
285 }
286
Charles Chan12a8a842020-02-14 13:23:57 -0800287 // Both dual-homed next hops present.
288 // Expect both routing table to be programmed with direct flow
289 @Test
290 public void initDhcpRouteBothDualHomeNextHop() {
291 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
292
293 routeHandler.init(CP1.deviceId());
294
295 assertEquals(2, ROUTING_TABLE.size());
296 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
297 assertEquals(M3, rtv1.macAddress);
298 assertEquals(V3, rtv1.vlanId);
299 assertEquals(CP1.port(), rtv1.portNumber);
300
301 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
302 assertEquals(M3, rtv2.macAddress);
303 assertEquals(V3, rtv2.vlanId);
304 assertEquals(CP2.port(), rtv2.portNumber);
305
306 assertEquals(2, SUBNET_TABLE.size());
Charles Chan7d20a4e2018-04-13 14:01:49 -0400307 }
308
309 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700310 public void initDhcpRouteBothDualHomeNextHopSingleLeafPair() {
311 srManager.setInfraDeviceIds(List.of());
312
313 ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
314
315 routeHandler.init(CP1.deviceId());
316
317 assertEquals(2, ROUTING_TABLE.size());
318 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
319 assertEquals(M3, rtv1.macAddress);
320 assertEquals(V3, rtv1.vlanId);
321 assertEquals(CP1.port(), rtv1.portNumber);
322
323 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
324 assertEquals(M3, rtv2.macAddress);
325 assertEquals(V3, rtv2.vlanId);
326 assertEquals(CP2.port(), rtv2.portNumber);
327
328 assertEquals(2, SUBNET_TABLE.size());
329 }
330
331
332 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400333 public void processRouteAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800334 reset(srManager.deviceConfiguration);
335 srManager.deviceConfiguration.addSubnet(CP1, P1);
336 expectLastCall().once();
337 replay(srManager.deviceConfiguration);
338
Charles Chan910be6a2017-08-23 14:46:43 -0700339 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700340 routeHandler.processRouteAdded(re);
341
342 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf0ae41e2017-08-23 13:55:39 -0700343 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
344 assertEquals(M1, rtv1.macAddress);
345 assertEquals(V1, rtv1.vlanId);
346 assertEquals(CP1.port(), rtv1.portNumber);
347
Charles Chan6c624992017-08-18 17:11:34 -0700348 assertEquals(1, SUBNET_TABLE.size());
349 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800350
351 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700352 }
353
354 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400355 public void processRouteUpdated() {
Charles Chan6c624992017-08-18 17:11:34 -0700356 processRouteAdded();
357
Charles Chan06f626c2018-02-05 17:20:05 -0800358 reset(srManager.deviceConfiguration);
359 srManager.deviceConfiguration.removeSubnet(CP1, P1);
360 expectLastCall().once();
361 srManager.deviceConfiguration.addSubnet(CP2, P1);
362 expectLastCall().once();
363 replay(srManager.deviceConfiguration);
364
Charles Chan910be6a2017-08-23 14:46:43 -0700365 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1, Sets.newHashSet(RR2),
366 Sets.newHashSet(RR1));
Charles Chan6c624992017-08-18 17:11:34 -0700367 routeHandler.processRouteUpdated(re);
368
Charles Chan06f626c2018-02-05 17:20:05 -0800369 // Note: We shouldn't remove the old nexthop during the occasion of route update
370 // since the populate subnet will take care of it and point it to an ECMP group
371 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700372 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
Charles Chanf0ae41e2017-08-23 13:55:39 -0700373 assertEquals(M2, rtv2.macAddress);
374 assertEquals(V2, rtv2.vlanId);
375 assertEquals(CP2.port(), rtv2.portNumber);
376
Charles Chan6c624992017-08-18 17:11:34 -0700377 assertEquals(1, SUBNET_TABLE.size());
378 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800379
380 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700381 }
382
383 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400384 public void processRouteRemoved() {
Charles Chan6c624992017-08-18 17:11:34 -0700385 processRouteAdded();
386
Charles Chan06f626c2018-02-05 17:20:05 -0800387 reset(srManager.deviceConfiguration);
388 srManager.deviceConfiguration.removeSubnet(CP1, P1);
389 expectLastCall().once();
390 replay(srManager.deviceConfiguration);
391
Charles Chan910be6a2017-08-23 14:46:43 -0700392 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1));
393 routeHandler.processRouteRemoved(re);
394
395 assertEquals(0, ROUTING_TABLE.size());
396 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800397
398 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700399 }
400
401 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400402 public void testTwoSingleHomedAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800403 reset(srManager.deviceConfiguration);
404 srManager.deviceConfiguration.addSubnet(CP1, P1);
405 expectLastCall().once();
406 srManager.deviceConfiguration.addSubnet(CP2, P1);
407 expectLastCall().once();
408 replay(srManager.deviceConfiguration);
409
Charles Chan910be6a2017-08-23 14:46:43 -0700410 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
411 routeHandler.processRouteAdded(re);
412
413 assertEquals(2, ROUTING_TABLE.size());
414 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
415 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
416 assertEquals(M1, rtv1.macAddress);
417 assertEquals(M2, rtv2.macAddress);
418 assertEquals(V1, rtv1.vlanId);
419 assertEquals(V2, rtv2.vlanId);
420 assertEquals(CP1.port(), rtv1.portNumber);
421 assertEquals(CP2.port(), rtv2.portNumber);
422
423 assertEquals(2, SUBNET_TABLE.size());
424 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
425 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800426
427 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700428 }
429
430 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400431 public void testOneDualHomedAdded() {
Charles Chan06f626c2018-02-05 17:20:05 -0800432 reset(srManager.deviceConfiguration);
433 srManager.deviceConfiguration.addSubnet(CP1, P1);
434 expectLastCall().once();
435 srManager.deviceConfiguration.addSubnet(CP2, P1);
436 expectLastCall().once();
437 replay(srManager.deviceConfiguration);
438
Charles Chan910be6a2017-08-23 14:46:43 -0700439 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
440 routeHandler.processRouteAdded(re);
441
442 assertEquals(2, ROUTING_TABLE.size());
443 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
444 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
445 assertEquals(M3, rtv1.macAddress);
446 assertEquals(M3, rtv2.macAddress);
447 assertEquals(V3, rtv1.vlanId);
448 assertEquals(V3, rtv2.vlanId);
449 assertEquals(CP1.port(), rtv1.portNumber);
450 assertEquals(CP2.port(), rtv2.portNumber);
451
452 assertEquals(2, SUBNET_TABLE.size());
453 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
454 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800455
456 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700457 }
458
459 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700460 public void testOneDualHomedAddedSingleLeafPair() {
461 srManager.setInfraDeviceIds(List.of());
462
463 reset(srManager.deviceConfiguration);
464 srManager.deviceConfiguration.addSubnet(CP1, P1);
465 expectLastCall().once();
466 srManager.deviceConfiguration.addSubnet(CP2, P1);
467 expectLastCall().once();
468 replay(srManager.deviceConfiguration);
469
470 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
471 routeHandler.processRouteAdded(re);
472
473 assertEquals(2, ROUTING_TABLE.size());
474 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
475 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
476 assertEquals(M3, rtv1.macAddress);
477 assertEquals(M3, rtv2.macAddress);
478 assertEquals(V3, rtv1.vlanId);
479 assertEquals(V3, rtv2.vlanId);
480 assertEquals(CP1.port(), rtv1.portNumber);
481 assertEquals(CP2.port(), rtv2.portNumber);
482
483 assertEquals(2, SUBNET_TABLE.size());
484 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
485 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
486
487 verify(srManager.deviceConfiguration);
488 }
489
490 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400491 public void testOneSingleHomedToTwoSingleHomed() {
Charles Chan910be6a2017-08-23 14:46:43 -0700492 processRouteAdded();
493
Charles Chan06f626c2018-02-05 17:20:05 -0800494 reset(srManager.deviceConfiguration);
495 srManager.deviceConfiguration.addSubnet(CP2, P1);
496 expectLastCall().once();
497 replay(srManager.deviceConfiguration);
498
Charles Chan910be6a2017-08-23 14:46:43 -0700499 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
500 Sets.newHashSet(RR1, RR2), Sets.newHashSet(RR1));
501 routeHandler.processAlternativeRoutesChanged(re);
502
503 assertEquals(2, ROUTING_TABLE.size());
504 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
505 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
506 assertEquals(M1, rtv1.macAddress);
507 assertEquals(M2, rtv2.macAddress);
508 assertEquals(V1, rtv1.vlanId);
509 assertEquals(V2, rtv2.vlanId);
510 assertEquals(CP1.port(), rtv1.portNumber);
511 assertEquals(CP2.port(), rtv2.portNumber);
512
513 assertEquals(2, SUBNET_TABLE.size());
514 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
515 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800516
517 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700518 }
519
520 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400521 public void testTwoSingleHomedToOneSingleHomed() {
Charles Chan910be6a2017-08-23 14:46:43 -0700522 testTwoSingleHomedAdded();
523
Charles Chan06f626c2018-02-05 17:20:05 -0800524 reset(srManager.deviceConfiguration);
525 srManager.deviceConfiguration.removeSubnet(CP2, P1);
526 expectLastCall().once();
527 replay(srManager.deviceConfiguration);
528
Charles Chan910be6a2017-08-23 14:46:43 -0700529 RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
530 Sets.newHashSet(RR1), Sets.newHashSet(RR1, RR2));
531 routeHandler.processAlternativeRoutesChanged(re);
532
Charles Chan06f626c2018-02-05 17:20:05 -0800533 // Note: We shouldn't remove the old nexthop during the occasion of route update
534 // since the populate subnet will take care of it and point it to an ECMP group
535 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700536 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
537 assertEquals(M1, rtv1.macAddress);
538 assertEquals(V1, rtv1.vlanId);
539 assertEquals(CP1.port(), rtv1.portNumber);
540
541 assertEquals(1, SUBNET_TABLE.size());
542 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan06f626c2018-02-05 17:20:05 -0800543
544 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700545 }
546
Charles Chan06f626c2018-02-05 17:20:05 -0800547 // TODO Add test cases for two single homed next hop at same location
548
Charles Chan910be6a2017-08-23 14:46:43 -0700549 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400550 public void testDualHomedSingleLocationFail() {
Charles Chan910be6a2017-08-23 14:46:43 -0700551 testOneDualHomedAdded();
552
Charles Chan7d20a4e2018-04-13 14:01:49 -0400553 ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
554
Charles Chan07203792018-07-17 16:33:11 -0700555 reset(srManager.deviceConfiguration);
Charles Chan5eec3b12019-04-18 14:30:41 -0700556 expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
557 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
Charles Chan07203792018-07-17 16:33:11 -0700558 srManager.deviceConfiguration.removeSubnet(CP2, P1);
559 expectLastCall().once();
560 replay(srManager.deviceConfiguration);
561
Charles Chan910be6a2017-08-23 14:46:43 -0700562 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
563 routeHandler.processHostMovedEvent(he);
564
Charles Chan4dcd5102019-02-28 15:40:57 -0800565 // We do not remove the route on CP2. Instead, we let the subnet population overrides it
566 assertEquals(2, ROUTING_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700567 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
Charles Chan910be6a2017-08-23 14:46:43 -0700568 assertEquals(M3, rtv1.macAddress);
Charles Chan910be6a2017-08-23 14:46:43 -0700569 assertEquals(V3, rtv1.vlanId);
Charles Chan910be6a2017-08-23 14:46:43 -0700570 assertEquals(CP1.port(), rtv1.portNumber);
Charles Chan910be6a2017-08-23 14:46:43 -0700571
Charles Chanfab61472021-06-14 23:31:23 -0700572 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
573 assertEquals(M3, rtv2.macAddress);
574 assertEquals(V3, rtv2.vlanId);
575 assertEquals(CP2.port(), rtv2.portNumber);
576
577 // ECMP route table hasn't changed
578 assertEquals(1, SUBNET_TABLE.size());
579 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
580
581 verify(srManager.deviceConfiguration);
582 }
583
584 @Test
585 public void testDualHomedSingleLocationFailSingleLeafPair() {
586 srManager.setInfraDeviceIds(List.of());
587
588 testOneDualHomedAddedSingleLeafPair();
589
590 ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
591
592 reset(srManager.deviceConfiguration);
593 expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
594 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
595 srManager.deviceConfiguration.removeSubnet(CP2, P1);
596 expectLastCall().once();
597 replay(srManager.deviceConfiguration);
598
599 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
600 routeHandler.processHostMovedEvent(he);
601
602 // We do not remove the route on CP2. Instead, we let the subnet population overrides it
603 assertEquals(2, ROUTING_TABLE.size());
604 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
605 assertEquals(M3, rtv1.macAddress);
606 assertEquals(V3, rtv1.vlanId);
607 assertEquals(CP1.port(), rtv1.portNumber);
608
609 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
610 assertEquals(ROUTER_MAC_1, rtv2.macAddress);
611 assertEquals(V3, rtv2.vlanId);
612 assertEquals(P9, rtv2.portNumber);
613
Charles Chan910be6a2017-08-23 14:46:43 -0700614 // ECMP route table hasn't changed
Charles Chan07203792018-07-17 16:33:11 -0700615 assertEquals(1, SUBNET_TABLE.size());
Charles Chan910be6a2017-08-23 14:46:43 -0700616 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
Charles Chan07203792018-07-17 16:33:11 -0700617
618 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700619 }
620
621 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400622 public void testDualHomedBothLocationFail() {
Charles Chan910be6a2017-08-23 14:46:43 -0700623 testDualHomedSingleLocationFail();
624
625 hostService = new MockHostService(HOSTS_ONE_FAIL);
626
Charles Chan06f626c2018-02-05 17:20:05 -0800627 reset(srManager.deviceConfiguration);
628 srManager.deviceConfiguration.removeSubnet(CP1, P1);
629 expectLastCall().once();
630 srManager.deviceConfiguration.removeSubnet(CP2, P1);
631 expectLastCall().once();
632 replay(srManager.deviceConfiguration);
633
Charles Chan910be6a2017-08-23 14:46:43 -0700634 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
635 routeHandler.processRouteRemoved(re);
636
637 assertEquals(0, ROUTING_TABLE.size());
638 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800639
640 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700641 }
642
643 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700644 public void testDualHomedBothLocationFaiSingleLeafPair() {
645 srManager.setInfraDeviceIds(List.of());
646
647 testDualHomedSingleLocationFailSingleLeafPair();
648
649 hostService = new MockHostService(HOSTS_ONE_FAIL);
650
651 reset(srManager.deviceConfiguration);
652 srManager.deviceConfiguration.removeSubnet(CP1, P1);
653 expectLastCall().once();
654 srManager.deviceConfiguration.removeSubnet(CP2, P1);
655 expectLastCall().once();
656 replay(srManager.deviceConfiguration);
657
658 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
659 routeHandler.processRouteRemoved(re);
660
661 assertEquals(0, ROUTING_TABLE.size());
662 assertEquals(0, SUBNET_TABLE.size());
663
664 verify(srManager.deviceConfiguration);
665 }
666
667 @Test
Charles Chan07203792018-07-17 16:33:11 -0700668 public void testSingleHomedToDualHomed() {
669 testDualHomedSingleLocationFail();
670
671 reset(srManager.deviceConfiguration);
Charles Chan5eec3b12019-04-18 14:30:41 -0700672 expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
673 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
Charles Chan07203792018-07-17 16:33:11 -0700674 srManager.deviceConfiguration.addSubnet(CP2, P1);
675 expectLastCall().once();
676 replay(srManager.deviceConfiguration);
677
678 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
679 routeHandler.processHostMovedEvent(he);
680
681 assertEquals(2, ROUTING_TABLE.size());
682 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
683 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
684 assertEquals(M3, rtv1.macAddress);
685 assertEquals(M3, rtv2.macAddress);
686 assertEquals(V3, rtv1.vlanId);
687 assertEquals(V3, rtv2.vlanId);
688 assertEquals(CP1.port(), rtv1.portNumber);
689 assertEquals(CP2.port(), rtv2.portNumber);
690
691 assertEquals(2, SUBNET_TABLE.size());
692 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
693 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
694
695 verify(srManager.deviceConfiguration);
696 }
697
698 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700699 public void testSingleHomedToDualHomedSingleLeafPair() {
700 srManager.setInfraDeviceIds(List.of());
701
702 testDualHomedSingleLocationFailSingleLeafPair();
703
704 reset(srManager.deviceConfiguration);
705 expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
706 .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
707 srManager.deviceConfiguration.addSubnet(CP2, P1);
708 expectLastCall().once();
709 replay(srManager.deviceConfiguration);
710
711 HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
712 routeHandler.processHostMovedEvent(he);
713
714 assertEquals(2, ROUTING_TABLE.size());
715 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
716 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
717 assertEquals(M3, rtv1.macAddress);
718 assertEquals(M3, rtv2.macAddress);
719 assertEquals(V3, rtv1.vlanId);
720 assertEquals(V3, rtv2.vlanId);
721 assertEquals(CP1.port(), rtv1.portNumber);
722 assertEquals(CP2.port(), rtv2.portNumber);
723
724 assertEquals(2, SUBNET_TABLE.size());
725 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
726 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
727
728 verify(srManager.deviceConfiguration);
729 }
730
731 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400732 public void testTwoSingleHomedRemoved() {
Charles Chan910be6a2017-08-23 14:46:43 -0700733 testTwoSingleHomedAdded();
734
735 hostService = new MockHostService(HOSTS_BOTH_FAIL);
736
Charles Chan06f626c2018-02-05 17:20:05 -0800737 reset(srManager.deviceConfiguration);
738 srManager.deviceConfiguration.removeSubnet(CP1, P1);
739 expectLastCall().once();
740 srManager.deviceConfiguration.removeSubnet(CP2, P1);
741 expectLastCall().once();
742 replay(srManager.deviceConfiguration);
743
Charles Chan910be6a2017-08-23 14:46:43 -0700744 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1, RR2));
745 routeHandler.processRouteRemoved(re);
746
747 assertEquals(0, ROUTING_TABLE.size());
748 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800749
750 verify(srManager.deviceConfiguration);
Charles Chan910be6a2017-08-23 14:46:43 -0700751 }
752
753 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400754 public void testOneDualHomeRemoved() {
Charles Chan910be6a2017-08-23 14:46:43 -0700755 testOneDualHomedAdded();
756
Charles Chan06f626c2018-02-05 17:20:05 -0800757 reset(srManager.deviceConfiguration);
758 srManager.deviceConfiguration.removeSubnet(CP1, P1);
759 expectLastCall().once();
760 srManager.deviceConfiguration.removeSubnet(CP2, P1);
761 expectLastCall().once();
762 replay(srManager.deviceConfiguration);
763
Charles Chan910be6a2017-08-23 14:46:43 -0700764 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
Charles Chan6c624992017-08-18 17:11:34 -0700765 routeHandler.processRouteRemoved(re);
766
767 assertEquals(0, ROUTING_TABLE.size());
768 assertEquals(0, SUBNET_TABLE.size());
Charles Chan06f626c2018-02-05 17:20:05 -0800769
770 verify(srManager.deviceConfiguration);
Charles Chan6c624992017-08-18 17:11:34 -0700771 }
Charles Chan482b6422018-04-09 11:52:08 -0400772
773 @Test
Charles Chanfab61472021-06-14 23:31:23 -0700774 public void testOneDualHomeRemovedSingleLeafPair() {
775 srManager.setInfraDeviceIds(List.of());
776
777 testOneDualHomedAddedSingleLeafPair();
778
779 reset(srManager.deviceConfiguration);
780 srManager.deviceConfiguration.removeSubnet(CP1, P1);
781 expectLastCall().once();
782 srManager.deviceConfiguration.removeSubnet(CP2, P1);
783 expectLastCall().once();
784 replay(srManager.deviceConfiguration);
785
786 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
787 routeHandler.processRouteRemoved(re);
788
789 assertEquals(0, ROUTING_TABLE.size());
790 assertEquals(0, SUBNET_TABLE.size());
791
792 verify(srManager.deviceConfiguration);
793 }
794
795 @Test
Charles Chan482b6422018-04-09 11:52:08 -0400796 public void testMoreThanTwoNextHop() {
797 // next hop = CP1, CP2
798 reset(srManager.deviceConfiguration);
799 srManager.deviceConfiguration.addSubnet(CP1, P1);
800 srManager.deviceConfiguration.addSubnet(CP2, P1);
801 expectLastCall().once();
802 replay(srManager.deviceConfiguration);
803
804 RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
805 routeHandler.processRouteAdded(re);
806
807 assertEquals(2, ROUTING_TABLE.size());
808 MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
809 assertEquals(M1, rtv1.macAddress);
810 assertEquals(V1, rtv1.vlanId);
811 assertEquals(CP1.port(), rtv1.portNumber);
812 MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
813 assertEquals(M2, rtv2.macAddress);
814 assertEquals(V2, rtv2.vlanId);
815 assertEquals(CP2.port(), rtv2.portNumber);
816
817 assertEquals(2, SUBNET_TABLE.size());
818 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
819 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
820
821 verify(srManager.deviceConfiguration);
822
823 // next hop = CP1, CP2, CP4 (invalid)
824 re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
825 Sets.newHashSet(RR1, RR2, RR4), Sets.newHashSet(RR1, RR2));
826 routeHandler.processAlternativeRoutesChanged(re);
827
828 assertEquals(2, ROUTING_TABLE.size());
829 rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
830 assertEquals(M1, rtv1.macAddress);
831 assertEquals(V1, rtv1.vlanId);
832 assertEquals(CP1.port(), rtv1.portNumber);
833 rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
834 assertEquals(M2, rtv2.macAddress);
835 assertEquals(V2, rtv2.vlanId);
836 assertEquals(CP2.port(), rtv2.portNumber);
837
838 assertEquals(2, SUBNET_TABLE.size());
839 assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
840 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
841
842 // next hop = CP2, CP4
843 reset(srManager.deviceConfiguration);
844 srManager.deviceConfiguration.addSubnet(CP2, P1);
845 srManager.deviceConfiguration.addSubnet(CP4, P1);
846 expectLastCall().once();
847 replay(srManager.deviceConfiguration);
848
pierventre37dcf4c2021-09-16 18:43:06 +0200849 // We don't lead of:0000000000000004 where RR4 next hop is attached
Charles Chan482b6422018-04-09 11:52:08 -0400850 re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
851 Sets.newHashSet(RR2, RR4), Sets.newHashSet(RR1, RR2, RR4));
852 routeHandler.processAlternativeRoutesChanged(re);
853
pierventre37dcf4c2021-09-16 18:43:06 +0200854 assertEquals(1, ROUTING_TABLE.size());
Charles Chan482b6422018-04-09 11:52:08 -0400855 rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
856 assertEquals(M2, rtv1.macAddress);
857 assertEquals(V2, rtv1.vlanId);
858 assertEquals(CP2.port(), rtv1.portNumber);
pierventre37dcf4c2021-09-16 18:43:06 +0200859 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1)));
Charles Chan482b6422018-04-09 11:52:08 -0400860
861 assertEquals(2, SUBNET_TABLE.size());
862 assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
863 assertTrue(SUBNET_TABLE.get(CP4).contains(P1));
864
865 verify(srManager.deviceConfiguration);
866 }
pierventre37dcf4c2021-09-16 18:43:06 +0200867
868 @Test
869 public void initOfNonLedDevices() {
870 // We dont lead CP4
871 ROUTE_STORE.put(P1, Sets.newHashSet(RR4));
872
873 routeHandler.init(CP4.deviceId());
874
875 // No routes programmed in the devices
876 assertEquals(0, ROUTING_TABLE.size());
877 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1)));
878
879 // But we still store the subnets
880 assertEquals(1, SUBNET_TABLE.size());
881 }
Ruchi Sahota71bcb4e2019-01-28 01:08:18 +0000882}