blob: 30462fbc056f2a17e16d6f00965546d1652c9c0d [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;
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 Chan6c624992017-08-18 17:11:34 -070030import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chanc6bcdf92018-06-01 16:33:48 -070031import org.onosproject.net.host.ProbeMode;
Ray Milkeyc2d43be2017-08-03 11:58:29 -070032import org.onosproject.net.intf.Interface;
Charles Chan114aec72017-06-19 14:00:53 -070033import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.DefaultHost;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.Host;
37import org.onosproject.net.HostId;
38import org.onosproject.net.HostLocation;
39import org.onosproject.net.PortNumber;
40import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Charles Chan114aec72017-06-19 14:00:53 -070041import org.onosproject.net.flow.TrafficTreatment;
Charles Chan114aec72017-06-19 14:00:53 -070042import org.onosproject.net.host.HostEvent;
43import org.onosproject.net.host.InterfaceIpAddress;
44import org.onosproject.net.provider.ProviderId;
45import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan3ed34d82017-06-22 18:03:14 -070046import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chand66d6712018-03-29 16:03:41 -070047import org.onosproject.store.service.StorageService;
48import org.onosproject.store.service.TestConsistentMap;
Charles Chan114aec72017-06-19 14:00:53 -070049
50import java.util.Map;
Charles Chan114aec72017-06-19 14:00:53 -070051import java.util.Set;
Charles Chan114aec72017-06-19 14:00:53 -070052
Charles Chand66d6712018-03-29 16:03:41 -070053import static org.easymock.EasyMock.createMock;
54import static org.easymock.EasyMock.expect;
55import static org.easymock.EasyMock.replay;
Charles Chan114aec72017-06-19 14:00:53 -070056import static org.junit.Assert.*;
57
Charles Chan6c624992017-08-18 17:11:34 -070058/**r
Charles Chan114aec72017-06-19 14:00:53 -070059 * Unit test for {@link HostHandler}.
60 */
61public class HostHandlerTest {
Charles Chan114aec72017-06-19 14:00:53 -070062 private HostHandler hostHandler;
63
64 // Mocked routing and bridging tables
Charles Chan6c624992017-08-18 17:11:34 -070065 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
66 Maps.newConcurrentMap();
67 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
68 Maps.newConcurrentMap();
Charles Chan910be6a2017-08-23 14:46:43 -070069 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070070 // Mocked Next Id
Charles Chan6c624992017-08-18 17:11:34 -070071 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070072
Charles Chand9265a32017-06-16 15:19:24 -070073 // Host Mac, VLAN
Charles Chan114aec72017-06-19 14:00:53 -070074 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
75 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
76 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
77 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
78 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
79 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chand9265a32017-06-16 15:19:24 -070080 // Host IP
81 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
82 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
83 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
84 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
85 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chanceb2a2e2017-09-12 18:57:47 -070086 private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
Charles Chand9265a32017-06-16 15:19:24 -070087 // Device
88 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
89 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chanabfe7e02017-08-09 16:50:15 -070090 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
91 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
92 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
93 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chand9265a32017-06-16 15:19:24 -070094 // Port
95 private static final PortNumber P1 = PortNumber.portNumber(1);
96 private static final PortNumber P2 = PortNumber.portNumber(2);
97 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan3ed34d82017-06-22 18:03:14 -070098 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chand9265a32017-06-16 15:19:24 -070099 // Connect Point
100 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
101 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
102 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
103 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
104 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
105 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
106 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
107 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
108 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
109 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700110 // Connect Point for dual-homed host failover
111 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
112 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700113 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
114 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700115 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
116 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
117 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
118 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chanabfe7e02017-08-09 16:50:15 -0700119 // Conenct Point for mastership test
120 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
121 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
122 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
123 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chand9265a32017-06-16 15:19:24 -0700124 // Interface VLAN
Charles Chan114aec72017-06-19 14:00:53 -0700125 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan868c9572018-06-15 18:54:18 -0700126 private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
127 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
Charles Chan114aec72017-06-19 14:00:53 -0700128 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan3ed34d82017-06-22 18:03:14 -0700129 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
130 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700131 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chand9265a32017-06-16 15:19:24 -0700132 // Interface subnet
133 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
134 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chanceb2a2e2017-09-12 18:57:47 -0700135 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chand9265a32017-06-16 15:19:24 -0700136 private static final InterfaceIpAddress INTF_IP1 =
137 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
138 private static final InterfaceIpAddress INTF_IP2 =
139 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700140 private static final InterfaceIpAddress INTF_IP3 =
141 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan6c624992017-08-18 17:11:34 -0700142 // Interfaces
143 private static final Interface INTF11 =
144 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
145 INTF_VLAN_UNTAGGED, null, null);
146 private static final Interface INTF12 =
147 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
148 INTF_VLAN_UNTAGGED, null, null);
149 private static final Interface INTF13 =
150 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
151 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
152 private static final Interface INTF21 =
153 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
154 INTF_VLAN_UNTAGGED, null, null);
155 private static final Interface INTF22 =
156 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
157 INTF_VLAN_UNTAGGED, null, null);
158 private static final Interface INTF31 =
159 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
160 INTF_VLAN_UNTAGGED, null, null);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700161 private static final Interface INTF32 =
162 new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
163 INTF_VLAN_OTHER, null, null);
Charles Chan6c624992017-08-18 17:11:34 -0700164 private static final Interface INTF39 =
165 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
166 null, INTF_VLAN_PAIR, null);
167 private static final Interface INTF41 =
168 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
169 INTF_VLAN_UNTAGGED, null, null);
170 private static final Interface INTF49 =
171 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
172 null, INTF_VLAN_PAIR, null);
Charles Chand9265a32017-06-16 15:19:24 -0700173 // Host
174 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
175 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
176 false);
Charles Chan114aec72017-06-19 14:00:53 -0700177
Charles Chan6c624992017-08-18 17:11:34 -0700178 // A set of hosts
179 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
180 // A set of devices of which we have mastership
181 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
182 // A set of interfaces
183 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chanceb2a2e2017-09-12 18:57:47 -0700184 INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
Charles Chan6c624992017-08-18 17:11:34 -0700185
Charles Chanc6bcdf92018-06-01 16:33:48 -0700186 private MockHostProbingService mockLocationProbingService;
Charles Chan873661e2017-11-30 15:37:50 -0800187
Charles Chan114aec72017-06-19 14:00:53 -0700188 @Before
189 public void setUp() throws Exception {
Charles Chan6c624992017-08-18 17:11:34 -0700190 // Initialize pairDevice and pairLocalPort config
191 ObjectMapper mapper = new ObjectMapper();
192 ConfigApplyDelegate delegate = config -> { };
193
194 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
195 JsonNode dev3Tree = mapper.createObjectNode();
196 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
197 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
198
199 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
200 JsonNode dev4Tree = mapper.createObjectNode();
201 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
202 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
203
204 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
205 mockNetworkConfigRegistry.applyConfig(dev3Config);
206 mockNetworkConfigRegistry.applyConfig(dev4Config);
207
208 // Initialize Segment Routing Manager
209 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chand66d6712018-03-29 16:03:41 -0700210 srManager.storageService = createMock(StorageService.class);
211 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
212 replay(srManager.storageService);
Charles Chan114aec72017-06-19 14:00:53 -0700213 srManager.cfgService = new NetworkConfigRegistryAdapter();
214 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan6c624992017-08-18 17:11:34 -0700215 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
216 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanc4d68882018-03-15 16:41:10 -0700217 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700218 srManager.interfaceService = new MockInterfaceService(INTERFACES);
219 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
220 srManager.hostService = new MockHostService(HOSTS);
221 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chanc6bcdf92018-06-01 16:33:48 -0700222 mockLocationProbingService = new MockHostProbingService();
Charles Chan873661e2017-11-30 15:37:50 -0800223 srManager.probingService = mockLocationProbingService;
Saurav Dase6c448a2018-01-18 12:07:33 -0800224 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan114aec72017-06-19 14:00:53 -0700225
226 hostHandler = new HostHandler(srManager);
227
Charles Chan6c624992017-08-18 17:11:34 -0700228 ROUTING_TABLE.clear();
229 BRIDGING_TABLE.clear();
Charles Chan114aec72017-06-19 14:00:53 -0700230 }
231
232 @Test
233 public void init() throws Exception {
Charles Chand9265a32017-06-16 15:19:24 -0700234 hostHandler.init(DEV1);
Charles Chan6c624992017-08-18 17:11:34 -0700235 assertEquals(1, ROUTING_TABLE.size());
236 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
237 assertEquals(1, BRIDGING_TABLE.size());
238 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700239
240 hostHandler.init(DEV2);
Charles Chan6c624992017-08-18 17:11:34 -0700241 assertEquals(2, ROUTING_TABLE.size());
242 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
243 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
244 assertEquals(2, BRIDGING_TABLE.size());
245 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
246 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700247 }
248
249 @Test(expected = IllegalArgumentException.class)
250 public void testHostAddedAtWrongLocation() throws Exception {
251 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
252 }
253
254
255 @Test()
256 public void testHostAddedAtCorrectLocation() throws Exception {
257 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan6c624992017-08-18 17:11:34 -0700258 assertEquals(1, ROUTING_TABLE.size());
259 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
260 assertEquals(1, BRIDGING_TABLE.size());
261 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700262 }
263
264 @Test
265 public void testHostAdded() throws Exception {
266 Host subject;
267
268 // Untagged host discovered on untagged port
269 // Expect: add one routing rule and one bridging rule
270 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700271 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700272 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
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 // Untagged host discovered on tagged/native port
279 // Expect: add one routing rule and one bridging rule
280 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700281 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700282 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700283 assertEquals(2, ROUTING_TABLE.size());
284 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
285 assertEquals(2, BRIDGING_TABLE.size());
286 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan114aec72017-06-19 14:00:53 -0700287
288 // Tagged host discovered on untagged port
289 // Expect: ignore the host. No rule is added.
290 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700291 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700292 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700293 assertEquals(2, ROUTING_TABLE.size());
294 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700295
296 // Tagged host discovered on tagged port with the same IP
297 // Expect: update existing route, add one bridging rule
298 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700299 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700300 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700301 assertEquals(2, ROUTING_TABLE.size());
302 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
303 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chand9265a32017-06-16 15:19:24 -0700304 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan6c624992017-08-18 17:11:34 -0700305 assertEquals(3, BRIDGING_TABLE.size());
306 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700307 }
308
309 @Test
310 public void testDualHomedHostAdded() throws Exception {
311 // Add a dual-homed host that has 2 locations
312 // Expect: add two routing rules and two bridging rules
313 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
314 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
315 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_IP11.toIpPrefix())));
318 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
319 assertEquals(2, BRIDGING_TABLE.size());
320 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
321 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700322 }
323
324 @Test
Charles Chanceb2a2e2017-09-12 18:57:47 -0700325 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
326 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
327 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
328
329 // Add a single-homed host with one location
330 // Expect: the pair link should not be utilized
331 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
332 assertEquals(1, ROUTING_TABLE.size());
333 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
334 assertEquals(1, BRIDGING_TABLE.size());
335 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
336 }
337
338 @Test
339 public void testDualHomedHostAddedOneByOne() throws Exception {
340 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
341 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
342 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
343 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
344
345 // Add a dual-homed host with one location
346 // Expect: the pair link is utilized temporarily before the second location is discovered
347 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
348 assertEquals(2, ROUTING_TABLE.size());
349 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
350 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
351 assertEquals(2, BRIDGING_TABLE.size());
352 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
353 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800354 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700355 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700356
357 // Add the second location of dual-homed host
358 // Expect: no longer use the pair link
359 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
360 assertEquals(2, ROUTING_TABLE.size());
361 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700362 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700363 assertEquals(2, BRIDGING_TABLE.size());
364 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
365 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
366 }
367
368 @Test
Charles Chan114aec72017-06-19 14:00:53 -0700369 public void testHostRemoved() throws Exception {
370 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700371 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700372
373 // Add a host
374 // Expect: add one routing rule and one bridging rule
375 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700376 assertEquals(1, ROUTING_TABLE.size());
377 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
378 assertEquals(1, BRIDGING_TABLE.size());
379 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700380
381 // Remove the host
382 // Expect: add the routing rule and the bridging rule
Charles Chand9265a32017-06-16 15:19:24 -0700383 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700384 assertEquals(0, ROUTING_TABLE.size());
385 assertEquals(0, BRIDGING_TABLE.size());
Charles Chand9265a32017-06-16 15:19:24 -0700386 }
387
388 @Test
389 public void testDualHomedHostRemoved() throws Exception {
390 // Add a dual-homed host that has 2 locations
391 // Expect: add two routing rules and two bridging rules
392 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
393 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
394 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700395 assertEquals(2, ROUTING_TABLE.size());
396 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
397 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
398 assertEquals(2, BRIDGING_TABLE.size());
399 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
400 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700401
402 // Remove a dual-homed host that has 2 locations
403 // Expect: all routing and bridging rules are removed
404 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700405 assertEquals(0, ROUTING_TABLE.size());
406 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700407 }
408
409 @Test
410 public void testHostMoved() throws Exception {
411 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700412 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700413 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700414 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700415 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700416 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700417
418 // Add a host
Charles Chan3ed34d82017-06-22 18:03:14 -0700419 // Expect: add one new routing rule, one new bridging rule
Charles Chan114aec72017-06-19 14:00:53 -0700420 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700421 assertEquals(1, ROUTING_TABLE.size());
422 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
423 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
424 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
425 assertEquals(1, BRIDGING_TABLE.size());
426 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
427 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700428
Charles Chand9265a32017-06-16 15:19:24 -0700429 // Move the host to CP13, which has different subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700430 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700431 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700432 assertEquals(0, ROUTING_TABLE.size());
433 assertEquals(1, BRIDGING_TABLE.size());
434 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
435 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700436
Charles Chand9265a32017-06-16 15:19:24 -0700437 // Move the host to CP21, which has same subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700438 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700439 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700440 assertEquals(1, ROUTING_TABLE.size());
441 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
442 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
443 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
444 assertEquals(1, BRIDGING_TABLE.size());
445 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
446 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700447 }
448
449 @Test
450 public void testDualHomedHostMoved() throws Exception {
451 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
452 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
453 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
454 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
455 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
456 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
457 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
458 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
Charles Chan4b5769a2018-04-25 18:51:46 -0400459 Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
460 Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
461
Charles Chand9265a32017-06-16 15:19:24 -0700462
463 // Add a host with IP11, IP12 and LOC11, LOC21
464 // Expect: 4 routing rules and 2 bridging rules
465 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700466 assertEquals(4, ROUTING_TABLE.size());
467 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
468 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
469 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
470 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
471 assertEquals(2, BRIDGING_TABLE.size());
472 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
473 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700474
Charles Chan4b5769a2018-04-25 18:51:46 -0400475 // Move the host to LOC12, LOC21 and keep the IP
476 // Expect: 4 routing rules and 2 bridging rules all at the new location
477 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
478 assertEquals(4, ROUTING_TABLE.size());
479 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
480 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
481 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
482 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
483 assertEquals(2, BRIDGING_TABLE.size());
484 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
485 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
486
Charles Chand9265a32017-06-16 15:19:24 -0700487 // Move the host to LOC12, LOC22 and keep the IP
488 // Expect: 4 routing rules and 2 bridging rules all at the new location
Charles Chan4b5769a2018-04-25 18:51:46 -0400489 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
Charles Chan6c624992017-08-18 17:11:34 -0700490 assertEquals(4, ROUTING_TABLE.size());
491 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
492 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
493 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
494 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
495 assertEquals(2, BRIDGING_TABLE.size());
496 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
497 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700498
499 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
500 // Expect: 4 routing rules and 2 bridging rules all at the new location
501 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700502 assertEquals(4, ROUTING_TABLE.size());
503 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
504 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
505 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
506 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
507 assertEquals(2, BRIDGING_TABLE.size());
508 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
509 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700510
511 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
512 // Expect: 4 routing rules and 2 bridging rules all at the new location
513 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700514 assertEquals(4, ROUTING_TABLE.size());
515 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
516 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
517 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
518 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
519 assertEquals(2, BRIDGING_TABLE.size());
520 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
521 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan114aec72017-06-19 14:00:53 -0700522 }
523
524 @Test
Charles Chanabfe7e02017-08-09 16:50:15 -0700525 public void testHostMoveToInvalidLocation() throws Exception {
526 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
527 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
528 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
529 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
530
531 // Add a host
532 // Expect: add one new routing rule, one new bridging rule
533 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700534 assertEquals(1, ROUTING_TABLE.size());
535 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
536 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
537 assertEquals(1, BRIDGING_TABLE.size());
538 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
539 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700540
541 // Move the host to an invalid location
542 // Expect: Old flow is removed. New flow is not created
543 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700544 assertEquals(0, ROUTING_TABLE.size());
545 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700546
547 // Move the host to a valid location
548 // Expect: add one new routing rule, one new bridging rule
549 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700550 assertEquals(1, ROUTING_TABLE.size());
551 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
552 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
553 assertEquals(1, BRIDGING_TABLE.size());
554 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
555 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700556 }
557
558 @Test
559 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
560 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
561 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
562 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
563 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
564 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
565 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
566
567 // Add a host
568 // Expect: add two new routing rules, two new bridging rules
569 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700570 assertEquals(2, ROUTING_TABLE.size());
571 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
572 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
573 assertEquals(2, BRIDGING_TABLE.size());
574 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
575 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700576
577 // Move first host location to an invalid location
578 // Expect: One routing and one bridging flow
579 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700580 assertEquals(1, ROUTING_TABLE.size());
581 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
582 assertEquals(1, BRIDGING_TABLE.size());
583 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700584
585 // Move second host location to an invalid location
586 // Expect: No routing or bridging rule
587 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700588 assertEquals(0, ROUTING_TABLE.size());
589 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700590
591 // Move second host location back to a valid location
592 // Expect: One routing and one bridging flow
593 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700594 assertEquals(1, ROUTING_TABLE.size());
595 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
596 assertEquals(1, BRIDGING_TABLE.size());
597 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700598
599 // Move first host location back to a valid location
600 // Expect: Two routing and two bridging flow
601 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700602 assertEquals(2, ROUTING_TABLE.size());
603 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
604 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
605 assertEquals(2, BRIDGING_TABLE.size());
606 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
607 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700608 }
609
610 @Test
Charles Chan3ed34d82017-06-22 18:03:14 -0700611 public void testDualHomingSingleLocationFail() throws Exception {
612 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
613 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
614 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
615 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
616
617 // Add a host
618 // Expect: add four new routing rules, two new bridging rules
619 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700620 assertEquals(4, ROUTING_TABLE.size());
621 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
622 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
623 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
624 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
625 assertEquals(2, BRIDGING_TABLE.size());
626 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
627 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700628
629 // Host becomes single-homed
630 // Expect: redirect flows from host location to pair link
631 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700632 assertEquals(4, ROUTING_TABLE.size());
633 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
634 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
635 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
636 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
637 assertEquals(2, BRIDGING_TABLE.size());
638 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
639 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700640
641 // Host becomes dual-homed again
642 // Expect: Redirect flows from pair link back to host location
643 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700644 assertEquals(4, ROUTING_TABLE.size());
645 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
646 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800647 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
648 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700649 assertEquals(2, BRIDGING_TABLE.size());
650 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan6c624992017-08-18 17:11:34 -0700651 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700652 }
653
654 @Test
655 public void testDualHomingBothLocationFail() throws Exception {
656 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
657 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
658 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
659 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
660
661 // Add a host
662 // Expect: add four new routing rules, two new bridging rules
663 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700664 assertEquals(4, ROUTING_TABLE.size());
665 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
666 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
667 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
668 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
669 assertEquals(2, BRIDGING_TABLE.size());
670 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
671 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700672
673 // Host becomes single-homed
674 // Expect: redirect flows from host location to pair link
675 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700676 assertEquals(4, ROUTING_TABLE.size());
677 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
678 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
679 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
680 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
681 assertEquals(2, BRIDGING_TABLE.size());
682 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
683 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700684
685 // Host loses both locations
686 // Expect: Remove last location and all previous redirection flows
687 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700688 assertEquals(0, ROUTING_TABLE.size());
689 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan3ed34d82017-06-22 18:03:14 -0700690 }
691
692 @Test
Charles Chan114aec72017-06-19 14:00:53 -0700693 public void testHostUpdated() throws Exception {
694 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700695 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700696 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700697 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700698 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700699 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan114aec72017-06-19 14:00:53 -0700700
701 // Add a host
Charles Chand9265a32017-06-16 15:19:24 -0700702 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan114aec72017-06-19 14:00:53 -0700703 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700704 assertEquals(1, ROUTING_TABLE.size());
705 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
706 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
707 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
708 assertEquals(1, BRIDGING_TABLE.size());
709 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
710 INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700711
712 // Update the host IP to same subnet
713 // Expect: update routing rule with new IP. No change to bridging rule.
714 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700715 assertEquals(1, ROUTING_TABLE.size());
716 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
717 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
718 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
719 assertEquals(1, BRIDGING_TABLE.size());
720 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700721
722 // Update the host IP to different subnet
723 // Expect: Remove routing rule. No change to bridging rule.
724 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700725 assertEquals(0, ROUTING_TABLE.size());
726 assertEquals(1, BRIDGING_TABLE.size());
727 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700728 }
729
730 @Test
Charles Chanb3c1faf2017-11-20 08:46:24 -0800731 public void testDelayedIpAndLocation() throws Exception {
732 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
733 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
734 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
735 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
736 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
737 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
738
739 // Add a dual-home host with only one location and no IP
740 // Expect: only bridging redirection works
741 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
742 assertEquals(0, ROUTING_TABLE.size());
743 assertEquals(2, BRIDGING_TABLE.size());
744 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
745 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
746
747 // Discover IP
748 // Expect: routing redirection should also work
Charles Chan873661e2017-11-30 15:37:50 -0800749 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800750 assertEquals(2, ROUTING_TABLE.size());
751 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
752 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
753 assertEquals(2, BRIDGING_TABLE.size());
754 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
755 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800756 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700757 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800758
759 // Discover location
760 // Expect: cancel all redirections
Charles Chan873661e2017-11-30 15:37:50 -0800761 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800762 assertEquals(2, ROUTING_TABLE.size());
763 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700764 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800765 assertEquals(2, BRIDGING_TABLE.size());
766 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700767 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800768 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800769 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
770 }
771
772 @Test
773 public void testDelayedIpAndLocation2() throws Exception {
774 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
775 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
776 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
777 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
778 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
779 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
780
781 // Add a dual-home host with only one location and no IP
782 // Expect: only bridging redirection works
783 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
784 assertEquals(0, ROUTING_TABLE.size());
785 assertEquals(2, BRIDGING_TABLE.size());
786 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
787 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
788
789 // Discover Location
790 // Expect: cancel bridging redirections
791 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
792 assertEquals(0, ROUTING_TABLE.size());
793 assertEquals(2, BRIDGING_TABLE.size());
794 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
795 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
796
797 // Discover IP
798 // Expect: add IP rules to both location
799 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
800 assertEquals(2, ROUTING_TABLE.size());
801 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
802 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
803 assertEquals(2, BRIDGING_TABLE.size());
804 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
805 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
806 }
807
808 @Test
Charles Chand9265a32017-06-16 15:19:24 -0700809 public void testDualHomedHostUpdated() throws Exception {
810 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
811 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
812 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
813 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
814 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
815 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
816
817 // Add a dual-homed host with two locations and two IPs
818 // Expect: add four new routing rules. Add two new bridging rules
819 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700820 assertEquals(4, ROUTING_TABLE.size());
821 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
822 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
823 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
824 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
825 assertEquals(2, BRIDGING_TABLE.size());
826 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
827 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700828
829 // Update both host IPs
830 // Expect: update routing rules with new IP. No change to bridging rule.
831 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700832 assertEquals(4, ROUTING_TABLE.size());
833 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
834 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
835 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
836 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
837 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
838 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
839 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
840 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
841 assertEquals(2, BRIDGING_TABLE.size());
842 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
843 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700844
845 // Update one of the host IP to different subnet
846 // Expect: update routing rule with new IP. No change to bridging rule.
847 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700848 assertEquals(2, ROUTING_TABLE.size());
849 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
850 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
851 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
852 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
853 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
854 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
855 assertEquals(2, BRIDGING_TABLE.size());
856 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
857 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700858 }
Charles Chan868c9572018-06-15 18:54:18 -0700859
860 @Test
861 public void testVlanForPairPort() {
862 assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
863 assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
864 assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
865 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
866 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
867 assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
868 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
869 }
Ray Milkeyc2d43be2017-08-03 11:58:29 -0700870}