blob: f3f49ae4e3413016ed280e41599ada7102ee193a [file] [log] [blame]
Charles Chan114aec72017-06-19 14:00:53 -07001/*
Brian O'Connor0947d7e2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Charles Chan114aec72017-06-19 14:00:53 -07003 *
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 Chan3ed34d82017-06-22 18:03:14 -070019import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
Charles Chan114aec72017-06-19 14:00:53 -070021import com.google.common.collect.Lists;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
Charles Chanbd84dd52018-06-21 19:07:12 -070024import org.easymock.EasyMock;
Charles Chan114aec72017-06-19 14:00:53 -070025import org.junit.Before;
26import org.junit.Test;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
Charles Chan6c624992017-08-18 17:11:34 -070031import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chanc6bcdf92018-06-01 16:33:48 -070032import org.onosproject.net.host.ProbeMode;
Ray Milkeyc2d43be2017-08-03 11:58:29 -070033import org.onosproject.net.intf.Interface;
Charles Chan114aec72017-06-19 14:00:53 -070034import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.DefaultHost;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Host;
38import org.onosproject.net.HostId;
39import org.onosproject.net.HostLocation;
40import org.onosproject.net.PortNumber;
41import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Charles Chan114aec72017-06-19 14:00:53 -070042import org.onosproject.net.flow.TrafficTreatment;
Charles Chan114aec72017-06-19 14:00:53 -070043import org.onosproject.net.host.HostEvent;
44import org.onosproject.net.host.InterfaceIpAddress;
45import org.onosproject.net.provider.ProviderId;
Charles Chanbd84dd52018-06-21 19:07:12 -070046import org.onosproject.routeservice.ResolvedRoute;
47import org.onosproject.routeservice.Route;
48import org.onosproject.routeservice.RouteInfo;
49import org.onosproject.routeservice.RouteService;
50import org.onosproject.routeservice.RouteTableId;
Charles Chan114aec72017-06-19 14:00:53 -070051import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan3ed34d82017-06-22 18:03:14 -070052import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chand66d6712018-03-29 16:03:41 -070053import org.onosproject.store.service.StorageService;
54import org.onosproject.store.service.TestConsistentMap;
Charles Chan114aec72017-06-19 14:00:53 -070055
56import java.util.Map;
Charles Chan114aec72017-06-19 14:00:53 -070057import java.util.Set;
Charles Chan114aec72017-06-19 14:00:53 -070058
Charles Chand66d6712018-03-29 16:03:41 -070059import static org.easymock.EasyMock.createMock;
Charles Chanbd84dd52018-06-21 19:07:12 -070060import static org.easymock.EasyMock.createNiceMock;
Charles Chand66d6712018-03-29 16:03:41 -070061import static org.easymock.EasyMock.expect;
Charles Chanbd84dd52018-06-21 19:07:12 -070062import static org.easymock.EasyMock.expectLastCall;
Charles Chand66d6712018-03-29 16:03:41 -070063import static org.easymock.EasyMock.replay;
Charles Chanbd84dd52018-06-21 19:07:12 -070064import static org.easymock.EasyMock.reset;
65import static org.easymock.EasyMock.verify;
Charles Chan114aec72017-06-19 14:00:53 -070066import static org.junit.Assert.*;
67
Charles Chan6c624992017-08-18 17:11:34 -070068/**r
Charles Chan114aec72017-06-19 14:00:53 -070069 * Unit test for {@link HostHandler}.
70 */
71public class HostHandlerTest {
Charles Chan114aec72017-06-19 14:00:53 -070072 private HostHandler hostHandler;
73
74 // Mocked routing and bridging tables
Charles Chan6c624992017-08-18 17:11:34 -070075 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
76 Maps.newConcurrentMap();
77 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
78 Maps.newConcurrentMap();
Charles Chan910be6a2017-08-23 14:46:43 -070079 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070080 // Mocked Next Id
Charles Chan6c624992017-08-18 17:11:34 -070081 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070082
Charles Chand9265a32017-06-16 15:19:24 -070083 // Host Mac, VLAN
Charles Chan114aec72017-06-19 14:00:53 -070084 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
85 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
86 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
87 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
88 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
89 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chand9265a32017-06-16 15:19:24 -070090 // Host IP
91 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
92 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
93 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
94 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
95 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chanceb2a2e2017-09-12 18:57:47 -070096 private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
Charles Chand9265a32017-06-16 15:19:24 -070097 // Device
98 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
99 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chanabfe7e02017-08-09 16:50:15 -0700100 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
101 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
102 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
103 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chand9265a32017-06-16 15:19:24 -0700104 // Port
105 private static final PortNumber P1 = PortNumber.portNumber(1);
106 private static final PortNumber P2 = PortNumber.portNumber(2);
107 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan3ed34d82017-06-22 18:03:14 -0700108 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chand9265a32017-06-16 15:19:24 -0700109 // Connect Point
110 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
111 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
112 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
113 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
114 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
115 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
116 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
117 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
118 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
119 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700120 // Connect Point for dual-homed host failover
121 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
122 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700123 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
124 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700125 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
126 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
127 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
128 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chanabfe7e02017-08-09 16:50:15 -0700129 // Conenct Point for mastership test
130 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
131 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
132 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
133 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chand9265a32017-06-16 15:19:24 -0700134 // Interface VLAN
Charles Chan114aec72017-06-19 14:00:53 -0700135 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan868c9572018-06-15 18:54:18 -0700136 private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
137 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
Charles Chan114aec72017-06-19 14:00:53 -0700138 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan3ed34d82017-06-22 18:03:14 -0700139 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
140 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700141 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chand9265a32017-06-16 15:19:24 -0700142 // Interface subnet
143 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
144 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chanceb2a2e2017-09-12 18:57:47 -0700145 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chand9265a32017-06-16 15:19:24 -0700146 private static final InterfaceIpAddress INTF_IP1 =
147 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
148 private static final InterfaceIpAddress INTF_IP2 =
149 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700150 private static final InterfaceIpAddress INTF_IP3 =
151 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan6c624992017-08-18 17:11:34 -0700152 // Interfaces
153 private static final Interface INTF11 =
154 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
155 INTF_VLAN_UNTAGGED, null, null);
156 private static final Interface INTF12 =
157 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
158 INTF_VLAN_UNTAGGED, null, null);
159 private static final Interface INTF13 =
160 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
161 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
162 private static final Interface INTF21 =
163 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
164 INTF_VLAN_UNTAGGED, null, null);
165 private static final Interface INTF22 =
166 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
167 INTF_VLAN_UNTAGGED, null, null);
168 private static final Interface INTF31 =
169 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
170 INTF_VLAN_UNTAGGED, null, null);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700171 private static final Interface INTF32 =
172 new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
173 INTF_VLAN_OTHER, null, null);
Charles Chan6c624992017-08-18 17:11:34 -0700174 private static final Interface INTF39 =
175 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
176 null, INTF_VLAN_PAIR, null);
177 private static final Interface INTF41 =
178 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
179 INTF_VLAN_UNTAGGED, null, null);
180 private static final Interface INTF49 =
181 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
182 null, INTF_VLAN_PAIR, null);
Charles Chand9265a32017-06-16 15:19:24 -0700183 // Host
184 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
185 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
186 false);
Charles Chan114aec72017-06-19 14:00:53 -0700187
Charles Chan6c624992017-08-18 17:11:34 -0700188 // A set of hosts
189 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
190 // A set of devices of which we have mastership
191 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
192 // A set of interfaces
193 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chanceb2a2e2017-09-12 18:57:47 -0700194 INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
Charles Chan6c624992017-08-18 17:11:34 -0700195
Charles Chanc6bcdf92018-06-01 16:33:48 -0700196 private MockHostProbingService mockLocationProbingService;
Charles Chan873661e2017-11-30 15:37:50 -0800197
Charles Chan114aec72017-06-19 14:00:53 -0700198 @Before
199 public void setUp() throws Exception {
Charles Chan6c624992017-08-18 17:11:34 -0700200 // Initialize pairDevice and pairLocalPort config
201 ObjectMapper mapper = new ObjectMapper();
202 ConfigApplyDelegate delegate = config -> { };
203
204 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
205 JsonNode dev3Tree = mapper.createObjectNode();
206 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
207 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
208
209 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
210 JsonNode dev4Tree = mapper.createObjectNode();
211 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
212 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
213
214 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
215 mockNetworkConfigRegistry.applyConfig(dev3Config);
216 mockNetworkConfigRegistry.applyConfig(dev4Config);
217
218 // Initialize Segment Routing Manager
219 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chand66d6712018-03-29 16:03:41 -0700220 srManager.storageService = createMock(StorageService.class);
221 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
222 replay(srManager.storageService);
Charles Chan114aec72017-06-19 14:00:53 -0700223 srManager.cfgService = new NetworkConfigRegistryAdapter();
224 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan6c624992017-08-18 17:11:34 -0700225 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
226 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanc4d68882018-03-15 16:41:10 -0700227 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700228 srManager.interfaceService = new MockInterfaceService(INTERFACES);
229 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
230 srManager.hostService = new MockHostService(HOSTS);
231 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chanc6bcdf92018-06-01 16:33:48 -0700232 mockLocationProbingService = new MockHostProbingService();
Charles Chan873661e2017-11-30 15:37:50 -0800233 srManager.probingService = mockLocationProbingService;
Saurav Dase6c448a2018-01-18 12:07:33 -0800234 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan114aec72017-06-19 14:00:53 -0700235
Charles Chanbd84dd52018-06-21 19:07:12 -0700236 // Not important for most of the HostHandler test case. Simply return an empty set here
237 srManager.routeService = createNiceMock(RouteService.class);
238 expect(srManager.routeService.getRouteTables()).andReturn(Sets.newHashSet()).anyTimes();
239 replay(srManager.routeService);
240
Charles Chan114aec72017-06-19 14:00:53 -0700241 hostHandler = new HostHandler(srManager);
242
Charles Chan6c624992017-08-18 17:11:34 -0700243 ROUTING_TABLE.clear();
244 BRIDGING_TABLE.clear();
Charles Chan114aec72017-06-19 14:00:53 -0700245 }
246
247 @Test
248 public void init() throws Exception {
Charles Chand9265a32017-06-16 15:19:24 -0700249 hostHandler.init(DEV1);
Charles Chan6c624992017-08-18 17:11:34 -0700250 assertEquals(1, ROUTING_TABLE.size());
251 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
252 assertEquals(1, BRIDGING_TABLE.size());
253 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700254
255 hostHandler.init(DEV2);
Charles Chan6c624992017-08-18 17:11:34 -0700256 assertEquals(2, ROUTING_TABLE.size());
257 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
258 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
259 assertEquals(2, BRIDGING_TABLE.size());
260 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
261 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700262 }
263
264 @Test(expected = IllegalArgumentException.class)
265 public void testHostAddedAtWrongLocation() throws Exception {
266 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
267 }
268
269
270 @Test()
271 public void testHostAddedAtCorrectLocation() throws Exception {
272 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan6c624992017-08-18 17:11:34 -0700273 assertEquals(1, ROUTING_TABLE.size());
274 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
275 assertEquals(1, BRIDGING_TABLE.size());
276 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700277 }
278
279 @Test
280 public void testHostAdded() throws Exception {
281 Host subject;
282
283 // Untagged host discovered on untagged port
284 // Expect: add one routing rule and one bridging rule
285 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700286 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700287 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700288 assertEquals(1, ROUTING_TABLE.size());
289 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
290 assertEquals(1, BRIDGING_TABLE.size());
291 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700292
293 // Untagged host discovered on tagged/native port
294 // Expect: add one routing rule and one bridging rule
295 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700296 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700297 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700298 assertEquals(2, ROUTING_TABLE.size());
299 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
300 assertEquals(2, BRIDGING_TABLE.size());
301 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan114aec72017-06-19 14:00:53 -0700302
303 // Tagged host discovered on untagged port
304 // Expect: ignore the host. No rule is added.
305 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700306 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700307 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700308 assertEquals(2, ROUTING_TABLE.size());
309 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700310
311 // Tagged host discovered on tagged port with the same IP
312 // Expect: update existing route, add one bridging rule
313 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700314 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700315 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700316 assertEquals(2, ROUTING_TABLE.size());
317 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
318 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chand9265a32017-06-16 15:19:24 -0700319 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan6c624992017-08-18 17:11:34 -0700320 assertEquals(3, BRIDGING_TABLE.size());
321 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700322 }
323
324 @Test
325 public void testDualHomedHostAdded() throws Exception {
326 // Add a dual-homed host that has 2 locations
327 // Expect: add two routing rules and two bridging rules
328 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
329 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
330 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700331 assertEquals(2, ROUTING_TABLE.size());
332 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
333 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
334 assertEquals(2, BRIDGING_TABLE.size());
335 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
336 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700337 }
338
339 @Test
Charles Chanceb2a2e2017-09-12 18:57:47 -0700340 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
341 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
342 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
343
344 // Add a single-homed host with one location
345 // Expect: the pair link should not be utilized
346 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
347 assertEquals(1, ROUTING_TABLE.size());
348 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
349 assertEquals(1, BRIDGING_TABLE.size());
350 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
351 }
352
353 @Test
354 public void testDualHomedHostAddedOneByOne() throws Exception {
355 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
356 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
357 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
358 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
359
360 // Add a dual-homed host with one location
361 // Expect: the pair link is utilized temporarily before the second location is discovered
362 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
363 assertEquals(2, ROUTING_TABLE.size());
364 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
365 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
366 assertEquals(2, BRIDGING_TABLE.size());
367 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
368 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800369 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700370 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700371
372 // Add the second location of dual-homed host
373 // Expect: no longer use the pair link
374 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
375 assertEquals(2, ROUTING_TABLE.size());
376 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700377 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700378 assertEquals(2, BRIDGING_TABLE.size());
379 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
380 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
381 }
382
383 @Test
Charles Chan114aec72017-06-19 14:00:53 -0700384 public void testHostRemoved() throws Exception {
385 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700386 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700387
388 // Add a host
389 // Expect: add one routing rule and one bridging rule
390 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700391 assertEquals(1, ROUTING_TABLE.size());
392 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
393 assertEquals(1, BRIDGING_TABLE.size());
394 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700395
396 // Remove the host
397 // Expect: add the routing rule and the bridging rule
Charles Chand9265a32017-06-16 15:19:24 -0700398 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700399 assertEquals(0, ROUTING_TABLE.size());
400 assertEquals(0, BRIDGING_TABLE.size());
Charles Chand9265a32017-06-16 15:19:24 -0700401 }
402
403 @Test
404 public void testDualHomedHostRemoved() throws Exception {
405 // Add a dual-homed host that has 2 locations
406 // Expect: add two routing rules and two bridging rules
407 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
408 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
409 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700410 assertEquals(2, ROUTING_TABLE.size());
411 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
412 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
413 assertEquals(2, BRIDGING_TABLE.size());
414 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
415 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700416
417 // Remove a dual-homed host that has 2 locations
418 // Expect: all routing and bridging rules are removed
419 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700420 assertEquals(0, ROUTING_TABLE.size());
421 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700422 }
423
424 @Test
425 public void testHostMoved() throws Exception {
426 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700427 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700428 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700429 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700430 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700431 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700432
433 // Add a host
Charles Chan3ed34d82017-06-22 18:03:14 -0700434 // Expect: add one new routing rule, one new bridging rule
Charles Chan114aec72017-06-19 14:00:53 -0700435 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700436 assertEquals(1, ROUTING_TABLE.size());
437 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
438 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
439 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
440 assertEquals(1, BRIDGING_TABLE.size());
441 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
442 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700443
Charles Chand9265a32017-06-16 15:19:24 -0700444 // Move the host to CP13, which has different subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700445 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700446 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700447 assertEquals(0, ROUTING_TABLE.size());
448 assertEquals(1, BRIDGING_TABLE.size());
449 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
450 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700451
Charles Chand9265a32017-06-16 15:19:24 -0700452 // Move the host to CP21, which has same subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700453 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700454 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700455 assertEquals(1, ROUTING_TABLE.size());
456 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
457 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
458 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
459 assertEquals(1, BRIDGING_TABLE.size());
460 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
461 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700462 }
463
464 @Test
465 public void testDualHomedHostMoved() throws Exception {
466 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
467 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
468 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
469 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
470 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
471 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
472 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
473 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
Charles Chan4b5769a2018-04-25 18:51:46 -0400474 Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
475 Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
476
Charles Chand9265a32017-06-16 15:19:24 -0700477
478 // Add a host with IP11, IP12 and LOC11, LOC21
479 // Expect: 4 routing rules and 2 bridging rules
480 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700481 assertEquals(4, ROUTING_TABLE.size());
482 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
483 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
484 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
485 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
486 assertEquals(2, BRIDGING_TABLE.size());
487 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
488 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700489
Charles Chan4b5769a2018-04-25 18:51:46 -0400490 // Move the host to LOC12, LOC21 and keep the IP
491 // Expect: 4 routing rules and 2 bridging rules all at the new location
492 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
493 assertEquals(4, ROUTING_TABLE.size());
494 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
495 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
496 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
497 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
498 assertEquals(2, BRIDGING_TABLE.size());
499 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
500 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
501
Charles Chand9265a32017-06-16 15:19:24 -0700502 // Move the host to LOC12, LOC22 and keep the IP
503 // Expect: 4 routing rules and 2 bridging rules all at the new location
Charles Chan4b5769a2018-04-25 18:51:46 -0400504 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
Charles Chan6c624992017-08-18 17:11:34 -0700505 assertEquals(4, ROUTING_TABLE.size());
506 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
507 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
508 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
509 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
510 assertEquals(2, BRIDGING_TABLE.size());
511 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
512 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700513
514 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
515 // Expect: 4 routing rules and 2 bridging rules all at the new location
516 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700517 assertEquals(4, ROUTING_TABLE.size());
518 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
519 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
520 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
521 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
522 assertEquals(2, BRIDGING_TABLE.size());
523 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
524 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700525
526 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
527 // Expect: 4 routing rules and 2 bridging rules all at the new location
528 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700529 assertEquals(4, ROUTING_TABLE.size());
530 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
531 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
532 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
533 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
534 assertEquals(2, BRIDGING_TABLE.size());
535 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
536 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan114aec72017-06-19 14:00:53 -0700537 }
538
539 @Test
Charles Chanabfe7e02017-08-09 16:50:15 -0700540 public void testHostMoveToInvalidLocation() throws Exception {
541 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
542 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
543 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
544 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
545
546 // Add a host
547 // Expect: add one new routing rule, one new bridging rule
548 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700549 assertEquals(1, ROUTING_TABLE.size());
550 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
551 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
552 assertEquals(1, BRIDGING_TABLE.size());
553 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
554 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700555
556 // Move the host to an invalid location
557 // Expect: Old flow is removed. New flow is not created
558 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700559 assertEquals(0, ROUTING_TABLE.size());
560 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700561
562 // Move the host to a valid location
563 // Expect: add one new routing rule, one new bridging rule
564 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700565 assertEquals(1, ROUTING_TABLE.size());
566 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
567 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
568 assertEquals(1, BRIDGING_TABLE.size());
569 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
570 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700571 }
572
573 @Test
574 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
575 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
576 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
577 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
578 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
579 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
580 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
581
582 // Add a host
583 // Expect: add two new routing rules, two new bridging rules
584 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700585 assertEquals(2, ROUTING_TABLE.size());
586 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
587 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
588 assertEquals(2, BRIDGING_TABLE.size());
589 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
590 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700591
592 // Move first host location to an invalid location
593 // Expect: One routing and one bridging flow
594 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700595 assertEquals(1, ROUTING_TABLE.size());
596 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
597 assertEquals(1, BRIDGING_TABLE.size());
598 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700599
600 // Move second host location to an invalid location
601 // Expect: No routing or bridging rule
602 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700603 assertEquals(0, ROUTING_TABLE.size());
604 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700605
606 // Move second host location back to a valid location
607 // Expect: One routing and one bridging flow
608 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700609 assertEquals(1, ROUTING_TABLE.size());
610 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
611 assertEquals(1, BRIDGING_TABLE.size());
612 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700613
614 // Move first host location back to a valid location
615 // Expect: Two routing and two bridging flow
616 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700617 assertEquals(2, ROUTING_TABLE.size());
618 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
619 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
620 assertEquals(2, BRIDGING_TABLE.size());
621 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
622 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700623 }
624
625 @Test
Charles Chan3ed34d82017-06-22 18:03:14 -0700626 public void testDualHomingSingleLocationFail() throws Exception {
627 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
628 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
629 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
630 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
631
632 // Add a host
633 // Expect: add four new routing rules, two new bridging rules
634 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700635 assertEquals(4, ROUTING_TABLE.size());
636 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
637 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
638 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
639 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
640 assertEquals(2, BRIDGING_TABLE.size());
641 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
642 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700643
644 // Host becomes single-homed
645 // Expect: redirect flows from host location to pair link
646 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700647 assertEquals(4, ROUTING_TABLE.size());
648 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
649 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
650 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
651 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
652 assertEquals(2, BRIDGING_TABLE.size());
653 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
654 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700655
656 // Host becomes dual-homed again
657 // Expect: Redirect flows from pair link back to host location
658 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700659 assertEquals(4, ROUTING_TABLE.size());
660 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
661 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800662 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
663 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700664 assertEquals(2, BRIDGING_TABLE.size());
665 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan6c624992017-08-18 17:11:34 -0700666 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700667 }
668
669 @Test
670 public void testDualHomingBothLocationFail() throws Exception {
671 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
672 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
673 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
674 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
675
676 // Add a host
677 // Expect: add four new routing rules, two new bridging rules
678 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700679 assertEquals(4, ROUTING_TABLE.size());
680 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
681 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
682 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
683 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
684 assertEquals(2, BRIDGING_TABLE.size());
685 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
686 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700687
688 // Host becomes single-homed
689 // Expect: redirect flows from host location to pair link
690 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700691 assertEquals(4, ROUTING_TABLE.size());
692 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
693 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
694 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
695 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
696 assertEquals(2, BRIDGING_TABLE.size());
697 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
698 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700699
700 // Host loses both locations
701 // Expect: Remove last location and all previous redirection flows
702 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700703 assertEquals(0, ROUTING_TABLE.size());
704 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan3ed34d82017-06-22 18:03:14 -0700705 }
706
707 @Test
Charles Chan114aec72017-06-19 14:00:53 -0700708 public void testHostUpdated() throws Exception {
709 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700710 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700711 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700712 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700713 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700714 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan114aec72017-06-19 14:00:53 -0700715
716 // Add a host
Charles Chand9265a32017-06-16 15:19:24 -0700717 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan114aec72017-06-19 14:00:53 -0700718 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700719 assertEquals(1, ROUTING_TABLE.size());
720 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
721 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
722 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
723 assertEquals(1, BRIDGING_TABLE.size());
724 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
725 INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700726
727 // Update the host IP to same subnet
728 // Expect: update routing rule with new IP. No change to bridging rule.
729 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700730 assertEquals(1, ROUTING_TABLE.size());
731 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
732 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
733 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
734 assertEquals(1, BRIDGING_TABLE.size());
735 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700736
737 // Update the host IP to different subnet
738 // Expect: Remove routing rule. No change to bridging rule.
739 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700740 assertEquals(0, ROUTING_TABLE.size());
741 assertEquals(1, BRIDGING_TABLE.size());
742 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700743 }
744
745 @Test
Charles Chanb3c1faf2017-11-20 08:46:24 -0800746 public void testDelayedIpAndLocation() throws Exception {
747 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
748 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
749 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
750 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
751 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
752 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
753
754 // Add a dual-home host with only one location and no IP
755 // Expect: only bridging redirection works
756 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
757 assertEquals(0, ROUTING_TABLE.size());
758 assertEquals(2, BRIDGING_TABLE.size());
759 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
760 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
761
762 // Discover IP
763 // Expect: routing redirection should also work
Charles Chan873661e2017-11-30 15:37:50 -0800764 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800765 assertEquals(2, ROUTING_TABLE.size());
766 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
767 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
768 assertEquals(2, BRIDGING_TABLE.size());
769 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
770 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800771 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700772 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800773
774 // Discover location
775 // Expect: cancel all redirections
Charles Chan873661e2017-11-30 15:37:50 -0800776 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800777 assertEquals(2, ROUTING_TABLE.size());
778 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700779 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800780 assertEquals(2, BRIDGING_TABLE.size());
781 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700782 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800783 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800784 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
785 }
786
787 @Test
788 public void testDelayedIpAndLocation2() throws Exception {
789 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
790 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
791 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
792 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
793 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
794 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
795
796 // Add a dual-home host with only one location and no IP
797 // Expect: only bridging redirection works
798 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
799 assertEquals(0, ROUTING_TABLE.size());
800 assertEquals(2, BRIDGING_TABLE.size());
801 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
802 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
803
804 // Discover Location
805 // Expect: cancel bridging redirections
806 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
807 assertEquals(0, ROUTING_TABLE.size());
808 assertEquals(2, BRIDGING_TABLE.size());
809 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
810 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
811
812 // Discover IP
813 // Expect: add IP rules to both location
814 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
815 assertEquals(2, ROUTING_TABLE.size());
816 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
817 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
818 assertEquals(2, BRIDGING_TABLE.size());
819 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
820 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
821 }
822
823 @Test
Charles Chand9265a32017-06-16 15:19:24 -0700824 public void testDualHomedHostUpdated() throws Exception {
825 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
826 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
827 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
828 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
829 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
830 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
831
832 // Add a dual-homed host with two locations and two IPs
833 // Expect: add four new routing rules. Add two new bridging rules
834 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700835 assertEquals(4, ROUTING_TABLE.size());
836 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
837 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
838 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
839 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
840 assertEquals(2, BRIDGING_TABLE.size());
841 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
842 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700843
844 // Update both host IPs
845 // Expect: update routing rules with new IP. No change to bridging rule.
846 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700847 assertEquals(4, ROUTING_TABLE.size());
848 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
849 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
850 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
851 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
852 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
853 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
854 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
855 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
856 assertEquals(2, BRIDGING_TABLE.size());
857 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
858 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700859
860 // Update one of the host IP to different subnet
861 // Expect: update routing rule with new IP. No change to bridging rule.
862 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700863 assertEquals(2, ROUTING_TABLE.size());
864 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
865 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
866 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
867 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
868 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
869 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
870 assertEquals(2, BRIDGING_TABLE.size());
871 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
872 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700873 }
Charles Chan868c9572018-06-15 18:54:18 -0700874
875 @Test
876 public void testVlanForPairPort() {
877 assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
878 assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
879 assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
880 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
881 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
882 assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
883 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
884 }
Charles Chanbd84dd52018-06-21 19:07:12 -0700885
886 @Test
887 public void testHostRemovedWithRouteRemoved() throws Exception {
888 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
889 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
890
891 // Add a host
892 // Expect: add one routing rule and one bridging rule
893 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
894 assertEquals(1, ROUTING_TABLE.size());
895 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
896 assertEquals(1, BRIDGING_TABLE.size());
897 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
898
899 IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
900
901 // Setting up mock route service
902 RouteService routeService = hostHandler.srManager.routeService;
903 reset(routeService);
904
905 IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
906 MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
907 VlanId nextHopVlan2 = VlanId.NONE;
908
909 Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
910 ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
911 Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
912 ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
913 RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
914 RouteTableId routeTableId = new RouteTableId("ipv4");
915
916 expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
917 expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
918 replay(routeService);
919
920 // Setting up mock device configuration
921 hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
922 DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
923 expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
924 deviceConfiguration.removeSubnet(CP11, prefix);
925 expectLastCall();
926 replay(deviceConfiguration);
927
928 // Remove the host
929 // Expect: add the routing rule and the bridging rule
930 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
931 assertEquals(0, ROUTING_TABLE.size());
932 assertEquals(0, BRIDGING_TABLE.size());
933
934 // Expect: subnet is removed from device config
935 verify(deviceConfiguration);
936 }
Ray Milkeyc2d43be2017-08-03 11:58:29 -0700937}